diff --git a/pyproject.toml b/pyproject.toml index 49237c9a..30dbb443 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,7 +56,7 @@ dev = [ "mkdocs>=1.6.1", "mkdocs-material>=9.6.14", "pre-commit>=4.2.0", - "pyright>=1.1.402", + "pyright>=1.1.403", "pytest>=8.4.0", "pytest-asyncio>=1.0.0", "pytest-cov>=6.2.1", diff --git a/src/haiku/rag/store/engine.py b/src/haiku/rag/store/engine.py index cdf1d2ca..4133b6dc 100644 --- a/src/haiku/rag/store/engine.py +++ b/src/haiku/rag/store/engine.py @@ -60,11 +60,28 @@ class Store: ) """) + # Create settings table for storing current configuration + db.execute(""" + CREATE TABLE IF NOT EXISTS settings ( + id INTEGER PRIMARY KEY DEFAULT 1, + settings TEXT NOT NULL DEFAULT '{}' + ) + """) + # Create indexes for better performance db.execute( "CREATE INDEX IF NOT EXISTS idx_chunks_document_id ON chunks(document_id)" ) + # Save current settings to the new database + from haiku.rag.config import Config + + settings_json = Config.model_dump_json() + db.execute( + "INSERT OR IGNORE INTO settings (id, settings) VALUES (1, ?)", + (settings_json,), + ) + db.commit() return db diff --git a/src/haiku/rag/store/repositories/settings.py b/src/haiku/rag/store/repositories/settings.py new file mode 100644 index 00000000..d51cb0d5 --- /dev/null +++ b/src/haiku/rag/store/repositories/settings.py @@ -0,0 +1,36 @@ +import json +from typing import Any + +from haiku.rag.store.engine import Store + + +class SettingsRepository: + def __init__(self, store: Store): + self.store = store + + def get(self) -> dict[str, Any]: + """Get all settings from the database.""" + if self.store._connection is None: + raise ValueError("Store connection is not available") + + cursor = self.store._connection.execute("SELECT settings FROM settings LIMIT 1") + row = cursor.fetchone() + if row: + return json.loads(row[0]) + return {} + + def save(self) -> None: + """Sync settings from the current AppConfig to database.""" + if self.store._connection is None: + raise ValueError("Store connection is not available") + + from haiku.rag.config import Config + + settings_json = Config.model_dump_json() + + self.store._connection.execute( + "INSERT INTO settings (id, settings) VALUES (1, ?) ON CONFLICT(id) DO UPDATE SET settings = excluded.settings", + (settings_json,), + ) + + self.store._connection.commit() diff --git a/tests/test_settings.py b/tests/test_settings.py new file mode 100644 index 00000000..aaec6ac5 --- /dev/null +++ b/tests/test_settings.py @@ -0,0 +1,33 @@ +from haiku.rag.config import Config +from haiku.rag.store.engine import Store +from haiku.rag.store.repositories.settings import SettingsRepository + + +def test_settings_table_populated_on_store_init(): + """Test that settings table is populated with current config when store is initialized.""" + + store = Store(":memory:") + settings_repo = SettingsRepository(store) + + db_settings = settings_repo.get() + config_dict = Config.model_dump(mode="json") + + assert db_settings == config_dict + + store.close() + + +def test_settings_save_and_retrieve(): + """Test saving and retrieving settings after config change.""" + store = Store(":memory:") + settings_repo = SettingsRepository(store) + + original_chunk_size = Config.CHUNK_SIZE + Config.CHUNK_SIZE = 2 * original_chunk_size + + settings_repo.save() + retrieved_settings = settings_repo.get() + assert retrieved_settings["CHUNK_SIZE"] == 2 * original_chunk_size + + Config.CHUNK_SIZE = original_chunk_size + store.close() diff --git a/uv.lock b/uv.lock index 088ad51f..fd6b3649 100644 --- a/uv.lock +++ b/uv.lock @@ -881,7 +881,7 @@ dev = [ { name = "mkdocs", specifier = ">=1.6.1" }, { name = "mkdocs-material", specifier = ">=9.6.14" }, { name = "pre-commit", specifier = ">=4.2.0" }, - { name = "pyright", specifier = ">=1.1.402" }, + { name = "pyright", specifier = ">=1.1.403" }, { name = "pytest", specifier = ">=8.4.0" }, { name = "pytest-asyncio", specifier = ">=1.0.0" }, { name = "pytest-cov", specifier = ">=6.2.1" }, @@ -2305,15 +2305,15 @@ wheels = [ [[package]] name = "pyright" -version = "1.1.402" +version = "1.1.403" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "nodeenv" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/aa/04/ce0c132d00e20f2d2fb3b3e7c125264ca8b909e693841210534b1ea1752f/pyright-1.1.402.tar.gz", hash = "sha256:85a33c2d40cd4439c66aa946fd4ce71ab2f3f5b8c22ce36a623f59ac22937683", size = 3888207, upload-time = "2025-06-11T08:48:35.759Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/f6/35f885264ff08c960b23d1542038d8da86971c5d8c955cfab195a4f672d7/pyright-1.1.403.tar.gz", hash = "sha256:3ab69b9f41c67fb5bbb4d7a36243256f0d549ed3608678d381d5f51863921104", size = 3913526, upload-time = "2025-07-09T07:15:52.882Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/37/1a1c62d955e82adae588be8e374c7f77b165b6cb4203f7d581269959abbc/pyright-1.1.402-py3-none-any.whl", hash = "sha256:2c721f11869baac1884e846232800fe021c33f1b4acb3929cff321f7ea4e2982", size = 5624004, upload-time = "2025-06-11T08:48:33.998Z" }, + { url = "https://files.pythonhosted.org/packages/49/b6/b04e5c2f41a5ccad74a1a4759da41adb20b4bc9d59a5e08d29ba60084d07/pyright-1.1.403-py3-none-any.whl", hash = "sha256:c0eeca5aa76cbef3fcc271259bbd785753c7ad7bcac99a9162b4c4c7daed23b3", size = 5684504, upload-time = "2025-07-09T07:15:50.958Z" }, ] [[package]]