{
  "$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
        }
      }
    }
  }
}
