Ctrl K
ComunidadGuías…

migrations/033_memory_store.sql

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
CREATE EXTENSION IF NOT EXISTS pg_trgm;

CREATE TABLE IF NOT EXISTS memory_episode (
  episode_id text PRIMARY KEY,
  source_kind text NOT NULL CHECK (source_kind IN ('task_run', 'explicit', 'import')),
  source_id text NOT NULL,
  requester_person_id text NOT NULL,
  conversation_id text NOT NULL DEFAULT '',
  content text NOT NULL,
  occurred_at timestamptz NOT NULL,
  created_at timestamptz NOT NULL DEFAULT now(),
  UNIQUE (source_kind, source_id)
);

CREATE TABLE IF NOT EXISTS memory_fact (
  fact_id text PRIMARY KEY,
  episode_id text NOT NULL REFERENCES memory_episode (episode_id),
  owner_person_id text NOT NULL CHECK (owner_person_id <> ''),
  subject_person_id text NOT NULL DEFAULT '',
  kind text NOT NULL CHECK (kind IN ('identity', 'preference', 'fact', 'episode', 'temporary')),
  content text NOT NULL CHECK (char_length(content) BETWEEN 1 AND 240),
  embedding_model text NOT NULL DEFAULT '',
  security_level_rank smallint NOT NULL DEFAULT 0,
  required_classes text[] NOT NULL DEFAULT '{}',
  valid_from timestamptz NOT NULL,
  valid_until timestamptz,
  superseded_by text REFERENCES memory_fact (fact_id),
  reinforcement_count integer NOT NULL DEFAULT 1,
  last_recalled_at timestamptz,
  forgotten_at timestamptz,
  forget_reason text,
  created_at timestamptz NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS memory_fact_circle (
  fact_id text NOT NULL REFERENCES memory_fact (fact_id) ON DELETE CASCADE,
  circle_id text NOT NULL,
  PRIMARY KEY (fact_id, circle_id)
);

CREATE INDEX IF NOT EXISTS memory_fact_circle_circle_idx
  ON memory_fact_circle (circle_id);
CREATE INDEX IF NOT EXISTS memory_fact_content_trgm_idx
  ON memory_fact USING gin (content gin_trgm_ops);
CREATE INDEX IF NOT EXISTS memory_fact_owner_idx
  ON memory_fact (owner_person_id)
  WHERE superseded_by IS NULL AND forgotten_at IS NULL;
CREATE INDEX IF NOT EXISTS memory_fact_subject_idx
  ON memory_fact (subject_person_id)
  WHERE subject_person_id <> '';

CREATE TABLE IF NOT EXISTS memory_profile (
  person_id text PRIMARY KEY,
  identity_lines text[] NOT NULL DEFAULT '{}',
  current_lines text[] NOT NULL DEFAULT '{}',
  built_from_fact_count integer NOT NULL DEFAULT 0,
  built_at timestamptz NOT NULL
);

CREATE TABLE IF NOT EXISTS memory_job (
  job_id text PRIMARY KEY,
  kind text NOT NULL CHECK (kind IN ('extract', 'profile', 'reembed', 'import')),
  subject_id text NOT NULL,
  attempts integer NOT NULL DEFAULT 0,
  run_after timestamptz NOT NULL DEFAULT now(),
  locked_until timestamptz,
  last_error text,
  created_at timestamptz NOT NULL DEFAULT now(),
  finished_at timestamptz
);

CREATE UNIQUE INDEX IF NOT EXISTS memory_job_pending_idx
  ON memory_job (kind, subject_id)
  WHERE finished_at IS NULL;
CREATE INDEX IF NOT EXISTS memory_job_due_idx
  ON memory_job (run_after)
  WHERE finished_at IS NULL;