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,126 lines (1,069 loc) 197 kB
"use strict"; function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } 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 _class3; var _class4; var _class5; var _class6; var _chunkEL6AAGQAjs = require('./chunk-EL6AAGQA.js'); var _chunk5EKUVSA3js = require('./chunk-5EKUVSA3.js'); var _chunkVLUR4YNDjs = require('./chunk-VLUR4YND.js'); var _chunkHPM3R2DVjs = require('./chunk-HPM3R2DV.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'); // cli/run.ts var _commander = require('commander'); // telemetry/helpers/formatting/terminal.ts var _path2 = require('path'); var _path3 = _interopRequireDefault(_path2); var _chalk = require('chalk'); var _chalk2 = _interopRequireDefault(_chalk); var _esbuild = require('esbuild'); var _esbuild2 = _interopRequireDefault(_esbuild); var _zod = require('zod'); var _zod2 = _interopRequireDefault(_zod); // cli/utils/theme.ts var theme = { orange: "#E77823", gray: { light: "#bbbbbb", medium: "#888888", dark: "#444444" }, level: { fatal: "red", error: "red", warn: "#FFA500", info: "cyan", debug: "gray" } }; var themeChalk = { orange: _chalk2.default.hex(theme.orange), gray: { light: _chalk2.default.hex(theme.gray.light), medium: _chalk2.default.hex(theme.gray.medium), dark: _chalk2.default.hex(theme.gray.dark) }, level: { fatal: _chalk2.default.bgRed, error: _chalk2.default.red, info: _chalk2.default.cyan, debug: _chalk2.default.gray, warn: _chalk2.default.hex(theme.level.warn) } }; // telemetry/helpers/formatting/terminal.ts var isEsbuildError = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (error) => { if (error instanceof Error && "errors" in error) { const errorsSchema = _zod2.default.array( _zod2.default.object({ id: _zod2.default.string().optional(), pluginName: _zod2.default.string().optional(), text: _zod2.default.string().optional() }) ); const { success: success2 } = errorsSchema.safeParse(error.errors); return success2; } return false; }, "isEsbuildError"); function formatErrorForTerminal(error) { let code = ""; let message = ""; let stack = ""; let after = ""; let processed = false; if (_chunk22H3U7VVjs.isLifeError.call(void 0, error)) { code = `LifeError (${_chalk2.default.bold(error.code)})`; message = error.message; stack = error.stack ? error.stack.split("\n").slice(3).join("\n") : ""; if (error.cause) { after += formatErrorForTerminal(error.cause); const typedCause = error.cause; if (error.code === "Unknown" && _optionalChain([typedCause, 'optionalAccess', _2 => _2.stack])) stack = ""; } processed = true; } else if (error instanceof _zod2.default.ZodError) { code = "ZodError"; message = _zod2.default.prettifyError(error); stack = _nullishCoalesce(error.stack, () => ( "")); if (stack.includes(" at ")) { stack = ` ${_nullishCoalesce(stack.split(" at ").slice(1).map((line) => ` at ${line}`).join(""), () => ( ""))}`; } processed = true; } else if (isEsbuildError(error)) { const formatEsbuildMessage = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (msg) => _nullishCoalesce(_optionalChain([_esbuild2.default, 'access', _3 => _3.formatMessagesSync, 'call', _4 => _4([msg], { kind: "error", color: true }), 'optionalAccess', _5 => _5[0], 'optionalAccess', _6 => _6.replace, 'call', _7 => _7("\x1B[31m\u2718 \x1B[41;31m[\x1B[41;97mERROR\x1B[41;31m]\x1B[0m \x1B[1m", ""), 'optionalAccess', _8 => _8.trim, 'call', _9 => _9()]), () => ( "")), "formatEsbuildMessage"); try { const esbuildError = error; const formattedMessages = esbuildError.errors.map(formatEsbuildMessage); message = `BuildError: ${formattedMessages.join("\n\n")}`; processed = true; } catch (_) { } } if (!processed && error instanceof Error) { if ("name" in error && typeof error.name === "string") code = error.name; else if ("code" in error && typeof error.code === "string") code = error.code; if ("message" in error && typeof error.message === "string") message = error.message; else if ("reason" in error && typeof error.reason === "string") message = error.reason; if ("stack" in error && typeof error.stack === "string") stack = error.stack; stack = _nullishCoalesce(_optionalChain([stack, 'optionalAccess', _10 => _10.split, 'call', _11 => _11("\n"), 'optionalAccess', _12 => _12.filter, 'call', _13 => _13((line) => !line.includes(error.message.trim())), 'optionalAccess', _14 => _14.join, 'call', _15 => _15("\n")]), () => ( "")); if (!code) code = "Unknown Error"; if (!message) message = "An unknown error occurred."; if (!stack) stack = ""; } if (error instanceof Error && error.cause && !_chunk22H3U7VVjs.isLifeError.call(void 0, error)) { after += `${formatErrorForTerminal(error.cause)}`; } stack = stack.replace(/\/[^\s\n\r:;,()[\]{}'"<>]+/g, (match) => { try { if (_path3.default.isAbsolute(match)) { const relativePath = _path3.default.relative(process.cwd(), match); if (relativePath.length < match.length) return relativePath; } return match; } catch (e) { return match; } }); return `${code}${code ? ": " : ""}${message}${message ? " " : ""}${stack ? ` ${stack}` : ""}${after ? ` ${after}` : ""}`; } _chunk6PEHRAEPjs.__name.call(void 0, formatErrorForTerminal, "formatErrorForTerminal"); function formatLogForTerminal(log) { let style; if (log.level === "fatal") style = { prefix: themeChalk.level.fatal.bold("\u2718"), color: themeChalk.level.fatal }; else if (log.level === "error") style = { prefix: themeChalk.level.error.bold("\u2718"), color: themeChalk.level.error }; else if (log.level === "warn") style = { prefix: themeChalk.level.warn.bold("\u25B2"), color: themeChalk.level.warn }; else if (log.level === "info") style = { prefix: themeChalk.level.info.bold("\u29BF"), color: themeChalk.level.info }; else style = { prefix: themeChalk.level.debug.bold("\u2234"), color: themeChalk.level.debug }; const scopeDefinition = _nullishCoalesce(_optionalChain([_chunk5EKUVSA3js.telemetryNodeScopesDefinition, 'optionalAccess', _16 => _16[log.scope]]), () => ( _optionalChain([_chunkEL6AAGQAjs.telemetryBrowserScopesDefinition, 'optionalAccess', _17 => _17[log.scope]]))); const scopeDisplayName = _optionalChain([scopeDefinition, 'optionalAccess', _18 => _18.displayName]) instanceof Function ? ( // biome-ignore lint/suspicious/noExplicitAny: fine here scopeDefinition.displayName(log.attributes) ) : _optionalChain([scopeDefinition, 'optionalAccess', _19 => _19.displayName]); const scope = `${_chalk2.default.gray(`[${_chalk2.default.italic(_nullishCoalesce(scopeDisplayName, () => ( "Unknown")))}]`)} `; const message = log.message || ""; const header = `${style.prefix} ${scope}${style.color ? style.color(message) : message}`; const error = formatErrorForTerminal(log.error); const errorColor = ["error", "fatal"].includes(log.level) ? themeChalk.level.error : themeChalk.level.warn; let output = header; if (error) output += ` ${errorColor.dim("-----")} ${errorColor(error)} ${errorColor.dim("-----")}`; return output; } _chunk6PEHRAEPjs.__name.call(void 0, formatLogForTerminal, "formatLogForTerminal"); // cli/commands/build/index.ts // cli/utils/header.ts // cli/utils/version.ts var _fastnpmmeta = require('fast-npm-meta'); async function getVersion() { const currentVersion = _chunkVLUR4YNDjs.package_default.version; try { const latestVersionData = await _fastnpmmeta.getLatestVersion.call(void 0, "life"); const latestVersion = latestVersionData.version; return { current: currentVersion, latest: _nullishCoalesce(latestVersion, () => ( void 0)), hasUpdate: currentVersion !== latestVersion }; } catch (e2) { return { current: currentVersion, hasUpdate: false }; } } _chunk6PEHRAEPjs.__name.call(void 0, getVersion, "getVersion"); function formatVersion(versionInfo) { const hasUpdate = versionInfo.hasUpdate && versionInfo.latest; const raw = hasUpdate ? `${versionInfo.current} (\u2191 ${versionInfo.latest})` : versionInfo.current; const output = hasUpdate ? `${themeChalk.gray.medium(versionInfo.current)} ${_chalk2.default.green(_chalk2.default.bold(`(\u2191 ${versionInfo.latest})`))}` : themeChalk.gray.medium(versionInfo.current); return { raw, output }; } _chunk6PEHRAEPjs.__name.call(void 0, formatVersion, "formatVersion"); // cli/utils/header.ts async function generateHeader(name) { const nameLength = `Life.js ${name}`.length; const formattedVersion = formatVersion(await getVersion()); const gap = 13; const padding = 1; const headerSeparator = _chalk2.default.gray( "\u2500".repeat(nameLength + gap + formattedVersion.raw.length + padding * 2) ); return ` ${headerSeparator} ${" ".repeat(padding)}${themeChalk.gray.medium("Life.js")} ${themeChalk.orange(_chalk2.default.italic(name))}${" ".repeat(gap)}${formattedVersion.output}${" ".repeat(padding)} ${headerSeparator} `; } _chunk6PEHRAEPjs.__name.call(void 0, generateHeader, "generateHeader"); // compiler/index.ts var _crypto = require('crypto'); var _promises = require('fs/promises'); var _promises2 = _interopRequireDefault(_promises); var _os = require('os'); var _os2 = _interopRequireDefault(_os); var _napi = require('@ast-grep/napi'); var _chokidar = require('chokidar'); var _chokidar2 = _interopRequireDefault(_chokidar); var _globby = require('globby'); var _typescript = require('typescript'); var _typescript2 = _interopRequireDefault(_typescript); // compiler/helpers/dependencies-map.ts var _oxcparser = require('oxc-parser'); var _oxcwalker = require('oxc-walker'); var _resolve = require('resolve'); var _resolve2 = _interopRequireDefault(_resolve); var EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs", ".json"]; var detectLanguage = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (f) => { const ext = _path3.default.extname(f).toLowerCase(); if (ext === ".tsx") return "tsx"; if (ext === ".ts" || ext === ".mts" || ext === ".cts") return "ts"; if (ext === ".jsx") return "jsx"; return "js"; }, "detectLanguage"); var resolveLocalFrom = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (spec, basedir) => { try { const resolved = _resolve2.default.sync(spec, { basedir, extensions: EXTENSIONS, preserveSymlinks: true, includeCoreModules: false }); return resolved.includes("/node_modules/") ? null : resolved; } catch (e3) { return null; } }, "resolveLocalFrom"); var isTypeOnlyImport = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (node) => { if (node.type === "ImportDeclaration" && node.importKind === "type") { return true; } if (node.type === "ImportDeclaration" && node.specifiers) { if (node.specifiers.length === 0) { return false; } const hasValueImports = node.specifiers.some((spec) => { if (spec.type === "ImportDefaultSpecifier" || spec.type === "ImportNamespaceSpecifier") { return true; } return spec.type === "ImportSpecifier" && spec.importKind !== "type"; }); return !hasValueImports; } return false; }, "isTypeOnlyImport"); var getDependenciesMap = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async (entries, exclude = [], skipTypeOnlyDependencies = false) => { const output = /* @__PURE__ */ new Set(); const entriesArray = Array.isArray(entries) ? entries : [entries]; for (const p of entriesArray) { if (!_path3.default.isAbsolute(p)) return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Provided entry path must be absolute: ${p}` }); } const entriesSet = new Set(entriesArray.map((p) => _path3.default.resolve(p))); const excludeArray = Array.isArray(exclude) ? exclude : [exclude]; for (const p of excludeArray) { if (p && !_path3.default.isAbsolute(p)) return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Provided exclude path must be absolute: ${p}` }); } const excludeSet = new Set(excludeArray.filter(Boolean).map((p) => _path3.default.resolve(p))); const queue = [...entriesSet]; const visited = /* @__PURE__ */ new Set(); while (queue.length) { const file = queue.pop(); if (!file) throw new Error("Shouldn't happen"); if (visited.has(file) || excludeSet.has(file)) continue; visited.add(file); let content; try { content = await _promises2.default.readFile(file, "utf8"); } catch (e4) { continue; } let ast; try { ast = await _oxcparser.parseAsync.call(void 0, file, content, { sourceType: "module", lang: detectLanguage(file) }); } catch (e5) { continue; } const specifiers = /* @__PURE__ */ new Set(); _oxcwalker.walk.call(void 0, ast.program, { enter(node) { if (node.type === "ImportDeclaration" && _optionalChain([node, 'access', _20 => _20.source, 'optionalAccess', _21 => _21.value])) { if (skipTypeOnlyDependencies && isTypeOnlyImport(node)) { return; } specifiers.add(node.source.value); } if ((node.type === "ExportAllDeclaration" || node.type === "ExportNamedDeclaration") && _optionalChain([node, 'access', _22 => _22.source, 'optionalAccess', _23 => _23.value])) { if (skipTypeOnlyDependencies && node.exportKind === "type") { return; } specifiers.add(node.source.value); } if (node.type === "ImportExpression" && _optionalChain([node, 'access', _24 => _24.source, 'optionalAccess', _25 => _25.type]) === "Literal" && typeof node.source.value === "string") { specifiers.add(node.source.value); } if (node.type === "CallExpression" && _optionalChain([node, 'access', _26 => _26.arguments, 'optionalAccess', _27 => _27.length]) === 1) { const arg = node.arguments[0]; const literalArg = arg && arg.type === "Literal" && typeof arg.value === "string" ? arg.value : null; if (literalArg && node.callee.type === "Identifier" && node.callee.name === "require") { specifiers.add(literalArg); } else if (literalArg && node.callee.type === "MemberExpression" && node.callee.object.type === "Identifier" && node.callee.object.name === "require" && node.callee.property.type === "Identifier" && node.callee.property.name === "resolve") { specifiers.add(literalArg); } } } }); const basedir = _path3.default.dirname(file); for (const spec of specifiers) { const resolved = resolveLocalFrom(spec, basedir); if (!resolved || excludeSet.has(resolved)) continue; if (!entriesSet.has(resolved)) output.add(resolved); if (!visited.has(resolved)) queue.push(resolved); } } return _chunk22H3U7VVjs.success.call(void 0, Array.from(output)); }, "getDependenciesMap"); // compiler/options.ts var compilerOptionsSchema = _zod2.default.object({ projectDirectory: _zod2.default.string(), outputDirectory: _zod2.default.string().prefault(".life"), watch: _zod2.default.boolean().prefault(false), stopOnError: _zod2.default.boolean().prefault(true) }); // compiler/index.ts var EXCLUDED_DEFAULTS = ["**/node_modules/**", "**/build/**", "**/generated/**", "**/dist/**"]; var LifeCompiler = (_class = class { static { _chunk6PEHRAEPjs.__name.call(void 0, this, "LifeCompiler"); } __init() {this.hashes = /* @__PURE__ */ new Map()} __init2() {this.watcher = null} __init3() {this.paths = { configs: /* @__PURE__ */ new Set(), servers: /* @__PURE__ */ new Set(), clients: /* @__PURE__ */ new Set(), dependencies: /* @__PURE__ */ new Map(), // entryPath -> dependencies serverBuilds: /* @__PURE__ */ new Map(), // entryPath -> buildPath clientBuilds: /* @__PURE__ */ new Map() // entryPath -> buildPath }} // Language Service for faster type extraction #serverBundleContext = null; #languageService; #serviceHost; #virtualFiles = /* @__PURE__ */ new Map(); #pluginNamesCache = /* @__PURE__ */ new Map(); constructor(options) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this); this.options = compilerOptionsSchema.parse(options); if (this.options.watch && _optionalChain([options, 'optionalAccess', _28 => _28.stopOnError]) === void 0) { this.options.stopOnError = false; } this.telemetry = _chunk5EKUVSA3js.createTelemetryClient.call(void 0, "compiler", { watch: this.options.watch }); this.options.outputDirectory = this.options.outputDirectory.startsWith("/") ? this.options.outputDirectory : _path2.join.call(void 0, this.options.projectDirectory, this.options.outputDirectory); } async start() { return await this.telemetry.trace("start()", async (span) => { try { span.log.info({ message: "Starting compiler." }); span.log.debug({ message: `Project directory: ${this.options.projectDirectory}` }); span.log.debug({ message: `Output directory: ${this.options.outputDirectory}` }); this.telemetry.counter("compiler_started").increment(); await this.telemetry.trace("initial-compilation", async (spanCompilation) => { await Promise.all([this.ensureBuildDirectory(), this.linkBuildDirectory()]); const entryPaths = _globby.globbySync.call(void 0, [ "**/agent/{server.ts,client.ts}", "**/agents/*/{server.ts,client.ts}", "**/life.config.ts" ], { cwd: this.options.projectDirectory, ignore: EXCLUDED_DEFAULTS, dot: false, onlyFiles: true, absolute: true, gitignore: true, unique: true } ); await Promise.all(entryPaths.map(async (p) => this.refreshEntryPathDependencies(p))); const configResults = await Promise.all( entryPaths.filter((p) => p.endsWith("life.config.ts")).map( async (absPath) => await this.processFileEvent({ action: "added", absPath, type: "config", noTimingLogs: true }) ) ); const agentResults = await Promise.all([ ...entryPaths.filter((p) => p.endsWith("server.ts")).map( async (absPath) => await this.processFileEvent({ action: "added", absPath, type: "server", noTimingLogs: true }) ), ...entryPaths.filter((p) => p.endsWith("client.ts")).map( async (absPath) => await this.processFileEvent({ action: "added", absPath, type: "client", noTimingLogs: true }) ) ]); const results = [...configResults, ...agentResults]; spanCompilation.end(); const duration = spanCompilation.getData().duration; const errorsCount = results.filter((r) => Boolean(_optionalChain([r, 'optionalAccess', _29 => _29[0]]))).length; const hasAgents = entryPaths.filter((p) => p.endsWith("server.ts")).length > 0; if (hasAgents) { span.log.info({ message: `Initial compilation in ${_chalk2.default.bold(`${_chunkVLUR4YNDjs.ns.toMs(duration)}ms`)}. ${errorsCount > 0 ? _chalk2.default.red(`(${_chalk2.default.bold(errorsCount)} error${errorsCount > 1 ? "s" : ""})`) : _chalk2.default.dim("(no errors)")}` }); } else span.log.info({ message: "No agent server to compile yet. Create a first `agent/server.ts` file in your project." }); }); if (this.options.watch) { this.watchEntryPaths(); span.log.info({ message: "Watching for changes..." }); const handleShutdown = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async (signal) => { console.log(""); this.telemetry.log.info({ message: `Received ${signal}, shutting down gracefully...` }); await this.stop(); }, "handleShutdown"); process.once("SIGINT", () => handleShutdown("SIGINT")); process.once("SIGTERM", () => handleShutdown("SIGTERM")); } else await this.stop(); return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }); } #stopStarted = false; async stop() { return await this.telemetry.trace("stop()", async (span) => { if (this.#stopStarted) return; this.#stopStarted = true; span.log.info({ message: "Stopping compiler." }); _optionalChain([this, 'access', _30 => _30.#serverBundleContext, 'optionalAccess', _31 => _31.dispose, 'call', _32 => _32()]); this.#serverBundleContext = null; await _optionalChain([this, 'access', _33 => _33.watcher, 'optionalAccess', _34 => _34.close, 'call', _35 => _35()]); this.watcher = null; await this.telemetry.flushConsumers(); }); } async ensureBuildDirectory() { await Promise.all([ _promises.mkdir.call(void 0, _path3.default.join(this.options.outputDirectory, "server", "raw"), { recursive: true }), _promises.mkdir.call(void 0, _path3.default.join(this.options.outputDirectory, "server", "dist"), { recursive: true }), _promises.mkdir.call(void 0, _path3.default.join(this.options.outputDirectory, "server", "signal"), { recursive: true }), _promises.mkdir.call(void 0, _path3.default.join(this.options.outputDirectory, "client"), { recursive: true }) ]); } async linkBuildDirectory() { const generatedClientPath = _path2.join.call(void 0, this.options.outputDirectory, "client", "index.ts"); const generatedServerPath = _path2.join.call(void 0, this.options.outputDirectory, "server", "dist", "index.js"); const [errDistDir, distDir] = await this.findDistDirectory(); if (errDistDir) return _chunk22H3U7VVjs.failure.call(void 0, errDistDir); const distFiles = _globby.globbySync.call(void 0, "**/*", { cwd: distDir, onlyFiles: true, absolute: false }); const CODE_FILE_EXTENSIONS = [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts", ".jsx", ".tsx"]; const codeFiles = distFiles.filter((file) => { const ext = _path3.default.extname(file).toLowerCase(); return CODE_FILE_EXTENSIONS.includes(ext); }); await Promise.all( codeFiles.map(async (file) => { const filePath = _path2.join.call(void 0, distDir, file); const content = await _promises.readFile.call(void 0, filePath, "utf-8"); const clientPath = _path2.relative.call(void 0, _path2.dirname.call(void 0, filePath), generatedClientPath); const serverPath = _path2.relative.call(void 0, _path2.dirname.call(void 0, filePath), generatedServerPath); const updatedContent = content.replaceAll(/"LIFE()_CLIENT_BUILD_PATH"/g, `"${clientPath}"`).replaceAll(/String\("LIFE()_CLIENT_BUILD_MODULE"\)/g, `import("${clientPath}")`).replaceAll(/"LIFE()_CLIENT_BUILD_MODULE"/g, `import("${clientPath}")`).replaceAll(/"LIFE()_SERVER_BUILD_PATH"/g, `"${serverPath}"`).replaceAll(/"LIFE()_BUILD_MODE"/g, '"production"').replaceAll(/'LIFE()_CLIENT_BUILD_PATH'/g, `'${clientPath}'`).replaceAll(/String\('LIFE()_CLIENT_BUILD_MODULE'\)/g, `import("${clientPath}")`).replaceAll(/'LIFE()_CLIENT_BUILD_MODULE'/g, `import("${clientPath}")`).replaceAll(/'LIFE()_SERVER_BUILD_PATH'/g, `'${serverPath}'`).replaceAll(/'LIFE()_BUILD_MODE'/g, "'production'"); if (updatedContent !== content) await _promises.writeFile.call(void 0, filePath, updatedContent, "utf-8"); }) ); } async getPathDisplayName(_path, type) { const relativePath = _path3.default.relative(this.options.projectDirectory, _path); if (["config", "dependency", "unknown"].includes(type)) return relativePath; const clientContent = await _promises.readFile.call(void 0, _path, "utf-8"); const ast = await _napi.parseAsync.call(void 0, _napi.Lang.TypeScript, clientContent); const root = ast.root(); const defineCall = root.find({ rule: { kind: "call_expression", any: [ { pattern: `defineAgent${type === "client" ? "Client" : ""}<$$$>($ARG)` }, { pattern: `defineAgent${type === "client" ? "Client" : ""}($ARG)` } ] } }); if (!defineCall) return relativePath; let name = _nullishCoalesce(_optionalChain([defineCall, 'optionalAccess', _36 => _36.getMatch, 'call', _37 => _37("ARG"), 'optionalAccess', _38 => _38.text, 'call', _39 => _39()]), () => ( null)); if (name) name = JSON.parse(name); else return relativePath; return name; } /** * Main compiler entry point. Used to process a file. * @param params - The parameters for the file event. * @returns The result of the file event. */ async processFileEvent({ type, action, absPath, noCache = false, noTimingLogs = false }) { const result = await this.telemetry.trace("processFileEvent()", async (span) => { span.setAttributes({ action, relPath: absPath }); const emitTimingLogs = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, async (recompiled) => { if (noTimingLogs) return; if (!["server", "client"].includes(type)) return; span.end(); const name = await this.getPathDisplayName(absPath, type); this.telemetry.log.info({ message: `Agent ${type} '${_chalk2.default.bold.italic(name)}' ${recompiled ? "re-compiled" : "compiled"} in ${_chalk2.default.bold(`${_chunkVLUR4YNDjs.ns.toMs(span.getData().duration)}ms`)}.`, attributes: { type, name } }); }, "emitTimingLogs"); absPath = this.ensureAbsolute(absPath); if (type === "unknown") return _chunk22H3U7VVjs.success.call(void 0, ); if (action === "added") { this.hashes.set(absPath, await this.hashFile(absPath)); span.log.debug({ message: `Added '${type}' path: ${absPath}`, attributes: { path: absPath } }); if (type === "config") return await this.onAddedConfig(absPath); else if (type === "server") { const res = await this.onAddedServer(absPath); if (!_optionalChain([res, 'optionalAccess', _40 => _40[0]])) await emitTimingLogs(false); return res; } else if (type === "client") { const res = await this.onAddedClient(absPath); if (!_optionalChain([res, 'optionalAccess', _41 => _41[0]])) await emitTimingLogs(false); return res; } else if (type === "dependency") return _chunk22H3U7VVjs.failure.call(void 0, { code: "Conflict", message: "'added' action is not supported for dependency paths. Shouldn't happen." }); } else if (action === "removed") { this.hashes.delete(absPath); span.log.debug({ message: `Removed '${type}' path: ${absPath}`, attributes: { path: absPath } }); if (type === "config") return await this.onRemovedConfig(absPath); else if (type === "server") return await this.onRemovedServer(absPath); else if (type === "client") return await this.onRemovedClient(absPath); else if (type === "dependency") return await this.onRemovedDependency(absPath); } else if (action === "changed") { const newHash = await this.hashFile(absPath); if (newHash === this.hashes.get(absPath) && !noCache) return _chunk22H3U7VVjs.success.call(void 0, ); this.hashes.set(absPath, newHash); span.log.debug({ message: `Changed '${type}' path: ${absPath}`, attributes: { path: absPath } }); if (type !== "dependency") await this.refreshEntryPathDependencies(absPath); if (type === "config") return await this.onChangedConfig(absPath); else if (type === "server") { const res = await this.onChangedServer(absPath); if (!_optionalChain([res, 'optionalAccess', _42 => _42[0]])) await emitTimingLogs(true); return res; } else if (type === "client") { const res = await this.onChangedClient(absPath); if (!_optionalChain([res, 'optionalAccess', _43 => _43[0]])) await emitTimingLogs(true); return res; } else if (type === "dependency") return await this.onChangedDependency(absPath); } throw new Error("Invalid action. Shouldn't happen."); }); const [error] = result; if (error) { const displayName = await this.getPathDisplayName(absPath, type); let baseMessage = "Failed to compile "; if (["client", "server"].includes(type)) baseMessage += `agent ${type} '${_chalk2.default.bold.italic(displayName)}'.`; else baseMessage += `'${_chalk2.default.bold.italic(displayName)}' ${type} file.`; const relativePath = _path3.default.relative(this.options.projectDirectory, absPath); if (this.options.stopOnError) { this.telemetry.log.error({ message: `${baseMessage} Path: ${relativePath}`, error }); await this.stop(); } else this.telemetry.log.warn({ message: `${baseMessage} It has been ignored. Path: ${relativePath}`, error }); } return result; } // Configs Events Handlers async onAddedConfig(configPath) { return await this.telemetry.trace( "onAddedConfig()", async () => { try { this.paths.configs.add(configPath); return await this.onChangedConfig(configPath); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }, { attributes: { configPath } } ); } async onRemovedConfig(configPath) { return await this.telemetry.trace( "onRemovedConfig()", async () => { try { this.paths.configs.delete(configPath); return await this.onChangedConfig(configPath); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }, { attributes: { configPath } } ); } async onChangedConfig(configPath) { return await this.telemetry.trace( "onChangedConfig()", async () => { try { const configContent = await _promises.readFile.call(void 0, configPath, "utf-8"); const ast = await _napi.parseAsync.call(void 0, _napi.Lang.TypeScript, configContent); const root = ast.root(); const defineConfigCall = root.find({ rule: { kind: "call_expression", pattern: "defineConfig($ARG)" } }); if (!defineConfigCall) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: "Config file does not contain a defineConfig() call.", attributes: { path: configPath } }); } const exportDefaultStatement = root.find({ rule: { kind: "export_statement", pattern: "export default", has: { regex: "defineConfig(.*)" } } }); if (!exportDefaultStatement) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Config file has defineConfig() but doesn't export it as default. Use \`export default defineConfig(...)\` instead.`, attributes: { path: configPath } }); } const affected = Array.from(this.paths.servers).filter( (p) => this.isEntryPathTouchedByConfig(p, configPath) ); await Promise.all( affected.map(async (serverPath) => { const absPath = this.ensureAbsolute(serverPath); return await this.processFileEvent({ action: "changed", absPath, type: "server", noCache: true }); }) ); return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }, { attributes: { configPath } } ); } // Agent Servers Events Handlers async onAddedServer(serverPath) { return await this.telemetry.trace( "onAddedServer()", async () => { try { this.paths.servers.add(serverPath); return await this.onChangedServer(serverPath); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }, { attributes: { serverPath } } ); } async onRemovedServer(serverPath) { return await this.telemetry.trace( "onRemovedServer()", async () => { try { this.paths.servers.delete(serverPath); const buildPath = this.paths.serverBuilds.get(serverPath); if (buildPath) { this.paths.serverBuilds.delete(serverPath); await _promises.rm.call(void 0, buildPath); } const res = await this.generateServerBundle(); if (!_optionalChain([res, 'optionalAccess', _44 => _44[0]])) return res; const name = this.getPathDisplayName(serverPath, "server"); const signalPath = _path3.default.join( this.options.outputDirectory, "server", "signal", `${name}.txt` ); if (await this.fileExists(signalPath)) { await _promises.writeFile.call(void 0, signalPath, "removed", "utf-8"); } return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }, { attributes: { serverPath } } ); } async onChangedServer(serverPath) { return await this.telemetry.trace( "onChangedServer()", async (span) => { try { const serverContent = await _promises.readFile.call(void 0, serverPath, "utf-8"); const ast = await _napi.parseAsync.call(void 0, _napi.Lang.TypeScript, serverContent); const root = ast.root(); const defineAgentCall = root.find({ rule: { kind: "call_expression", pattern: "defineAgent($ARG)" } }); if (!defineAgentCall) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Agent server '${_chalk2.default.bold.italic(_path3.default.relative(this.options.projectDirectory, serverPath))}' doesn't contain a ${_chalk2.default.bold.italic("defineAgent(...)")} call.`, attributes: { serverPath } }); } const exportDefaultStatement = root.find({ rule: { kind: "export_statement", pattern: "export default", has: { regex: "defineAgent(.*)" } } }); if (!exportDefaultStatement) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Agent server '${_chalk2.default.bold.italic(_path3.default.relative(this.options.projectDirectory, serverPath))}' doesn't export ${_chalk2.default.bold.italic("defineAgent(...)")} call as default. Use ${_chalk2.default.bold.italic("export default defineAgent(...)")}.`, attributes: { serverPath } }); } let name = _nullishCoalesce(_optionalChain([defineAgentCall, 'optionalAccess', _45 => _45.getMatch, 'call', _46 => _46("ARG"), 'optionalAccess', _47 => _47.text, 'call', _48 => _48()]), () => ( null)); if (name) name = JSON.parse(name); if (!name) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Agent server '${_chalk2.default.bold.italic(name)}' has ${_chalk2.default.bold.italic("defineAgent()")} but doesn't provide a name. Use ${_chalk2.default.bold.italic("defineAgent(<name>)")}.`, attributes: { serverPath } }); } const configPaths = []; for (const configPath of this.paths.configs) { if (this.isEntryPathTouchedByConfig(serverPath, configPath)) configPaths.push(configPath); } configPaths.sort((a, b) => b.length - a.length); const treeFiles = /* @__PURE__ */ new Set([serverPath, ...configPaths]); for (const file of _chunkBFC2WP6Qjs.deepClone.call(void 0, treeFiles)) { const deps = this.paths.dependencies.get(file); if (deps) for (const dep of deps) treeFiles.add(dep); } const treeHashes = Array.from(treeFiles).map((file) => this.hashes.get(file)); const filteredTreeHashes = treeHashes.filter((hash) => hash !== void 0); if (treeHashes.length !== filteredTreeHashes.length) { span.log.warn({ message: "Some tree files have no hash. Shouldn't happen.", attributes: { treeFiles } }); } const sha = _crypto.createHash.call(void 0, "md5").update(treeHashes.join(":")).digest("hex"); const buildPath = _path3.default.join(this.options.outputDirectory, "server", "raw", `${name}.ts`); const relServerPath = _path3.default.relative(_path3.default.dirname(buildPath), serverPath); const relConfigPaths = configPaths.map( (configPath) => _path3.default.relative(_path3.default.dirname(buildPath), configPath) ); const content = ` ${relConfigPaths.map((configPath, i) => `import config${i} from "${configPath}";`).join("\n")} import agent from "${relServerPath}"; export default { definition: agent.def, globalConfigs: [${configPaths.map((_, i) => `config${i}`).join(", ")}], sha: "${sha}" } as const; `.trim(); await _promises.writeFile.call(void 0, buildPath, content, "utf-8"); this.paths.serverBuilds.set(serverPath, buildPath); const [errBundle] = await this.generateServerBundle(); if (errBundle) return _chunk22H3U7VVjs.failure.call(void 0, errBundle); const signalPath = _path3.default.join( this.options.outputDirectory, "server", "signal", `${name}.txt` ); await _promises.writeFile.call(void 0, signalPath, sha, "utf-8"); return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }, { attributes: { serverPath } } ); } // Agent Clients Events Handlers async onAddedClient(clientPath) { return await this.telemetry.trace( "onAddedClient()", async () => { try { this.paths.clients.add(clientPath); return await this.onChangedClient(clientPath); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }, { attributes: { clientPath } } ); } async onRemovedClient(clientPath) { return await this.telemetry.trace( "onRemovedClient()", async () => { try { this.paths.clients.delete(clientPath); const buildPath = this.paths.clientBuilds.get(clientPath); if (buildPath) { this.paths.clientBuilds.delete(clientPath); await _promises.rm.call(void 0, buildPath); } return await this.onChangedClient(clientPath); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }, { attributes: { clientPath } } ); } async onChangedClient(clientPath) { return await this.telemetry.trace( "onChangedClient()", async () => { try { const clientContent = await _promises.readFile.call(void 0, clientPath, "utf-8"); const ast = await _napi.parseAsync.call(void 0, _napi.Lang.TypeScript, clientContent); const root = ast.root(); const defineAgentClientCall = root.find({ rule: { kind: "call_expression", any: [ { pattern: "defineAgentClient<$$$>($ARG)" }, { pattern: "defineAgentClient($ARG)" } ] } }); if (!defineAgentClientCall) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Agent client '${_chalk2.default.bold.italic(_path3.default.relative(this.options.projectDirectory, clientPath))}' doesn't contain a ${_chalk2.default.bold.italic("defineAgentClient(...)")} call. It has been ignored.`, attributes: { clientPath } }); } const exportDefaultStatement = root.find({ rule: { kind: "export_statement", pattern: "export default", has: { regex: "defineAgentClient(<.*>)?(.*)" } } }); if (!exportDefaultStatement) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Agent client '${_chalk2.default.bold.italic(_path3.default.relative(this.options.projectDirectory, clientPath))}' doesn't export ${_chalk2.default.bold.italic("defineAgentClient(...)")} call as default. It has been ignored. Use ${_chalk2.default.bold.italic("export default defineAgentClient(...)")}.`, attributes: { clientPath } }); } let name = _nullishCoalesce(_optionalChain([defineAgentClientCall, 'optionalAccess', _49 => _49.getMatch, 'call', _50 => _50("ARG"), 'optionalAccess', _51 => _51.text, 'call', _52 => _52()]), () => ( null)); if (name) name = JSON.parse(name); if (!name) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Validation", message: `Agent client '${_chalk2.default.bold.italic(_path3.default.relative(this.options.projectDirectory, clientPath))}' has ${_chalk2.default.bold.italic("defineAgentClient()")} but doesn't provide a name. It has been ignored. Use ${_chalk2.default.bold.italic("defineAgentClient(<name>)")}.`, attributes: { clientPath } }); } const pluginNames = await this.extractClientPluginNames(clientPath); const plugins = pluginNames.map( (pluginName) => ` "${pluginName}": { def: p["${pluginName}"], $types: { atoms: (mock as typeof p["${pluginName}"]["atoms"])<PC["${pluginName}"]>(null as any), class: (mock as typeof p["${pluginName}"]["class"])<PC["${pluginName}"]>(null as any), clientConfig: {} as PC["${pluginName}"]["client"], serverConfig: {} as PC["${pluginName}"]["server"], } }` ).join(",\n"); const buildPath = _path3.default.join(this.options.outputDirectory, "client", `${name}.ts`); const relClientPath = _path3.default.relative(_path3.default.dirname(buildPath), clientPath); const content = `import agentClient from "${relClientPath.replace(".ts", "")}"; type SC = typeof agentClient["def"]["$serverDef"]["pluginConfigs"]; type CC = typeof agentClient["def"]["pluginConfigs"]; type PC = { ${pluginNames.map((pluginName) => ` "${pluginName}": { client: CC["${pluginName}"], server: SC extends { "${pluginName}": unknown } ? SC["${pluginName}"] : never }`).join(",\n")} } const p = { ${pluginNames.map((pluginName) => ` "${pluginName}": agentClient.def.plugins.find(p => p.name === "${pluginName}")!`).join(",\n")} } as const; const mock = (() => void 0) as any; export default { definition: agentClient.def, plugins: { ${plugins} } } as const; `.trim(); await _promises.writeFile.call(void 0, buildPath, content, "utf-8"); this.paths.clientBuilds.set(clientPath, buildPath); const [errBundle] = await this.generateClientBundle(); if (errBundle) return _chunk22H3U7VVjs.failure.call(void 0, errBundle); return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }, { attributes: { clientPath } } ); } // Dependency Paths Events Handlers async onRemovedDependency(dependencyPath) { return await this.telemetry.trace( "onRemovedDependency()", async () => { try { return await this.onChangedDependency(dependencyPath); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }, { attributes: { dependencyPath } } ); } async onChangedDependency(dependencyPath) { return await this.telemetry.trace( "onChangedDependency()", async () => { try { const affected = /* @__PURE__ */ new Set(); for (const [entryPath, dependencies] of this.paths.dependencies) { if (dependencies.has(dependencyPath)) affected.add(entryPath); } await Promise.all( Array.from(affected).map((p) => { const absPath = this.ensureAbsolute(p); const type = this.getPathType(absPath); return this.processFileEvent({ action: "changed", absPath, type, noCache: true }); }) ); return _chunk22H3U7VVjs.success.call(void 0, ); } catch (error) { return _chunk22H3U7VVjs.failure.call(void 0, { code: "Unknown", cause: error }); } }, { attributes: { dependencyPath } } ); } watchEntryPaths() { return this.telemetry.trace("watchEntryPaths()", () => { function isMacOS26_1_x() { if (process.platform !== "darwin") return false; const release = _os2.default.release(); const majorVersion = _nullishCoalesce(Number.parseInt(_nullishCoalesce(_optionalChain([release, 'optionalAccess', _53 => _53.split, 'call', _54 => _54("."), 'access', _55 => _55[0]]), () => ( "0")), 10), () => ( 0)); const minorVersion = _nullishCoalesce(Number.parseInt(_nullishCoalesce(_optionalChain([release, 'optionalAccess', _56 => _56.split, 'call', _57 => _57("."), 'access', _58 => _58[1]]), () => ( "0")), 10), () => ( 0)); return majorVersion >= 25 && minorVersion >= 1; } _chunk6PEHRAEPjs.__name.call(void 0, isMacOS26_1_x, "isMacOS26_1_x"); const enableFSEventsWorkaround = isMacOS26_1_x(); this.watcher = _chokidar2.default.watch(".", { cwd: this.options.projectDirectory, ignoreInitial: true, ignored: EXCLUDED_DEFAULTS, awaitWriteFinish: { stabilityThreshold: 20, pollInterval: 5 }, // Apply workaround on affected macOS versions ...enableFSEventsWorkaround && { usePolling: true, interval: 100 } }); const onWatcherEventFn = /* @__PURE__ */ _chunk6PEHRAEPjs.__name.call(void 0, (action) => (p) => { const absPath = this.ensureAbsolute(p); const type = this.getPathType(absPath); this.processFileEvent({ action, absPath, type }); }, "onWatcherEventFn"); this.watcher.on("add", onWatcherEventFn("added")); this.watcher.on("unlink", onWatcherEventFn("removed")); this.watcher.on("change", onWatcherEventFn("changed")); }); } async refreshEntryPathDependencies(entryPath) { const absPath = this.ensureAbsolute(entryPath); const exclude = []; if (this.getPathType(absPath) === "client") { exclude.push(absPath.replace("/client.ts", "/server.ts")); } const [error, dependencies] = await getDependenciesMap(absPath, exclude, true); if (error) { this.telemetry.log.error({ message: "Obtaining entry path dependencies failed.", error, attributes: { entryPath } }); return; } this.paths.dependencies.set(entryPath, new Set(dependenc