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