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,231 lines (1,189 loc) 44.6 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } 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