UNPKG

prompt-version-manager

Version:

Centralized prompt management system for Human Behavior AI agents

211 lines 7.4 kB
"use strict"; /** * Simplified prompt loading and rendering for TypeScript */ 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.prompts = prompts; exports.getCurrentPromptFile = getCurrentPromptFile; exports.getParentExecutionId = getParentExecutionId; exports.clearPromptContext = clearPromptContext; const fs = __importStar(require("fs")); const path = __importStar(require("path")); const yaml = __importStar(require("js-yaml")); // Global state for tracking current prompt file let currentPromptFile; // Global state for tracking parent execution ID from ModelResponse let parentExecutionId; /** * Load and render a prompt template with positional variables. * * Variables are matched to {{variable}} placeholders in order of appearance. * * @param templateName - Name of the template file (with or without .md extension) * @param variables - List of values to substitute in order of appearance * @returns Rendered prompt string * * @example * // If template has {{role}} and {{task}} * const prompt = prompts("assistant.md", ["expert", "analyze data"]); */ function prompts(templateName, variables) { // Find .pvm directory const pvmDir = findPvmDirectory(); if (!pvmDir) { throw new Error("No .pvm directory found. Run 'pvm init' first."); } // Ensure template name has .md extension if (!templateName.endsWith('.md')) { templateName += '.md'; } // Load template file const templatePath = path.join(pvmDir, 'prompts', templateName); if (!fs.existsSync(templatePath)) { throw new Error(`Template not found: ${templatePath}`); } const content = fs.readFileSync(templatePath, 'utf-8'); // Parse frontmatter and template const { templateContent } = parseTemplate(content); // Extract variables in order of appearance const variableNames = extractVariables(templateContent); // Create variable mapping if (variables.length !== variableNames.length) { throw new Error(`Expected ${variableNames.length} variables ${JSON.stringify(variableNames)}, ` + `but got ${variables.length} values`); } // Process variables and detect ModelResponse objects const processedVariables = []; parentExecutionId = undefined; // Reset parent ID for (const variable of variables) { // Check if this is a ModelResponse object if (variable && typeof variable === 'object' && '_isPvmResponse' in variable && variable._isPvmResponse) { // Extract content from ModelResponse processedVariables.push(variable.content); // Store the execution ID for chaining (use the first one found) if (!parentExecutionId) { parentExecutionId = variable.executionId; } } else { processedVariables.push(variable); } } const variableMap = {}; variableNames.forEach((name, index) => { variableMap[name] = processedVariables[index]; }); // Render template const rendered = renderTemplate(templateContent, variableMap); // Track current prompt file for execution tracking currentPromptFile = templateName; return rendered; } /** * Find the .pvm directory by searching up from current directory */ function findPvmDirectory() { let current = process.cwd(); while (current !== path.dirname(current)) { const pvmDir = path.join(current, '.pvm'); if (fs.existsSync(pvmDir) && fs.statSync(pvmDir).isDirectory()) { return pvmDir; } current = path.dirname(current); } // Check current directory one more time const pvmDir = path.join(process.cwd(), '.pvm'); if (fs.existsSync(pvmDir) && fs.statSync(pvmDir).isDirectory()) { return pvmDir; } return null; } /** * Parse template content into frontmatter and body */ function parseTemplate(content) { if (content.startsWith('---')) { const parts = content.split('---', 3); if (parts.length >= 3) { const frontmatterStr = parts[1].trim(); const templateContent = parts[2].trim(); // Parse YAML frontmatter let frontmatter = {}; try { frontmatter = yaml.load(frontmatterStr) || {}; } catch (e) { // Ignore YAML errors } return { frontmatter, templateContent }; } } return { frontmatter: {}, templateContent: content }; } /** * Extract variable names from template in order of appearance */ function extractVariables(template) { // Find all {{variable}} patterns const pattern = /\{\{(\w+)\}\}/g; const matches = [...template.matchAll(pattern)]; // Remove duplicates while preserving order const seen = new Set(); const uniqueVars = []; for (const match of matches) { const varName = match[1]; if (!seen.has(varName)) { seen.add(varName); uniqueVars.push(varName); } } return uniqueVars; } /** * Render template by replacing variables */ function renderTemplate(template, variables) { let rendered = template; for (const [varName, value] of Object.entries(variables)) { const pattern = new RegExp(`\\{\\{${escapeRegExp(varName)}\\}\\}`, 'g'); rendered = rendered.replace(pattern, String(value)); } return rendered; } /** * Escape special regex characters */ function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } /** * Get the current prompt file being used */ function getCurrentPromptFile() { return currentPromptFile; } /** * Get the parent execution ID if a ModelResponse was passed to prompts() */ function getParentExecutionId() { return parentExecutionId; } /** * Clear the prompt context (used after model execution) */ function clearPromptContext() { currentPromptFile = undefined; parentExecutionId = undefined; } //# sourceMappingURL=prompts.js.map