Skip to main content
Glama
memory-config.schema.tsβ€’12.1 kB
/** * Memory Configuration Schema * * Comprehensive Zod schemas for validating YAML configuration files * that define custom memory types in the Cipher system. */ import { z } from 'zod'; /** * Base validation types */ export const FieldValidationType = z.enum([ 'non_empty', 'url', 'email', 'range', 'enum', 'regex', 'custom', 'uuid', 'json', 'positive_number', 'identifier', 'path', ]); export const FieldType = z.enum(['string', 'number', 'boolean', 'array', 'object']); /** * Field configuration schema */ export const FieldConfigSchema = z .object({ name: z.string().min(1, 'Field name is required'), type: FieldType, required: z.boolean().default(false), description: z.string().optional(), validation: FieldValidationType.optional(), default: z.any().optional(), // Type-specific validations min_value: z.number().optional(), max_value: z.number().optional(), allowed_values: z.array(z.string()).optional(), pattern: z.string().optional(), // Array-specific item_type: z.string().optional(), // Object-specific properties: z.record(z.string()).optional(), }) .refine( data => { // Array fields must specify item_type if (data.type === 'array' && !data.item_type) { return false; } // Range validation requires min/max for numbers if (data.validation === 'range' && data.type === 'number') { return data.min_value !== undefined || data.max_value !== undefined; } // Enum validation requires allowed_values if (data.validation === 'enum' && !data.allowed_values) { return false; } // Regex validation requires pattern if (data.validation === 'regex' && !data.pattern) { return false; } return true; }, { message: 'Field configuration validation failed', } ); /** * Schema configuration */ export const SchemaConfigSchema = z.object({ version: z.string().default('1.0'), custom_fields: z.array(FieldConfigSchema).default([]), cross_validations: z .array( z.object({ rule: z.string(), message: z.string(), }) ) .optional(), business_rules: z .array( z.object({ rule: z.string(), message: z.string(), }) ) .optional(), }); /** * Embedding configuration schema */ export const EmbeddingConfigSchema = z.object({ model: z .enum(['text-embedding-3-small', 'text-embedding-3-large', 'text-embedding-ada-002']) .default('text-embedding-3-small'), dimension: z.number().positive().default(1536), batch_size: z.number().positive().default(100), timeout_ms: z.number().positive().default(30000), // Optional preprocessing preprocessing: z .object({ normalize_whitespace: z.boolean().default(false), preserve_structure: z.boolean().default(false), include_comments: z.boolean().default(true), }) .optional(), }); /** * Vector store configuration schema */ export const VectorStoreConfigSchema = z.object({ similarity_threshold: z.number().min(0).max(1).default(0.7), max_results: z.number().positive().default(10), rerank: z.boolean().default(false), time_decay_factor: z.number().min(0).max(1).optional(), // Search options search_options: z .object({ include_metadata: z.boolean().default(true), include_values: z.boolean().default(false), }) .optional(), }); /** * Behavior trigger configuration */ export const BehaviorTriggerSchema = z.object({ keyword_triggers: z.array(z.string()).optional(), pattern_triggers: z.array(z.string()).optional(), semantic_triggers: z.array(z.string()).optional(), conditions: z.string().optional(), exclusions: z.array(z.string()).optional(), // Store-specific field extraction rules field_extraction: z.record(z.string()).optional(), }); /** * Behavior configuration schema */ export const BehaviorConfigSchema = z .object({ search: BehaviorTriggerSchema.optional(), store: BehaviorTriggerSchema.optional(), }) .refine( data => { return data.search || data.store; }, { message: 'At least one of search or store behavior must be defined', } ); /** * Memory type configuration schema */ export const MemoryTypeConfigSchema = z.object({ name: z .string() .min(1, 'Memory type name is required') .regex(/^[a-zA-Z][a-zA-Z0-9_]*$/, 'Name must be a valid identifier'), collection_name: z .string() .min(1, 'Collection name is required') .regex(/^[a-zA-Z][a-zA-Z0-9_]*$/, 'Collection name must be a valid identifier'), description: z.string().default(''), priority: z.number().int().min(0).default(0), embedding: EmbeddingConfigSchema, vector_store: VectorStoreConfigSchema, schema: SchemaConfigSchema, behavior: BehaviorConfigSchema, }); /** * Global configuration schema */ export const GlobalConfigSchema = z.object({ enabled: z.boolean().default(true), fallback_to_default: z.boolean().default(true), max_memory_types: z.number().positive().optional(), id_range_size: z.number().positive().default(100000), }); /** * Advanced configuration schema */ export const AdvancedConfigSchema = z.object({ orchestrator: z .object({ decision_algorithm: z .enum(['priority_weighted', 'round_robin', 'semantic_routing']) .default('priority_weighted'), parallel_search: z.boolean().default(true), max_concurrent_searches: z.number().positive().default(3), search_timeout_ms: z.number().positive().default(5000), }) .optional(), performance: z .object({ cache_enabled: z.boolean().default(true), cache_ttl_seconds: z.number().positive().default(300), batch_operations: z.boolean().default(true), async_storage: z.boolean().default(true), }) .optional(), monitoring: z .object({ enable_metrics: z.boolean().default(true), log_decisions: z.boolean().default(true), performance_tracking: z.boolean().default(true), usage_analytics: z.boolean().default(true), }) .optional(), error_handling: z .object({ retry_attempts: z.number().int().min(0).default(3), retry_delay_ms: z.number().positive().default(1000), fallback_on_error: z.boolean().default(true), strict_validation: z.boolean().default(false), }) .optional(), }); /** * Main custom memory configuration schema */ export const CustomMemoryConfigSchema = z .object({ global: GlobalConfigSchema, custom_memory_types: z .array(MemoryTypeConfigSchema) .min(1, 'At least one memory type must be defined'), advanced: AdvancedConfigSchema.optional(), }) .refine( data => { // Validate unique memory type names const names = data.custom_memory_types.map(t => t.name); const uniqueNames = new Set(names); if (names.length !== uniqueNames.size) { return false; } // Validate unique collection names const collections = data.custom_memory_types.map(t => t.collection_name); const uniqueCollections = new Set(collections); if (collections.length !== uniqueCollections.size) { return false; } // Validate max memory types limit if ( data.global.max_memory_types && data.custom_memory_types.length > data.global.max_memory_types ) { return false; } return true; }, { message: 'Memory type names and collection names must be unique, and count must not exceed max_memory_types', } ); /** * Type inference for configuration objects */ export type FieldConfig = z.infer<typeof FieldConfigSchema>; export type SchemaConfig = z.infer<typeof SchemaConfigSchema>; export type EmbeddingConfig = z.infer<typeof EmbeddingConfigSchema>; export type VectorStoreConfig = z.infer<typeof VectorStoreConfigSchema>; export type BehaviorTrigger = z.infer<typeof BehaviorTriggerSchema>; export type BehaviorConfig = z.infer<typeof BehaviorConfigSchema>; export type MemoryTypeConfig = z.infer<typeof MemoryTypeConfigSchema>; export type GlobalConfig = z.infer<typeof GlobalConfigSchema>; export type AdvancedConfig = z.infer<typeof AdvancedConfigSchema>; export type CustomMemoryConfig = z.infer<typeof CustomMemoryConfigSchema>; /** * Validation errors */ export class ConfigValidationError extends Error { constructor( message: string, public readonly issues?: z.ZodIssue[] ) { super(message); this.name = 'ConfigValidationError'; } } /** * Validate custom memory configuration */ export function validateCustomMemoryConfig(config: unknown): CustomMemoryConfig { const result = CustomMemoryConfigSchema.safeParse(config); if (!result.success) { throw new ConfigValidationError('Configuration validation failed', result.error.issues); } return result.data; } /** * Validate a single memory type configuration */ export function validateMemoryTypeConfig(config: unknown): MemoryTypeConfig { const result = MemoryTypeConfigSchema.safeParse(config); if (!result.success) { throw new ConfigValidationError( 'Memory type configuration validation failed', result.error.issues ); } return result.data; } /** * Default configurations for common use cases */ export const DEFAULT_CONFIGURATIONS = { research_notes: { name: 'research_notes', collection_name: 'research_collection', description: 'Stores research findings and references', priority: 1, embedding: { model: 'text-embedding-3-small' as const, dimension: 1536, batch_size: 100, timeout_ms: 30000, }, vector_store: { similarity_threshold: 0.7, max_results: 10, rerank: true, }, schema: { version: '1.0', custom_fields: [ { name: 'source_url', type: 'string' as const, required: false, validation: 'url' as const, description: 'URL of the research source', }, { name: 'research_domain', type: 'string' as const, required: true, validation: 'non_empty' as const, description: 'Domain/field of research', }, { name: 'confidence_score', type: 'number' as const, required: false, validation: 'range' as const, min_value: 0.0, max_value: 1.0, default: 0.5, }, ], }, behavior: { search: { keyword_triggers: ['research', 'study', 'paper', 'academic'], pattern_triggers: ['.*research.*', '.*study shows.*'], semantic_triggers: ['asking about academic topics', 'requesting research information'], }, store: { keyword_triggers: ['learned', 'discovered', 'research shows'], pattern_triggers: ['.*according to.*', '.*study found.*'], semantic_triggers: ['sharing research findings', 'providing academic information'], }, }, }, code_snippets: { name: 'code_snippets', collection_name: 'code_collection', description: 'Stores code examples and implementation patterns', priority: 2, embedding: { model: 'text-embedding-3-small' as const, dimension: 1536, preprocessing: { normalize_whitespace: true, preserve_structure: true, include_comments: true, }, }, vector_store: { similarity_threshold: 0.8, max_results: 5, rerank: false, }, schema: { version: '1.0', custom_fields: [ { name: 'language', type: 'string' as const, required: true, validation: 'enum' as const, allowed_values: ['javascript', 'typescript', 'python', 'java', 'go', 'rust', 'other'], }, { name: 'function_name', type: 'string' as const, required: false, validation: 'identifier' as const, }, { name: 'complexity_score', type: 'number' as const, required: false, validation: 'range' as const, min_value: 1, max_value: 10, }, ], }, behavior: { search: { keyword_triggers: ['code', 'implementation', 'function', 'example'], pattern_triggers: ['.*how to implement.*', '.*code example.*', '.*function.*'], semantic_triggers: ['asking for code help', 'requesting implementation examples'], }, store: { keyword_triggers: ['function', 'class', 'method', 'implementation'], pattern_triggers: ['```.*```', '.*\\.js:|.*\\.py:|.*\\.ts:'], field_extraction: { language: 'detect_programming_language(text)', function_name: 'extract_function_names(text)', complexity_score: 'calculate_code_complexity(text)', }, }, }, }, } as const;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/campfirein/cipher'

If you have feedback or need assistance with the MCP directory API, please join our Discord server