prompt-version-manager
Version:
Centralized prompt management system for Human Behavior AI agents
442 lines • 15.6 kB
JavaScript
"use strict";
/**
* Storage objects for PVM TypeScript - Git-like content-addressable storage.
*/
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.ExecutionObject = exports.MetricRecordObject = exports.ChainObject = exports.CommitObject = exports.TreeObject = exports.PromptVersionObject = exports.BlobObject = exports.StorageObject = void 0;
exports.parseObjectHeader = parseObjectHeader;
exports.deserializeObject = deserializeObject;
const crypto = __importStar(require("crypto"));
const zlib = __importStar(require("zlib"));
const util_1 = require("util");
const deflate = (0, util_1.promisify)(zlib.deflate);
/**
* Base class for all stored objects (similar to Git objects).
*/
class StorageObject {
/**
* Calculate SHA-256 hash of the object content.
*/
hash() {
const content = this.serialize();
const contentStr = JSON.stringify(content, null, 0);
// Use Python-compatible format: "type length\0content"
const fullContent = `${this.objectType} ${contentStr.length}\0${contentStr}`;
return crypto.createHash('sha256').update(fullContent, 'utf8').digest('hex');
}
/**
* Get the raw content for storage (compressed).
*/
async getRawContent() {
const content = this.serialize();
const contentStr = JSON.stringify(content, null, 0);
// Use Python-compatible format: "type length\0content"
const fullContent = `${this.objectType} ${contentStr.length}\0${contentStr}`;
return await deflate(fullContent);
}
}
exports.StorageObject = StorageObject;
/**
* Blob object for storing raw content.
*/
class BlobObject extends StorageObject {
content;
constructor(content) {
super();
this.content = content;
}
get objectType() {
return 'blob';
}
serialize() {
return {
content: this.content,
};
}
static fromData(data) {
return new BlobObject(data.content);
}
}
exports.BlobObject = BlobObject;
/**
* Prompt version object.
*/
class PromptVersionObject extends StorageObject {
promptVersion;
constructor(promptVersion) {
super();
this.promptVersion = promptVersion;
}
get objectType() {
return 'prompt'; // Match Python's object type
}
serialize() {
return {
id: this.promptVersion.id,
hash: this.promptVersion.hash,
content: this.promptVersion.content,
messages: this.promptVersion.messages.map(msg => ({
role: msg.role,
content: msg.content,
metadata: msg.metadata
})),
model_config: this.promptVersion.modelConfig,
metadata: this.promptVersion.metadata,
parent_id: this.promptVersion.parentId,
created_at: this.promptVersion.createdAt.toISOString(),
tags: this.promptVersion.tags
};
}
static fromData(data) {
return new PromptVersionObject({
id: data.id,
hash: data.hash,
content: data.content,
messages: data.messages.map((msg) => ({
role: msg.role,
content: msg.content,
metadata: msg.metadata
})),
modelConfig: data.model_config,
metadata: data.metadata,
parentId: data.parent_id,
createdAt: new Date(data.created_at),
tags: data.tags || []
});
}
}
exports.PromptVersionObject = PromptVersionObject;
/**
* Tree object - groups related objects (similar to Git tree).
*/
class TreeObject extends StorageObject {
entries;
constructor(entries) {
super();
this.entries = entries;
}
get objectType() {
return 'tree';
}
serialize() {
// Sort entries for deterministic hashing
const sortedEntries = {};
Object.keys(this.entries).sort().forEach(key => {
sortedEntries[key] = this.entries[key];
});
return {
entries: sortedEntries
};
}
static fromData(data) {
return new TreeObject(data.entries);
}
}
exports.TreeObject = TreeObject;
/**
* Commit object.
*/
class CommitObject extends StorageObject {
commit;
constructor(commit) {
super();
this.commit = commit;
}
get objectType() {
return 'commit';
}
serialize() {
return {
tree: this.commit.treeHash || '', // For Python compatibility
parents: this.commit.parentHashes, // Python uses 'parents' not 'parent_hashes'
author: this.commit.author,
message: this.commit.message,
timestamp: this.commit.timestamp.toISOString(),
metadata: this.commit.metadata
};
}
static fromData(data) {
return new CommitObject({
hash: '', // Hash will be set from storage key
message: data.message,
author: data.author,
timestamp: new Date(data.timestamp),
parentHashes: data.parents || data.parent_hashes || [], // Support both formats
treeHash: data.tree,
promptVersions: [], // Will be loaded from tree
metadata: data.metadata || {}
});
}
}
exports.CommitObject = CommitObject;
/**
* Chain object for storing agent chains.
*/
class ChainObject extends StorageObject {
chain;
constructor(chain) {
super();
this.chain = chain;
}
get objectType() {
return 'chain';
}
serialize() {
return {
id: this.chain.id,
name: this.chain.name,
description: this.chain.description,
status: this.chain.status,
nodes: Object.fromEntries(Object.entries(this.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,
start_time: node.startTime?.toISOString(),
end_time: node.endTime?.toISOString(),
result: node.result ? {
content: node.result.content,
tokens: node.result.tokens,
model: node.result.model,
provider: node.result.provider,
latency: node.result.latency,
cost: node.result.cost,
timestamp: node.result.timestamp.toISOString(),
finish_reason: node.result.finishReason,
parsed: node.result.parsed,
metadata: node.result.metadata,
request_id: node.result.requestId,
raw_response: node.result.rawResponse
} : null,
error: node.error,
retry_count: node.retryCount,
metadata: node.metadata
}
])),
start_time: this.chain.startTime?.toISOString(),
end_time: this.chain.endTime?.toISOString(),
total_cost: this.chain.totalCost,
total_tokens: this.chain.totalTokens,
metadata: this.chain.metadata,
root_nodes: this.chain.rootNodes,
leaf_nodes: this.chain.leafNodes,
created_at: this.chain.createdAt.toISOString(),
updated_at: this.chain.updatedAt.toISOString(),
total_latency: this.chain.totalLatency
};
}
static fromData(data) {
const nodes = {};
for (const [nodeId, nodeData] of Object.entries(data.nodes)) {
nodes[nodeId] = {
id: nodeData.id,
tag: nodeData.tag,
model: nodeData.model,
provider: nodeData.provider,
language: nodeData.language,
dependencies: nodeData.dependencies || [],
status: nodeData.status,
startTime: nodeData.start_time ? new Date(nodeData.start_time) : undefined,
endTime: nodeData.end_time ? new Date(nodeData.end_time) : undefined,
result: nodeData.result ? {
content: nodeData.result.content,
tokens: nodeData.result.tokens,
model: nodeData.result.model,
provider: nodeData.result.provider,
latency: nodeData.result.latency,
cost: nodeData.result.cost,
timestamp: new Date(nodeData.result.timestamp),
finishReason: nodeData.result.finish_reason,
parsed: nodeData.result.parsed,
metadata: nodeData.result.metadata,
requestId: nodeData.result.request_id,
rawResponse: nodeData.result.raw_response
} : undefined,
error: nodeData.error,
retryCount: nodeData.retry_count || 0,
metadata: nodeData.metadata
};
}
return new ChainObject({
id: data.id,
name: data.name,
description: data.description,
status: data.status,
nodes,
startTime: data.start_time ? new Date(data.start_time) : undefined,
endTime: data.end_time ? new Date(data.end_time) : undefined,
totalCost: data.total_cost || 0,
totalTokens: data.total_tokens || { input: 0, output: 0, total: 0 },
metadata: data.metadata,
rootNodes: data.root_nodes || [],
leafNodes: data.leaf_nodes || [],
createdAt: new Date(data.created_at),
updatedAt: new Date(data.updated_at),
totalLatency: data.total_latency
});
}
}
exports.ChainObject = ChainObject;
/**
* Metric record object.
*/
class MetricRecordObject extends StorageObject {
metric;
constructor(metric) {
super();
this.metric = metric;
}
get objectType() {
return 'metric_record';
}
serialize() {
return {
request_id: this.metric.requestId,
tag: this.metric.tag,
model: this.metric.model,
provider: this.metric.provider,
tokens: this.metric.tokens,
cost: this.metric.cost,
latency: this.metric.latency,
timestamp: this.metric.timestamp.toISOString(),
success: this.metric.success,
error_type: this.metric.errorType,
error_message: this.metric.errorMessage,
user_id: this.metric.userId,
session_id: this.metric.sessionId,
environment: this.metric.environment
};
}
static fromData(data) {
return new MetricRecordObject({
requestId: data.request_id,
tag: data.tag,
model: data.model,
provider: data.provider,
tokens: data.tokens,
cost: data.cost,
latency: data.latency,
timestamp: new Date(data.timestamp),
success: data.success,
errorType: data.error_type,
errorMessage: data.error_message,
userId: data.user_id,
sessionId: data.session_id,
environment: data.environment || 'default'
});
}
}
exports.MetricRecordObject = MetricRecordObject;
/**
* Parse object header from compressed content.
*/
function parseObjectHeader(compressedContent) {
const decompressed = zlib.inflateSync(compressedContent).toString('utf8');
const nullIndex = decompressed.indexOf('\0');
if (nullIndex === -1) {
throw new Error('Invalid object format: no null separator found');
}
const header = decompressed.substring(0, nullIndex);
const content = decompressed.substring(nullIndex + 1);
// Handle both formats: "commit" (TypeScript) and "commit 191" (Python with length)
let type;
if (header.includes(' ')) {
// Python format: "commit 191" -> extract just "commit"
const parts = header.split(' ');
type = parts[0];
// Optionally validate the length if needed
const expectedLength = parseInt(parts[1], 10);
if (!isNaN(expectedLength) && content.length !== expectedLength) {
throw new Error(`Content size mismatch: expected ${expectedLength}, got ${content.length}`);
}
}
else {
// TypeScript format: "commit"
type = header;
}
return { type, content };
}
/**
* Deserialize object from compressed content.
*/
function deserializeObject(compressedContent) {
const { type, content } = parseObjectHeader(compressedContent);
const data = JSON.parse(content);
switch (type) {
case 'blob':
return BlobObject.fromData(data);
case 'prompt': // Match Python's object type
return PromptVersionObject.fromData(data);
case 'prompt_version': // Keep for backward compatibility
return PromptVersionObject.fromData(data);
case 'tree':
return TreeObject.fromData(data);
case 'commit':
return CommitObject.fromData(data);
case 'chain':
return ChainObject.fromData(data);
case 'metric_record':
return MetricRecordObject.fromData(data);
case 'execution':
return ExecutionObject.fromData(data);
default:
throw new Error(`Unknown object type: ${type}`);
}
}
/**
* Storage object for executions (for simplified API tracking).
*/
class ExecutionObject extends StorageObject {
data;
get objectType() { return 'execution'; }
constructor(data) {
super();
this.data = data;
}
serialize() {
return this.data;
}
static fromData(data) {
return new ExecutionObject(data);
}
}
exports.ExecutionObject = ExecutionObject;
//# sourceMappingURL=objects.js.map