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