life
Version:
Life.js is the first fullstack framework to build agentic web applications. It is minimal, extensible, and typesafe. Well, everything you love.
351 lines (328 loc) • 12.3 kB
JavaScript
;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(); } } 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 _chunkSDCJCCXNjs = require('../chunk-SDCJCCXN.js');
require('../chunk-EL6AAGQA.js');
require('../chunk-W2LGDDT2.js');
require('../chunk-FID44QSN.js');
require('../chunk-VLUR4YND.js');
var _chunkOTBM3PZSjs = require('../chunk-OTBM3PZS.js');
var _chunkBFC2WP6Qjs = require('../chunk-BFC2WP6Q.js');
require('../chunk-22H3U7VV.js');
var _chunk6PEHRAEPjs = require('../chunk-6PEHRAEP.js');
// agent/client/builder.ts
var AgentClientBuilder = class _AgentClientBuilder {
static {
_chunk6PEHRAEPjs.__name.call(void 0, this, "AgentClientBuilder");
}
constructor(definition) {
this.def = definition;
}
/**
* Register plugins to extend the agent client features.
* Defaults to `[generation, memories, stores, actions, percepts]` plugins if not specified.
*
* In case you want to register custom plugins and still keep the defaults you can do:
* ```ts
* import { defaults } from "life/server";
*
* defineAgent("my-agent").plugins([...defaults.plugins, myCustomPlugin]);
* ```
*
* Or if you want only some of the defaults, you can do:
* ```ts
* import { defaults } from "life/server";
*
* defineAgent("my-agent").plugins([defaults.plugins.generation, defaults.plugins.memories]);
* ```
*/
plugins(plugins) {
const builder = new _AgentClientBuilder({ ...this.def, plugins: plugins.map((p) => p.def) });
const builderWithPlugins = _AgentClientBuilder.withPluginsMethods(builder);
return builderWithPlugins;
}
// biome-ignore lint/suspicious/noExplicitAny: reason
static withPluginsMethods(builder) {
for (const plugin of builder.def.plugins) {
Object.assign(builder, {
[_chunkOTBM3PZSjs.toMethodName.call(void 0, plugin.name)]: (config) => {
const newBuilder = new _AgentClientBuilder({
...builder.def,
pluginConfigs: {
..._nullishCoalesce(builder.def.pluginConfigs, () => ( {})),
[plugin.name]: config
}
});
return _AgentClientBuilder.withPluginsMethods(newBuilder);
}
});
}
return builder;
}
};
function defineAgentClient(name) {
const defaultDefinition = {
name,
plugins: [...defaults.plugins].map((p) => p.def),
pluginConfigs: {},
$serverDef: {}
};
const builder = new AgentClientBuilder(defaultDefinition);
const builderWithPlugins = AgentClientBuilder.withPluginsMethods(builder);
return builderWithPlugins;
}
_chunk6PEHRAEPjs.__name.call(void 0, defineAgentClient, "defineAgentClient");
// plugins/client/builder.ts
var _zod = require('zod'); var _zod2 = _interopRequireDefault(_zod);
var PluginClientBuilder = class _PluginClientBuilder {
static {
_chunk6PEHRAEPjs.__name.call(void 0, this, "PluginClientBuilder");
}
constructor(definition) {
this.def = definition;
}
/**
* ### `.dependencies()`
*
* Specify other plugins clients as required by this plugin client.
*
* Their config, atoms, and class can then be accessed from `dependencies.*` inside the plugin client's class and atoms.
*
* @see TODO: Add docs link
*
* @example
* ```ts
* const pluginClient = definePluginClient("my-plugin")
* .dependencies([anotherPluginClient])
* .atoms(({ dependencies }) => {
* // Obtain the atoms of the dependency plugin client
* const anotherPluginAtoms = dependencies.anotherPlugin.atoms();
* // ...
* });
* ```
*
*
* ---
* @param plugins - The dependencies definitions.
* @returns TypedPluginClientBuilder
*/
dependencies(plugins) {
const dependencies = plugins.map((p) => p.def);
const builder = new _PluginClientBuilder({ ...this.def, dependencies });
return builder;
}
/**
* ### `.config()`
*
* Add a configuration that users can provide to tweak plugin client's behavior.
*
* @see TODO: Add docs link
*
* @example
* ```ts
* const myPluginClient = definePluginClient("my-plugin")
* .config({ schema: z.object({ refreshRate: z.number() }) });
*
* const myAgentClient = defineAgentClient("my-agent")
* .plugins([myPluginClient])
* .myPlugin({ refreshRate: 1000 }); // <-- Here
* ```
*
*
* ---
*
* The provided config can then be accessed from `plugin.config` inside atoms and class.
*
* @example
* ```ts
* const pluginClient = definePluginClient("my-plugin")
* .config({ schema: z.object({ refreshRate: z.number() }) });
* .atoms(({ config }) => {
* const refreshRate = config.refreshRate; // <-- Here
* });
* ```
*
*
* ---
* @param config - The config definition.
* @returns TypedPluginClientBuilder
*/
config(config) {
return this.$config(_chunkBFC2WP6Qjs.zodObjectWithTelemetry.call(void 0, config));
}
/**
* ### `.$config()`
*
* Define plugin client config from the output of `definePluginClientConfig()`.
*
* @see TODO: Add docs link for `definePluginClientConfig()`
*
* ---
* @param config - The config definition.
* @returns TypedPluginClientBuilder
*/
$config(config) {
const builder = new _PluginClientBuilder({ ...this.def, config });
return builder;
}
/**
* ### `.class()`
*
* TODO
*
* @see TODO: Add docs link
*
* ---
* @param input - The class definition.
* @returns TypedPluginClientBuilder
*/
class(extension) {
const builder = new _PluginClientBuilder({ ...this.def, class: extension });
return builder;
}
/**
* ### `.atoms()`
*
* Add reactive states (atoms) that can then be consumed from various UI frameworks
* (React, Vue, Svelte, etc.) to render the plugin data in real-time on the user interface.
*
* Atoms are powered by [nanostores](https://github.com/nanostores/nanostores).
*
* @see TODO: Add docs link
*
* @example
* ```ts
* import { onMount } from "nanostores";
*
* const pluginClient = definePluginClient("my-plugin")
* .atoms(({ plugin }) => {
* const value = atom(0);
* onMount(() => {
* setInterval(async () => {
* const context = await plugin.context.get();
* value.set(context.value + 1);
* }, 1000);
* });
* return { value };
* });
* ```
*
*
* ---
*
* Then from a React component, you can render the `value` atom:
* ```ts
* import { useStore } from "nanostores/react";
*
* export default function Page() {
* const agent = useAgent("my-agent");
* const value = useStore(agent.myPlugin.atoms.value);
* return <div>{value}</div>;
* };
* ```
*
*
* ---
* @param definition - The atoms definition.
* @returns TypedPluginClientBuilder
*/
atoms(atoms) {
const builder = new _PluginClientBuilder({ ...this.def, atoms });
return builder;
}
};
function definePluginClient(name) {
const defaultDefinition = {
name,
config: _chunkBFC2WP6Qjs.zodObjectWithTelemetry.call(void 0, { schema: _zod.z.object() }),
dependencies: [],
class: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (..._args) => class {
}, "class"),
atoms: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (..._args) => [], "atoms"),
$serverDef: null
};
return new PluginClientBuilder(defaultDefinition);
}
_chunk6PEHRAEPjs.__name.call(void 0, definePluginClient, "definePluginClient");
// plugins/defaults/generation/client.ts
var _nanostores = require('nanostores');
var generationPluginClient = definePluginClient("generation").config({ schema: _zod2.default.object({ enableVoice: _zod2.default.boolean().prefault(false) }) }).class(
({ plugin }) => (_class = class {constructor() { _class.prototype.__init.call(this); }
async continue(params) {
return await plugin.server.events.emit({ name: "agent.continue", data: params });
}
async decide(params) {
return await plugin.server.events.emit({ name: "agent.decide", data: params });
}
async say(params) {
return await plugin.server.events.emit({ name: "agent.say", data: params });
}
async interrupt(params) {
return await plugin.server.events.emit({ name: "agent.interrupt", data: params });
}
__init() {this.messages = {
create: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async (params) => await plugin.server.events.emit({ name: "messages.create", data: params }), "create"),
update: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async (params) => await plugin.server.events.emit({ name: "messages.update", data: params }), "update"),
get: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, () => plugin.server.context.get().messages, "get")
}}
}, _class)
).atoms(({ plugin, telemetry }) => [
{
name: "status",
create: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, () => {
const store = _nanostores.atom.call(void 0, null);
_nanostores.onMount.call(void 0, store, () => {
const [error, context] = plugin.server.context.safe.get();
if (error)
telemetry.log.error({
message: "Failed to fetch initial status from context.",
error
});
if (_optionalChain([context, 'optionalAccess', _2 => _2.status])) store.set(context.status);
const unsubscribe = plugin.server.context.onChange(
(ctx) => ctx.status,
(ctx) => store.set(ctx.status)
);
return () => _optionalChain([unsubscribe, 'optionalCall', _3 => _3()]);
});
return { store, refresh: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async () => void 0, "refresh") };
}, "create")
},
{
name: "messages",
create: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, () => {
const store = _nanostores.atom.call(void 0, []);
_nanostores.onMount.call(void 0, store, () => {
const [error, context] = plugin.server.context.safe.get();
if (error)
telemetry.log.error({
message: "Failed to fetch initial messages from context.",
error
});
if (_optionalChain([context, 'optionalAccess', _4 => _4.messages])) store.set(context.messages);
const unsubscribe = plugin.server.context.onChange(
(ctx) => ctx.messages,
(ctx) => store.set(ctx.messages)
);
return () => _optionalChain([unsubscribe, 'optionalCall', _5 => _5()]);
});
return { store, refresh: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async () => void 0, "refresh") };
}, "create")
}
]);
// plugins/defaults/memories/client.ts
var memoriesPluginClient = definePluginClient("memories").dependencies([generationPluginClient]).class((_) => class {
});
// plugins/defaults/stores/client.ts
var storesPluginClient = definePluginClient("stores");
// exports/client.ts
var defaults = {
plugins: {
generation: generationPluginClient,
memories: memoriesPluginClient,
stores: storesPluginClient,
*[Symbol.iterator]() {
for (const entry of Object.values(this)) yield entry;
}
}
};
exports.createLifeClient = _chunkSDCJCCXNjs.createLifeClient; exports.defaults = defaults; exports.defineAgentClient = defineAgentClient; exports.definePluginClient = definePluginClient; exports.parseAgentClientParam = _chunkSDCJCCXNjs.parseAgentClientParam;
//# sourceMappingURL=client.js.map