Move monitor config in its own section

This commit is contained in:
Yiorgis Gozadinos 2025-10-29 11:23:56 +02:00
parent e6e3273cae
commit ad1ee52a27
No known key found for this signature in database
8 changed files with 64 additions and 60 deletions

View file

@ -55,14 +55,16 @@ environment: production
storage: storage:
data_dir: "" # Empty = use default platform location data_dir: "" # Empty = use default platform location
monitor_directories:
- /path/to/documents
- /another/path
monitor_ignore_patterns: [] # Gitignore-style patterns to exclude
monitor_include_patterns: [] # Gitignore-style patterns to include
disable_autocreate: false disable_autocreate: false
vacuum_retention_seconds: 60 vacuum_retention_seconds: 60
monitor:
directories:
- /path/to/documents
- /another/path
ignore_patterns: [] # Gitignore-style patterns to exclude
include_patterns: [] # Gitignore-style patterns to include
lancedb: lancedb:
uri: "" # Empty for local, or db://, s3://, az://, gs:// uri: "" # Empty for local, or db://, s3://, az://, gs://
api_key: "" api_key: ""
@ -163,8 +165,8 @@ export OLLAMA_BASE_URL=http://localhost:11434
Set directories to monitor for automatic indexing: Set directories to monitor for automatic indexing:
```yaml ```yaml
storage: monitor:
monitor_directories: directories:
- /path/to/documents - /path/to/documents
- /another_path/to/documents - /another_path/to/documents
``` ```
@ -174,19 +176,19 @@ storage:
Use gitignore-style patterns to control which files are monitored: Use gitignore-style patterns to control which files are monitored:
```yaml ```yaml
storage: monitor:
monitor_directories: directories:
- /path/to/documents - /path/to/documents
# Exclude specific files or directories # Exclude specific files or directories
monitor_ignore_patterns: ignore_patterns:
- "*draft*" # Ignore files with "draft" in the name - "*draft*" # Ignore files with "draft" in the name
- "temp/" # Ignore temp directory - "temp/" # Ignore temp directory
- "**/archive/**" # Ignore all archive directories - "**/archive/**" # Ignore all archive directories
- "*.backup" # Ignore backup files - "*.backup" # Ignore backup files
# Only include specific files (whitelist mode) # Only include specific files (whitelist mode)
monitor_include_patterns: include_patterns:
- "*.md" # Only markdown files - "*.md" # Only markdown files
- "*.pdf" # Only PDF files - "*.pdf" # Only PDF files
- "**/docs/**" # Only files in docs directories - "**/docs/**" # Only files in docs directories
@ -203,18 +205,20 @@ storage:
```yaml ```yaml
# Only monitor markdown documentation, but ignore drafts # Only monitor markdown documentation, but ignore drafts
monitor_include_patterns: monitor:
- "*.md" include_patterns:
monitor_ignore_patterns: - "*.md"
- "*draft*" ignore_patterns:
- "*WIP*" - "*draft*"
- "*WIP*"
# Monitor all supported files except in specific directories # Monitor all supported files except in specific directories
monitor_ignore_patterns: monitor:
- "node_modules/" ignore_patterns:
- ".git/" - "node_modules/"
- "**/test/**" - ".git/"
- "**/temp/**" - "**/test/**"
- "**/temp/**"
``` ```
Patterns follow [gitignore syntax](https://git-scm.com/docs/gitignore#_pattern_format): Patterns follow [gitignore syntax](https://git-scm.com/docs/gitignore#_pattern_format):
@ -589,8 +593,8 @@ This will read your current environment variables and generate a `haiku.rag.yaml
When migrating from environment variables, list values like `MONITOR_DIRECTORIES` that were comma-separated (`/path1,/path2`) will be converted to proper YAML lists. In YAML, always use list syntax: When migrating from environment variables, list values like `MONITOR_DIRECTORIES` that were comma-separated (`/path1,/path2`) will be converted to proper YAML lists. In YAML, always use list syntax:
```yaml ```yaml
storage: monitor:
monitor_directories: directories:
- /path/to/dir1 - /path/to/dir1
- /path/to/dir2 - /path/to/dir2
``` ```

View file

@ -48,8 +48,8 @@ This will start file monitoring, MCP server on port 8001, and A2A server on port
Configure directories to monitor in your `haiku.rag.yaml`: Configure directories to monitor in your `haiku.rag.yaml`:
```yaml ```yaml
storage: monitor:
monitor_directories: directories:
- /path/to/documents - /path/to/documents
- /another/path - /another/path
``` ```
@ -71,18 +71,18 @@ haiku-rag serve --monitor
You can filter which files to monitor using gitignore-style patterns: You can filter which files to monitor using gitignore-style patterns:
```yaml ```yaml
storage: monitor:
monitor_directories: directories:
- /path/to/documents - /path/to/documents
# Ignore patterns (exclude files) # Ignore patterns (exclude files)
monitor_ignore_patterns: ignore_patterns:
- "*draft*" # Ignore draft files - "*draft*" # Ignore draft files
- "temp/" # Ignore temp directory - "temp/" # Ignore temp directory
- "**/archive/**" # Ignore archive directories - "**/archive/**" # Ignore archive directories
# Include patterns (whitelist files) # Include patterns (whitelist files)
monitor_include_patterns: include_patterns:
- "*.md" # Only markdown files - "*.md" # Only markdown files
- "**/docs/**" # Files in docs directories - "**/docs/**" # Files in docs directories
``` ```

View file

@ -11,6 +11,7 @@ from haiku.rag.config.models import (
AppConfig, AppConfig,
EmbeddingsConfig, EmbeddingsConfig,
LanceDBConfig, LanceDBConfig,
MonitorConfig,
OllamaConfig, OllamaConfig,
ProcessingConfig, ProcessingConfig,
ProvidersConfig, ProvidersConfig,
@ -25,6 +26,7 @@ __all__ = [
"Config", "Config",
"AppConfig", "AppConfig",
"StorageConfig", "StorageConfig",
"MonitorConfig",
"LanceDBConfig", "LanceDBConfig",
"EmbeddingsConfig", "EmbeddingsConfig",
"RerankingConfig", "RerankingConfig",

View file

@ -50,10 +50,14 @@ def generate_default_config() -> dict:
"environment": "production", "environment": "production",
"storage": { "storage": {
"data_dir": "", "data_dir": "",
"monitor_directories": [],
"disable_autocreate": False, "disable_autocreate": False,
"vacuum_retention_seconds": 60, "vacuum_retention_seconds": 60,
}, },
"monitor": {
"directories": [],
"ignore_patterns": [],
"include_patterns": [],
},
"lancedb": {"uri": "", "api_key": "", "region": ""}, "lancedb": {"uri": "", "api_key": "", "region": ""},
"embeddings": { "embeddings": {
"provider": "ollama", "provider": "ollama",
@ -88,7 +92,7 @@ def load_config_from_env() -> dict:
env_mappings = { env_mappings = {
"ENV": "environment", "ENV": "environment",
"DEFAULT_DATA_DIR": ("storage", "data_dir"), "DEFAULT_DATA_DIR": ("storage", "data_dir"),
"MONITOR_DIRECTORIES": ("storage", "monitor_directories"), "MONITOR_DIRECTORIES": ("monitor", "directories"),
"DISABLE_DB_AUTOCREATE": ("storage", "disable_autocreate"), "DISABLE_DB_AUTOCREATE": ("storage", "disable_autocreate"),
"VACUUM_RETENTION_SECONDS": ("storage", "vacuum_retention_seconds"), "VACUUM_RETENTION_SECONDS": ("storage", "vacuum_retention_seconds"),
"LANCEDB_URI": ("lancedb", "uri"), "LANCEDB_URI": ("lancedb", "uri"),

View file

@ -7,13 +7,16 @@ from haiku.rag.utils import get_default_data_dir
class StorageConfig(BaseModel): class StorageConfig(BaseModel):
data_dir: Path = Field(default_factory=get_default_data_dir) data_dir: Path = Field(default_factory=get_default_data_dir)
monitor_directories: list[Path] = []
monitor_ignore_patterns: list[str] = []
monitor_include_patterns: list[str] = []
disable_autocreate: bool = False disable_autocreate: bool = False
vacuum_retention_seconds: int = 60 vacuum_retention_seconds: int = 60
class MonitorConfig(BaseModel):
directories: list[Path] = []
ignore_patterns: list[str] = []
include_patterns: list[str] = []
class LanceDBConfig(BaseModel): class LanceDBConfig(BaseModel):
uri: str = "" uri: str = ""
api_key: str = "" api_key: str = ""
@ -74,6 +77,7 @@ class A2AConfig(BaseModel):
class AppConfig(BaseModel): class AppConfig(BaseModel):
environment: str = "production" environment: str = "production"
storage: StorageConfig = Field(default_factory=StorageConfig) storage: StorageConfig = Field(default_factory=StorageConfig)
monitor: MonitorConfig = Field(default_factory=MonitorConfig)
lancedb: LanceDBConfig = Field(default_factory=LanceDBConfig) lancedb: LanceDBConfig = Field(default_factory=LanceDBConfig)
embeddings: EmbeddingsConfig = Field(default_factory=EmbeddingsConfig) embeddings: EmbeddingsConfig = Field(default_factory=EmbeddingsConfig)
reranking: RerankingConfig = Field(default_factory=RerankingConfig) reranking: RerankingConfig = Field(default_factory=RerankingConfig)

View file

@ -64,10 +64,10 @@ class FileWatcher:
client: HaikuRAG, client: HaikuRAG,
config: AppConfig = Config, config: AppConfig = Config,
): ):
self.paths = config.storage.monitor_directories self.paths = config.monitor.directories
self.client = client self.client = client
self.ignore_patterns = config.storage.monitor_ignore_patterns or None self.ignore_patterns = config.monitor.ignore_patterns or None
self.include_patterns = config.storage.monitor_include_patterns or None self.include_patterns = config.monitor.include_patterns or None
async def observe(self): async def observe(self):
logger.info(f"Watching files in {self.paths}") logger.info(f"Watching files in {self.paths}")

View file

@ -5,7 +5,7 @@ from unittest.mock import AsyncMock
import pytest import pytest
from haiku.rag.client import HaikuRAG from haiku.rag.client import HaikuRAG
from haiku.rag.config import AppConfig, StorageConfig from haiku.rag.config import AppConfig, MonitorConfig
from haiku.rag.monitor import FileWatcher from haiku.rag.monitor import FileWatcher
from haiku.rag.store.models.document import Document from haiku.rag.store.models.document import Document
@ -23,9 +23,7 @@ async def test_file_watcher_upsert_document():
mock_client.create_document_from_source.return_value = mock_doc mock_client.create_document_from_source.return_value = mock_doc
mock_client.get_document_by_uri.return_value = None # No existing document mock_client.get_document_by_uri.return_value = None # No existing document
test_config = AppConfig( test_config = AppConfig(monitor=MonitorConfig(directories=[temp_path.parent]))
storage=StorageConfig(monitor_directories=[temp_path.parent])
)
watcher = FileWatcher(client=mock_client, config=test_config) watcher = FileWatcher(client=mock_client, config=test_config)
result = await watcher._upsert_document(temp_path) result = await watcher._upsert_document(temp_path)
@ -53,9 +51,7 @@ async def test_file_watcher_upsert_existing_document():
mock_client.get_document_by_uri.return_value = existing_doc mock_client.get_document_by_uri.return_value = existing_doc
mock_client.create_document_from_source.return_value = updated_doc mock_client.create_document_from_source.return_value = updated_doc
test_config = AppConfig( test_config = AppConfig(monitor=MonitorConfig(directories=[temp_path.parent]))
storage=StorageConfig(monitor_directories=[temp_path.parent])
)
watcher = FileWatcher(client=mock_client, config=test_config) watcher = FileWatcher(client=mock_client, config=test_config)
result = await watcher._upsert_document(temp_path) result = await watcher._upsert_document(temp_path)
@ -76,9 +72,7 @@ async def test_file_watcher_delete_document():
mock_client.get_document_by_uri.return_value = existing_doc mock_client.get_document_by_uri.return_value = existing_doc
mock_client.delete_document.return_value = True mock_client.delete_document.return_value = True
test_config = AppConfig( test_config = AppConfig(monitor=MonitorConfig(directories=[temp_path.parent]))
storage=StorageConfig(monitor_directories=[temp_path.parent])
)
watcher = FileWatcher(client=mock_client, config=test_config) watcher = FileWatcher(client=mock_client, config=test_config)
await watcher._delete_document(temp_path) await watcher._delete_document(temp_path)
@ -95,9 +89,7 @@ async def test_file_watcher_delete_nonexistent_document():
mock_client = AsyncMock(spec=HaikuRAG) mock_client = AsyncMock(spec=HaikuRAG)
mock_client.get_document_by_uri.return_value = None mock_client.get_document_by_uri.return_value = None
test_config = AppConfig( test_config = AppConfig(monitor=MonitorConfig(directories=[temp_path.parent]))
storage=StorageConfig(monitor_directories=[temp_path.parent])
)
watcher = FileWatcher(client=mock_client, config=test_config) watcher = FileWatcher(client=mock_client, config=test_config)
await watcher._delete_document(temp_path) await watcher._delete_document(temp_path)
@ -210,9 +202,7 @@ async def test_file_watcher_with_ignore_patterns():
mock_client.get_document_by_uri.return_value = None mock_client.get_document_by_uri.return_value = None
test_config = AppConfig( test_config = AppConfig(
storage=StorageConfig( monitor=MonitorConfig(directories=[temp_path], ignore_patterns=["draft*"])
monitor_directories=[temp_path], monitor_ignore_patterns=["draft*"]
)
) )
watcher = FileWatcher(client=mock_client, config=test_config) watcher = FileWatcher(client=mock_client, config=test_config)
@ -243,9 +233,7 @@ async def test_file_watcher_with_include_patterns():
mock_client.get_document_by_uri.return_value = None mock_client.get_document_by_uri.return_value = None
test_config = AppConfig( test_config = AppConfig(
storage=StorageConfig( monitor=MonitorConfig(directories=[temp_path], include_patterns=["*.md"])
monitor_directories=[temp_path], monitor_include_patterns=["*.md"]
)
) )
watcher = FileWatcher(client=mock_client, config=test_config) watcher = FileWatcher(client=mock_client, config=test_config)

View file

@ -86,7 +86,9 @@ async def test_config_validation_on_db_load(temp_db_path):
def test_monitor_filter_patterns_config(): def test_monitor_filter_patterns_config():
"""Test that monitor filter patterns are available in config.""" """Test that monitor filter patterns are available in config."""
assert hasattr(Config.storage, "monitor_ignore_patterns") assert hasattr(Config.monitor, "ignore_patterns")
assert hasattr(Config.storage, "monitor_include_patterns") assert hasattr(Config.monitor, "include_patterns")
assert isinstance(Config.storage.monitor_ignore_patterns, list) assert hasattr(Config.monitor, "directories")
assert isinstance(Config.storage.monitor_include_patterns, list) assert isinstance(Config.monitor.ignore_patterns, list)
assert isinstance(Config.monitor.include_patterns, list)
assert isinstance(Config.monitor.directories, list)