mlld
Version:
mlld: a modular prompt scripting language
721 lines (718 loc) • 20.6 kB
JavaScript
import { ResolverError, ResolverErrorCode } from './chunk-YMCO2JI3.mjs';
import { __name, __publicField } from './chunk-OMKLS24H.mjs';
import * as os from 'os';
import * as path from 'path';
// core/resolvers/builtin/NowResolver.ts
var _NowResolver = class _NowResolver {
constructor() {
__publicField(this, "name", "now");
__publicField(this, "description", "Provides current timestamp");
__publicField(this, "type", "input");
__publicField(this, "capabilities", {
io: {
read: true,
write: false,
list: false
},
contexts: {
import: true,
path: true,
output: false
},
supportedContentTypes: [
"text",
"data"
],
defaultContentType: "text",
priority: 1,
cache: {
strategy: "none"
}
// now is always computed fresh
});
}
canResolve(ref) {
const cleanRef = ref.replace(/^@/, "");
return cleanRef === "now";
}
async resolve(ref, config) {
const currentTime = this.getMockedTime() || /* @__PURE__ */ new Date();
if (!config?.context || config.context === "variable" || config.context === "path") {
return {
content: currentTime.toISOString(),
contentType: "text",
metadata: {
source: "now",
timestamp: currentTime
}
};
}
if (config.context === "import") {
const exports = {};
const requestedImports = config.requestedImports || [];
if (requestedImports.length === 0) {
exports.iso = currentTime.toISOString();
exports.unix = Math.floor(currentTime.getTime() / 1e3).toString();
exports.date = currentTime.toISOString().split("T")[0];
exports.time = currentTime.toTimeString().split(" ")[0];
} else {
for (const importName of requestedImports) {
if (importName === "iso") {
exports[importName] = currentTime.toISOString();
} else if (importName === "unix") {
exports[importName] = Math.floor(currentTime.getTime() / 1e3).toString();
} else if (importName === "date") {
exports[importName] = currentTime.toISOString().split("T")[0];
} else if (importName === "time") {
exports[importName] = currentTime.toTimeString().split(" ")[0];
} else {
exports[importName] = currentTime.toISOString();
}
}
}
return {
content: JSON.stringify(exports),
contentType: "data",
metadata: {
source: "now",
timestamp: currentTime
}
};
}
throw new ResolverError("NOW resolver only supports variable and import contexts", ResolverErrorCode.UNSUPPORTED_CONTEXT, {
resolverName: this.name,
context: config?.context,
operation: "resolve"
});
}
/**
* Get mocked time for testing
*/
getMockedTime() {
if (process.env.MLLD_MOCK_TIME) {
if (/^\d+$/.test(process.env.MLLD_MOCK_TIME)) {
return new Date(parseInt(process.env.MLLD_MOCK_TIME) * 1e3);
}
return new Date(process.env.MLLD_MOCK_TIME);
}
return null;
}
/**
* Get default value for when NOW is used as a variable
* This handles the mock time logic for tests
*/
getDefaultValue() {
const currentTime = this.getMockedTime() || /* @__PURE__ */ new Date();
return currentTime.toISOString();
}
};
__name(_NowResolver, "NowResolver");
var NowResolver = _NowResolver;
var _DebugResolver = class _DebugResolver {
constructor() {
__publicField(this, "name", "debug");
__publicField(this, "description", "Provides environment and debug information");
__publicField(this, "type", "input");
__publicField(this, "capabilities", {
io: {
read: true,
write: false,
list: false
},
contexts: {
import: true,
path: false,
output: false
},
supportedContentTypes: [
"data",
"text"
],
defaultContentType: "data",
priority: 1,
cache: {
strategy: "none"
}
// debug info should be fresh
});
}
canResolve(ref) {
const cleanRef = ref.replace(/^@/, "");
return cleanRef === "debug" || cleanRef.startsWith("debug/");
}
async resolve(ref, config) {
if (!config?.context || config.context === "variable") {
const info = await this.collectDebugInfo();
return {
content: JSON.stringify(info),
contentType: "data",
metadata: {
source: "debug",
timestamp: /* @__PURE__ */ new Date()
}
};
}
if (config.context === "import") {
const info = await this.collectDebugInfo();
const exports = {};
const imports = config.requestedImports || [
"json",
"reduced",
"markdown"
];
for (const importName of imports) {
switch (importName) {
case "environment":
exports.environment = info.environment;
break;
case "system":
exports.system = info.system;
break;
case "process":
exports.process = info.process;
break;
case "mlld":
exports.mlld = info.mlld;
break;
case "full":
exports.full = info;
break;
case "json":
exports.json = JSON.stringify(info, null, 2);
break;
case "reduced":
exports.reduced = JSON.stringify({
environment: info.environment,
version: info.mlld.version
});
break;
case "summary":
exports.summary = this.formatSummary(info);
break;
case "markdown":
exports.markdown = this.formatMarkdown(info);
break;
default:
const value = this.getNestedValue(info, importName);
if (value !== void 0) {
exports[importName] = value;
}
}
}
return {
content: JSON.stringify(exports),
contentType: "data",
metadata: {
source: "debug",
timestamp: /* @__PURE__ */ new Date()
}
};
}
throw new ResolverError("DEBUG resolver only supports variable and import contexts", ResolverErrorCode.UNSUPPORTED_CONTEXT, {
resolverName: this.name,
context: config?.context,
operation: "resolve"
});
}
/**
* Generate debug information in requested format
*/
async generateDebugInfo(format) {
const info = await this.collectDebugInfo();
switch (format.toLowerCase()) {
case "summary":
return this.formatSummary(info);
case "markdown":
return this.formatMarkdown(info);
case "json":
return JSON.stringify(info, null, 2);
case "full":
default:
return this.formatFull(info);
}
}
/**
* Collect all debug information
*/
async collectDebugInfo() {
const cwd = process.cwd?.() || "/";
const projectPath = await this.findProjectRoot(cwd);
const time = this.getMockedTime() || /* @__PURE__ */ new Date();
const version = await this.getMlldVersion();
return {
timestamp: time.toISOString(),
version,
mlld: {
version,
configFile: await this.findConfigFile(projectPath || cwd)
},
project: {
basePath: projectPath || cwd,
configFile: await this.findConfigFile(projectPath || cwd)
},
environment: {
cwd,
projectPath,
nodeVersion: process.version || "unknown",
platform: process.platform || "unknown",
arch: process.arch || "unknown",
user: os.userInfo().username,
hostname: os.hostname()
},
system: {
cpus: os.cpus().length,
memory: {
total: os.totalmem(),
free: os.freemem(),
used: os.totalmem() - os.freemem()
},
uptime: os.uptime(),
loadAvg: os.loadavg()
},
process: {
pid: process.pid || 0,
ppid: process.ppid || 0,
argv: process.argv || [],
execPath: process.execPath || "",
memoryUsage: process.memoryUsage?.() || {}
},
env: this.getFilteredEnv()
};
}
/**
* Format as summary (key info only)
*/
formatSummary(info) {
return [
`MLLD Debug Summary`,
`==================`,
`Time: ${info.timestamp}`,
`Version: ${info.mlld.version}`,
`Platform: ${info.environment.platform} (${info.environment.arch})`,
`Node: ${info.environment.nodeVersion}`,
`CWD: ${info.environment.cwd}`,
`Project: ${info.environment.projectPath || "Not found"}`,
`Memory: ${this.formatBytes(info.system.memory.used)} / ${this.formatBytes(info.system.memory.total)}`
].join("\n");
}
/**
* Format as markdown
*/
formatMarkdown(info) {
return [
`# MLLD Debug Information`,
``,
`## Environment`,
`- **Time**: ${info.timestamp}`,
`- **MLLD Version**: ${info.mlld.version}`,
`- **Platform**: ${info.environment.platform} (${info.environment.arch})`,
`- **Node Version**: ${info.environment.nodeVersion}`,
`- **Current Directory**: \`${info.environment.cwd}\``,
`- **Project Root**: \`${info.environment.projectPath || "Not found"}\``,
``,
`## System`,
`- **CPUs**: ${info.system.cpus}`,
`- **Memory**: ${this.formatBytes(info.system.memory.used)} / ${this.formatBytes(info.system.memory.total)}`,
`- **System Uptime**: ${this.formatDuration(info.system.uptime)}`,
``,
`## Process`,
`- **PID**: ${info.process.pid}`,
`- **Memory Usage**:`,
` - Heap: ${this.formatBytes(info.process.memoryUsage.heapUsed)} / ${this.formatBytes(info.process.memoryUsage.heapTotal)}`,
` - RSS: ${this.formatBytes(info.process.memoryUsage.rss)}`,
` - External: ${this.formatBytes(info.process.memoryUsage.external)}`
].join("\n");
}
/**
* Format as full text output
*/
formatFull(info) {
const sections = [];
sections.push([
`MLLD Debug Information`,
`======================`,
`Generated: ${info.timestamp}`,
``
].join("\n"));
sections.push([
`MLLD:`,
` Version: ${info.mlld.version}`,
` Config: ${info.mlld.configFile || "Not found"}`,
``
].join("\n"));
sections.push([
`Environment:`,
` Current Directory: ${info.environment.cwd}`,
` Project Root: ${info.environment.projectPath || "Not found"}`,
` Node Version: ${info.environment.nodeVersion}`,
` Platform: ${info.environment.platform} (${info.environment.arch})`,
` User: ${info.environment.user}`,
` Hostname: ${info.environment.hostname}`,
``
].join("\n"));
sections.push([
`System:`,
` CPUs: ${info.system.cpus}`,
` Memory:`,
` Total: ${this.formatBytes(info.system.memory.total)}`,
` Free: ${this.formatBytes(info.system.memory.free)}`,
` Used: ${this.formatBytes(info.system.memory.used)}`,
` Uptime: ${this.formatDuration(info.system.uptime)}`,
` Load Average: ${info.system.loadAvg.map((n) => n.toFixed(2)).join(", ")}`,
``
].join("\n"));
sections.push([
`Process:`,
` PID: ${info.process.pid}`,
` Parent PID: ${info.process.ppid}`,
` Executable: ${info.process.execPath}`,
` Memory Usage:`,
` RSS: ${this.formatBytes(info.process.memoryUsage.rss)}`,
` Heap Total: ${this.formatBytes(info.process.memoryUsage.heapTotal)}`,
` Heap Used: ${this.formatBytes(info.process.memoryUsage.heapUsed)}`,
` External: ${this.formatBytes(info.process.memoryUsage.external)}`,
``
].join("\n"));
sections.push([
`Environment Variables (filtered):`,
...Object.entries(info.env).map(([key, value]) => ` ${key}=${value}`),
``
].join("\n"));
return sections.join("\n");
}
/**
* Find project root by looking for package.json
*/
async findProjectRoot(startPath) {
return startPath;
}
/**
* Find mlld config file
*/
async findConfigFile(projectPath) {
const configFiles = [
"mlld.config.json",
".mlldrc",
".mlldrc.json"
];
for (const configFile of configFiles) {
path.join(projectPath, configFile);
}
return null;
}
/**
* Get mlld version
*/
async getMlldVersion() {
try {
return "1.0.0";
} catch {
return "unknown";
}
}
/**
* Get filtered environment variables
*/
getFilteredEnv() {
const filtered = {};
const includePatterns = [
/^MLLD_/,
/^NODE_/,
/^npm_/,
/^PATH$/,
/^HOME$/,
/^USER$/,
/^SHELL$/,
/^LANG$/,
/^LC_/,
/^TERM/
];
for (const [key, value] of Object.entries(process.env)) {
if (includePatterns.some((pattern) => pattern.test(key))) {
filtered[key] = value || "";
}
}
return filtered;
}
/**
* Format bytes as human-readable
*/
formatBytes(bytes) {
const units = [
"B",
"KB",
"MB",
"GB",
"TB"
];
let size = bytes;
let unitIndex = 0;
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024;
unitIndex++;
}
return `${size.toFixed(2)} ${units[unitIndex]}`;
}
/**
* Format duration in seconds as human-readable
*/
formatDuration(seconds) {
const days = Math.floor(seconds / 86400);
const hours = Math.floor(seconds % 86400 / 3600);
const minutes = Math.floor(seconds % 3600 / 60);
const secs = Math.floor(seconds % 60);
const parts = [];
if (days > 0) parts.push(`${days}d`);
if (hours > 0) parts.push(`${hours}h`);
if (minutes > 0) parts.push(`${minutes}m`);
if (secs > 0 || parts.length === 0) parts.push(`${secs}s`);
return parts.join(" ");
}
/**
* Get mocked time for testing
*/
getMockedTime() {
if (process.env.MLLD_MOCK_TIME) {
if (/^\d+$/.test(process.env.MLLD_MOCK_TIME)) {
return new Date(parseInt(process.env.MLLD_MOCK_TIME) * 1e3);
}
return new Date(process.env.MLLD_MOCK_TIME);
}
return null;
}
/**
* Get nested value from object using dot notation
*/
getNestedValue(obj, path2) {
const parts = path2.split(".");
let current = obj;
for (const part of parts) {
if (current && typeof current === "object" && part in current) {
current = current[part];
} else {
return void 0;
}
}
return current;
}
};
__name(_DebugResolver, "DebugResolver");
var DebugResolver = _DebugResolver;
// core/resolvers/builtin/InputResolver.ts
var _InputResolver = class _InputResolver {
constructor(stdinContent) {
__publicField(this, "name", "input");
__publicField(this, "description", "Provides merged stdin and environment variable data");
__publicField(this, "type", "input");
__publicField(this, "capabilities", {
io: {
read: true,
write: false,
list: false
},
contexts: {
import: true,
path: false,
output: false
},
supportedContentTypes: [
"data",
"text"
],
defaultContentType: "data",
priority: 1,
cache: {
strategy: "memory",
ttl: {
duration: -1
}
// Never expire during session
}
});
__publicField(this, "inputData", null);
__publicField(this, "stdinContent");
this.stdinContent = stdinContent;
}
canResolve(ref) {
const cleanRef = ref.replace(/^@/, "");
return cleanRef === "input" || cleanRef.startsWith("input/");
}
async resolve(ref, config) {
if (!this.inputData) {
await this.initializeInputData();
}
if (!config?.context || config.context === "variable") {
return {
content: JSON.stringify(this.inputData, null, 2),
contentType: "data",
metadata: {
source: "input",
timestamp: /* @__PURE__ */ new Date()
}
};
}
if (config.context === "import") {
const exports = {};
const imports = config.requestedImports || [];
if (imports.length === 0) {
const exportData = {
...this.inputData
};
delete exportData._meta;
return {
content: JSON.stringify(exportData),
contentType: "data",
metadata: {
source: "input",
timestamp: /* @__PURE__ */ new Date()
}
};
}
for (const fieldName of imports) {
const value = this.getFieldValue(fieldName);
if (value !== null) {
exports[fieldName] = value;
}
}
return {
content: JSON.stringify(exports),
contentType: "data",
metadata: {
source: "input",
timestamp: /* @__PURE__ */ new Date()
}
};
}
throw new ResolverError("input resolver only supports variable and import contexts", ResolverErrorCode.UNSUPPORTED_CONTEXT, {
resolverName: this.name,
context: config?.context,
operation: "resolve"
});
}
/**
* Initialize input data from stdin and environment
*/
async initializeInputData() {
const stdin = await this.readStdin();
const envVars = this.getEnvironmentVariables();
this.inputData = {
...envVars,
...stdin
};
if (stdin.config || stdin.data) {
this.inputData.config = stdin.config;
this.inputData.data = stdin.data;
}
this.inputData._meta = {
source: "INPUT",
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
hasStdin: Object.keys(stdin).length > 0,
envVarCount: Object.keys(envVars).length
};
}
/**
* Read and parse stdin content
*/
async readStdin() {
try {
const content = this.stdinContent || "";
if (!content) {
return {};
}
try {
const parsed = JSON.parse(content);
return typeof parsed === "object" && parsed !== null ? parsed : {
value: parsed
};
} catch {
return {
stdin: content.trim()
};
}
} catch (error) {
return {};
}
}
/**
* Get filtered environment variables
*/
getEnvironmentVariables() {
const filtered = {};
for (const [key, value] of Object.entries(process.env)) {
if (key.startsWith("MLLD_") && value !== void 0) {
filtered[key] = value;
}
}
const includeVars = [
"NODE_ENV",
"DEBUG",
"CI",
"HOME",
"USER",
"PATH"
];
for (const varName of includeVars) {
if (process.env[varName] !== void 0) {
filtered[varName] = process.env[varName];
}
}
return filtered;
}
/**
* Get field value from input data
*/
getFieldValue(field) {
if (!this.inputData) {
return null;
}
switch (field.toLowerCase()) {
case "content":
return this.inputData.stdin || "";
case "json":
return this.inputData;
case "text":
return this.inputData.stdin || "";
case "env":
const env = {};
for (const [key, value] of Object.entries(this.inputData)) {
if (typeof value === "string" && key !== "stdin" && key !== "_meta") {
env[key] = value;
}
}
return env;
case "stdin":
const stdinData = {
...this.inputData
};
delete stdinData._meta;
for (const key of Object.keys(stdinData)) {
if (typeof stdinData[key] === "string" && key !== "stdin") {
delete stdinData[key];
}
}
return stdinData;
}
const parts = field.split(".");
let current = this.inputData;
for (const part of parts) {
if (current && typeof current === "object" && part in current) {
current = current[part];
} else {
return null;
}
}
return current;
}
/**
* Update stdin content (for testing or dynamic updates)
*/
setStdinContent(content) {
this.stdinContent = content;
this.inputData = null;
}
};
__name(_InputResolver, "InputResolver");
var InputResolver = _InputResolver;
export { DebugResolver, InputResolver, NowResolver };
//# sourceMappingURL=builtin-PUSUPKEM.mjs.map
//# sourceMappingURL=builtin-PUSUPKEM.mjs.map