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,231 lines (1,189 loc) • 44.6 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 _chunkBFC2WP6Qjs = require('./chunk-BFC2WP6Q.js');
var _chunk22H3U7VVjs = require('./chunk-22H3U7VV.js');
var _chunk6PEHRAEPjs = require('./chunk-6PEHRAEP.js');
// shared/canon/serialize.ts
var _serializeerror = require('serialize-error');
var _superjson = require('superjson'); var _superjson2 = _interopRequireDefault(_superjson);
var _zod = require('zod'); var _zod2 = _interopRequireDefault(_zod);
_superjson2.default.registerCustom(
{
isApplicable: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (v) => _chunk22H3U7VVjs.isLifeError.call(void 0, v), "isApplicable"),
// Using superjson.serialize ensures that 'err.cause' gets serialized properly
serialize: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (err) => _superjson2.default.serialize(_chunk22H3U7VVjs.lifeErrorToObject.call(void 0, err)), "serialize"),
deserialize: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (data) => _chunk22H3U7VVjs.lifeErrorFromObject.call(void 0, _superjson2.default.deserialize(data)), "deserialize")
},
"LifeError"
);
_superjson2.default.registerCustom(
{
isApplicable: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (v) => v instanceof _zod.ZodError, "isApplicable"),
serialize: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (err) => err.issues, "serialize"),
deserialize: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (data) => new (0, _zod.ZodError)(data), "deserialize")
},
"ZodError"
);
_superjson2.default.registerCustom(
{
isApplicable: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (v) => _serializeerror.isErrorLike.call(void 0, v), "isApplicable"),
serialize: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (err) => _serializeerror.serializeError.call(void 0, err), "serialize"),
deserialize: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (data) => _serializeerror.deserializeError.call(void 0, data), "deserialize")
},
"Error"
);
_superjson2.default.registerCustom(
{
isApplicable: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (v) => _chunk22H3U7VVjs.isResult.call(void 0, v), "isApplicable"),
serialize: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (result) => _chunk22H3U7VVjs.serializeResult.call(void 0, result), "serialize"),
deserialize: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (data) => _chunk22H3U7VVjs.deserializeResult.call(void 0, data), "deserialize")
},
"OperationResult"
);
var serializablePrimitivesSchema = _zod.z.union([
_zod.z.string(),
_zod.z.number(),
_zod.z.boolean(),
_zod.z.null(),
_zod.z.undefined(),
_zod.z.bigint(),
_zod.z.date(),
_zod.z.instanceof(RegExp),
_zod.z.instanceof(Error),
_zod.z.instanceof(URL),
_zod.z.instanceof(ArrayBuffer),
_zod.z.instanceof(Int8Array),
_zod.z.instanceof(Uint8Array),
_zod.z.instanceof(Uint8ClampedArray),
_zod.z.instanceof(Int16Array),
_zod.z.instanceof(Uint16Array),
_zod.z.instanceof(Int32Array),
_zod.z.instanceof(Uint32Array),
_zod.z.instanceof(Float32Array),
_zod.z.instanceof(Float64Array),
_zod.z.instanceof(BigInt64Array),
_zod.z.instanceof(BigUint64Array)
]);
var serializableValueSchema = _zod.z.lazy(
() => _zod.z.union([
serializablePrimitivesSchema,
_zod.z.array(serializableValueSchema),
_zod.z.set(serializableValueSchema),
_zod.z.map(_zod.z.any(), serializableValueSchema),
_zod.z.record(_zod.z.string(), serializableValueSchema)
])
);
var serialize = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (value) => _chunk22H3U7VVjs.attempt.call(void 0, () => _superjson2.default.serialize(value)), "serialize");
var deserialize = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (value) => {
if (!value) return _chunk22H3U7VVjs.success.call(void 0, value);
return _chunk22H3U7VVjs.attempt.call(void 0, () => _superjson2.default.deserialize(value));
}, "deserialize");
// shared/canon/stringify.ts
function stableDeepStringify(data, sortArrays, opts) {
if (!opts) opts = {};
if (typeof opts === "function") opts = { cmp: opts };
var cycles = typeof opts.cycles === "boolean" ? opts.cycles : false;
var cmp = opts.cmp && /* @__PURE__ */ ((f) => (node) => (a, b) => {
var aobj = { key: a, value: node[a] };
var bobj = { key: b, value: node[b] };
return f(aobj, bobj);
})(opts.cmp);
var seen = [];
return (/* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (function stringify_(node) {
if (node && node.toJSON && typeof node.toJSON === "function") {
node = node.toJSON();
}
if (node === void 0) return "";
if (typeof node == "number") return isFinite(node) ? "" + node : "null";
if (typeof node !== "object") return JSON.stringify(node);
var i, out;
if (Array.isArray(node)) {
const items = node.map((item) => stringify_(item) || "null");
if (sortArrays) items.sort();
return "[" + items.join(",") + "]";
}
if (node === null) return "null";
if (seen.indexOf(node) !== -1) {
if (cycles) return JSON.stringify("__cycle__");
throw new TypeError("Converting circular structure to JSON");
}
var seenIndex = seen.push(node) - 1;
var keys = Object.keys(node).sort(cmp && cmp(node));
out = "";
for (i = 0; i < keys.length; i++) {
var key = keys[i];
var value = stringify_(node[key]);
if (!value) continue;
if (out) out += ",";
out += JSON.stringify(key) + ":" + value;
}
seen.splice(seenIndex, 1);
return "{" + out + "}";
}), "stringify_"))(data);
}
_chunk6PEHRAEPjs.__name.call(void 0, stableDeepStringify, "stableDeepStringify");
var stringify = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (value, sortArrays = false) => {
const [err, res] = serialize(value);
if (err) return _chunk22H3U7VVjs.failure.call(void 0, err);
return _chunk22H3U7VVjs.attempt.call(void 0, () => stableDeepStringify(res, sortArrays));
}, "stringify");
var parse = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (value) => {
const [err, res] = _chunk22H3U7VVjs.attempt.call(void 0, () => JSON.parse(value));
if (err) return _chunk22H3U7VVjs.failure.call(void 0, err);
return deserialize(res);
}, "parse");
// shared/canon/equal.ts
var equal = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (a, b) => {
const [err1, data1] = stringify(a, true);
if (err1) return _chunk22H3U7VVjs.failure.call(void 0, err1);
const [err2, data2] = stringify(b, true);
if (err2) return _chunk22H3U7VVjs.failure.call(void 0, err2);
return _chunk22H3U7VVjs.success.call(void 0, data1 === data2);
}, "equal");
// shared/canon/equal-schema.ts
var equalSchema = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (a, b) => {
const [errJsonA, jsonA] = _chunk22H3U7VVjs.attempt.call(void 0, () => _zod2.default.toJSONSchema(a, { unrepresentable: "any" }));
if (errJsonA) return _chunk22H3U7VVjs.failure.call(void 0, errJsonA);
const [errJsonB, jsonB] = _chunk22H3U7VVjs.attempt.call(void 0, () => _zod2.default.toJSONSchema(b, { unrepresentable: "any" }));
if (errJsonB) return _chunk22H3U7VVjs.failure.call(void 0, errJsonB);
return equal(jsonA, jsonB);
}, "equalSchema");
// shared/canon/murmur.ts
var _imurmurhash = require('imurmurhash'); var _imurmurhash2 = _interopRequireDefault(_imurmurhash);
var murmur3 = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (value) => {
try {
const [err, data] = stringify(value);
if (err) return _chunk22H3U7VVjs.failure.call(void 0, err);
const [errHash, hashNumber] = _chunk22H3U7VVjs.attempt.call(void 0, () => _imurmurhash2.default.call(void 0, data).result());
if (errHash) return _chunk22H3U7VVjs.failure.call(void 0, errHash);
const hash = hashNumber.toString(16);
return _chunk22H3U7VVjs.success.call(void 0, hash);
} catch (error) {
return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error });
}
}, "murmur3");
// shared/canon/sha256.ts
var sha256 = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async (value) => {
try {
const [err, data] = stringify(value);
if (err) return _chunk22H3U7VVjs.failure.call(void 0, err);
const hashedData = new TextEncoder().encode(data);
const hashBuffer = await crypto.subtle.digest("SHA-256", hashedData);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hash = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
return _chunk22H3U7VVjs.success.call(void 0, hash);
} catch (error) {
return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error });
}
}, "sha256");
// shared/canon/index.ts
var canon = {
equal,
equalSchema,
serialize,
deserialize,
sha256,
stringify,
parse,
murmur3
};
// shared/nanoseconds.ts
var hrtimeBigint = (() => {
if (typeof _optionalChain([globalThis, 'access', _ => _.process, 'optionalAccess', _2 => _2.hrtime, 'optionalAccess', _3 => _3.bigint]) === "function") {
return () => globalThis.process.hrtime.bigint();
}
if (typeof _optionalChain([globalThis, 'access', _4 => _4.process, 'optionalAccess', _5 => _5.hrtime]) === "function") {
return () => {
const [s, n] = globalThis.process.hrtime();
return BigInt(s) * 1000000000n + BigInt(n);
};
}
if (typeof _optionalChain([globalThis, 'access', _6 => _6.performance, 'optionalAccess', _7 => _7.now]) === "function") {
let last = 0n;
return () => {
const ns2 = BigInt(Math.floor(globalThis.performance.now() * 1e6));
if (ns2 > last) last = ns2;
return last;
};
}
return () => BigInt(Date.now()) * 1000000n;
})();
var ns = {
/**
* Returns the current Unix timestamp in nanoseconds
* @returns BigInt (ns since epoch)
*/
now() {
return hrtimeBigint();
},
/**
* Returns the duration between the current time and the given start time
* @param start - BigInt (ns since epoch)
* @returns BigInt (ns)
*/
since(n) {
if (!n) return 0n;
return ns.now() - n;
},
/**
* Converts nanoseconds to milliseconds
* @param ns - BigInt (ns)
* @returns number (ms)
*/
toMs(n) {
if (!n) return 0n;
return n / 1000000n;
}
};
// telemetry/helpers/otel-id.ts
var SPAN_ID_BYTES = 8;
var TRACE_ID_BYTES = 16;
var LOG_ID_BYTES = 16;
var METRIC_ID_BYTES = 16;
var SHARED_CHAR_CODES_ARRAY = new Array(32);
function getOtelIdGenerator(bytes) {
return /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, function generateId() {
for (let i = 0; i < bytes * 2; i++) {
SHARED_CHAR_CODES_ARRAY[i] = Math.floor(Math.random() * 16) + 48;
if (SHARED_CHAR_CODES_ARRAY[i] >= 58) {
SHARED_CHAR_CODES_ARRAY[i] += 39;
}
}
return String.fromCharCode.apply(null, SHARED_CHAR_CODES_ARRAY.slice(0, bytes * 2));
}, "generateId");
}
_chunk6PEHRAEPjs.__name.call(void 0, getOtelIdGenerator, "getOtelIdGenerator");
var generateSpanId = getOtelIdGenerator(SPAN_ID_BYTES);
var generateTraceId = getOtelIdGenerator(TRACE_ID_BYTES);
var generateLogId = getOtelIdGenerator(LOG_ID_BYTES);
var generateMetricId = getOtelIdGenerator(METRIC_ID_BYTES);
// telemetry/helpers/register-consumer.ts
var registerConsumer = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (consumer, list) => {
const queue = new (0, _chunkBFC2WP6Qjs.AsyncQueue)();
list.push({ instance: consumer, queue });
consumer.start(queue);
let unregistered = false;
return () => {
if (unregistered) return;
const index = list.findIndex((c) => c.instance === consumer);
if (index !== -1) {
_optionalChain([list, 'access', _8 => _8[index], 'optionalAccess', _9 => _9.queue, 'access', _10 => _10.stop, 'call', _11 => _11()]);
list.splice(index, 1);
unregistered = true;
}
};
}, "registerConsumer");
// telemetry/helpers/strip-ansi.ts
var regex = new RegExp(
[
"[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))",
"(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"
].join("|"),
"g"
);
function stripAnsi(string) {
if (typeof string !== "string") {
throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
}
return string.replace(regex, "");
}
_chunk6PEHRAEPjs.__name.call(void 0, stripAnsi, "stripAnsi");
// telemetry/schemas.ts
var telemetryAttributeSchema = _zod2.default.record(_zod2.default.string(), _zod2.default.unknown());
var telemetryResourceSchema = _zod2.default.object({
environment: _zod2.default.enum(["development", "production", "staging", "test"]),
lifeVersion: _zod2.default.string()
}).and(
_zod2.default.discriminatedUnion("platform", [
_zod2.default.object({
platform: _zod2.default.literal("node"),
isCi: _zod2.default.boolean(),
nodeVersion: _zod2.default.string(),
osName: _zod2.default.string(),
osVersion: _zod2.default.string(),
cpuCount: _zod2.default.number(),
cpuArchitecture: _zod2.default.string(),
schemaVersion: _zod2.default.string().prefault("1")
}),
_zod2.default.object({
platform: _zod2.default.literal("browser"),
deviceType: _zod2.default.enum([
"desktop",
"mobile",
"tablet",
"wearable",
"smarttv",
"console",
"xr",
"embedded",
"unknown"
]),
deviceBrand: _zod2.default.string(),
deviceModel: _zod2.default.string(),
osName: _zod2.default.string(),
osVersion: _zod2.default.string(),
cpuArchitecture: _zod2.default.enum([
"ia32",
"ia64",
"amd64",
"arm",
"arm64",
"armhf",
"avr",
"avr32",
"irix",
"irix64",
"mips",
"mips64",
"68k",
"pa-risc",
"ppc",
"sparc",
"sparc64",
"alpha",
"unknown"
]).optional(),
browserUserAgent: _zod2.default.string(),
browserName: _zod2.default.string(),
browserVersion: _zod2.default.string(),
browserEngine: _zod2.default.enum([
"Amaya",
"ArkWeb",
"Blink",
"EdgeHTML",
"Flow",
"Gecko",
"Goanna",
"iCab",
"KHTML",
"LibWeb",
"Links",
"Lynx",
"NetFront",
"NetSurf",
"Presto",
"Servo",
"Tasman",
"Trident",
"w3m",
"WebKit",
"unknown"
]),
isBot: _zod2.default.boolean(),
isAiBot: _zod2.default.boolean(),
schemaVersion: _zod2.default.string().prefault("1")
})
])
);
var HEX_LOWER_RE = /^[0-9a-f]+$/;
function createOtelHexIdSchema(bytes) {
const len = bytes * 2;
return _zod2.default.string().length(len, `expected ${len} lowercase hex chars`).regex(HEX_LOWER_RE, "must be lowercase hex [0-9a-f]");
}
_chunk6PEHRAEPjs.__name.call(void 0, createOtelHexIdSchema, "createOtelHexIdSchema");
var telemetryTraceIdSchema = createOtelHexIdSchema(TRACE_ID_BYTES);
var telemetryLogIdSchema = createOtelHexIdSchema(LOG_ID_BYTES);
var telemetrySpanIdSchema = createOtelHexIdSchema(SPAN_ID_BYTES);
var telemetryMetricIdSchema = createOtelHexIdSchema(METRIC_ID_BYTES);
var telemetryLogSchema = _zod2.default.object({
id: telemetryLogIdSchema,
scope: _zod2.default.string(),
resource: telemetryResourceSchema,
attributes: telemetryAttributeSchema.optional(),
level: _zod2.default.enum(["debug", "info", "warn", "error", "fatal"]),
/**
* The raw message with ANSI escape codes.
* Useful for displaying in the terminal.
* e.g., will preserve style of `chalk.bold.red("Hello")`
*/
message: _zod2.default.string(),
/**
* The message without any ANSI escape codes.
* Useful for using messages outside of the terminal.
*/
messageUnstyled: _zod2.default.string(),
timestamp: _zod2.default.bigint(),
stack: _zod2.default.string(),
traceId: telemetryTraceIdSchema.optional(),
spanId: telemetrySpanIdSchema.optional(),
error: _zod2.default.custom().optional()
});
var telemetrySpanSchema = _zod2.default.object({
id: telemetrySpanIdSchema,
scope: _zod2.default.string(),
resource: telemetryResourceSchema,
attributes: telemetryAttributeSchema.optional(),
name: _zod2.default.string(),
/**
* The timestamp when the span started in nanoseconds.
*/
startTimestamp: _zod2.default.bigint(),
/**
* The timestamp when the span ended in nanoseconds.
* Is undefined if the span hasn't ended yet.
*/
endTimestamp: _zod2.default.bigint(),
/**
* The duration of the span in nanoseconds.
* Is undefined if the span hasn't ended yet.
*/
duration: _zod2.default.bigint(),
traceId: telemetryTraceIdSchema,
parentSpanId: _zod2.default.string().optional(),
logs: _zod2.default.array(
telemetryLogSchema.omit({ resource: true, scope: true, traceId: true, spanId: true })
)
});
var telemetryMetricSchema = _zod2.default.object({
id: telemetryMetricIdSchema,
scope: _zod2.default.string(),
resource: telemetryResourceSchema,
attributes: telemetryAttributeSchema.optional(),
kind: _zod2.default.enum(["counter", "updown", "histogram"]),
name: _zod2.default.string(),
value: _zod2.default.number().or(_zod2.default.bigint())
});
var telemetrySignalSchema = _zod2.default.discriminatedUnion("type", [
telemetryLogSchema.extend({ type: _zod2.default.literal("log") }),
telemetrySpanSchema.extend({ type: _zod2.default.literal("span") }),
telemetryMetricSchema.extend({ type: _zod2.default.literal("metric") })
]);
// telemetry/clients/base.ts
var defineScopes = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (scopes) => scopes, "defineScopes");
var TelemetryClient = (_class = class _TelemetryClient {
static {
_chunk6PEHRAEPjs.__name.call(void 0, this, "TelemetryClient");
}
static #clients = [];
#scopesDefinition = {};
__init() {this.clientAttributes = {}}
constructor(scopesDefinition, scope) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);
this.scope = scope;
this.#scopesDefinition = scopesDefinition;
this.resource = this.getResource();
_TelemetryClient.#clients.push(this);
}
// Global consumers
static #globalConsumers = [];
/**
* Registers a callback consumer to receive telemetry data from all the clients.
* @param consumer - The consumer to register
* @returns A function that unregisters the consumer when called
* @example
* ```typescript
* const unregister = telemetry.registerGlobalConsumer(myConsumer);
* unregister(); // Later, to stop receiving events
* ```
*/
static registerGlobalConsumer(consumer) {
return registerConsumer(consumer, _TelemetryClient.#globalConsumers);
}
/**
* Flushes any globally pending telemetry data, ensuring that all the consumers
* of all the TelemetryClient instances have finished processing before returning
* or until the timeout is reached.
* @param timeoutMs - Maximum time to wait in milliseconds (default: 10000ms)
* @returns A promise that resolves when flushing is complete or timeout is reached
*/
static async flushAllConsumers(timeoutMs = 1e4) {
await Promise.all(_TelemetryClient.#clients.map((client) => client.flushConsumers(timeoutMs)));
}
// Local consumers
#consumers = [];
/**
* Registers a callback consumer to receive telemetry data from this client.
* @param consumer - The consumer to register
* @returns A function that unregisters the consumer when called
* @example
* ```typescript
* const unregister = telemetry.registerConsumer(myConsumer);
* unregister(); // Later, to stop receiving events
* ```
*/
registerConsumer(consumer) {
try {
return registerConsumer(consumer, this.#consumers);
} catch (error) {
this.log.error({
message: "Error registering telemetry consumer.",
error,
attributes: { consumer }
});
return () => void 0;
}
}
/**
* Flushes any pending telemetry data, ensuring that all consumers have finished
* processing before returning or until the timeout is reached.
* @param timeoutMs - Maximum time to wait in milliseconds (default: 10000ms)
* @returns A promise that resolves when flushing is complete or timeout is reached
*/
async flushConsumers(timeoutMs = 1e4) {
try {
const startTime = Date.now();
while (Date.now() - startTime < timeoutMs) {
let allDone = true;
for (const { instance, queue } of this.#allConsumers) {
if (queue.length() > 0 || _optionalChain([instance, 'access', _12 => _12.isProcessing, 'optionalCall', _13 => _13()])) {
allDone = false;
break;
}
}
if (allDone) return;
await new Promise((resolve) => setTimeout(resolve, 50));
}
} catch (error) {
this.log.error({
message: "Error flushing telemetry consumers.",
error,
attributes: { timeoutMs }
});
}
}
/**
* Sets a client-level attribute that will be included in all telemetry data from this client.
* @param key - The attribute key
* @param value - The attribute value (must be serializable, else will be ignored)
* @example
* ```typescript
* telemetry.setAttribute("modelId", "abc");
* telemetry.setAttribute("region", "us-west-2");
* ```
*/
setAttribute(key, value) {
this.clientAttributes[key] = value;
}
/**
* Sets multiple client-level attributes that will be included in all telemetry data from this client.
* @param attributes - The attributes to set
* @example
* ```typescript
* telemetry.setAttributes({ modelId: "abc", region: "us-west-2" });
* ```
*/
setAttributes(attributes) {
this.clientAttributes = { ...this.clientAttributes, ...attributes };
}
/**
* Measure the duration and capture logs about an operation.
* Automatically handles both sync and async functions, preserving their return types.
* trace() calls can be nested and will produce nested spans.
* @param name - The name of the operation being traced
* @param fn - The function to execute within the span context (sync or async)
* @param options - Optional attributes and parent span
* @returns The result of the function (direct value for sync, Promise for async)
* @example
* ```typescript
* // Sync function - no await needed
* const hash = telemetry.trace("compute-hash", ({ log, setAttribute }) => {
* log.info({ message: "Computing hash" });
* const result = computeHash(data);
* setAttribute("algorithm", "sha256");
* return result;
* }, { attributes: { dataSize: data.length } });
*
* // Async function - await the result
* const user = await telemetry.trace("fetch-user", async ({ log }) => {
* log.info({ message: "Fetching user" });
* const response = await fetch(`/api/users/${id}`);
* return response.json();
* }, { attributes: { userId: id } });
*
* // Early end example:
* telemetry.trace("process-item", ({ end }) => {
* if (shouldSkip) {
* end();
* return;
* }
* // ... process item
* });
* ```
*/
trace(name, fn, options = {}) {
const parentSpan = _nullishCoalesce(options.parent, () => ( this.getCurrentSpan()));
const parentSpanData = _optionalChain([parentSpan, 'optionalAccess', _14 => _14.getData, 'call', _15 => _15()]);
const spanData = {
id: generateSpanId(),
resource: this.resource,
scope: this.scope,
attributes: { ...options.attributes, ...this.clientAttributes },
name,
startTimestamp: ns.now(),
endTimestamp: -1n,
duration: -1n,
traceId: _optionalChain([parentSpanData, 'optionalAccess', _16 => _16.traceId]) || generateTraceId(),
parentSpanId: _optionalChain([parentSpanData, 'optionalAccess', _17 => _17.id]),
logs: []
};
const span = this.#createSpanHandle(spanData);
return this.runWithSpanData(spanData, () => {
try {
const result = fn(span);
if (result instanceof Promise) return result.finally(() => span.end());
span.end();
return result;
} catch (error) {
span.end();
throw error;
}
});
}
/**
* Get the ambient tracing span handle.
* @returns The current tracing span parent (if any)
*/
getCurrentSpan() {
const spanData = this.getCurrentSpanData();
if (!spanData) return;
return this.#createSpanHandle(spanData);
}
/**
* Send a telemetry signal to all consumers.
* This a raw method, prefer using log.*(), counter(), updown(), histogram(), etc.
* @param signal - The telemetry signal to send
*/
sendSignal(signal, throwOnError = false) {
try {
signal.attributes = { ...signal.attributes, ...this.clientAttributes };
const { error, data: parsedSignal } = telemetrySignalSchema.safeParse(signal);
if (error)
throw _chunk22H3U7VVjs.lifeError.call(void 0, {
code: "Validation",
message: "Invalid telemetry signal shape. It has been ignored.",
attributes: { signal },
cause: error
});
const scopeDefinition = _optionalChain([this, 'access', _18 => _18.#scopesDefinition, 'optionalAccess', _19 => _19[_nullishCoalesce(_optionalChain([parsedSignal, 'optionalAccess', _20 => _20.scope]), () => ( ""))]]);
if (!scopeDefinition) {
throw _chunk22H3U7VVjs.lifeError.call(void 0, {
code: "Validation",
message: `Invalid telemetry scope '${parsedSignal.scope}' in signal. It has been ignored.`,
attributes: { parsedSignal }
});
}
if (scopeDefinition.requiredAttributesSchema) {
const { error: attributesError, data: parsedAttributes } = scopeDefinition.requiredAttributesSchema.safeParse(_nullishCoalesce(_optionalChain([parsedSignal, 'optionalAccess', _21 => _21.attributes]), () => ( {})));
if (attributesError)
throw _chunk22H3U7VVjs.lifeError.call(void 0, {
code: "Validation",
message: `Signal contains invalid required attributes for scope '${parsedSignal.scope}'. It has been ignored.`,
attributes: { parsedSignal },
cause: attributesError
});
parsedSignal.attributes = { ...parsedSignal.attributes, ...parsedAttributes };
}
const [errSerialize, serializedSignal] = canon.stringify(parsedSignal);
if (errSerialize) {
throw _chunk22H3U7VVjs.lifeError.call(void 0, {
code: "Validation",
message: "Failed to serialize telemetry signal. It has been ignored.",
attributes: { parsedSignal },
cause: errSerialize
});
}
const MAX_SIGNAL_SIZE = 1024 * 1024;
if (serializedSignal.length > MAX_SIGNAL_SIZE) {
throw _chunk22H3U7VVjs.lifeError.call(void 0, {
code: "Validation",
message: "Telemetry signal is too large. It has been ignored.",
attributes: { parsedSignal }
});
}
for (const consumer of this.#allConsumers) consumer.queue.push(parsedSignal);
} catch (error) {
if (throwOnError) throw error;
else
this.log.error({
message: "Unexpected error sending telemetry signal. It has been ignored.",
error,
attributes: { signal }
});
}
}
/**
* Unsafe version of sendSignal() bypassing all validation and checks.
* Used internally to forward telemetry signals between processes.
* @internal
*/
_unsafeSendSignal(signal) {
for (const consumer of this.#allConsumers) consumer.queue.push(signal);
}
/**
* Creates a counter metric for tracking monotonically increasing values.
* @param name - The name of the counter metric
* @returns An object with methods to increment the counter
* @example
* ```typescript
* const requestCounter = telemetry.counter("http_requests_total");
* requestCounter.increment({ method: "GET", status: "200" });
* requestCounter.add(5, { batch: "true" });
* ```
*/
counter(name) {
return {
add: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (n, attributes) => {
try {
const fullMetric = {
id: generateMetricId(),
resource: this.resource,
scope: this.scope,
attributes,
name,
kind: "counter",
value: n
};
this.sendSignal({ type: "metric", ...fullMetric });
} catch (error) {
this.log.error({
message: "Error adding to counter metric.",
error,
attributes: { name, n, attributes }
});
}
}, "add"),
increment: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (attributes) => {
try {
this.counter(name).add(1, attributes);
} catch (error) {
this.log.error({
message: "Error incrementing counter metric.",
error,
attributes: { name, attributes }
});
}
}, "increment")
};
}
/**
* Creates an up/down counter metric for tracking values that can increase or decrease.
* @param name - The name of the up/down counter metric
* @returns An object with methods to modify the counter
* @example
* ```typescript
* const connectionGauge = telemetry.updown("active_connections");
* connectionGauge.increment(); // New connection
* connectionGauge.decrement(); // Connection closed
* connectionGauge.add(10); // Bulk connections
* ```
*/
updown(name) {
return {
add: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (n, attributes) => {
try {
const fullMetric = {
id: generateMetricId(),
resource: this.resource,
scope: this.scope,
attributes,
name,
kind: "updown",
value: n
};
this.sendSignal({ type: "metric", ...fullMetric });
} catch (error) {
this.log.error({
message: "Error adding to updown metric.",
error,
attributes: { name, n, attributes }
});
}
}, "add"),
remove: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (n, attributes) => {
try {
this.updown(name).add(-n, attributes);
} catch (error) {
this.log.error({
message: "Error removing from updown metric.",
error,
attributes: { name, n, attributes }
});
}
}, "remove"),
increment: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (attributes) => {
try {
this.updown(name).add(1, attributes);
} catch (error) {
this.log.error({
message: "Error incrementing updown metric.",
error,
attributes: { name, attributes }
});
}
}, "increment"),
decrement: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (attributes) => {
try {
this.updown(name).add(-1, attributes);
} catch (error) {
this.log.error({
message: "Error decrementing updown metric.",
error,
attributes: { name, attributes }
});
}
}, "decrement")
};
}
/**
* Creates a histogram metric for recording value distributions over time.
* @param name - The name of the histogram metric
* @returns An object with a method to record values
* @example
* ```typescript
* const latencyHistogram = telemetry.histogram("request_duration_ms");
* latencyHistogram.record(responseTime, { endpoint: "/api/users" });
* ```
*/
histogram(name) {
return {
record: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (value, attributes) => {
try {
const fullMetric = {
id: generateMetricId(),
resource: this.resource,
scope: this.scope,
attributes,
name,
kind: "histogram",
value
};
this.sendSignal({ type: "metric", ...fullMetric });
} catch (error) {
this.log.error({
message: "Error recording histogram metric.",
error,
attributes: { name, value, attributes }
});
}
}, "record")
};
}
/**
* Log writer for recording events at different severity levels.
* Logs are automatically associated with the current span context if one exists.
* @example
* ```typescript
* telemetry.log.info({ message: "Server started", attributes: { port: 3000 } });
* telemetry.log.error({ error: new Error("Connection failed"), attributes: { host: "db.example.com" } });
* telemetry.log.warn({ message: "Deprecated API used", attributes: { endpoint: "/v1/users" } });
* ```
*/
__init2() {this.log = {
debug: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (input) => this.#emitLog("debug", input), "debug"),
info: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (input) => this.#emitLog("info", input), "info"),
warn: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (input) => this.#emitLog("warn", input), "warn"),
error: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (input) => this.#emitLog("error", input), "error"),
fatal: /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (input) => this.#emitLog("fatal", input), "fatal")
}}
// ========== Private Methods ==========
/**
* Get all consumers.
* Including local and global consumers.
*/
get #allConsumers() {
return this.#consumers.concat(_TelemetryClient.#globalConsumers);
}
#endSpan(spanData) {
try {
if (spanData.endTimestamp !== -1n) return;
spanData.endTimestamp = ns.now();
spanData.duration = ns.since(spanData.startTimestamp);
this.sendSignal({ type: "span", ...spanData });
} catch (error) {
this.log.error({
message: "Error ending span.",
error,
attributes: { span: spanData }
});
}
}
/**
* Private helper to create a span and its associated methods.
* Used by both trace() and traceBlock() to avoid code duplication.
*/
#createSpanHandle(spanData) {
const getData = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, () => _chunkBFC2WP6Qjs.deepClone.call(void 0, spanData), "getData");
const _getWritableData = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, () => spanData, "_getWritableData");
const end = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, () => this.#endSpan(spanData), "end");
const setAttribute = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (key, value) => {
if (spanData.endTimestamp !== -1n) {
this.log.error({
message: "Attempted to call 'setAttribute()' on already ended span. This is unexpected and must be fixed.",
attributes: { span: spanData, key, value }
});
return;
}
spanData.attributes = spanData.attributes || {};
spanData.attributes[key] = value;
}, "setAttribute");
const setAttributes = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (_attributes) => {
if (spanData.endTimestamp !== -1n) {
this.log.error({
message: "Attempted to call 'setAttributes()' on already ended span. This is unexpected and must be fixed.",
attributes: { span: spanData, attributes: _attributes }
});
return;
}
spanData.attributes = { ...spanData.attributes, ..._attributes };
}, "setAttributes");
const span = { end, setAttribute, setAttributes, getData, _getWritableData };
const createSpanLogMethod = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (level) => (input) => {
if (spanData.endTimestamp !== -1n) {
this.log.error({
message: `Attempted to call 'log.${level}()' on already ended span. This is unexpected and must be fixed.`,
attributes: { span: spanData, input }
});
return;
}
this.#emitLog(level, { ...input, span });
}, "createSpanLogMethod");
const log = {
debug: createSpanLogMethod("debug"),
info: createSpanLogMethod("info"),
warn: createSpanLogMethod("warn"),
error: createSpanLogMethod("error"),
fatal: createSpanLogMethod("fatal")
};
Object.assign(span, { log });
return span;
}
/**
* Internal log method that handles all log levels
*/
#emitLog(level, input, fromEmitLog = false) {
try {
if (fromEmitLog) {
let consoleMethod = "log";
if (level === "error") consoleMethod = "error";
else if (level === "warn") consoleMethod = "warn";
console[consoleMethod](`[${level}] ${JSON.stringify(input)}`);
return;
}
const spanData = _nullishCoalesce(_optionalChain([input, 'access', _22 => _22.span, 'optionalAccess', _23 => _23._getWritableData, 'call', _24 => _24()]), () => ( this.getCurrentSpanData()));
const error = input.error;
const message = "message" in input ? input.message : _optionalChain([error, 'optionalAccess', _25 => _25.message]);
if (!message)
throw _chunk22H3U7VVjs.lifeError.call(void 0, {
code: "Validation",
message: "No message provided in log input or error. This is unexpected and must be fixed.",
attributes: { level, input }
});
const log = {
id: generateLogId(),
resource: this.resource,
scope: this.scope,
attributes: input.attributes,
level,
message,
messageUnstyled: stripAnsi(message),
timestamp: ns.now(),
stack: _nullishCoalesce(_nullishCoalesce(_optionalChain([error, 'optionalAccess', _26 => _26.stack]), () => ( new Error(".").stack)), () => ( "unknown")),
traceId: _optionalChain([spanData, 'optionalAccess', _27 => _27.traceId]),
spanId: _optionalChain([spanData, 'optionalAccess', _28 => _28.id]),
error
};
if (input.span && spanData) spanData.logs.push(log);
this.sendSignal({ type: "log", ...log }, true);
} catch (error) {
if (this.resource.environment === "test") throw error;
if (fromEmitLog) {
console.error("[emitLog] Error occurred while logging error:", error);
return;
}
this.#emitLog(
"error",
{
message: "Error emitting log.",
error,
attributes: { level, input }
},
true
);
}
}
}, _class);
// package.json
var package_default = {
name: "life",
version: "0.40.0",
description: "Life.js is the first fullstack framework to build agentic web applications. It is minimal, extensible, and typesafe. Well, everything you love.",
author: "Lila Rest",
license: "MIT+Services",
homepage: "https://lifejs.org",
bugs: {
url: "https://github.com/lifejs/lifejs/issues"
},
repository: {
type: "git",
url: "https://github.com/lifejs/lifejs"
},
files: [
"dist/",
"package.json",
"README.md",
"LICENSE",
"LICENSE.SERVICES"
],
keywords: [
"react",
"framework",
"typescript",
"fullstack",
"agents",
"agentic"
],
scripts: {
build: "tsup",
dev: "tsup --watch",
types: "tsc --noEmit --emitDeclarationOnly false",
test: "dotenv -e ../../.env -- vitest run",
prepack: "cp ../../README.md README.md && cp ../../LICENSE LICENSE && cp ../../LICENSE.SERVICES LICENSE.SERVICES"
},
bin: {
life: "./dist/cli/index.mjs"
},
sideEffects: false,
engines: {
node: ">=20.0.0"
},
publishConfig: {
access: "public"
},
exports: {
"./config": {
import: {
types: "./dist/exports/config.d.ts",
default: "./dist/exports/config.mjs"
},
require: {
types: "./dist/exports/config.d.ts",
default: "./dist/exports/config.js"
}
},
"./server": {
import: {
types: "./dist/exports/server.d.ts",
default: "./dist/exports/server.mjs"
},
require: {
types: "./dist/exports/server.d.ts",
default: "./dist/exports/server.js"
}
},
"./client": {
import: {
types: "./dist/exports/client.d.ts",
default: "./dist/exports/client.mjs"
},
require: {
types: "./dist/exports/client.d.ts",
default: "./dist/exports/client.js"
}
},
"./react": {
import: {
types: "./dist/exports/react.d.ts",
default: "./dist/exports/react.mjs"
},
require: {
types: "./dist/exports/react.d.ts",
default: "./dist/exports/react.js"
}
}
},
dependencies: {
"@ast-grep/napi": "^0.39.9",
"@hono/node-server": "^1.19.6",
"@hono/node-ws": "^1.2.0",
"@huggingface/transformers": "^3.7.6",
"@inkjs/ui": "^2.0.0",
"@jridgewell/trace-mapping": "^0.3.31",
"@livekit/rtc-node": "^0.13.20",
"@nanostores/react": "^1.0.0",
"@paralleldrive/cuid2": "^3.0.4",
"@vitest/browser-playwright": "^4.0.8",
"@zenobius/ink-mouse": "^1.0.3",
birpc: "^2.8.0",
chalk: "^5.6.2",
chokidar: "^4.0.3",
commander: "^14.0.2",
dotenv: "^17.2.3",
"error-stack-parser": "^2.1.4",
esbuild: "^0.27.0",
"fast-npm-meta": "^0.4.7",
figures: "^6.1.0",
globby: "^15.0.0",
hono: "^4.10.5",
imurmurhash: "^0.1.4",
ink: "^6.5.0",
"ink-link": "^5.0.0",
"livekit-client": "^2.15.15",
"livekit-server-sdk": "^2.14.0",
"mathjax-full": "^3.2.2",
"mdast-flatten-nested-lists": "^1.2.0",
"mdast-util-from-markdown": "^2.0.2",
"mdast-util-gfm": "^3.1.0",
"mdast-util-math": "^3.0.0",
"mdast-util-mdx-jsx": "^3.2.0",
"mdast-util-to-markdown": "^2.1.2",
"micromark-extension-gfm": "^3.0.0",
"micromark-extension-math": "^3.1.0",
"micromark-extension-mdx-jsx": "^3.0.2",
nanostores: "^1.0.1",
"onnxruntime-node": ">=1.24.0-0",
"oxc-parser": "^0.97.0",
"oxc-walker": "^0.5.2",
react: "^19.2.0",
resolve: "^1.22.11",
"serialize-error": "^12.0.0",
"speech-rule-engine": "^5.0.0-alpha.8",
"string-width": "^8.1.0",
superjson: "^2.2.5",
"to-words": "^4.8.0",
"ua-parser-js": "^2.0.5",
"wrap-ansi": "^9.0.2",
yjs: "^13.6.27",
zod: "^4.1.12"
},
devDependencies: {
"@cartesia/cartesia-js": "^2.2.9",
"@deepgram/sdk": "4.11.2",
"@mistralai/mistralai": "^1.10.0",
"@playwright/test": "^1.56.1",
"@types/imurmurhash": "^0.1.4",
"@types/mdast": "^4.0.4",
"@types/node": "^24.10.1",
"@types/react": "^19.2",
"@types/react-dom": "^19.2",
"@types/resolve": "^1.20.6",
"@types/ws": "^8.18.1",
"@vitest/browser": "^4.0.8",
"dotenv-cli": "^11.0.0",
"esbuild-plugin-preserve-directives": "^0.0.11",
openai: "^5.20.2",
playwright: "^1.56.1",
tsup: "^8.5.0",
"type-fest": "^5.2.0",
vitest: "^4.0.8"
},
peerDependencies: {
"@cartesia/cartesia-js": "^2.2.5",
"@deepgram/sdk": "4.9.1",
"@mistralai/mistralai": "^1.7.4",
openai: "^5.9.0"
},
peerDependenciesMeta: {
"@cartesia/cartesia-js": {
optional: true
},
"@deepgram/sdk": {
optional: true
},
"@mistralai/mistralai": {
optional: true
},
openai: {
optional: true
}
}
};
exports.canon = canon; exports.ns = ns; exports.stripAnsi = stripAnsi; exports.telemetrySignalSchema = telemetrySignalSchema; exports.defineScopes = defineScopes; exports.TelemetryClient = TelemetryClient; exports.package_default = package_default;
//# sourceMappingURL=chunk-VLUR4YND.js.map