chore: import upstream snapshot with attribution
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
+11
View File
@@ -0,0 +1,11 @@
# Database connection used by @sim/db scripts (drizzle-kit generate,
# db:migrate, register-sso-provider, etc.). Must match DATABASE_URL in
# apps/sim/.env and apps/realtime/.env. Migrations always run against the
# primary — never set a replica URL here.
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/simstudio"
# Direct (non-pooled) DSN for db:migrate. Required when DATABASE_URL points at
# a transaction-pooling PgBouncer: session advisory locks and session SETs are
# unsupported through transaction pooling. Falls back to DATABASE_URL.
# MIGRATION_DATABASE_URL=""
+57
View File
@@ -0,0 +1,57 @@
/**
* @vitest-environment node
*/
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
import { resolveDbUrl } from './connection-url'
describe('resolveDbUrl', () => {
const KEYS = [
'DATABASE_URL',
'DATABASE_URL_WEB',
'DATABASE_URL_TRIGGER',
'DATABASE_REPLICA_URL',
'DATABASE_REPLICA_URL_TRIGGER',
] as const
const saved: Record<string, string | undefined> = {}
beforeEach(() => {
for (const key of KEYS) {
saved[key] = process.env[key]
delete process.env[key]
}
})
afterEach(() => {
for (const key of KEYS) {
if (saved[key] === undefined) delete process.env[key]
else process.env[key] = saved[key]
}
})
it('prefers the role-keyed primary URL over the base', () => {
process.env.DATABASE_URL = 'postgres://base/db'
process.env.DATABASE_URL_TRIGGER = 'postgres://trigger/db'
expect(resolveDbUrl('DATABASE_URL', 'trigger')).toBe('postgres://trigger/db')
})
it('falls back to the base URL when the keyed var is unset', () => {
process.env.DATABASE_URL = 'postgres://base/db'
expect(resolveDbUrl('DATABASE_URL', 'web')).toBe('postgres://base/db')
})
it('returns undefined when neither keyed nor base is set', () => {
expect(resolveDbUrl('DATABASE_URL', 'realtime')).toBeUndefined()
})
it('resolves the replica variant independently of the primary', () => {
process.env.DATABASE_REPLICA_URL = 'postgres://replica/db'
process.env.DATABASE_REPLICA_URL_TRIGGER = 'postgres://trigger-replica/db'
expect(resolveDbUrl('DATABASE_REPLICA_URL', 'trigger')).toBe('postgres://trigger-replica/db')
expect(resolveDbUrl('DATABASE_REPLICA_URL', 'web')).toBe('postgres://replica/db')
})
it('uppercases the role to build the keyed var name', () => {
process.env.DATABASE_URL_WEB = 'postgres://web/db'
expect(resolveDbUrl('DATABASE_URL', 'web')).toBe('postgres://web/db')
})
})
+12
View File
@@ -0,0 +1,12 @@
/**
* Resolve a connection URL for the active DB role, preferring the role-keyed
* variant (e.g. `DATABASE_URL_TRIGGER`) and falling back to the shared base.
* Lets each deploy point its surface at its own Postgres user + PgBouncer via
* env alone; unset keyed vars preserve the prior single-URL behavior.
*/
export function resolveDbUrl(
base: 'DATABASE_URL' | 'DATABASE_REPLICA_URL',
role: string
): string | undefined {
return process.env[`${base}_${role.toUpperCase()}`] ?? process.env[base]
}
+73
View File
@@ -0,0 +1,73 @@
/**
* Database-only constants used in schema definitions and migrations.
* These constants are independent of application logic to keep migrations container lightweight.
*/
/**
* Default free credits (in dollars) for new users
*/
export const DEFAULT_FREE_CREDITS = 5
/**
* Storage limit constants (in GB)
* Can be overridden via environment variables
*/
export const DEFAULT_FREE_STORAGE_LIMIT_GB = 5
export const DEFAULT_PRO_STORAGE_LIMIT_GB = 50
export const DEFAULT_TEAM_STORAGE_LIMIT_GB = 500
export const DEFAULT_ENTERPRISE_STORAGE_LIMIT_GB = 500
/**
* Text tag slots for knowledge base documents and embeddings
*/
export const TEXT_TAG_SLOTS = ['tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6', 'tag7'] as const
/**
* Number tag slots for knowledge base documents and embeddings (5 slots)
*/
export const NUMBER_TAG_SLOTS = ['number1', 'number2', 'number3', 'number4', 'number5'] as const
/**
* Date tag slots for knowledge base documents and embeddings (2 slots)
*/
export const DATE_TAG_SLOTS = ['date1', 'date2'] as const
/**
* Boolean tag slots for knowledge base documents and embeddings (3 slots)
*/
export const BOOLEAN_TAG_SLOTS = ['boolean1', 'boolean2', 'boolean3'] as const
/**
* All tag slots combined (for backwards compatibility)
*/
export const TAG_SLOTS = [
...TEXT_TAG_SLOTS,
...NUMBER_TAG_SLOTS,
...DATE_TAG_SLOTS,
...BOOLEAN_TAG_SLOTS,
] as const
/**
* Type for all tag slot names
*/
export type TagSlot = (typeof TAG_SLOTS)[number]
/**
* Type for text tag slot names
*/
export type TextTagSlot = (typeof TEXT_TAG_SLOTS)[number]
/**
* Type for number tag slot names
*/
export type NumberTagSlot = (typeof NUMBER_TAG_SLOTS)[number]
/**
* Type for date tag slot names
*/
export type DateTagSlot = (typeof DATE_TAG_SLOTS)[number]
/**
* Type for boolean tag slot names
*/
export type BooleanTagSlot = (typeof BOOLEAN_TAG_SLOTS)[number]
+73
View File
@@ -0,0 +1,73 @@
import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'
import { resolveDbUrl } from './connection-url'
import * as schema from './schema'
import { instrumentPoolClient } from './tx-tripwire'
/**
* Per-role pool profiles. Starting numbers — validate against real per-role
* process counts (PgBouncer transaction mode, max_connections=200).
*/
export const DB_POOL_PROFILES = {
web: { primaryMax: 10, replicaMax: 4, appName: 'sim-app' },
// 5, not 3 — one run can need 3+ simultaneous connections (parallel queries +
// overlapping logging writes); 3 risks intra-run deadlock.
trigger: { primaryMax: 5, replicaMax: 2, appName: 'sim-trigger' },
realtime: { primaryMax: 5, replicaMax: 3, appName: 'sim-realtime' },
} as const
type DbRole = keyof typeof DB_POOL_PROFILES
const roleEnv = process.env.SIM_DB_ROLE?.trim()
if (roleEnv && !Object.hasOwn(DB_POOL_PROFILES, roleEnv)) {
throw new Error(
`Invalid SIM_DB_ROLE '${roleEnv}' — expected one of ${Object.keys(DB_POOL_PROFILES).join(', ')} (or unset for web)`
)
}
const role = (roleEnv as DbRole) || 'web'
const profile = DB_POOL_PROFILES[role]
const connectionString = resolveDbUrl('DATABASE_URL', role)
if (!connectionString) {
throw new Error('Missing DATABASE_URL environment variable')
}
const poolOptions = {
prepare: false,
idle_timeout: 20,
connect_timeout: 30,
onnotice: () => {},
connection: { application_name: process.env.DB_APP_NAME ?? profile.appName },
}
const postgresClient = instrumentPoolClient(
postgres(connectionString, { ...poolOptions, max: profile.primaryMax }),
'db'
)
export const db = drizzle(postgresClient, { schema })
/**
* Opt-in read-replica client for reads that tolerate bounded staleness and have
* no read-your-writes dependency (logs, exports, dashboard aggregations). Never
* for auth, workflow state, or billing enforcement. Falls back to the primary
* when `DATABASE_REPLICA_URL` is unset, so call sites never branch.
*/
const replicaUrl = resolveDbUrl('DATABASE_REPLICA_URL', role)
if (replicaUrl && !/^postgres(ql)?:\/\//.test(replicaUrl)) {
throw new Error(
'DATABASE_REPLICA_URL is set but is not a postgres:// DSN — fix the URL or unset the variable'
)
}
export const dbReplica: typeof db = replicaUrl
? drizzle(
instrumentPoolClient(
postgres(replicaUrl, { ...poolOptions, max: profile.replicaMax }),
'dbReplica'
),
{
schema,
}
)
: db
+18
View File
@@ -0,0 +1,18 @@
import { relative } from 'node:path'
import { fileURLToPath } from 'node:url'
import type { Config } from 'drizzle-kit'
const schemaPath = relative(process.cwd(), fileURLToPath(new URL('./schema.ts', import.meta.url)))
const migrationsPath = relative(
process.cwd(),
fileURLToPath(new URL('./migrations', import.meta.url))
)
export default {
schema: schemaPath,
out: migrationsPath,
dialect: 'postgresql',
dbCredentials: {
url: process.env.DATABASE_URL!,
},
} satisfies Config
+5
View File
@@ -0,0 +1,5 @@
export * from './connection-url'
export * from './db'
export * from './schema'
export * from './triggers'
export { instrumentPoolClient, runOutsideTransactionContext } from './tx-tripwire'
@@ -0,0 +1,52 @@
-- Current sql file was generated after introspecting the database
CREATE TABLE "verification" (
"id" text PRIMARY KEY NOT NULL,
"identifier" text NOT NULL,
"value" text NOT NULL,
"expires_at" timestamp NOT NULL,
"created_at" timestamp,
"updated_at" timestamp
);
--> statement-breakpoint
CREATE TABLE "user" (
"id" text PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"email" text NOT NULL,
"email_verified" boolean NOT NULL,
"image" text,
"created_at" timestamp NOT NULL,
"updated_at" timestamp NOT NULL,
CONSTRAINT "user_email_unique" UNIQUE("email")
);
--> statement-breakpoint
CREATE TABLE "account" (
"id" text PRIMARY KEY NOT NULL,
"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 NOT NULL,
"updated_at" timestamp NOT NULL
);
--> statement-breakpoint
CREATE TABLE "session" (
"id" text PRIMARY KEY NOT NULL,
"expires_at" timestamp NOT NULL,
"token" text NOT NULL,
"created_at" timestamp NOT NULL,
"updated_at" timestamp NOT NULL,
"ip_address" text,
"user_agent" text,
"user_id" text NOT NULL,
CONSTRAINT "session_token_unique" UNIQUE("token")
);
--> statement-breakpoint
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
@@ -0,0 +1,12 @@
CREATE TABLE "workflow" (
"id" text PRIMARY KEY NOT NULL,
"user_id" text NOT NULL,
"name" text NOT NULL,
"description" text,
"state" text NOT NULL,
"last_synced" timestamp NOT NULL,
"created_at" timestamp NOT NULL,
"updated_at" timestamp NOT NULL
);
--> statement-breakpoint
ALTER TABLE "workflow" ADD CONSTRAINT "workflow_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
@@ -0,0 +1,8 @@
CREATE TABLE "waitlist" (
"id" text PRIMARY KEY NOT NULL,
"email" text NOT NULL,
"status" text DEFAULT 'pending' NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL,
CONSTRAINT "waitlist_email_unique" UNIQUE("email")
);
@@ -0,0 +1,28 @@
CREATE TABLE "logs" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text NOT NULL,
"execution_id" text,
"level" text NOT NULL,
"message" text NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "user_environment" (
"id" text PRIMARY KEY NOT NULL,
"user_id" text NOT NULL,
"variables" text NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL,
CONSTRAINT "user_environment_user_id_unique" UNIQUE("user_id")
);
--> statement-breakpoint
CREATE TABLE "user_settings" (
"id" text PRIMARY KEY NOT NULL,
"user_id" text NOT NULL,
"is_auto_connect_enabled" boolean DEFAULT true NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL,
CONSTRAINT "user_settings_user_id_unique" UNIQUE("user_id")
);
--> statement-breakpoint
ALTER TABLE "logs" ADD CONSTRAINT "logs_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "user_environment" ADD CONSTRAINT "user_environment_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "user_settings" ADD CONSTRAINT "user_settings_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
@@ -0,0 +1 @@
ALTER TABLE "user_settings" ADD COLUMN "is_debug_mode_enabled" boolean DEFAULT false NOT NULL;
@@ -0,0 +1,13 @@
CREATE TABLE "workflow_schedule" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text NOT NULL,
"cron_expression" text,
"next_run_at" timestamp,
"last_ran_at" timestamp,
"trigger_type" text NOT NULL,
"timezone" text DEFAULT 'UTC' NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "workflow_schedule" ADD CONSTRAINT "workflow_schedule_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;
@@ -0,0 +1,35 @@
CREATE TABLE "workflow_logs" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text NOT NULL,
"execution_id" text,
"level" text NOT NULL,
"message" text NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "settings" (
"id" text PRIMARY KEY NOT NULL,
"user_id" text NOT NULL,
"general" json NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL,
CONSTRAINT "settings_user_id_unique" UNIQUE("user_id")
);
--> statement-breakpoint
CREATE TABLE "environment" (
"id" text PRIMARY KEY NOT NULL,
"user_id" text NOT NULL,
"variables" json NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL,
CONSTRAINT "environment_user_id_unique" UNIQUE("user_id")
);
--> statement-breakpoint
ALTER TABLE "logs" DISABLE ROW LEVEL SECURITY;--> statement-breakpoint
ALTER TABLE "user_environment" DISABLE ROW LEVEL SECURITY;--> statement-breakpoint
ALTER TABLE "user_settings" DISABLE ROW LEVEL SECURITY;--> statement-breakpoint
DROP TABLE "logs" CASCADE;--> statement-breakpoint
DROP TABLE "user_environment" CASCADE;--> statement-breakpoint
DROP TABLE "user_settings" CASCADE;--> statement-breakpoint
ALTER TABLE "workflow" ALTER COLUMN "state" SET DATA TYPE json USING state::json;--> statement-breakpoint
ALTER TABLE "workflow_logs" ADD CONSTRAINT "workflow_logs_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "settings" ADD CONSTRAINT "settings_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "environment" ADD CONSTRAINT "environment_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
@@ -0,0 +1 @@
ALTER TABLE "workflow_schedule" ADD CONSTRAINT "workflow_schedule_workflow_id_unique" UNIQUE("workflow_id");
@@ -0,0 +1 @@
ALTER TABLE "workflow_logs" ADD COLUMN "duration" text;
@@ -0,0 +1,3 @@
ALTER TABLE "workflow" ADD COLUMN "is_deployed" boolean DEFAULT false NOT NULL;--> statement-breakpoint
ALTER TABLE "workflow" ADD COLUMN "deployed_at" timestamp;--> statement-breakpoint
ALTER TABLE "workflow" ADD COLUMN "api_key" text;
@@ -0,0 +1 @@
ALTER TABLE "workflow_logs" ADD COLUMN "trigger" text NOT NULL;
@@ -0,0 +1 @@
ALTER TABLE "workflow_logs" ALTER COLUMN "trigger" DROP NOT NULL;
@@ -0,0 +1 @@
ALTER TABLE "workflow" ADD COLUMN "color" text DEFAULT '#3972F6' NOT NULL;
@@ -0,0 +1,13 @@
CREATE TABLE "webhook" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text NOT NULL,
"path" text NOT NULL,
"secret" text,
"provider" text,
"is_active" boolean DEFAULT true NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "webhook" ADD CONSTRAINT "webhook_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "path_idx" ON "webhook" USING btree ("path");
@@ -0,0 +1,2 @@
ALTER TABLE "webhook" ADD COLUMN "provider_config" json;--> statement-breakpoint
ALTER TABLE "webhook" DROP COLUMN "secret";
@@ -0,0 +1 @@
ALTER TABLE "workflow_logs" ADD COLUMN "metadata" json;
@@ -0,0 +1 @@
ALTER TABLE "workflow" ADD COLUMN "collaborators" json DEFAULT '[]' NOT NULL;
@@ -0,0 +1,13 @@
CREATE TABLE "api_key" (
"id" text PRIMARY KEY NOT NULL,
"user_id" text NOT NULL,
"name" text NOT NULL,
"key" text NOT NULL,
"last_used" timestamp,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL,
"expires_at" timestamp,
CONSTRAINT "api_key_key_unique" UNIQUE("key")
);
--> statement-breakpoint
ALTER TABLE "api_key" ADD CONSTRAINT "api_key_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
@@ -0,0 +1,36 @@
CREATE TABLE "marketplace" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text NOT NULL,
"state" json NOT NULL,
"name" text NOT NULL,
"description" text,
"author_id" text NOT NULL,
"author_name" text NOT NULL,
"stars" integer DEFAULT 0 NOT NULL,
"executions" integer DEFAULT 0 NOT NULL,
"category" text,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "marketplace_execution" (
"id" text PRIMARY KEY NOT NULL,
"marketplace_id" text NOT NULL,
"user_id" text,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "marketplace_star" (
"id" text PRIMARY KEY NOT NULL,
"marketplace_id" text NOT NULL,
"user_id" text NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "marketplace" ADD CONSTRAINT "marketplace_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "marketplace" ADD CONSTRAINT "marketplace_author_id_user_id_fk" FOREIGN KEY ("author_id") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "marketplace_execution" ADD CONSTRAINT "marketplace_execution_marketplace_id_marketplace_id_fk" FOREIGN KEY ("marketplace_id") REFERENCES "public"."marketplace"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "marketplace_execution" ADD CONSTRAINT "marketplace_execution_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "marketplace_star" ADD CONSTRAINT "marketplace_star_marketplace_id_marketplace_id_fk" FOREIGN KEY ("marketplace_id") REFERENCES "public"."marketplace"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "marketplace_star" ADD CONSTRAINT "marketplace_star_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "user_marketplace_idx" ON "marketplace_star" USING btree ("user_id","marketplace_id");
@@ -0,0 +1,2 @@
DROP TABLE "marketplace_execution" CASCADE;--> statement-breakpoint
ALTER TABLE "marketplace" RENAME COLUMN "executions" TO "views";
@@ -0,0 +1 @@
ALTER TABLE "workflow" ADD COLUMN "is_published" boolean DEFAULT false NOT NULL;
@@ -0,0 +1,16 @@
CREATE TABLE "user_stats" (
"id" text PRIMARY KEY NOT NULL,
"user_id" text NOT NULL,
"total_manual_executions" integer DEFAULT 0 NOT NULL,
"total_api_calls" integer DEFAULT 0 NOT NULL,
"total_webhook_triggers" integer DEFAULT 0 NOT NULL,
"total_scheduled_executions" integer DEFAULT 0 NOT NULL,
"total_tokens_used" integer DEFAULT 0 NOT NULL,
"total_cost" numeric DEFAULT '0' NOT NULL,
"last_active" timestamp DEFAULT now() NOT NULL,
CONSTRAINT "user_stats_user_id_unique" UNIQUE("user_id")
);
--> statement-breakpoint
ALTER TABLE "workflow" ADD COLUMN "run_count" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
ALTER TABLE "workflow" ADD COLUMN "last_run_at" timestamp;--> statement-breakpoint
ALTER TABLE "user_stats" ADD CONSTRAINT "user_stats_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
@@ -0,0 +1 @@
ALTER TABLE "workflow" ADD COLUMN "variables" json DEFAULT '{}';
@@ -0,0 +1 @@
ALTER TABLE "workflow" DROP COLUMN "api_key";
@@ -0,0 +1 @@
ALTER TABLE "workflow" ADD COLUMN "marketplace_data" json DEFAULT 'null'::json;
@@ -0,0 +1 @@
ALTER TABLE "workflow" ALTER COLUMN "marketplace_data" DROP DEFAULT;
@@ -0,0 +1 @@
ALTER TABLE "workflow" ADD COLUMN "deployed_state" json;
@@ -0,0 +1,2 @@
DROP TABLE "marketplace_star" CASCADE;--> statement-breakpoint
ALTER TABLE "marketplace" DROP COLUMN "stars";
@@ -0,0 +1,11 @@
CREATE TABLE "custom_tools" (
"id" text PRIMARY KEY NOT NULL,
"user_id" text NOT NULL,
"title" text NOT NULL,
"schema" json NOT NULL,
"code" text NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "custom_tools" ADD CONSTRAINT "custom_tools_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
@@ -0,0 +1,35 @@
CREATE TABLE "chat" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text NOT NULL,
"user_id" text NOT NULL,
"subdomain" text NOT NULL,
"title" text NOT NULL,
"description" text,
"is_active" boolean DEFAULT true NOT NULL,
"customizations" json DEFAULT '{}',
"auth_type" text DEFAULT 'public' NOT NULL,
"password" text,
"allowed_emails" json DEFAULT '[]',
"output_block_id" text,
"output_path" text,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "subscription" (
"id" text PRIMARY KEY NOT NULL,
"plan" text NOT NULL,
"reference_id" text NOT NULL,
"stripe_customer_id" text,
"stripe_subscription_id" text,
"status" text,
"period_start" timestamp,
"period_end" timestamp,
"cancel_at_period_end" boolean,
"seats" integer
);
--> statement-breakpoint
ALTER TABLE "user" ADD COLUMN "stripe_customer_id" text;--> statement-breakpoint
ALTER TABLE "chat" ADD CONSTRAINT "chat_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "chat" ADD CONSTRAINT "chat_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "subdomain_idx" ON "chat" USING btree ("subdomain");
@@ -0,0 +1,37 @@
CREATE TABLE "invitation" (
"id" text PRIMARY KEY NOT NULL,
"email" text NOT NULL,
"inviter_id" text NOT NULL,
"organization_id" text NOT NULL,
"role" text NOT NULL,
"status" text NOT NULL,
"expires_at" timestamp NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "member" (
"id" text PRIMARY KEY NOT NULL,
"user_id" text NOT NULL,
"organization_id" text NOT NULL,
"role" text NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "organization" (
"id" text PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"slug" text NOT NULL,
"logo" text,
"metadata" jsonb,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "session" ADD COLUMN "active_organization_id" text;--> statement-breakpoint
ALTER TABLE "subscription" ADD COLUMN "trial_start" timestamp;--> statement-breakpoint
ALTER TABLE "subscription" ADD COLUMN "trial_end" timestamp;--> statement-breakpoint
ALTER TABLE "invitation" ADD CONSTRAINT "invitation_inviter_id_user_id_fk" FOREIGN KEY ("inviter_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "invitation" ADD CONSTRAINT "invitation_organization_id_organization_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "member" ADD CONSTRAINT "member_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "member" ADD CONSTRAINT "member_organization_id_organization_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "session" ADD CONSTRAINT "session_active_organization_id_organization_id_fk" FOREIGN KEY ("active_organization_id") REFERENCES "public"."organization"("id") ON DELETE set null ON UPDATE no action;
@@ -0,0 +1,3 @@
ALTER TABLE "chat" ADD COLUMN "output_configs" json DEFAULT '[]';--> statement-breakpoint
ALTER TABLE "chat" DROP COLUMN "output_block_id";--> statement-breakpoint
ALTER TABLE "chat" DROP COLUMN "output_path";
@@ -0,0 +1,7 @@
ALTER TABLE "settings" ALTER COLUMN "general" SET DEFAULT '{}';--> statement-breakpoint
ALTER TABLE "settings" ADD COLUMN "theme" text DEFAULT 'system' NOT NULL;--> statement-breakpoint
ALTER TABLE "settings" ADD COLUMN "debug_mode" boolean DEFAULT false NOT NULL;--> statement-breakpoint
ALTER TABLE "settings" ADD COLUMN "auto_connect" boolean DEFAULT true NOT NULL;--> statement-breakpoint
ALTER TABLE "settings" ADD COLUMN "auto_fill_env_vars" boolean DEFAULT true NOT NULL;--> statement-breakpoint
ALTER TABLE "settings" ADD COLUMN "telemetry_enabled" boolean DEFAULT true NOT NULL;--> statement-breakpoint
ALTER TABLE "settings" ADD COLUMN "telemetry_notified_user" boolean DEFAULT false NOT NULL;
@@ -0,0 +1,23 @@
CREATE TABLE "workspace" (
"id" text PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"owner_id" text NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "workspace_member" (
"id" text PRIMARY KEY NOT NULL,
"workspace_id" text NOT NULL,
"user_id" text NOT NULL,
"role" text DEFAULT 'member' NOT NULL,
"joined_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "workflow" ADD COLUMN "workspace_id" text;--> statement-breakpoint
ALTER TABLE "workspace" ADD CONSTRAINT "workspace_owner_id_user_id_fk" FOREIGN KEY ("owner_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workspace_member" ADD CONSTRAINT "workspace_member_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workspace_member" ADD CONSTRAINT "workspace_member_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "user_workspace_idx" ON "workspace_member" USING btree ("user_id","workspace_id");--> statement-breakpoint
ALTER TABLE "workflow" ADD CONSTRAINT "workflow_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE cascade ON UPDATE no action;
@@ -0,0 +1,16 @@
CREATE TABLE "workspace_invitation" (
"id" text PRIMARY KEY NOT NULL,
"workspace_id" text NOT NULL,
"email" text NOT NULL,
"inviter_id" text NOT NULL,
"role" text DEFAULT 'member' NOT NULL,
"status" text DEFAULT 'pending' NOT NULL,
"token" text NOT NULL,
"expires_at" timestamp NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL,
CONSTRAINT "workspace_invitation_token_unique" UNIQUE("token")
);
--> statement-breakpoint
ALTER TABLE "workspace_invitation" ADD CONSTRAINT "workspace_invitation_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workspace_invitation" ADD CONSTRAINT "workspace_invitation_inviter_id_user_id_fk" FOREIGN KEY ("inviter_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
@@ -0,0 +1,3 @@
ALTER TABLE "organization" ALTER COLUMN "metadata" SET DATA TYPE json;--> statement-breakpoint
ALTER TABLE "subscription" ADD COLUMN "metadata" json;--> statement-breakpoint
ALTER TABLE "user_stats" ADD COLUMN "total_chat_executions" integer DEFAULT 0 NOT NULL;
@@ -0,0 +1,3 @@
ALTER TABLE "workflow_schedule" ADD COLUMN "failed_count" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
ALTER TABLE "workflow_schedule" ADD COLUMN "status" text DEFAULT 'active' NOT NULL;--> statement-breakpoint
ALTER TABLE "workflow_schedule" ADD COLUMN "last_failed_at" timestamp;
@@ -0,0 +1,15 @@
CREATE TABLE "memory" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text,
"key" text NOT NULL,
"type" text NOT NULL,
"data" json NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL,
"deleted_at" timestamp
);
--> statement-breakpoint
ALTER TABLE "memory" ADD CONSTRAINT "memory_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "memory_key_idx" ON "memory" USING btree ("key");--> statement-breakpoint
CREATE INDEX "memory_workflow_idx" ON "memory" USING btree ("workflow_id");--> statement-breakpoint
CREATE UNIQUE INDEX "memory_workflow_key_idx" ON "memory" USING btree ("workflow_id","key");
@@ -0,0 +1,114 @@
-- Enable pgvector extension
CREATE EXTENSION IF NOT EXISTS vector;
-- Create knowledge_base table
CREATE TABLE IF NOT EXISTS "knowledge_base" (
"id" text PRIMARY KEY NOT NULL,
"user_id" text NOT NULL,
"workspace_id" text,
"name" text NOT NULL,
"description" text,
"token_count" integer DEFAULT 0 NOT NULL,
"embedding_model" text DEFAULT 'text-embedding-3-small' NOT NULL,
"embedding_dimension" integer DEFAULT 1536 NOT NULL,
"chunking_config" json DEFAULT '{"maxSize": 1024, "minSize": 100, "overlap": 200}' NOT NULL,
"deleted_at" timestamp,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
-- Create document table
CREATE TABLE IF NOT EXISTS "document" (
"id" text PRIMARY KEY NOT NULL,
"knowledge_base_id" text NOT NULL,
"filename" text NOT NULL,
"file_url" text NOT NULL,
"file_size" integer NOT NULL,
"mime_type" text NOT NULL,
"file_hash" text,
"chunk_count" integer DEFAULT 0 NOT NULL,
"token_count" integer DEFAULT 0 NOT NULL,
"character_count" integer DEFAULT 0 NOT NULL,
"enabled" boolean DEFAULT true NOT NULL,
"deleted_at" timestamp,
"uploaded_at" timestamp DEFAULT now() NOT NULL
);
-- Create embedding table with optimized vector type
CREATE TABLE IF NOT EXISTS "embedding" (
"id" text PRIMARY KEY NOT NULL,
"knowledge_base_id" text NOT NULL,
"document_id" text NOT NULL,
"chunk_index" integer NOT NULL,
"chunk_hash" text NOT NULL,
"content" text NOT NULL,
"content_length" integer NOT NULL,
"token_count" integer NOT NULL,
"embedding" vector(1536) NOT NULL, -- Optimized for text-embedding-3-small with HNSW support
"embedding_model" text DEFAULT 'text-embedding-3-small' NOT NULL,
"start_offset" integer NOT NULL,
"end_offset" integer NOT NULL,
"overlap_tokens" integer DEFAULT 0 NOT NULL,
"metadata" jsonb DEFAULT '{}' NOT NULL,
"search_rank" numeric DEFAULT '1.0',
"access_count" integer DEFAULT 0 NOT NULL,
"last_accessed_at" timestamp,
"quality_score" numeric,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL,
-- Ensure embedding exists (simplified constraint)
CONSTRAINT "embedding_not_null_check" CHECK ("embedding" IS NOT NULL)
);
-- Add foreign key constraints
ALTER TABLE "knowledge_base" ADD CONSTRAINT "knowledge_base_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "knowledge_base" ADD CONSTRAINT "knowledge_base_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "workspace"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "document" ADD CONSTRAINT "document_knowledge_base_id_knowledge_base_id_fk" FOREIGN KEY ("knowledge_base_id") REFERENCES "knowledge_base"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "embedding" ADD CONSTRAINT "embedding_knowledge_base_id_knowledge_base_id_fk" FOREIGN KEY ("knowledge_base_id") REFERENCES "knowledge_base"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "embedding" ADD CONSTRAINT "embedding_document_id_document_id_fk" FOREIGN KEY ("document_id") REFERENCES "document"("id") ON DELETE cascade ON UPDATE no action;
-- Create indexes for knowledge_base table
CREATE INDEX IF NOT EXISTS "kb_user_id_idx" ON "knowledge_base" USING btree ("user_id");
CREATE INDEX IF NOT EXISTS "kb_workspace_id_idx" ON "knowledge_base" USING btree ("workspace_id");
CREATE INDEX IF NOT EXISTS "kb_user_workspace_idx" ON "knowledge_base" USING btree ("user_id","workspace_id");
CREATE INDEX IF NOT EXISTS "kb_deleted_at_idx" ON "knowledge_base" USING btree ("deleted_at");
-- Create indexes for document table
CREATE INDEX IF NOT EXISTS "doc_kb_id_idx" ON "document" USING btree ("knowledge_base_id");
CREATE INDEX IF NOT EXISTS "doc_file_hash_idx" ON "document" USING btree ("file_hash");
CREATE INDEX IF NOT EXISTS "doc_filename_idx" ON "document" USING btree ("filename");
CREATE INDEX IF NOT EXISTS "doc_kb_uploaded_at_idx" ON "document" USING btree ("knowledge_base_id","uploaded_at");
-- Create embedding table indexes
CREATE INDEX IF NOT EXISTS "emb_kb_id_idx" ON "embedding" USING btree ("knowledge_base_id");
CREATE INDEX IF NOT EXISTS "emb_doc_id_idx" ON "embedding" USING btree ("document_id");
CREATE UNIQUE INDEX IF NOT EXISTS "emb_doc_chunk_idx" ON "embedding" USING btree ("document_id","chunk_index");
CREATE INDEX IF NOT EXISTS "emb_kb_model_idx" ON "embedding" USING btree ("knowledge_base_id","embedding_model");
CREATE INDEX IF NOT EXISTS "emb_chunk_hash_idx" ON "embedding" USING btree ("chunk_hash");
CREATE INDEX IF NOT EXISTS "emb_kb_access_idx" ON "embedding" USING btree ("knowledge_base_id","last_accessed_at");
CREATE INDEX IF NOT EXISTS "emb_kb_rank_idx" ON "embedding" USING btree ("knowledge_base_id","search_rank");
-- Create optimized HNSW index for vector similarity search
CREATE INDEX IF NOT EXISTS "embedding_vector_hnsw_idx" ON "embedding"
USING hnsw ("embedding" vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- GIN index for JSONB metadata queries
CREATE INDEX IF NOT EXISTS "emb_metadata_gin_idx" ON "embedding" USING gin ("metadata");
-- Full-text search support with generated tsvector column
ALTER TABLE "embedding" ADD COLUMN IF NOT EXISTS "content_tsv" tsvector GENERATED ALWAYS AS (to_tsvector('english', "content")) STORED;
CREATE INDEX IF NOT EXISTS "emb_content_fts_idx" ON "embedding" USING gin ("content_tsv");
-- Performance optimization: Set fillfactor for high-update tables
ALTER TABLE "embedding" SET (fillfactor = 85);
ALTER TABLE "document" SET (fillfactor = 90);
-- Add table comments for documentation
COMMENT ON TABLE "knowledge_base" IS 'Stores knowledge base configurations and settings';
COMMENT ON TABLE "document" IS 'Stores document metadata and processing status';
COMMENT ON TABLE "embedding" IS 'Stores vector embeddings optimized for text-embedding-3-small with HNSW similarity search';
COMMENT ON COLUMN "embedding"."embedding" IS 'Vector embedding using pgvector type optimized for HNSW similarity search';
COMMENT ON COLUMN "embedding"."metadata" IS 'JSONB metadata for flexible filtering (e.g., page numbers, sections, tags)';
COMMENT ON COLUMN "embedding"."search_rank" IS 'Boost factor for search results, higher values appear first';
@@ -0,0 +1,8 @@
-- Add enabled field to embedding table
ALTER TABLE "embedding" ADD COLUMN IF NOT EXISTS "enabled" boolean DEFAULT true NOT NULL;
-- Composite index for knowledge base + enabled chunks (for search optimization)
CREATE INDEX IF NOT EXISTS "emb_kb_enabled_idx" ON "embedding" USING btree ("knowledge_base_id", "enabled");
-- Composite index for document + enabled chunks (for document chunk listings)
CREATE INDEX IF NOT EXISTS "emb_doc_enabled_idx" ON "embedding" USING btree ("document_id", "enabled");
@@ -0,0 +1 @@
ALTER TABLE "settings" ADD COLUMN "email_preferences" json DEFAULT '{}' NOT NULL;
@@ -0,0 +1,21 @@
CREATE TABLE "workflow_folder" (
"id" text PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"user_id" text NOT NULL,
"workspace_id" text NOT NULL,
"parent_id" text,
"color" text DEFAULT '#6B7280',
"is_expanded" boolean DEFAULT true NOT NULL,
"sort_order" integer DEFAULT 0 NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "workflow" ADD COLUMN "folder_id" text;--> statement-breakpoint
ALTER TABLE "workflow_folder" ADD CONSTRAINT "workflow_folder_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_folder" ADD CONSTRAINT "workflow_folder_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_folder" ADD CONSTRAINT "workflow_folder_parent_id_workflow_folder_id_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."workflow_folder"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "workflow_folder_workspace_parent_idx" ON "workflow_folder" USING btree ("workspace_id","parent_id");--> statement-breakpoint
CREATE INDEX "workflow_folder_user_idx" ON "workflow_folder" USING btree ("user_id");--> statement-breakpoint
CREATE INDEX "workflow_folder_parent_sort_idx" ON "workflow_folder" USING btree ("parent_id","sort_order");--> statement-breakpoint
ALTER TABLE "workflow" ADD CONSTRAINT "workflow_folder_id_workflow_folder_id_fk" FOREIGN KEY ("folder_id") REFERENCES "public"."workflow_folder"("id") ON DELETE set null ON UPDATE no action;
@@ -0,0 +1,58 @@
CREATE TABLE "workflow_blocks" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text NOT NULL,
"type" text NOT NULL,
"name" text NOT NULL,
"position_x" integer NOT NULL,
"position_y" integer NOT NULL,
"enabled" boolean DEFAULT true NOT NULL,
"horizontal_handles" boolean DEFAULT true NOT NULL,
"is_wide" boolean DEFAULT false NOT NULL,
"height" integer DEFAULT 0 NOT NULL,
"sub_blocks" jsonb DEFAULT '{}' NOT NULL,
"outputs" jsonb DEFAULT '{}' NOT NULL,
"data" jsonb DEFAULT '{}',
"parent_id" text,
"extent" text,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "workflow_edges" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text NOT NULL,
"source_block_id" text NOT NULL,
"target_block_id" text NOT NULL,
"source_handle" text,
"target_handle" text,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "workflow_subflows" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text NOT NULL,
"type" text NOT NULL,
"config" jsonb DEFAULT '{}' NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "workflow_blocks" ADD CONSTRAINT "workflow_blocks_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_blocks" ADD CONSTRAINT "workflow_blocks_parent_id_workflow_blocks_id_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."workflow_blocks"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_edges" ADD CONSTRAINT "workflow_edges_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_edges" ADD CONSTRAINT "workflow_edges_source_block_id_workflow_blocks_id_fk" FOREIGN KEY ("source_block_id") REFERENCES "public"."workflow_blocks"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_edges" ADD CONSTRAINT "workflow_edges_target_block_id_workflow_blocks_id_fk" FOREIGN KEY ("target_block_id") REFERENCES "public"."workflow_blocks"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_subflows" ADD CONSTRAINT "workflow_subflows_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "workflow_blocks_workflow_id_idx" ON "workflow_blocks" USING btree ("workflow_id");--> statement-breakpoint
CREATE INDEX "workflow_blocks_parent_id_idx" ON "workflow_blocks" USING btree ("parent_id");--> statement-breakpoint
CREATE INDEX "workflow_blocks_workflow_parent_idx" ON "workflow_blocks" USING btree ("workflow_id","parent_id");--> statement-breakpoint
CREATE INDEX "workflow_blocks_workflow_type_idx" ON "workflow_blocks" USING btree ("workflow_id","type");--> statement-breakpoint
CREATE INDEX "workflow_edges_workflow_id_idx" ON "workflow_edges" USING btree ("workflow_id");--> statement-breakpoint
CREATE INDEX "workflow_edges_source_block_idx" ON "workflow_edges" USING btree ("source_block_id");--> statement-breakpoint
CREATE INDEX "workflow_edges_target_block_idx" ON "workflow_edges" USING btree ("target_block_id");--> statement-breakpoint
CREATE INDEX "workflow_edges_workflow_source_idx" ON "workflow_edges" USING btree ("workflow_id","source_block_id");--> statement-breakpoint
CREATE INDEX "workflow_edges_workflow_target_idx" ON "workflow_edges" USING btree ("workflow_id","target_block_id");--> statement-breakpoint
CREATE INDEX "workflow_edges_source_block_fk_idx" ON "workflow_edges" USING btree ("source_block_id");--> statement-breakpoint
CREATE INDEX "workflow_edges_target_block_fk_idx" ON "workflow_edges" USING btree ("target_block_id");--> statement-breakpoint
CREATE INDEX "workflow_subflows_workflow_id_idx" ON "workflow_subflows" USING btree ("workflow_id");--> statement-breakpoint
CREATE INDEX "workflow_subflows_workflow_type_idx" ON "workflow_subflows" USING btree ("workflow_id","type");
@@ -0,0 +1,4 @@
ALTER TABLE "workflow_blocks" ALTER COLUMN "position_x" SET DATA TYPE numeric;--> statement-breakpoint
ALTER TABLE "workflow_blocks" ALTER COLUMN "position_y" SET DATA TYPE numeric;--> statement-breakpoint
ALTER TABLE "workflow_blocks" ALTER COLUMN "height" SET DATA TYPE numeric;--> statement-breakpoint
ALTER TABLE "workflow_blocks" ALTER COLUMN "height" SET DEFAULT '0';
@@ -0,0 +1,10 @@
DROP INDEX "doc_file_hash_idx";--> statement-breakpoint
DROP INDEX "emb_chunk_hash_idx";--> statement-breakpoint
DROP INDEX "emb_kb_access_idx";--> statement-breakpoint
DROP INDEX "emb_kb_rank_idx";--> statement-breakpoint
ALTER TABLE "document" DROP COLUMN "file_hash";--> statement-breakpoint
ALTER TABLE "embedding" DROP COLUMN "overlap_tokens";--> statement-breakpoint
ALTER TABLE "embedding" DROP COLUMN "search_rank";--> statement-breakpoint
ALTER TABLE "embedding" DROP COLUMN "access_count";--> statement-breakpoint
ALTER TABLE "embedding" DROP COLUMN "last_accessed_at";--> statement-breakpoint
ALTER TABLE "embedding" DROP COLUMN "quality_score";
@@ -0,0 +1,19 @@
CREATE TYPE "public"."permission_type" AS ENUM('admin', 'write', 'read');--> statement-breakpoint
CREATE TABLE "permissions" (
"id" text PRIMARY KEY NOT NULL,
"user_id" text NOT NULL,
"entity_type" text NOT NULL,
"entity_id" text NOT NULL,
"permission_type" "permission_type" NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "workspace_invitation" ADD COLUMN "permissions" "permission_type" DEFAULT 'admin' NOT NULL;--> statement-breakpoint
ALTER TABLE "permissions" ADD CONSTRAINT "permissions_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "permissions_user_id_idx" ON "permissions" USING btree ("user_id");--> statement-breakpoint
CREATE INDEX "permissions_entity_idx" ON "permissions" USING btree ("entity_type","entity_id");--> statement-breakpoint
CREATE INDEX "permissions_user_entity_type_idx" ON "permissions" USING btree ("user_id","entity_type");--> statement-breakpoint
CREATE INDEX "permissions_user_entity_permission_idx" ON "permissions" USING btree ("user_id","entity_type","permission_type");--> statement-breakpoint
CREATE INDEX "permissions_user_entity_idx" ON "permissions" USING btree ("user_id","entity_type","entity_id");--> statement-breakpoint
CREATE UNIQUE INDEX "permissions_unique_constraint" ON "permissions" USING btree ("user_id","entity_type","entity_id");
@@ -0,0 +1 @@
ALTER TABLE "workflow_blocks" ADD COLUMN "advanced_mode" boolean DEFAULT false NOT NULL;
@@ -0,0 +1,9 @@
ALTER TABLE "user_stats" ADD COLUMN "current_usage_limit" numeric DEFAULT '5' NOT NULL;--> statement-breakpoint
ALTER TABLE "user_stats" ADD COLUMN "usage_limit_set_by" text;--> statement-breakpoint
ALTER TABLE "user_stats" ADD COLUMN "usage_limit_updated_at" timestamp DEFAULT now();--> statement-breakpoint
ALTER TABLE "user_stats" ADD COLUMN "current_period_cost" numeric DEFAULT '0' NOT NULL;--> statement-breakpoint
ALTER TABLE "user_stats" ADD COLUMN "billing_period_start" timestamp DEFAULT now();--> statement-breakpoint
ALTER TABLE "user_stats" ADD COLUMN "billing_period_end" timestamp;--> statement-breakpoint
ALTER TABLE "user_stats" ADD COLUMN "last_period_cost" numeric DEFAULT '0';--> statement-breakpoint
CREATE INDEX "subscription_reference_status_idx" ON "subscription" USING btree ("reference_id","status");--> statement-breakpoint
ALTER TABLE "subscription" ADD CONSTRAINT "check_enterprise_metadata" CHECK (plan != 'enterprise' OR (metadata IS NOT NULL AND (metadata->>'perSeatAllowance' IS NOT NULL OR metadata->>'totalAllowance' IS NOT NULL)));
@@ -0,0 +1,82 @@
CREATE TABLE "workflow_execution_blocks" (
"id" text PRIMARY KEY NOT NULL,
"execution_id" text NOT NULL,
"workflow_id" text NOT NULL,
"block_id" text NOT NULL,
"block_name" text,
"block_type" text NOT NULL,
"started_at" timestamp NOT NULL,
"ended_at" timestamp,
"duration_ms" integer,
"status" text NOT NULL,
"error_message" text,
"error_stack_trace" text,
"input_data" jsonb,
"output_data" jsonb,
"cost_input" numeric(10, 6),
"cost_output" numeric(10, 6),
"cost_total" numeric(10, 6),
"tokens_prompt" integer,
"tokens_completion" integer,
"tokens_total" integer,
"model_used" text,
"metadata" jsonb,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "workflow_execution_logs" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text NOT NULL,
"execution_id" text NOT NULL,
"state_snapshot_id" text NOT NULL,
"level" text NOT NULL,
"message" text NOT NULL,
"trigger" text NOT NULL,
"started_at" timestamp NOT NULL,
"ended_at" timestamp,
"total_duration_ms" integer,
"block_count" integer DEFAULT 0 NOT NULL,
"success_count" integer DEFAULT 0 NOT NULL,
"error_count" integer DEFAULT 0 NOT NULL,
"skipped_count" integer DEFAULT 0 NOT NULL,
"total_cost" numeric(10, 6),
"total_input_cost" numeric(10, 6),
"total_output_cost" numeric(10, 6),
"total_tokens" integer,
"metadata" jsonb DEFAULT '{}' NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "workflow_execution_snapshots" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text NOT NULL,
"state_hash" text NOT NULL,
"state_data" jsonb NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "workflow_execution_blocks" ADD CONSTRAINT "workflow_execution_blocks_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_execution_logs" ADD CONSTRAINT "workflow_execution_logs_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_execution_logs" ADD CONSTRAINT "workflow_execution_logs_state_snapshot_id_workflow_execution_snapshots_id_fk" FOREIGN KEY ("state_snapshot_id") REFERENCES "public"."workflow_execution_snapshots"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_execution_snapshots" ADD CONSTRAINT "workflow_execution_snapshots_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "execution_blocks_execution_id_idx" ON "workflow_execution_blocks" USING btree ("execution_id");--> statement-breakpoint
CREATE INDEX "execution_blocks_workflow_id_idx" ON "workflow_execution_blocks" USING btree ("workflow_id");--> statement-breakpoint
CREATE INDEX "execution_blocks_block_id_idx" ON "workflow_execution_blocks" USING btree ("block_id");--> statement-breakpoint
CREATE INDEX "execution_blocks_status_idx" ON "workflow_execution_blocks" USING btree ("status");--> statement-breakpoint
CREATE INDEX "execution_blocks_duration_idx" ON "workflow_execution_blocks" USING btree ("duration_ms");--> statement-breakpoint
CREATE INDEX "execution_blocks_cost_idx" ON "workflow_execution_blocks" USING btree ("cost_total");--> statement-breakpoint
CREATE INDEX "execution_blocks_workflow_execution_idx" ON "workflow_execution_blocks" USING btree ("workflow_id","execution_id");--> statement-breakpoint
CREATE INDEX "execution_blocks_execution_status_idx" ON "workflow_execution_blocks" USING btree ("execution_id","status");--> statement-breakpoint
CREATE INDEX "execution_blocks_started_at_idx" ON "workflow_execution_blocks" USING btree ("started_at");--> statement-breakpoint
CREATE INDEX "workflow_execution_logs_workflow_id_idx" ON "workflow_execution_logs" USING btree ("workflow_id");--> statement-breakpoint
CREATE INDEX "workflow_execution_logs_execution_id_idx" ON "workflow_execution_logs" USING btree ("execution_id");--> statement-breakpoint
CREATE INDEX "workflow_execution_logs_trigger_idx" ON "workflow_execution_logs" USING btree ("trigger");--> statement-breakpoint
CREATE INDEX "workflow_execution_logs_level_idx" ON "workflow_execution_logs" USING btree ("level");--> statement-breakpoint
CREATE INDEX "workflow_execution_logs_started_at_idx" ON "workflow_execution_logs" USING btree ("started_at");--> statement-breakpoint
CREATE INDEX "workflow_execution_logs_cost_idx" ON "workflow_execution_logs" USING btree ("total_cost");--> statement-breakpoint
CREATE INDEX "workflow_execution_logs_duration_idx" ON "workflow_execution_logs" USING btree ("total_duration_ms");--> statement-breakpoint
CREATE UNIQUE INDEX "workflow_execution_logs_execution_id_unique" ON "workflow_execution_logs" USING btree ("execution_id");--> statement-breakpoint
CREATE INDEX "workflow_snapshots_workflow_id_idx" ON "workflow_execution_snapshots" USING btree ("workflow_id");--> statement-breakpoint
CREATE INDEX "workflow_snapshots_hash_idx" ON "workflow_execution_snapshots" USING btree ("state_hash");--> statement-breakpoint
CREATE UNIQUE INDEX "workflow_snapshots_workflow_hash_idx" ON "workflow_execution_snapshots" USING btree ("workflow_id","state_hash");--> statement-breakpoint
CREATE INDEX "workflow_snapshots_created_at_idx" ON "workflow_execution_snapshots" USING btree ("created_at");
@@ -0,0 +1 @@
ALTER TABLE "settings" ADD COLUMN "auto_pan" boolean DEFAULT true NOT NULL;
@@ -0,0 +1,37 @@
CREATE TABLE "docs_embeddings" (
"chunk_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"chunk_text" text NOT NULL,
"source_document" text NOT NULL,
"source_link" text NOT NULL,
"header_text" text NOT NULL,
"header_level" integer NOT NULL,
"token_count" integer NOT NULL,
"embedding" vector(1536) NOT NULL,
"embedding_model" text DEFAULT 'text-embedding-3-small' NOT NULL,
"metadata" jsonb DEFAULT '{}' NOT NULL,
"chunk_text_tsv" "tsvector" GENERATED ALWAYS AS (to_tsvector('english', "docs_embeddings"."chunk_text")) STORED,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL,
CONSTRAINT "docs_embedding_not_null_check" CHECK ("embedding" IS NOT NULL),
CONSTRAINT "docs_header_level_check" CHECK ("header_level" >= 1 AND "header_level" <= 6)
);
--> statement-breakpoint
CREATE INDEX "docs_emb_source_document_idx" ON "docs_embeddings" USING btree ("source_document");--> statement-breakpoint
CREATE INDEX "docs_emb_header_level_idx" ON "docs_embeddings" USING btree ("header_level");--> statement-breakpoint
CREATE INDEX "docs_emb_source_header_idx" ON "docs_embeddings" USING btree ("source_document","header_level");--> statement-breakpoint
CREATE INDEX "docs_emb_model_idx" ON "docs_embeddings" USING btree ("embedding_model");--> statement-breakpoint
CREATE INDEX "docs_emb_created_at_idx" ON "docs_embeddings" USING btree ("created_at");--> statement-breakpoint
CREATE INDEX "docs_embedding_vector_hnsw_idx" ON "docs_embeddings" USING hnsw ("embedding" vector_cosine_ops) WITH (m=16,ef_construction=64);--> statement-breakpoint
CREATE INDEX "docs_emb_metadata_gin_idx" ON "docs_embeddings" USING gin ("metadata");--> statement-breakpoint
CREATE INDEX "docs_emb_chunk_text_fts_idx" ON "docs_embeddings" USING gin ("chunk_text_tsv");--> statement-breakpoint
CREATE OR REPLACE FUNCTION trigger_set_timestamp()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;--> statement-breakpoint
CREATE TRIGGER set_updated_at
BEFORE UPDATE ON docs_embeddings
FOR EACH ROW
EXECUTE FUNCTION trigger_set_timestamp();
@@ -0,0 +1,18 @@
CREATE TABLE "copilot_chats" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"user_id" text NOT NULL,
"workflow_id" text NOT NULL,
"title" text,
"messages" jsonb DEFAULT '[]' NOT NULL,
"model" text DEFAULT 'claude-3-7-sonnet-latest' NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "copilot_chats" ADD CONSTRAINT "copilot_chats_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "copilot_chats" ADD CONSTRAINT "copilot_chats_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "copilot_chats_user_id_idx" ON "copilot_chats" USING btree ("user_id");--> statement-breakpoint
CREATE INDEX "copilot_chats_workflow_id_idx" ON "copilot_chats" USING btree ("workflow_id");--> statement-breakpoint
CREATE INDEX "copilot_chats_user_workflow_idx" ON "copilot_chats" USING btree ("user_id","workflow_id");--> statement-breakpoint
CREATE INDEX "copilot_chats_created_at_idx" ON "copilot_chats" USING btree ("created_at");--> statement-breakpoint
CREATE INDEX "copilot_chats_updated_at_idx" ON "copilot_chats" USING btree ("updated_at");
@@ -0,0 +1,30 @@
DROP INDEX "emb_metadata_gin_idx";--> statement-breakpoint
ALTER TABLE "document" ADD COLUMN "tag1" text;--> statement-breakpoint
ALTER TABLE "document" ADD COLUMN "tag2" text;--> statement-breakpoint
ALTER TABLE "document" ADD COLUMN "tag3" text;--> statement-breakpoint
ALTER TABLE "document" ADD COLUMN "tag4" text;--> statement-breakpoint
ALTER TABLE "document" ADD COLUMN "tag5" text;--> statement-breakpoint
ALTER TABLE "document" ADD COLUMN "tag6" text;--> statement-breakpoint
ALTER TABLE "document" ADD COLUMN "tag7" text;--> statement-breakpoint
ALTER TABLE "embedding" ADD COLUMN "tag1" text;--> statement-breakpoint
ALTER TABLE "embedding" ADD COLUMN "tag2" text;--> statement-breakpoint
ALTER TABLE "embedding" ADD COLUMN "tag3" text;--> statement-breakpoint
ALTER TABLE "embedding" ADD COLUMN "tag4" text;--> statement-breakpoint
ALTER TABLE "embedding" ADD COLUMN "tag5" text;--> statement-breakpoint
ALTER TABLE "embedding" ADD COLUMN "tag6" text;--> statement-breakpoint
ALTER TABLE "embedding" ADD COLUMN "tag7" text;--> statement-breakpoint
CREATE INDEX "doc_tag1_idx" ON "document" USING btree ("tag1");--> statement-breakpoint
CREATE INDEX "doc_tag2_idx" ON "document" USING btree ("tag2");--> statement-breakpoint
CREATE INDEX "doc_tag3_idx" ON "document" USING btree ("tag3");--> statement-breakpoint
CREATE INDEX "doc_tag4_idx" ON "document" USING btree ("tag4");--> statement-breakpoint
CREATE INDEX "doc_tag5_idx" ON "document" USING btree ("tag5");--> statement-breakpoint
CREATE INDEX "doc_tag6_idx" ON "document" USING btree ("tag6");--> statement-breakpoint
CREATE INDEX "doc_tag7_idx" ON "document" USING btree ("tag7");--> statement-breakpoint
CREATE INDEX "emb_tag1_idx" ON "embedding" USING btree ("tag1");--> statement-breakpoint
CREATE INDEX "emb_tag2_idx" ON "embedding" USING btree ("tag2");--> statement-breakpoint
CREATE INDEX "emb_tag3_idx" ON "embedding" USING btree ("tag3");--> statement-breakpoint
CREATE INDEX "emb_tag4_idx" ON "embedding" USING btree ("tag4");--> statement-breakpoint
CREATE INDEX "emb_tag5_idx" ON "embedding" USING btree ("tag5");--> statement-breakpoint
CREATE INDEX "emb_tag6_idx" ON "embedding" USING btree ("tag6");--> statement-breakpoint
CREATE INDEX "emb_tag7_idx" ON "embedding" USING btree ("tag7");--> statement-breakpoint
ALTER TABLE "embedding" DROP COLUMN "metadata";
@@ -0,0 +1,47 @@
CREATE TABLE "template_stars" (
"id" text PRIMARY KEY NOT NULL,
"user_id" text NOT NULL,
"template_id" text NOT NULL,
"starred_at" timestamp DEFAULT now() NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "templates" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text NOT NULL,
"user_id" text NOT NULL,
"name" text NOT NULL,
"description" text,
"author" text NOT NULL,
"views" integer DEFAULT 0 NOT NULL,
"stars" integer DEFAULT 0 NOT NULL,
"color" text DEFAULT '#3972F6' NOT NULL,
"icon" text DEFAULT 'FileText' NOT NULL,
"category" text NOT NULL,
"state" jsonb NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
DROP TABLE "workspace_member" CASCADE;--> statement-breakpoint
ALTER TABLE "template_stars" ADD CONSTRAINT "template_stars_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "template_stars" ADD CONSTRAINT "template_stars_template_id_templates_id_fk" FOREIGN KEY ("template_id") REFERENCES "public"."templates"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "templates" ADD CONSTRAINT "templates_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "templates" ADD CONSTRAINT "templates_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "template_stars_user_id_idx" ON "template_stars" USING btree ("user_id");--> statement-breakpoint
CREATE INDEX "template_stars_template_id_idx" ON "template_stars" USING btree ("template_id");--> statement-breakpoint
CREATE INDEX "template_stars_user_template_idx" ON "template_stars" USING btree ("user_id","template_id");--> statement-breakpoint
CREATE INDEX "template_stars_template_user_idx" ON "template_stars" USING btree ("template_id","user_id");--> statement-breakpoint
CREATE INDEX "template_stars_starred_at_idx" ON "template_stars" USING btree ("starred_at");--> statement-breakpoint
CREATE INDEX "template_stars_template_starred_at_idx" ON "template_stars" USING btree ("template_id","starred_at");--> statement-breakpoint
CREATE UNIQUE INDEX "template_stars_user_template_unique" ON "template_stars" USING btree ("user_id","template_id");--> statement-breakpoint
CREATE INDEX "templates_workflow_id_idx" ON "templates" USING btree ("workflow_id");--> statement-breakpoint
CREATE INDEX "templates_user_id_idx" ON "templates" USING btree ("user_id");--> statement-breakpoint
CREATE INDEX "templates_category_idx" ON "templates" USING btree ("category");--> statement-breakpoint
CREATE INDEX "templates_views_idx" ON "templates" USING btree ("views");--> statement-breakpoint
CREATE INDEX "templates_stars_idx" ON "templates" USING btree ("stars");--> statement-breakpoint
CREATE INDEX "templates_category_views_idx" ON "templates" USING btree ("category","views");--> statement-breakpoint
CREATE INDEX "templates_category_stars_idx" ON "templates" USING btree ("category","stars");--> statement-breakpoint
CREATE INDEX "templates_user_category_idx" ON "templates" USING btree ("user_id","category");--> statement-breakpoint
CREATE INDEX "templates_created_at_idx" ON "templates" USING btree ("created_at");--> statement-breakpoint
CREATE INDEX "templates_updated_at_idx" ON "templates" USING btree ("updated_at");
@@ -0,0 +1,2 @@
ALTER TABLE "settings" ADD COLUMN "console_expanded_by_default" boolean DEFAULT true NOT NULL;--> statement-breakpoint
ALTER TABLE "settings" DROP COLUMN "debug_mode";
@@ -0,0 +1,11 @@
CREATE TABLE "user_rate_limits" (
"user_id" text PRIMARY KEY NOT NULL,
"sync_api_requests" integer DEFAULT 0 NOT NULL,
"async_api_requests" integer DEFAULT 0 NOT NULL,
"window_start" timestamp DEFAULT now() NOT NULL,
"last_request_at" timestamp DEFAULT now() NOT NULL,
"is_rate_limited" boolean DEFAULT false NOT NULL,
"rate_limit_reset_at" timestamp
);
--> statement-breakpoint
ALTER TABLE "user_rate_limits" ADD CONSTRAINT "user_rate_limits_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
@@ -0,0 +1,6 @@
ALTER TABLE "workflow_schedule" DROP CONSTRAINT "workflow_schedule_workflow_id_unique";--> statement-breakpoint
ALTER TABLE "webhook" ADD COLUMN "block_id" text;--> statement-breakpoint
ALTER TABLE "workflow_schedule" ADD COLUMN "block_id" text;--> statement-breakpoint
ALTER TABLE "webhook" ADD CONSTRAINT "webhook_block_id_workflow_blocks_id_fk" FOREIGN KEY ("block_id") REFERENCES "public"."workflow_blocks"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_schedule" ADD CONSTRAINT "workflow_schedule_block_id_workflow_blocks_id_fk" FOREIGN KEY ("block_id") REFERENCES "public"."workflow_blocks"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "workflow_schedule_workflow_block_unique" ON "workflow_schedule" USING btree ("workflow_id","block_id");
@@ -0,0 +1,20 @@
CREATE TABLE "copilot_checkpoints" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"user_id" text NOT NULL,
"workflow_id" text NOT NULL,
"chat_id" uuid NOT NULL,
"yaml" text NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "copilot_checkpoints" ADD CONSTRAINT "copilot_checkpoints_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "copilot_checkpoints" ADD CONSTRAINT "copilot_checkpoints_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "copilot_checkpoints" ADD CONSTRAINT "copilot_checkpoints_chat_id_copilot_chats_id_fk" FOREIGN KEY ("chat_id") REFERENCES "public"."copilot_chats"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "copilot_checkpoints_user_id_idx" ON "copilot_checkpoints" USING btree ("user_id");--> statement-breakpoint
CREATE INDEX "copilot_checkpoints_workflow_id_idx" ON "copilot_checkpoints" USING btree ("workflow_id");--> statement-breakpoint
CREATE INDEX "copilot_checkpoints_chat_id_idx" ON "copilot_checkpoints" USING btree ("chat_id");--> statement-breakpoint
CREATE INDEX "copilot_checkpoints_user_workflow_idx" ON "copilot_checkpoints" USING btree ("user_id","workflow_id");--> statement-breakpoint
CREATE INDEX "copilot_checkpoints_workflow_chat_idx" ON "copilot_checkpoints" USING btree ("workflow_id","chat_id");--> statement-breakpoint
CREATE INDEX "copilot_checkpoints_created_at_idx" ON "copilot_checkpoints" USING btree ("created_at");--> statement-breakpoint
CREATE INDEX "copilot_checkpoints_chat_created_at_idx" ON "copilot_checkpoints" USING btree ("chat_id","created_at");
@@ -0,0 +1,5 @@
CREATE INDEX "workflow_user_id_idx" ON "workflow" USING btree ("user_id");--> statement-breakpoint
CREATE INDEX "workflow_workspace_id_idx" ON "workflow" USING btree ("workspace_id");--> statement-breakpoint
CREATE INDEX "workflow_user_workspace_idx" ON "workflow" USING btree ("user_id","workspace_id");--> statement-breakpoint
CREATE INDEX "workflow_logs_workflow_id_idx" ON "workflow_logs" USING btree ("workflow_id");--> statement-breakpoint
CREATE INDEX "workflow_logs_workflow_created_idx" ON "workflow_logs" USING btree ("workflow_id","created_at");
@@ -0,0 +1,3 @@
ALTER TABLE "knowledge_base" DROP CONSTRAINT "knowledge_base_workspace_id_workspace_id_fk";
--> statement-breakpoint
ALTER TABLE "knowledge_base" ADD CONSTRAINT "knowledge_base_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE no action ON UPDATE no action;
@@ -0,0 +1 @@
DROP TABLE "workflow_execution_blocks" CASCADE;
@@ -0,0 +1 @@
DROP TABLE "workflow_logs" CASCADE;
@@ -0,0 +1,13 @@
CREATE TABLE "knowledge_base_tag_definitions" (
"id" text PRIMARY KEY NOT NULL,
"knowledge_base_id" text NOT NULL,
"tag_slot" text NOT NULL,
"display_name" text NOT NULL,
"field_type" text DEFAULT 'text' NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "knowledge_base_tag_definitions" ADD CONSTRAINT "knowledge_base_tag_definitions_knowledge_base_id_knowledge_base_id_fk" FOREIGN KEY ("knowledge_base_id") REFERENCES "public"."knowledge_base"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "kb_tag_definitions_kb_slot_idx" ON "knowledge_base_tag_definitions" USING btree ("knowledge_base_id","tag_slot");--> statement-breakpoint
CREATE INDEX "kb_tag_definitions_kb_id_idx" ON "knowledge_base_tag_definitions" USING btree ("knowledge_base_id");
@@ -0,0 +1,3 @@
DROP INDEX "workflow_execution_logs_cost_idx";--> statement-breakpoint
DROP INDEX "workflow_execution_logs_duration_idx";--> statement-breakpoint
CREATE INDEX "workflow_execution_logs_workflow_started_at_idx" ON "workflow_execution_logs" USING btree ("workflow_id","started_at");
@@ -0,0 +1,24 @@
CREATE TABLE "workflow_checkpoints" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"user_id" text NOT NULL,
"workflow_id" text NOT NULL,
"chat_id" uuid NOT NULL,
"message_id" text,
"workflow_state" json NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
DROP TABLE "copilot_checkpoints" CASCADE;--> statement-breakpoint
ALTER TABLE "copilot_chats" ADD COLUMN "preview_yaml" text;--> statement-breakpoint
ALTER TABLE "workflow_checkpoints" ADD CONSTRAINT "workflow_checkpoints_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_checkpoints" ADD CONSTRAINT "workflow_checkpoints_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_checkpoints" ADD CONSTRAINT "workflow_checkpoints_chat_id_copilot_chats_id_fk" FOREIGN KEY ("chat_id") REFERENCES "public"."copilot_chats"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "workflow_checkpoints_user_id_idx" ON "workflow_checkpoints" USING btree ("user_id");--> statement-breakpoint
CREATE INDEX "workflow_checkpoints_workflow_id_idx" ON "workflow_checkpoints" USING btree ("workflow_id");--> statement-breakpoint
CREATE INDEX "workflow_checkpoints_chat_id_idx" ON "workflow_checkpoints" USING btree ("chat_id");--> statement-breakpoint
CREATE INDEX "workflow_checkpoints_message_id_idx" ON "workflow_checkpoints" USING btree ("message_id");--> statement-breakpoint
CREATE INDEX "workflow_checkpoints_user_workflow_idx" ON "workflow_checkpoints" USING btree ("user_id","workflow_id");--> statement-breakpoint
CREATE INDEX "workflow_checkpoints_workflow_chat_idx" ON "workflow_checkpoints" USING btree ("workflow_id","chat_id");--> statement-breakpoint
CREATE INDEX "workflow_checkpoints_created_at_idx" ON "workflow_checkpoints" USING btree ("created_at");--> statement-breakpoint
CREATE INDEX "workflow_checkpoints_chat_created_at_idx" ON "workflow_checkpoints" USING btree ("chat_id","created_at");
@@ -0,0 +1,21 @@
CREATE TABLE "copilot_feedback" (
"feedback_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"user_id" text NOT NULL,
"chat_id" uuid NOT NULL,
"user_query" text NOT NULL,
"agent_response" text NOT NULL,
"is_positive" boolean NOT NULL,
"feedback" text,
"workflow_yaml" text,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "user_stats" ALTER COLUMN "current_usage_limit" SET DEFAULT '10';--> statement-breakpoint
ALTER TABLE "copilot_feedback" ADD CONSTRAINT "copilot_feedback_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "copilot_feedback" ADD CONSTRAINT "copilot_feedback_chat_id_copilot_chats_id_fk" FOREIGN KEY ("chat_id") REFERENCES "public"."copilot_chats"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "copilot_feedback_user_id_idx" ON "copilot_feedback" USING btree ("user_id");--> statement-breakpoint
CREATE INDEX "copilot_feedback_chat_id_idx" ON "copilot_feedback" USING btree ("chat_id");--> statement-breakpoint
CREATE INDEX "copilot_feedback_user_chat_idx" ON "copilot_feedback" USING btree ("user_id","chat_id");--> statement-breakpoint
CREATE INDEX "copilot_feedback_is_positive_idx" ON "copilot_feedback" USING btree ("is_positive");--> statement-breakpoint
CREATE INDEX "copilot_feedback_created_at_idx" ON "copilot_feedback" USING btree ("created_at");
@@ -0,0 +1 @@
CREATE UNIQUE INDEX "kb_tag_definitions_kb_display_name_idx" ON "knowledge_base_tag_definitions" USING btree ("knowledge_base_id","display_name");
@@ -0,0 +1 @@
ALTER TABLE "workflow_execution_logs" ADD COLUMN "files" jsonb;
@@ -0,0 +1 @@
ALTER TABLE "workflow_blocks" ADD COLUMN "trigger_mode" boolean DEFAULT false NOT NULL;
@@ -0,0 +1 @@
ALTER TABLE "knowledge_base" ALTER COLUMN "chunking_config" SET DEFAULT '{"maxSize": 1024, "minSize": 1, "overlap": 200}';
@@ -0,0 +1 @@
ALTER TABLE "workflow" ADD COLUMN "pinned_api_key" text;
@@ -0,0 +1 @@
ALTER TABLE "copilot_chats" ADD COLUMN "conversation_id" text;
@@ -0,0 +1 @@
ALTER TABLE "settings" DROP COLUMN "telemetry_notified_user";
@@ -0,0 +1,13 @@
CREATE TABLE "copilot_api_keys" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"user_id" text NOT NULL,
"api_key_encrypted" text NOT NULL,
"api_key_lookup" text NOT NULL
);
--> statement-breakpoint
ALTER TABLE "user_stats" ADD COLUMN "total_copilot_cost" numeric DEFAULT '0' NOT NULL;--> statement-breakpoint
ALTER TABLE "user_stats" ADD COLUMN "total_copilot_tokens" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
ALTER TABLE "user_stats" ADD COLUMN "total_copilot_calls" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
ALTER TABLE "copilot_api_keys" ADD CONSTRAINT "copilot_api_keys_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "copilot_api_keys_api_key_encrypted_hash_idx" ON "copilot_api_keys" USING hash ("api_key_encrypted");--> statement-breakpoint
CREATE INDEX "copilot_api_keys_lookup_hash_idx" ON "copilot_api_keys" USING hash ("api_key_lookup");
@@ -0,0 +1 @@
ALTER TABLE "workflow" DROP COLUMN "state";
+167
View File
@@ -0,0 +1,167 @@
-- One-shot data migration to create/populate execution_data & cost, then drop legacy columns
-- Safe on reruns and across differing prior schemas
-- Note: Depending on runner timeouts, might have to be run manually
-- 1) Ensure execution_data exists (prefer rename if only metadata exists)
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'workflow_execution_logs' AND column_name = 'metadata'
) AND NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'workflow_execution_logs' AND column_name = 'execution_data'
) THEN
EXECUTE 'ALTER TABLE workflow_execution_logs RENAME COLUMN metadata TO execution_data';
END IF;
END $$;--> statement-breakpoint
ALTER TABLE "workflow_execution_logs"
ADD COLUMN IF NOT EXISTS "execution_data" jsonb NOT NULL DEFAULT '{}'::jsonb,
ADD COLUMN IF NOT EXISTS "cost" jsonb;--> statement-breakpoint
-- Process the backfill in batches to avoid large temporary files on big datasets
DO $$
DECLARE
v_batch_size integer := 500; -- keep batches small to avoid timeouts/spills
v_rows_updated integer := 0;
v_rows_selected integer := 0;
v_last_id text := '';
v_last_created_at timestamp := '1970-01-01 00:00:00';
BEGIN
-- modest per-statement timeout; adjust based on observed per-batch runtime
PERFORM set_config('statement_timeout', '180s', true);
LOOP
CREATE TEMP TABLE IF NOT EXISTS _tmp_candidate_ids(id text, created_at timestamp) ON COMMIT DROP;
TRUNCATE _tmp_candidate_ids;
INSERT INTO _tmp_candidate_ids(id, created_at)
SELECT id, created_at
FROM workflow_execution_logs
WHERE (created_at, id) > (v_last_created_at, v_last_id) AND cost IS NULL
ORDER BY created_at, id
LIMIT v_batch_size;
SELECT COUNT(*) INTO v_rows_selected FROM _tmp_candidate_ids;
EXIT WHEN v_rows_selected = 0;
SELECT created_at, id
INTO v_last_created_at, v_last_id
FROM _tmp_candidate_ids
ORDER BY created_at DESC, id DESC
LIMIT 1;
WITH RECURSIVE
spans AS (
SELECT l.id, s.span
FROM workflow_execution_logs l
JOIN _tmp_candidate_ids c ON c.id = l.id
LEFT JOIN LATERAL jsonb_array_elements(
COALESCE(
CASE
WHEN jsonb_typeof(l.execution_data->'traceSpans') = 'array' THEN l.execution_data->'traceSpans'
ELSE '[]'::jsonb
END
)
) s(span) ON true
UNION ALL
SELECT spans.id, c.span
FROM spans
JOIN LATERAL jsonb_array_elements(COALESCE(spans.span->'children','[]'::jsonb)) c(span) ON true
),
agg AS (
SELECT id,
SUM(COALESCE((span->'cost'->>'input')::numeric,0)) AS agg_input,
SUM(COALESCE((span->'cost'->>'output')::numeric,0)) AS agg_output,
SUM(COALESCE((span->'cost'->>'total')::numeric,0)) AS agg_total,
SUM(COALESCE((span->'cost'->'tokens'->>'prompt')::numeric, COALESCE((span->'tokens'->>'prompt')::numeric,0))) AS agg_tokens_prompt,
SUM(COALESCE((span->'cost'->'tokens'->>'completion')::numeric, COALESCE((span->'tokens'->>'completion')::numeric,0))) AS agg_tokens_completion,
SUM(COALESCE((span->'cost'->'tokens'->>'total')::numeric, COALESCE((span->'tokens'->>'total')::numeric,0))) AS agg_tokens_total
FROM spans
GROUP BY id
),
model_rows AS (
SELECT id,
(span->'cost'->>'model') AS model,
COALESCE((span->'cost'->>'input')::numeric,0) AS input,
COALESCE((span->'cost'->>'output')::numeric,0) AS output,
COALESCE((span->'cost'->>'total')::numeric,0) AS total,
COALESCE((span->'cost'->'tokens'->>'prompt')::numeric,0) AS tokens_prompt,
COALESCE((span->'cost'->'tokens'->>'completion')::numeric,0) AS tokens_completion,
COALESCE((span->'cost'->'tokens'->>'total')::numeric,0) AS tokens_total
FROM spans
WHERE span ? 'cost' AND (span->'cost'->>'model') IS NOT NULL
),
model_sums AS (
SELECT id,
model,
SUM(input) AS input,
SUM(output) AS output,
SUM(total) AS total,
SUM(tokens_prompt) AS tokens_prompt,
SUM(tokens_completion) AS tokens_completion,
SUM(tokens_total) AS tokens_total
FROM model_rows
GROUP BY id, model
),
models AS (
SELECT id,
jsonb_object_agg(model, jsonb_build_object(
'input', input,
'output', output,
'total', total,
'tokens', jsonb_build_object(
'prompt', tokens_prompt,
'completion', tokens_completion,
'total', tokens_total
)
)) AS models
FROM model_sums
GROUP BY id
),
tb AS (
SELECT l.id,
NULLIF((l.execution_data->'tokenBreakdown'->>'prompt')::numeric, 0) AS prompt,
NULLIF((l.execution_data->'tokenBreakdown'->>'completion')::numeric, 0) AS completion
FROM workflow_execution_logs l
JOIN _tmp_candidate_ids c ON c.id = l.id
)
UPDATE workflow_execution_logs AS l
SET cost = jsonb_strip_nulls(
jsonb_build_object(
'total', COALESCE((to_jsonb(l)->>'total_cost')::numeric, NULLIF(agg.agg_total,0)),
'input', COALESCE((to_jsonb(l)->>'total_input_cost')::numeric, NULLIF(agg.agg_input,0)),
'output', COALESCE((to_jsonb(l)->>'total_output_cost')::numeric, NULLIF(agg.agg_output,0)),
'tokens', CASE
WHEN (to_jsonb(l) ? 'total_tokens') OR tb.prompt IS NOT NULL OR tb.completion IS NOT NULL OR NULLIF(agg.agg_tokens_total,0) IS NOT NULL THEN
jsonb_strip_nulls(
jsonb_build_object(
'total', COALESCE((to_jsonb(l)->>'total_tokens')::numeric, NULLIF(agg.agg_tokens_total,0)),
'prompt', COALESCE(tb.prompt, NULLIF(agg.agg_tokens_prompt,0)),
'completion', COALESCE(tb.completion, NULLIF(agg.agg_tokens_completion,0))
)
)
ELSE NULL
END,
'models', models.models
)
)
FROM agg
LEFT JOIN models ON models.id = agg.id
LEFT JOIN tb ON tb.id = agg.id
WHERE l.id = agg.id;
GET DIAGNOSTICS v_rows_updated = ROW_COUNT;
-- continue advancing by id until no more rows are selected
END LOOP;
END $$;--> statement-breakpoint
-- 3) Drop legacy columns now that backfill is complete
ALTER TABLE "workflow_execution_logs"
DROP COLUMN IF EXISTS "message",
DROP COLUMN IF EXISTS "block_count",
DROP COLUMN IF EXISTS "success_count",
DROP COLUMN IF EXISTS "error_count",
DROP COLUMN IF EXISTS "skipped_count",
DROP COLUMN IF EXISTS "total_cost",
DROP COLUMN IF EXISTS "total_input_cost",
DROP COLUMN IF EXISTS "total_output_cost",
DROP COLUMN IF EXISTS "total_tokens",
DROP COLUMN IF EXISTS "metadata";
@@ -0,0 +1 @@
ALTER TABLE "templates" ALTER COLUMN "workflow_id" DROP NOT NULL;
@@ -0,0 +1 @@
DROP TABLE "copilot_api_keys" CASCADE;
@@ -0,0 +1,8 @@
ALTER TABLE "subscription" DROP CONSTRAINT IF EXISTS "check_enterprise_metadata";--> statement-breakpoint
ALTER TABLE "organization" ADD COLUMN IF NOT EXISTS "org_usage_limit" numeric;--> statement-breakpoint
ALTER TABLE "user_stats" ALTER COLUMN "current_usage_limit" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "user_stats" ADD COLUMN IF NOT EXISTS "billing_blocked" boolean DEFAULT false;--> statement-breakpoint
ALTER TABLE "user_stats" DROP COLUMN IF EXISTS "usage_limit_set_by";--> statement-breakpoint
ALTER TABLE "user_stats" DROP COLUMN IF EXISTS "billing_period_start";--> statement-breakpoint
ALTER TABLE "user_stats" DROP COLUMN IF EXISTS "billing_period_end";--> statement-breakpoint
ALTER TABLE "subscription" ADD CONSTRAINT "check_enterprise_metadata" CHECK (plan != 'enterprise' OR metadata IS NOT NULL);
@@ -0,0 +1,10 @@
CREATE TABLE "workspace_environment" (
"id" text PRIMARY KEY NOT NULL,
"workspace_id" text NOT NULL,
"variables" json DEFAULT '{}' NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "workspace_environment" ADD CONSTRAINT "workspace_environment_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "workspace_environment_workspace_unique" ON "workspace_environment" USING btree ("workspace_id");
@@ -0,0 +1 @@
ALTER TABLE "workspace_invitation" ADD COLUMN "org_invitation_id" text;
@@ -0,0 +1,8 @@
CREATE INDEX "account_user_id_idx" ON "account" USING btree ("user_id");--> statement-breakpoint
CREATE INDEX "invitation_email_idx" ON "invitation" USING btree ("email");--> statement-breakpoint
CREATE INDEX "invitation_organization_id_idx" ON "invitation" USING btree ("organization_id");--> statement-breakpoint
CREATE INDEX "member_user_id_idx" ON "member" USING btree ("user_id");--> statement-breakpoint
CREATE INDEX "member_organization_id_idx" ON "member" USING btree ("organization_id");--> statement-breakpoint
CREATE INDEX "session_user_id_idx" ON "session" USING btree ("user_id");--> statement-breakpoint
CREATE INDEX "session_token_idx" ON "session" USING btree ("token");--> statement-breakpoint
CREATE INDEX "verification_identifier_idx" ON "verification" USING btree ("identifier");
@@ -0,0 +1,3 @@
CREATE TYPE "public"."workspace_invitation_status" AS ENUM('pending', 'accepted', 'rejected', 'cancelled');--> statement-breakpoint
ALTER TABLE "workspace_invitation" ALTER COLUMN "status" SET DEFAULT 'pending'::"public"."workspace_invitation_status";--> statement-breakpoint
ALTER TABLE "workspace_invitation" ALTER COLUMN "status" SET DATA TYPE "public"."workspace_invitation_status" USING "status"::"public"."workspace_invitation_status";
@@ -0,0 +1,2 @@
ALTER TABLE "user_rate_limits" RENAME COLUMN "user_id" TO "reference_id";--> statement-breakpoint
ALTER TABLE "user_rate_limits" DROP CONSTRAINT "user_rate_limits_user_id_user_id_fk";
@@ -0,0 +1,2 @@
ALTER TABLE "settings" ADD COLUMN "billing_usage_notifications_enabled" boolean DEFAULT true NOT NULL;--> statement-breakpoint
ALTER TABLE "settings" DROP COLUMN "general";
@@ -0,0 +1,43 @@
CREATE TYPE "public"."webhook_delivery_status" AS ENUM('pending', 'in_progress', 'success', 'failed');--> statement-breakpoint
CREATE TABLE "workflow_log_webhook" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text NOT NULL,
"url" text NOT NULL,
"secret" text,
"include_final_output" boolean DEFAULT false NOT NULL,
"include_trace_spans" boolean DEFAULT false NOT NULL,
"include_rate_limits" boolean DEFAULT false NOT NULL,
"include_usage_data" boolean DEFAULT false NOT NULL,
"level_filter" text[] DEFAULT ARRAY['info', 'error']::text[] NOT NULL,
"trigger_filter" text[] DEFAULT ARRAY['api', 'webhook', 'schedule', 'manual', 'chat']::text[] NOT NULL,
"active" boolean DEFAULT true NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "workflow_log_webhook_delivery" (
"id" text PRIMARY KEY NOT NULL,
"subscription_id" text NOT NULL,
"workflow_id" text NOT NULL,
"execution_id" text NOT NULL,
"status" "webhook_delivery_status" DEFAULT 'pending' NOT NULL,
"attempts" integer DEFAULT 0 NOT NULL,
"last_attempt_at" timestamp,
"next_attempt_at" timestamp,
"response_status" integer,
"response_body" text,
"error_message" text,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "user_rate_limits" ADD COLUMN "api_endpoint_requests" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
ALTER TABLE "workflow_log_webhook" ADD CONSTRAINT "workflow_log_webhook_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_log_webhook_delivery" ADD CONSTRAINT "workflow_log_webhook_delivery_subscription_id_workflow_log_webhook_id_fk" FOREIGN KEY ("subscription_id") REFERENCES "public"."workflow_log_webhook"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow_log_webhook_delivery" ADD CONSTRAINT "workflow_log_webhook_delivery_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "workflow_log_webhook_workflow_id_idx" ON "workflow_log_webhook" USING btree ("workflow_id");--> statement-breakpoint
CREATE INDEX "workflow_log_webhook_active_idx" ON "workflow_log_webhook" USING btree ("active");--> statement-breakpoint
CREATE INDEX "workflow_log_webhook_delivery_subscription_id_idx" ON "workflow_log_webhook_delivery" USING btree ("subscription_id");--> statement-breakpoint
CREATE INDEX "workflow_log_webhook_delivery_execution_id_idx" ON "workflow_log_webhook_delivery" USING btree ("execution_id");--> statement-breakpoint
CREATE INDEX "workflow_log_webhook_delivery_status_idx" ON "workflow_log_webhook_delivery" USING btree ("status");--> statement-breakpoint
CREATE INDEX "workflow_log_webhook_delivery_next_attempt_idx" ON "workflow_log_webhook_delivery" USING btree ("next_attempt_at");
@@ -0,0 +1,28 @@
CREATE TABLE "mcp_servers" (
"id" text PRIMARY KEY NOT NULL,
"workspace_id" text NOT NULL,
"created_by" text,
"name" text NOT NULL,
"description" text,
"transport" text NOT NULL,
"url" text,
"headers" json DEFAULT '{}',
"timeout" integer DEFAULT 30000,
"retries" integer DEFAULT 3,
"enabled" boolean DEFAULT true NOT NULL,
"last_connected" timestamp,
"connection_status" text DEFAULT 'disconnected',
"last_error" text,
"tool_count" integer DEFAULT 0,
"last_tools_refresh" timestamp,
"total_requests" integer DEFAULT 0,
"last_used" timestamp,
"deleted_at" timestamp,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "mcp_servers" ADD CONSTRAINT "mcp_servers_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "mcp_servers" ADD CONSTRAINT "mcp_servers_created_by_user_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "mcp_servers_workspace_enabled_idx" ON "mcp_servers" USING btree ("workspace_id","enabled");--> statement-breakpoint
CREATE INDEX "mcp_servers_workspace_deleted_idx" ON "mcp_servers" USING btree ("workspace_id","deleted_at");
@@ -0,0 +1,15 @@
CREATE TABLE "workflow_deployment_version" (
"id" text PRIMARY KEY NOT NULL,
"workflow_id" text NOT NULL,
"version" integer NOT NULL,
"state" json NOT NULL,
"is_active" boolean DEFAULT false NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"created_by" text
);
--> statement-breakpoint
ALTER TABLE "workflow_deployment_version" ADD CONSTRAINT "workflow_deployment_version_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "workflow_deployment_version_workflow_id_idx" ON "workflow_deployment_version" USING btree ("workflow_id");--> statement-breakpoint
CREATE UNIQUE INDEX "workflow_deployment_version_workflow_version_unique" ON "workflow_deployment_version" USING btree ("workflow_id","version");--> statement-breakpoint
CREATE INDEX "workflow_deployment_version_workflow_active_idx" ON "workflow_deployment_version" USING btree ("workflow_id","is_active");--> statement-breakpoint
CREATE INDEX "workflow_deployment_version_created_at_idx" ON "workflow_deployment_version" USING btree ("created_at");
@@ -0,0 +1,25 @@
-- Step 1: Add new columns to api_key table
ALTER TABLE "api_key" ADD COLUMN "workspace_id" text;--> statement-breakpoint
ALTER TABLE "api_key" ADD COLUMN "created_by" text;--> statement-breakpoint
ALTER TABLE "api_key" ADD COLUMN "type" text DEFAULT 'personal' NOT NULL;--> statement-breakpoint
-- Step 2: Add pinned_api_key_id column to workflow table
ALTER TABLE "workflow" ADD COLUMN "pinned_api_key_id" text;--> statement-breakpoint
-- Step 3: Migrate pinned API key references from text key to foreign key ID
UPDATE "workflow"
SET "pinned_api_key_id" = ak."id"
FROM "api_key" ak
WHERE "workflow"."pinned_api_key" IS NOT NULL
AND ak."key" = "workflow"."pinned_api_key";--> statement-breakpoint
-- Step 4: Add foreign key constraints
ALTER TABLE "api_key" ADD CONSTRAINT "api_key_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "api_key" ADD CONSTRAINT "api_key_created_by_user_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "workflow" ADD CONSTRAINT "workflow_pinned_api_key_id_api_key_id_fk" FOREIGN KEY ("pinned_api_key_id") REFERENCES "public"."api_key"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
-- Step 5: Add check constraint to ensure data integrity
ALTER TABLE "api_key" ADD CONSTRAINT "workspace_type_check" CHECK ((type = 'workspace' AND workspace_id IS NOT NULL) OR (type = 'personal' AND workspace_id IS NULL));--> statement-breakpoint
-- Step 6: Drop old columns
ALTER TABLE "workflow" DROP COLUMN "pinned_api_key";
@@ -0,0 +1,10 @@
CREATE TABLE "idempotency_key" (
"key" text NOT NULL,
"namespace" text DEFAULT 'default' NOT NULL,
"result" json NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE UNIQUE INDEX "idempotency_key_namespace_unique" ON "idempotency_key" USING btree ("key","namespace");--> statement-breakpoint
CREATE INDEX "idempotency_key_created_at_idx" ON "idempotency_key" USING btree ("created_at");--> statement-breakpoint
CREATE INDEX "idempotency_key_namespace_idx" ON "idempotency_key" USING btree ("namespace");
@@ -0,0 +1 @@
ALTER TABLE "user_stats" ADD COLUMN "pro_period_cost_snapshot" numeric DEFAULT '0';
@@ -0,0 +1,47 @@
-- Backfill user_stats for any users missing a stats row
-- Uses defaults from schema for limits and counters
INSERT INTO "user_stats" (
"id",
"user_id",
"current_usage_limit",
"usage_limit_updated_at",
"total_manual_executions",
"total_api_calls",
"total_webhook_triggers",
"total_scheduled_executions",
"total_chat_executions",
"total_tokens_used",
"total_cost",
"current_period_cost",
"last_period_cost",
"total_copilot_cost",
"total_copilot_tokens",
"total_copilot_calls",
"last_active",
"billing_blocked"
)
SELECT
u."id" AS id,
u."id" AS user_id,
NULL::decimal AS current_usage_limit,
NOW() AS usage_limit_updated_at,
0 AS total_manual_executions,
0 AS total_api_calls,
0 AS total_webhook_triggers,
0 AS total_scheduled_executions,
0 AS total_chat_executions,
0 AS total_tokens_used,
'0'::decimal AS total_cost,
'0'::decimal AS current_period_cost,
'0'::decimal AS last_period_cost,
'0'::decimal AS total_copilot_cost,
0 AS total_copilot_tokens,
0 AS total_copilot_calls,
NOW() AS last_active,
FALSE AS billing_blocked
FROM "user" u
LEFT JOIN "user_stats" s ON s."user_id" = u."id"
WHERE s."user_id" IS NULL;
@@ -0,0 +1,2 @@
ALTER TABLE "settings" ADD COLUMN "show_floating_controls" boolean DEFAULT true NOT NULL;--> statement-breakpoint
ALTER TABLE "settings" ADD COLUMN "show_training_controls" boolean DEFAULT false NOT NULL;

Some files were not shown because too many files have changed in this diff Show More