/**
 * Migration: upgrade
 * Version: 26.0.0
 * Generated: 2026-03-31T07:55:28.611Z
 *
 * This migration was automatically generated by TypeORM
 * based on entity definition changes.
 */

import { MigrationInterface, QueryRunner } from "typeorm";

export class Migration1774943726484 implements MigrationInterface {
    name = "Migration1774943726484";

    public async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(
            `ALTER TABLE "ai_agent_annotation" DROP CONSTRAINT IF EXISTS "FK_1b7295e37ffc1156e34f650949e"`,
        );
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_00ed9f001cbfe4eaa9ffb4640e"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_b95504e424a3874b0e15a4f6ca"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_d0f3b0eaba0207b6ebc5421fa2"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."idx_annotation_reviewed_by"`);
        await queryRunner.query(
            `DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'ai_mcp_servers' AND column_name = 'custom_headers') THEN ALTER TABLE "ai_mcp_servers" RENAME COLUMN "custom_headers" TO "headers"; END IF; END $$`,
        );
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "datasets_chat_message" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "conversation_id" uuid NOT NULL, "model_id" uuid, "sequence" integer NOT NULL, "parent_id" character varying(36), "frontend_id" character varying(64), "message" jsonb NOT NULL, "status" character varying(20) NOT NULL DEFAULT 'completed', "error_message" text, "usage" jsonb, CONSTRAINT "PK_5fe94be1d1701c6bb2e0368d643" PRIMARY KEY ("id")); COMMENT ON COLUMN "datasets_chat_message"."conversation_id" IS '所属对话ID'; COMMENT ON COLUMN "datasets_chat_message"."model_id" IS '消息使用的AI模型ID'; COMMENT ON COLUMN "datasets_chat_message"."sequence" IS '在对话中的消息序号'; COMMENT ON COLUMN "datasets_chat_message"."parent_id" IS '父消息ID（用于消息树结构）'; COMMENT ON COLUMN "datasets_chat_message"."frontend_id" IS '前端消息ID（用于映射前端临时ID到数据库ID）'; COMMENT ON COLUMN "datasets_chat_message"."message" IS '消息内容（包含 role 和 parts）'; COMMENT ON COLUMN "datasets_chat_message"."status" IS '消息状态: streaming-流式传输中, completed-已完成, failed-失败'; COMMENT ON COLUMN "datasets_chat_message"."error_message" IS '错误信息'; COMMENT ON COLUMN "datasets_chat_message"."usage" IS 'Token使用情况'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_5fe94be1d1701c6bb2e0368d64" ON "datasets_chat_message" ("id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_f42cb8e4f363b05770e5e54985" ON "datasets_chat_message" ("model_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_7d4e8f759ac53f58cc33ae5db7" ON "datasets_chat_message" ("sequence") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_15c4fcf8078809f95081f7ce31" ON "datasets_chat_message" ("parent_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_9685e85792d18ca408ffebbfd3" ON "datasets_chat_message" ("frontend_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_0881581b3999a29ff574c0ce88" ON "datasets_chat_message" ("conversation_id", "created_at") `,
        );
        await queryRunner.query(`COMMENT ON TABLE "datasets_chat_message" IS '知识库调试对话消息'`);
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "datasets_chat_record" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "dataset_id" uuid NOT NULL, "user_id" uuid NOT NULL, "title" character varying(200), "model_id" uuid, "summary" text, "message_count" integer NOT NULL DEFAULT '0', "total_tokens" integer NOT NULL DEFAULT '0', "config" jsonb, "status" character varying(20) NOT NULL DEFAULT 'active', "is_deleted" boolean NOT NULL DEFAULT false, "metadata" jsonb, CONSTRAINT "PK_4ac5f12827b3ff676d554caec6c" PRIMARY KEY ("id")); COMMENT ON COLUMN "datasets_chat_record"."dataset_id" IS '关联的知识库ID'; COMMENT ON COLUMN "datasets_chat_record"."user_id" IS '用户ID（调试人）'; COMMENT ON COLUMN "datasets_chat_record"."title" IS '对话标题'; COMMENT ON COLUMN "datasets_chat_record"."model_id" IS '使用的AI模型ID'; COMMENT ON COLUMN "datasets_chat_record"."summary" IS '对话摘要'; COMMENT ON COLUMN "datasets_chat_record"."message_count" IS '对话中的消息总数'; COMMENT ON COLUMN "datasets_chat_record"."total_tokens" IS '本次对话消耗的总Token数'; COMMENT ON COLUMN "datasets_chat_record"."config" IS '对话相关配置，如温度、最大令牌数等'; COMMENT ON COLUMN "datasets_chat_record"."status" IS '对话状态: active-进行中, completed-已完成, failed-失败, cancelled-已取消'; COMMENT ON COLUMN "datasets_chat_record"."is_deleted" IS '是否已删除'; COMMENT ON COLUMN "datasets_chat_record"."metadata" IS '扩展数据字段'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_4ac5f12827b3ff676d554caec6" ON "datasets_chat_record" ("id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_96bb837b36ff4f4329ece6c756" ON "datasets_chat_record" ("dataset_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_a5cad699344f07a7406d12fc0f" ON "datasets_chat_record" ("user_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_ac9701a784b76c7d0d1f139a2f" ON "datasets_chat_record" ("status") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_64bdebacddf9c1f550b34ad6db" ON "datasets_chat_record" ("is_deleted") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_622f8dcf924d88933939aeca4c" ON "datasets_chat_record" ("is_deleted", "created_at") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_af85e8f3d176b922b11faac584" ON "datasets_chat_record" ("user_id", "created_at") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_d89f8f55fd64aeea7322af4d98" ON "datasets_chat_record" ("dataset_id", "created_at") `,
        );
        await queryRunner.query(`COMMENT ON TABLE "datasets_chat_record" IS '知识库调试对话记录'`);
        await queryRunner.query(
            `DO $$ BEGIN CREATE TYPE "public"."member_application_status" AS ENUM('pending', 'approved', 'rejected'); EXCEPTION WHEN duplicate_object THEN NULL; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN CREATE TYPE "public"."dataset_member_applications_applied_role_enum" AS ENUM('owner', 'manager', 'editor', 'viewer'); EXCEPTION WHEN duplicate_object THEN NULL; END $$`,
        );
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "dataset_member_applications" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "dataset_id" uuid NOT NULL, "user_id" uuid NOT NULL, "status" "public"."member_application_status" NOT NULL DEFAULT 'pending', "applied_role" "public"."dataset_member_applications_applied_role_enum" NOT NULL DEFAULT 'viewer', "message" text, "reviewed_by" uuid, "reviewed_at" TIMESTAMP WITH TIME ZONE, "reject_reason" text, CONSTRAINT "PK_4032850cf7c0528031b995b8ed4" PRIMARY KEY ("id")); COMMENT ON COLUMN "dataset_member_applications"."dataset_id" IS '知识库ID'; COMMENT ON COLUMN "dataset_member_applications"."user_id" IS '申请人用户ID'; COMMENT ON COLUMN "dataset_member_applications"."status" IS '申请状态：pending-待审核，approved-已通过，rejected-已拒绝'; COMMENT ON COLUMN "dataset_member_applications"."applied_role" IS '申请的角色（通过后赋予）'; COMMENT ON COLUMN "dataset_member_applications"."message" IS '申请留言'; COMMENT ON COLUMN "dataset_member_applications"."reviewed_by" IS '审核人ID'; COMMENT ON COLUMN "dataset_member_applications"."reviewed_at" IS '审核时间'; COMMENT ON COLUMN "dataset_member_applications"."reject_reason" IS '拒绝原因'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_4032850cf7c0528031b995b8ed" ON "dataset_member_applications" ("id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_ec1cc76a3db62ec53d87aba884" ON "dataset_member_applications" ("user_id", "status") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_b4a503361221499c7adfbce1e5" ON "dataset_member_applications" ("dataset_id", "status") `,
        );
        await queryRunner.query(
            `COMMENT ON TABLE "dataset_member_applications" IS '知识库会员申请列表'`,
        );
        await queryRunner.query(
            `DO $$ BEGIN CREATE TYPE "public"."sms_config_provider_enum" AS ENUM('aliyun', 'tencent'); EXCEPTION WHEN duplicate_object THEN NULL; END $$`,
        );
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "sms_config" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "provider" "public"."sms_config_provider_enum" NOT NULL, "enable" boolean NOT NULL DEFAULT false, "sort" integer NOT NULL DEFAULT '0', "provider_config" jsonb, CONSTRAINT "PK_5747a22aa47df1c51d160d902b7" PRIMARY KEY ("id")); COMMENT ON COLUMN "sms_config"."provider" IS '提供商'; COMMENT ON COLUMN "sms_config"."enable" IS '是否使用'; COMMENT ON COLUMN "sms_config"."sort" IS '排序'; COMMENT ON COLUMN "sms_config"."provider_config" IS '具体配置'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_5747a22aa47df1c51d160d902b" ON "sms_config" ("id") `,
        );
        await queryRunner.query(`COMMENT ON TABLE "sms_config" IS '短信服务配置'`);
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "notice" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "scene_code" character varying(16) NOT NULL, "scene_name" character varying(32) NOT NULL, "scene_desc" character varying(128), "recipient" integer NOT NULL DEFAULT '1', "notice_type" integer NOT NULL DEFAULT '1', "sms_notice" jsonb DEFAULT '{}', "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), CONSTRAINT "PK_705062b14410ff1a04998f86d72" PRIMARY KEY ("id")); COMMENT ON COLUMN "notice"."scene_code" IS '场景编码'; COMMENT ON COLUMN "notice"."scene_name" IS '场景名称'; COMMENT ON COLUMN "notice"."scene_desc" IS '场景描述'; COMMENT ON COLUMN "notice"."recipient" IS '接收者 1-用户 2-平台'; COMMENT ON COLUMN "notice"."notice_type" IS '通知类型: 1-验证码 2-业务通知'; COMMENT ON COLUMN "notice"."sms_notice" IS '短信通知配置'`,
        );
        await queryRunner.query(`COMMENT ON TABLE "notice" IS '通知管理'`);
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "department" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "name" character varying NOT NULL, "parent_id" uuid, "level" integer NOT NULL DEFAULT '1', "system" integer NOT NULL DEFAULT '0', CONSTRAINT "PK_9a2213262c1593bffb581e382f5" PRIMARY KEY ("id")); COMMENT ON COLUMN "department"."name" IS '部门名称'; COMMENT ON COLUMN "department"."parent_id" IS '父部门ID'; COMMENT ON COLUMN "department"."level" IS '部门层级'; COMMENT ON COLUMN "department"."system" IS '是否系统部门'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_9a2213262c1593bffb581e382f" ON "department" ("id") `,
        );
        await queryRunner.query(`COMMENT ON TABLE "department" IS '部门'`);
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "department_user_index" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "department_id" uuid NOT NULL, "user_id" uuid NOT NULL, CONSTRAINT "PK_c3f1ce24c1b3da469b5e7a5d67a" PRIMARY KEY ("id")); COMMENT ON COLUMN "department_user_index"."department_id" IS '部门ID'; COMMENT ON COLUMN "department_user_index"."user_id" IS 'userId'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_c3f1ce24c1b3da469b5e7a5d67" ON "department_user_index" ("id") `,
        );
        await queryRunner.query(`COMMENT ON TABLE "department_user_index" IS '部门用户索引'`);
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "department_principal" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "department_id" uuid NOT NULL, "user_id" uuid NOT NULL, CONSTRAINT "PK_c4d429460edbcd5f9dad9e351fd" PRIMARY KEY ("id")); COMMENT ON COLUMN "department_principal"."department_id" IS '部门id'; COMMENT ON COLUMN "department_principal"."user_id" IS '负责人id'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_c4d429460edbcd5f9dad9e351f" ON "department_principal" ("id") `,
        );
        await queryRunner.query(`COMMENT ON TABLE "department_principal" IS '部门负责人'`);
        await queryRunner.query(
            `DO $$ BEGIN CREATE TYPE "public"."card_batch_redeem_type_enum" AS ENUM('1', '2'); EXCEPTION WHEN duplicate_object THEN NULL; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN CREATE TYPE "public"."card_batch_membership_duration_enum" AS ENUM('1', '2', '3', '4', '5', '6'); EXCEPTION WHEN duplicate_object THEN NULL; END $$`,
        );
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "card_batch" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "batch_no" character varying(12) NOT NULL, "name" character varying(100) NOT NULL, "redeem_type" "public"."card_batch_redeem_type_enum" NOT NULL, "level_id" uuid, "membership_duration" "public"."card_batch_membership_duration_enum", "custom_duration" jsonb, "points_amount" integer, "expire_at" TIMESTAMP WITH TIME ZONE NOT NULL, "total_count" integer NOT NULL, "remark" text, CONSTRAINT "UQ_06e9d8eb6d809d03d74f2538566" UNIQUE ("batch_no"), CONSTRAINT "PK_8872d22ce9660b4ed97e00da14c" PRIMARY KEY ("id")); COMMENT ON COLUMN "card_batch"."batch_no" IS '批次编号'; COMMENT ON COLUMN "card_batch"."name" IS '卡密名称'; COMMENT ON COLUMN "card_batch"."redeem_type" IS '兑换类型'; COMMENT ON COLUMN "card_batch"."level_id" IS '会员等级ID'; COMMENT ON COLUMN "card_batch"."membership_duration" IS '会员时长配置'; COMMENT ON COLUMN "card_batch"."custom_duration" IS '自定义会员时长'; COMMENT ON COLUMN "card_batch"."points_amount" IS '积分数量'; COMMENT ON COLUMN "card_batch"."expire_at" IS '到期时间'; COMMENT ON COLUMN "card_batch"."total_count" IS '生成数量'; COMMENT ON COLUMN "card_batch"."remark" IS '备注'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_8872d22ce9660b4ed97e00da14" ON "card_batch" ("id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_06e9d8eb6d809d03d74f253856" ON "card_batch" ("batch_no") `,
        );
        await queryRunner.query(`COMMENT ON TABLE "card_batch" IS '卡密批次'`);
        await queryRunner.query(
            `DO $$ BEGIN CREATE TYPE "public"."cdk_status_enum" AS ENUM('0', '1', '2'); EXCEPTION WHEN duplicate_object THEN NULL; END $$`,
        );
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "cdk" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "key_code" character varying(12) NOT NULL, "batch_id" uuid NOT NULL, "status" "public"."cdk_status_enum" NOT NULL DEFAULT '0', "user_id" uuid, "used_at" TIMESTAMP WITH TIME ZONE, CONSTRAINT "UQ_5b3f4c4c8b8a6421180e3702610" UNIQUE ("key_code"), CONSTRAINT "PK_f659070fa8811faed4ccf9e8468" PRIMARY KEY ("id")); COMMENT ON COLUMN "cdk"."key_code" IS '卡密编号'; COMMENT ON COLUMN "cdk"."batch_id" IS '批次ID'; COMMENT ON COLUMN "cdk"."status" IS '使用状态'; COMMENT ON COLUMN "cdk"."user_id" IS '使用用户ID'; COMMENT ON COLUMN "cdk"."used_at" IS '使用时间'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_f659070fa8811faed4ccf9e846" ON "cdk" ("id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_5b3f4c4c8b8a6421180e370261" ON "cdk" ("key_code") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_86ed0054aaa02957d45e0d37c5" ON "cdk" ("batch_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_14982790fd83b4a19735df99cc" ON "cdk" ("status") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_aef43a6f7f88c0e8cf8393d590" ON "cdk" ("user_id") `,
        );
        await queryRunner.query(`COMMENT ON TABLE "cdk" IS '卡密'`);
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "ai_user_memory" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "user_id" uuid NOT NULL, "content" text NOT NULL, "category" character varying(50) NOT NULL, "source" character varying(255), "source_agent_id" uuid, "metadata" jsonb, "is_active" boolean NOT NULL DEFAULT true, CONSTRAINT "PK_dd1178bc48bd857bd3780babe61" PRIMARY KEY ("id")); COMMENT ON COLUMN "ai_user_memory"."user_id" IS '用户ID'; COMMENT ON COLUMN "ai_user_memory"."content" IS '记忆内容'; COMMENT ON COLUMN "ai_user_memory"."category" IS '记忆分类'; COMMENT ON COLUMN "ai_user_memory"."source" IS '来源会话ID'; COMMENT ON COLUMN "ai_user_memory"."source_agent_id" IS '来源智能体ID'; COMMENT ON COLUMN "ai_user_memory"."metadata" IS '扩展元数据'; COMMENT ON COLUMN "ai_user_memory"."is_active" IS '是否有效'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_dd1178bc48bd857bd3780babe6" ON "ai_user_memory" ("id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_eb317b1104d6dac6d2023674f1" ON "ai_user_memory" ("user_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_d628e065abe29f02666c47a477" ON "ai_user_memory" ("user_id", "is_active", "created_at") `,
        );
        await queryRunner.query(`COMMENT ON TABLE "ai_user_memory" IS '用户全局记忆'`);
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "ai_chat_tool_call" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "message_id" uuid NOT NULL, "conversation_id" uuid NOT NULL, "tool_call_id" character varying(100) NOT NULL, "type" character varying(20) NOT NULL, "name" character varying(100) NOT NULL, "arguments" jsonb, "result" jsonb, "status" character varying(20) NOT NULL DEFAULT 'pending', "error_message" text, "duration" integer, "mcp_server_id" uuid, "sequence" integer NOT NULL, "metadata" jsonb, CONSTRAINT "PK_26a0f17c06e8354ac11197bc234" PRIMARY KEY ("id")); COMMENT ON COLUMN "ai_chat_tool_call"."message_id" IS '关联的消息ID（工具调用发起消息）'; COMMENT ON COLUMN "ai_chat_tool_call"."conversation_id" IS '所属会话ID'; COMMENT ON COLUMN "ai_chat_tool_call"."tool_call_id" IS '工具调用唯一标识符'; COMMENT ON COLUMN "ai_chat_tool_call"."type" IS '工具类型: function-函数调用, mcp-MCP工具'; COMMENT ON COLUMN "ai_chat_tool_call"."name" IS '工具名称'; COMMENT ON COLUMN "ai_chat_tool_call"."arguments" IS '工具调用参数'; COMMENT ON COLUMN "ai_chat_tool_call"."result" IS '工具执行结果'; COMMENT ON COLUMN "ai_chat_tool_call"."status" IS '执行状态: pending-等待执行, executing-执行中, completed-已完成, failed-失败'; COMMENT ON COLUMN "ai_chat_tool_call"."error_message" IS '错误信息（当状态为failed时）'; COMMENT ON COLUMN "ai_chat_tool_call"."duration" IS '工具执行耗时（毫秒）'; COMMENT ON COLUMN "ai_chat_tool_call"."mcp_server_id" IS 'MCP服务器ID（type为mcp时使用）'; COMMENT ON COLUMN "ai_chat_tool_call"."sequence" IS '在同一消息中的工具调用序号'; COMMENT ON COLUMN "ai_chat_tool_call"."metadata" IS '扩展数据字段'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_26a0f17c06e8354ac11197bc23" ON "ai_chat_tool_call" ("id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_18bf46d4c3599b04afa1251934" ON "ai_chat_tool_call" ("message_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_6bb46b80eb0310f3dd11f34fec" ON "ai_chat_tool_call" ("conversation_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_75b4acef3b1d2f2ca5ad30eb7a" ON "ai_chat_tool_call" ("tool_call_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_9a53ec799510aa057baab7a483" ON "ai_chat_tool_call" ("type") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_86344badc858b35f022ca7cb60" ON "ai_chat_tool_call" ("name") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_4df73ea323e64345d149a260e4" ON "ai_chat_tool_call" ("status") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_6274fd4cd331e21ddbe8cb9c37" ON "ai_chat_tool_call" ("mcp_server_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_29306703decd21657bac34df8e" ON "ai_chat_tool_call" ("status", "created_at") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_df76be3aaf61579d0725c622d9" ON "ai_chat_tool_call" ("conversation_id", "created_at") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_a2ffcb5043f71c52568a7080dd" ON "ai_chat_tool_call" ("message_id", "sequence") `,
        );
        await queryRunner.query(`COMMENT ON TABLE "ai_chat_tool_call" IS '对话工具调用记录'`);
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "ai_chat_feedback" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "message_id" uuid NOT NULL, "conversation_id" uuid NOT NULL, "user_id" uuid, "type" character varying(20) NOT NULL, "dislike_reason" character varying(100), "confidence_score" numeric(3,2) NOT NULL DEFAULT '0.5', CONSTRAINT "PK_22d87c38427b45f51c2511e3998" PRIMARY KEY ("id")); COMMENT ON COLUMN "ai_chat_feedback"."message_id" IS '消息ID'; COMMENT ON COLUMN "ai_chat_feedback"."conversation_id" IS '对话ID'; COMMENT ON COLUMN "ai_chat_feedback"."user_id" IS '用户ID'; COMMENT ON COLUMN "ai_chat_feedback"."type" IS '反馈类型: like-点赞, dislike-踩'; COMMENT ON COLUMN "ai_chat_feedback"."dislike_reason" IS '不喜欢的原因'; COMMENT ON COLUMN "ai_chat_feedback"."confidence_score" IS '置信度分数 (0-1)，用于智能判断：用户是否犹豫、是否连续点踩、是否撤销'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_22d87c38427b45f51c2511e399" ON "ai_chat_feedback" ("id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_43538779da0206a985468504de" ON "ai_chat_feedback" ("message_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_041b2e7711150958546a457ad8" ON "ai_chat_feedback" ("conversation_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_1c4e8fa17f9bcf0708ccd81bfc" ON "ai_chat_feedback" ("user_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_907884fb146162b020cef41b3f" ON "ai_chat_feedback" ("message_id", "user_id", "conversation_id") `,
        );
        await queryRunner.query(`COMMENT ON TABLE "ai_chat_feedback" IS 'AI对话反馈'`);
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "ai_agent_memory" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "user_id" uuid NOT NULL, "agent_id" uuid NOT NULL, "content" text NOT NULL, "category" character varying(50) NOT NULL, "source" character varying(255), "metadata" jsonb, "is_active" boolean NOT NULL DEFAULT true, CONSTRAINT "PK_9d0ce5d5b9340ec1db0ea717cb3" PRIMARY KEY ("id")); COMMENT ON COLUMN "ai_agent_memory"."user_id" IS '用户ID'; COMMENT ON COLUMN "ai_agent_memory"."agent_id" IS '智能体ID'; COMMENT ON COLUMN "ai_agent_memory"."content" IS '记忆内容'; COMMENT ON COLUMN "ai_agent_memory"."category" IS '记忆分类'; COMMENT ON COLUMN "ai_agent_memory"."source" IS '来源会话ID'; COMMENT ON COLUMN "ai_agent_memory"."metadata" IS '扩展元数据'; COMMENT ON COLUMN "ai_agent_memory"."is_active" IS '是否有效'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_9d0ce5d5b9340ec1db0ea717cb" ON "ai_agent_memory" ("id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_32789c775b08871ddee3a54632" ON "ai_agent_memory" ("user_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_f94ebc85afdf40ac5cb3b201eb" ON "ai_agent_memory" ("agent_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_3f3d56aba995261cd6b633cbde" ON "ai_agent_memory" ("user_id", "agent_id", "is_active", "created_at") `,
        );
        await queryRunner.query(`COMMENT ON TABLE "ai_agent_memory" IS '智能体专属记忆'`);
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "ai_agent_chat_message_feedback" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "message_id" uuid NOT NULL, "conversation_id" uuid NOT NULL, "user_id" uuid, "type" character varying(20) NOT NULL, "dislike_reason" character varying(100), "confidence_score" numeric(3,2) NOT NULL DEFAULT '0.5', CONSTRAINT "PK_94d7c76e1d851a8acfb3e429335" PRIMARY KEY ("id")); COMMENT ON COLUMN "ai_agent_chat_message_feedback"."message_id" IS '消息ID'; COMMENT ON COLUMN "ai_agent_chat_message_feedback"."conversation_id" IS '对话ID'; COMMENT ON COLUMN "ai_agent_chat_message_feedback"."user_id" IS '用户ID'; COMMENT ON COLUMN "ai_agent_chat_message_feedback"."type" IS '反馈类型: like-点赞, dislike-踩'; COMMENT ON COLUMN "ai_agent_chat_message_feedback"."dislike_reason" IS '不喜欢的原因'; COMMENT ON COLUMN "ai_agent_chat_message_feedback"."confidence_score" IS '置信度分数 (0-1)，用于智能判断：用户是否犹豫、是否连续点踩、是否撤销'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_94d7c76e1d851a8acfb3e42933" ON "ai_agent_chat_message_feedback" ("id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_cc265cd43a64ff9a9745125b64" ON "ai_agent_chat_message_feedback" ("message_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_54a082e0c04971c99ce2165ba5" ON "ai_agent_chat_message_feedback" ("conversation_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_0026b3408f0040f59863a4b722" ON "ai_agent_chat_message_feedback" ("user_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_353756e948d70ac3227fdf64ef" ON "ai_agent_chat_message_feedback" ("message_id", "user_id", "conversation_id") `,
        );
        await queryRunner.query(
            `COMMENT ON TABLE "ai_agent_chat_message_feedback" IS '智能体对话消息反馈'`,
        );
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "user_config" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "user_id" uuid NOT NULL, "key" character varying(100) NOT NULL, "value" jsonb NOT NULL, "group" character varying(50) NOT NULL DEFAULT 'default', "description" character varying(255), CONSTRAINT "PK_5cb73472aaca5c0cf69e74d870e" PRIMARY KEY ("id")); COMMENT ON COLUMN "user_config"."user_id" IS '用户ID'; COMMENT ON COLUMN "user_config"."key" IS '配置键'; COMMENT ON COLUMN "user_config"."value" IS '配置值(JSONB格式)'; COMMENT ON COLUMN "user_config"."group" IS '配置分组'; COMMENT ON COLUMN "user_config"."description" IS '配置描述'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_5cb73472aaca5c0cf69e74d870" ON "user_config" ("id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_8c72fcf81a78b388f0503f6764" ON "user_config" ("user_id") `,
        );
        await queryRunner.query(
            `CREATE UNIQUE INDEX IF NOT EXISTS "UQ_user_dict_user_key_group" ON "user_config" ("user_id", "key", "group") `,
        );
        await queryRunner.query(`COMMENT ON TABLE "user_config" IS '用户个人配置字典'`);
        await queryRunner.query(
            `CREATE TABLE IF NOT EXISTS "datasets_tags" ("dataset_id" uuid NOT NULL, "tag_id" uuid NOT NULL, CONSTRAINT "PK_6913b97f553574e185dd92481a5" PRIMARY KEY ("dataset_id", "tag_id"))`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_88e56e216d926163f3895104f0" ON "datasets_tags" ("dataset_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_6036b74579c7c11571e7f8f06c" ON "datasets_tags" ("tag_id") `,
        );
        await queryRunner.query(`ALTER TABLE "ai_providers" DROP COLUMN IF EXISTS "website_url"`);
        await queryRunner.query(`ALTER TABLE "datasets" DROP COLUMN IF EXISTS "indexing_config"`);
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "enable_feedback"`);
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "billing_config"`);
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "is_published"`);
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "is_public"`);
        await queryRunner.query(
            `ALTER TABLE "ai_agent" DROP CONSTRAINT IF EXISTS "UQ_8b75ecd46770aa60d094b3e2f22"`,
        );
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "publish_token"`);
        await queryRunner.query(
            `ALTER TABLE "ai_agent" DROP CONSTRAINT IF EXISTS "UQ_fd2402541080fb42d890ff0c2ff"`,
        );
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "api_key"`);
        await queryRunner.query(`ALTER TABLE "user_subscription" DROP COLUMN IF EXISTS "source"`);
        await queryRunner.query(`ALTER TABLE "ai_chat_message" DROP COLUMN IF EXISTS "role"`);
        await queryRunner.query(`ALTER TABLE "ai_chat_message" DROP COLUMN IF EXISTS "content"`);
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" DROP COLUMN IF EXISTS "message_type"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" DROP COLUMN IF EXISTS "attachments"`,
        );
        await queryRunner.query(`ALTER TABLE "ai_chat_message" DROP COLUMN IF EXISTS "tokens"`);
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" DROP COLUMN IF EXISTS "user_consumed_power"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" DROP COLUMN IF EXISTS "processing_time"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" DROP COLUMN IF EXISTS "raw_response"`,
        );
        await queryRunner.query(`ALTER TABLE "ai_chat_message" DROP COLUMN IF EXISTS "metadata"`);
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" DROP COLUMN IF EXISTS "mcp_tool_calls"`,
        );
        // Pre-migrate ai_chat_message: populate new `message` column from old `role`+`content` before dropping them
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" ADD COLUMN IF NOT EXISTS "message" jsonb`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'ai_chat_message' AND column_name = 'role') THEN UPDATE "ai_chat_message" SET "message" = jsonb_build_object('role', "role", 'parts', COALESCE("content", '[]'::jsonb)) WHERE "message" IS NULL; END IF; END $$`,
        );
        // Pre-migrate ai_agent_chat_message: populate new `message` column from old `role`+`content` before dropping them
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" ADD COLUMN IF NOT EXISTS "message" jsonb`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'ai_agent_chat_message' AND column_name = 'role') THEN UPDATE "ai_agent_chat_message" SET "message" = jsonb_build_object('role', "role"::text, 'parts', COALESCE("content", '[]'::jsonb)) WHERE "message" IS NULL; END IF; END $$`,
        );
        await queryRunner.query(
            `UPDATE "ai_agent_chat_message" SET "message" = '{"role":"user","parts":[]}'::jsonb WHERE "message" IS NULL`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" ALTER COLUMN "message" SET NOT NULL`,
        );
        await queryRunner.query(`ALTER TABLE "ai_agent_chat_message" DROP COLUMN IF EXISTS "role"`);
        await queryRunner.query(`DROP TYPE IF EXISTS "public"."ai_agent_chat_message_role_enum"`);
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" DROP COLUMN IF EXISTS "content"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" DROP COLUMN IF EXISTS "message_type"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" DROP COLUMN IF EXISTS "attachments"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" DROP COLUMN IF EXISTS "tokens"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" DROP COLUMN IF EXISTS "metadata"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" DROP COLUMN IF EXISTS "mcp_tool_calls"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_annotation" DROP COLUMN IF EXISTS "review_status"`,
        );
        await queryRunner.query(
            `DROP TYPE IF EXISTS "public"."ai_agent_annotation_review_status_enum"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_annotation" DROP COLUMN IF EXISTS "reviewed_by"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_annotation" DROP COLUMN IF EXISTS "reviewed_at"`,
        );
        await queryRunner.query(
            `ALTER TABLE "user" ADD COLUMN IF NOT EXISTS "mp_openid" character varying`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'UQ_12525723738bdb386c7393983aa') THEN ALTER TABLE "user" ADD CONSTRAINT "UQ_12525723738bdb386c7393983aa" UNIQUE ("mp_openid"); END IF; END $$`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "user"."mp_openid" IS '用户mp_openid'`);
        await queryRunner.query(
            `ALTER TABLE "user" ADD COLUMN IF NOT EXISTS "unionid" character varying`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'UQ_e3f6feab5c4faea9df84b9fc816') THEN ALTER TABLE "user" ADD CONSTRAINT "UQ_e3f6feab5c4faea9df84b9fc816" UNIQUE ("unionid"); END IF; END $$`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "user"."unionid" IS '用户unionid'`);
        await queryRunner.query(
            `ALTER TABLE "user" ADD COLUMN IF NOT EXISTS "manage_status" integer NOT NULL DEFAULT '1'`,
        );
        await queryRunner.query(
            `ALTER TABLE "membership_levels" ADD COLUMN IF NOT EXISTS "storage_capacity" bigint NOT NULL DEFAULT '0'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "membership_levels"."storage_capacity" IS '存储容量（字节）'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_models" ADD COLUMN IF NOT EXISTS "thinking" boolean NOT NULL DEFAULT false`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_models"."thinking" IS '是否允许开关深度思考'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_models" ADD COLUMN IF NOT EXISTS "enable_thinking_param" boolean NOT NULL DEFAULT false`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_models"."enable_thinking_param" IS '是否传递thinking参数到AI模型'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets_documents" ADD COLUMN IF NOT EXISTS "file_url" character varying(1024)`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets_documents"."file_url" IS '文件存储路径'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets_documents" ADD COLUMN IF NOT EXISTS "summary" text`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "datasets_documents"."summary" IS '摘要'`);
        await queryRunner.query(
            `ALTER TABLE "datasets_documents" ADD COLUMN IF NOT EXISTS "summary_generating" boolean NOT NULL DEFAULT false`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets_documents"."summary_generating" IS '摘要是否正在生成中'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets_documents" ADD COLUMN IF NOT EXISTS "tags" text array`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "datasets_documents"."tags" IS '标签'`);
        await queryRunner.query(
            `ALTER TABLE "datasets" ADD COLUMN IF NOT EXISTS "cover_url" character varying(512)`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "datasets"."cover_url" IS '封面图 URL'`);
        await queryRunner.query(
            `ALTER TABLE "datasets" ADD COLUMN IF NOT EXISTS "published_to_square" boolean NOT NULL DEFAULT false`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets"."published_to_square" IS '是否已发布到广场'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets" ADD COLUMN IF NOT EXISTS "published_at" TIMESTAMP WITH TIME ZONE`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets"."published_at" IS '发布到广场的时间'`,
        );
        await queryRunner.query(
            `DO $$ BEGIN CREATE TYPE "public"."datasets_square_publish_status_enum" AS ENUM('none', 'pending', 'approved', 'rejected'); EXCEPTION WHEN duplicate_object THEN NULL; END $$`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets" ADD COLUMN IF NOT EXISTS "square_publish_status" "public"."datasets_square_publish_status_enum" NOT NULL DEFAULT 'none'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets"."square_publish_status" IS '发布到广场审核状态：none-未申请/已撤销，pending-待审核，approved-已通过，rejected-已拒绝'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets" ADD COLUMN IF NOT EXISTS "square_reviewed_by" uuid`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets"."square_reviewed_by" IS '广场发布审核人ID'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets" ADD COLUMN IF NOT EXISTS "square_reviewed_at" TIMESTAMP WITH TIME ZONE`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets"."square_reviewed_at" IS '广场发布审核时间'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets" ADD COLUMN IF NOT EXISTS "square_reject_reason" text`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets"."square_reject_reason" IS '广场发布拒绝原因'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets" ADD COLUMN IF NOT EXISTS "member_join_approval_required" boolean NOT NULL DEFAULT true`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets"."member_join_approval_required" IS '成员加入是否需要审核'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "enable_file_upload" boolean NOT NULL DEFAULT false`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."enable_file_upload" IS '是否开启文件上传'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "chat_avatar_enabled" boolean NOT NULL DEFAULT false`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."chat_avatar_enabled" IS '是否开启对话头像'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "memory_config" json`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "ai_agent"."memory_config" IS '记忆配置'`);
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "model_routing" json`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "ai_agent"."model_routing" IS '多模型路由配置'`);
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "context_config" json`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."context_config" IS '上下文窗口管理'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "voice_config" json`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "ai_agent"."voice_config" IS '语音配置'`);
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "tool_config" json`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "ai_agent"."tool_config" IS '工具配置'`);
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "annotation_config" json`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."annotation_config" IS '问答标注配置'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "max_steps" integer NOT NULL DEFAULT '10'`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "ai_agent"."max_steps" IS '最大执行步数'`);
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "published_to_square" boolean NOT NULL DEFAULT false`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."published_to_square" IS '是否已发布到广场'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "published_at" TIMESTAMP WITH TIME ZONE`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."published_at" IS '发布到广场的时间'`,
        );
        await queryRunner.query(
            `DO $$ BEGIN CREATE TYPE "public"."ai_agent_square_publish_status_enum" AS ENUM('none', 'pending', 'approved', 'rejected'); EXCEPTION WHEN duplicate_object THEN NULL; END $$`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "square_publish_status" "public"."ai_agent_square_publish_status_enum" NOT NULL DEFAULT 'none'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."square_publish_status" IS '发布到广场审核状态：none-未申请/已撤销，pending-待审核，approved-已通过，rejected-已拒绝'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "square_reviewed_by" uuid`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."square_reviewed_by" IS '广场发布审核人ID'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "square_reviewed_at" TIMESTAMP WITH TIME ZONE`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."square_reviewed_at" IS '广场发布审核时间'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "square_reject_reason" text`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."square_reject_reason" IS '广场发布拒绝原因'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "decorate_sort" integer`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."decorate_sort" IS '智能体装修排序字段'`,
        );
        await queryRunner.query(
            `ALTER TABLE "extension" ADD COLUMN IF NOT EXISTS "app_center_sort" integer DEFAULT '0'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "extension"."app_center_sort" IS '应用中心排序'`,
        );
        await queryRunner.query(
            `ALTER TABLE "extension" ADD COLUMN IF NOT EXISTS "app_center_tag_ids" jsonb`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "extension"."app_center_tag_ids" IS '应用中心标签ID列表'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" ADD COLUMN IF NOT EXISTS "parent_id" character varying(36)`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_chat_message"."parent_id" IS '父消息ID（用于消息树结构）'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" ADD COLUMN IF NOT EXISTS "frontend_id" character varying(64)`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_chat_message"."frontend_id" IS '前端消息ID（用于映射前端临时ID到数据库ID）'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" ADD COLUMN IF NOT EXISTS "message" jsonb`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_chat_message"."message" IS '消息内容（ChatUIMessage：含 role、parts、usage、userConsumedPower）'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" ADD COLUMN IF NOT EXISTS "parent_id" uuid`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_chat_message"."parent_id" IS '父消息ID，用于重新生成版本管理'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" ADD COLUMN IF NOT EXISTS "message" jsonb`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" ALTER COLUMN "message" SET NOT NULL`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_chat_message"."message" IS '消息内容（ChatUIMessage：含 role、parts、metadata、usage、userConsumedPower）'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" ADD COLUMN IF NOT EXISTS "status" character varying(20) NOT NULL DEFAULT 'completed'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_chat_message"."status" IS '消息状态: streaming-流式传输中, completed-已完成, failed-失败'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_record" ADD COLUMN IF NOT EXISTS "feedback_status" jsonb`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_chat_record"."feedback_status" IS '对话内点赞/踩汇总'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_annotation" ADD COLUMN IF NOT EXISTS "embedding" double precision array`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_annotation"."embedding" IS '问题向量'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_annotation" ADD COLUMN IF NOT EXISTS "embedding_model_id" character varying(100)`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_annotation"."embedding_model_id" IS '向量化使用的模型ID'`,
        );
        await queryRunner.query(
            `ALTER TABLE "account_log" ADD COLUMN IF NOT EXISTS "subscription_id" uuid`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "account_log"."subscription_id" IS '关联订阅ID'`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "user"."openid" IS '用户oa_openid'`);
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'UQ_0fda9260b0aaff9a5b8f38ac16c') THEN ALTER TABLE "user" ADD CONSTRAINT "UQ_0fda9260b0aaff9a5b8f38ac16c" UNIQUE ("openid"); END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'user_create_source_enum_old') AND EXISTS (SELECT 1 FROM pg_type WHERE typname = 'user_create_source_enum') THEN ALTER TYPE "public"."user_create_source_enum" RENAME TO "user_create_source_enum_old"; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN CREATE TYPE "public"."user_create_source_enum" AS ENUM('0', '1', '2', '3', '4', '5'); EXCEPTION WHEN duplicate_object THEN NULL; END $$`,
        );
        await queryRunner.query(
            `ALTER TABLE "user" ALTER COLUMN "source" TYPE "public"."user_create_source_enum" USING "source"::"text"::"public"."user_create_source_enum"`,
        );
        await queryRunner.query(`DROP TYPE IF EXISTS "public"."user_create_source_enum_old"`);
        await queryRunner.query(
            `ALTER TABLE "datasets_documents" ALTER COLUMN "file_id" DROP NOT NULL`,
        );
        await queryRunner.query(
            `ALTER TABLE "user_subscription" DROP CONSTRAINT IF EXISTS "FK_273c32785b2e09ccdd2649068fd"`,
        );
        await queryRunner.query(
            `ALTER TABLE "user_subscription" ALTER COLUMN "level_id" SET NOT NULL`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "membership_order"."source" IS '订单来源: 0-系统调整, 1-订单购买, 2-卡密兑换'`,
        );
        await queryRunner.query(`ALTER TABLE "ai_mcp_servers" DROP COLUMN IF EXISTS "icon"`);
        await queryRunner.query(
            `ALTER TABLE "ai_mcp_servers" ADD COLUMN IF NOT EXISTS "icon" character varying(500)`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "ai_mcp_servers"."icon" IS '图标'`);
        await queryRunner.query(
            `ALTER TABLE "ai_mcp_servers" DROP COLUMN IF EXISTS "provider_icon"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_mcp_servers" ADD COLUMN IF NOT EXISTS "provider_icon" character varying(255)`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_mcp_servers"."provider_icon" IS '供应商图标'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_chat_record"."status" IS '对话状态: active-进行中, completed-已完成, failed-失败, cancelled-已取消'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_chat_message"."status" IS '消息状态: streaming-流式传输中, completed-已完成, failed-失败'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_chat_message"."error_message" IS '错误信息'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_chat_record"."anonymous_identifier" IS '匿名用户标识'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_chat_record"."config" IS '对话相关配置'`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_b58915dc93a35434fab9ad86fa" ON "ai_chat_message" ("parent_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_a505b0355e88d53601c20c5291" ON "ai_chat_message" ("frontend_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_a5f2ace695dec7b589585ed38d" ON "ai_agent_chat_message" ("parent_id") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_5a426147ae17bb4d4102a97624" ON "account_log" ("subscription_id") `,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'UQ_user_subscription_user_level') THEN ALTER TABLE "user_subscription" ADD CONSTRAINT "UQ_user_subscription_user_level" UNIQUE ("user_id", "level_id"); END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_e88e0e981caf110189fcf623d3d') THEN ALTER TABLE "datasets_chat_message" ADD CONSTRAINT "FK_e88e0e981caf110189fcf623d3d" FOREIGN KEY ("conversation_id") REFERENCES "datasets_chat_record"("id") ON DELETE CASCADE ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_f42cb8e4f363b05770e5e549850') THEN ALTER TABLE "datasets_chat_message" ADD CONSTRAINT "FK_f42cb8e4f363b05770e5e549850" FOREIGN KEY ("model_id") REFERENCES "ai_models"("id") ON DELETE SET NULL ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_96bb837b36ff4f4329ece6c756a') THEN ALTER TABLE "datasets_chat_record" ADD CONSTRAINT "FK_96bb837b36ff4f4329ece6c756a" FOREIGN KEY ("dataset_id") REFERENCES "datasets"("id") ON DELETE CASCADE ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_a5cad699344f07a7406d12fc0f6') THEN ALTER TABLE "datasets_chat_record" ADD CONSTRAINT "FK_a5cad699344f07a7406d12fc0f6" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_7d0c369af1854e1b016ed0931de') THEN ALTER TABLE "dataset_member_applications" ADD CONSTRAINT "FK_7d0c369af1854e1b016ed0931de" FOREIGN KEY ("dataset_id") REFERENCES "datasets"("id") ON DELETE CASCADE ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_273c32785b2e09ccdd2649068fd') THEN ALTER TABLE "user_subscription" ADD CONSTRAINT "FK_273c32785b2e09ccdd2649068fd" FOREIGN KEY ("level_id") REFERENCES "membership_levels"("id") ON DELETE NO ACTION ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_ed8ac0dbf6bc8d85e70e3975a70') THEN ALTER TABLE "card_batch" ADD CONSTRAINT "FK_ed8ac0dbf6bc8d85e70e3975a70" FOREIGN KEY ("level_id") REFERENCES "membership_levels"("id") ON DELETE NO ACTION ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_86ed0054aaa02957d45e0d37c5d') THEN ALTER TABLE "cdk" ADD CONSTRAINT "FK_86ed0054aaa02957d45e0d37c5d" FOREIGN KEY ("batch_id") REFERENCES "card_batch"("id") ON DELETE NO ACTION ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_aef43a6f7f88c0e8cf8393d590c') THEN ALTER TABLE "cdk" ADD CONSTRAINT "FK_aef43a6f7f88c0e8cf8393d590c" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_eb317b1104d6dac6d2023674f1f') THEN ALTER TABLE "ai_user_memory" ADD CONSTRAINT "FK_eb317b1104d6dac6d2023674f1f" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_18bf46d4c3599b04afa1251934c') THEN ALTER TABLE "ai_chat_tool_call" ADD CONSTRAINT "FK_18bf46d4c3599b04afa1251934c" FOREIGN KEY ("message_id") REFERENCES "ai_chat_message"("id") ON DELETE CASCADE ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_6bb46b80eb0310f3dd11f34fece') THEN ALTER TABLE "ai_chat_tool_call" ADD CONSTRAINT "FK_6bb46b80eb0310f3dd11f34fece" FOREIGN KEY ("conversation_id") REFERENCES "ai_chat_record"("id") ON DELETE CASCADE ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_6274fd4cd331e21ddbe8cb9c37c') THEN ALTER TABLE "ai_chat_tool_call" ADD CONSTRAINT "FK_6274fd4cd331e21ddbe8cb9c37c" FOREIGN KEY ("mcp_server_id") REFERENCES "ai_mcp_servers"("id") ON DELETE SET NULL ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_43538779da0206a985468504de7') THEN ALTER TABLE "ai_chat_feedback" ADD CONSTRAINT "FK_43538779da0206a985468504de7" FOREIGN KEY ("message_id") REFERENCES "ai_chat_message"("id") ON DELETE CASCADE ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_1c4e8fa17f9bcf0708ccd81bfc4') THEN ALTER TABLE "ai_chat_feedback" ADD CONSTRAINT "FK_1c4e8fa17f9bcf0708ccd81bfc4" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_32789c775b08871ddee3a546328') THEN ALTER TABLE "ai_agent_memory" ADD CONSTRAINT "FK_32789c775b08871ddee3a546328" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_f94ebc85afdf40ac5cb3b201ebb') THEN ALTER TABLE "ai_agent_memory" ADD CONSTRAINT "FK_f94ebc85afdf40ac5cb3b201ebb" FOREIGN KEY ("agent_id") REFERENCES "ai_agent"("id") ON DELETE CASCADE ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_cc265cd43a64ff9a9745125b64b') THEN ALTER TABLE "ai_agent_chat_message_feedback" ADD CONSTRAINT "FK_cc265cd43a64ff9a9745125b64b" FOREIGN KEY ("message_id") REFERENCES "ai_agent_chat_message"("id") ON DELETE CASCADE ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_0026b3408f0040f59863a4b722c') THEN ALTER TABLE "ai_agent_chat_message_feedback" ADD CONSTRAINT "FK_0026b3408f0040f59863a4b722c" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_8c72fcf81a78b388f0503f67641') THEN ALTER TABLE "user_config" ADD CONSTRAINT "FK_8c72fcf81a78b388f0503f67641" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_88e56e216d926163f3895104f0f') THEN ALTER TABLE "datasets_tags" ADD CONSTRAINT "FK_88e56e216d926163f3895104f0f" FOREIGN KEY ("dataset_id") REFERENCES "datasets"("id") ON DELETE CASCADE ON UPDATE CASCADE; END IF; END $$`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_6036b74579c7c11571e7f8f06c2') THEN ALTER TABLE "datasets_tags" ADD CONSTRAINT "FK_6036b74579c7c11571e7f8f06c2" FOREIGN KEY ("tag_id") REFERENCES "tag"("id") ON DELETE NO ACTION ON UPDATE NO ACTION; END IF; END $$`,
        );
    }

    public async down(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(
            `ALTER TABLE "datasets_tags" DROP CONSTRAINT "FK_6036b74579c7c11571e7f8f06c2"`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets_tags" DROP CONSTRAINT "FK_88e56e216d926163f3895104f0f"`,
        );
        await queryRunner.query(
            `ALTER TABLE "user_config" DROP CONSTRAINT "FK_8c72fcf81a78b388f0503f67641"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message_feedback" DROP CONSTRAINT "FK_0026b3408f0040f59863a4b722c"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message_feedback" DROP CONSTRAINT "FK_cc265cd43a64ff9a9745125b64b"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_memory" DROP CONSTRAINT "FK_f94ebc85afdf40ac5cb3b201ebb"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_memory" DROP CONSTRAINT "FK_32789c775b08871ddee3a546328"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_feedback" DROP CONSTRAINT "FK_1c4e8fa17f9bcf0708ccd81bfc4"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_feedback" DROP CONSTRAINT "FK_43538779da0206a985468504de7"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_tool_call" DROP CONSTRAINT "FK_6274fd4cd331e21ddbe8cb9c37c"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_tool_call" DROP CONSTRAINT "FK_6bb46b80eb0310f3dd11f34fece"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_tool_call" DROP CONSTRAINT "FK_18bf46d4c3599b04afa1251934c"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_user_memory" DROP CONSTRAINT "FK_eb317b1104d6dac6d2023674f1f"`,
        );
        await queryRunner.query(
            `ALTER TABLE "cdk" DROP CONSTRAINT "FK_aef43a6f7f88c0e8cf8393d590c"`,
        );
        await queryRunner.query(
            `ALTER TABLE "cdk" DROP CONSTRAINT "FK_86ed0054aaa02957d45e0d37c5d"`,
        );
        await queryRunner.query(
            `ALTER TABLE "card_batch" DROP CONSTRAINT "FK_ed8ac0dbf6bc8d85e70e3975a70"`,
        );
        await queryRunner.query(
            `ALTER TABLE "user_subscription" DROP CONSTRAINT IF EXISTS "FK_273c32785b2e09ccdd2649068fd"`,
        );
        await queryRunner.query(
            `ALTER TABLE "dataset_member_applications" DROP CONSTRAINT "FK_7d0c369af1854e1b016ed0931de"`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets_chat_record" DROP CONSTRAINT "FK_a5cad699344f07a7406d12fc0f6"`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets_chat_record" DROP CONSTRAINT "FK_96bb837b36ff4f4329ece6c756a"`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets_chat_message" DROP CONSTRAINT "FK_f42cb8e4f363b05770e5e549850"`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets_chat_message" DROP CONSTRAINT "FK_e88e0e981caf110189fcf623d3d"`,
        );
        await queryRunner.query(
            `ALTER TABLE "user_subscription" DROP CONSTRAINT "UQ_user_subscription_user_level"`,
        );
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_5a426147ae17bb4d4102a97624"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_a5f2ace695dec7b589585ed38d"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_a505b0355e88d53601c20c5291"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_b58915dc93a35434fab9ad86fa"`);
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_chat_record"."config" IS '对话相关配置，如温度、最大令牌数等'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_chat_record"."anonymous_identifier" IS '匿名用户标识，如设备ID或访问令牌的hash'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_chat_message"."error_message" IS '错误信息（当状态为failed时）'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_chat_message"."status" IS '消息状态: sending-发送中, completed-已完成, failed-失败'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_chat_record"."status" IS '对话状态: active-进行中, completed-已完成, failed-失败'`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_mcp_servers"."provider_icon" IS '供应商图标'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_mcp_servers" DROP COLUMN IF EXISTS "provider_icon"`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_mcp_servers" ADD COLUMN IF NOT EXISTS "provider_icon" character varying(100)`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_mcp_servers"."headers" IS '自定义请求头，JSON格式存储'`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "ai_mcp_servers"."icon" IS '图标'`);
        await queryRunner.query(`ALTER TABLE "ai_mcp_servers" DROP COLUMN IF EXISTS "icon"`);
        await queryRunner.query(
            `ALTER TABLE "ai_mcp_servers" ADD COLUMN IF NOT EXISTS "icon" character varying(100)`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "membership_order"."source" IS '订单来源: 0-系统调整, 1-订单购买'`,
        );
        await queryRunner.query(
            `ALTER TABLE "user_subscription" ALTER COLUMN "level_id" DROP NOT NULL`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'FK_273c32785b2e09ccdd2649068fd') THEN ALTER TABLE "user_subscription" ADD CONSTRAINT "FK_273c32785b2e09ccdd2649068fd" FOREIGN KEY ("level_id") REFERENCES "membership_levels"("id") ON DELETE NO ACTION ON UPDATE NO ACTION; END IF; END $$`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets_documents" ALTER COLUMN "file_id" SET NOT NULL`,
        );
        await queryRunner.query(
            `DO $$ BEGIN CREATE TYPE "public"."user_create_source_enum_old" AS ENUM('0', '1', '2', '3', '4'); EXCEPTION WHEN duplicate_object THEN NULL; END $$`,
        );
        await queryRunner.query(
            `ALTER TABLE "user" ALTER COLUMN "source" TYPE "public"."user_create_source_enum_old" USING "source"::"text"::"public"."user_create_source_enum_old"`,
        );
        await queryRunner.query(`DROP TYPE IF EXISTS "public"."user_create_source_enum"`);
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'user_create_source_enum') AND EXISTS (SELECT 1 FROM pg_type WHERE typname = 'user_create_source_enum_old') THEN ALTER TYPE "public"."user_create_source_enum_old" RENAME TO "user_create_source_enum"; END IF; END $$`,
        );
        await queryRunner.query(
            `ALTER TABLE "user" DROP CONSTRAINT IF EXISTS "UQ_0fda9260b0aaff9a5b8f38ac16c"`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "user"."openid" IS NULL`);
        await queryRunner.query(
            `COMMENT ON COLUMN "account_log"."subscription_id" IS '关联订阅ID'`,
        );
        await queryRunner.query(
            `ALTER TABLE "account_log" DROP COLUMN IF EXISTS "subscription_id"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_annotation"."embedding_model_id" IS '向量化使用的模型ID'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_annotation" DROP COLUMN IF EXISTS "embedding_model_id"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_annotation"."embedding" IS '问题向量'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_annotation" DROP COLUMN IF EXISTS "embedding"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_chat_record"."feedback_status" IS '对话内点赞/踩汇总'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_record" DROP COLUMN IF EXISTS "feedback_status"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_chat_message"."status" IS '消息状态: streaming-流式传输中, completed-已完成, failed-失败'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" DROP COLUMN IF EXISTS "status"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_chat_message"."message" IS '消息内容（ChatUIMessage：含 role、parts、metadata、usage、userConsumedPower）'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" DROP COLUMN IF EXISTS "message"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent_chat_message"."parent_id" IS '父消息ID，用于重新生成版本管理'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" DROP COLUMN IF EXISTS "parent_id"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_chat_message"."message" IS '消息内容（ChatUIMessage：含 role、parts、usage、userConsumedPower）'`,
        );
        await queryRunner.query(`ALTER TABLE "ai_chat_message" DROP COLUMN IF EXISTS "message"`);
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_chat_message"."frontend_id" IS '前端消息ID（用于映射前端临时ID到数据库ID）'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" DROP COLUMN IF EXISTS "frontend_id"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_chat_message"."parent_id" IS '父消息ID（用于消息树结构）'`,
        );
        await queryRunner.query(`ALTER TABLE "ai_chat_message" DROP COLUMN IF EXISTS "parent_id"`);
        await queryRunner.query(
            `COMMENT ON COLUMN "extension"."app_center_tag_ids" IS '应用中心标签ID列表'`,
        );
        await queryRunner.query(
            `ALTER TABLE "extension" DROP COLUMN IF EXISTS "app_center_tag_ids"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "extension"."app_center_sort" IS '应用中心排序'`,
        );
        await queryRunner.query(`ALTER TABLE "extension" DROP COLUMN IF EXISTS "app_center_sort"`);
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."decorate_sort" IS '智能体装修排序字段'`,
        );
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "decorate_sort"`);
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."square_reject_reason" IS '广场发布拒绝原因'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "square_reject_reason"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."square_reviewed_at" IS '广场发布审核时间'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "square_reviewed_at"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."square_reviewed_by" IS '广场发布审核人ID'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "square_reviewed_by"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."square_publish_status" IS '发布到广场审核状态：none-未申请/已撤销，pending-待审核，approved-已通过，rejected-已拒绝'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "square_publish_status"`,
        );
        await queryRunner.query(
            `DROP TYPE IF EXISTS "public"."ai_agent_square_publish_status_enum"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."published_at" IS '发布到广场的时间'`,
        );
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "published_at"`);
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."published_to_square" IS '是否已发布到广场'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "published_to_square"`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "ai_agent"."max_steps" IS '最大执行步数'`);
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "max_steps"`);
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."annotation_config" IS '问答标注配置'`,
        );
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "annotation_config"`);
        await queryRunner.query(`COMMENT ON COLUMN "ai_agent"."tool_config" IS '工具配置'`);
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "tool_config"`);
        await queryRunner.query(`COMMENT ON COLUMN "ai_agent"."voice_config" IS '语音配置'`);
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "voice_config"`);
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."context_config" IS '上下文窗口管理'`,
        );
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "context_config"`);
        await queryRunner.query(`COMMENT ON COLUMN "ai_agent"."model_routing" IS '多模型路由配置'`);
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "model_routing"`);
        await queryRunner.query(`COMMENT ON COLUMN "ai_agent"."memory_config" IS '记忆配置'`);
        await queryRunner.query(`ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "memory_config"`);
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."chat_avatar_enabled" IS '是否开启对话头像'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "chat_avatar_enabled"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_agent"."enable_file_upload" IS '是否开启文件上传'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" DROP COLUMN IF EXISTS "enable_file_upload"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets"."member_join_approval_required" IS '成员加入是否需要审核'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets" DROP COLUMN IF EXISTS "member_join_approval_required"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets"."square_reject_reason" IS '广场发布拒绝原因'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets" DROP COLUMN IF EXISTS "square_reject_reason"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets"."square_reviewed_at" IS '广场发布审核时间'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets" DROP COLUMN IF EXISTS "square_reviewed_at"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets"."square_reviewed_by" IS '广场发布审核人ID'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets" DROP COLUMN IF EXISTS "square_reviewed_by"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets"."square_publish_status" IS '发布到广场审核状态：none-未申请/已撤销，pending-待审核，approved-已通过，rejected-已拒绝'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets" DROP COLUMN IF EXISTS "square_publish_status"`,
        );
        await queryRunner.query(
            `DROP TYPE IF EXISTS "public"."datasets_square_publish_status_enum"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets"."published_at" IS '发布到广场的时间'`,
        );
        await queryRunner.query(`ALTER TABLE "datasets" DROP COLUMN IF EXISTS "published_at"`);
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets"."published_to_square" IS '是否已发布到广场'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets" DROP COLUMN IF EXISTS "published_to_square"`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "datasets"."cover_url" IS '封面图 URL'`);
        await queryRunner.query(`ALTER TABLE "datasets" DROP COLUMN IF EXISTS "cover_url"`);
        await queryRunner.query(`COMMENT ON COLUMN "datasets_documents"."tags" IS '标签'`);
        await queryRunner.query(`ALTER TABLE "datasets_documents" DROP COLUMN IF EXISTS "tags"`);
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets_documents"."summary_generating" IS '摘要是否正在生成中'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets_documents" DROP COLUMN IF EXISTS "summary_generating"`,
        );
        await queryRunner.query(`COMMENT ON COLUMN "datasets_documents"."summary" IS '摘要'`);
        await queryRunner.query(`ALTER TABLE "datasets_documents" DROP COLUMN IF EXISTS "summary"`);
        await queryRunner.query(
            `COMMENT ON COLUMN "datasets_documents"."file_url" IS '文件存储路径'`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets_documents" DROP COLUMN IF EXISTS "file_url"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_models"."enable_thinking_param" IS '是否传递thinking参数到AI模型'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_models" DROP COLUMN IF EXISTS "enable_thinking_param"`,
        );
        await queryRunner.query(
            `COMMENT ON COLUMN "ai_models"."thinking" IS '是否允许开关深度思考'`,
        );
        await queryRunner.query(`ALTER TABLE "ai_models" DROP COLUMN IF EXISTS "thinking"`);
        await queryRunner.query(
            `COMMENT ON COLUMN "membership_levels"."storage_capacity" IS '存储容量（字节）'`,
        );
        await queryRunner.query(
            `ALTER TABLE "membership_levels" DROP COLUMN IF EXISTS "storage_capacity"`,
        );
        await queryRunner.query(`ALTER TABLE "user" DROP COLUMN IF EXISTS "manage_status"`);
        await queryRunner.query(`COMMENT ON COLUMN "user"."unionid" IS '用户unionid'`);
        await queryRunner.query(
            `ALTER TABLE "user" DROP CONSTRAINT IF EXISTS "UQ_e3f6feab5c4faea9df84b9fc816"`,
        );
        await queryRunner.query(`ALTER TABLE "user" DROP COLUMN IF EXISTS "unionid"`);
        await queryRunner.query(`COMMENT ON COLUMN "user"."mp_openid" IS '用户mp_openid'`);
        await queryRunner.query(
            `ALTER TABLE "user" DROP CONSTRAINT IF EXISTS "UQ_12525723738bdb386c7393983aa"`,
        );
        await queryRunner.query(`ALTER TABLE "user" DROP COLUMN IF EXISTS "mp_openid"`);
        await queryRunner.query(
            `ALTER TABLE "ai_agent_annotation" ADD COLUMN IF NOT EXISTS "reviewed_at" TIMESTAMP`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_annotation" ADD COLUMN IF NOT EXISTS "reviewed_by" uuid`,
        );
        await queryRunner.query(
            `DO $$ BEGIN CREATE TYPE "public"."ai_agent_annotation_review_status_enum" AS ENUM('pending', 'approved', 'rejected'); EXCEPTION WHEN duplicate_object THEN NULL; END $$`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_annotation" ADD COLUMN IF NOT EXISTS "review_status" "public"."ai_agent_annotation_review_status_enum" NOT NULL DEFAULT 'approved'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" ADD COLUMN IF NOT EXISTS "mcp_tool_calls" jsonb`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" ADD COLUMN IF NOT EXISTS "metadata" jsonb`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" ADD COLUMN IF NOT EXISTS "tokens" jsonb`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" ADD COLUMN IF NOT EXISTS "attachments" jsonb`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" ADD COLUMN IF NOT EXISTS "message_type" character varying(20) NOT NULL DEFAULT 'text'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" ADD COLUMN IF NOT EXISTS "content" jsonb NOT NULL`,
        );
        await queryRunner.query(
            `DO $$ BEGIN CREATE TYPE "public"."ai_agent_chat_message_role_enum" AS ENUM('user', 'assistant', 'system'); EXCEPTION WHEN duplicate_object THEN NULL; END $$`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_chat_message" ADD COLUMN IF NOT EXISTS "role" "public"."ai_agent_chat_message_role_enum" NOT NULL`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" ADD COLUMN IF NOT EXISTS "mcp_tool_calls" jsonb`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" ADD COLUMN IF NOT EXISTS "metadata" jsonb`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" ADD COLUMN IF NOT EXISTS "raw_response" jsonb`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" ADD COLUMN IF NOT EXISTS "processing_time" integer`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" ADD COLUMN IF NOT EXISTS "user_consumed_power" integer`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" ADD COLUMN IF NOT EXISTS "tokens" jsonb`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" ADD COLUMN IF NOT EXISTS "attachments" jsonb`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" ADD COLUMN IF NOT EXISTS "message_type" character varying(20) NOT NULL DEFAULT 'text'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" ADD COLUMN IF NOT EXISTS "content" jsonb NOT NULL`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_chat_message" ADD COLUMN IF NOT EXISTS "role" character varying(20) NOT NULL`,
        );
        await queryRunner.query(
            `ALTER TABLE "user_subscription" ADD COLUMN IF NOT EXISTS "source" integer NOT NULL`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "api_key" character varying(255)`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'UQ_fd2402541080fb42d890ff0c2ff') THEN ALTER TABLE "ai_agent" ADD CONSTRAINT "UQ_fd2402541080fb42d890ff0c2ff" UNIQUE ("api_key"); END IF; END $$`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "publish_token" character varying(255)`,
        );
        await queryRunner.query(
            `DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'UQ_8b75ecd46770aa60d094b3e2f22') THEN ALTER TABLE "ai_agent" ADD CONSTRAINT "UQ_8b75ecd46770aa60d094b3e2f22" UNIQUE ("publish_token"); END IF; END $$`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "is_public" boolean NOT NULL DEFAULT false`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "is_published" boolean NOT NULL DEFAULT false`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "billing_config" json DEFAULT '{"price":0}'`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent" ADD COLUMN IF NOT EXISTS "enable_feedback" boolean NOT NULL DEFAULT false`,
        );
        await queryRunner.query(
            `ALTER TABLE "datasets" ADD COLUMN IF NOT EXISTS "indexing_config" json NOT NULL`,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_providers" ADD COLUMN IF NOT EXISTS "website_url" character varying(500)`,
        );
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_6036b74579c7c11571e7f8f06c"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_88e56e216d926163f3895104f0"`);
        await queryRunner.query(`DROP TABLE "datasets_tags"`);
        await queryRunner.query(`COMMENT ON TABLE "user_config" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."UQ_user_dict_user_key_group"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_8c72fcf81a78b388f0503f6764"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_5cb73472aaca5c0cf69e74d870"`);
        await queryRunner.query(`DROP TABLE "user_config"`);
        await queryRunner.query(`COMMENT ON TABLE "ai_agent_chat_message_feedback" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_353756e948d70ac3227fdf64ef"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_0026b3408f0040f59863a4b722"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_54a082e0c04971c99ce2165ba5"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_cc265cd43a64ff9a9745125b64"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_94d7c76e1d851a8acfb3e42933"`);
        await queryRunner.query(`DROP TABLE "ai_agent_chat_message_feedback"`);
        await queryRunner.query(`COMMENT ON TABLE "ai_agent_memory" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_3f3d56aba995261cd6b633cbde"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_f94ebc85afdf40ac5cb3b201eb"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_32789c775b08871ddee3a54632"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_9d0ce5d5b9340ec1db0ea717cb"`);
        await queryRunner.query(`DROP TABLE "ai_agent_memory"`);
        await queryRunner.query(`COMMENT ON TABLE "ai_chat_feedback" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_907884fb146162b020cef41b3f"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_1c4e8fa17f9bcf0708ccd81bfc"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_041b2e7711150958546a457ad8"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_43538779da0206a985468504de"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_22d87c38427b45f51c2511e399"`);
        await queryRunner.query(`DROP TABLE "ai_chat_feedback"`);
        await queryRunner.query(`COMMENT ON TABLE "ai_chat_tool_call" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_a2ffcb5043f71c52568a7080dd"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_df76be3aaf61579d0725c622d9"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_29306703decd21657bac34df8e"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_6274fd4cd331e21ddbe8cb9c37"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_4df73ea323e64345d149a260e4"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_86344badc858b35f022ca7cb60"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_9a53ec799510aa057baab7a483"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_75b4acef3b1d2f2ca5ad30eb7a"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_6bb46b80eb0310f3dd11f34fec"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_18bf46d4c3599b04afa1251934"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_26a0f17c06e8354ac11197bc23"`);
        await queryRunner.query(`DROP TABLE "ai_chat_tool_call"`);
        await queryRunner.query(`COMMENT ON TABLE "ai_user_memory" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_d628e065abe29f02666c47a477"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_eb317b1104d6dac6d2023674f1"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_dd1178bc48bd857bd3780babe6"`);
        await queryRunner.query(`DROP TABLE "ai_user_memory"`);
        await queryRunner.query(`COMMENT ON TABLE "cdk" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_aef43a6f7f88c0e8cf8393d590"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_14982790fd83b4a19735df99cc"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_86ed0054aaa02957d45e0d37c5"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_5b3f4c4c8b8a6421180e370261"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_f659070fa8811faed4ccf9e846"`);
        await queryRunner.query(`DROP TABLE "cdk"`);
        await queryRunner.query(`DROP TYPE IF EXISTS "public"."cdk_status_enum"`);
        await queryRunner.query(`COMMENT ON TABLE "card_batch" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_06e9d8eb6d809d03d74f253856"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_8872d22ce9660b4ed97e00da14"`);
        await queryRunner.query(`DROP TABLE "card_batch"`);
        await queryRunner.query(
            `DROP TYPE IF EXISTS "public"."card_batch_membership_duration_enum"`,
        );
        await queryRunner.query(`DROP TYPE IF EXISTS "public"."card_batch_redeem_type_enum"`);
        await queryRunner.query(`COMMENT ON TABLE "department_principal" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_c4d429460edbcd5f9dad9e351f"`);
        await queryRunner.query(`DROP TABLE "department_principal"`);
        await queryRunner.query(`COMMENT ON TABLE "department_user_index" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_c3f1ce24c1b3da469b5e7a5d67"`);
        await queryRunner.query(`DROP TABLE "department_user_index"`);
        await queryRunner.query(`COMMENT ON TABLE "department" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_9a2213262c1593bffb581e382f"`);
        await queryRunner.query(`DROP TABLE "department"`);
        await queryRunner.query(`COMMENT ON TABLE "notice" IS NULL`);
        await queryRunner.query(`DROP TABLE "notice"`);
        await queryRunner.query(`COMMENT ON TABLE "sms_config" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_5747a22aa47df1c51d160d902b"`);
        await queryRunner.query(`DROP TABLE "sms_config"`);
        await queryRunner.query(`DROP TYPE IF EXISTS "public"."sms_config_provider_enum"`);
        await queryRunner.query(`COMMENT ON TABLE "dataset_member_applications" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_b4a503361221499c7adfbce1e5"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_ec1cc76a3db62ec53d87aba884"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_4032850cf7c0528031b995b8ed"`);
        await queryRunner.query(`DROP TABLE "dataset_member_applications"`);
        await queryRunner.query(
            `DROP TYPE IF EXISTS "public"."dataset_member_applications_applied_role_enum"`,
        );
        await queryRunner.query(`DROP TYPE IF EXISTS "public"."member_application_status"`);
        await queryRunner.query(`COMMENT ON TABLE "datasets_chat_record" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_d89f8f55fd64aeea7322af4d98"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_af85e8f3d176b922b11faac584"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_622f8dcf924d88933939aeca4c"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_64bdebacddf9c1f550b34ad6db"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_ac9701a784b76c7d0d1f139a2f"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_a5cad699344f07a7406d12fc0f"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_96bb837b36ff4f4329ece6c756"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_4ac5f12827b3ff676d554caec6"`);
        await queryRunner.query(`DROP TABLE "datasets_chat_record"`);
        await queryRunner.query(`COMMENT ON TABLE "datasets_chat_message" IS NULL`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_0881581b3999a29ff574c0ce88"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_9685e85792d18ca408ffebbfd3"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_15c4fcf8078809f95081f7ce31"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_7d4e8f759ac53f58cc33ae5db7"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_f42cb8e4f363b05770e5e54985"`);
        await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_5fe94be1d1701c6bb2e0368d64"`);
        await queryRunner.query(`DROP TABLE "datasets_chat_message"`);
        await queryRunner.query(
            `DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'ai_mcp_servers' AND column_name = 'headers') THEN ALTER TABLE "ai_mcp_servers" RENAME COLUMN "headers" TO "custom_headers"; END IF; END $$`,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "idx_annotation_reviewed_by" ON "ai_agent_annotation" ("reviewed_by") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_d0f3b0eaba0207b6ebc5421fa2" ON "ai_agent_annotation" ("review_status") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_b95504e424a3874b0e15a4f6ca" ON "ai_chat_message" ("created_at", "role") `,
        );
        await queryRunner.query(
            `CREATE INDEX IF NOT EXISTS "IDX_00ed9f001cbfe4eaa9ffb4640e" ON "ai_chat_message" ("role") `,
        );
        await queryRunner.query(
            `ALTER TABLE "ai_agent_annotation" ADD CONSTRAINT "FK_1b7295e37ffc1156e34f650949e" FOREIGN KEY ("reviewed_by") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE NO ACTION`,
        );
    }
}
