@meldscience/meld
Version:
pipeable one-shot prompt scripting toolkit
108 lines • 4.11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PromptScript = void 0;
const fs_1 = require("fs");
const child_process_1 = require("child_process");
const errors_1 = require("./errors");
class PromptScript {
constructor(options) {
this.options = options;
}
/**
* Main entry point. Orchestrates reading file, extracting commands,
* executing them, and replacing placeholders.
*/
async process() {
if (!(0, fs_1.existsSync)(this.options.inputFile)) {
throw new errors_1.ToolError(`PromptScript: Input file does not exist: ${this.options.inputFile}`, 'FILE_NOT_FOUND');
}
const rawContent = (0, fs_1.readFileSync)(this.options.inputFile, 'utf-8');
const commands = await this.extractCommands(rawContent);
// If dry-run, skip actual execution
let commandResults = [];
if (!this.options.dryRun) {
for (const cmd of commands) {
const result = await this.executeCommand(cmd);
commandResults.push(result);
}
}
else {
commandResults = commands.map((c) => ({
command: c,
output: `# [DRY-RUN] Would have executed: ${c.command}`
}));
}
const replacedContent = await this.replaceCommands(rawContent, commandResults);
// Write to output file if specified
if (this.options.outputFile) {
(0, fs_1.writeFileSync)(this.options.outputFile, replacedContent);
}
return replacedContent;
}
/**
* Scans markdown content for lines containing @cmd[...]
* @param content entire markdown file text
* @returns array of Command objects
*/
async extractCommands(content) {
const cmdRegex = /@cmd\[(?<command>[^\]]+)\]/g;
const lines = content.split('\n');
const commands = [];
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
let match;
while ((match = cmdRegex.exec(line)) !== null) {
const commandStr = match.groups?.command || '';
commands.push({
raw: match[0],
command: commandStr.trim(),
lineNumber: i + 1
});
}
}
return commands;
}
/**
* Executes a single shell command synchronously.
* @param cmd object containing the command string
* @returns command result with output
*/
async executeCommand(cmd) {
try {
const output = (0, child_process_1.execSync)(cmd.command, { encoding: 'utf-8' });
return { command: cmd, output };
}
catch (error) {
// Capture error but keep going
return { command: cmd, output: '', error };
}
}
/**
* Replaces each @cmd[...] in the original content with its execution result.
* If there's an error, it inserts the error message into a fenced code block.
* @param content original markdown
* @param results command results
* @returns final processed markdown
*/
async replaceCommands(content, results) {
let finalContent = content;
for (const result of results) {
const placeholder = result.command.raw;
let replacement;
if (result.error) {
const errMsg = `Command failed: ${result.command.command}\nError: ${result.error.message}`;
replacement = `\`\`\`\n${errMsg}\n\`\`\``;
}
else {
// If the output is code-like, we can fence it automatically,
// but we'll keep it simple here:
replacement = `\`\`\`\n${result.output.trim()}\n\`\`\``;
}
// Replace all occurrences of the placeholder
finalContent = finalContent.replace(placeholder, replacement);
}
return finalContent;
}
}
exports.PromptScript = PromptScript;
//# sourceMappingURL=prompt-script.js.map