UNPKG

@lenne.tech/cli

Version:

lenne.Tech CLI: lt

296 lines (294 loc) 12.6 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const child_process_1 = require("child_process"); const path_1 = require("path"); /** * Copy text to clipboard (cross-platform) */ function copyToClipboard(text) { return __awaiter(this, void 0, void 0, function* () { try { const platform = process.platform; if (platform === 'darwin') { return new Promise((resolve) => { const proc = (0, child_process_1.spawn)('pbcopy'); proc.stdin.write(text); proc.stdin.end(); proc.on('close', () => resolve(true)); proc.on('error', () => resolve(false)); }); } else if (platform === 'linux') { try { return new Promise((resolve) => { const proc = (0, child_process_1.spawn)('xclip', ['-selection', 'clipboard']); proc.stdin.write(text); proc.stdin.end(); proc.on('close', () => resolve(true)); proc.on('error', () => resolve(false)); }); } catch (_a) { return false; } } else if (platform === 'win32') { return new Promise((resolve) => { const proc = (0, child_process_1.spawn)('clip'); proc.stdin.write(text); proc.stdin.end(); proc.on('close', () => resolve(true)); proc.on('error', () => resolve(false)); }); } return false; } catch (_b) { return false; } }); } /** * Extract prompt content (everything after frontmatter) */ function getPromptContent(promptPath, filesystem) { const content = filesystem.read(promptPath); // Remove frontmatter if present const withoutFrontmatter = content.replace(/^---\n[\s\S]*?\n---\n*/, ''); return withoutFrontmatter.trim(); } /** * Get prompt metadata from .md frontmatter */ function getPromptMetadata(promptPath, filesystem) { if (!filesystem.exists(promptPath)) { return { description: 'No description available', name: '' }; } const content = filesystem.read(promptPath); const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/); if (!frontmatterMatch) { return { description: 'No description available', name: '' }; } const frontmatter = frontmatterMatch[1]; const descMatch = frontmatter.match(/description:\s*([^\n]+)/); const nameMatch = frontmatter.match(/name:\s*([^\n]+)/); return { description: descMatch ? descMatch[1].trim() : 'No description available', name: nameMatch ? nameMatch[1].trim() : '', }; } /** * LLM Prompt Templates - Get prompts for various LLMs */ const LlmCommand = { alias: ['llm', 'prompts'], description: 'Get LLM prompt templates', hidden: false, name: 'llm', run: (toolbox) => __awaiter(void 0, void 0, void 0, function* () { const { filesystem, parameters, print: { error, highlight, info, success, warning }, prompt, } = toolbox; try { // Get the CLI installation directory const cliRoot = (0, path_1.join)(__dirname, '..', '..'); const promptsTemplateDir = (0, path_1.join)(cliRoot, 'templates', 'llm-prompts'); // Check if llm-prompts directory exists if (!filesystem.exists(promptsTemplateDir)) { error('LLM prompts directory not found in CLI installation.'); info(`Expected location: ${promptsTemplateDir}`); info('Please reinstall the CLI or report this issue.'); return; } // Get all available prompts (*.md files) const allFiles = filesystem.list(promptsTemplateDir) || []; const availablePrompts = allFiles.filter((file) => file.endsWith('.md')); if (availablePrompts.length === 0) { error('No LLM prompts found in CLI installation.'); return; } // Show available prompts if no specific prompt requested let selectedPrompt; if (parameters.first) { // Check if the requested prompt exists const requestedPrompt = parameters.first.endsWith('.md') ? parameters.first : `${parameters.first}.md`; if (!availablePrompts.includes(requestedPrompt)) { error(`Prompt "${parameters.first}" not found.`); info(''); info('Available prompts:'); availablePrompts.forEach((p) => { const promptPath = (0, path_1.join)(promptsTemplateDir, p); const metadata = getPromptMetadata(promptPath, filesystem); const promptName = p.replace('.md', ''); info(` • ${promptName}`); info(` ${metadata.description}`); info(''); }); return; } selectedPrompt = requestedPrompt; } else { // Interactive mode: show menu info(''); info('Available LLM Prompt Templates:'); info(''); const choices = []; availablePrompts.forEach((p) => { const promptPath = (0, path_1.join)(promptsTemplateDir, p); const metadata = getPromptMetadata(promptPath, filesystem); const promptName = p.replace('.md', ''); choices.push({ message: `${promptName} - ${metadata.description}`, name: promptName, value: p, }); }); const { selected } = yield prompt.ask({ choices: choices.map((c) => c.message), message: 'Select a prompt template:', name: 'selected', type: 'select', }); // Find the selected prompt file const selectedChoice = choices.find((c) => c.message === selected); if (!selectedChoice) { error('Invalid selection.'); return; } selectedPrompt = selectedChoice.value; } // Get prompt content const promptPath = (0, path_1.join)(promptsTemplateDir, selectedPrompt); const promptContent = getPromptContent(promptPath, filesystem); const metadata = getPromptMetadata(promptPath, filesystem); // Determine output method let outputMethod; if (parameters.options.output || parameters.options.o) { // Save to file outputMethod = 'file'; } else if (parameters.options.clipboard || parameters.options.c) { // Copy to clipboard outputMethod = 'clipboard'; } else if (parameters.options.display || parameters.options.d) { // Display only outputMethod = 'display'; } else { // Interactive: ask user const { action } = yield prompt.ask({ choices: ['Display in terminal', 'Copy to clipboard', 'Save as Markdown file'], message: 'What would you like to do with this prompt?', name: 'action', type: 'select', }); if (action === 'Display in terminal') { outputMethod = 'display'; } else if (action === 'Copy to clipboard') { outputMethod = 'clipboard'; } else { outputMethod = 'file'; } } // Execute output method if (outputMethod === 'clipboard') { const copied = yield copyToClipboard(promptContent); if (copied) { success('✓ Prompt copied to clipboard!'); info(''); info('You can now paste it into ChatGPT, Gemini, Claude, or any other LLM.'); } else { warning('Could not copy to clipboard automatically.'); info(''); info('The prompt will be displayed below for manual copying:'); info(''); info('─'.repeat(60)); info(promptContent); info('─'.repeat(60)); } } else if (outputMethod === 'display') { info(''); info('─'.repeat(60)); highlight(`📝 ${metadata.name || selectedPrompt.replace('.md', '')}`); info('─'.repeat(60)); info(''); info(promptContent); info(''); info('─'.repeat(60)); success('Prompt displayed above. Copy and paste into your preferred LLM.'); } else if (outputMethod === 'file') { let outputPath; if (typeof parameters.options.output === 'string') { outputPath = parameters.options.output; } else if (typeof parameters.options.o === 'string') { outputPath = parameters.options.o; } else { // Ask for file path const defaultFilename = selectedPrompt; const { filepath } = yield prompt.ask({ initial: defaultFilename, message: 'Enter the file path to save:', name: 'filepath', type: 'input', }); outputPath = filepath; } // Ensure .md extension if (!outputPath.endsWith('.md')) { outputPath += '.md'; } // Check if file exists if (filesystem.exists(outputPath)) { const { overwrite } = yield prompt.ask({ initial: false, message: `File "${outputPath}" already exists. Overwrite?`, name: 'overwrite', type: 'confirm', }); if (!overwrite) { info('Operation cancelled.'); return; } } // Write file with frontmatter const fileContent = `--- name: ${metadata.name || selectedPrompt.replace('.md', '')} description: ${metadata.description} source: lenne.tech CLI (lt templates llm) --- ${promptContent} `; filesystem.write(outputPath, fileContent); success(`✓ Prompt saved to: ${outputPath}`); } info(''); // Exit if not running from menu if (!toolbox.parameters.options.fromGluegunMenu) { process.exit(); } // For tests return `templates llm ${selectedPrompt.replace('.md', '')}`; } catch (err) { error(`Failed to process prompt: ${err.message}`); return; } }), }; exports.default = LlmCommand;