10d9e1e2dd
Festinger now reads X-Agent-Name from every intercepted request and resolves the utility LLM model in priority order: 1. agent_models table — agent-specific (e.g. gunnar → claude, rind → qwen) 2. write_model_id config — global default 3. Request mirror — same provider/model Agent0 is currently using New API: GET/PUT/DELETE /agent-models New admin UI: "Agent models" section with assignment form and table. Agent0 side: add a custom header X-Agent-Name: <name> in the LLM provider config per agent container (AGENT_NAME env var can drive this). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
125 lines
6.0 KiB
SQL
125 lines
6.0 KiB
SQL
-- Festinger schema
|
|
-- Run once at container init via db.py:init_schema()
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- models — LLM provider configuration
|
|
-- ---------------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS models (
|
|
id SERIAL PRIMARY KEY,
|
|
provider VARCHAR(32) NOT NULL, -- 'claude' or 'openai'
|
|
model_name VARCHAR(128) NOT NULL,
|
|
api_key TEXT NOT NULL DEFAULT '',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- config — runtime key-value configuration
|
|
-- ---------------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS config (
|
|
key VARCHAR(64) PRIMARY KEY,
|
|
value TEXT NOT NULL,
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
INSERT INTO config (key, value) VALUES
|
|
('saliency_read_threshold', '0.5'),
|
|
('saliency_write_threshold', '1.2'),
|
|
('recollection_confidence_floor','0.6'),
|
|
('recollection_recency_days', '90'),
|
|
('resolution_schedule', '0 2 * * *'),
|
|
('write_model_id', ''),
|
|
('resolve_model_id', '')
|
|
ON CONFLICT (key) DO NOTHING;
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- soas — concept vocabulary and saliency
|
|
-- ---------------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS soas (
|
|
id SERIAL PRIMARY KEY,
|
|
token VARCHAR(256) UNIQUE NOT NULL,
|
|
encounter_count INT NOT NULL DEFAULT 0,
|
|
last_seen TIMESTAMPTZ,
|
|
saliency FLOAT NOT NULL DEFAULT 0.0,
|
|
novelty FLOAT NOT NULL DEFAULT 0.0
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS soas_token_idx ON soas (token);
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- urd — acyclic concept graph (the IN table)
|
|
-- ---------------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS urd (
|
|
id INT NOT NULL REFERENCES soas(id),
|
|
parent_id INT NOT NULL REFERENCES soas(id),
|
|
dim_id INT NOT NULL REFERENCES soas(id),
|
|
is_isa BOOLEAN NOT NULL DEFAULT false,
|
|
confidence FLOAT NOT NULL DEFAULT 1.0,
|
|
last_confirmed TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
source VARCHAR(32) NOT NULL DEFAULT 'cloud_llm',
|
|
PRIMARY KEY (id, parent_id, dim_id)
|
|
);
|
|
|
|
-- One parent per concept per dimension — contradiction-resistance mechanism
|
|
CREATE UNIQUE INDEX IF NOT EXISTS urd_concept_dim_idx ON urd (id, dim_id);
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- resolution_queue — pending conflicts waiting for nightly resolution
|
|
-- ---------------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS resolution_queue (
|
|
id SERIAL PRIMARY KEY,
|
|
concept_id INT NOT NULL REFERENCES soas(id),
|
|
existing_parent_id INT NOT NULL REFERENCES soas(id),
|
|
incoming_parent_id INT NOT NULL REFERENCES soas(id),
|
|
dim_id INT NOT NULL REFERENCES soas(id),
|
|
collision_type VARCHAR(32) NOT NULL, -- 'isa_isa', 'ispart_ispart', 'misclassification'
|
|
status VARCHAR(16) NOT NULL DEFAULT 'pending',
|
|
resolution JSONB,
|
|
priority BOOLEAN NOT NULL DEFAULT false, -- gutask conflicts reviewed first
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
resolved_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS rq_status_idx ON resolution_queue (status);
|
|
CREATE INDEX IF NOT EXISTS rq_concept_idx ON resolution_queue (concept_id);
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- kg_write_log — immutable audit log of every knowledge graph write
|
|
-- ---------------------------------------------------------------------------
|
|
-- op values:
|
|
-- 'insert' — new URD edge written for the first time
|
|
-- 'rewrite' — existing edge replaced (ispart_ispart update)
|
|
-- 'decompose' — isa_isa collision resolved by splitting into two dimensions
|
|
-- 'reclassify' — concept re-inserted in the correct dimension
|
|
CREATE TABLE IF NOT EXISTS kg_write_log (
|
|
id SERIAL PRIMARY KEY,
|
|
op VARCHAR(16) NOT NULL,
|
|
concept_id INT NOT NULL REFERENCES soas(id),
|
|
concept_token TEXT NOT NULL,
|
|
parent_id INT NOT NULL REFERENCES soas(id),
|
|
parent_token TEXT NOT NULL,
|
|
prev_parent_id INT REFERENCES soas(id),
|
|
prev_parent_token TEXT,
|
|
dim_id INT NOT NULL REFERENCES soas(id),
|
|
dim_token TEXT NOT NULL,
|
|
is_isa BOOLEAN NOT NULL DEFAULT false,
|
|
confidence FLOAT NOT NULL DEFAULT 1.0,
|
|
source VARCHAR(32) NOT NULL DEFAULT 'cloud_llm',
|
|
resolution_queue_id INT REFERENCES resolution_queue(id),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS kwl_created_idx ON kg_write_log (created_at DESC);
|
|
CREATE INDEX IF NOT EXISTS kwl_concept_idx ON kg_write_log (concept_id);
|
|
CREATE INDEX IF NOT EXISTS kwl_op_idx ON kg_write_log (op);
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- agent_models — per-agent LLM model assignments
|
|
-- Maps an agent identity (from X-Agent-Name header) to a specific model.
|
|
-- Priority over write_model_id (global default) when agent_name is present.
|
|
-- ---------------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS agent_models (
|
|
agent_name TEXT PRIMARY KEY, -- normalised lowercase, e.g. 'gunnar', 'rind'
|
|
model_id INT NOT NULL REFERENCES models(id) ON DELETE CASCADE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|