Terminal / migrations /MASTER_SCHEMA.sql
Baida-A
Initial clean deploy (Reverse Proxy removed)
28a08e7
Raw
History Blame
14.3 kB
-- ══════════════════════════════════════════════════════════════════════════════
-- AGENTE AI β€” Schema Supabase completo
-- Incolla questo file nel SQL Editor: Dashboard β†’ SQL Editor β†’ New query β†’ Run
-- Tutti gli statement sono idempotenti (IF NOT EXISTS / CREATE OR REPLACE).
-- ══════════════════════════════════════════════════════════════════════════════
-- ── 0. Estensioni ─────────────────────────────────────────────────────────────
CREATE EXTENSION IF NOT EXISTS vector;
-- ══════════════════════════════════════════════════════════════════════════════
-- 1. MEMORIA EPISODICA β€” tabella episodes
-- ══════════════════════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS public.episodes (
id BIGSERIAL PRIMARY KEY,
type TEXT NOT NULL,
task TEXT NOT NULL,
output TEXT,
success INTEGER DEFAULT 1,
ts TEXT NOT NULL,
tags TEXT DEFAULT '[]'
);
CREATE INDEX IF NOT EXISTS idx_episodes_type ON public.episodes (type);
CREATE INDEX IF NOT EXISTS idx_episodes_ts ON public.episodes (ts);
ALTER TABLE public.episodes ENABLE ROW LEVEL SECURITY;
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE tablename='episodes' AND policyname='anon full access') THEN
CREATE POLICY "anon full access" ON public.episodes FOR ALL TO anon USING (true) WITH CHECK (true);
END IF;
END $$;
-- ══════════════════════════════════════════════════════════════════════════════
-- 2. MEMORIA SEMANTICA β€” tabella semantic_memory + pgvector
-- ══════════════════════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS public.semantic_memory (
id TEXT PRIMARY KEY,
content TEXT NOT NULL,
metadata JSONB DEFAULT '{}'
);
ALTER TABLE public.semantic_memory
ADD COLUMN IF NOT EXISTS embedding vector(384);
ALTER TABLE public.semantic_memory ENABLE ROW LEVEL SECURITY;
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE tablename='semantic_memory' AND policyname='anon full access') THEN
CREATE POLICY "anon full access" ON public.semantic_memory FOR ALL TO anon USING (true) WITH CHECK (true);
END IF;
END $$;
CREATE OR REPLACE FUNCTION match_semantic_memory(
query_embedding vector(384),
match_count int DEFAULT 5,
match_threshold float DEFAULT 0.2
)
RETURNS TABLE (id text, content text, metadata jsonb, similarity float)
LANGUAGE sql STABLE AS $$
SELECT id, content, metadata,
(1 - (embedding <=> query_embedding))::float AS similarity
FROM public.semantic_memory
WHERE embedding IS NOT NULL
AND (1 - (embedding <=> query_embedding)) > match_threshold
ORDER BY embedding <=> query_embedding
LIMIT match_count;
$$;
-- ══════════════════════════════════════════════════════════════════════════════
-- 3. MEMORIA AGENTE β€” tabella agent_memory (incident registry + decision memory)
-- ══════════════════════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS public.agent_memory (
key TEXT PRIMARY KEY,
value TEXT NOT NULL DEFAULT '{}',
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
ALTER TABLE public.agent_memory ENABLE ROW LEVEL SECURITY;
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE tablename='agent_memory' AND policyname='anon full access') THEN
CREATE POLICY "anon full access" ON public.agent_memory FOR ALL TO anon USING (true) WITH CHECK (true);
END IF;
END $$;
-- ══════════════════════════════════════════════════════════════════════════════
-- 4. TASK AGENTE β€” tabelle agent_tasks + agent_task_events
-- ══════════════════════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS public.agent_tasks (
task_id TEXT PRIMARY KEY,
goal TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'QUEUED',
max_steps INTEGER NOT NULL DEFAULT 8,
context TEXT NOT NULL DEFAULT '[]',
created_at BIGINT NOT NULL DEFAULT 0,
updated_at BIGINT NOT NULL DEFAULT 0
);
CREATE TABLE IF NOT EXISTS public.agent_task_events (
id BIGSERIAL PRIMARY KEY,
task_id TEXT NOT NULL REFERENCES public.agent_tasks(task_id) ON DELETE CASCADE,
event_index INTEGER NOT NULL,
event_data TEXT NOT NULL,
created_at BIGINT NOT NULL DEFAULT 0,
UNIQUE (task_id, event_index)
);
CREATE INDEX IF NOT EXISTS idx_agent_task_events_lookup
ON public.agent_task_events (task_id, event_index ASC);
ALTER TABLE public.agent_tasks ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.agent_task_events ENABLE ROW LEVEL SECURITY;
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE tablename='agent_tasks' AND policyname='anon full access') THEN
CREATE POLICY "anon full access" ON public.agent_tasks FOR ALL TO anon USING (true) WITH CHECK (true);
CREATE POLICY "anon full access" ON public.agent_task_events FOR ALL TO anon USING (true) WITH CHECK (true);
END IF;
END $$;
CREATE OR REPLACE FUNCTION purge_old_agent_tasks() RETURNS void
LANGUAGE plpgsql AS $$
DECLARE cutoff BIGINT := (EXTRACT(EPOCH FROM NOW()) * 1000 - 7 * 86400000)::BIGINT;
BEGIN DELETE FROM public.agent_tasks WHERE updated_at < cutoff; END;
$$;
-- ══════════════════════════════════════════════════════════════════════════════
-- 5. SKILL TRACKER β€” tabelle skill_stats + skill_patterns
-- ══════════════════════════════════════════════════════════════════════════════
CREATE OR REPLACE FUNCTION _touch_updated_at()
RETURNS TRIGGER LANGUAGE plpgsql AS $$
BEGIN NEW.updated_at = now(); RETURN NEW; END;
$$;
CREATE TABLE IF NOT EXISTS public.skill_stats (
session_id TEXT NOT NULL,
tool_name TEXT NOT NULL,
success_count INTEGER NOT NULL DEFAULT 0,
fail_count INTEGER NOT NULL DEFAULT 0,
last_used DOUBLE PRECISION NOT NULL DEFAULT 0,
total_latency_ms DOUBLE PRECISION NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (session_id, tool_name)
);
CREATE INDEX IF NOT EXISTS idx_skill_stats_session ON public.skill_stats (session_id);
ALTER TABLE public.skill_stats ENABLE ROW LEVEL SECURITY;
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE tablename='skill_stats' AND policyname='anon full access') THEN
CREATE POLICY "anon full access" ON public.skill_stats FOR ALL TO anon USING (true) WITH CHECK (true);
END IF;
END $$;
DROP TRIGGER IF EXISTS trg_skill_stats_updated_at ON public.skill_stats;
CREATE TRIGGER trg_skill_stats_updated_at BEFORE UPDATE ON public.skill_stats
FOR EACH ROW EXECUTE FUNCTION _touch_updated_at();
CREATE TABLE IF NOT EXISTS public.skill_patterns (
id TEXT PRIMARY KEY,
task_signature TEXT NOT NULL,
tool_sequence TEXT[] NOT NULL,
success_count INTEGER NOT NULL DEFAULT 0,
total_count INTEGER NOT NULL DEFAULT 0,
last_used BIGINT NOT NULL DEFAULT 0,
confidence DOUBLE PRECISION NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_skill_patterns_confidence ON public.skill_patterns (confidence DESC);
CREATE INDEX IF NOT EXISTS idx_skill_patterns_last_used ON public.skill_patterns (last_used DESC);
ALTER TABLE public.skill_patterns ENABLE ROW LEVEL SECURITY;
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE tablename='skill_patterns' AND policyname='anon full access') THEN
CREATE POLICY "anon full access" ON public.skill_patterns FOR ALL TO anon USING (true) WITH CHECK (true);
END IF;
END $$;
DROP TRIGGER IF EXISTS trg_skill_patterns_updated_at ON public.skill_patterns;
CREATE TRIGGER trg_skill_patterns_updated_at BEFORE UPDATE ON public.skill_patterns
FOR EACH ROW EXECUTE FUNCTION _touch_updated_at();
-- ══════════════════════════════════════════════════════════════════════════════
-- 6. FILE SYSTEM VIRTUALE β€” tabella vfs_files
-- ══════════════════════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS public.vfs_files (
id TEXT PRIMARY KEY,
path TEXT NOT NULL,
content TEXT NOT NULL DEFAULT '',
mime_type TEXT NOT NULL DEFAULT 'text/plain',
size BIGINT NOT NULL DEFAULT 0,
created_at BIGINT NOT NULL DEFAULT 0,
updated_at BIGINT NOT NULL DEFAULT 0
);
ALTER TABLE public.vfs_files ADD COLUMN IF NOT EXISTS version BIGINT NOT NULL DEFAULT 0;
CREATE INDEX IF NOT EXISTS idx_vfs_files_path ON public.vfs_files (path);
CREATE INDEX IF NOT EXISTS vfs_files_version_idx ON public.vfs_files (id, version);
ALTER TABLE public.vfs_files ENABLE ROW LEVEL SECURITY;
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE tablename='vfs_files' AND policyname='anon full access') THEN
CREATE POLICY "anon full access" ON public.vfs_files FOR ALL TO anon USING (true) WITH CHECK (true);
END IF;
END $$;
CREATE OR REPLACE FUNCTION public._vfs_bump_version()
RETURNS TRIGGER LANGUAGE plpgsql AS $$
BEGIN NEW.version = OLD.version + 1; RETURN NEW; END;
$$;
DROP TRIGGER IF EXISTS trg_vfs_version ON public.vfs_files;
CREATE TRIGGER trg_vfs_version BEFORE UPDATE ON public.vfs_files
FOR EACH ROW EXECUTE FUNCTION public._vfs_bump_version();
-- ══════════════════════════════════════════════════════════════════════════════
-- 7. TOKEN OAUTH β€” tabelle managed_tokens + oauth_states
-- ══════════════════════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS public.managed_tokens (
user_id TEXT NOT NULL DEFAULT 'default',
provider TEXT NOT NULL,
access_token TEXT NOT NULL DEFAULT '',
refresh_token TEXT NOT NULL DEFAULT '',
expires_at BIGINT NOT NULL DEFAULT 0,
scope TEXT NOT NULL DEFAULT '',
raw_meta TEXT NOT NULL DEFAULT '{}',
created_at BIGINT NOT NULL DEFAULT 0,
updated_at BIGINT NOT NULL DEFAULT 0,
UNIQUE (user_id, provider)
);
CREATE INDEX IF NOT EXISTS managed_tokens_user_idx ON public.managed_tokens (user_id, provider);
ALTER TABLE public.managed_tokens ENABLE ROW LEVEL SECURITY;
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE tablename='managed_tokens' AND policyname='service only') THEN
CREATE POLICY "service only" ON public.managed_tokens FOR ALL TO service_role USING (true) WITH CHECK (true);
END IF;
END $$;
CREATE TABLE IF NOT EXISTS public.oauth_states (
state TEXT PRIMARY KEY,
provider TEXT NOT NULL,
user_id TEXT NOT NULL DEFAULT 'default',
created_at BIGINT NOT NULL DEFAULT 0
);
CREATE OR REPLACE FUNCTION public._purge_oauth_states() RETURNS void
LANGUAGE plpgsql AS $$
BEGIN
DELETE FROM public.oauth_states
WHERE created_at < (EXTRACT(EPOCH FROM NOW()) * 1000 - 600000)::BIGINT;
END;
$$;
-- ══════════════════════════════════════════════════════════════════════════════
-- FINE β€” Verifica eseguendo:
-- SELECT table_name FROM information_schema.tables
-- WHERE table_schema = 'public' ORDER BY table_name;
-- ══════════════════════════════════════════════════════════════════════════════