From d8600f342d7e7b31ab09ba578ccec0e4334d9e9a Mon Sep 17 00:00:00 2001 From: KiwiGaze <1244666638@qq.com> Date: Wed, 31 Dec 2025 17:09:44 +0800 Subject: [PATCH 001/428] build: add Vercel configuration to disable Git deployment. --- vercel.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 vercel.json diff --git a/vercel.json b/vercel.json new file mode 100644 index 00000000..45c873bf --- /dev/null +++ b/vercel.json @@ -0,0 +1,5 @@ +{ + "git": { + "deploymentEnabled": false + } +} From 5434f96ce7cae3a21f3966a13602e1e0907ecf45 Mon Sep 17 00:00:00 2001 From: KiwiGaze <1244666638@qq.com> Date: Wed, 31 Dec 2025 17:31:44 +0800 Subject: [PATCH 002/428] chore: block search engine crawlers for staging - Update robots.ts to disallow all user agents - Remove redundant public/robots.txt file - Add X-Robots-Tag header in vercel.json for additional protection --- app/robots.ts | 2 +- public/robots.txt | 3 --- vercel.json | 13 ++++++++++++- 3 files changed, 13 insertions(+), 5 deletions(-) delete mode 100644 public/robots.txt diff --git a/app/robots.ts b/app/robots.ts index f86f1678..8cd9bdf9 100644 --- a/app/robots.ts +++ b/app/robots.ts @@ -4,7 +4,7 @@ export default function robots(): MetadataRoute.Robots { return { rules: { userAgent: "*", - allow: "/", + disallow: "/", }, } } diff --git a/public/robots.txt b/public/robots.txt deleted file mode 100644 index e0c530ef..00000000 --- a/public/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# Disallow all web crawlers during staging period -User-agent: * -Disallow: / diff --git a/vercel.json b/vercel.json index 45c873bf..40ff5a13 100644 --- a/vercel.json +++ b/vercel.json @@ -1,5 +1,16 @@ { "git": { "deploymentEnabled": false - } + }, + "headers": [ + { + "source": "/(.*)", + "headers": [ + { + "key": "X-Robots-Tag", + "value": "noindex, nofollow" + } + ] + } + ] } From 937ea13b4b886ebe60fa0304a3e33705aca3d399 Mon Sep 17 00:00:00 2001 From: KiwiGaze <1244666638@qq.com> Date: Wed, 31 Dec 2025 17:37:46 +0800 Subject: [PATCH 003/428] hore: add baseline migration for staging deployment --- package.json | 2 +- .../20251231093636_init/migration.sql | 539 ++++++++++++++++++ prisma/migrations/migration_lock.toml | 3 + 3 files changed, 543 insertions(+), 1 deletion(-) create mode 100644 prisma/migrations/20251231093636_init/migration.sql create mode 100644 prisma/migrations/migration_lock.toml diff --git a/package.json b/package.json index db723416..2772b55e 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ }, "scripts": { "dev": "NODE_OPTIONS='--no-deprecation' next dev --turbo", - "build": "NODE_OPTIONS='--no-deprecation' next build", + "build": "prisma generate && prisma migrate deploy && next build", "turbo": "NODE_OPTIONS='--no-deprecation' next dev --turbo", "start": "NODE_OPTIONS='--no-deprecation' next start", "lint": "eslint .", diff --git a/prisma/migrations/20251231093636_init/migration.sql b/prisma/migrations/20251231093636_init/migration.sql new file mode 100644 index 00000000..8d0b58c0 --- /dev/null +++ b/prisma/migrations/20251231093636_init/migration.sql @@ -0,0 +1,539 @@ +-- CreateEnum +CREATE TYPE "UserRole" AS ENUM ('ADMIN', 'USER'); + +-- CreateEnum +CREATE TYPE "InputSource" AS ENUM ('CHAT'); + +-- CreateEnum +CREATE TYPE "IntentType" AS ENUM ('CREATE'); + +-- CreateEnum +CREATE TYPE "Priority" AS ENUM ('LOW', 'MEDIUM', 'HIGH'); + +-- CreateEnum +CREATE TYPE "SyncStatus" AS ENUM ('PENDING', 'PENDING_SYNC', 'PENDING_UPDATE', 'PENDING_DELETE', 'SYNCED', 'FAILED', 'DISABLED'); + +-- CreateEnum +CREATE TYPE "LifeCycle" AS ENUM ('PENDING', 'DECLINED', 'ACCEPTED'); + +-- CreateTable +CREATE TABLE "accounts" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "type" TEXT NOT NULL, + "provider" TEXT NOT NULL, + "providerAccountId" TEXT NOT NULL, + "refresh_token" TEXT, + "access_token" TEXT, + "expires_at" INTEGER, + "token_type" TEXT, + "scope" TEXT, + "id_token" TEXT, + "session_state" TEXT, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "accounts_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "sessions" ( + "id" TEXT NOT NULL, + "sessionToken" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "expires" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "sessions_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "users" ( + "id" TEXT NOT NULL, + "name" TEXT, + "email" TEXT, + "emailVerified" TIMESTAMP(3), + "image" TEXT, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "role" "UserRole" NOT NULL DEFAULT 'USER', + "stripe_customer_id" TEXT, + "stripe_subscription_id" TEXT, + "stripe_price_id" TEXT, + "stripe_current_period_end" TIMESTAMP(3), + "time_zone" TEXT NOT NULL DEFAULT 'UTC', + "working_hours_start" INTEGER, + "working_hours_end" INTEGER, + "working_days_mask" INTEGER, + "week_start_day" SMALLINT NOT NULL DEFAULT 1, + "time_zone_confirmed_at" TIMESTAMP(3), + "preferences" JSONB, + "conflict_detection_enabled" BOOLEAN NOT NULL DEFAULT false, + "default_buffer_before" INTEGER NOT NULL DEFAULT 15, + "default_buffer_after" INTEGER NOT NULL DEFAULT 0, + "working_hours_warning_enabled" BOOLEAN NOT NULL DEFAULT false, + + CONSTRAINT "users_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "verification_tokens" ( + "identifier" TEXT NOT NULL, + "token" TEXT NOT NULL, + "expires" TIMESTAMP(3) NOT NULL +); + +-- CreateTable +CREATE TABLE "raw_inputs" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "text" TEXT NOT NULL, + "source" "InputSource" NOT NULL DEFAULT 'CHAT', + "request_id" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "raw_inputs_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "raw_input_attachments" ( + "id" TEXT NOT NULL, + "rawInputId" TEXT NOT NULL, + "filename" TEXT NOT NULL, + "mimeType" TEXT NOT NULL, + "size" INTEGER NOT NULL, + "checksum" TEXT, + "etag" TEXT, + "objectKey" TEXT NOT NULL, + "uploadedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "raw_input_attachments_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "parsed_results" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "rawInputId" TEXT NOT NULL, + "intent" "IntentType" NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "aiProvider" TEXT, + "routingReason" TEXT, + "processingDurationMs" INTEGER, + + CONSTRAINT "parsed_results_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "parsed_events" ( + "id" TEXT NOT NULL, + "parseResultId" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "ordinal" INTEGER NOT NULL, + "title" TEXT, + "description" TEXT, + "start" TIMESTAMP(3), + "end" TIMESTAMP(3), + "timeZone" TEXT, + "allDay" BOOLEAN NOT NULL DEFAULT false, + "attendees" TEXT[] DEFAULT ARRAY[]::TEXT[], + "recurrence" TEXT, + "confidence" DOUBLE PRECISION, + "reasoning" TEXT, + "lifeCycle" "LifeCycle" NOT NULL DEFAULT 'PENDING', + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "parsed_events_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "parsed_tasks" ( + "id" TEXT NOT NULL, + "parseResultId" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "ordinal" INTEGER NOT NULL, + "title" TEXT, + "description" TEXT, + "dueDate" TIMESTAMP(3), + "timeZone" TEXT, + "priority" "Priority", + "confidence" DOUBLE PRECISION, + "reasoning" TEXT, + "lifeCycle" "LifeCycle" NOT NULL DEFAULT 'PENDING', + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "parsed_tasks_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "events" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "title" TEXT NOT NULL, + "description" TEXT, + "start" TIMESTAMP(3) NOT NULL, + "end" TIMESTAMP(3) NOT NULL, + "timeZone" TEXT NOT NULL, + "allDay" BOOLEAN NOT NULL DEFAULT false, + "attendees" TEXT[], + "recurrence" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "buffer_before" INTEGER, + "buffer_after" INTEGER, + + CONSTRAINT "events_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "calendar_credentials" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "provider" TEXT NOT NULL DEFAULT 'GOOGLE_CALENDAR', + "accessTokenEncrypted" TEXT NOT NULL, + "refreshTokenEncrypted" TEXT NOT NULL, + "expiresAt" TIMESTAMP(3) NOT NULL, + "invalid" BOOLEAN NOT NULL DEFAULT false, + "invalidReason" TEXT, + "connectedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "lastRefreshedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "calendar_credentials_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "selected_calendars" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "credentialId" TEXT NOT NULL, + "provider" TEXT NOT NULL, + "externalCalendarId" TEXT NOT NULL, + "calendarName" TEXT NOT NULL, + "backgroundColor" TEXT, + "enabledForConflicts" BOOLEAN NOT NULL DEFAULT true, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "selected_calendars_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "destination_calendars" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "credentialId" TEXT NOT NULL, + "provider" TEXT NOT NULL DEFAULT 'GOOGLE_CALENDAR', + "externalCalendarId" TEXT NOT NULL, + "calendarName" TEXT NOT NULL, + "isPrimary" BOOLEAN NOT NULL DEFAULT false, + "selectedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "destination_calendars_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "event_references" ( + "id" TEXT NOT NULL, + "eventId" TEXT NOT NULL, + "credentialId" TEXT NOT NULL, + "externalEventId" TEXT, + "externalCalendarId" TEXT NOT NULL, + "provider" TEXT NOT NULL DEFAULT 'GOOGLE_CALENDAR', + "syncStatus" "SyncStatus" NOT NULL DEFAULT 'PENDING', + "syncStatusReason" TEXT, + "lastSyncAttemptAt" TIMESTAMP(3), + "syncedAt" TIMESTAMP(3), + "deletedAt" TIMESTAMP(3), + + CONSTRAINT "event_references_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "task_credentials" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "provider" TEXT NOT NULL DEFAULT 'GOOGLE_TASKS', + "accessTokenEncrypted" TEXT NOT NULL, + "refreshTokenEncrypted" TEXT NOT NULL, + "expiresAt" TIMESTAMP(3) NOT NULL, + "invalid" BOOLEAN NOT NULL DEFAULT false, + "invalidReason" TEXT, + "connectedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "lastRefreshedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "task_credentials_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "destination_task_lists" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "credentialId" TEXT NOT NULL, + "provider" TEXT NOT NULL DEFAULT 'GOOGLE_TASKS', + "externalTaskListId" TEXT NOT NULL, + "taskListName" TEXT NOT NULL, + "isPrimary" BOOLEAN NOT NULL DEFAULT false, + "selectedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "destination_task_lists_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "task_references" ( + "id" TEXT NOT NULL, + "taskId" TEXT NOT NULL, + "credentialId" TEXT NOT NULL, + "externalTaskId" TEXT, + "externalTaskListId" TEXT NOT NULL, + "provider" TEXT NOT NULL DEFAULT 'GOOGLE_TASKS', + "syncStatus" "SyncStatus" NOT NULL DEFAULT 'PENDING', + "syncStatusReason" TEXT, + "lastSyncAttemptAt" TIMESTAMP(3), + "syncedAt" TIMESTAMP(3), + "deletedAt" TIMESTAMP(3), + + CONSTRAINT "task_references_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "tasks" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "title" TEXT NOT NULL, + "description" TEXT, + "dueDate" TIMESTAMP(3), + "timeZone" TEXT NOT NULL, + "priority" "Priority", + "isCompleted" BOOLEAN NOT NULL DEFAULT false, + "completedAt" TIMESTAMP(3), + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3), + + CONSTRAINT "tasks_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE INDEX "accounts_userId_idx" ON "accounts"("userId"); + +-- CreateIndex +CREATE UNIQUE INDEX "accounts_provider_providerAccountId_key" ON "accounts"("provider", "providerAccountId"); + +-- CreateIndex +CREATE UNIQUE INDEX "sessions_sessionToken_key" ON "sessions"("sessionToken"); + +-- CreateIndex +CREATE INDEX "sessions_userId_idx" ON "sessions"("userId"); + +-- CreateIndex +CREATE UNIQUE INDEX "users_email_key" ON "users"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "users_stripe_customer_id_key" ON "users"("stripe_customer_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "users_stripe_subscription_id_key" ON "users"("stripe_subscription_id"); + +-- CreateIndex +CREATE UNIQUE INDEX "verification_tokens_token_key" ON "verification_tokens"("token"); + +-- CreateIndex +CREATE UNIQUE INDEX "verification_tokens_identifier_token_key" ON "verification_tokens"("identifier", "token"); + +-- CreateIndex +CREATE UNIQUE INDEX "raw_inputs_request_id_key" ON "raw_inputs"("request_id"); + +-- CreateIndex +CREATE INDEX "raw_inputs_userId_createdAt_idx" ON "raw_inputs"("userId", "createdAt"); + +-- CreateIndex +CREATE UNIQUE INDEX "raw_input_attachments_objectKey_key" ON "raw_input_attachments"("objectKey"); + +-- CreateIndex +CREATE INDEX "raw_input_attachments_rawInputId_idx" ON "raw_input_attachments"("rawInputId"); + +-- CreateIndex +CREATE INDEX "raw_input_attachments_uploadedAt_idx" ON "raw_input_attachments"("uploadedAt"); + +-- CreateIndex +CREATE UNIQUE INDEX "parsed_results_rawInputId_key" ON "parsed_results"("rawInputId"); + +-- CreateIndex +CREATE INDEX "parsed_results_userId_intent_createdAt_idx" ON "parsed_results"("userId", "intent", "createdAt"); + +-- CreateIndex +CREATE INDEX "parsed_results_aiProvider_createdAt_idx" ON "parsed_results"("aiProvider", "createdAt"); + +-- CreateIndex +CREATE INDEX "parsed_events_parseResultId_ordinal_idx" ON "parsed_events"("parseResultId", "ordinal"); + +-- CreateIndex +CREATE INDEX "parsed_events_userId_lifeCycle_createdAt_idx" ON "parsed_events"("userId", "lifeCycle", "createdAt"); + +-- CreateIndex +CREATE INDEX "parsed_tasks_parseResultId_ordinal_idx" ON "parsed_tasks"("parseResultId", "ordinal"); + +-- CreateIndex +CREATE INDEX "parsed_tasks_userId_lifeCycle_createdAt_idx" ON "parsed_tasks"("userId", "lifeCycle", "createdAt"); + +-- CreateIndex +CREATE INDEX "events_userId_start_idx" ON "events"("userId", "start"); + +-- CreateIndex +CREATE INDEX "events_userId_updatedAt_idx" ON "events"("userId", "updatedAt"); + +-- CreateIndex +CREATE INDEX "calendar_credentials_userId_idx" ON "calendar_credentials"("userId"); + +-- CreateIndex +CREATE INDEX "calendar_credentials_provider_idx" ON "calendar_credentials"("provider"); + +-- CreateIndex +CREATE INDEX "calendar_credentials_userId_invalid_idx" ON "calendar_credentials"("userId", "invalid"); + +-- CreateIndex +CREATE INDEX "selected_calendars_userId_idx" ON "selected_calendars"("userId"); + +-- CreateIndex +CREATE INDEX "selected_calendars_credentialId_idx" ON "selected_calendars"("credentialId"); + +-- CreateIndex +CREATE UNIQUE INDEX "selected_calendars_userId_provider_externalCalendarId_key" ON "selected_calendars"("userId", "provider", "externalCalendarId"); + +-- CreateIndex +CREATE INDEX "destination_calendars_credentialId_idx" ON "destination_calendars"("credentialId"); + +-- CreateIndex +CREATE UNIQUE INDEX "destination_calendars_userId_key" ON "destination_calendars"("userId"); + +-- CreateIndex +CREATE INDEX "event_references_eventId_idx" ON "event_references"("eventId"); + +-- CreateIndex +CREATE INDEX "event_references_syncStatus_idx" ON "event_references"("syncStatus"); + +-- CreateIndex +CREATE INDEX "event_references_credentialId_idx" ON "event_references"("credentialId"); + +-- CreateIndex +CREATE INDEX "event_references_credentialId_syncStatus_idx" ON "event_references"("credentialId", "syncStatus"); + +-- CreateIndex +CREATE UNIQUE INDEX "event_references_eventId_credentialId_provider_key" ON "event_references"("eventId", "credentialId", "provider"); + +-- CreateIndex +CREATE INDEX "task_credentials_userId_idx" ON "task_credentials"("userId"); + +-- CreateIndex +CREATE INDEX "task_credentials_provider_idx" ON "task_credentials"("provider"); + +-- CreateIndex +CREATE INDEX "destination_task_lists_credentialId_idx" ON "destination_task_lists"("credentialId"); + +-- CreateIndex +CREATE UNIQUE INDEX "destination_task_lists_userId_key" ON "destination_task_lists"("userId"); + +-- CreateIndex +CREATE INDEX "task_references_taskId_idx" ON "task_references"("taskId"); + +-- CreateIndex +CREATE INDEX "task_references_syncStatus_idx" ON "task_references"("syncStatus"); + +-- CreateIndex +CREATE INDEX "task_references_credentialId_idx" ON "task_references"("credentialId"); + +-- CreateIndex +CREATE UNIQUE INDEX "task_references_taskId_credentialId_provider_key" ON "task_references"("taskId", "credentialId", "provider"); + +-- CreateIndex +CREATE INDEX "tasks_userId_dueDate_idx" ON "tasks"("userId", "dueDate"); + +-- CreateIndex +CREATE INDEX "tasks_userId_completedAt_idx" ON "tasks"("userId", "completedAt"); + +-- CreateIndex +CREATE INDEX "tasks_userId_isCompleted_idx" ON "tasks"("userId", "isCompleted"); + +-- CreateIndex +CREATE INDEX "tasks_userId_isCompleted_dueDate_idx" ON "tasks"("userId", "isCompleted", "dueDate"); + +-- CreateIndex +CREATE INDEX "tasks_userId_isCompleted_priority_idx" ON "tasks"("userId", "isCompleted", "priority"); + +-- CreateIndex +CREATE INDEX "tasks_userId_isCompleted_createdAt_idx" ON "tasks"("userId", "isCompleted", "createdAt"); + +-- CreateIndex +CREATE INDEX "tasks_priority_idx" ON "tasks"("priority"); + +-- AddForeignKey +ALTER TABLE "accounts" ADD CONSTRAINT "accounts_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "sessions" ADD CONSTRAINT "sessions_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "raw_inputs" ADD CONSTRAINT "raw_inputs_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "raw_input_attachments" ADD CONSTRAINT "raw_input_attachments_rawInputId_fkey" FOREIGN KEY ("rawInputId") REFERENCES "raw_inputs"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "parsed_results" ADD CONSTRAINT "parsed_results_rawInputId_fkey" FOREIGN KEY ("rawInputId") REFERENCES "raw_inputs"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "parsed_results" ADD CONSTRAINT "parsed_results_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "parsed_events" ADD CONSTRAINT "parsed_events_parseResultId_fkey" FOREIGN KEY ("parseResultId") REFERENCES "parsed_results"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "parsed_events" ADD CONSTRAINT "parsed_events_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "parsed_tasks" ADD CONSTRAINT "parsed_tasks_parseResultId_fkey" FOREIGN KEY ("parseResultId") REFERENCES "parsed_results"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "parsed_tasks" ADD CONSTRAINT "parsed_tasks_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "events" ADD CONSTRAINT "events_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "calendar_credentials" ADD CONSTRAINT "calendar_credentials_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "selected_calendars" ADD CONSTRAINT "selected_calendars_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "selected_calendars" ADD CONSTRAINT "selected_calendars_credentialId_fkey" FOREIGN KEY ("credentialId") REFERENCES "calendar_credentials"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "destination_calendars" ADD CONSTRAINT "destination_calendars_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "destination_calendars" ADD CONSTRAINT "destination_calendars_credentialId_fkey" FOREIGN KEY ("credentialId") REFERENCES "calendar_credentials"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "event_references" ADD CONSTRAINT "event_references_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "events"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "event_references" ADD CONSTRAINT "event_references_credentialId_fkey" FOREIGN KEY ("credentialId") REFERENCES "calendar_credentials"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "task_credentials" ADD CONSTRAINT "task_credentials_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "destination_task_lists" ADD CONSTRAINT "destination_task_lists_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "destination_task_lists" ADD CONSTRAINT "destination_task_lists_credentialId_fkey" FOREIGN KEY ("credentialId") REFERENCES "task_credentials"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "task_references" ADD CONSTRAINT "task_references_taskId_fkey" FOREIGN KEY ("taskId") REFERENCES "tasks"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "task_references" ADD CONSTRAINT "task_references_credentialId_fkey" FOREIGN KEY ("credentialId") REFERENCES "task_credentials"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "tasks" ADD CONSTRAINT "tasks_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 00000000..fbffa92c --- /dev/null +++ b/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" \ No newline at end of file From c6b0e3e8c3650f1ea2732d6a585d4b356c3980a6 Mon Sep 17 00:00:00 2001 From: KiwiGaze <1244666638@qq.com> Date: Wed, 31 Dec 2025 18:00:11 +0800 Subject: [PATCH 004/428] fix: Increase Node.js memory limit for build and preview scripts. --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2772b55e..e89c49e5 100644 --- a/package.json +++ b/package.json @@ -8,11 +8,11 @@ }, "scripts": { "dev": "NODE_OPTIONS='--no-deprecation' next dev --turbo", - "build": "prisma generate && prisma migrate deploy && next build", + "build": "prisma generate && prisma migrate deploy && NODE_OPTIONS='--max-old-space-size=4096' next build", "turbo": "NODE_OPTIONS='--no-deprecation' next dev --turbo", "start": "NODE_OPTIONS='--no-deprecation' next start", "lint": "eslint .", - "preview": "next build && next start", + "preview": "NODE_OPTIONS='--max-old-space-size=4096' next build && next start", "postinstall": "prisma generate", "email": "email dev --dir emails --port 3333", "db:push": "prisma db push", From 24d716d09067564db8fc242c92c49afa122f3f70 Mon Sep 17 00:00:00 2001 From: KiwiGaze <1244666638@qq.com> Date: Wed, 31 Dec 2025 18:12:46 +0800 Subject: [PATCH 005/428] refactor: remove Next.js output file tracing configuration and add Sentry auth token example to environment. --- .env.example | 1 + next.config.js | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 0caa2f3d..0e64815a 100644 --- a/.env.example +++ b/.env.example @@ -61,6 +61,7 @@ SENTRY_TRACES_SAMPLE_RATE=1.0 SENTRY_DEBUG="1" # Enable Sentry client-side logging ("true" or "1" to enable) SENTRY_ENABLE_LOGS="false" +SENTRY_AUTH_TOKEN = "" # ----------------------------------------------------------------------------- # Parser Provider Configuration diff --git a/next.config.js b/next.config.js index b572876e..3d9bf0a0 100644 --- a/next.config.js +++ b/next.config.js @@ -1,12 +1,10 @@ const { withSentryConfig } = require("@sentry/nextjs"); -const path = require("path"); import("./env.mjs"); /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, - outputFileTracingRoot: path.join(__dirname, "../../"), images: { remotePatterns: [ { From 912c533cbb02a7c5613adcacfdcac37a49655b8e Mon Sep 17 00:00:00 2001 From: KiwiGaze <1244666638@qq.com> Date: Wed, 31 Dec 2025 23:26:57 +0800 Subject: [PATCH 006/428] fix(parsing-input): correct textarea display in fullscreen mode - Add isFullscreen prop to ParsingTextarea component - Use dedicated fullscreen rendering that fills container properly - Replace overflow-y-auto with min-h-0 for correct flex behavior - Extract base textarea classes to avoid duplication --- components/parsing/parsing-input.tsx | 3 ++- .../parsing-input/parsing-textarea.tsx | 26 +++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/components/parsing/parsing-input.tsx b/components/parsing/parsing-input.tsx index ea8f9fd3..07a15cac 100644 --- a/components/parsing/parsing-input.tsx +++ b/components/parsing/parsing-input.tsx @@ -613,7 +613,7 @@ export function ParsingInput({ onRequestExternalFileHandler, voiceEnabled = true )} -
+
setIsFocused(true)} onBlur={() => setIsFocused(false)} + isFullscreen={isFullscreen} />
diff --git a/components/parsing/parsing-input/parsing-textarea.tsx b/components/parsing/parsing-input/parsing-textarea.tsx index e0e4e2e4..63adf41d 100644 --- a/components/parsing/parsing-input/parsing-textarea.tsx +++ b/components/parsing/parsing-input/parsing-textarea.tsx @@ -15,6 +15,7 @@ export interface ParsingTextareaProps { maxRows?: number; onFocus?: () => void; onBlur?: () => void; + isFullscreen?: boolean; } export function ParsingTextarea({ @@ -25,7 +26,8 @@ export function ParsingTextarea({ onRowCountChange, maxRows = 6, onFocus, - onBlur + onBlur, + isFullscreen = false }: ParsingTextareaProps) { const textareaRef = useRef(null); @@ -45,7 +47,27 @@ export function ParsingTextarea({ } }; + const baseClasses = "custom-scrollbar w-full resize-none border-0 bg-transparent px-1 py-2 font-urban text-base font-medium leading-relaxed tracking-tight text-foreground placeholder:text-muted-foreground/50 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 md:text-lg"; + // In fullscreen mode, use a regular textarea that fills the container + if (isFullscreen) { + return ( +
+