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,038 lines (980 loc) 48 kB
"use strict"; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return 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 _class2; var _chunk5EKUVSA3js = require('../../chunk-5EKUVSA3.js'); var _chunkFID44QSNjs = require('../../chunk-FID44QSN.js'); var _chunkVLUR4YNDjs = require('../../chunk-VLUR4YND.js'); var _chunk6CYSQII7js = require('../../chunk-6CYSQII7.js'); var _chunkHPM3R2DVjs = require('../../chunk-HPM3R2DV.js'); var _chunkOTBM3PZSjs = require('../../chunk-OTBM3PZS.js'); var _chunkBFC2WP6Qjs = require('../../chunk-BFC2WP6Q.js'); var _chunkUGNVT3WEjs = require('../../chunk-UGNVT3WE.js'); var _chunk22H3U7VVjs = require('../../chunk-22H3U7VV.js'); var _chunk6PEHRAEPjs = require('../../chunk-6PEHRAEP.js'); // server/agent-process/process.ts var _birpc = require('birpc'); // agent/server/class.ts var _zod = require('zod'); var _zod2 = _interopRequireDefault(_zod); // plugins/server/class.ts var PluginServer = (_class = class { static { _chunk6PEHRAEPjs.__name.call(void 0, this, "PluginServer"); } __init() {this.queue = new (0, _chunkBFC2WP6Qjs.AsyncQueue)()} __init2() {this.eventsListeners = /* @__PURE__ */ new Map()} __init3() {this.contextListeners = /* @__PURE__ */ new Map()} __init4() {this.streamHandlersQueues = []} __init5() {this.externalInterceptHandlers = []} #internalAccessor; #waitProcessingResolvers = /* @__PURE__ */ new Map(); #waitResultResolvers = /* @__PURE__ */ new Map(); #waitProcessingHistory = new (0, _chunk6CYSQII7js.RollingBuffer)(1e3); #waitResultHistory = new (0, _chunk6CYSQII7js.RollingBuffer)(1e3); #handlersStates = /* @__PURE__ */ new Map(); constructor({ agent, definition, config, context = {} }) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this); this.def = definition; this.agent = agent; const { error: errConfig, data: parsedConfig } = definition.config.schema.safeParse(config); if (errConfig) throw _chunk22H3U7VVjs.lifeError.call(void 0, { code: "Validation", message: `Invalid config provided to plugin server '${definition.name}'.`, cause: errConfig }); this.config = parsedConfig; const { error: errContext, data: parsedContext } = definition.context.schema.safeParse(context); if (errContext) throw _chunk22H3U7VVjs.lifeError.call(void 0, { code: "Validation", message: `Invalid context provided to plugin server '${definition.name}'.`, cause: errContext }); this.context = parsedContext; this.telemetry = _chunk5EKUVSA3js.createTelemetryClient.call(void 0, "plugin.server", { agentId: agent.id, agentSha: agent.sha, agentName: agent.def.name, agentConfig: agent.config, transportProviderName: agent.config.transport.provider, llmProviderName: agent.config.models.llm.provider, sttProviderName: agent.config.models.stt.provider, eouProviderName: agent.config.models.eou.provider, ttsProviderName: agent.config.models.tts.provider, vadProviderName: agent.config.models.vad.provider, pluginName: definition.name, pluginServerConfig: this.config }); this.#initClientRPC(); const [errAccessor, accessor] = this.getAccessor({ type: "server", name: this.def.name }); if (errAccessor) throw errAccessor; this.#internalAccessor = accessor; } /** * Produces an accessor object, exposing methods to interact safely with the plugin * from a given source (plugin, handler, client). * @param source - The source accessing the plugin. * @param handlerAccess - The access mode for the handler. * @returns An accessor object. */ getAccessor(source, handlerAccess) { const [errClone, clonedConfig] = _chunk22H3U7VVjs.attempt.call(void 0, () => _chunkBFC2WP6Qjs.deepClone.call(void 0, this.config)); if (errClone) return _chunk22H3U7VVjs.failure.call(void 0, errClone); const contextOnChange = /* @__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)); }), "contextOnChange"); const contextGet = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (() => _chunk22H3U7VVjs.attempt.call(void 0, () => _chunkBFC2WP6Qjs.deepClone.call(void 0, this.context))), "contextGet"); const contextSet = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, ((valueOrUpdater) => { const [errOld, oldContext] = _chunk22H3U7VVjs.attempt.call(void 0, () => _chunkBFC2WP6Qjs.deepClone.call(void 0, this.context)); if (errOld) return _chunk22H3U7VVjs.failure.call(void 0, errOld); if (typeof valueOrUpdater === "function") this.context = valueOrUpdater(oldContext); else this.context = valueOrUpdater; Promise.all([ // Notify context change listeners Array.from(this.contextListeners.values()).map(async (listener) => { try { const newSelectedValue = listener.selector(this.context); const oldSelectedValue = listener.selector(oldContext); const [errEqual, equal] = _chunkVLUR4YNDjs.canon.equal(newSelectedValue, oldSelectedValue); if (errEqual) return _chunk22H3U7VVjs.failure.call(void 0, errEqual); if (equal) await listener.callback(_chunkBFC2WP6Qjs.deepClone.call(void 0, this.context), _chunkBFC2WP6Qjs.deepClone.call(void 0, oldContext)); } catch (error) { this.telemetry.log.error({ message: `Error while notifying context listeners in plugin '${this.def.name}'.`, error }); } }), // Send new context value updates via RPC this.agent.transport.call({ name: `plugin.${this.def.name}.context.changed`, schema: { input: _zod2.default.object({ value: _zod2.default.any(), timestamp: _zod2.default.number() }) }, input: { value: this.context, timestamp: Date.now() } }) ]); return _chunk22H3U7VVjs.success.call(void 0, ); }), "contextSet"); const eventsEmit = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, ((event) => { const { error: errEvent, data: parsedEvent } = _chunkOTBM3PZSjs.pluginEventInputSchema.safeParse(event); if (errEvent) return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: "Invalid event shape for event.", cause: errEvent }); const isInternal = source.type === "server" && source.name === this.def.name; if (!isInternal && parsedEvent.name.startsWith("plugin.")) return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: "Internal events cannot be emitted from outside the plugin." }); const eventDef = _optionalChain([this, 'access', _ => _.def, 'access', _2 => _2.events, 'optionalAccess', _3 => _3.find, 'call', _4 => _4((e) => e.name === parsedEvent.name)]); if (!eventDef) return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Event of type '${parsedEvent.name}' not found.` }); let parsedData = null; if (eventDef.dataSchema) { const { error: errData, data } = eventDef.dataSchema.safeParse(parsedEvent.data); parsedData = data; if (errData) return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Invalid event data shape for '${parsedEvent.name}' event.`, cause: errData }); } const outputEvent = { id: _chunk22H3U7VVjs.newId.call(void 0, "event"), name: parsedEvent.name, urgent: parsedEvent.urgent, data: parsedData, created: { at: Date.now(), by: source }, edited: false, dropped: false, contextChanges: [] }; if (outputEvent.urgent) this.queue.pushFirst(outputEvent); else this.queue.push(outputEvent); return _chunk22H3U7VVjs.success.call(void 0, outputEvent.id); }), "eventsEmit"); const eventsOn = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, ((selector, callback, includeDropped = false) => { const id = _chunk22H3U7VVjs.newId.call(void 0, "listener"); this.eventsListeners.set(id, { id, callback, selector, includeDropped }); return _chunk22H3U7VVjs.success.call(void 0, () => this.eventsListeners.delete(id)); }), "eventsOn"); const eventsOnce = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, ((selector, callback, includeDropped = false) => { const [errOn, unsubscribe] = eventsOn( selector, async (event) => { _optionalChain([unsubscribe, 'optionalCall', _5 => _5()]); await callback(event); }, includeDropped ); if (errOn) return _chunk22H3U7VVjs.failure.call(void 0, errOn); return _chunk22H3U7VVjs.success.call(void 0, unsubscribe); }), "eventsOnce"); const eventsWaitForProcessing = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (async (eventId) => { let resolver; const cleanupResolver = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, () => { if (!resolver) return; _optionalChain([this, 'access', _6 => _6.#waitProcessingResolvers, 'access', _7 => _7.get, 'call', _8 => _8(eventId), 'optionalAccess', _9 => _9.delete, 'call', _10 => _10(resolver)]); if (_optionalChain([this, 'access', _11 => _11.#waitProcessingResolvers, 'access', _12 => _12.get, 'call', _13 => _13(eventId), 'optionalAccess', _14 => _14.size]) === 0) this.#waitProcessingResolvers.delete(eventId); }, "cleanupResolver"); try { if (this.#waitProcessingHistory.get().includes(eventId)) return _chunk22H3U7VVjs.success.call(void 0, ); const resolverPromise = new Promise( (r) => resolver = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, () => void r(_chunk22H3U7VVjs.success.call(void 0, )), "resolver") ); if (!resolver) throw new Error("Resolver not found. Shouldn't happen."); if (!this.#waitProcessingResolvers.has(eventId)) this.#waitProcessingResolvers.set(eventId, /* @__PURE__ */ new Set()); _optionalChain([this, 'access', _15 => _15.#waitProcessingResolvers, 'access', _16 => _16.get, 'call', _17 => _17(eventId), 'optionalAccess', _18 => _18.add, 'call', _19 => _19(resolver)]); const timeoutPromise = new Promise((resolve) => { setTimeout(() => { resolve( _chunk22H3U7VVjs.failure.call(void 0, { code: "Timeout", message: `Waiting for event '${eventId}' processing timed out.`, isPublic: true }) ); }, 15e3); }); const [err] = await Promise.race([resolverPromise, timeoutPromise]); if (err) return _chunk22H3U7VVjs.failure.call(void 0, err); this.#waitProcessingHistory.add(eventId); return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } finally { cleanupResolver(); } }), "eventsWaitForProcessing"); const eventsWaitForResult = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (async (eventId, handlerName) => { let resolver; const cleanupResolver = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, () => { if (!resolver) return; _optionalChain([this, 'access', _20 => _20.#waitResultResolvers, 'access', _21 => _21.get, 'call', _22 => _22(eventId), 'optionalAccess', _23 => _23.get, 'call', _24 => _24(handlerName), 'optionalAccess', _25 => _25.delete, 'call', _26 => _26(resolver)]); if (_optionalChain([this, 'access', _27 => _27.#waitResultResolvers, 'access', _28 => _28.get, 'call', _29 => _29(eventId), 'optionalAccess', _30 => _30.get, 'call', _31 => _31(handlerName), 'optionalAccess', _32 => _32.size]) === 0) _optionalChain([this, 'access', _33 => _33.#waitResultResolvers, 'access', _34 => _34.get, 'call', _35 => _35(eventId), 'optionalAccess', _36 => _36.delete, 'call', _37 => _37(handlerName)]); if (_optionalChain([this, 'access', _38 => _38.#waitResultResolvers, 'access', _39 => _39.get, 'call', _40 => _40(eventId), 'optionalAccess', _41 => _41.size]) === 0) this.#waitResultResolvers.delete(eventId); }, "cleanupResolver"); try { const historyItem = this.#waitResultHistory.get().find((h) => h.eventId === eventId && h.handlerName === handlerName); if (historyItem) return historyItem.result; const resolverPromise = new Promise((r) => resolver = r); if (!resolver) throw new Error("Resolver not found. Shouldn't happen."); if (!this.#waitResultResolvers.has(eventId)) this.#waitResultResolvers.set(eventId, /* @__PURE__ */ new Map()); if (!_optionalChain([this, 'access', _42 => _42.#waitResultResolvers, 'access', _43 => _43.get, 'call', _44 => _44(eventId), 'optionalAccess', _45 => _45.get, 'call', _46 => _46(handlerName)])) _optionalChain([this, 'access', _47 => _47.#waitResultResolvers, 'access', _48 => _48.get, 'call', _49 => _49(eventId), 'optionalAccess', _50 => _50.set, 'call', _51 => _51(handlerName, /* @__PURE__ */ new Set())]); _optionalChain([this, 'access', _52 => _52.#waitResultResolvers, 'access', _53 => _53.get, 'call', _54 => _54(eventId), 'optionalAccess', _55 => _55.get, 'call', _56 => _56(handlerName), 'optionalAccess', _57 => _57.add, 'call', _58 => _58(resolver)]); const timeoutPromise = new Promise((resolve) => { setTimeout(() => { resolve( _chunk22H3U7VVjs.failure.call(void 0, { code: "Timeout", message: `Waiting for event '${eventId}' result timed out.`, isPublic: true }) ); }, 15e3); }); const result = await Promise.race([resolverPromise, timeoutPromise]); this.#waitResultHistory.add({ eventId, handlerName, result }); return result; } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } finally { cleanupResolver(); } }), "eventsWaitForResult"); if (source.type === "handler") { return _chunk22H3U7VVjs.success.call(void 0, { config: clonedConfig, context: { get: contextGet, ...handlerAccess === "write" ? { set: contextSet } : {}, onChange: contextOnChange }, events: { emit: eventsEmit, waitForResult: eventsWaitForResult, waitForProcessing: eventsWaitForProcessing } }); } if (source.type === "server") { return _chunk22H3U7VVjs.success.call(void 0, { config: clonedConfig, context: { get: contextGet, onChange: contextOnChange }, events: { emit: eventsEmit, on: eventsOn, once: eventsOnce, waitForResult: eventsWaitForResult, waitForProcessing: eventsWaitForProcessing } }); } if (source.type === "client") { return _chunk22H3U7VVjs.success.call(void 0, { config: clonedConfig, context: { get: contextGet, onChange: contextOnChange }, events: { emit: eventsEmit, on: eventsOn, once: eventsOnce, waitForResult: eventsWaitForResult, waitForProcessing: eventsWaitForProcessing } }); } return _chunk22H3U7VVjs.failure.call(void 0, { code: "NotFound", message: `Unknown source type '${source.type}'.` }); } /** * Produces a map of dependencies' accessors, see `getAccessor()`. * @param source - The source accessing the dependencies. * @returns A map of dependencies' accessors. */ getDependenciesAccessors(source) { const dependenciesAccessors = {}; for (const dependencyDef of _nullishCoalesce(this.def.dependencies, () => ( []))) { const depServer = _optionalChain([this, 'access', _59 => _59.agent, 'access', _60 => _60.plugins, 'optionalAccess', _61 => _61[_chunkOTBM3PZSjs.toMethodName.call(void 0, dependencyDef.name)]]); if (!depServer) return _chunk22H3U7VVjs.failure.call(void 0, { code: "NotFound", message: `Failed to obtain server instance for dependency plugin '${dependencyDef.name}'. Shouldn't happen.` }); const [errAccessor, accessor] = depServer.getAccessor(source); if (errAccessor) return _chunk22H3U7VVjs.failure.call(void 0, errAccessor); dependenciesAccessors[dependencyDef.name] = accessor; } return _chunk22H3U7VVjs.success.call(void 0, dependenciesAccessors); } async start() { return await this.telemetry.trace(`plugin.${this.def.name}.start()`, async () => { const streamHandlers = this.def.handlers.filter((h) => h.mode === "stream"); for (const handler of streamHandlers) { const queue = new (0, _chunkBFC2WP6Qjs.AsyncQueue)(); this.streamHandlersQueues.push(queue); (async () => { for await (const event of queue) await this.#executeHandler(handler, event); })(); } const interceptHandlers = this.def.handlers.filter((h) => h.mode === "intercept"); for (const handler of interceptHandlers) { for (const dependencyDef of _nullishCoalesce(this.def.dependencies, () => ( []))) { const dependency = _optionalChain([this, 'access', _62 => _62.agent, 'access', _63 => _63.plugins, 'optionalAccess', _64 => _64[dependencyDef.name]]); if (!dependency) { this.telemetry.log.error( _chunk22H3U7VVjs.lifeError.call(void 0, { code: "NotFound", message: `Failed to obtain server instance for dependency plugin '${dependencyDef.name}'. Shouldn't happen.` }) ); continue; } dependency.externalInterceptHandlers.push({ dependent: this, handler }); } } (async () => { for await (const event of this.queue) { try { for (const { handler, dependent } of this.externalInterceptHandlers) { await this.#executeHandler(handler, event, dependent, (result) => { if (result.type === "drop") { if (event.dropped) event.dropped = { at: Date.now(), by: { plugin: this.def.name, handler: handler.name }, reason: result.reason }; } else if (result.type === "next") { const [errClone, oldData] = _chunk22H3U7VVjs.attempt.call(void 0, () => _chunkBFC2WP6Qjs.deepClone.call(void 0, event.data)); if (errClone) return _chunk22H3U7VVjs.failure.call(void 0, errClone); if (!event.edited) event.edited = []; event.edited.push({ at: Date.now(), by: { plugin: this.def.name, handler: handler.name }, reason: result.reason, dataBefore: oldData, dataAfter: result.data }); event.data = result.data; } }); if (event.dropped) break; } if (!event.dropped) { const blockHandlers = this.def.handlers.filter((h) => h.mode === "block"); for (const handler of blockHandlers) { const [errOld, oldContext] = _chunk22H3U7VVjs.attempt.call(void 0, () => _chunkBFC2WP6Qjs.deepClone.call(void 0, this.context)); if (errOld) { this.telemetry.log.error({ error: errOld }); continue; } await this.#executeHandler(handler, event); const [errEqual, equal] = _chunkVLUR4YNDjs.canon.equal( this.context, oldContext ); if (errEqual) { this.telemetry.log.error({ error: errEqual }); continue; } if (!equal) { if (!event.contextChanges) event.contextChanges = []; event.contextChanges.push({ at: Date.now(), byHandler: handler.name, valueBefore: oldContext, valueAfter: this.context }); } } for (const queue of this.streamHandlersQueues) queue.push(event); } await Promise.all( Array.from(this.eventsListeners.values()).map( async ({ id, callback, selector, includeDropped }) => { if (this.#eventMatchesSelector(event, selector)) { if (!event.dropped || includeDropped) { if (callback === "remote") { const [err] = await this.agent.transport.call({ name: `plugin.${this.def.name}.events.callback`, schema: { input: _zod2.default.object({ listenerId: _zod2.default.string(), event: _chunkOTBM3PZSjs.pluginEventInputSchema }) }, input: { listenerId: id, event } }); if (err) this.telemetry.log.error({ message: `Error while steaming event to remote listener in plugin '${this.def.name}'.`, error: err }); } else await callback(event); } } } ) ); const waiters = _nullishCoalesce(this.#waitProcessingResolvers.get(event.id), () => ( [])); for (const resolver of waiters) resolver(); } catch (error) { this.telemetry.log.error({ message: `Unknown error while executing event in plugin '${this.def.name}'.`, error }); } } })(); const [errEmit, eventId] = this.#emitInternalEvent({ name: "plugin.start", data: { isRestart: this.agent.isRestart, restartCount: 0 } }); if (errEmit) return _chunk22H3U7VVjs.failure.call(void 0, errEmit); const [errWaitForResult] = await this.#internalAccessor.events.waitForProcessing(eventId); if (errWaitForResult) return _chunk22H3U7VVjs.failure.call(void 0, errWaitForResult); return _chunk22H3U7VVjs.success.call(void 0, ); }); } async stop() { return await this.telemetry.trace(`plugin.${this.def.name}.stop()`, async () => { const [errEmit, eventId] = this.#emitInternalEvent({ name: "plugin.stop", urgent: true }); if (errEmit) return _chunk22H3U7VVjs.failure.call(void 0, errEmit); const [errWaitForResult] = await this.#internalAccessor.events.waitForProcessing(eventId); if (errWaitForResult) return _chunk22H3U7VVjs.failure.call(void 0, errWaitForResult); this.queue.stop(); for (const queue of this.streamHandlersQueues) queue.stop(); this.#handlersStates.clear(); return _chunk22H3U7VVjs.success.call(void 0, ); }); } #getHandlerState(handler, accessor) { const savedState = this.#handlersStates.get(handler.name); if (savedState) return savedState; const initialState = typeof handler.state === "function" ? handler.state({ config: accessor.config }) : _nullishCoalesce(handler.state, () => ( {})); this.#handlersStates.set(handler.name, initialState); return initialState; } #emitInternalEvent(event) { const [errEmit, eventId] = this.#internalAccessor.events.emit(event); if (errEmit) return _chunk22H3U7VVjs.failure.call(void 0, errEmit); return _chunk22H3U7VVjs.success.call(void 0, eventId); } async #executeHandler(handler, event, dependency, onInterceptResult) { const result = await (async () => { const [errClone, clonedEvent] = _chunk22H3U7VVjs.attempt.call(void 0, () => _chunkBFC2WP6Qjs.deepClone.call(void 0, event)); if (errClone) return _chunk22H3U7VVjs.failure.call(void 0, errClone); const handlerAccess = handler.mode === "block" ? "write" : "read"; const [errAccessor, accessor] = this.getAccessor( { type: "handler", plugin: this.def.name, handler: handler.name, event: event.name }, handlerAccess ); if (errAccessor) return _chunk22H3U7VVjs.failure.call(void 0, errAccessor); const state = this.#getHandlerState(handler, accessor); const [errDependency, dependencyAccessor] = dependency ? dependency.getAccessor({ type: "server", name: dependency.def.name }) : _chunk22H3U7VVjs.success.call(void 0, {}); if (errDependency) return _chunk22H3U7VVjs.failure.call(void 0, errDependency); const [errDependencies, dependenciesAccessor] = this.getDependenciesAccessors({ type: "handler", plugin: this.def.name, handler: handler.name, event: event.name }); if (errDependencies) return _chunk22H3U7VVjs.failure.call(void 0, errDependencies); const drop = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (reason) => _optionalChain([onInterceptResult, 'optionalCall', _65 => _65({ type: "drop", reason })]), "drop"); const next = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (data, reason) => _optionalChain([onInterceptResult, 'optionalCall', _66 => _66({ type: "next", data, reason })]), "next"); return await this.telemetry.trace( `plugin.${this.def.name}.handler.${handler.name}`, async (span) => _chunk22H3U7VVjs.attempt.call(void 0, async () => await handler.onEvent({ event: clonedEvent, plugin: _chunk22H3U7VVjs.toPublic.call(void 0, accessor), state, telemetry: span, agent: _chunk22H3U7VVjs.toPublic.call(void 0, this.agent), ...handler.mode === "intercept" ? { drop, next, dependency: dependencyAccessor } : { dependencies: dependenciesAccessor } }) ) ); })(); if (result[0]) { this.telemetry.log.error({ message: `Error while executing ${handler.mode} handler '${handler.name}' in plugin '${this.def.name}'.`, error: result[0] }); this.#emitInternalEvent({ name: "plugin.error", data: { error: result[0], event } }); } const waiters = _nullishCoalesce(_optionalChain([this, 'access', _67 => _67.#waitResultResolvers, 'access', _68 => _68.get, 'call', _69 => _69(event.id), 'optionalAccess', _70 => _70.get, 'call', _71 => _71(handler.name)]), () => ( [])); for (const resolver of waiters) resolver(result); } #initClientRPC() { const [errAccessor, accessor] = this.getAccessor({ type: "client", name: this.def.name }); if (errAccessor) return _chunk22H3U7VVjs.failure.call(void 0, errAccessor); this.agent.transport.register({ name: `plugin.${this.def.name}.context.get`, schema: { output: _zod2.default.object().loose() }, execute: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, () => _chunk22H3U7VVjs.success.call(void 0, { value: this.context, timestamp: Date.now() }), "execute") }); this.agent.transport.register({ name: `plugin.${this.def.name}.events.emit`, schema: { input: _chunkOTBM3PZSjs.pluginEventInputSchema, output: _zod2.default.object({ id: _zod2.default.string() }) }, execute: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async (input) => { const [err, id] = await accessor.events.emit(input); if (err) return _chunk22H3U7VVjs.failure.call(void 0, err); return _chunk22H3U7VVjs.success.call(void 0, { id }); }, "execute") }); this.agent.transport.register({ 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) }) }, execute: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (input) => { const { listenerId, selector, includeDropped } = input; this.eventsListeners.set(listenerId, { id: listenerId, callback: "remote", selector, includeDropped }); return _chunk22H3U7VVjs.success.call(void 0, ); }, "execute") }); this.agent.transport.register({ name: `plugin.${this.def.name}.events.unsubscribe`, schema: { input: _zod2.default.object({ listenerId: _zod2.default.string() }) }, execute: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (input) => { const { listenerId } = input; this.eventsListeners.delete(listenerId); return _chunk22H3U7VVjs.success.call(void 0, ); }, "execute") }); this.agent.transport.register({ name: `plugin.${this.def.name}.events.waitForProcessing`, schema: { input: _zod2.default.object({ eventId: _zod2.default.string() }) }, execute: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async (input) => await accessor.events.waitForProcessing(input.eventId), "execute") }); this.agent.transport.register({ 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() }, execute: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async (input) => await accessor.events.waitForResult( input.eventId, input.handlerName ), "execute") }); } #eventMatchesSelector(event, selector) { const isAllSelector = selector === "*"; const isArraySelectorAndIncludesEvent = Array.isArray(selector) && selector.includes(event.name); const isObjectSelectorAndIncludesEvent = typeof selector === "object" && "include" in selector && (selector.include === "*" || selector.include.includes(event.name)); const isObjectSelectorAndExcludesEvent = typeof selector === "object" && "exclude" in selector && _optionalChain([selector, 'access', _72 => _72.exclude, 'optionalAccess', _73 => _73.includes, 'call', _74 => _74(event.name)]); return isAllSelector || isArraySelectorAndIncludesEvent || isObjectSelectorAndIncludesEvent && !isObjectSelectorAndExcludesEvent; } }, _class); // shared/ensure-server.ts function ensureServer(featureName) { const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined"; if (isBrowser) { throw new Error(`\u274C "${featureName}" is a server-only and must not run in the browser.`); } } _chunk6PEHRAEPjs.__name.call(void 0, ensureServer, "ensureServer"); // transport/client/node.ts ensureServer("transport.client.node"); var nodeTransportProviders = { livekit: _chunkHPM3R2DVjs.LiveKitNodeClient }; var TransportNodeClient = class extends _chunkFID44QSNjs.TransportClientBase { static { _chunk6PEHRAEPjs.__name.call(void 0, this, "TransportNodeClient"); } constructor({ config, obfuscateErrors = false, telemetry: telemetry2 = null }) { const ProviderClass = nodeTransportProviders[config.provider]; super({ provider: new ProviderClass(config), obfuscateErrors, telemetry: telemetry2 }); } }; // agent/server/class.ts var AgentServer = (_class2 = class { static { _chunk6PEHRAEPjs.__name.call(void 0, this, "AgentServer"); } __init6() {this.storage = null} __init7() {this.plugins = {}} #initialPluginsContexts; constructor({ id, sha, definition, scope, config, pluginsContexts, isRestart }) {;_class2.prototype.__init6.call(this);_class2.prototype.__init7.call(this); this.id = id; this.sha = sha; this.def = definition; this.scope = _nullishCoalesce(scope, () => ( this.def.scope.schema.parse({}))); this.config = config; this.isRestart = _nullishCoalesce(isRestart, () => ( false)); this.#initialPluginsContexts = _nullishCoalesce(pluginsContexts, () => ( {})); this.telemetry = _chunk5EKUVSA3js.createTelemetryClient.call(void 0, "agent.server", { agentId: id, agentSha: this.sha, agentName: this.def.name, agentConfig: this.config, transportProviderName: this.config.transport.provider, llmProviderName: this.config.models.llm.provider, sttProviderName: this.config.models.stt.provider, eouProviderName: this.config.models.eou.provider, ttsProviderName: this.config.models.tts.provider, vadProviderName: this.config.models.vad.provider }); this.transport = new TransportNodeClient({ config: this.config.transport, obfuscateErrors: true, telemetry: this.telemetry }); const vadProvider = _chunkHPM3R2DVjs.vadProviders[this.config.models.vad.provider]; const sttProvider = _chunkHPM3R2DVjs.sttProviders[this.config.models.stt.provider]; const eouProvider = _chunkHPM3R2DVjs.eouProviders[this.config.models.eou.provider]; const llmProvider = _chunkHPM3R2DVjs.llmProviders[this.config.models.llm.provider]; const ttsProvider = _chunkHPM3R2DVjs.ttsProviders[this.config.models.tts.provider]; this.models = { vad: new vadProvider.class(this.config.models.vad), stt: new sttProvider.class(this.config.models.stt), eou: new eouProvider.class(this.config.models.eou), llm: new llmProvider.class(this.config.models.llm), tts: new ttsProvider.class(this.config.models.tts) }; this.#initializePlugins(); } #initializePlugins() { const pluginNames = this.def.plugins.map((p) => p.name); const duplicates = pluginNames.filter((name, index) => pluginNames.indexOf(name) !== index); if (duplicates.length > 0) { const uniqueDuplicates = [...new Set(duplicates)]; throw _chunk22H3U7VVjs.lifeError.call(void 0, { code: "Validation", message: `Two or more plugins are named "${uniqueDuplicates.join('", "')}". Plugin names must be unique. (agent: '${this.def.name}')` }); } for (const plugin of this.def.plugins) { for (const dependency of plugin.dependencies) { const depPlugin = this.def.plugins.find((p) => p.name === dependency.name); if (!depPlugin) { throw _chunk22H3U7VVjs.lifeError.call(void 0, { code: "Validation", message: `Plugin '${plugin.name}' depends on plugin '${dependency.name}', but '${dependency.name}' is not registered. (agent: '${this.def.name}')` }); } } } this.transport.register({ name: "agent.has-plugin-server", schema: { input: _zod2.default.object({ pluginName: _zod2.default.string() }), output: _zod2.default.object({ hasServer: _zod2.default.boolean() }) }, execute: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, ({ pluginName }) => { const plugin = _optionalChain([this, 'access', _75 => _75.plugins, 'optionalAccess', _76 => _76[pluginName]]); if (!plugin) return _chunk22H3U7VVjs.success.call(void 0, { hasServer: false }); return _chunk22H3U7VVjs.success.call(void 0, { hasServer: true }); }, "execute") }); } async start() { return await this.telemetry.trace("AgentServer.start()", async () => { try { for (const definition of this.def.plugins) { const { error: errorContext, data: parsedContext } = definition.context.schema.safeParse( _nullishCoalesce(_optionalChain([this, 'access', _77 => _77.#initialPluginsContexts, 'optionalAccess', _78 => _78[definition.name]]), () => ( {})) ); if (errorContext) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Invalid initial context value for plugin '${definition.name}'.`, cause: errorContext }); } const { error: errorConfig, data: parsedConfig } = definition.config.schema.safeParse( _nullishCoalesce(_optionalChain([this, 'access', _79 => _79.def, 'access', _80 => _80.pluginConfigs, 'optionalAccess', _81 => _81[definition.name]]), () => ( {})) ); if (errorConfig) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Invalid config value for plugin '${definition.name}'.`, cause: errorConfig }); } const [errCreate, instance] = _chunk22H3U7VVjs.attempt.call(void 0, () => new PluginServer({ agent: this, definition, config: parsedConfig, context: parsedContext }) ); if (errCreate) return _chunk22H3U7VVjs.failure.call(void 0, errCreate); this.plugins[definition.name] = instance; } const result = await Promise.all(Object.values(this.plugins).map((p) => p.start())); const err = _optionalChain([result, 'access', _82 => _82.find, 'call', _83 => _83((r) => r[0]), 'optionalAccess', _84 => _84[0]]); if (err) return _chunk22H3U7VVjs.failure.call(void 0, err); return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }); } async stop() { return await this.telemetry.trace("AgentServer.stop()", async (span) => { try { await Promise.all( Object.entries(this.plugins).map( ([pluginId, plugin]) => plugin.stop().catch( (error) => span.log.error({ message: `Error stopping plugin ${pluginId}:`, error }) ) ) ); const [errLeave] = await this.transport.leaveRoom(); if (errLeave) return _chunk22H3U7VVjs.failure.call(void 0, errLeave); return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }); } }, _class2); // server/agent-process/process.ts var processStats = new (0, _chunk5EKUVSA3js.ProcessStats)(); var agentServer = null; var telemetry = null; var rpc = _birpc.createBirpc.call(void 0, { init(params) { telemetry = _chunk5EKUVSA3js.createTelemetryClient.call(void 0, "agent.process", { agentId: params.agentId }); _chunk5EKUVSA3js.pipeConsoleToTelemetryClient.call(void 0, telemetry); return _chunk22H3U7VVjs.success.call(void 0, ); }, // async start(params) { try { const [errIndex, buildIndex] = await _chunkUGNVT3WEjs.importServerBuild.call(void 0, { projectDirectory: process.cwd(), noCache: true }); if (errIndex) return _chunk22H3U7VVjs.failure.call(void 0, errIndex); const build = _optionalChain([buildIndex, 'optionalAccess', _85 => _85[params.name]]); if (!build) return _chunk22H3U7VVjs.failure.call(void 0, { code: "NotFound", message: `Agent '${params.name}' not found.` }); const [errConfig, config] = _chunkHPM3R2DVjs.prepareAgentConfig.call(void 0, build.definition.config, build.globalConfigs ); if (errConfig) return _chunk22H3U7VVjs.failure.call(void 0, errConfig); const [errCreate, instance] = _chunk22H3U7VVjs.attempt.call(void 0, () => new AgentServer({ id: params.id, definition: build.definition, scope: params.scope, sha: build.sha, config: config.server, pluginsContexts: params.pluginsContexts, isRestart: params.isRestart }) ); if (errCreate) return _chunk22H3U7VVjs.failure.call(void 0, errCreate); agentServer = instance; const [err] = await agentServer.start(); if (err) return _chunk22H3U7VVjs.failure.call(void 0, err); for (const pluginDef of build.definition.plugins) { const [errAccessor, accessor] = _nullishCoalesce(_optionalChain([agentServer, 'access', _86 => _86.plugins, 'access', _87 => _87[pluginDef.name], 'optionalAccess', _88 => _88.getAccessor, 'call', _89 => _89({ type: "server", name: pluginDef.name })]), () => ( _chunk22H3U7VVjs.failure.call(void 0, { code: "NotFound", message: `Plugin '${pluginDef.name}' not found.` }))); if (errAccessor) return _chunk22H3U7VVjs.failure.call(void 0, errAccessor); accessor.context.onChange( (c) => c, async (c) => { if (!agentServer) return; const [error] = await rpc.syncContext({ agentId: agentServer.id, pluginName: pluginDef.name, context: c, timestamp: Date.now() }); if (error) _optionalChain([telemetry, 'optionalAccess', _90 => _90.log, 'access', _91 => _91.error, 'call', _92 => _92({ message: `Failed to sync for plugin '${pluginDef.name}' in agent '${agentServer.def.name}' process.`, error })]); } ); } await agentServer.transport.joinRoom(params.transportRoom.name, params.transportRoom.token); await rpc.ready(); _optionalChain([telemetry, 'optionalAccess', _93 => _93.log, 'access', _94 => _94.info, 'call', _95 => _95({ message: "Agent started successfully." })]); return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }, async stop() { try { if (agentServer) { const [err] = await agentServer.stop(); if (err) return _chunk22H3U7VVjs.failure.call(void 0, err); agentServer = null; } return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }, // Simple ping to check if process is responsive async ping() { return await _chunk22H3U7VVjs.success.call(void 0, ); }, // Get detailed stats from the child process async getProcessStats() { try { return await processStats.get(); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } } }, { post: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (data) => _optionalChain([process, 'access', _96 => _96.send, 'optionalCall', _97 => _97(data)]), "post"), on: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (fn) => process.on("message", fn), "on"), serialize: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (data) => { const [error, result] = _chunkVLUR4YNDjs.canon.serialize(data); if (error) { throw _chunk22H3U7VVjs.lifeError.call(void 0, { code: "Validation", message: "Failed to serialize data from agent process to server. The message has been discarded.", attributes: { agentId: _optionalChain([agentServer, 'optionalAccess', _98 => _98.id]), agentName: _optionalChain([agentServer, 'optionalAccess', _99 => _99.def, 'access', _100 => _100.name]), data }, cause: error }); } return result; }, "serialize"), deserialize: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (data) => { const [error, result] = _chunkVLUR4YNDjs.canon.deserialize(data); if (error) { throw _chunk22H3U7VVjs.lifeError.call(void 0, { code: "Validation", message: "Failed to deserialize data from agent process to server. The message has been discarded.", attributes: { agentId: _optionalChain([agentServer, 'optionalAccess', _101 => _101.id]), agentName: _optionalChain([agentServer, 'optionalAccess', _102 => _102.def, 'access', _103 => _103.name]), data }, cause: error }); } return result; }, "deserialize"), onFunctionError: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (error) => { _optionalChain([telemetry, 'optionalAccess', _104 => _104.log, 'access', _105 => _105.error, 'call', _106 => _106( _chunk22H3U7VVjs.isLifeError.call(void 0, error) ? error : _chunk22H3U7VVjs.lifeError.call(void 0, { code: "Unknown", cause: error }) )]); }, "onFunctionError"), onGeneralError: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (error) => { _optionalChain([telemetry, 'optionalAccess', _107 => _107.log, 'access', _108 => _108.error, 'call', _109 => _109( _chunk22H3U7VVjs.isLifeError.call(void 0, error) ? error : _chunk22H3U7VVjs.lifeError.call(void 0, { code: "Unknown", cause: error }) )]); }, "onGeneralError"), // Disable Birpc timeout onTimeoutError: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, () => true, "onTimeoutError"), timeout: -1 } ); _chunk5EKUVSA3js.TelemetryNodeClient.registerGlobalConsumer({ start: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async (queue) => { for await (const signal of queue) rpc.syncTelemetry(signal); }, "start") }); process.on("uncaughtException", async (error) => { _optionalChain([telemetry, 'optionalAccess', _110 => _110.log, 'access', _111 => _111.error, 'call', _112 => _112({ error })]); await _optionalChain([telemetry, 'optionalAccess', _113 => _113.flushConsumers, 'call', _114 => _114(1e3)]); process.exit(1); }); process.on("unhandledRejection", async (reason) => { _optionalChain([telemetry, 'optionalAccess', _115 => _115.log, 'access', _116 => _116.error, 'call', _117 => _117({ message: reason instanceof Error ? reason.message : String(reason), error: reason instanceof Error ? reason : void 0 })]); await _optionalChain([telemetry, 'optionalAccess', _118 => _118.flushConsumers, 'call', _119 => _119(1e3)]); process.exit(1); }); //# sourceMappingURL=process.js.map