refactor: replace focusedIndex with activeChildId

- Replace focusedIndex integer with activeChildId string in messages schema
- Add migration to convert existing data and drop focused_index column
- Add  hooks for providers.updatedAt and messageParts.lastUpdatedAt
- Add file size column to files table
- Update message navigation to use child ID-based lookup
- Simplify delete logic by removing focusedIndex math
- Fix file delete endpoint filename ([id[ -> [id])
This commit is contained in:
Zoe
2026-05-11 17:41:57 -05:00
parent 7a944afdb5
commit 103dedd9cc
16 changed files with 2106 additions and 1793 deletions
@@ -0,0 +1,218 @@
CREATE TYPE "part_type" AS ENUM('reasoning', 'text', 'tool-call', 'file');--> statement-breakpoint
CREATE TYPE "role" AS ENUM('user', 'assistant');--> statement-breakpoint
CREATE TYPE "status" AS ENUM('pending', 'completed', 'failed', 'cancelled');--> statement-breakpoint
CREATE TABLE "accounts" (
"id" text PRIMARY KEY,
"account_id" text NOT NULL,
"provider_id" text NOT NULL,
"user_id" text NOT NULL,
"access_token" text,
"refresh_token" text,
"id_token" text,
"access_token_expires_at" timestamp,
"refresh_token_expires_at" timestamp,
"scope" text,
"password" text,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp NOT NULL
);
--> statement-breakpoint
CREATE TABLE "agents" (
"id" text PRIMARY KEY,
"user_id" text NOT NULL,
"name" text NOT NULL,
"system_prompt" text,
"image_url" text,
"default_model_id" text,
"config" jsonb DEFAULT '{}',
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "attachments" (
"id" text PRIMARY KEY,
"user_id" text NOT NULL,
"topic_id" text NOT NULL,
"message_id" text NOT NULL,
"file_id" text NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "embeddings" (
"id" text PRIMARY KEY,
"file_id" text NOT NULL,
"content" text NOT NULL,
"embedding" vector(1536),
"metadata" jsonb
);
--> statement-breakpoint
CREATE TABLE "files" (
"id" text PRIMARY KEY,
"user_id" text NOT NULL,
"name" text NOT NULL,
"mime_type" text NOT NULL,
"url" text NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "generations" (
"id" text PRIMARY KEY,
"user_id" text NOT NULL,
"topic_id" text NOT NULL,
"model_id" text NOT NULL,
"status" "status" NOT NULL,
"tokens" jsonb,
"error" text
);
--> statement-breakpoint
CREATE TABLE "message_parts" (
"id" text PRIMARY KEY,
"user_id" text NOT NULL,
"topic_id" text NOT NULL,
"message_id" text NOT NULL,
"tool_call_id" text,
"type" "part_type" NOT NULL,
"content" text,
"provider_options" jsonb,
"finished" boolean DEFAULT false NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"last_updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "messages" (
"id" text PRIMARY KEY,
"user_id" text NOT NULL,
"topic_id" text NOT NULL,
"parent_message_id" text,
"generation_id" text,
"role" "role" NOT NULL,
"content" text,
"focused_index" integer,
"deleted" boolean DEFAULT false,
"updated_at" timestamp DEFAULT now() NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "models" (
"id" text PRIMARY KEY,
"user_id" text NOT NULL,
"external_id" text NOT NULL,
"provider_id" text NOT NULL,
"name" text NOT NULL,
"cost" jsonb DEFAULT '{}' NOT NULL,
"input_modalities" text[] DEFAULT '{}'::text[] NOT NULL,
"output_modalities" text[] DEFAULT '{}'::text[] NOT NULL,
"capabilities" text[] DEFAULT '{}'::text[] NOT NULL,
"context_window" integer,
"supported_parameters" text[],
"is_custom" boolean DEFAULT false NOT NULL,
"enabled" boolean DEFAULT true NOT NULL,
"released_at" timestamp
);
--> statement-breakpoint
CREATE TABLE "providers" (
"id" text PRIMARY KEY,
"user_id" text NOT NULL,
"type" text NOT NULL,
"name" text NOT NULL,
"enabled" boolean DEFAULT true NOT NULL,
"config" jsonb DEFAULT '{}' NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "sessions" (
"id" text PRIMARY KEY,
"expires_at" timestamp NOT NULL,
"token" text NOT NULL UNIQUE,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp NOT NULL,
"ip_address" text,
"user_agent" text,
"user_id" text NOT NULL
);
--> statement-breakpoint
CREATE TABLE "settings" (
"id" text PRIMARY KEY,
"user_id" text NOT NULL,
"system_assistants" jsonb DEFAULT '{}' NOT NULL,
"appearance" jsonb
);
--> statement-breakpoint
CREATE TABLE "tool_calls" (
"id" text PRIMARY KEY,
"user_id" text NOT NULL,
"tool_name" text NOT NULL,
"status" "status" DEFAULT 'pending'::"status" NOT NULL,
"input" jsonb,
"output" jsonb,
"error" jsonb,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "topics" (
"id" text PRIMARY KEY,
"user_id" text NOT NULL,
"agent_id" text NOT NULL,
"name" text NOT NULL,
"renaming" boolean DEFAULT false,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "users" (
"id" text PRIMARY KEY,
"name" text NOT NULL,
"email" text NOT NULL UNIQUE,
"email_verified" boolean DEFAULT false NOT NULL,
"image" text,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "verifications" (
"id" text PRIMARY KEY,
"identifier" text NOT NULL,
"value" text NOT NULL,
"expires_at" timestamp NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE INDEX "accounts_userId_idx" ON "accounts" ("user_id");--> statement-breakpoint
CREATE INDEX "agents_userId_idx" ON "agents" ("user_id");--> statement-breakpoint
CREATE INDEX "attachments_topicId_idx" ON "attachments" ("topic_id");--> statement-breakpoint
CREATE INDEX "attachments_messageId_idx" ON "attachments" ("message_id");--> statement-breakpoint
CREATE INDEX "attachments_userId_idx" ON "attachments" ("user_id");--> statement-breakpoint
CREATE INDEX "embeddings_fileId_idx" ON "embeddings" ("file_id");--> statement-breakpoint
CREATE INDEX "files_userId_idx" ON "files" ("user_id");--> statement-breakpoint
CREATE INDEX "generations_topicId_idx" ON "generations" ("topic_id");--> statement-breakpoint
CREATE INDEX "generations_userId_idx" ON "generations" ("user_id");--> statement-breakpoint
CREATE INDEX "message_parts_topicId_idx" ON "message_parts" ("topic_id");--> statement-breakpoint
CREATE INDEX "message_parts_messageId_idx" ON "message_parts" ("message_id");--> statement-breakpoint
CREATE INDEX "message_parts_userId_idx" ON "message_parts" ("user_id");--> statement-breakpoint
CREATE INDEX "messages_topicId_idx" ON "messages" ("topic_id");--> statement-breakpoint
CREATE INDEX "messages_parentMessageId_idx" ON "messages" ("parent_message_id");--> statement-breakpoint
CREATE INDEX "messages_userId_idx" ON "messages" ("user_id");--> statement-breakpoint
CREATE INDEX "models_providerId_idx" ON "models" ("provider_id");--> statement-breakpoint
CREATE INDEX "models_userId_idx" ON "models" ("user_id");--> statement-breakpoint
CREATE INDEX "providers_userId_idx" ON "providers" ("user_id");--> statement-breakpoint
CREATE INDEX "sessions_userId_idx" ON "sessions" ("user_id");--> statement-breakpoint
CREATE INDEX "settings_userId_idx" ON "settings" ("user_id");--> statement-breakpoint
CREATE INDEX "tool_calls_userId_idx" ON "tool_calls" ("user_id");--> statement-breakpoint
CREATE INDEX "topics_agentId_idx" ON "topics" ("agent_id");--> statement-breakpoint
CREATE INDEX "topics_userId_idx" ON "topics" ("user_id");--> statement-breakpoint
CREATE INDEX "verifications_identifier_idx" ON "verifications" ("identifier");--> statement-breakpoint
ALTER TABLE "accounts" ADD CONSTRAINT "accounts_user_id_users_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE;--> statement-breakpoint
ALTER TABLE "agents" ADD CONSTRAINT "agents_default_model_id_models_id_fkey" FOREIGN KEY ("default_model_id") REFERENCES "models"("id") ON DELETE SET NULL;--> statement-breakpoint
ALTER TABLE "attachments" ADD CONSTRAINT "attachments_topic_id_topics_id_fkey" FOREIGN KEY ("topic_id") REFERENCES "topics"("id") ON DELETE CASCADE;--> statement-breakpoint
ALTER TABLE "attachments" ADD CONSTRAINT "attachments_message_id_messages_id_fkey" FOREIGN KEY ("message_id") REFERENCES "messages"("id") ON DELETE CASCADE;--> statement-breakpoint
ALTER TABLE "attachments" ADD CONSTRAINT "attachments_file_id_files_id_fkey" FOREIGN KEY ("file_id") REFERENCES "files"("id") ON DELETE CASCADE;--> statement-breakpoint
ALTER TABLE "embeddings" ADD CONSTRAINT "embeddings_file_id_files_id_fkey" FOREIGN KEY ("file_id") REFERENCES "files"("id") ON DELETE CASCADE;--> statement-breakpoint
ALTER TABLE "generations" ADD CONSTRAINT "generations_topic_id_topics_id_fkey" FOREIGN KEY ("topic_id") REFERENCES "topics"("id") ON DELETE CASCADE;--> statement-breakpoint
ALTER TABLE "message_parts" ADD CONSTRAINT "message_parts_topic_id_topics_id_fkey" FOREIGN KEY ("topic_id") REFERENCES "topics"("id") ON DELETE CASCADE;--> statement-breakpoint
ALTER TABLE "message_parts" ADD CONSTRAINT "message_parts_message_id_messages_id_fkey" FOREIGN KEY ("message_id") REFERENCES "messages"("id") ON DELETE CASCADE;--> statement-breakpoint
ALTER TABLE "message_parts" ADD CONSTRAINT "message_parts_tool_call_id_tool_calls_id_fkey" FOREIGN KEY ("tool_call_id") REFERENCES "tool_calls"("id") ON DELETE CASCADE;--> statement-breakpoint
ALTER TABLE "messages" ADD CONSTRAINT "messages_topic_id_topics_id_fkey" FOREIGN KEY ("topic_id") REFERENCES "topics"("id") ON DELETE CASCADE;--> statement-breakpoint
ALTER TABLE "messages" ADD CONSTRAINT "messages_generation_id_generations_id_fkey" FOREIGN KEY ("generation_id") REFERENCES "generations"("id") ON DELETE CASCADE;--> statement-breakpoint
ALTER TABLE "models" ADD CONSTRAINT "models_provider_id_providers_id_fkey" FOREIGN KEY ("provider_id") REFERENCES "providers"("id") ON DELETE CASCADE;--> statement-breakpoint
ALTER TABLE "sessions" ADD CONSTRAINT "sessions_user_id_users_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE;--> statement-breakpoint
ALTER TABLE "topics" ADD CONSTRAINT "topics_agent_id_agents_id_fkey" FOREIGN KEY ("agent_id") REFERENCES "agents"("id") ON DELETE CASCADE;