UNPKG

@jasondark/proompt

Version:

CLI tool for running AI prompts with structure and repeatability

200 lines 9.62 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.documentDirsCommand = void 0; const child_process_1 = require("child_process"); const fs_1 = require("fs"); const path = __importStar(require("path")); const command_utils_1 = require("@/core/command-utils"); const resolver_1 = require("@/core/config/resolver"); const constants_1 = require("@/core/constants"); const doc_metadata_1 = require("@/core/utils/doc-metadata"); const file_tracker_1 = require("@/core/utils/file-tracker"); const git_1 = require("@/core/utils/git"); const repomix_1 = require("@/core/utils/repomix"); const rules_1 = require("@/core/utils/rules"); const temp_file_1 = require("@/core/utils/temp-file"); const schema_1 = require("./schema"); // Read proompt content const proomptContent = (0, fs_1.readFileSync)(path.join(__dirname, 'proompt.md'), 'utf-8'); /** * Custom handler that generates XML file before AI execution */ const customDocumentDirsHandler = async (args) => { // Validate arguments using schema const validatedArgs = schema_1.documentDirsArgsSchema.parse(args); try { // Get current commit hash for tracking const commitHash = (0, git_1.getCurrentCommitHash)(); if (!commitHash) { console.warn('⚠️ Warning: Not in a git repository, commit hash tracking disabled'); } // Parse directory paths from CLI input string const directoryPaths = validatedArgs.directoryPaths .split(/\s+/) .filter((path) => path.length > 0); // Validate that all directory paths exist and are accessible for (const dirPath of directoryPaths) { try { const stats = await fs_1.promises.stat(dirPath); if (!stats.isDirectory()) { throw new Error(`Path is not a directory: ${dirPath}`); } } catch (error) { if (error.code === 'ENOENT') { throw new Error(`Directory does not exist: ${dirPath}`); } throw new Error(`Cannot access directory: ${dirPath} - ${error.message}`); } } console.log(`📁 Validated ${directoryPaths.length} director${directoryPaths.length === 1 ? 'y' : 'ies'} for analysis`); // Generate XML files for each directory const directoryXmlMap = {}; console.log('📦 Packing directories with repomix...'); for (const dirPath of directoryPaths) { const xmlFilePath = (0, temp_file_1.generateTempXmlPath)(`document-dir-${dirPath.replace(/[^a-zA-Z0-9]/g, '_')}`); console.log(`📁 Packing ${dirPath}...`); await (0, repomix_1.executeRepomix)({ outputPath: xmlFilePath, workingDirectory: dirPath, }); directoryXmlMap[dirPath] = xmlFilePath; (0, temp_file_1.logTempFileLocation)(xmlFilePath); } console.log('✅ All directories packed successfully'); // Resolve settings using hierarchy: args > user settings > defaults const settingsOverride = { llmCli: args?.llmCli, outputFormat: args?.outputFormat, }; const resolvedSettings = (0, resolver_1.resolveSettings)(settingsOverride); const llmCli = resolvedSettings.llmCli; const outputFormat = resolvedSettings.outputFormat; // Generate output file names based on configured formats const outputFileNames = outputFormat.map((format) => constants_1.OUTPUT_FILE_NAMES[format]); const isPlural = outputFileNames.length > 1; // Create formatted directory-to-XML mapping for the prompt const directoryXmlMapping = Object.entries(directoryXmlMap) .map(([dir, xmlPath]) => `- ${dir}: \`${xmlPath}\``) .join('\n'); // Check for optional RULES.md files in each directory const rulesMap = (0, rules_1.readRulesFromDirectories)(directoryPaths); const formattedRules = (0, rules_1.formatMultipleRulesForPrompt)(rulesMap) || ''; // Inject template variables including XML mappings and optional rules const enhancedArgs = { ...validatedArgs, directoryXmlMap: directoryXmlMapping, directoryPaths: directoryPaths.join(', '), outputFiles: outputFileNames.map((name) => `\`${name}\``).join(' and '), outputFileList: outputFileNames.join(' and '), outputAction: isPlural ? 'Create identical' : 'Create a', fileOrFiles: isPlural ? 'files' : 'file', requiredDocFiles: outputFileNames.map((name) => `"${name}"`).join(', '), allRequiredFilesExist: `all required files (${outputFileNames.join(', ')}) exist`, directoryRules: formattedRules, }; // Replace variables with provided arguments using imported function const processedContent = (0, command_utils_1.replaceVariables)(proomptContent, enhancedArgs); // Record start time for file modification tracking const startTime = new Date(); // Launch interactive CLI with initial prompt console.log(`🤖 Launching ${llmCli} for directory analysis...`); let child; if (llmCli === 'claude') { child = (0, child_process_1.spawn)('claude', [processedContent], { stdio: 'inherit', }); } else if (llmCli === 'gemini') { child = (0, child_process_1.spawn)('gemini', ['-i', processedContent], { stdio: 'inherit', }); } else { throw new Error(`Unsupported LLM CLI: ${llmCli}`); } return new Promise((resolve, reject) => { child.on('close', (code) => { if (code === 0) { // Check if documentation files were actually modified in the documented directories const filesModified = (0, file_tracker_1.anyDocumentationFilesModifiedInDirs)(startTime, outputFileNames, directoryPaths); // Update metadata for each directory if files were modified and we have a commit hash if (filesModified && commitHash) { try { for (const dirPath of directoryPaths) { (0, doc_metadata_1.updateDirDocHash)(dirPath, commitHash); } const shortHash = commitHash.substring(0, 7); console.log(`📝 Updated directory documentation metadata for ${directoryPaths.length} director${directoryPaths.length === 1 ? 'y' : 'ies'} with commit ${shortHash}`); } catch (error) { console.warn('⚠️ Warning: Failed to update documentation metadata:', error.message); } } else if (filesModified && !commitHash) { console.log('📝 Documentation files were modified but no commit hash available for tracking'); } resolve(); } else { reject(new Error(`${llmCli} command failed with exit code ${code}`)); } }); child.on('error', (error) => { reject(error); }); }); } catch (error) { console.error('❌ Error during directory processing:', error.message); throw error; } }; // Create and export the command module exports.documentDirsCommand = (0, command_utils_1.createCommandModule)({ name: 'document-dirs', description: 'Generate comprehensive documentation for AI coding tools for any directory with specific project logic', arguments: [ { name: 'directory-paths', description: 'Paths to directories for documentation generation (space-separated)', required: true, type: 'string', positional: true, }, ], }, schema_1.documentDirsArgsSchema, proomptContent, customDocumentDirsHandler); //# sourceMappingURL=index.js.map