pit-manager
Version:
Centralized prompt management system for Human Behavior AI agents
213 lines • 7.6 kB
JavaScript
;
/**
* 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 .pit directory
const pitDir = findPitDirectory();
if (!pitDir) {
throw new Error("No .pit directory found. Run 'pit init' first.");
}
// Ensure template name has .md extension
if (!templateName.endsWith('.md')) {
templateName += '.md';
}
// Load template file
const templatePath = path.join(pitDir, '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' && '_isPitResponse' in variable && variable._isPitResponse) {
// 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 .pit directory by searching up from current directory
*/
function findPitDirectory() {
let current = process.cwd();
while (current !== path.dirname(current)) {
const pitDir = path.join(current, '.pit');
if (fs.existsSync(pitDir) && fs.statSync(pitDir).isDirectory()) {
return pitDir;
}
current = path.dirname(current);
}
// Check current directory one more time
const pitDir = path.join(process.cwd(), '.pit');
if (fs.existsSync(pitDir) && fs.statSync(pitDir).isDirectory()) {
return pitDir;
}
return null;
}
/**
* Parse template content into frontmatter and body
*/
function parseTemplate(content) {
if (content.startsWith('---')) {
// Find the second --- to properly extract frontmatter
const firstDelimiter = 0;
const secondDelimiter = content.indexOf('---', firstDelimiter + 3);
if (secondDelimiter !== -1) {
const frontmatterStr = content.substring(firstDelimiter + 3, secondDelimiter).trim();
const templateContent = content.substring(secondDelimiter + 3).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