prompt-version-manager
Version:
Centralized prompt management system for Human Behavior AI agents
242 lines • 8.28 kB
JavaScript
"use strict";
/**
* Native structured output support for different LLM providers in TypeScript
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.StructuredOutputHandler = void 0;
class StructuredOutputHandler {
/**
* Prepare structured output configuration for OpenAI
*/
prepareOpenAIStructured(schema) {
// Determine the actual JSON schema to use
let jsonSchema;
if (this.isStructuredOutput(schema)) {
if (schema.schema) {
jsonSchema = schema.schema;
}
else if (schema.type) {
// Type/class provided - use directly (for beta API with parse)
return {
response_format: schema.type,
useBeta: true
};
}
else {
// StructuredOutput but no schema or type
throw new Error("StructuredOutput must have either 'schema' or 'type' property");
}
}
else {
// Plain object is treated as JSON schema
jsonSchema = schema;
}
// Use beta API with JSON schema
return {
response_format: {
type: "json_schema",
json_schema: {
name: "structured_response",
schema: jsonSchema
}
},
useBeta: true
};
}
/**
* Prepare structured output configuration for Gemini
*/
prepareGeminiStructured(schema) {
let jsonSchema;
if (this.isStructuredOutput(schema) && schema.schema) {
jsonSchema = schema.schema;
}
else if (this.isStructuredOutput(schema) && schema.type) {
// Convert type to JSON schema (simplified)
jsonSchema = this.typeToJsonSchema(schema.type);
}
else {
jsonSchema = schema;
}
// Convert JSON schema to Gemini format
const geminiSchema = this.jsonToGeminiSchema(jsonSchema);
return {
responseMimeType: 'application/json',
responseSchema: geminiSchema
};
}
/**
* Prepare structured output configuration for Claude
*/
prepareClaudeStructured(schema, toolName = 'generate_output') {
let jsonSchema;
if (this.isStructuredOutput(schema) && schema.schema) {
jsonSchema = schema.schema;
}
else if (this.isStructuredOutput(schema) && schema.type) {
// Convert type to JSON schema (simplified)
jsonSchema = this.typeToJsonSchema(schema.type);
}
else {
jsonSchema = schema;
}
// Use custom name if provided
if (this.isStructuredOutput(schema) && schema.name) {
toolName = schema.name;
}
// Create tool definition
const tool = {
name: toolName,
description: `Generate structured output according to schema`,
input_schema: jsonSchema
};
return {
tools: [tool],
tool_choice: { type: 'tool', name: toolName }
};
}
/**
* Parse OpenAI structured response
*/
parseOpenAIResponse(response, _schema) {
if (response.choices?.[0]?.message?.parsed) {
// Beta API with parsing
return response.choices[0].message.parsed;
}
else {
// Regular JSON response
const content = response.choices?.[0]?.message?.content || '';
try {
const data = JSON.parse(content);
return data;
}
catch (e) {
return content;
}
}
}
/**
* Parse Gemini structured response
*/
parseGeminiResponse(response, _schema) {
try {
// Try different ways to extract the text content
const text = response.content ||
response.text ||
response.rawResponse?.text ||
response.candidates?.[0]?.content?.parts?.[0]?.text ||
'';
if (!text) {
return '';
}
const data = JSON.parse(text);
return data;
}
catch (e) {
return response.content || response.text || '';
}
}
/**
* Parse Claude structured response from tool use
*/
parseClaudeResponse(response, _schema) {
// Check for tool use in response
if (response.content) {
for (const content of response.content) {
if (content.type === 'tool_use') {
return content.input;
}
}
}
// Fallback to text content
if (response.content?.[0]?.text) {
return response.content[0].text;
}
return '';
}
/**
* Check if value is a StructuredOutput interface (not a plain JSON schema)
*/
isStructuredOutput(value) {
// Check if it's a StructuredOutput interface vs plain JSON schema
// StructuredOutput has .schema, .type (class/function), or .name
// JSON schema has .type (string like "object", "string", etc.)
if (!value)
return false;
// If it has a 'schema' property, it's definitely a StructuredOutput
if (value.schema !== undefined)
return true;
// If it has a 'name' property, it's probably a StructuredOutput
if (value.name !== undefined)
return true;
// For 'type' property, we need to distinguish between:
// - StructuredOutput.type (should be a class/function)
// - JSON schema type (should be a string like "object", "array", etc.)
if (value.type !== undefined) {
// If type is a string matching JSON schema types, it's a plain JSON schema
if (typeof value.type === 'string' &&
['object', 'array', 'string', 'number', 'integer', 'boolean', 'null'].includes(value.type)) {
return false;
}
// Otherwise, assume it's a StructuredOutput with a type/class
return true;
}
return false;
}
/**
* Convert a type/class to JSON schema (simplified)
*/
typeToJsonSchema(_type) {
// This is a simplified version
// In a real implementation, you'd introspect the type
return {
type: 'object',
properties: {},
required: []
};
}
/**
* Convert JSON schema to Gemini schema format
*/
jsonToGeminiSchema(jsonSchema) {
const convertType = (jsonType) => {
const typeMap = {
'string': 'STRING',
'number': 'NUMBER',
'integer': 'INTEGER',
'boolean': 'BOOLEAN',
'array': 'ARRAY',
'object': 'OBJECT'
};
return typeMap[jsonType] || 'STRING';
};
const convertSchema = (schema) => {
if (!schema.type) {
return schema;
}
const geminiSchema = { type: convertType(schema.type) };
// Handle object properties
if (schema.type === 'object' && schema.properties) {
geminiSchema.properties = {};
for (const [propName, propSchema] of Object.entries(schema.properties)) {
geminiSchema.properties[propName] = convertSchema(propSchema);
}
if (schema.required) {
geminiSchema.required = schema.required;
}
}
// Handle arrays
else if (schema.type === 'array' && schema.items) {
geminiSchema.items = convertSchema(schema.items);
}
// Add description if present
if (schema.description) {
geminiSchema.description = schema.description;
}
return geminiSchema;
};
return convertSchema(jsonSchema);
}
}
exports.StructuredOutputHandler = StructuredOutputHandler;
//# sourceMappingURL=structured-output.js.map