From d9a2bcaa0b227a76b03ea71f77e97f414d5ee30d Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Sun, 22 Mar 2026 18:15:31 +0000 Subject: [PATCH] Initial upload: shell-history-semantic-search v0.1.0 --- src/shell_history_search/db/__init__.py | 91 +++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/shell_history_search/db/__init__.py diff --git a/src/shell_history_search/db/__init__.py b/src/shell_history_search/db/__init__.py new file mode 100644 index 0000000..8c876da --- /dev/null +++ b/src/shell_history_search/db/__init__.py @@ -0,0 +1,91 @@ +import os +import sqlite3 +from pathlib import Path +from typing import Optional +import logging + +logger = logging.getLogger(__name__) + +DEFAULT_DB_PATH = Path.home() / ".local" / "share" / "shell_history_search" / "history.db" + + +def get_db_path() -> Path: + return Path(os.environ.get("SHELL_HISTORY_DB", str(DEFAULT_DB_PATH))) + + +def ensure_db_directory(db_path: Path) -> None: + db_path.parent.mkdir(parents=True, exist_ok=True) + + +def get_connection(db_path: Optional[Path] = None) -> sqlite3.Connection: + if db_path is None: + db_path = get_db_path() + + ensure_db_directory(db_path) + + conn = sqlite3.connect(str(db_path), check_same_thread=False) + conn.row_factory = sqlite3.Row + + conn.execute("PRAGMA journal_mode=WAL") + conn.execute("PRAGMA foreign_keys=ON") + + return conn + + +def init_database(db_path: Optional[Path] = None) -> sqlite3.Connection: + conn = get_connection(db_path) + + conn.execute(""" + CREATE TABLE IF NOT EXISTS commands ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + command TEXT NOT NULL, + shell_type TEXT NOT NULL, + timestamp INTEGER, + hostname TEXT, + command_hash TEXT UNIQUE NOT NULL, + created_at INTEGER DEFAULT (strftime('%s', 'now')), + indexed_at INTEGER + ) + """) + + conn.execute(""" + CREATE INDEX IF NOT EXISTS idx_commands_hash ON commands(command_hash) + """) + + conn.execute(""" + CREATE INDEX IF NOT EXISTS idx_commands_shell ON commands(shell_type) + """) + + conn.execute(""" + CREATE INDEX IF NOT EXISTS idx_commands_timestamp ON commands(timestamp) + """) + + conn.execute(""" + CREATE TABLE IF NOT EXISTS embeddings ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + command_id INTEGER NOT NULL, + embedding BLOB NOT NULL, + model_name TEXT NOT NULL, + created_at INTEGER DEFAULT (strftime('%s', 'now')), + FOREIGN KEY (command_id) REFERENCES commands(id) ON DELETE CASCADE, + UNIQUE(command_id) + ) + """) + + conn.execute(""" + CREATE INDEX IF NOT EXISTS idx_embeddings_command ON embeddings(command_id) + """) + + conn.execute(""" + CREATE TABLE IF NOT EXISTS index_state ( + shell_type TEXT PRIMARY KEY, + last_indexed_at INTEGER, + last_indexed_hash TEXT + ) + """) + + conn.commit() + + logger.info(f"Database initialized at {db_path}") + + return conn \ No newline at end of file