UNPKG

prompt-version-manager

Version:

Centralized prompt management system for Human Behavior AI agents

382 lines 14.2 kB
"use strict"; /** * Chain management for tracking agent chains in 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.ChainManager = void 0; const fs = __importStar(require("fs/promises")); const path = __importStar(require("path")); const uuid_1 = require("uuid"); const models_1 = require("../core/models"); const exceptions_1 = require("../core/exceptions"); class ChainManager { // private repoPath: string; activeChains = new Map(); chainMetadataPath; constructor(repoPath = '.pvm') { // this.repoPath = repoPath; this.chainMetadataPath = path.join(repoPath, 'chains.json'); this.loadChainMetadata(); } async loadChainMetadata() { try { const data = await fs.readFile(this.chainMetadataPath, 'utf-8'); const chainData = JSON.parse(data); for (const [chainId, chainInfo] of Object.entries(chainData)) { const chain = this.deserializeChain(chainInfo); this.activeChains.set(chainId, chain); } } catch (error) { // File doesn't exist or invalid JSON - start with empty chains console.warn(`Warning: Failed to load chain metadata: ${error}`); } } async saveChainMetadata() { try { // Ensure directory exists await fs.mkdir(path.dirname(this.chainMetadataPath), { recursive: true }); const data = {}; for (const [chainId, chain] of this.activeChains.entries()) { data[chainId] = this.serializeChain(chain); } await fs.writeFile(this.chainMetadataPath, JSON.stringify(data, null, 2)); } catch (error) { console.warn(`Warning: Failed to save chain metadata: ${error}`); } } serializeChain(chain) { return { id: chain.id, name: chain.name, description: chain.description, status: chain.status, startTime: chain.startTime?.toISOString(), endTime: chain.endTime?.toISOString(), totalCost: chain.totalCost, totalTokens: chain.totalTokens, metadata: chain.metadata || {}, nodes: Object.fromEntries(Object.entries(chain.nodes).map(([nodeId, node]) => [ nodeId, { id: node.id, tag: node.tag, model: node.model, provider: node.provider, language: node.language, dependencies: node.dependencies, status: node.status, startTime: node.startTime?.toISOString(), endTime: node.endTime?.toISOString(), result: node.result, error: node.error, retryCount: node.retryCount, metadata: node.metadata || {} } ])) }; } deserializeChain(data) { const chain = { id: data.id, name: data.name, description: data.description, status: data.status, startTime: data.startTime ? new Date(data.startTime) : undefined, endTime: data.endTime ? new Date(data.endTime) : undefined, totalCost: data.totalCost, totalTokens: data.totalTokens, metadata: data.metadata, nodes: {} }; // Deserialize nodes for (const [nodeId, nodeData] of Object.entries(data.nodes)) { const node = { id: nodeData.id, tag: nodeData.tag, model: nodeData.model, provider: nodeData.provider, language: nodeData.language, dependencies: nodeData.dependencies, status: nodeData.status, startTime: nodeData.startTime ? new Date(nodeData.startTime) : undefined, endTime: nodeData.endTime ? new Date(nodeData.endTime) : undefined, result: nodeData.result, error: nodeData.error, retryCount: nodeData.retryCount, metadata: nodeData.metadata }; chain.nodes[nodeId] = node; } return chain; } createChain(name, description, chainId) { if (!chainId) { chainId = (0, uuid_1.v4)(); } if (this.activeChains.has(chainId)) { throw new exceptions_1.ChainError(`Chain ${chainId} already exists`); } const chain = { id: chainId, name, description, status: models_1.ChainStatus.PENDING, nodes: {}, totalCost: 0.0, totalTokens: { input: 0, output: 0, total: 0 } }; this.activeChains.set(chainId, chain); this.saveChainMetadata(); return chainId; } addNode(chainId, tag, model, provider, language = 'typescript', dependencies = [], nodeId) { if (!nodeId) { nodeId = (0, uuid_1.v4)(); } const chain = this.activeChains.get(chainId); if (!chain) { throw new exceptions_1.ChainNotFoundError(`Chain ${chainId} not found`); } if (chain.nodes[nodeId]) { throw new exceptions_1.ChainError(`Node ${nodeId} already exists in chain ${chainId}`); } // Validate dependencies exist for (const depId of dependencies) { if (!chain.nodes[depId]) { throw new exceptions_1.ChainError(`Dependency ${depId} not found in chain ${chainId}`); } } // Check for circular dependencies this.checkCircularDependency(chain, nodeId, dependencies); const node = { id: nodeId, tag, model, provider, language, dependencies, status: models_1.ChainStatus.PENDING, retryCount: 0 }; chain.nodes[nodeId] = node; this.saveChainMetadata(); return nodeId; } checkCircularDependency(chain, newNodeId, dependencies) { const hasPathTo = (fromNode, toNode, visited) => { if (fromNode === toNode) { return true; } if (visited.has(fromNode)) { return false; } visited.add(fromNode); const node = chain.nodes[fromNode]; if (node) { for (const dep of node.dependencies) { if (hasPathTo(dep, toNode, visited)) { return true; } } } return false; }; // Check if adding this node would create a cycle for (const depId of dependencies) { if (hasPathTo(depId, newNodeId, new Set())) { throw new exceptions_1.CircularDependencyError(`Adding node ${newNodeId} with dependency ${depId} would create a circular dependency`); } } } startChain(chainId) { const chain = this.activeChains.get(chainId); if (!chain) { throw new exceptions_1.ChainNotFoundError(`Chain ${chainId} not found`); } chain.status = models_1.ChainStatus.RUNNING; chain.startTime = new Date(); this.saveChainMetadata(); } completeChain(chainId) { const chain = this.activeChains.get(chainId); if (!chain) { throw new exceptions_1.ChainNotFoundError(`Chain ${chainId} not found`); } chain.status = models_1.ChainStatus.COMPLETED; chain.endTime = new Date(); this.saveChainMetadata(); } failChain(chainId, error) { const chain = this.activeChains.get(chainId); if (!chain) { throw new exceptions_1.ChainNotFoundError(`Chain ${chainId} not found`); } chain.status = models_1.ChainStatus.FAILED; chain.endTime = new Date(); if (!chain.metadata) { chain.metadata = {}; } chain.metadata.error = error; this.saveChainMetadata(); } startNode(chainId, nodeId) { const chain = this.activeChains.get(chainId); if (!chain) { throw new exceptions_1.ChainNotFoundError(`Chain ${chainId} not found`); } const node = chain.nodes[nodeId]; if (!node) { throw new exceptions_1.ChainError(`Node ${nodeId} not found in chain ${chainId}`); } node.status = models_1.ChainStatus.RUNNING; node.startTime = new Date(); this.saveChainMetadata(); } completeNode(chainId, nodeId, result) { const chain = this.activeChains.get(chainId); if (!chain) { throw new exceptions_1.ChainNotFoundError(`Chain ${chainId} not found`); } const node = chain.nodes[nodeId]; if (!node) { throw new exceptions_1.ChainError(`Node ${nodeId} not found in chain ${chainId}`); } node.status = models_1.ChainStatus.COMPLETED; node.endTime = new Date(); node.result = result; // Update chain totals chain.totalCost += result.cost; chain.totalTokens.input += result.tokens.input; chain.totalTokens.output += result.tokens.output; chain.totalTokens.total += result.tokens.total; this.saveChainMetadata(); } failNode(chainId, nodeId, error) { const chain = this.activeChains.get(chainId); if (!chain) { throw new exceptions_1.ChainNotFoundError(`Chain ${chainId} not found`); } const node = chain.nodes[nodeId]; if (!node) { throw new exceptions_1.ChainError(`Node ${nodeId} not found in chain ${chainId}`); } node.status = models_1.ChainStatus.FAILED; node.endTime = new Date(); node.error = error; this.saveChainMetadata(); } getChain(chainId) { const chain = this.activeChains.get(chainId); if (!chain) { throw new exceptions_1.ChainNotFoundError(`Chain ${chainId} not found`); } return chain; } listChains() { return Array.from(this.activeChains.values()); } getReadyNodes(chainId) { const chain = this.activeChains.get(chainId); if (!chain) { throw new exceptions_1.ChainNotFoundError(`Chain ${chainId} not found`); } const readyNodes = []; for (const [nodeId, node] of Object.entries(chain.nodes)) { if (node.status !== models_1.ChainStatus.PENDING) { continue; } // Check if all dependencies are completed const allDepsCompleted = node.dependencies.every(depId => { const depNode = chain.nodes[depId]; return depNode && depNode.status === models_1.ChainStatus.COMPLETED; }); if (allDepsCompleted) { readyNodes.push(nodeId); } } return readyNodes; } getChainStats(chainId) { const chain = this.activeChains.get(chainId); if (!chain) { throw new exceptions_1.ChainNotFoundError(`Chain ${chainId} not found`); } const nodeStats = { total: Object.keys(chain.nodes).length, pending: 0, inProgress: 0, completed: 0, failed: 0 }; for (const node of Object.values(chain.nodes)) { switch (node.status) { case models_1.ChainStatus.PENDING: nodeStats.pending++; break; case models_1.ChainStatus.RUNNING: nodeStats.inProgress++; break; case models_1.ChainStatus.COMPLETED: nodeStats.completed++; break; case models_1.ChainStatus.FAILED: nodeStats.failed++; break; } } return { chainId, name: chain.name, status: chain.status, nodes: nodeStats, totalCost: chain.totalCost, totalTokens: chain.totalTokens, duration: chain.startTime && chain.endTime ? (chain.endTime.getTime() - chain.startTime.getTime()) / 1000 : null }; } async getChainNodes(chainId) { const chain = await this.getChain(chainId); if (!chain || !chain.nodes) return []; return Object.values(chain.nodes); } } exports.ChainManager = ChainManager; //# sourceMappingURL=manager.js.map