feat: refactor User/Bot architecture and implement multi-channel gateway

Major changes:
1. Core Architecture: Decoupled Bots from Users. Bots now have independent lifecycles, member management (bot_members), and dedicated configurations.
2. Channel Gateway:
   - Implemented a unified Channel Manager supporting Feishu, Telegram, and Local (Web/CLI) adapters.
   - Added message processing pipeline to normalize interactions across different platforms.
   - Introduced a Contact system for identity binding and guest access policies.
3. Database & Tooling:
   - Consolidated all migrations into 0001_init with updated schema for bots, channels, and contacts.
   - Optimized sqlc.yaml to automatically track the migrations directory.
4. Agent Enhancements:
   - Introduced ToolContext to provide Agents with platform-aware execution capabilities (e.g., messaging, contact lookups).
   - Added tool logging and fallback mechanisms for toolChoice execution.
5. UI & Docs: Updated frontend stores, UI components, and Swagger documentation to align with the new Bot-centric model.
This commit is contained in:
BBQ
2026-02-04 23:49:50 +08:00
parent efd68d306d
commit 6aebbe9279
110 changed files with 18406 additions and 3709 deletions
+15 -4
View File
@@ -1,13 +1,24 @@
DROP TABLE IF EXISTS user_settings;
DROP TABLE IF EXISTS history;
DROP TABLE IF EXISTS schedule;
DROP TABLE IF EXISTS subagents;
DROP TABLE IF EXISTS schedule;
DROP TABLE IF EXISTS lifecycle_events;
DROP TABLE IF EXISTS container_versions;
DROP TABLE IF EXISTS snapshots;
DROP TABLE IF EXISTS containers;
DROP TABLE IF EXISTS channel_sessions;
DROP TABLE IF EXISTS contact_bind_tokens;
DROP TABLE IF EXISTS contact_channels;
DROP TABLE IF EXISTS contacts;
DROP TABLE IF EXISTS bot_channel_configs;
DROP TABLE IF EXISTS user_channel_bindings;
DROP TABLE IF EXISTS history;
DROP TABLE IF EXISTS conversations;
DROP TABLE IF EXISTS bot_model_configs;
DROP TABLE IF EXISTS bot_settings;
DROP TABLE IF EXISTS bot_members;
DROP TABLE IF EXISTS bots;
DROP TABLE IF EXISTS model_variants;
DROP TABLE IF EXISTS models;
DROP TABLE IF EXISTS llm_providers;
DROP TABLE IF EXISTS snapshots;
DROP TABLE IF EXISTS containers;
DROP TABLE IF EXISTS users;
DROP TYPE IF EXISTS user_role;
+208 -58
View File
@@ -25,39 +25,6 @@ CREATE TABLE IF NOT EXISTS users (
CONSTRAINT users_username_unique UNIQUE (username)
);
CREATE TABLE IF NOT EXISTS containers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
container_id TEXT NOT NULL,
container_name TEXT NOT NULL,
image TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'created',
namespace TEXT NOT NULL DEFAULT 'default',
auto_start BOOLEAN NOT NULL DEFAULT true,
host_path TEXT,
container_path TEXT NOT NULL DEFAULT '/data',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
last_started_at TIMESTAMPTZ,
last_stopped_at TIMESTAMPTZ,
CONSTRAINT containers_container_id_unique UNIQUE (container_id),
CONSTRAINT containers_container_name_unique UNIQUE (container_name)
);
CREATE INDEX IF NOT EXISTS idx_containers_user_id ON containers(user_id);
CREATE TABLE IF NOT EXISTS snapshots (
id TEXT PRIMARY KEY,
container_id TEXT NOT NULL REFERENCES containers(container_id) ON DELETE CASCADE,
parent_snapshot_id TEXT REFERENCES snapshots(id) ON DELETE SET NULL,
snapshotter TEXT NOT NULL,
digest TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_snapshots_container_id ON snapshots(container_id);
CREATE INDEX IF NOT EXISTS idx_snapshots_parent_id ON snapshots(parent_snapshot_id);
CREATE TABLE IF NOT EXISTS llm_providers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
@@ -99,6 +66,203 @@ CREATE TABLE IF NOT EXISTS model_variants (
CREATE INDEX IF NOT EXISTS idx_model_variants_model_uuid ON model_variants(model_uuid);
CREATE INDEX IF NOT EXISTS idx_model_variants_variant_id ON model_variants(variant_id);
CREATE TABLE IF NOT EXISTS bots (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
owner_user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
type TEXT NOT NULL,
display_name TEXT,
avatar_url TEXT,
is_active BOOLEAN NOT NULL DEFAULT true,
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT bots_type_check CHECK (type IN ('personal', 'public'))
);
CREATE INDEX IF NOT EXISTS idx_bots_owner_user_id ON bots(owner_user_id);
CREATE TABLE IF NOT EXISTS bot_members (
bot_id UUID NOT NULL REFERENCES bots(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
role TEXT NOT NULL DEFAULT 'member',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT bot_members_role_check CHECK (role IN ('owner', 'admin', 'member')),
CONSTRAINT bot_members_unique UNIQUE (bot_id, user_id)
);
CREATE INDEX IF NOT EXISTS idx_bot_members_user_id ON bot_members(user_id);
CREATE TABLE IF NOT EXISTS bot_settings (
bot_id UUID PRIMARY KEY REFERENCES bots(id) ON DELETE CASCADE,
max_context_load_time INTEGER NOT NULL DEFAULT 1440,
language TEXT NOT NULL DEFAULT 'Same as user input',
allow_guest BOOLEAN NOT NULL DEFAULT false
);
CREATE TABLE IF NOT EXISTS bot_model_configs (
bot_id UUID PRIMARY KEY REFERENCES bots(id) ON DELETE CASCADE,
chat_model_id UUID REFERENCES models(id) ON DELETE SET NULL,
embedding_model_id UUID REFERENCES models(id) ON DELETE SET NULL,
memory_model_id UUID REFERENCES models(id) ON DELETE SET NULL
);
CREATE TABLE IF NOT EXISTS conversations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
bot_id UUID NOT NULL REFERENCES bots(id) ON DELETE CASCADE,
session_id TEXT NOT NULL,
channel_type TEXT NOT NULL,
chat_id TEXT,
sender_id TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT conversations_session_unique UNIQUE (bot_id, session_id)
);
CREATE INDEX IF NOT EXISTS idx_conversations_bot_id ON conversations(bot_id);
CREATE TABLE IF NOT EXISTS history (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
bot_id UUID NOT NULL REFERENCES bots(id) ON DELETE CASCADE,
session_id TEXT NOT NULL,
messages JSONB NOT NULL,
skills TEXT[] NOT NULL DEFAULT '{}'::text[],
timestamp TIMESTAMPTZ NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_history_bot ON history(bot_id);
CREATE INDEX IF NOT EXISTS idx_history_session ON history(session_id);
CREATE INDEX IF NOT EXISTS idx_history_timestamp ON history(timestamp);
CREATE TABLE IF NOT EXISTS user_channel_bindings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
channel_type TEXT NOT NULL,
config JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT user_channel_bindings_unique UNIQUE (user_id, channel_type)
);
CREATE INDEX IF NOT EXISTS idx_user_channel_bindings_user_id ON user_channel_bindings(user_id);
CREATE TABLE IF NOT EXISTS bot_channel_configs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
bot_id UUID NOT NULL REFERENCES bots(id) ON DELETE CASCADE,
channel_type TEXT NOT NULL,
credentials JSONB NOT NULL DEFAULT '{}'::jsonb,
external_identity TEXT,
self_identity JSONB NOT NULL DEFAULT '{}'::jsonb,
routing JSONB NOT NULL DEFAULT '{}'::jsonb,
capabilities JSONB NOT NULL DEFAULT '{}'::jsonb,
status TEXT NOT NULL DEFAULT 'pending',
verified_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT bot_channel_status_check CHECK (status IN ('pending', 'verified', 'disabled')),
CONSTRAINT bot_channel_unique UNIQUE (bot_id, channel_type)
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_bot_channel_external_identity
ON bot_channel_configs(channel_type, external_identity);
CREATE INDEX IF NOT EXISTS idx_bot_channel_bot_id ON bot_channel_configs(bot_id);
CREATE TABLE IF NOT EXISTS contacts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
bot_id UUID NOT NULL REFERENCES bots(id) ON DELETE CASCADE,
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
display_name TEXT,
alias TEXT,
tags TEXT[] NOT NULL DEFAULT '{}'::text[],
status TEXT NOT NULL DEFAULT 'active',
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT contacts_status_check CHECK (status IN ('active', 'blocked', 'pending'))
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_contacts_bot_user_unique
ON contacts(bot_id, user_id)
WHERE user_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_contacts_bot_id ON contacts(bot_id);
CREATE TABLE IF NOT EXISTS contact_channels (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
bot_id UUID NOT NULL REFERENCES bots(id) ON DELETE CASCADE,
contact_id UUID NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
platform TEXT NOT NULL,
external_id TEXT NOT NULL,
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT contact_channels_unique UNIQUE (bot_id, platform, external_id)
);
CREATE INDEX IF NOT EXISTS idx_contact_channels_contact_id ON contact_channels(contact_id);
CREATE INDEX IF NOT EXISTS idx_contact_channels_platform_external ON contact_channels(platform, external_id);
CREATE TABLE IF NOT EXISTS contact_bind_tokens (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
bot_id UUID NOT NULL REFERENCES bots(id) ON DELETE CASCADE,
contact_id UUID NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
token TEXT NOT NULL,
target_platform TEXT,
target_external_id TEXT,
issued_by_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
expires_at TIMESTAMPTZ NOT NULL,
used_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT contact_bind_tokens_unique UNIQUE (token)
);
CREATE INDEX IF NOT EXISTS idx_contact_bind_tokens_contact_id ON contact_bind_tokens(contact_id);
CREATE INDEX IF NOT EXISTS idx_contact_bind_tokens_expires ON contact_bind_tokens(expires_at);
CREATE TABLE IF NOT EXISTS channel_sessions (
session_id TEXT PRIMARY KEY,
bot_id UUID NOT NULL REFERENCES bots(id) ON DELETE CASCADE,
channel_config_id UUID REFERENCES bot_channel_configs(id) ON DELETE SET NULL,
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
contact_id UUID REFERENCES contacts(id) ON DELETE SET NULL,
platform TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_channel_sessions_bot_id ON channel_sessions(bot_id);
CREATE INDEX IF NOT EXISTS idx_channel_sessions_user_id ON channel_sessions(user_id);
CREATE TABLE IF NOT EXISTS containers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
bot_id UUID NOT NULL REFERENCES bots(id) ON DELETE CASCADE,
container_id TEXT NOT NULL,
container_name TEXT NOT NULL,
image TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'created',
namespace TEXT NOT NULL DEFAULT 'default',
auto_start BOOLEAN NOT NULL DEFAULT true,
host_path TEXT,
container_path TEXT NOT NULL DEFAULT '/data',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
last_started_at TIMESTAMPTZ,
last_stopped_at TIMESTAMPTZ,
CONSTRAINT containers_container_id_unique UNIQUE (container_id),
CONSTRAINT containers_container_name_unique UNIQUE (container_name)
);
CREATE INDEX IF NOT EXISTS idx_containers_bot_id ON containers(bot_id);
CREATE TABLE IF NOT EXISTS snapshots (
id TEXT PRIMARY KEY,
container_id TEXT NOT NULL REFERENCES containers(container_id) ON DELETE CASCADE,
parent_snapshot_id TEXT REFERENCES snapshots(id) ON DELETE SET NULL,
snapshotter TEXT NOT NULL,
digest TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_snapshots_container_id ON snapshots(container_id);
CREATE INDEX IF NOT EXISTS idx_snapshots_parent_id ON snapshots(parent_snapshot_id);
@@ -124,26 +288,6 @@ CREATE TABLE IF NOT EXISTS lifecycle_events (
CREATE INDEX IF NOT EXISTS idx_lifecycle_events_container_id ON lifecycle_events(container_id);
CREATE INDEX IF NOT EXISTS idx_lifecycle_events_event_type ON lifecycle_events(event_type);
CREATE TABLE IF NOT EXISTS history (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
messages JSONB NOT NULL,
skills TEXT[] NOT NULL DEFAULT '{}'::text[],
timestamp TIMESTAMPTZ NOT NULL,
"user" UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_history_user ON history("user");
CREATE INDEX IF NOT EXISTS idx_history_timestamp ON history(timestamp);
CREATE TABLE IF NOT EXISTS user_settings (
user_id UUID PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
chat_model_id TEXT,
memory_model_id TEXT,
embedding_model_id TEXT,
max_context_load_time INTEGER NOT NULL DEFAULT 1440,
language TEXT NOT NULL DEFAULT 'Same as user input'
);
CREATE TABLE IF NOT EXISTS schedule (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
@@ -155,10 +299,10 @@ CREATE TABLE IF NOT EXISTS schedule (
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
enabled BOOLEAN NOT NULL DEFAULT true,
command TEXT NOT NULL,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE
bot_id UUID NOT NULL REFERENCES bots(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_schedule_user_id ON schedule(user_id);
CREATE INDEX IF NOT EXISTS idx_schedule_bot_id ON schedule(bot_id);
CREATE INDEX IF NOT EXISTS idx_schedule_enabled ON schedule(enabled);
CREATE TABLE IF NOT EXISTS subagents (
@@ -169,12 +313,18 @@ CREATE TABLE IF NOT EXISTS subagents (
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
deleted BOOLEAN NOT NULL DEFAULT false,
deleted_at TIMESTAMPTZ,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
bot_id UUID NOT NULL REFERENCES bots(id) ON DELETE CASCADE,
messages JSONB NOT NULL DEFAULT '[]'::jsonb,
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
skills JSONB NOT NULL DEFAULT '[]'::jsonb,
CONSTRAINT subagents_name_unique UNIQUE (name)
CONSTRAINT subagents_name_unique UNIQUE (bot_id, name)
);
CREATE INDEX IF NOT EXISTS idx_subagents_user_id ON subagents(user_id);
CREATE INDEX IF NOT EXISTS idx_subagents_bot_id ON subagents(bot_id);
CREATE INDEX IF NOT EXISTS idx_subagents_deleted ON subagents(deleted);
CREATE TABLE IF NOT EXISTS user_settings (
user_id UUID PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
max_context_load_time INTEGER NOT NULL DEFAULT 1440,
language TEXT NOT NULL DEFAULT 'Same as user input'
);
+64
View File
@@ -0,0 +1,64 @@
-- name: CreateBot :one
INSERT INTO bots (owner_user_id, type, display_name, avatar_url, is_active, metadata)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id, owner_user_id, type, display_name, avatar_url, is_active, metadata, created_at, updated_at;
-- name: GetBotByID :one
SELECT id, owner_user_id, type, display_name, avatar_url, is_active, metadata, created_at, updated_at
FROM bots
WHERE id = $1;
-- name: ListBotsByOwner :many
SELECT id, owner_user_id, type, display_name, avatar_url, is_active, metadata, created_at, updated_at
FROM bots
WHERE owner_user_id = $1
ORDER BY created_at DESC;
-- name: ListBotsByMember :many
SELECT b.id, b.owner_user_id, b.type, b.display_name, b.avatar_url, b.is_active, b.metadata, b.created_at, b.updated_at
FROM bots b
JOIN bot_members m ON m.bot_id = b.id
WHERE m.user_id = $1
ORDER BY b.created_at DESC;
-- name: UpdateBotProfile :one
UPDATE bots
SET display_name = $2,
avatar_url = $3,
is_active = $4,
metadata = $5,
updated_at = now()
WHERE id = $1
RETURNING id, owner_user_id, type, display_name, avatar_url, is_active, metadata, created_at, updated_at;
-- name: UpdateBotOwner :one
UPDATE bots
SET owner_user_id = $2,
updated_at = now()
WHERE id = $1
RETURNING id, owner_user_id, type, display_name, avatar_url, is_active, metadata, created_at, updated_at;
-- name: DeleteBotByID :exec
DELETE FROM bots WHERE id = $1;
-- name: UpsertBotMember :one
INSERT INTO bot_members (bot_id, user_id, role)
VALUES ($1, $2, $3)
ON CONFLICT (bot_id, user_id) DO UPDATE SET
role = EXCLUDED.role
RETURNING bot_id, user_id, role, created_at;
-- name: ListBotMembers :many
SELECT bot_id, user_id, role, created_at
FROM bot_members
WHERE bot_id = $1
ORDER BY created_at DESC;
-- name: GetBotMember :one
SELECT bot_id, user_id, role, created_at
FROM bot_members
WHERE bot_id = $1 AND user_id = $2
LIMIT 1;
-- name: DeleteBotMember :exec
DELETE FROM bot_members WHERE bot_id = $1 AND user_id = $2;
+3 -3
View File
@@ -1,10 +1,10 @@
-- name: UpsertContainer :exec
INSERT INTO containers (
user_id, container_id, container_name, image, status, namespace, auto_start,
bot_id, container_id, container_name, image, status, namespace, auto_start,
host_path, container_path, last_started_at, last_stopped_at
)
VALUES (
sqlc.arg(user_id),
sqlc.arg(bot_id),
sqlc.arg(container_id),
sqlc.arg(container_name),
sqlc.arg(image),
@@ -17,7 +17,7 @@ VALUES (
sqlc.arg(last_stopped_at)
)
ON CONFLICT (container_id) DO UPDATE SET
user_id = EXCLUDED.user_id,
bot_id = EXCLUDED.bot_id,
container_name = EXCLUDED.container_name,
image = EXCLUDED.image,
status = EXCLUDED.status,
+13 -13
View File
@@ -1,31 +1,31 @@
-- name: CreateHistory :one
INSERT INTO history (messages, skills, timestamp, "user")
VALUES ($1, $2, $3, $4)
RETURNING id, messages, skills, timestamp, "user";
INSERT INTO history (bot_id, session_id, messages, skills, timestamp)
VALUES ($1, $2, $3, $4, $5)
RETURNING id, bot_id, session_id, messages, skills, timestamp;
-- name: ListHistoryByUserSince :many
SELECT id, messages, skills, timestamp, "user"
-- name: ListHistoryByBotSessionSince :many
SELECT id, bot_id, session_id, messages, skills, timestamp
FROM history
WHERE "user" = $1 AND timestamp >= $2
WHERE bot_id = $1 AND session_id = $2 AND timestamp >= $3
ORDER BY timestamp ASC;
-- name: GetHistoryByID :one
SELECT id, messages, skills, timestamp, "user"
SELECT id, bot_id, session_id, messages, skills, timestamp
FROM history
WHERE id = $1;
-- name: ListHistoryByUser :many
SELECT id, messages, skills, timestamp, "user"
-- name: ListHistoryByBotSession :many
SELECT id, bot_id, session_id, messages, skills, timestamp
FROM history
WHERE "user" = $1
WHERE bot_id = $1 AND session_id = $2
ORDER BY timestamp DESC
LIMIT $2;
LIMIT $3;
-- name: DeleteHistoryByID :exec
DELETE FROM history
WHERE id = $1;
-- name: DeleteHistoryByUser :exec
-- name: DeleteHistoryByBotSession :exec
DELETE FROM history
WHERE "user" = $1;
WHERE bot_id = $1 AND session_id = $2;
+9 -9
View File
@@ -1,21 +1,21 @@
-- name: CreateSchedule :one
INSERT INTO schedule (name, description, pattern, max_calls, enabled, command, user_id)
INSERT INTO schedule (name, description, pattern, max_calls, enabled, command, bot_id)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING id, name, description, pattern, max_calls, current_calls, created_at, updated_at, enabled, command, user_id;
RETURNING id, name, description, pattern, max_calls, current_calls, created_at, updated_at, enabled, command, bot_id;
-- name: GetScheduleByID :one
SELECT id, name, description, pattern, max_calls, current_calls, created_at, updated_at, enabled, command, user_id
SELECT id, name, description, pattern, max_calls, current_calls, created_at, updated_at, enabled, command, bot_id
FROM schedule
WHERE id = $1;
-- name: ListSchedulesByUser :many
SELECT id, name, description, pattern, max_calls, current_calls, created_at, updated_at, enabled, command, user_id
-- name: ListSchedulesByBot :many
SELECT id, name, description, pattern, max_calls, current_calls, created_at, updated_at, enabled, command, bot_id
FROM schedule
WHERE user_id = $1
WHERE bot_id = $1
ORDER BY created_at DESC;
-- name: ListEnabledSchedules :many
SELECT id, name, description, pattern, max_calls, current_calls, created_at, updated_at, enabled, command, user_id
SELECT id, name, description, pattern, max_calls, current_calls, created_at, updated_at, enabled, command, bot_id
FROM schedule
WHERE enabled = true
ORDER BY created_at DESC;
@@ -30,7 +30,7 @@ SET name = $2,
command = $7,
updated_at = now()
WHERE id = $1
RETURNING id, name, description, pattern, max_calls, current_calls, created_at, updated_at, enabled, command, user_id;
RETURNING id, name, description, pattern, max_calls, current_calls, created_at, updated_at, enabled, command, bot_id;
-- name: DeleteSchedule :exec
DELETE FROM schedule
@@ -45,5 +45,5 @@ SET current_calls = current_calls + 1,
END,
updated_at = now()
WHERE id = $1
RETURNING id, name, description, pattern, max_calls, current_calls, created_at, updated_at, enabled, command, user_id;
RETURNING id, name, description, pattern, max_calls, current_calls, created_at, updated_at, enabled, command, bot_id;
+18 -4
View File
@@ -3,7 +3,7 @@ SELECT user_id, chat_model_id, memory_model_id, embedding_model_id, max_context_
FROM user_settings
WHERE user_id = $1;
-- name: UpsertSettings :one
-- name: UpsertUserSettings :one
INSERT INTO user_settings (user_id, chat_model_id, memory_model_id, embedding_model_id, max_context_load_time, language)
VALUES ($1, $2, $3, $4, $5, $6)
ON CONFLICT (user_id) DO UPDATE SET
@@ -14,7 +14,21 @@ ON CONFLICT (user_id) DO UPDATE SET
language = EXCLUDED.language
RETURNING user_id, chat_model_id, memory_model_id, embedding_model_id, max_context_load_time, language;
-- name: DeleteSettingsByUserID :exec
DELETE FROM user_settings
WHERE user_id = $1;
-- name: GetSettingsByBotID :one
SELECT bot_id, max_context_load_time, language, allow_guest
FROM bot_settings
WHERE bot_id = $1;
-- name: UpsertBotSettings :one
INSERT INTO bot_settings (bot_id, max_context_load_time, language, allow_guest)
VALUES ($1, $2, $3, $4)
ON CONFLICT (bot_id) DO UPDATE SET
max_context_load_time = EXCLUDED.max_context_load_time,
language = EXCLUDED.language,
allow_guest = EXCLUDED.allow_guest
RETURNING bot_id, max_context_load_time, language, allow_guest;
-- name: DeleteSettingsByBotID :exec
DELETE FROM bot_settings
WHERE bot_id = $1;
+9 -9
View File
@@ -1,17 +1,17 @@
-- name: CreateSubagent :one
INSERT INTO subagents (name, description, user_id, messages, metadata, skills)
INSERT INTO subagents (name, description, bot_id, messages, metadata, skills)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, user_id, messages, metadata, skills;
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills;
-- name: GetSubagentByID :one
SELECT id, name, description, created_at, updated_at, deleted, deleted_at, user_id, messages, metadata, skills
SELECT id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills
FROM subagents
WHERE id = $1 AND deleted = false;
-- name: ListSubagentsByUser :many
SELECT id, name, description, created_at, updated_at, deleted, deleted_at, user_id, messages, metadata, skills
-- name: ListSubagentsByBot :many
SELECT id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills
FROM subagents
WHERE user_id = $1 AND deleted = false
WHERE bot_id = $1 AND deleted = false
ORDER BY created_at DESC;
-- name: UpdateSubagent :one
@@ -21,21 +21,21 @@ SET name = $2,
metadata = $4,
updated_at = now()
WHERE id = $1 AND deleted = false
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, user_id, messages, metadata, skills;
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills;
-- name: UpdateSubagentMessages :one
UPDATE subagents
SET messages = $2,
updated_at = now()
WHERE id = $1 AND deleted = false
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, user_id, messages, metadata, skills;
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills;
-- name: UpdateSubagentSkills :one
UPDATE subagents
SET skills = $2,
updated_at = now()
WHERE id = $1 AND deleted = false
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, user_id, messages, metadata, skills;
RETURNING id, name, description, created_at, updated_at, deleted, deleted_at, bot_id, messages, metadata, skills;
-- name: SoftDeleteSubagent :exec
UPDATE subagents
+45 -3
View File
@@ -4,7 +4,7 @@ VALUES (
sqlc.arg(username),
sqlc.arg(email),
sqlc.arg(password_hash),
sqlc.arg(role),
sqlc.arg(role)::user_role,
sqlc.arg(display_name),
sqlc.arg(avatar_url),
sqlc.arg(is_active),
@@ -18,7 +18,7 @@ VALUES (
sqlc.arg(username),
sqlc.arg(email),
sqlc.arg(password_hash),
sqlc.arg(role),
sqlc.arg(role)::user_role,
sqlc.arg(display_name),
sqlc.arg(avatar_url),
sqlc.arg(is_active),
@@ -38,6 +38,9 @@ RETURNING *;
-- name: GetUserByUsername :one
SELECT * FROM users WHERE username = sqlc.arg(username);
-- name: GetUserByIdentity :one
SELECT * FROM users WHERE username = sqlc.arg(identity) OR email = sqlc.arg(identity);
-- name: GetUserByID :one
SELECT * FROM users WHERE id = sqlc.arg(id);
@@ -48,7 +51,7 @@ VALUES (
sqlc.arg(username),
sqlc.arg(email),
sqlc.arg(password_hash),
sqlc.arg(role),
sqlc.arg(role)::user_role,
sqlc.arg(display_name),
sqlc.arg(avatar_url),
sqlc.arg(is_active),
@@ -58,3 +61,42 @@ RETURNING *;
-- name: CountUsers :one
SELECT COUNT(*)::bigint AS count FROM users;
-- name: ListUsers :many
SELECT * FROM users
ORDER BY created_at DESC;
-- name: UpdateUserProfile :one
UPDATE users
SET display_name = $2,
avatar_url = $3,
is_active = $4,
updated_at = now()
WHERE id = $1
RETURNING *;
-- name: UpdateUserAdmin :one
UPDATE users
SET role = sqlc.arg(role)::user_role,
display_name = sqlc.arg(display_name),
avatar_url = sqlc.arg(avatar_url),
is_active = sqlc.arg(is_active),
updated_at = now()
WHERE id = sqlc.arg(id)
RETURNING *;
-- name: UpdateUserPassword :one
UPDATE users
SET password_hash = $2,
updated_at = now()
WHERE id = $1
RETURNING *;
-- name: UpdateUserLastLogin :one
UPDATE users
SET last_login_at = now(),
updated_at = now()
WHERE id = $1
RETURNING *;