prompt-version-manager
Version:
Centralized prompt management system for Human Behavior AI agents
436 lines • 16.2 kB
JavaScript
;
/**
* PVM CLI - Git-like version control for AI prompts (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.main = main;
const commander_1 = require("commander");
const fs = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
const operations_1 = require("../versioning/operations");
const branches_1 = require("../versioning/branches");
// Core exceptions imported as needed
class PVMCLI {
versioning;
branchManager;
constructor(repoPath = '.pvm') {
this.versioning = new operations_1.VersioningEngine(repoPath);
this.branchManager = new branches_1.BranchManager(repoPath);
}
async init(_options = {}) {
try {
await this.versioning.init();
console.log(`Initialized empty PVM repository in ${path.resolve('.pvm')}`);
console.log("\nCreated example files:");
console.log(" .pvm/prompts/template.md - Example prompt template");
console.log(" example.ts - TypeScript example using simplified API");
console.log("\nRun 'npx tsx example.ts' to see the simplified API in action!");
return 0;
}
catch (error) {
console.error(`Error: ${error.message}`);
return 1;
}
}
async add(options) {
try {
let content;
if (options.file) {
content = await fs.readFile(options.file, 'utf-8');
content = content.trim();
}
else if (options.content) {
content = options.content;
}
else {
console.error('Error: No content provided. Use --content or --file');
return 1;
}
if (!content) {
console.error('Error: Content is empty');
return 1;
}
// Create message from content
const messages = [
{ role: 'user', content, metadata: {} }
];
// Parse model config
const modelConfig = {};
if (options.temperature !== undefined) {
modelConfig.temperature = options.temperature;
}
if (options.maxTokens !== undefined) {
modelConfig.max_tokens = options.maxTokens;
}
if (options.model) {
modelConfig.model = options.model;
}
// Parse metadata
const metadata = {};
if (options.metadata) {
for (const item of options.metadata) {
if (item.includes('=')) {
const [key, value] = item.split('=', 2);
metadata[key] = value;
}
}
}
const tags = options.tag ? [options.tag] : [];
const promptHash = await this.versioning.add(content, messages, modelConfig, metadata, tags);
console.log(`Added prompt ${promptHash.substring(0, 8)}`);
return 0;
}
catch (error) {
if (error.code === 'ENOENT') {
console.error(`Error: File '${options.file}' not found`);
}
else {
console.error(`Error: ${error.message}`);
}
return 1;
}
}
async commit(message, options = {}) {
try {
const commitHash = await this.versioning.commit(message, options.author || 'PVM User');
const currentBranch = await this.branchManager.getCurrentBranch();
const branchInfo = currentBranch || 'detached';
console.log(`[${branchInfo}] ${commitHash.substring(0, 8)} ${message}`);
return 0;
}
catch (error) {
console.error(`Error: ${error.message}`);
return 1;
}
}
async status(_options = {}) {
try {
const statusInfo = await this.versioning.status();
const currentBranch = statusInfo.currentBranch;
if (currentBranch) {
console.log(`On branch ${currentBranch}`);
}
else {
console.log('HEAD detached');
}
const stagedCount = statusInfo.stagedChanges;
if (stagedCount > 0) {
console.log('\nChanges to be committed:');
console.log(` ${stagedCount} prompt(s) staged`);
}
else {
console.log('\nNothing to commit, working tree clean');
}
return 0;
}
catch (error) {
console.error(`Error: ${error.message}`);
return 1;
}
}
async log(options = {}) {
try {
const commits = await this.versioning.log(options.limit || 10);
if (commits.length === 0) {
console.log('No commits found');
return 0;
}
for (const commit of commits) {
console.log(`commit ${commit.hash}`);
console.log(`Author: ${commit.author}`);
console.log(`Date: ${commit.timestamp.toDateString()}`);
console.log(`\n ${commit.message}\n`);
if (options.showPrompts && commit.promptVersions) {
commit.promptVersions.forEach((promptHash, i) => {
console.log(` Prompt ${i + 1}: ${promptHash.substring(0, 8)}`);
console.log();
});
}
}
return 0;
}
catch (error) {
console.error(`Error: ${error.message}`);
return 1;
}
}
async branch(branchName, options = {}) {
try {
if (options.delete) {
// Delete branch
await this.branchManager.deleteBranch(options.delete, options.force);
console.log(`Deleted branch ${options.delete}`);
}
else if (branchName) {
// Create branch
const commitHash = await this.branchManager.createBranch(branchName, options.startPoint, options.force);
console.log(`Created branch ${branchName} -> ${commitHash.substring(0, 8)}`);
}
else {
// List branches
const branches = await this.branchManager.listBranches();
const currentBranch = await this.branchManager.getCurrentBranch();
if (Object.keys(branches).length === 0) {
console.log('No branches found');
return 0;
}
for (const [branchNameLocal, commitHash] of Object.entries(branches)) {
const marker = branchNameLocal === currentBranch ? '* ' : ' ';
if (options.verbose) {
try {
const info = await this.branchManager.getBranchInfo(branchNameLocal);
console.log(`${marker}${branchNameLocal} ${commitHash.substring(0, 8)} ${info.commitMessage || ''}`);
}
catch {
console.log(`${marker}${branchNameLocal} ${commitHash.substring(0, 8)}`);
}
}
else {
console.log(`${marker}${branchNameLocal}`);
}
}
}
return 0;
}
catch (error) {
console.error(`Error: ${error.message}`);
return 1;
}
}
async checkout(target, options = {}) {
try {
const commitHash = await this.branchManager.checkout(target, options.createBranch, options.force);
const currentBranch = await this.branchManager.getCurrentBranch();
if (currentBranch) {
console.log(`Switched to branch '${currentBranch}'`);
}
else {
console.log(`HEAD is now at ${commitHash.substring(0, 8)}`);
}
return 0;
}
catch (error) {
console.error(`Error: ${error.message}`);
return 1;
}
}
async merge(branch, options = {}) {
try {
const result = await this.branchManager.merge(branch, options.message, options.noFf);
if (result === null) {
console.log(`Fast-forward merge of ${branch}`);
}
else {
console.log(`Merge commit ${result.substring(0, 8)} created`);
}
return 0;
}
catch (error) {
console.error(`Error: ${error.message}`);
return 1;
}
}
async diff(commit1, commit2) {
try {
if (!commit1 && !commit2) {
console.error('Error: Please specify commits to compare');
return 1;
}
const diffResult = await this.versioning.diff(commit1, commit2);
const hasChanges = diffResult.added.length > 0 ||
diffResult.removed.length > 0 ||
diffResult.modified.length > 0;
if (!hasChanges) {
console.log('No differences found');
return 0;
}
if (diffResult.added.length > 0) {
console.log('\nADDED:');
diffResult.added.forEach(hash => {
console.log(` ${hash.substring(0, 8)}`);
});
}
if (diffResult.removed.length > 0) {
console.log('\nREMOVED:');
diffResult.removed.forEach(hash => {
console.log(` ${hash.substring(0, 8)}`);
});
}
if (diffResult.modified.length > 0) {
console.log('\nMODIFIED:');
diffResult.modified.forEach(hash => {
console.log(` ${hash.substring(0, 8)}`);
});
}
return 0;
}
catch (error) {
console.error(`Error: ${error.message}`);
return 1;
}
}
async close() {
await this.versioning.close();
await this.branchManager.close();
}
}
async function main() {
const program = new commander_1.Command();
program
.name('pvm')
.description('PVM - Git-like version control for AI prompts')
.version('0.1.0');
const cli = new PVMCLI();
// pvm init
program
.command('init')
.description('Initialize a new PVM repository')
.option('--force', 'Reinitialize existing repository')
.action(async (options) => {
const exitCode = await cli.init(options);
await cli.close();
process.exit(exitCode);
});
// pvm add
program
.command('add')
.description('Add a prompt to the staging area')
.option('-c, --content <content>', 'Prompt content')
.option('-f, --file <file>', 'Read prompt from file')
.option('-t, --tag <tag>', 'Tag for the prompt')
.option('--temperature <temperature>', 'Model temperature', parseFloat)
.option('--max-tokens <maxTokens>', 'Maximum tokens', parseInt)
.option('--model <model>', 'Model name')
.option('-m, --metadata <metadata>', 'Metadata key=value pairs', (value, previous = []) => {
return [...previous, value];
})
.action(async (options) => {
const exitCode = await cli.add(options);
await cli.close();
process.exit(exitCode);
});
// pvm commit
program
.command('commit <message>')
.description('Create a commit')
.option('-a, --author <author>', 'Author name')
.action(async (message, options) => {
const exitCode = await cli.commit(message, options);
await cli.close();
process.exit(exitCode);
});
// pvm status
program
.command('status')
.description('Show repository status')
.option('-v, --verbose', 'Show detailed status')
.action(async (options) => {
const exitCode = await cli.status(options);
await cli.close();
process.exit(exitCode);
});
// pvm log
program
.command('log')
.description('Show commit history')
.option('-n, --limit <limit>', 'Limit number of commits', parseInt, 10)
.option('-b, --branch <branch>', 'Branch to show history for')
.option('-p, --show-prompts', 'Show prompt content')
.action(async (options) => {
const exitCode = await cli.log(options);
await cli.close();
process.exit(exitCode);
});
// pvm branch
program
.command('branch [branchName]')
.description('Branch operations')
.option('-d, --delete <branch>', 'Delete branch')
.option('-f, --force', 'Force operation')
.option('-s, --start-point <startPoint>', 'Starting point for new branch')
.option('-v, --verbose', 'Show commit messages')
.action(async (branchName, options) => {
const exitCode = await cli.branch(branchName, options);
await cli.close();
process.exit(exitCode);
});
// pvm checkout
program
.command('checkout <target>')
.description('Checkout branch or commit')
.option('-b, --create-branch', 'Create new branch')
.option('-f, --force', 'Force checkout')
.action(async (target, options) => {
const exitCode = await cli.checkout(target, options);
await cli.close();
process.exit(exitCode);
});
// pvm merge
program
.command('merge <branch>')
.description('Merge a branch')
.option('-m, --message <message>', 'Merge commit message')
.option('--no-ff', 'Force merge commit')
.action(async (branch, options) => {
const exitCode = await cli.merge(branch, options);
await cli.close();
process.exit(exitCode);
});
// pvm diff
program
.command('diff [commit1] [commit2]')
.description('Show differences')
.action(async (commit1, commit2) => {
const exitCode = await cli.diff(commit1, commit2);
await cli.close();
process.exit(exitCode);
});
try {
await program.parseAsync(process.argv);
await cli.close();
return 0;
}
catch (error) {
console.error(`Error: ${error.message}`);
await cli.close();
return 1;
}
}
if (require.main === module) {
main().then(code => process.exit(code));
}
//# sourceMappingURL=main.js.map