{ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "https://companion.ai/config-schema.json", "title": "Companion AI Configuration", "description": "Configuration schema for Personal Companion AI", "type": "object", "required": ["companion", "vault", "rag", "model", "api", "ui", "logging", "security"], "properties": { "companion": { "type": "object", "title": "Companion Settings", "required": ["name", "persona", "memory", "chat"], "properties": { "name": { "type": "string", "description": "Display name for the companion", "default": "SAN" }, "persona": { "type": "object", "required": ["role", "tone", "style", "boundaries"], "properties": { "role": { "type": "string", "description": "Role of the companion", "enum": ["companion", "advisor", "reflector"], "default": "companion" }, "tone": { "type": "string", "description": "Communication tone", "enum": ["reflective", "supportive", "analytical", "mixed"], "default": "reflective" }, "style": { "type": "string", "description": "Interaction style", "enum": ["questioning", "supportive", "direct", "mixed"], "default": "questioning" }, "boundaries": { "type": "array", "description": "Behavioral guardrails", "items": { "type": "string", "enum": [ "does_not_impersonate_user", "no_future_predictions", "no_medical_or_legal_advice" ] }, "default": ["does_not_impersonate_user", "no_future_predictions", "no_medical_or_legal_advice"] } } }, "memory": { "type": "object", "required": ["session_turns", "persistent_store", "summarize_after"], "properties": { "session_turns": { "type": "integer", "description": "Messages to keep in context", "minimum": 1, "maximum": 100, "default": 20 }, "persistent_store": { "type": "string", "description": "SQLite database path", "default": "~/.companion/memory.db" }, "summarize_after": { "type": "integer", "description": "Summarize history after N turns", "minimum": 5, "maximum": 50, "default": 10 } } }, "chat": { "type": "object", "required": ["streaming", "max_response_tokens", "default_temperature", "allow_temperature_override"], "properties": { "streaming": { "type": "boolean", "description": "Stream responses in real-time", "default": true }, "max_response_tokens": { "type": "integer", "description": "Max tokens per response", "minimum": 256, "maximum": 8192, "default": 2048 }, "default_temperature": { "type": "number", "description": "Creativity level (0.0=deterministic, 2.0=creative)", "minimum": 0.0, "maximum": 2.0, "default": 0.7 }, "allow_temperature_override": { "type": "boolean", "description": "Let users adjust temperature", "default": true } } } } }, "vault": { "type": "object", "title": "Vault Settings", "required": ["path", "indexing", "chunking_rules"], "properties": { "path": { "type": "string", "description": "Absolute path to Obsidian vault root" }, "indexing": { "type": "object", "required": ["auto_sync", "auto_sync_interval_minutes", "watch_fs_events", "file_patterns", "deny_dirs", "deny_patterns"], "properties": { "auto_sync": { "type": "boolean", "description": "Enable automatic syncing", "default": true }, "auto_sync_interval_minutes": { "type": "integer", "description": "Minutes between full syncs", "minimum": 60, "maximum": 10080, "default": 1440 }, "watch_fs_events": { "type": "boolean", "description": "Watch for file system changes", "default": true }, "file_patterns": { "type": "array", "description": "File patterns to index", "items": { "type": "string" }, "default": ["*.md"] }, "deny_dirs": { "type": "array", "description": "Directories to skip", "items": { "type": "string" }, "default": [".obsidian", ".trash", "zzz-Archive", ".git", ".logseq"] }, "deny_patterns": { "type": "array", "description": "File patterns to ignore", "items": { "type": "string" }, "default": ["*.tmp", "*.bak", "*conflict*", ".*"] } } }, "chunking_rules": { "type": "object", "description": "Per-directory chunking rules (key: glob pattern, value: rule)", "additionalProperties": { "type": "object", "required": ["strategy", "chunk_size", "chunk_overlap"], "properties": { "strategy": { "type": "string", "enum": ["sliding_window", "section"], "description": "Chunking strategy" }, "chunk_size": { "type": "integer", "description": "Target chunk size in words", "minimum": 50, "maximum": 2000 }, "chunk_overlap": { "type": "integer", "description": "Overlap between chunks in words", "minimum": 0, "maximum": 500 }, "section_tags": { "type": "array", "description": "Tags that mark sections (for section strategy)", "items": { "type": "string" } } } } } } }, "rag": { "type": "object", "title": "RAG Settings", "required": ["embedding", "vector_store", "search"], "properties": { "embedding": { "type": "object", "required": ["provider", "model", "base_url", "dimensions", "batch_size"], "properties": { "provider": { "type": "string", "description": "Embedding service provider", "enum": ["ollama"], "default": "ollama" }, "model": { "type": "string", "description": "Model name for embeddings", "enum": ["mxbai-embed-large", "nomic-embed-text", "all-minilm"], "default": "mxbai-embed-large" }, "base_url": { "type": "string", "description": "Provider API endpoint", "format": "uri", "default": "http://localhost:11434" }, "dimensions": { "type": "integer", "description": "Embedding vector size", "enum": [384, 768, 1024], "default": 1024 }, "batch_size": { "type": "integer", "description": "Texts per embedding batch", "minimum": 1, "maximum": 256, "default": 32 } } }, "vector_store": { "type": "object", "required": ["type", "path"], "properties": { "type": { "type": "string", "description": "Vector database type", "enum": ["lancedb"], "default": "lancedb" }, "path": { "type": "string", "description": "Storage path", "default": "~/.companion/vectors.lance" } } }, "search": { "type": "object", "required": ["default_top_k", "max_top_k", "similarity_threshold", "hybrid_search", "filters"], "properties": { "default_top_k": { "type": "integer", "description": "Default results to retrieve", "minimum": 1, "maximum": 100, "default": 8 }, "max_top_k": { "type": "integer", "description": "Maximum allowed results", "minimum": 1, "maximum": 100, "default": 20 }, "similarity_threshold": { "type": "number", "description": "Minimum relevance score (0-1)", "minimum": 0.0, "maximum": 1.0, "default": 0.75 }, "hybrid_search": { "type": "object", "required": ["enabled", "keyword_weight", "semantic_weight"], "properties": { "enabled": { "type": "boolean", "description": "Combine keyword + semantic search", "default": true }, "keyword_weight": { "type": "number", "description": "Keyword search weight", "minimum": 0.0, "maximum": 1.0, "default": 0.3 }, "semantic_weight": { "type": "number", "description": "Semantic search weight", "minimum": 0.0, "maximum": 1.0, "default": 0.7 } } }, "filters": { "type": "object", "required": ["date_range_enabled", "tag_filter_enabled", "directory_filter_enabled"], "properties": { "date_range_enabled": { "type": "boolean", "description": "Enable date range filtering", "default": true }, "tag_filter_enabled": { "type": "boolean", "description": "Enable tag filtering", "default": true }, "directory_filter_enabled": { "type": "boolean", "description": "Enable directory filtering", "default": true } } } } } } }, "model": { "type": "object", "title": "Model Settings", "required": ["inference", "fine_tuning", "retrain_schedule"], "properties": { "inference": { "type": "object", "required": ["backend", "model_path", "context_length", "gpu_layers", "batch_size", "threads"], "properties": { "backend": { "type": "string", "description": "Inference engine", "enum": ["llama.cpp", "vllm"], "default": "llama.cpp" }, "model_path": { "type": "string", "description": "Path to GGUF or HF model", "default": "~/.companion/models/companion-7b-q4.gguf" }, "context_length": { "type": "integer", "description": "Max context tokens", "minimum": 2048, "maximum": 32768, "default": 8192 }, "gpu_layers": { "type": "integer", "description": "Layers to offload to GPU (0 for CPU-only)", "minimum": 0, "maximum": 100, "default": 35 }, "batch_size": { "type": "integer", "description": "Inference batch size", "minimum": 1, "maximum": 2048, "default": 512 }, "threads": { "type": "integer", "description": "CPU threads for inference", "minimum": 1, "maximum": 64, "default": 8 } } }, "fine_tuning": { "type": "object", "required": ["base_model", "output_dir", "lora_rank", "lora_alpha", "learning_rate", "batch_size", "gradient_accumulation_steps", "num_epochs", "warmup_steps", "save_steps", "eval_steps", "training_data_path", "validation_split"], "properties": { "base_model": { "type": "string", "description": "Base model for fine-tuning", "default": "unsloth/Meta-Llama-3.1-8B-Instruct-bnb-4bit" }, "output_dir": { "type": "string", "description": "Training outputs directory", "default": "~/.companion/training" }, "lora_rank": { "type": "integer", "description": "LoRA rank (higher = more capacity, more VRAM)", "minimum": 4, "maximum": 128, "default": 16 }, "lora_alpha": { "type": "integer", "description": "LoRA alpha (scaling factor, typically 2x rank)", "minimum": 8, "maximum": 256, "default": 32 }, "learning_rate": { "type": "number", "description": "Training learning rate", "minimum": 1e-6, "maximum": 1e-3, "default": 0.0002 }, "batch_size": { "type": "integer", "description": "Per-device batch size", "minimum": 1, "maximum": 32, "default": 4 }, "gradient_accumulation_steps": { "type": "integer", "description": "Steps to accumulate before update", "minimum": 1, "maximum": 64, "default": 4 }, "num_epochs": { "type": "integer", "description": "Training epochs", "minimum": 1, "maximum": 20, "default": 3 }, "warmup_steps": { "type": "integer", "description": "Learning rate warmup steps", "minimum": 0, "maximum": 10000, "default": 100 }, "save_steps": { "type": "integer", "description": "Checkpoint frequency", "minimum": 10, "maximum": 10000, "default": 500 }, "eval_steps": { "type": "integer", "description": "Evaluation frequency", "minimum": 10, "maximum": 10000, "default": 250 }, "training_data_path": { "type": "string", "description": "Training data directory", "default": "~/.companion/training_data/" }, "validation_split": { "type": "number", "description": "Fraction of data for validation", "minimum": 0.0, "maximum": 0.5, "default": 0.1 } } }, "retrain_schedule": { "type": "object", "required": ["auto_reminder", "default_interval_days", "reminder_channels"], "properties": { "auto_reminder": { "type": "boolean", "description": "Enable retrain reminders", "default": true }, "default_interval_days": { "type": "integer", "description": "Days between retrain reminders", "minimum": 30, "maximum": 365, "default": 90 }, "reminder_channels": { "type": "array", "description": "Where to show reminders", "items": { "type": "string", "enum": ["chat_stream", "log", "ui"] }, "default": ["chat_stream", "log"] } } } } }, "api": { "type": "object", "title": "API Settings", "required": ["host", "port", "cors_origins", "auth"], "properties": { "host": { "type": "string", "description": "Bind address (use 0.0.0.0 for LAN access)", "default": "127.0.0.1" }, "port": { "type": "integer", "description": "HTTP port", "minimum": 1, "maximum": 65535, "default": 7373 }, "cors_origins": { "type": "array", "description": "Allowed CORS origins", "items": { "type": "string", "format": "uri" }, "default": ["http://localhost:5173"] }, "auth": { "type": "object", "required": ["enabled"], "properties": { "enabled": { "type": "boolean", "description": "Enable API key authentication", "default": false } } } } }, "ui": { "type": "object", "title": "UI Settings", "required": ["web", "cli"], "properties": { "web": { "type": "object", "required": ["enabled", "theme", "features"], "properties": { "enabled": { "type": "boolean", "description": "Enable web interface", "default": true }, "theme": { "type": "string", "description": "UI theme", "enum": ["obsidian"], "default": "obsidian" }, "features": { "type": "object", "required": ["streaming", "citations", "source_preview"], "properties": { "streaming": { "type": "boolean", "description": "Real-time response streaming", "default": true }, "citations": { "type": "boolean", "description": "Show source citations", "default": true }, "source_preview": { "type": "boolean", "description": "Preview source snippets", "default": true } } } } }, "cli": { "type": "object", "required": ["enabled", "rich_output"], "properties": { "enabled": { "type": "boolean", "description": "Enable CLI interface", "default": true }, "rich_output": { "type": "boolean", "description": "Rich terminal formatting", "default": true } } } } }, "logging": { "type": "object", "title": "Logging Settings", "required": ["level", "file", "max_size_mb", "backup_count"], "properties": { "level": { "type": "string", "description": "Log level", "enum": ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], "default": "INFO" }, "file": { "type": "string", "description": "Log file path", "default": "~/.companion/logs/companion.log" }, "max_size_mb": { "type": "integer", "description": "Max log file size in MB", "minimum": 10, "maximum": 1000, "default": 100 }, "backup_count": { "type": "integer", "description": "Number of rotated backups", "minimum": 1, "maximum": 20, "default": 5 } } }, "security": { "type": "object", "title": "Security Settings", "required": ["local_only", "vault_path_traversal_check", "sensitive_content_detection", "sensitive_patterns", "require_confirmation_for_external_apis"], "properties": { "local_only": { "type": "boolean", "description": "Block external API calls", "default": true }, "vault_path_traversal_check": { "type": "boolean", "description": "Prevent path traversal attacks", "default": true }, "sensitive_content_detection": { "type": "boolean", "description": "Tag sensitive content", "default": true }, "sensitive_patterns": { "type": "array", "description": "Tags considered sensitive", "items": { "type": "string" }, "default": ["#mentalhealth", "#physicalhealth", "#finance", "#Relations"] }, "require_confirmation_for_external_apis": { "type": "boolean", "description": "Confirm before external API calls", "default": true } } } } }