Extend command line and add db init.

This also removes obsolete schema files for clarity
This commit is contained in:
Χγφτ Kompanion 2025-10-15 22:35:19 +13:00
parent e881bc4998
commit a04506a081
7 changed files with 27 additions and 176 deletions

View File

@ -4,6 +4,8 @@ project(metal_kompanion_mcp LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(GNUInstallDirs)
option(KOM_ENABLE_PG "Enable Postgres-backed DAL support" ON)
set(KOM_HAVE_PG OFF)
@ -38,6 +40,9 @@ if (KOMPANION_KCONFIG_TARGET STREQUAL "")
message(WARNING "KConfig (KF6/KF5) not found; defaulting to environment-based configuration.")
endif()
set(KOMPANION_DB_INIT_INSTALL_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/kompanion/db/init")
install(DIRECTORY db/init/ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/kompanion/db/init FILES_MATCHING PATTERN "*.sql")
option(BUILD_KOMPANION_CLI "Build Kompanion Qt command-line client" ON)
if (BUILD_KOMPANION_CLI)
find_package(Qt6 COMPONENTS Core QUIET)
@ -58,7 +63,10 @@ add_executable(kom_mcp
)
target_include_directories(kom_mcp PRIVATE src)
target_link_libraries(kom_mcp PRIVATE kom_dal)
target_compile_definitions(kom_mcp PRIVATE PROJECT_SOURCE_DIR="${CMAKE_SOURCE_DIR}")
target_compile_definitions(kom_mcp PRIVATE
PROJECT_SOURCE_DIR="${CMAKE_SOURCE_DIR}"
KOMPANION_DB_INIT_INSTALL_DIR="${KOMPANION_DB_INIT_INSTALL_DIR}"
)
if (NOT KOMPANION_KCONFIG_TARGET STREQUAL "")
target_link_libraries(kom_mcp PRIVATE ${KOMPANION_KCONFIG_TARGET})
target_compile_definitions(kom_mcp PRIVATE HAVE_KCONFIG)
@ -74,7 +82,10 @@ if (BUILD_KOMPANION_CLI)
)
target_include_directories(kompanion PRIVATE src)
target_link_libraries(kompanion PRIVATE Qt6::Core kom_dal)
target_compile_definitions(kompanion PRIVATE PROJECT_SOURCE_DIR="${CMAKE_SOURCE_DIR}")
target_compile_definitions(kompanion PRIVATE
PROJECT_SOURCE_DIR="${CMAKE_SOURCE_DIR}"
KOMPANION_DB_INIT_INSTALL_DIR="${KOMPANION_DB_INIT_INSTALL_DIR}"
)
if (NOT KOMPANION_KCONFIG_TARGET STREQUAL "")
target_link_libraries(kompanion PRIVATE ${KOMPANION_KCONFIG_TARGET})
target_compile_definitions(kompanion PRIVATE HAVE_KCONFIG)

View File

@ -1,59 +0,0 @@
-- metal-kompanion core schema (pgvector)
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE IF NOT EXISTS knowledge (
id BIGSERIAL PRIMARY KEY,
source TEXT,
path TEXT,
sha256 TEXT,
lineno INT,
text TEXT NOT NULL,
tags TEXT[],
created_at TIMESTAMPTZ DEFAULT now()
);
-- embeddings: 1024-dim space (extend with more tables if needed)
CREATE TABLE IF NOT EXISTS embeddings_1024 (
id BIGSERIAL PRIMARY KEY,
knowledge_id BIGINT REFERENCES knowledge(id) ON DELETE CASCADE,
model TEXT NOT NULL,
embedding vector(1024) NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX IF NOT EXISTS embeddings_1024_l2 ON embeddings_1024 USING ivfflat (embedding vector_l2_ops) WITH (lists=100);
-- memory branches (git-like)
CREATE TABLE IF NOT EXISTS mem_branch (
id BIGSERIAL PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
purpose TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE IF NOT EXISTS mem_commit (
id BIGSERIAL PRIMARY KEY,
branch_id BIGINT REFERENCES mem_branch(id) ON DELETE CASCADE,
parent_id BIGINT,
author_did TEXT,
message TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX IF NOT EXISTS mem_commit_branch ON mem_commit(branch_id);
-- commit deltas referencing knowledge rows
CREATE TABLE IF NOT EXISTS mem_delta (
id BIGSERIAL PRIMARY KEY,
commit_id BIGINT REFERENCES mem_commit(id) ON DELETE CASCADE,
knowledge_id BIGINT REFERENCES knowledge(id) ON DELETE CASCADE,
action SMALLINT NOT NULL CHECK (action IN (0,1,2)) -- 0:add,1:update,2:delete
);
CREATE INDEX IF NOT EXISTS mem_delta_commit ON mem_delta(commit_id);
-- per-branch centroid for fast routing
CREATE TABLE IF NOT EXISTS branch_embedding_1024 (
branch_id BIGINT REFERENCES mem_branch(id) ON DELETE CASCADE,
model TEXT NOT NULL,
embedding vector(1024) NOT NULL,
updated_at TIMESTAMPTZ DEFAULT now(),
PRIMARY KEY(branch_id, model)
);

View File

@ -1,5 +0,0 @@
INSERT INTO komp.space(name, model, dim) VALUES
('dev_knowledge','mxbai-embed-large',1024),
('pattern_exchange','mxbai-embed-large',1024),
('runtime_memory','mxbai-embed-large',1024)
ON CONFLICT (name) DO NOTHING;

View File

@ -1,105 +0,0 @@
-- Requires: CREATE EXTENSION IF NOT EXISTS vector; CREATE EXTENSION IF NOT EXISTS ltree;
CREATE SCHEMA IF NOT EXISTS komp;
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS ltree;
CREATE TABLE IF NOT EXISTS komp.source (
id BIGSERIAL PRIMARY KEY,
kind TEXT NOT NULL, -- filesystem|repo|url|note
uri TEXT NOT NULL, -- path or URL
repo TEXT,
ref TEXT,
meta JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE IF NOT EXISTS komp.chunk (
id BIGSERIAL PRIMARY KEY,
source_id BIGINT REFERENCES komp.source(id) ON DELETE CASCADE,
lineno INT,
text TEXT NOT NULL,
sha256 TEXT NOT NULL,
tokens INT,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_chunk_source ON komp.chunk(source_id);
-- A space is a distinct memory with its own model+dim & policy
CREATE TABLE IF NOT EXISTS komp.space (
id SERIAL PRIMARY KEY,
name TEXT UNIQUE, -- dev_knowledge | pattern_exchange | runtime_memory
model TEXT NOT NULL,
dim INT NOT NULL,
metric TEXT NOT NULL DEFAULT 'cosine'
);
-- Embedding tables per common dimension (add more as needed)
CREATE TABLE IF NOT EXISTS komp.embedding_768 (
id BIGSERIAL PRIMARY KEY,
chunk_id BIGINT REFERENCES komp.chunk(id) ON DELETE CASCADE,
space_id INT REFERENCES komp.space(id) ON DELETE CASCADE,
embedding VECTOR(768) NOT NULL,
created_at TIMESTAMPTZ DEFAULT now(),
UNIQUE(chunk_id, space_id)
);
CREATE INDEX IF NOT EXISTS idx_embed768_space ON komp.embedding_768(space_id);
CREATE INDEX IF NOT EXISTS ivf_embed768 ON komp.embedding_768 USING ivfflat (embedding vector_cosine_ops) WITH (lists=100);
CREATE TABLE IF NOT EXISTS komp.embedding_1024 (
id BIGSERIAL PRIMARY KEY,
chunk_id BIGINT REFERENCES komp.chunk(id) ON DELETE CASCADE,
space_id INT REFERENCES komp.space(id) ON DELETE CASCADE,
embedding VECTOR(1024) NOT NULL,
created_at TIMESTAMPTZ DEFAULT now(),
UNIQUE(chunk_id, space_id)
);
CREATE INDEX IF NOT EXISTS idx_embed1024_space ON komp.embedding_1024(space_id);
CREATE INDEX IF NOT EXISTS ivf_embed1024 ON komp.embedding_1024 USING ivfflat (embedding vector_cosine_ops) WITH (lists=100);
-- Branch hierarchy (Branch Embeddings): path encodes the cluster tree (e.g., physics.quantum.tunneling)
CREATE TABLE IF NOT EXISTS komp.branch (
id BIGSERIAL PRIMARY KEY,
space_id INT REFERENCES komp.space(id) ON DELETE CASCADE,
path LTREE NOT NULL,
label TEXT,
meta JSONB DEFAULT '{}'::jsonb,
UNIQUE(space_id, path)
);
CREATE INDEX IF NOT EXISTS gist_branch_path ON komp.branch USING GIST (path);
-- Centroids per dimension (store only the dim matching the space)
CREATE TABLE IF NOT EXISTS komp.branch_centroid_768 (
branch_id BIGINT PRIMARY KEY REFERENCES komp.branch(id) ON DELETE CASCADE,
embedding VECTOR(768) NOT NULL,
updated_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE IF NOT EXISTS komp.branch_centroid_1024 (
branch_id BIGINT PRIMARY KEY REFERENCES komp.branch(id) ON DELETE CASCADE,
embedding VECTOR(1024) NOT NULL,
updated_at TIMESTAMPTZ DEFAULT now()
);
-- Soft membership of chunks to branches
CREATE TABLE IF NOT EXISTS komp.chunk_branch (
chunk_id BIGINT REFERENCES komp.chunk(id) ON DELETE CASCADE,
branch_id BIGINT REFERENCES komp.branch(id) ON DELETE CASCADE,
weight REAL NOT NULL CHECK (weight >= 0 AND weight <= 1),
PRIMARY KEY(chunk_id, branch_id)
);
-- Relations between chunks (similarity / cites / derives / contradicts / …)
CREATE TABLE IF NOT EXISTS komp.chunk_edge (
src_chunk_id BIGINT REFERENCES komp.chunk(id) ON DELETE CASCADE,
dst_chunk_id BIGINT REFERENCES komp.chunk(id) ON DELETE CASCADE,
relation TEXT NOT NULL,
weight REAL,
meta JSONB DEFAULT '{}'::jsonb,
PRIMARY KEY(src_chunk_id, dst_chunk_id, relation)
);
CREATE OR REPLACE VIEW komp.latest_sources AS
SELECT s.*, max(c.created_at) AS last_chunk_at
FROM komp.source s LEFT JOIN komp.chunk c ON c.source_id = s.id
GROUP BY s.id;

View File

@ -1,5 +0,0 @@
-- pgvector knowledge schema (v0.2, branch embeddings)nCREATE EXTENSION IF NOT EXISTS vector;nn-- Documents tracked by content hash; multiple logical paths may point to same blobnCREATE TABLE IF NOT EXISTS doc_blob (n blob_sha256 text PRIMARY KEY,n bytes bigint NOT NULL,n created_at timestamptz DEFAULT now()n);nn-- Logical document identity and branch/commit lineagenCREATE TABLE IF NOT EXISTS doc (n id bigserial PRIMARY KEY,n origin text, -- e.g., filesystem, forgejo, exportn root_path text, -- repo root or base dirn rel_path text, -- path relative to rootn blob_sha256 text REFERENCES doc_blob(blob_sha256)n);nCREATE TABLE IF NOT EXISTS branch (n id bigserial PRIMARY KEY,n name text UNIQUE,n created_at timestamptz DEFAULT now()n);nCREATE TABLE IF NOT EXISTS revision (n id bigserial PRIMARY KEY,n branch_id bigint REFERENCES branch(id) ON DELETE CASCADE,n parent_id bigint REFERENCES revision(id),n commit_sha text, -- optional link to VCSn message text,n created_at timestamptz DEFAULT now()n);nn-- Chunked text with provenance; each revision can re-chunk same docnCREATE TABLE IF NOT EXISTS chunk (n id bigserial PRIMARY KEY,n revision_id bigint REFERENCES revision(id) ON DELETE CASCADE,n doc_id bigint REFERENCES doc(id) ON DELETE CASCADE,n lineno int,n text text NOT NULL,n tags text[],n sha256 text,n created_at timestamptz DEFAULT now()n);nCREATE INDEX IF NOT EXISTS idx_chunk_doc ON chunk(doc_id);nCREATE INDEX IF NOT EXISTS idx_chunk_rev ON chunk(revision_id);nn-- Embedding models registrynCREATE TABLE IF NOT EXISTS embed_model (n id bigserial PRIMARY KEY,n name text UNIQUE NOT NULL, -- e.g., mxbai-embed-largen dims int NOT NULL,n tokenizer text,n notes textn);nn-- Branch embeddings: per revision, per chunk, per model (dims parametrized by table)nCREATE TABLE IF NOT EXISTS embedding_1024 (n id bigserial PRIMARY KEY,n chunk_id bigint REFERENCES chunk(id) ON DELETE CASCADE,n model_id bigint REFERENCES embed_model(id),n embedding vector(1024) NOT NULL,n created_at timestamptz DEFAULT now()n);nCREATE INDEX IF NOT EXISTS idx_emb1024_chunk ON embedding_1024(chunk_id);nCREATE INDEX IF NOT EXISTS idx_emb1024_vec ON embedding_1024 USING ivfflat (embedding vector_l2_ops) WITH (lists=100);nn-- Views: latest chunks per branchnCREATE OR REPLACE VIEW v_latest_chunks AS
SELECT c.* FROM chunk c
JOIN (SELECT revision_id, max(id) over (partition by doc_id, branch_id) as maxid, doc_id
FROM revision r JOIN chunk c2 ON c2.revision_id=r.id) t
ON c.id=t.maxid;nn-- Ledger mirror (optional)nCREATE TABLE IF NOT EXISTS ledger_mirror (n id bigserial PRIMARY KEY,n ts timestamptz NOT NULL,n actor text,n action text,n body jsonbn);n

View File

@ -9,6 +9,19 @@ Kompanion adheres to KDEs KConfig conventions so deployments are kioskable an
The CLI (`kompanion`) and MCP runner (`kom_mcp`) fall back to this entry when the `PG_DSN` environment variable is not set. If neither are present the in-memory DAL stub is used.
## Initialization Wizard
- Run `kompanion --init` to launch an interactive wizard.
- Autodetects reachable Postgres instances (tries `postgresql://kompanion:komup@localhost/kompanion_test`).
- Prompts for host, port, database, user, password, or Unix socket path with sensible defaults.
- Writes the resulting DSN to `kompanionrc` and exports `PG_DSN` for the current session.
- If the target database is empty, it applies the SQL migrations shipped under `share/kompanion/db/init/*.sql`.
- The wizard is also triggered automatically the first time you run `kompanion` without a configured DSN.
## CLI Modes
- Standard invocation: `kompanion <tool> --request payload.json`
- Interactive prompt: `kompanion -I <tool>` keeps a REPL open; enter JSON payloads or `!prompt text` to wrap plain text. Use `-V/--verbose` to echo request/response JSON streams.
- Use `kompanion --list` to enumerate available tools, including `kom.meta.v1.project_snapshot` for quick project context dumps.
## Future HTTP Streaming
While current tooling focuses on stdio dispatch (for editor and agent integration), the roadmap includes an HTTP/2 or WebSocket streaming surface so MCP clients can maintain persistent conversations without leaving CLI compatibility behind. The same configuration keys will apply for both transports.

View File

@ -73,6 +73,7 @@
- **Observability**: CLI should read the `jobs/semantic_sync` state block to display cursors, pending counts, and last error logs; dry-run mode estimates embeddings without committing.
- **Activation parity**: Long term, mirror the KDE `akonadiclient`/`akonadi-console` pattern—Kompanion CLI doubles as an MCP surface today and later as a DBus-activated helper so tools can be socket-triggered into the memory service.
- **KConfig defaults**: `kom_mcp` and `kompanion` load `Database/PgDsn` from `~/.config/kompanionrc` (see `docs/configuration.md`) when `PG_DSN` is unset, keeping deployments kioskable.
- **CLI UX**: `kompanion --init` guides first-run setup (auto-detects databases, applies schemas); `-I/--interactive` keeps a JSON REPL open, and `-V/--verbose` echoes request/response streams for future HTTP transport parity.
## Next-Step Checklist
- [x] Detect pqxx via CMake and plumb `HAVE_PG`.