229 lines
10 KiB
MySQL
229 lines
10 KiB
MySQL
|
|
\set ON_ERROR_STOP on
|
||
|
|
|
||
|
|
BEGIN;
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS bot_instance (
|
||
|
|
id TEXT PRIMARY KEY,
|
||
|
|
name TEXT NOT NULL,
|
||
|
|
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||
|
|
access_password TEXT NOT NULL DEFAULT '',
|
||
|
|
workspace_dir TEXT NOT NULL UNIQUE,
|
||
|
|
docker_status TEXT NOT NULL DEFAULT 'STOPPED',
|
||
|
|
current_state TEXT DEFAULT 'IDLE',
|
||
|
|
last_action TEXT,
|
||
|
|
image_tag TEXT NOT NULL DEFAULT 'nanobot-base:v0.1.4',
|
||
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS bot_image (
|
||
|
|
tag TEXT PRIMARY KEY,
|
||
|
|
image_id TEXT,
|
||
|
|
version TEXT NOT NULL,
|
||
|
|
status TEXT NOT NULL DEFAULT 'READY',
|
||
|
|
source_dir TEXT,
|
||
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS bot_message (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
bot_id TEXT NOT NULL REFERENCES bot_instance(id),
|
||
|
|
role TEXT NOT NULL,
|
||
|
|
text TEXT NOT NULL,
|
||
|
|
media_json TEXT,
|
||
|
|
feedback TEXT,
|
||
|
|
feedback_at TIMESTAMP,
|
||
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS sys_login_log (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
auth_type TEXT NOT NULL,
|
||
|
|
token_hash TEXT NOT NULL,
|
||
|
|
subject_id TEXT NOT NULL,
|
||
|
|
bot_id TEXT,
|
||
|
|
auth_source TEXT NOT NULL DEFAULT '',
|
||
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
expires_at TIMESTAMP NOT NULL,
|
||
|
|
last_seen_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
revoked_at TIMESTAMP,
|
||
|
|
revoke_reason TEXT,
|
||
|
|
client_ip TEXT,
|
||
|
|
user_agent TEXT,
|
||
|
|
device_info TEXT
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS sys_setting (
|
||
|
|
key VARCHAR(120) PRIMARY KEY,
|
||
|
|
name VARCHAR(200) NOT NULL DEFAULT '',
|
||
|
|
category VARCHAR(64) NOT NULL DEFAULT 'general',
|
||
|
|
description TEXT NOT NULL DEFAULT '',
|
||
|
|
value_type VARCHAR(32) NOT NULL DEFAULT 'json',
|
||
|
|
value_json TEXT NOT NULL DEFAULT '{}',
|
||
|
|
is_public BOOLEAN NOT NULL DEFAULT FALSE,
|
||
|
|
sort_order INTEGER NOT NULL DEFAULT 100,
|
||
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS bot_request_usage (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
bot_id TEXT NOT NULL REFERENCES bot_instance(id),
|
||
|
|
message_id INTEGER,
|
||
|
|
request_id VARCHAR(120) NOT NULL,
|
||
|
|
channel VARCHAR(64) NOT NULL DEFAULT 'dashboard',
|
||
|
|
status VARCHAR(32) NOT NULL DEFAULT 'PENDING',
|
||
|
|
provider VARCHAR(120),
|
||
|
|
model VARCHAR(255),
|
||
|
|
token_source VARCHAR(32) NOT NULL DEFAULT 'estimated',
|
||
|
|
input_tokens INTEGER NOT NULL DEFAULT 0,
|
||
|
|
output_tokens INTEGER NOT NULL DEFAULT 0,
|
||
|
|
total_tokens INTEGER NOT NULL DEFAULT 0,
|
||
|
|
input_text_preview TEXT,
|
||
|
|
output_text_preview TEXT,
|
||
|
|
attachments_json TEXT,
|
||
|
|
error_text TEXT,
|
||
|
|
metadata_json TEXT,
|
||
|
|
started_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
completed_at TIMESTAMP,
|
||
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS bot_activity_event (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
bot_id TEXT NOT NULL REFERENCES bot_instance(id),
|
||
|
|
request_id VARCHAR(120),
|
||
|
|
event_type VARCHAR(64) NOT NULL,
|
||
|
|
channel VARCHAR(64) NOT NULL DEFAULT 'dashboard',
|
||
|
|
detail TEXT,
|
||
|
|
metadata_json TEXT,
|
||
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS skill_market_item (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
skill_key VARCHAR(120) NOT NULL,
|
||
|
|
display_name VARCHAR(255) NOT NULL DEFAULT '',
|
||
|
|
description TEXT NOT NULL DEFAULT '',
|
||
|
|
zip_filename VARCHAR(255) NOT NULL,
|
||
|
|
zip_size_bytes INTEGER NOT NULL DEFAULT 0,
|
||
|
|
entry_names_json TEXT NOT NULL DEFAULT '[]',
|
||
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
CONSTRAINT uq_skill_market_item_skill_key UNIQUE (skill_key),
|
||
|
|
CONSTRAINT uq_skill_market_item_zip_filename UNIQUE (zip_filename)
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS bot_skill_install (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
bot_id TEXT NOT NULL REFERENCES bot_instance(id),
|
||
|
|
skill_market_item_id INTEGER NOT NULL REFERENCES skill_market_item(id),
|
||
|
|
installed_entries_json TEXT NOT NULL DEFAULT '[]',
|
||
|
|
source_zip_filename VARCHAR(255) NOT NULL DEFAULT '',
|
||
|
|
status VARCHAR(32) NOT NULL DEFAULT 'INSTALLED',
|
||
|
|
last_error TEXT,
|
||
|
|
installed_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
CONSTRAINT uq_bot_skill_install_bot_market UNIQUE (bot_id, skill_market_item_id)
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS topic_topic (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
bot_id TEXT NOT NULL REFERENCES bot_instance(id),
|
||
|
|
topic_key TEXT NOT NULL,
|
||
|
|
name TEXT NOT NULL DEFAULT '',
|
||
|
|
description TEXT NOT NULL DEFAULT '',
|
||
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||
|
|
is_default_fallback BOOLEAN NOT NULL DEFAULT FALSE,
|
||
|
|
routing_json TEXT NOT NULL DEFAULT '{}',
|
||
|
|
view_schema_json TEXT NOT NULL DEFAULT '{}',
|
||
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
CONSTRAINT uq_topic_topic_bot_topic_key UNIQUE (bot_id, topic_key)
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS topic_item (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
bot_id TEXT NOT NULL REFERENCES bot_instance(id),
|
||
|
|
topic_key TEXT NOT NULL,
|
||
|
|
title TEXT NOT NULL DEFAULT '',
|
||
|
|
content TEXT NOT NULL DEFAULT '',
|
||
|
|
level TEXT NOT NULL DEFAULT 'info',
|
||
|
|
tags_json TEXT,
|
||
|
|
view_json TEXT,
|
||
|
|
source TEXT NOT NULL DEFAULT 'mcp',
|
||
|
|
dedupe_key TEXT,
|
||
|
|
is_read BOOLEAN NOT NULL DEFAULT FALSE,
|
||
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_instance_enabled ON bot_instance (enabled);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_instance_docker_status ON bot_instance (docker_status);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_message_bot_id ON bot_message (bot_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_message_role ON bot_message (role);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_message_feedback ON bot_message (feedback);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_message_created_at ON bot_message (created_at);
|
||
|
|
|
||
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_sys_login_log_token_hash ON sys_login_log (token_hash);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_sys_login_log_auth_type ON sys_login_log (auth_type);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_sys_login_log_subject_id ON sys_login_log (subject_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_sys_login_log_bot_id ON sys_login_log (bot_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_sys_login_log_auth_source ON sys_login_log (auth_source);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_sys_login_log_created_at ON sys_login_log (created_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_sys_login_log_expires_at ON sys_login_log (expires_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_sys_login_log_last_seen_at ON sys_login_log (last_seen_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_sys_login_log_revoked_at ON sys_login_log (revoked_at);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_sys_setting_category ON sys_setting (category);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_sys_setting_is_public ON sys_setting (is_public);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_sys_setting_sort_order ON sys_setting (sort_order);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_sys_setting_updated_at ON sys_setting (updated_at);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_request_usage_bot_id ON bot_request_usage (bot_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_request_usage_message_id ON bot_request_usage (message_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_request_usage_request_id ON bot_request_usage (request_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_request_usage_channel ON bot_request_usage (channel);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_request_usage_status ON bot_request_usage (status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_request_usage_started_at ON bot_request_usage (started_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_request_usage_completed_at ON bot_request_usage (completed_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_request_usage_created_at ON bot_request_usage (created_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_request_usage_updated_at ON bot_request_usage (updated_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_request_usage_started_at_bot_id ON bot_request_usage (started_at, bot_id);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_activity_event_bot_id ON bot_activity_event (bot_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_activity_event_request_id ON bot_activity_event (request_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_activity_event_event_type ON bot_activity_event (event_type);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_activity_event_channel ON bot_activity_event (channel);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_activity_event_created_at ON bot_activity_event (created_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_activity_event_bot_id_request_present
|
||
|
|
ON bot_activity_event (bot_id)
|
||
|
|
WHERE request_id IS NOT NULL AND request_id <> '';
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_skill_market_item_created_at ON skill_market_item (created_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_skill_market_item_updated_at ON skill_market_item (updated_at);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_skill_install_bot_id ON bot_skill_install (bot_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_skill_install_skill_market_item_id ON bot_skill_install (skill_market_item_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_skill_install_status ON bot_skill_install (status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_skill_install_installed_at ON bot_skill_install (installed_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_bot_skill_install_updated_at ON bot_skill_install (updated_at);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_topic_topic_bot_id ON topic_topic (bot_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_topic_topic_topic_key ON topic_topic (topic_key);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_topic_topic_created_at ON topic_topic (created_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_topic_topic_updated_at ON topic_topic (updated_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_topic_topic_bot_fallback ON topic_topic (bot_id, is_default_fallback);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_topic_item_bot_id ON topic_item (bot_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_topic_item_topic_key ON topic_item (topic_key);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_topic_item_level ON topic_item (level);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_topic_item_source ON topic_item (source);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_topic_item_is_read ON topic_item (is_read);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_topic_item_created_at ON topic_item (created_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_topic_item_bot_topic_created_at ON topic_item (bot_id, topic_key, created_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_topic_item_bot_dedupe ON topic_item (bot_id, dedupe_key);
|
||
|
|
|
||
|
|
COMMIT;
|