sync: migrate ai-operator to Gitea (2026-08-10)
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS schema_migrations (
|
||||
version text PRIMARY KEY,
|
||||
applied_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS knowledge_documents (
|
||||
id uuid PRIMARY KEY,
|
||||
external_id text NOT NULL UNIQUE,
|
||||
title text NOT NULL,
|
||||
language text NOT NULL CHECK (language IN ('ru','kk')),
|
||||
region_code text NOT NULL DEFAULT 'global' CHECK (length(region_code) > 0),
|
||||
category text NOT NULL DEFAULT 'general',
|
||||
source_type text NOT NULL,
|
||||
source_uri text,
|
||||
source_hash text NOT NULL,
|
||||
status text NOT NULL DEFAULT 'published' CHECK (status IN ('draft','published','archived')),
|
||||
content text NOT NULL,
|
||||
question text,
|
||||
short_answer text,
|
||||
full_answer text,
|
||||
keywords text[] NOT NULL DEFAULT '{}',
|
||||
source text,
|
||||
metadata jsonb NOT NULL DEFAULT '{}',
|
||||
valid_from timestamptz,
|
||||
valid_to timestamptz,
|
||||
priority int NOT NULL DEFAULT 0,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS knowledge_chunks (
|
||||
id uuid PRIMARY KEY,
|
||||
document_id uuid NOT NULL REFERENCES knowledge_documents(id) ON DELETE CASCADE,
|
||||
chunk_index int NOT NULL,
|
||||
language text NOT NULL CHECK (language IN ('ru','kk')),
|
||||
region_code text NOT NULL,
|
||||
title text NOT NULL,
|
||||
content text NOT NULL,
|
||||
content_hash text NOT NULL,
|
||||
token_estimate int NOT NULL DEFAULT 0,
|
||||
char_count int NOT NULL DEFAULT 0,
|
||||
embedding vector(1536),
|
||||
embedding_model text NOT NULL DEFAULT 'fake',
|
||||
embedding_provider text NOT NULL DEFAULT 'fake',
|
||||
metadata jsonb NOT NULL DEFAULT '{}',
|
||||
tsv tsvector,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
UNIQUE(document_id, chunk_index)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS knowledge_ingest_runs (
|
||||
id uuid PRIMARY KEY,
|
||||
source_path text NOT NULL,
|
||||
status text NOT NULL,
|
||||
documents_seen int NOT NULL DEFAULT 0,
|
||||
documents_ingested int NOT NULL DEFAULT 0,
|
||||
chunks_created int NOT NULL DEFAULT 0,
|
||||
skipped int NOT NULL DEFAULT 0,
|
||||
error text,
|
||||
started_at timestamptz NOT NULL DEFAULT now(),
|
||||
finished_at timestamptz
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS knowledge_search_logs (
|
||||
id uuid PRIMARY KEY,
|
||||
call_id text,
|
||||
query text NOT NULL,
|
||||
language text NOT NULL,
|
||||
region_code text NOT NULL,
|
||||
result_count int NOT NULL,
|
||||
top_score double precision,
|
||||
cross_language_fallback_used boolean NOT NULL DEFAULT false,
|
||||
created_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
@@ -0,0 +1,20 @@
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_kd_external_id ON knowledge_documents(external_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_kd_language_region_status ON knowledge_documents(language, region_code, status);
|
||||
CREATE INDEX IF NOT EXISTS idx_kd_source_hash ON knowledge_documents(source_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_kd_validity ON knowledge_documents(valid_from, valid_to);
|
||||
CREATE INDEX IF NOT EXISTS idx_kc_document_id ON knowledge_chunks(document_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_kc_language_region ON knowledge_chunks(language, region_code);
|
||||
CREATE INDEX IF NOT EXISTS idx_kc_content_hash ON knowledge_chunks(content_hash);
|
||||
CREATE INDEX IF NOT EXISTS idx_kc_tsv ON knowledge_chunks USING GIN(tsv);
|
||||
DO $$
|
||||
BEGIN
|
||||
BEGIN
|
||||
CREATE INDEX IF NOT EXISTS idx_kc_embedding_hnsw ON knowledge_chunks USING hnsw (embedding vector_cosine_ops);
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
BEGIN
|
||||
CREATE INDEX IF NOT EXISTS idx_kc_embedding_ivfflat ON knowledge_chunks USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE NOTICE 'vector index creation skipped: %', SQLERRM;
|
||||
END;
|
||||
END;
|
||||
END $$;
|
||||
@@ -0,0 +1,163 @@
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ai_calls (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
call_id text NOT NULL UNIQUE,
|
||||
asterisk_channel_id text,
|
||||
route text NOT NULL DEFAULT 'unknown',
|
||||
caller_number_masked text,
|
||||
language text,
|
||||
region_code text,
|
||||
state text,
|
||||
started_at timestamptz NOT NULL,
|
||||
ended_at timestamptz,
|
||||
duration_ms bigint,
|
||||
end_reason text,
|
||||
handoff_status text,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
metadata jsonb NOT NULL DEFAULT '{}'
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_calls_started_at ON ai_calls(started_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_calls_route ON ai_calls(route);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_calls_language_region ON ai_calls(language, region_code);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_calls_state ON ai_calls(state);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ai_call_events (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
call_id text NOT NULL,
|
||||
event_type text NOT NULL,
|
||||
event_source text NOT NULL,
|
||||
state_before text,
|
||||
state_after text,
|
||||
severity text NOT NULL DEFAULT 'info',
|
||||
message text,
|
||||
reason_code text,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
metadata jsonb NOT NULL DEFAULT '{}'
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_call_events_call_id_created_at ON ai_call_events(call_id, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_call_events_type ON ai_call_events(event_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_call_events_severity ON ai_call_events(severity);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ai_transcript_events (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
call_id text NOT NULL,
|
||||
speaker text NOT NULL CHECK (speaker IN ('user','assistant','system','tool')),
|
||||
event_type text NOT NULL,
|
||||
language text,
|
||||
text_redacted text,
|
||||
text_raw_encrypted text,
|
||||
text_hash text,
|
||||
char_count int NOT NULL DEFAULT 0,
|
||||
redaction_applied boolean NOT NULL DEFAULT true,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
metadata jsonb NOT NULL DEFAULT '{}'
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_transcript_events_call_id_created_at ON ai_transcript_events(call_id, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_transcript_events_speaker ON ai_transcript_events(speaker);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_transcript_events_language ON ai_transcript_events(language);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ai_tool_audit (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
call_id text NOT NULL,
|
||||
tool_call_id text,
|
||||
tool_name text NOT NULL,
|
||||
state text,
|
||||
language text,
|
||||
region_code text,
|
||||
allowed boolean NOT NULL,
|
||||
denied boolean NOT NULL DEFAULT false,
|
||||
reason_code text,
|
||||
args_redacted jsonb NOT NULL DEFAULT '{}',
|
||||
result_redacted jsonb NOT NULL DEFAULT '{}',
|
||||
duration_ms bigint,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
metadata jsonb NOT NULL DEFAULT '{}'
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_tool_audit_call_id_created_at ON ai_tool_audit(call_id, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_tool_audit_tool_name ON ai_tool_audit(tool_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_tool_audit_denied ON ai_tool_audit(denied);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ai_kb_audit (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
call_id text,
|
||||
query_redacted text NOT NULL,
|
||||
language text NOT NULL,
|
||||
region_code text NOT NULL,
|
||||
result_count int NOT NULL DEFAULT 0,
|
||||
top_score double precision,
|
||||
cross_language_fallback_used boolean NOT NULL DEFAULT false,
|
||||
citations_count int NOT NULL DEFAULT 0,
|
||||
no_answer boolean NOT NULL DEFAULT false,
|
||||
duration_ms bigint,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
metadata jsonb NOT NULL DEFAULT '{}'
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_kb_audit_call_id_created_at ON ai_kb_audit(call_id, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_kb_audit_language_region ON ai_kb_audit(language, region_code);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_kb_audit_no_answer ON ai_kb_audit(no_answer);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ai_handoff_audit (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
call_id text NOT NULL,
|
||||
handoff_id text,
|
||||
mode text NOT NULL,
|
||||
status text NOT NULL,
|
||||
reason_code text,
|
||||
transfer_attempted boolean NOT NULL DEFAULT false,
|
||||
transfer_succeeded boolean NOT NULL DEFAULT false,
|
||||
target_redacted text,
|
||||
summary_redacted text,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
metadata jsonb NOT NULL DEFAULT '{}'
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_handoff_audit_call_id_created_at ON ai_handoff_audit(call_id, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_handoff_audit_status ON ai_handoff_audit(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_handoff_audit_mode ON ai_handoff_audit(mode);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ai_provider_audit (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
call_id text,
|
||||
provider text NOT NULL,
|
||||
event_type text NOT NULL,
|
||||
severity text NOT NULL DEFAULT 'info',
|
||||
error_redacted text,
|
||||
input_audio_bytes bigint NOT NULL DEFAULT 0,
|
||||
output_audio_bytes bigint NOT NULL DEFAULT 0,
|
||||
events_received bigint NOT NULL DEFAULT 0,
|
||||
events_sent bigint NOT NULL DEFAULT 0,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
metadata jsonb NOT NULL DEFAULT '{}'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ai_media_audit (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
call_id text,
|
||||
event_type text NOT NULL,
|
||||
severity text NOT NULL DEFAULT 'info',
|
||||
codec text,
|
||||
inbound_frames bigint NOT NULL DEFAULT 0,
|
||||
inbound_bytes bigint NOT NULL DEFAULT 0,
|
||||
outbound_frames bigint NOT NULL DEFAULT 0,
|
||||
outbound_bytes bigint NOT NULL DEFAULT 0,
|
||||
xoff_count bigint NOT NULL DEFAULT 0,
|
||||
xon_count bigint NOT NULL DEFAULT 0,
|
||||
error_redacted text,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
metadata jsonb NOT NULL DEFAULT '{}'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ai_audit_retention_runs (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
dry_run boolean NOT NULL DEFAULT true,
|
||||
status text NOT NULL,
|
||||
started_at timestamptz NOT NULL DEFAULT now(),
|
||||
finished_at timestamptz,
|
||||
calls_deleted int NOT NULL DEFAULT 0,
|
||||
events_deleted int NOT NULL DEFAULT 0,
|
||||
transcripts_deleted int NOT NULL DEFAULT 0,
|
||||
tool_audit_deleted int NOT NULL DEFAULT 0,
|
||||
error text,
|
||||
metadata jsonb NOT NULL DEFAULT '{}'
|
||||
);
|
||||
Reference in New Issue
Block a user