From 3f8f2317dc86a72c3d61ab3f5ae9e3390ec993ca Mon Sep 17 00:00:00 2001 From: Harshith Mullapudi <17528887+harshithmullapudi@users.noreply.github.com> Date: Fri, 30 Oct 2026 19:04:03 +0000 Subject: [PATCH 1/9] feat(db): add users.experimental_chat, off by default Account-level switch for opening new agent sessions as chat, so desktop, mobile and server-side launches read one value. Constant-default ADD COLUMN: metadata-only on Postgres 11+. --- .../drizzle/0179_users_experimental_chat.sql | 1 + packages/db/drizzle/meta/0179_snapshot.json | 17240 ++++++++++++++++ packages/db/drizzle/meta/_journal.json | 7 + packages/db/src/schema/auth.ts | 1 + 4 files changed, 17249 insertions(+) create mode 100644 packages/db/drizzle/0179_users_experimental_chat.sql create mode 100644 packages/db/drizzle/meta/0179_snapshot.json diff --git a/packages/db/drizzle/0179_users_experimental_chat.sql b/packages/db/drizzle/0179_users_experimental_chat.sql new file mode 100644 index 00000000000..b73c9e5cf7e --- /dev/null +++ b/packages/db/drizzle/0179_users_experimental_chat.sql @@ -0,0 +1 @@ +ALTER TABLE "auth"."users" ADD COLUMN "experimental_chat" boolean DEFAULT false NOT NULL; \ No newline at end of file diff --git a/packages/db/drizzle/meta/0179_snapshot.json b/packages/db/drizzle/meta/0179_snapshot.json new file mode 100644 index 00000000000..a4038c61eff --- /dev/null +++ b/packages/db/drizzle/meta/0179_snapshot.json @@ -0,0 +1,17240 @@ +{ + "id": "5b5c0f1b-ddf4-4fef-a5d0-d613e9eefade", + "prevId": "2f315a6a-b681-4dfc-955f-f3bc498bc50d", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.actors": { + "name": "actors", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "agent_id": { + "name": "agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "actors_user_id_users_id_fk": { + "name": "actors_user_id_users_id_fk", + "tableFrom": "actors", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "actors_agent_id_agents_id_fk": { + "name": "actors_agent_id_agents_id_fk", + "tableFrom": "actors", + "tableTo": "agents", + "columnsFrom": [ + "agent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "actors_user_id_unique": { + "name": "actors_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + }, + "actors_agent_id_unique": { + "name": "actors_agent_id_unique", + "nullsNotDistinct": false, + "columns": [ + "agent_id" + ] + } + }, + "policies": {}, + "checkConstraints": { + "actors_one_kind": { + "name": "actors_one_kind", + "value": "(\"actors\".\"user_id\" IS NULL) <> (\"actors\".\"agent_id\" IS NULL)" + }, + "actors_id_matches": { + "name": "actors_id_matches", + "value": "\"actors\".\"id\" = coalesce(\"actors\".\"user_id\", \"actors\".\"agent_id\")" + } + }, + "isRLSEnabled": false + }, + "public.agent_memories": { + "name": "agent_memories", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "agent_id": { + "name": "agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "agent_memories_agent_idx": { + "name": "agent_memories_agent_idx", + "columns": [ + { + "expression": "agent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "agent_memories_organization_id_organizations_id_fk": { + "name": "agent_memories_organization_id_organizations_id_fk", + "tableFrom": "agent_memories", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_memories_agent_id_agents_id_fk": { + "name": "agent_memories_agent_id_agents_id_fk", + "tableFrom": "agent_memories", + "tableTo": "agents", + "columnsFrom": [ + "agent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.agent_routines": { + "name": "agent_routines", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "agent_id": { + "name": "agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "channel_id": { + "name": "channel_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "thread_root_id": { + "name": "thread_root_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "prompt": { + "name": "prompt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "schedule": { + "name": "schedule", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "triggers": { + "name": "triggers", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "next_run_at": { + "name": "next_run_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_run_at": { + "name": "last_run_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "agent_routines_agent_idx": { + "name": "agent_routines_agent_idx", + "columns": [ + { + "expression": "agent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "agent_routines_due_idx": { + "name": "agent_routines_due_idx", + "columns": [ + { + "expression": "next_run_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"agent_routines\".\"enabled\" and \"agent_routines\".\"next_run_at\" is not null", + "concurrently": false, + "method": "btree", + "with": {} + }, + "agent_routines_triggers_idx": { + "name": "agent_routines_triggers_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"agent_routines\".\"enabled\" and jsonb_array_length(\"agent_routines\".\"triggers\") > 0", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "agent_routines_organization_id_organizations_id_fk": { + "name": "agent_routines_organization_id_organizations_id_fk", + "tableFrom": "agent_routines", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_routines_agent_id_agents_id_fk": { + "name": "agent_routines_agent_id_agents_id_fk", + "tableFrom": "agent_routines", + "tableTo": "agents", + "columnsFrom": [ + "agent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_routines_created_by_user_id_users_id_fk": { + "name": "agent_routines_created_by_user_id_users_id_fk", + "tableFrom": "agent_routines", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_routines_channel_id_channels_id_fk": { + "name": "agent_routines_channel_id_channels_id_fk", + "tableFrom": "agent_routines", + "tableTo": "channels", + "columnsFrom": [ + "channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_routines_thread_root_id_channel_messages_id_fk": { + "name": "agent_routines_thread_root_id_channel_messages_id_fk", + "tableFrom": "agent_routines", + "tableTo": "channel_messages", + "columnsFrom": [ + "thread_root_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.agent_sessions": { + "name": "agent_sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "agent_id": { + "name": "agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "agent_session_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "channel_id": { + "name": "channel_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "thread_root_id": { + "name": "thread_root_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "cloud_workspace_id": { + "name": "cloud_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "parent_session_id": { + "name": "parent_session_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "task_id": { + "name": "task_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "role": { + "name": "role", + "type": "agent_task_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "task_status": { + "name": "task_status", + "type": "agent_task_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "instructions": { + "name": "instructions", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "requested_by_user_id": { + "name": "requested_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_activity_at": { + "name": "last_activity_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "agent_sessions_dm_unique": { + "name": "agent_sessions_dm_unique", + "columns": [ + { + "expression": "agent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"agent_sessions\".\"kind\" = 'dm'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "agent_sessions_thread_unique": { + "name": "agent_sessions_thread_unique", + "columns": [ + { + "expression": "agent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "thread_root_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"agent_sessions\".\"kind\" = 'thread'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "agent_sessions_parent_idx": { + "name": "agent_sessions_parent_idx", + "columns": [ + { + "expression": "parent_session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "agent_sessions_task_idx": { + "name": "agent_sessions_task_idx", + "columns": [ + { + "expression": "task_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "agent_sessions_active_writer_per_task_unique": { + "name": "agent_sessions_active_writer_per_task_unique", + "columns": [ + { + "expression": "task_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"agent_sessions\".\"task_id\" is not null and \"agent_sessions\".\"role\" = 'writer' and \"agent_sessions\".\"task_status\" in ('queued', 'running')", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "agent_sessions_organization_id_organizations_id_fk": { + "name": "agent_sessions_organization_id_organizations_id_fk", + "tableFrom": "agent_sessions", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_sessions_agent_id_agents_id_fk": { + "name": "agent_sessions_agent_id_agents_id_fk", + "tableFrom": "agent_sessions", + "tableTo": "agents", + "columnsFrom": [ + "agent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_sessions_channel_id_channels_id_fk": { + "name": "agent_sessions_channel_id_channels_id_fk", + "tableFrom": "agent_sessions", + "tableTo": "channels", + "columnsFrom": [ + "channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_sessions_thread_root_id_channel_messages_id_fk": { + "name": "agent_sessions_thread_root_id_channel_messages_id_fk", + "tableFrom": "agent_sessions", + "tableTo": "channel_messages", + "columnsFrom": [ + "thread_root_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_sessions_user_id_users_id_fk": { + "name": "agent_sessions_user_id_users_id_fk", + "tableFrom": "agent_sessions", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_sessions_cloud_workspace_id_cloud_workspaces_id_fk": { + "name": "agent_sessions_cloud_workspace_id_cloud_workspaces_id_fk", + "tableFrom": "agent_sessions", + "tableTo": "cloud_workspaces", + "columnsFrom": [ + "cloud_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "agent_sessions_task_id_tasks_id_fk": { + "name": "agent_sessions_task_id_tasks_id_fk", + "tableFrom": "agent_sessions", + "tableTo": "tasks", + "columnsFrom": [ + "task_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "agent_sessions_environment_id_environments_id_fk": { + "name": "agent_sessions_environment_id_environments_id_fk", + "tableFrom": "agent_sessions", + "tableTo": "environments", + "columnsFrom": [ + "environment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "agent_sessions_requested_by_user_id_users_id_fk": { + "name": "agent_sessions_requested_by_user_id_users_id_fk", + "tableFrom": "agent_sessions", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "requested_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.agent_turns": { + "name": "agent_turns", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "agent_id": { + "name": "agent_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "agent_turn_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'running'" + }, + "reason": { + "name": "reason", + "type": "agent_turn_reason", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "acting_user_id": { + "name": "acting_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "trigger_message_id": { + "name": "trigger_message_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "routine_id": { + "name": "routine_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "prompt_id": { + "name": "prompt_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "steer_prompt_ids": { + "name": "steer_prompt_ids", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "settled_at": { + "name": "settled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "reply": { + "name": "reply", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tool_calls": { + "name": "tool_calls", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "input_tokens": { + "name": "input_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "output_tokens": { + "name": "output_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "cost_micros_usd": { + "name": "cost_micros_usd", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "error_code": { + "name": "error_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "last_attempt_error": { + "name": "last_attempt_error", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "agent_turns_session_idx": { + "name": "agent_turns_session_idx", + "columns": [ + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "agent_turns_agent_status_idx": { + "name": "agent_turns_agent_status_idx", + "columns": [ + { + "expression": "agent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "agent_turns_one_running_per_session_idx": { + "name": "agent_turns_one_running_per_session_idx", + "columns": [ + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"agent_turns\".\"status\" = 'running'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "agent_turns_prompt_idx": { + "name": "agent_turns_prompt_idx", + "columns": [ + { + "expression": "session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "prompt_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"agent_turns\".\"prompt_id\" is not null", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "agent_turns_organization_id_organizations_id_fk": { + "name": "agent_turns_organization_id_organizations_id_fk", + "tableFrom": "agent_turns", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_turns_agent_id_agents_id_fk": { + "name": "agent_turns_agent_id_agents_id_fk", + "tableFrom": "agent_turns", + "tableTo": "agents", + "columnsFrom": [ + "agent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_turns_session_id_agent_sessions_id_fk": { + "name": "agent_turns_session_id_agent_sessions_id_fk", + "tableFrom": "agent_turns", + "tableTo": "agent_sessions", + "columnsFrom": [ + "session_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_turns_acting_user_id_users_id_fk": { + "name": "agent_turns_acting_user_id_users_id_fk", + "tableFrom": "agent_turns", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "acting_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "agent_turns_trigger_message_id_channel_messages_id_fk": { + "name": "agent_turns_trigger_message_id_channel_messages_id_fk", + "tableFrom": "agent_turns", + "tableTo": "channel_messages", + "columnsFrom": [ + "trigger_message_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "agent_turns_routine_id_agent_routines_id_fk": { + "name": "agent_turns_routine_id_agent_routines_id_fk", + "tableFrom": "agent_turns", + "tableTo": "agent_routines", + "columnsFrom": [ + "routine_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.agents": { + "name": "agents", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "avatar": { + "name": "avatar", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{\"shape\":\"pebble\",\"eyes\":\"dots\",\"color\":\"#7aa7ff\"}'::jsonb" + }, + "instructions": { + "name": "instructions", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "main_session_id": { + "name": "main_session_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "default_environment_id": { + "name": "default_environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "paused_at": { + "name": "paused_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "agents_organization_idx": { + "name": "agents_organization_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "agents_organization_id_organizations_id_fk": { + "name": "agents_organization_id_organizations_id_fk", + "tableFrom": "agents", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agents_default_environment_id_environments_id_fk": { + "name": "agents_default_environment_id_environments_id_fk", + "tableFrom": "agents", + "tableTo": "environments", + "columnsFrom": [ + "default_environment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "agents_created_by_user_id_users_id_fk": { + "name": "agents_created_by_user_id_users_id_fk", + "tableFrom": "agents", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.accounts": { + "name": "accounts", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "accounts_user_id_idx": { + "name": "accounts_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "accounts_user_id_users_id_fk": { + "name": "accounts_user_id_users_id_fk", + "tableFrom": "accounts", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.apikeys": { + "name": "apikeys", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "config_id": { + "name": "config_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'default'" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "start": { + "name": "start", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "prefix": { + "name": "prefix", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refill_interval": { + "name": "refill_interval", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "refill_amount": { + "name": "refill_amount", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_refill_at": { + "name": "last_refill_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "rate_limit_enabled": { + "name": "rate_limit_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "rate_limit_time_window": { + "name": "rate_limit_time_window", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 86400000 + }, + "rate_limit_max": { + "name": "rate_limit_max", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 10 + }, + "request_count": { + "name": "request_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "remaining": { + "name": "remaining", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_request": { + "name": "last_request", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "permissions": { + "name": "permissions", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": false, + "generated": { + "as": "CASE\n\t\t\t\tWHEN metadata IS NULL OR metadata = '' THEN NULL\n\t\t\t\tWHEN NOT (metadata IS JSON OBJECT) THEN NULL\n\t\t\t\tWHEN (metadata::jsonb->>'organizationId') ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'\n\t\t\t\t\tTHEN (metadata::jsonb->>'organizationId')::uuid\n\t\t\t\tELSE NULL\n\t\t\tEND", + "type": "stored" + } + } + }, + "indexes": { + "apikeys_configId_idx": { + "name": "apikeys_configId_idx", + "columns": [ + { + "expression": "config_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "apikeys_referenceId_idx": { + "name": "apikeys_referenceId_idx", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "apikeys_key_idx": { + "name": "apikeys_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "apikeys_organization_id_idx": { + "name": "apikeys_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "apikeys_metadata_trgm_idx": { + "name": "apikeys_metadata_trgm_idx", + "columns": [ + { + "expression": "\"metadata\" gin_trgm_ops", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.device_codes": { + "name": "device_codes", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "device_code": { + "name": "device_code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_code": { + "name": "user_code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "last_polled_at": { + "name": "last_polled_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "polling_interval": { + "name": "polling_interval", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.invitations": { + "name": "invitations", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "inviter_id": { + "name": "inviter_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "invitations_organization_id_idx": { + "name": "invitations_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invitations_email_idx": { + "name": "invitations_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "invitations_organization_id_organizations_id_fk": { + "name": "invitations_organization_id_organizations_id_fk", + "tableFrom": "invitations", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitations_inviter_id_users_id_fk": { + "name": "invitations_inviter_id_users_id_fk", + "tableFrom": "invitations", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitations_team_id_teams_id_fk": { + "name": "invitations_team_id_teams_id_fk", + "tableFrom": "invitations", + "tableTo": "teams", + "schemaTo": "auth", + "columnsFrom": [ + "team_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.jwkss": { + "name": "jwkss", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.members": { + "name": "members", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "members_organization_id_idx": { + "name": "members_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "members_user_id_idx": { + "name": "members_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "members_organization_id_organizations_id_fk": { + "name": "members_organization_id_organizations_id_fk", + "tableFrom": "members", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "members_user_id_users_id_fk": { + "name": "members_user_id_users_id_fk", + "tableFrom": "members", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.oauth_access_tokens": { + "name": "oauth_access_tokens", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_id": { + "name": "refresh_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scopes": { + "name": "scopes", + "type": "text[]", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "oauth_access_tokens_client_id_oauth_clients_client_id_fk": { + "name": "oauth_access_tokens_client_id_oauth_clients_client_id_fk", + "tableFrom": "oauth_access_tokens", + "tableTo": "oauth_clients", + "schemaTo": "auth", + "columnsFrom": [ + "client_id" + ], + "columnsTo": [ + "client_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "oauth_access_tokens_session_id_sessions_id_fk": { + "name": "oauth_access_tokens_session_id_sessions_id_fk", + "tableFrom": "oauth_access_tokens", + "tableTo": "sessions", + "schemaTo": "auth", + "columnsFrom": [ + "session_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "oauth_access_tokens_user_id_users_id_fk": { + "name": "oauth_access_tokens_user_id_users_id_fk", + "tableFrom": "oauth_access_tokens", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "oauth_access_tokens_refresh_id_oauth_refresh_tokens_id_fk": { + "name": "oauth_access_tokens_refresh_id_oauth_refresh_tokens_id_fk", + "tableFrom": "oauth_access_tokens", + "tableTo": "oauth_refresh_tokens", + "schemaTo": "auth", + "columnsFrom": [ + "refresh_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "oauth_access_tokens_token_unique": { + "name": "oauth_access_tokens_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.oauth_clients": { + "name": "oauth_clients", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "client_secret": { + "name": "client_secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "disabled": { + "name": "disabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "skip_consent": { + "name": "skip_consent", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "enable_end_session": { + "name": "enable_end_session", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "scopes": { + "name": "scopes", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "uri": { + "name": "uri", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "icon": { + "name": "icon", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "contacts": { + "name": "contacts", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "tos": { + "name": "tos", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "policy": { + "name": "policy", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "software_id": { + "name": "software_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "software_version": { + "name": "software_version", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "software_statement": { + "name": "software_statement", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "redirect_uris": { + "name": "redirect_uris", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "post_logout_redirect_uris": { + "name": "post_logout_redirect_uris", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "token_endpoint_auth_method": { + "name": "token_endpoint_auth_method", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "grant_types": { + "name": "grant_types", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "response_types": { + "name": "response_types", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "public": { + "name": "public", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "require_pkce": { + "name": "require_pkce", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "subject_type": { + "name": "subject_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "oauth_clients_user_id_users_id_fk": { + "name": "oauth_clients_user_id_users_id_fk", + "tableFrom": "oauth_clients", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "oauth_clients_client_id_unique": { + "name": "oauth_clients_client_id_unique", + "nullsNotDistinct": false, + "columns": [ + "client_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.oauth_consents": { + "name": "oauth_consents", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scopes": { + "name": "scopes", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "oauth_consents_client_id_oauth_clients_client_id_fk": { + "name": "oauth_consents_client_id_oauth_clients_client_id_fk", + "tableFrom": "oauth_consents", + "tableTo": "oauth_clients", + "schemaTo": "auth", + "columnsFrom": [ + "client_id" + ], + "columnsTo": [ + "client_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "oauth_consents_user_id_users_id_fk": { + "name": "oauth_consents_user_id_users_id_fk", + "tableFrom": "oauth_consents", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.oauth_refresh_tokens": { + "name": "oauth_refresh_tokens", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "revoked": { + "name": "revoked", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "auth_time": { + "name": "auth_time", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scopes": { + "name": "scopes", + "type": "text[]", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "oauth_refresh_tokens_client_id_oauth_clients_client_id_fk": { + "name": "oauth_refresh_tokens_client_id_oauth_clients_client_id_fk", + "tableFrom": "oauth_refresh_tokens", + "tableTo": "oauth_clients", + "schemaTo": "auth", + "columnsFrom": [ + "client_id" + ], + "columnsTo": [ + "client_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "oauth_refresh_tokens_session_id_sessions_id_fk": { + "name": "oauth_refresh_tokens_session_id_sessions_id_fk", + "tableFrom": "oauth_refresh_tokens", + "tableTo": "sessions", + "schemaTo": "auth", + "columnsFrom": [ + "session_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "oauth_refresh_tokens_user_id_users_id_fk": { + "name": "oauth_refresh_tokens_user_id_users_id_fk", + "tableFrom": "oauth_refresh_tokens", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "oauth_refresh_tokens_token_unique": { + "name": "oauth_refresh_tokens_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.organizations": { + "name": "organizations", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "allowed_domains": { + "name": "allowed_domains", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "task_tracker": { + "name": "task_tracker", + "type": "task_tracker", + "typeSchema": "auth", + "primaryKey": false, + "notNull": true, + "default": "'superset'" + } + }, + "indexes": { + "organizations_slug_idx": { + "name": "organizations_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "organizations_allowed_domains_idx": { + "name": "organizations_allowed_domains_idx", + "columns": [ + { + "expression": "allowed_domains", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "organizations_slug_unique": { + "name": "organizations_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.sessions": { + "name": "sessions", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "active_team_id": { + "name": "active_team_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "sessions_user_id_idx": { + "name": "sessions_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "sessions_token_unique": { + "name": "sessions_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.team_members": { + "name": "team_members", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": { + "team_members_team_id_idx": { + "name": "team_members_team_id_idx", + "columns": [ + { + "expression": "team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "team_members_user_id_idx": { + "name": "team_members_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "team_members_organization_id_idx": { + "name": "team_members_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "team_members_team_user_unique": { + "name": "team_members_team_user_unique", + "columns": [ + { + "expression": "team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "team_members_team_id_teams_id_fk": { + "name": "team_members_team_id_teams_id_fk", + "tableFrom": "team_members", + "tableTo": "teams", + "schemaTo": "auth", + "columnsFrom": [ + "team_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "team_members_user_id_users_id_fk": { + "name": "team_members_user_id_users_id_fk", + "tableFrom": "team_members", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "team_members_organization_id_organizations_id_fk": { + "name": "team_members_organization_id_organizations_id_fk", + "tableFrom": "team_members", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.teams": { + "name": "teams", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": { + "teams_organization_id_idx": { + "name": "teams_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "teams_org_slug_unique": { + "name": "teams_org_slug_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "teams_organization_id_organizations_id_fk": { + "name": "teams_organization_id_organizations_id_fk", + "tableFrom": "teams", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.users": { + "name": "users", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_ids": { + "name": "organization_ids", + "type": "uuid[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "last_active_organization_id": { + "name": "last_active_organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "onboarded_at": { + "name": "onboarded_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "locale": { + "name": "locale", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "experimental_chat": { + "name": "experimental_chat", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "deletion_requested_at": { + "name": "deletion_requested_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "users_organization_ids_idx": { + "name": "users_organization_ids_idx", + "columns": [ + { + "expression": "organization_ids", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "auth.verifications": { + "name": "verifications", + "schema": "auth", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "verifications_identifier_idx": { + "name": "verifications_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.channel_members": { + "name": "channel_members", + "schema": "", + "columns": { + "channel_id": { + "name": "channel_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "actor_id": { + "name": "actor_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "channel_member_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "notify": { + "name": "notify", + "type": "channel_notify", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "muted": { + "name": "muted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "suppress_broadcasts": { + "name": "suppress_broadcasts", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "last_read_seq": { + "name": "last_read_seq", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "channel_members_actor_idx": { + "name": "channel_members_actor_idx", + "columns": [ + { + "expression": "actor_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "channel_members_channel_id_channels_id_fk": { + "name": "channel_members_channel_id_channels_id_fk", + "tableFrom": "channel_members", + "tableTo": "channels", + "columnsFrom": [ + "channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "channel_members_actor_id_actors_id_fk": { + "name": "channel_members_actor_id_actors_id_fk", + "tableFrom": "channel_members", + "tableTo": "actors", + "columnsFrom": [ + "actor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "channel_members_channel_id_actor_id_pk": { + "name": "channel_members_channel_id_actor_id_pk", + "columns": [ + "channel_id", + "actor_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.channel_message_reactions": { + "name": "channel_message_reactions", + "schema": "", + "columns": { + "message_id": { + "name": "message_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "actor_id": { + "name": "actor_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "emoji": { + "name": "emoji", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "channel_message_reactions_message_id_channel_messages_id_fk": { + "name": "channel_message_reactions_message_id_channel_messages_id_fk", + "tableFrom": "channel_message_reactions", + "tableTo": "channel_messages", + "columnsFrom": [ + "message_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "channel_message_reactions_actor_id_actors_id_fk": { + "name": "channel_message_reactions_actor_id_actors_id_fk", + "tableFrom": "channel_message_reactions", + "tableTo": "actors", + "columnsFrom": [ + "actor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "channel_message_reactions_message_id_actor_id_emoji_pk": { + "name": "channel_message_reactions_message_id_actor_id_emoji_pk", + "columns": [ + "message_id", + "actor_id", + "emoji" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.channel_messages": { + "name": "channel_messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "channel_id": { + "name": "channel_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "seq": { + "name": "seq", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "thread_root_id": { + "name": "thread_root_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "author_id": { + "name": "author_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "body": { + "name": "body", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "subtype": { + "name": "subtype", + "type": "channel_message_subtype", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "inviter_id": { + "name": "inviter_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "mentioned_ids": { + "name": "mentioned_ids", + "type": "uuid[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::uuid[]" + }, + "broadcast": { + "name": "broadcast", + "type": "channel_broadcast", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reply_count": { + "name": "reply_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_reply_at": { + "name": "last_reply_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "edited_at": { + "name": "edited_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "channel_messages_channel_seq_unique": { + "name": "channel_messages_channel_seq_unique", + "columns": [ + { + "expression": "channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "seq", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "channel_messages_thread_idx": { + "name": "channel_messages_thread_idx", + "columns": [ + { + "expression": "thread_root_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "seq", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "channel_messages_author_client_unique": { + "name": "channel_messages_author_client_unique", + "columns": [ + { + "expression": "author_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "client_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"channel_messages\".\"client_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "channel_messages_channel_id_channels_id_fk": { + "name": "channel_messages_channel_id_channels_id_fk", + "tableFrom": "channel_messages", + "tableTo": "channels", + "columnsFrom": [ + "channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "channel_messages_thread_root_id_channel_messages_id_fk": { + "name": "channel_messages_thread_root_id_channel_messages_id_fk", + "tableFrom": "channel_messages", + "tableTo": "channel_messages", + "columnsFrom": [ + "thread_root_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "channel_messages_author_id_actors_id_fk": { + "name": "channel_messages_author_id_actors_id_fk", + "tableFrom": "channel_messages", + "tableTo": "actors", + "columnsFrom": [ + "author_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "channel_messages_inviter_id_actors_id_fk": { + "name": "channel_messages_inviter_id_actors_id_fk", + "tableFrom": "channel_messages", + "tableTo": "actors", + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.channel_notification_prefs": { + "name": "channel_notification_prefs", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "notify": { + "name": "notify", + "type": "channel_notify", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'mentions'" + }, + "show_preview": { + "name": "show_preview", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "keywords": { + "name": "keywords", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'::text[]" + }, + "paused_until": { + "name": "paused_until", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "schedule_enabled": { + "name": "schedule_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "schedule_days": { + "name": "schedule_days", + "type": "integer[]", + "primaryKey": false, + "notNull": true, + "default": "'{0,1,2,3,4,5,6}'::integer[]" + }, + "schedule_start_minute": { + "name": "schedule_start_minute", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 480 + }, + "schedule_end_minute": { + "name": "schedule_end_minute", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1320 + }, + "time_zone": { + "name": "time_zone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dock_bounce": { + "name": "dock_bounce", + "type": "dock_bounce", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'off'" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "channel_notification_prefs_user_id_users_id_fk": { + "name": "channel_notification_prefs_user_id_users_id_fk", + "tableFrom": "channel_notification_prefs", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.channel_tasks": { + "name": "channel_tasks", + "schema": "", + "columns": { + "task_id": { + "name": "task_id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "channel_id": { + "name": "channel_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "channel_tasks_channel_id_idx": { + "name": "channel_tasks_channel_id_idx", + "columns": [ + { + "expression": "channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "channel_tasks_task_id_tasks_id_fk": { + "name": "channel_tasks_task_id_tasks_id_fk", + "tableFrom": "channel_tasks", + "tableTo": "tasks", + "columnsFrom": [ + "task_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "channel_tasks_channel_id_channels_id_fk": { + "name": "channel_tasks_channel_id_channels_id_fk", + "tableFrom": "channel_tasks", + "tableTo": "channels", + "columnsFrom": [ + "channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.channel_thread_follows": { + "name": "channel_thread_follows", + "schema": "", + "columns": { + "root_id": { + "name": "root_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "actor_id": { + "name": "actor_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "channel_id": { + "name": "channel_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "following": { + "name": "following", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "last_read_seq": { + "name": "last_read_seq", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "channel_thread_follows_actor_idx": { + "name": "channel_thread_follows_actor_idx", + "columns": [ + { + "expression": "actor_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "channel_thread_follows_root_id_channel_messages_id_fk": { + "name": "channel_thread_follows_root_id_channel_messages_id_fk", + "tableFrom": "channel_thread_follows", + "tableTo": "channel_messages", + "columnsFrom": [ + "root_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "channel_thread_follows_actor_id_actors_id_fk": { + "name": "channel_thread_follows_actor_id_actors_id_fk", + "tableFrom": "channel_thread_follows", + "tableTo": "actors", + "columnsFrom": [ + "actor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "channel_thread_follows_channel_id_channels_id_fk": { + "name": "channel_thread_follows_channel_id_channels_id_fk", + "tableFrom": "channel_thread_follows", + "tableTo": "channels", + "columnsFrom": [ + "channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "channel_thread_follows_root_id_actor_id_pk": { + "name": "channel_thread_follows_root_id_actor_id_pk", + "columns": [ + "root_id", + "actor_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.channels": { + "name": "channels", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "kind": { + "name": "kind", + "type": "channel_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'channel'" + }, + "visibility": { + "name": "visibility", + "type": "channel_visibility", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'public'" + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "last_seq": { + "name": "last_seq", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_message_at": { + "name": "last_message_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "channels_org_name_unique": { + "name": "channels_org_name_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(\"name\")", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"channels\".\"archived_at\" IS NULL AND \"channels\".\"kind\" = 'channel'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "channels_organization_idx": { + "name": "channels_organization_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "channels_organization_id_organizations_id_fk": { + "name": "channels_organization_id_organizations_id_fk", + "tableFrom": "channels", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "channels_created_by_user_id_users_id_fk": { + "name": "channels_created_by_user_id_users_id_fk", + "tableFrom": "channels", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.github_installations": { + "name": "github_installations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "connected_by_user_id": { + "name": "connected_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "installation_id": { + "name": "installation_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "account_login": { + "name": "account_login", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "account_type": { + "name": "account_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "suspended": { + "name": "suspended", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "suspended_at": { + "name": "suspended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "github_installations_installation_id_idx": { + "name": "github_installations_installation_id_idx", + "columns": [ + { + "expression": "installation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "github_installations_organization_id_organizations_id_fk": { + "name": "github_installations_organization_id_organizations_id_fk", + "tableFrom": "github_installations", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "github_installations_connected_by_user_id_users_id_fk": { + "name": "github_installations_connected_by_user_id_users_id_fk", + "tableFrom": "github_installations", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "connected_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "github_installations_installation_id_unique": { + "name": "github_installations_installation_id_unique", + "nullsNotDistinct": false, + "columns": [ + "installation_id" + ] + }, + "github_installations_org_unique": { + "name": "github_installations_org_unique", + "nullsNotDistinct": false, + "columns": [ + "organization_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.github_pull_requests": { + "name": "github_pull_requests", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "repository_id": { + "name": "repository_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "pr_number": { + "name": "pr_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "node_id": { + "name": "node_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "head_branch": { + "name": "head_branch", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "head_sha": { + "name": "head_sha", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "base_branch": { + "name": "base_branch", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "author_login": { + "name": "author_login", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "author_avatar_url": { + "name": "author_avatar_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_draft": { + "name": "is_draft", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "additions": { + "name": "additions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "deletions": { + "name": "deletions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "changed_files": { + "name": "changed_files", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "review_decision": { + "name": "review_decision", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "checks_status": { + "name": "checks_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'none'" + }, + "checks": { + "name": "checks", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "merged_at": { + "name": "merged_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "closed_at": { + "name": "closed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "github_pull_requests_repository_id_idx": { + "name": "github_pull_requests_repository_id_idx", + "columns": [ + { + "expression": "repository_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "github_pull_requests_state_idx": { + "name": "github_pull_requests_state_idx", + "columns": [ + { + "expression": "state", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "github_pull_requests_head_branch_idx": { + "name": "github_pull_requests_head_branch_idx", + "columns": [ + { + "expression": "head_branch", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "github_pull_requests_org_id_idx": { + "name": "github_pull_requests_org_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "github_pull_requests_repository_id_github_repositories_id_fk": { + "name": "github_pull_requests_repository_id_github_repositories_id_fk", + "tableFrom": "github_pull_requests", + "tableTo": "github_repositories", + "columnsFrom": [ + "repository_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "github_pull_requests_organization_id_organizations_id_fk": { + "name": "github_pull_requests_organization_id_organizations_id_fk", + "tableFrom": "github_pull_requests", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "github_pull_requests_repo_pr_unique": { + "name": "github_pull_requests_repo_pr_unique", + "nullsNotDistinct": false, + "columns": [ + "repository_id", + "pr_number" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.github_repositories": { + "name": "github_repositories", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "installation_id": { + "name": "installation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "repo_id": { + "name": "repo_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner": { + "name": "owner", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "full_name": { + "name": "full_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "default_branch": { + "name": "default_branch", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'main'" + }, + "is_private": { + "name": "is_private", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "github_repositories_installation_id_idx": { + "name": "github_repositories_installation_id_idx", + "columns": [ + { + "expression": "installation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "github_repositories_full_name_idx": { + "name": "github_repositories_full_name_idx", + "columns": [ + { + "expression": "full_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "github_repositories_org_id_idx": { + "name": "github_repositories_org_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "github_repositories_installation_id_github_installations_id_fk": { + "name": "github_repositories_installation_id_github_installations_id_fk", + "tableFrom": "github_repositories", + "tableTo": "github_installations", + "columnsFrom": [ + "installation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "github_repositories_organization_id_organizations_id_fk": { + "name": "github_repositories_organization_id_organizations_id_fk", + "tableFrom": "github_repositories", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "github_repositories_repo_id_unique": { + "name": "github_repositories_repo_id_unique", + "nullsNotDistinct": false, + "columns": [ + "repo_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "ingest.webhook_events": { + "name": "webhook_events", + "schema": "ingest", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "provider": { + "name": "provider", + "type": "integration_provider", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "event_id": { + "name": "event_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "event_type": { + "name": "event_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "processed_at": { + "name": "processed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "retry_count": { + "name": "retry_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "received_at": { + "name": "received_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "webhook_events_provider_status_idx": { + "name": "webhook_events_provider_status_idx", + "columns": [ + { + "expression": "provider", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "webhook_events_provider_event_id_idx": { + "name": "webhook_events_provider_event_id_idx", + "columns": [ + { + "expression": "provider", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "event_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "webhook_events_received_at_idx": { + "name": "webhook_events_received_at_idx", + "columns": [ + { + "expression": "received_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.leaderboard_daily": { + "name": "leaderboard_daily", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "day": { + "name": "day", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "host_id": { + "name": "host_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "uncached_input": { + "name": "uncached_input", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "cached_input": { + "name": "cached_input", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "cache_write_5m": { + "name": "cache_write_5m", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "cache_write_1h": { + "name": "cache_write_1h", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "output": { + "name": "output", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "reasoning_output": { + "name": "reasoning_output", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "tokens": { + "name": "tokens", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "usd_estimate": { + "name": "usd_estimate", + "type": "numeric(14, 6)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "approximate": { + "name": "approximate", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "sessions": { + "name": "sessions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "leaderboard_daily_day_idx": { + "name": "leaderboard_daily_day_idx", + "columns": [ + { + "expression": "day", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "leaderboard_daily_user_day_idx": { + "name": "leaderboard_daily_user_day_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "day", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "leaderboard_daily_model_day_idx": { + "name": "leaderboard_daily_model_day_idx", + "columns": [ + { + "expression": "model", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "day", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "leaderboard_daily_user_id_public_profiles_user_id_fk": { + "name": "leaderboard_daily_user_id_public_profiles_user_id_fk", + "tableFrom": "leaderboard_daily", + "tableTo": "public_profiles", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "user_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "leaderboard_daily_identity_key": { + "name": "leaderboard_daily_identity_key", + "nullsNotDistinct": false, + "columns": [ + "user_id", + "day", + "provider", + "model", + "host_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.leaderboard_daily_factory": { + "name": "leaderboard_daily_factory", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "day": { + "name": "day", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "host_id": { + "name": "host_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sessions": { + "name": "sessions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "parallel_sessions": { + "name": "parallel_sessions", + "type": "numeric(6, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "agent_prs_merged": { + "name": "agent_prs_merged", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "leaderboard_daily_factory_day_idx": { + "name": "leaderboard_daily_factory_day_idx", + "columns": [ + { + "expression": "day", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "leaderboard_daily_factory_user_day_idx": { + "name": "leaderboard_daily_factory_user_day_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "day", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "leaderboard_daily_factory_user_id_public_profiles_user_id_fk": { + "name": "leaderboard_daily_factory_user_id_public_profiles_user_id_fk", + "tableFrom": "leaderboard_daily_factory", + "tableTo": "public_profiles", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "user_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "leaderboard_daily_factory_identity_key": { + "name": "leaderboard_daily_factory_identity_key", + "nullsNotDistinct": false, + "columns": [ + "user_id", + "day", + "host_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.leaderboard_participants": { + "name": "leaderboard_participants", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "handle": { + "name": "handle", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "visibility": { + "name": "visibility", + "type": "leaderboard_visibility", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'public'" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "opted_in_at": { + "name": "opted_in_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "flagged_at": { + "name": "flagged_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_published_at": { + "name": "last_published_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "payload_version": { + "name": "payload_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "tokens": { + "name": "tokens", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "usd": { + "name": "usd", + "type": "numeric(20, 6)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "sessions": { + "name": "sessions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "uncached_input": { + "name": "uncached_input", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "cached_input": { + "name": "cached_input", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "cache_write_5m": { + "name": "cache_write_5m", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "cache_write_1h": { + "name": "cache_write_1h", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "output": { + "name": "output", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "reasoning_output": { + "name": "reasoning_output", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "approximate": { + "name": "approximate", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "day_range_start": { + "name": "day_range_start", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "day_range_end": { + "name": "day_range_end", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "tier": { + "name": "tier", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "tier_computed_at": { + "name": "tier_computed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "active_days": { + "name": "active_days", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "axis_width": { + "name": "axis_width", + "type": "numeric(6, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "axis_depth": { + "name": "axis_depth", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "axis_output": { + "name": "axis_output", + "type": "numeric(8, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "axis_cost": { + "name": "axis_cost", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "leaderboard_participants_tokens_idx": { + "name": "leaderboard_participants_tokens_idx", + "columns": [ + { + "expression": "tokens", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "leaderboard_participants_org_idx": { + "name": "leaderboard_participants_org_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "leaderboard_participants_usd_idx": { + "name": "leaderboard_participants_usd_idx", + "columns": [ + { + "expression": "usd", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "leaderboard_participants_tier_idx": { + "name": "leaderboard_participants_tier_idx", + "columns": [ + { + "expression": "tier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "leaderboard_participants_user_id_users_id_fk": { + "name": "leaderboard_participants_user_id_users_id_fk", + "tableFrom": "leaderboard_participants", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "leaderboard_participants_organization_id_organizations_id_fk": { + "name": "leaderboard_participants_organization_id_organizations_id_fk", + "tableFrom": "leaderboard_participants", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "leaderboard_participants_handle_unique": { + "name": "leaderboard_participants_handle_unique", + "nullsNotDistinct": false, + "columns": [ + "handle" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization_plugin_sources": { + "name": "organization_plugin_sources", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "repo": { + "name": "repo", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "ref": { + "name": "ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "synced_sha": { + "name": "synced_sha", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "synced_at": { + "name": "synced_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "sync_error": { + "name": "sync_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_problems": { + "name": "sync_problems", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "added_by_user_id": { + "name": "added_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "organization_plugin_sources_organization_repo_path_unique": { + "name": "organization_plugin_sources_organization_repo_path_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "repo", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "organization_plugin_sources_organization_id_organizations_id_fk": { + "name": "organization_plugin_sources_organization_id_organizations_id_fk", + "tableFrom": "organization_plugin_sources", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "organization_plugin_sources_added_by_user_id_users_id_fk": { + "name": "organization_plugin_sources_added_by_user_id_users_id_fk", + "tableFrom": "organization_plugin_sources", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "added_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "organization_plugin_sources_id_organization_unique": { + "name": "organization_plugin_sources_id_organization_unique", + "nullsNotDistinct": false, + "columns": [ + "id", + "organization_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.organization_plugins": { + "name": "organization_plugins", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "source_id": { + "name": "source_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "manifest": { + "name": "manifest", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "content_hash": { + "name": "content_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_fingerprint": { + "name": "source_fingerprint", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "install_policy": { + "name": "install_policy", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "removed_from_source_at": { + "name": "removed_from_source_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "organization_plugins_organization_name_unique": { + "name": "organization_plugins_organization_name_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "organization_plugins_source_idx": { + "name": "organization_plugins_source_idx", + "columns": [ + { + "expression": "source_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "organization_plugins_organization_id_organizations_id_fk": { + "name": "organization_plugins_organization_id_organizations_id_fk", + "tableFrom": "organization_plugins", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "organization_plugins_source_organization_fk": { + "name": "organization_plugins_source_organization_fk", + "tableFrom": "organization_plugins", + "tableTo": "organization_plugin_sources", + "columnsFrom": [ + "source_id", + "organization_id" + ], + "columnsTo": [ + "id", + "organization_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.plugin_installs": { + "name": "plugin_installs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "marketplace": { + "name": "marketplace", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "plugin_name": { + "name": "plugin_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "manifest": { + "name": "manifest", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "organization_plugin_id": { + "name": "organization_plugin_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "installed_at": { + "name": "installed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "plugin_installs_user_plugin_unique": { + "name": "plugin_installs_user_plugin_unique", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "marketplace", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "plugin_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "plugin_installs_user_idx": { + "name": "plugin_installs_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "plugin_installs_organization_plugin_idx": { + "name": "plugin_installs_organization_plugin_idx", + "columns": [ + { + "expression": "organization_plugin_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "plugin_installs_organization_id_organizations_id_fk": { + "name": "plugin_installs_organization_id_organizations_id_fk", + "tableFrom": "plugin_installs", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "plugin_installs_user_id_users_id_fk": { + "name": "plugin_installs_user_id_users_id_fk", + "tableFrom": "plugin_installs", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "plugin_installs_organization_plugin_id_organization_plugins_id_fk": { + "name": "plugin_installs_organization_plugin_id_organization_plugins_id_fk", + "tableFrom": "plugin_installs", + "tableTo": "organization_plugins", + "columnsFrom": [ + "organization_plugin_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.plugin_marketplaces": { + "name": "plugin_marketplaces", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_kind": { + "name": "source_kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "repo": { + "name": "repo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ref": { + "name": "ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "added_at": { + "name": "added_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "plugin_marketplaces_user_name_unique": { + "name": "plugin_marketplaces_user_name_unique", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "plugin_marketplaces_user_idx": { + "name": "plugin_marketplaces_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "plugin_marketplaces_organization_id_organizations_id_fk": { + "name": "plugin_marketplaces_organization_id_organizations_id_fk", + "tableFrom": "plugin_marketplaces", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "plugin_marketplaces_user_id_users_id_fk": { + "name": "plugin_marketplaces_user_id_users_id_fk", + "tableFrom": "plugin_marketplaces", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.plugin_oauth_clients": { + "name": "plugin_oauth_clients", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "issuer": { + "name": "issuer", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "redirect_uri": { + "name": "redirect_uri", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "client_secret": { + "name": "client_secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "client_secret_expires_at": { + "name": "client_secret_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "registration_access_token": { + "name": "registration_access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "registration_client_uri": { + "name": "registration_client_uri", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "token_endpoint_auth_method": { + "name": "token_endpoint_auth_method", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "plugin_oauth_clients_issuer_redirect_unique": { + "name": "plugin_oauth_clients_issuer_redirect_unique", + "columns": [ + { + "expression": "issuer", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "redirect_uri", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.handles": { + "name": "handles", + "schema": "", + "columns": { + "handle": { + "name": "handle", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "owner_type": { + "name": "owner_type", + "type": "handle_owner_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "handles_owner_type_idx": { + "name": "handles_owner_type_idx", + "columns": [ + { + "expression": "owner_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "handles_user_id_users_id_fk": { + "name": "handles_user_id_users_id_fk", + "tableFrom": "handles", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "handles_organization_id_organizations_id_fk": { + "name": "handles_organization_id_organizations_id_fk", + "tableFrom": "handles", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "handles_user_key": { + "name": "handles_user_key", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + }, + "handles_organization_key": { + "name": "handles_organization_key", + "nullsNotDistinct": false, + "columns": [ + "organization_id" + ] + }, + "handles_user_owner_key": { + "name": "handles_user_owner_key", + "nullsNotDistinct": false, + "columns": [ + "handle", + "user_id" + ] + } + }, + "policies": {}, + "checkConstraints": { + "handles_owner_matches_type": { + "name": "handles_owner_matches_type", + "value": "(\n\t\t\t\t(\"handles\".\"owner_type\" = 'user' and \"handles\".\"user_id\" is not null and \"handles\".\"organization_id\" is null)\n\t\t\t\tor (\"handles\".\"owner_type\" = 'organization' and \"handles\".\"organization_id\" is not null and \"handles\".\"user_id\" is null)\n\t\t\t\tor (\"handles\".\"owner_type\" = 'reserved' and \"handles\".\"user_id\" is null and \"handles\".\"organization_id\" is null)\n\t\t\t)" + }, + "handles_shape": { + "name": "handles_shape", + "value": "length(\"handles\".\"handle\") between 2 and 39 and \"handles\".\"handle\" ~ '^[a-z0-9]+(-[a-z0-9]+)*$'" + } + }, + "isRLSEnabled": false + }, + "public.profile_awards": { + "name": "profile_awards", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tier": { + "name": "tier", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "value": { + "name": "value", + "type": "numeric(20, 4)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "awarded_on": { + "name": "awarded_on", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "awarded_at": { + "name": "awarded_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "profile_awards_user_idx": { + "name": "profile_awards_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "profile_awards_slug_idx": { + "name": "profile_awards_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "awarded_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "profile_awards_user_id_public_profiles_user_id_fk": { + "name": "profile_awards_user_id_public_profiles_user_id_fk", + "tableFrom": "profile_awards", + "tableTo": "public_profiles", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "user_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "profile_awards_identity_key": { + "name": "profile_awards_identity_key", + "nullsNotDistinct": false, + "columns": [ + "user_id", + "slug", + "tier" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.public_profiles": { + "name": "public_profiles", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "handle": { + "name": "handle", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "visibility": { + "name": "visibility", + "type": "leaderboard_visibility", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'public'" + }, + "bio": { + "name": "bio", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "github_handle": { + "name": "github_handle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "x_handle": { + "name": "x_handle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "website_url": { + "name": "website_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "opted_in_at": { + "name": "opted_in_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "flagged_at": { + "name": "flagged_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_published_at": { + "name": "last_published_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "payload_version": { + "name": "payload_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "awards_catalog_version": { + "name": "awards_catalog_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "tokens": { + "name": "tokens", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "usd": { + "name": "usd", + "type": "numeric(20, 6)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "sessions": { + "name": "sessions", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "uncached_input": { + "name": "uncached_input", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "cached_input": { + "name": "cached_input", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "cache_write_5m": { + "name": "cache_write_5m", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "cache_write_1h": { + "name": "cache_write_1h", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "output": { + "name": "output", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "reasoning_output": { + "name": "reasoning_output", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "approximate": { + "name": "approximate", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "day_range_start": { + "name": "day_range_start", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "day_range_end": { + "name": "day_range_end", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "tier": { + "name": "tier", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "tier_computed_at": { + "name": "tier_computed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "active_days": { + "name": "active_days", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "axis_width": { + "name": "axis_width", + "type": "numeric(6, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "axis_depth": { + "name": "axis_depth", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "axis_output": { + "name": "axis_output", + "type": "numeric(8, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "axis_cost": { + "name": "axis_cost", + "type": "numeric(10, 2)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "public_profiles_tokens_idx": { + "name": "public_profiles_tokens_idx", + "columns": [ + { + "expression": "tokens", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "public_profiles_org_idx": { + "name": "public_profiles_org_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "public_profiles_usd_idx": { + "name": "public_profiles_usd_idx", + "columns": [ + { + "expression": "usd", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "public_profiles_tier_idx": { + "name": "public_profiles_tier_idx", + "columns": [ + { + "expression": "tier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "public_profiles_user_id_users_id_fk": { + "name": "public_profiles_user_id_users_id_fk", + "tableFrom": "public_profiles", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "public_profiles_organization_id_organizations_id_fk": { + "name": "public_profiles_organization_id_organizations_id_fk", + "tableFrom": "public_profiles", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "public_profiles_handle_owner_fk": { + "name": "public_profiles_handle_owner_fk", + "tableFrom": "public_profiles", + "tableTo": "handles", + "columnsFrom": [ + "handle", + "user_id" + ], + "columnsTo": [ + "handle", + "user_id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "public_profiles_handle_unique": { + "name": "public_profiles_handle_unique", + "nullsNotDistinct": false, + "columns": [ + "handle" + ] + } + }, + "policies": {}, + "checkConstraints": { + "public_profiles_bio_length": { + "name": "public_profiles_bio_length", + "value": "length(\"public_profiles\".\"bio\") <= 160" + }, + "public_profiles_website_scheme": { + "name": "public_profiles_website_scheme", + "value": "\"public_profiles\".\"website_url\" is null or \"public_profiles\".\"website_url\" ~ '^https://'" + } + }, + "isRLSEnabled": false + }, + "public.agent_commands": { + "name": "agent_commands", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "target_device_id": { + "name": "target_device_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "target_device_type": { + "name": "target_device_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tool": { + "name": "tool", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "params": { + "name": "params", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "parent_command_id": { + "name": "parent_command_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "command_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "result": { + "name": "result", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "executed_at": { + "name": "executed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "timeout_at": { + "name": "timeout_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "agent_commands_user_status_idx": { + "name": "agent_commands_user_status_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "agent_commands_target_device_status_idx": { + "name": "agent_commands_target_device_status_idx", + "columns": [ + { + "expression": "target_device_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "agent_commands_org_created_idx": { + "name": "agent_commands_org_created_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "agent_commands_user_id_users_id_fk": { + "name": "agent_commands_user_id_users_id_fk", + "tableFrom": "agent_commands", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agent_commands_organization_id_organizations_id_fk": { + "name": "agent_commands_organization_id_organizations_id_fk", + "tableFrom": "agent_commands", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.agent_credentials": { + "name": "agent_credentials", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "agent": { + "name": "agent", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "agent_credential_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "encrypted_value": { + "name": "encrypted_value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "base_url": { + "name": "base_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "account_label": { + "name": "account_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_validated_at": { + "name": "last_validated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "agent_credentials_user_id_idx": { + "name": "agent_credentials_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "agent_credentials_user_id_users_id_fk": { + "name": "agent_credentials_user_id_users_id_fk", + "tableFrom": "agent_credentials", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "agent_credentials_user_id_agent_unique": { + "name": "agent_credentials_user_id_agent_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id", + "agent" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.attachments": { + "name": "attachments", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "file_id": { + "name": "file_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "parent_kind": { + "name": "parent_kind", + "type": "attachment_parent_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "parent_id": { + "name": "parent_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "attachments_file_id_idx": { + "name": "attachments_file_id_idx", + "columns": [ + { + "expression": "file_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "attachments_parent_kind_parent_id_idx": { + "name": "attachments_parent_kind_parent_id_idx", + "columns": [ + { + "expression": "parent_kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "attachments_parent_path_unique": { + "name": "attachments_parent_path_unique", + "columns": [ + { + "expression": "parent_kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"attachments\".\"path\" is not null", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "attachments_file_id_files_id_fk": { + "name": "attachments_file_id_files_id_fk", + "tableFrom": "attachments", + "tableTo": "files", + "columnsFrom": [ + "file_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.automation_events": { + "name": "automation_events", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "integration_connection_id": { + "name": "integration_connection_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "event_type": { + "name": "event_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "external_event_id": { + "name": "external_event_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "resource_key": { + "name": "resource_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "repository_id": { + "name": "repository_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ref": { + "name": "ref", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "actor_login": { + "name": "actor_login", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "actor_is_external": { + "name": "actor_is_external", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "webhook_event_id": { + "name": "webhook_event_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "received_at": { + "name": "received_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "dispatch_input": { + "name": "dispatch_input", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "dispatched_at": { + "name": "dispatched_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "automation_events_undispatched_idx": { + "name": "automation_events_undispatched_idx", + "columns": [ + { + "expression": "received_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"automation_events\".\"dispatched_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_events_org_received_idx": { + "name": "automation_events_org_received_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "received_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_events_resource_idx": { + "name": "automation_events_resource_idx", + "columns": [ + { + "expression": "resource_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_events_received_at_idx": { + "name": "automation_events_received_at_idx", + "columns": [ + { + "expression": "received_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "automation_events_organization_id_organizations_id_fk": { + "name": "automation_events_organization_id_organizations_id_fk", + "tableFrom": "automation_events", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "automation_events_dedup_unique": { + "name": "automation_events_dedup_unique", + "nullsNotDistinct": true, + "columns": [ + "integration_connection_id", + "provider", + "external_event_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.automation_prompt_versions": { + "name": "automation_prompt_versions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "automation_id": { + "name": "automation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "author_user_id": { + "name": "author_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "window_bucket": { + "name": "window_bucket", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content_hash": { + "name": "content_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "automation_prompt_source", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "restored_from_version_id": { + "name": "restored_from_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "automation_prompt_versions_bucket_uniq": { + "name": "automation_prompt_versions_bucket_uniq", + "columns": [ + { + "expression": "automation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "author_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "window_bucket", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"automation_prompt_versions\".\"source\" <> 'restore'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_prompt_versions_automation_idx": { + "name": "automation_prompt_versions_automation_idx", + "columns": [ + { + "expression": "automation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "automation_prompt_versions_automation_id_automations_id_fk": { + "name": "automation_prompt_versions_automation_id_automations_id_fk", + "tableFrom": "automation_prompt_versions", + "tableTo": "automations", + "columnsFrom": [ + "automation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "automation_prompt_versions_author_user_id_users_id_fk": { + "name": "automation_prompt_versions_author_user_id_users_id_fk", + "tableFrom": "automation_prompt_versions", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "author_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "automation_prompt_versions_restored_from_version_id_fk": { + "name": "automation_prompt_versions_restored_from_version_id_fk", + "tableFrom": "automation_prompt_versions", + "tableTo": "automation_prompt_versions", + "columnsFrom": [ + "restored_from_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.automation_runs": { + "name": "automation_runs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "automation_id": { + "name": "automation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "trigger_id": { + "name": "trigger_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "event_id": { + "name": "event_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "scheduled_for": { + "name": "scheduled_for", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "resource_key": { + "name": "resource_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "host_id": { + "name": "host_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "v2_workspace_id": { + "name": "v2_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "cloud_workspace_id": { + "name": "cloud_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "session_kind": { + "name": "session_kind", + "type": "automation_session_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "chat_session_id": { + "name": "chat_session_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "terminal_session_id": { + "name": "terminal_session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "automation_run_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_code": { + "name": "error_code", + "type": "automation_run_error_code", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "dispatched_at": { + "name": "dispatched_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "automation_runs_schedule_dedup_idx": { + "name": "automation_runs_schedule_dedup_idx", + "columns": [ + { + "expression": "automation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scheduled_for", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "scheduled_for IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_runs_event_dedup_idx": { + "name": "automation_runs_event_dedup_idx", + "columns": [ + { + "expression": "trigger_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "event_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "event_id IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_runs_inflight_resource_idx": { + "name": "automation_runs_inflight_resource_idx", + "columns": [ + { + "expression": "trigger_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resource_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "status IN ('dispatching', 'dispatched')", + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_runs_history_idx": { + "name": "automation_runs_history_idx", + "columns": [ + { + "expression": "automation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_runs_org_created_idx": { + "name": "automation_runs_org_created_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_runs_status_idx": { + "name": "automation_runs_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_runs_workspace_idx": { + "name": "automation_runs_workspace_idx", + "columns": [ + { + "expression": "v2_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_runs_cloud_workspace_idx": { + "name": "automation_runs_cloud_workspace_idx", + "columns": [ + { + "expression": "cloud_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_runs_event_idx": { + "name": "automation_runs_event_idx", + "columns": [ + { + "expression": "event_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "automation_runs_organization_id_organizations_id_fk": { + "name": "automation_runs_organization_id_organizations_id_fk", + "tableFrom": "automation_runs", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "automation_runs_trigger_id_automation_triggers_id_fk": { + "name": "automation_runs_trigger_id_automation_triggers_id_fk", + "tableFrom": "automation_runs", + "tableTo": "automation_triggers", + "columnsFrom": [ + "trigger_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "automation_runs_event_id_automation_events_id_fk": { + "name": "automation_runs_event_id_automation_events_id_fk", + "tableFrom": "automation_runs", + "tableTo": "automation_events", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "automation_runs_cloud_workspace_id_cloud_workspaces_id_fk": { + "name": "automation_runs_cloud_workspace_id_cloud_workspaces_id_fk", + "tableFrom": "automation_runs", + "tableTo": "cloud_workspaces", + "columnsFrom": [ + "cloud_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "automation_runs_chat_session_id_chat_sessions_id_fk": { + "name": "automation_runs_chat_session_id_chat_sessions_id_fk", + "tableFrom": "automation_runs", + "tableTo": "chat_sessions", + "columnsFrom": [ + "chat_session_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "automation_runs_automation_org_fk": { + "name": "automation_runs_automation_org_fk", + "tableFrom": "automation_runs", + "tableTo": "automations", + "columnsFrom": [ + "automation_id", + "organization_id" + ], + "columnsTo": [ + "id", + "organization_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.automation_triggers": { + "name": "automation_triggers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "automation_id": { + "name": "automation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "automation_trigger_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "next_run_at": { + "name": "next_run_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "secret_hash": { + "name": "secret_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret_prefix": { + "name": "secret_prefix", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret_rotated_at": { + "name": "secret_rotated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "automation_triggers_dispatcher_idx": { + "name": "automation_triggers_dispatcher_idx", + "columns": [ + { + "expression": "next_run_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "kind = 'schedule'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_triggers_matcher_idx": { + "name": "automation_triggers_matcher_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_triggers_automation_idx": { + "name": "automation_triggers_automation_idx", + "columns": [ + { + "expression": "automation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "automation_triggers_schedule_idx": { + "name": "automation_triggers_schedule_idx", + "columns": [ + { + "expression": "automation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "kind = 'schedule'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "automation_triggers_organization_id_organizations_id_fk": { + "name": "automation_triggers_organization_id_organizations_id_fk", + "tableFrom": "automation_triggers", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "automation_triggers_automation_org_fk": { + "name": "automation_triggers_automation_org_fk", + "tableFrom": "automation_triggers", + "tableTo": "automations", + "columnsFrom": [ + "automation_id", + "organization_id" + ], + "columnsTo": [ + "id", + "organization_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "automation_triggers_kind_matches_config": { + "name": "automation_triggers_kind_matches_config", + "value": "config->>'kind' = kind::text" + } + }, + "isRLSEnabled": false + }, + "public.automations": { + "name": "automations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "owner_user_id": { + "name": "owner_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "prompt": { + "name": "prompt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "agent": { + "name": "agent", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "target_host_id": { + "name": "target_host_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "v2_project_id": { + "name": "v2_project_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "v2_workspace_id": { + "name": "v2_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "cloud_workspace_id": { + "name": "cloud_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "tags": { + "name": "tags", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[\"automation\"]'::jsonb" + }, + "continue_agent_session": { + "name": "continue_agent_session", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "machine_size": { + "name": "machine_size", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "automations_owner_idx": { + "name": "automations_owner_idx", + "columns": [ + { + "expression": "owner_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "automations_organization_idx": { + "name": "automations_organization_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "automations_organization_id_organizations_id_fk": { + "name": "automations_organization_id_organizations_id_fk", + "tableFrom": "automations", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "automations_owner_user_id_users_id_fk": { + "name": "automations_owner_user_id_users_id_fk", + "tableFrom": "automations", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "owner_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "automations_cloud_workspace_id_cloud_workspaces_id_fk": { + "name": "automations_cloud_workspace_id_cloud_workspaces_id_fk", + "tableFrom": "automations", + "tableTo": "cloud_workspaces", + "columnsFrom": [ + "cloud_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "automations_environment_id_environments_id_fk": { + "name": "automations_environment_id_environments_id_fk", + "tableFrom": "automations", + "tableTo": "environments", + "columnsFrom": [ + "environment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "automations_id_org_unique": { + "name": "automations_id_org_unique", + "nullsNotDistinct": false, + "columns": [ + "id", + "organization_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chat_sessions": { + "name": "chat_sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_by": { + "name": "created_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "v2_workspace_id": { + "name": "v2_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_active_at": { + "name": "last_active_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "chat_sessions_org_idx": { + "name": "chat_sessions_org_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "chat_sessions_created_by_idx": { + "name": "chat_sessions_created_by_idx", + "columns": [ + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "chat_sessions_last_active_idx": { + "name": "chat_sessions_last_active_idx", + "columns": [ + { + "expression": "last_active_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "chat_sessions_organization_id_organizations_id_fk": { + "name": "chat_sessions_organization_id_organizations_id_fk", + "tableFrom": "chat_sessions", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "chat_sessions_created_by_users_id_fk": { + "name": "chat_sessions_created_by_users_id_fk", + "tableFrom": "chat_sessions", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "chat_sessions_workspace_id_workspaces_id_fk": { + "name": "chat_sessions_workspace_id_workspaces_id_fk", + "tableFrom": "chat_sessions", + "tableTo": "workspaces", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.cloud_workspace_activity": { + "name": "cloud_workspace_activity", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cloud_workspace_id": { + "name": "cloud_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "actor_kind": { + "name": "actor_kind", + "type": "actor_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "actor_user_id": { + "name": "actor_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "event": { + "name": "event", + "type": "cloud_workspace_activity_event", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "from_name": { + "name": "from_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "to_name": { + "name": "to_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "from_visibility": { + "name": "from_visibility", + "type": "cloud_workspace_visibility", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "to_visibility": { + "name": "to_visibility", + "type": "cloud_workspace_visibility", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "target_user_id": { + "name": "target_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "target_team_id": { + "name": "target_team_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "target_email": { + "name": "target_email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "from_project_id": { + "name": "from_project_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "to_project_id": { + "name": "to_project_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "added_label_ids": { + "name": "added_label_ids", + "type": "uuid[]", + "primaryKey": false, + "notNull": false + }, + "removed_label_ids": { + "name": "removed_label_ids", + "type": "uuid[]", + "primaryKey": false, + "notNull": false + }, + "linked_task_id": { + "name": "linked_task_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "unlinked_task_id": { + "name": "unlinked_task_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "pr_url": { + "name": "pr_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "page_id": { + "name": "page_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "suggestion_id": { + "name": "suggestion_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "cloud_workspace_activity_workspace_created_idx": { + "name": "cloud_workspace_activity_workspace_created_idx", + "columns": [ + { + "expression": "cloud_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "cloud_workspace_activity_linked_task_id_idx": { + "name": "cloud_workspace_activity_linked_task_id_idx", + "columns": [ + { + "expression": "linked_task_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "cloud_workspace_activity_unlinked_task_id_idx": { + "name": "cloud_workspace_activity_unlinked_task_id_idx", + "columns": [ + { + "expression": "unlinked_task_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "cloud_workspace_activity_target_user_id_idx": { + "name": "cloud_workspace_activity_target_user_id_idx", + "columns": [ + { + "expression": "target_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "cloud_workspace_activity_target_team_id_idx": { + "name": "cloud_workspace_activity_target_team_id_idx", + "columns": [ + { + "expression": "target_team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "cloud_workspace_activity_cloud_workspace_id_cloud_workspaces_id_fk": { + "name": "cloud_workspace_activity_cloud_workspace_id_cloud_workspaces_id_fk", + "tableFrom": "cloud_workspace_activity", + "tableTo": "cloud_workspaces", + "columnsFrom": [ + "cloud_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "cloud_workspace_activity_actor_user_id_users_id_fk": { + "name": "cloud_workspace_activity_actor_user_id_users_id_fk", + "tableFrom": "cloud_workspace_activity", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "actor_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "cloud_workspace_activity_target_user_id_users_id_fk": { + "name": "cloud_workspace_activity_target_user_id_users_id_fk", + "tableFrom": "cloud_workspace_activity", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "target_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "cloud_workspace_activity_target_team_id_teams_id_fk": { + "name": "cloud_workspace_activity_target_team_id_teams_id_fk", + "tableFrom": "cloud_workspace_activity", + "tableTo": "teams", + "schemaTo": "auth", + "columnsFrom": [ + "target_team_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "cloud_workspace_activity_from_project_id_task_projects_id_fk": { + "name": "cloud_workspace_activity_from_project_id_task_projects_id_fk", + "tableFrom": "cloud_workspace_activity", + "tableTo": "task_projects", + "columnsFrom": [ + "from_project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "cloud_workspace_activity_to_project_id_task_projects_id_fk": { + "name": "cloud_workspace_activity_to_project_id_task_projects_id_fk", + "tableFrom": "cloud_workspace_activity", + "tableTo": "task_projects", + "columnsFrom": [ + "to_project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "cloud_workspace_activity_linked_task_id_tasks_id_fk": { + "name": "cloud_workspace_activity_linked_task_id_tasks_id_fk", + "tableFrom": "cloud_workspace_activity", + "tableTo": "tasks", + "columnsFrom": [ + "linked_task_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "cloud_workspace_activity_unlinked_task_id_tasks_id_fk": { + "name": "cloud_workspace_activity_unlinked_task_id_tasks_id_fk", + "tableFrom": "cloud_workspace_activity", + "tableTo": "tasks", + "columnsFrom": [ + "unlinked_task_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "cloud_workspace_activity_page_id_pages_id_fk": { + "name": "cloud_workspace_activity_page_id_pages_id_fk", + "tableFrom": "cloud_workspace_activity", + "tableTo": "pages", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "cloud_workspace_activity_suggestion_id_suggestions_id_fk": { + "name": "cloud_workspace_activity_suggestion_id_suggestions_id_fk", + "tableFrom": "cloud_workspace_activity", + "tableTo": "suggestions", + "columnsFrom": [ + "suggestion_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.cloud_workspace_boots": { + "name": "cloud_workspace_boots", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "vercel_session_id": { + "name": "vercel_session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "cloud_workspace_id": { + "name": "cloud_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "memory_mb": { + "name": "memory_mb", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "vcpus": { + "name": "vcpus", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "started_at": { + "name": "started_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "stopped_at": { + "name": "stopped_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "lock_seq": { + "name": "lock_seq", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "lock_open": { + "name": "lock_open", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "finalized_through": { + "name": "finalized_through", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "settle_lease_until": { + "name": "settle_lease_until", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "cloud_workspace_boots_cloud_workspace_id_idx": { + "name": "cloud_workspace_boots_cloud_workspace_id_idx", + "columns": [ + { + "expression": "cloud_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "cloud_workspace_boots_organization_id_idx": { + "name": "cloud_workspace_boots_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "cloud_workspace_boots_open_idx": { + "name": "cloud_workspace_boots_open_idx", + "columns": [ + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"cloud_workspace_boots\".\"stopped_at\" is null or \"cloud_workspace_boots\".\"finalized_through\" is null or \"cloud_workspace_boots\".\"finalized_through\" < \"cloud_workspace_boots\".\"stopped_at\"", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "cloud_workspace_boots_cloud_workspace_id_cloud_workspaces_id_fk": { + "name": "cloud_workspace_boots_cloud_workspace_id_cloud_workspaces_id_fk", + "tableFrom": "cloud_workspace_boots", + "tableTo": "cloud_workspaces", + "columnsFrom": [ + "cloud_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "cloud_workspace_boots_vercel_session_id_unique": { + "name": "cloud_workspace_boots_vercel_session_id_unique", + "nullsNotDistinct": false, + "columns": [ + "vercel_session_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.cloud_workspace_labels": { + "name": "cloud_workspace_labels", + "schema": "", + "columns": { + "cloud_workspace_id": { + "name": "cloud_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "label_id": { + "name": "label_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "cloud_workspace_labels_label_id_idx": { + "name": "cloud_workspace_labels_label_id_idx", + "columns": [ + { + "expression": "label_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "cloud_workspace_labels_cloud_workspace_id_cloud_workspaces_id_fk": { + "name": "cloud_workspace_labels_cloud_workspace_id_cloud_workspaces_id_fk", + "tableFrom": "cloud_workspace_labels", + "tableTo": "cloud_workspaces", + "columnsFrom": [ + "cloud_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "cloud_workspace_labels_label_id_task_labels_id_fk": { + "name": "cloud_workspace_labels_label_id_task_labels_id_fk", + "tableFrom": "cloud_workspace_labels", + "tableTo": "task_labels", + "columnsFrom": [ + "label_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "cloud_workspace_labels_cloud_workspace_id_label_id_pk": { + "name": "cloud_workspace_labels_cloud_workspace_id_label_id_pk", + "columns": [ + "cloud_workspace_id", + "label_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.cloud_workspace_pull_requests": { + "name": "cloud_workspace_pull_requests", + "schema": "", + "columns": { + "cloud_workspace_id": { + "name": "cloud_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "repository_id": { + "name": "repository_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "pr_number": { + "name": "pr_number", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "linked_at": { + "name": "linked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "cloud_workspace_pull_requests_repository_id_idx": { + "name": "cloud_workspace_pull_requests_repository_id_idx", + "columns": [ + { + "expression": "repository_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "cloud_workspace_pull_requests_cloud_workspace_id_cloud_workspaces_id_fk": { + "name": "cloud_workspace_pull_requests_cloud_workspace_id_cloud_workspaces_id_fk", + "tableFrom": "cloud_workspace_pull_requests", + "tableTo": "cloud_workspaces", + "columnsFrom": [ + "cloud_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "cloud_workspace_pull_requests_repository_id_github_repositories_id_fk": { + "name": "cloud_workspace_pull_requests_repository_id_github_repositories_id_fk", + "tableFrom": "cloud_workspace_pull_requests", + "tableTo": "github_repositories", + "columnsFrom": [ + "repository_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "cloud_workspace_pull_requests_pk": { + "name": "cloud_workspace_pull_requests_pk", + "columns": [ + "cloud_workspace_id", + "repository_id", + "pr_number" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.cloud_workspace_repositories": { + "name": "cloud_workspace_repositories", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cloud_workspace_id": { + "name": "cloud_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "repository_id": { + "name": "repository_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "cloud_workspace_repositories_cloud_workspace_id_idx": { + "name": "cloud_workspace_repositories_cloud_workspace_id_idx", + "columns": [ + { + "expression": "cloud_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "cloud_workspace_repositories_cloud_workspace_id_cloud_workspaces_id_fk": { + "name": "cloud_workspace_repositories_cloud_workspace_id_cloud_workspaces_id_fk", + "tableFrom": "cloud_workspace_repositories", + "tableTo": "cloud_workspaces", + "columnsFrom": [ + "cloud_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "cloud_workspace_repositories_repository_id_github_repositories_id_fk": { + "name": "cloud_workspace_repositories_repository_id_github_repositories_id_fk", + "tableFrom": "cloud_workspace_repositories", + "tableTo": "github_repositories", + "columnsFrom": [ + "repository_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "cloud_workspace_repositories_workspace_repository_unique": { + "name": "cloud_workspace_repositories_workspace_repository_unique", + "nullsNotDistinct": false, + "columns": [ + "cloud_workspace_id", + "repository_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.cloud_workspace_shares": { + "name": "cloud_workspace_shares", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "invitation_id": { + "name": "invitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "shared_by_user_id": { + "name": "shared_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "cloud_workspace_id": { + "name": "cloud_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "cloud_workspace_shares_user_unique": { + "name": "cloud_workspace_shares_user_unique", + "columns": [ + { + "expression": "cloud_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "cloud_workspace_shares_team_unique": { + "name": "cloud_workspace_shares_team_unique", + "columns": [ + { + "expression": "cloud_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "cloud_workspace_shares_invitation_unique": { + "name": "cloud_workspace_shares_invitation_unique", + "columns": [ + { + "expression": "cloud_workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "invitation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "cloud_workspace_shares_user_id_idx": { + "name": "cloud_workspace_shares_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "cloud_workspace_shares_team_id_idx": { + "name": "cloud_workspace_shares_team_id_idx", + "columns": [ + { + "expression": "team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "cloud_workspace_shares_invitation_id_idx": { + "name": "cloud_workspace_shares_invitation_id_idx", + "columns": [ + { + "expression": "invitation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "cloud_workspace_shares_shared_by_user_id_idx": { + "name": "cloud_workspace_shares_shared_by_user_id_idx", + "columns": [ + { + "expression": "shared_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "cloud_workspace_shares_user_id_users_id_fk": { + "name": "cloud_workspace_shares_user_id_users_id_fk", + "tableFrom": "cloud_workspace_shares", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "cloud_workspace_shares_team_id_teams_id_fk": { + "name": "cloud_workspace_shares_team_id_teams_id_fk", + "tableFrom": "cloud_workspace_shares", + "tableTo": "teams", + "schemaTo": "auth", + "columnsFrom": [ + "team_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "cloud_workspace_shares_invitation_id_invitations_id_fk": { + "name": "cloud_workspace_shares_invitation_id_invitations_id_fk", + "tableFrom": "cloud_workspace_shares", + "tableTo": "invitations", + "schemaTo": "auth", + "columnsFrom": [ + "invitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "cloud_workspace_shares_shared_by_user_id_users_id_fk": { + "name": "cloud_workspace_shares_shared_by_user_id_users_id_fk", + "tableFrom": "cloud_workspace_shares", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "shared_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "cloud_workspace_shares_cloud_workspace_id_cloud_workspaces_id_fk": { + "name": "cloud_workspace_shares_cloud_workspace_id_cloud_workspaces_id_fk", + "tableFrom": "cloud_workspace_shares", + "tableTo": "cloud_workspaces", + "columnsFrom": [ + "cloud_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "cloud_workspace_shares_one_grantee": { + "name": "cloud_workspace_shares_one_grantee", + "value": "num_nonnulls(user_id, team_id, invitation_id) = 1" + } + }, + "isRLSEnabled": false + }, + "public.cloud_workspace_tags": { + "name": "cloud_workspace_tags", + "schema": "", + "columns": { + "cloud_workspace_id": { + "name": "cloud_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "tag": { + "name": "tag", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "cloud_workspace_tags_cloud_workspace_id_cloud_workspaces_id_fk": { + "name": "cloud_workspace_tags_cloud_workspace_id_cloud_workspaces_id_fk", + "tableFrom": "cloud_workspace_tags", + "tableTo": "cloud_workspaces", + "columnsFrom": [ + "cloud_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "cloud_workspace_tags_created_by_user_id_users_id_fk": { + "name": "cloud_workspace_tags_created_by_user_id_users_id_fk", + "tableFrom": "cloud_workspace_tags", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "cloud_workspace_tags_cloud_workspace_id_tag_created_by_user_id_pk": { + "name": "cloud_workspace_tags_cloud_workspace_id_tag_created_by_user_id_pk", + "columns": [ + "cloud_workspace_id", + "tag", + "created_by_user_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.cloud_workspace_tasks": { + "name": "cloud_workspace_tasks", + "schema": "", + "columns": { + "cloud_workspace_id": { + "name": "cloud_workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "task_id": { + "name": "task_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "linked_by_kind": { + "name": "linked_by_kind", + "type": "actor_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "linked_by_user_id": { + "name": "linked_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "cloud_workspace_tasks_task_id_idx": { + "name": "cloud_workspace_tasks_task_id_idx", + "columns": [ + { + "expression": "task_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "cloud_workspace_tasks_cloud_workspace_id_cloud_workspaces_id_fk": { + "name": "cloud_workspace_tasks_cloud_workspace_id_cloud_workspaces_id_fk", + "tableFrom": "cloud_workspace_tasks", + "tableTo": "cloud_workspaces", + "columnsFrom": [ + "cloud_workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "cloud_workspace_tasks_task_id_tasks_id_fk": { + "name": "cloud_workspace_tasks_task_id_tasks_id_fk", + "tableFrom": "cloud_workspace_tasks", + "tableTo": "tasks", + "columnsFrom": [ + "task_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "cloud_workspace_tasks_linked_by_user_id_users_id_fk": { + "name": "cloud_workspace_tasks_linked_by_user_id_users_id_fk", + "tableFrom": "cloud_workspace_tasks", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "linked_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "cloud_workspace_tasks_cloud_workspace_id_task_id_pk": { + "name": "cloud_workspace_tasks_cloud_workspace_id_task_id_pk", + "columns": [ + "cloud_workspace_id", + "task_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.cloud_workspaces": { + "name": "cloud_workspaces", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "base_branch": { + "name": "base_branch", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'vercel'" + }, + "provider_sandbox_id": { + "name": "provider_sandbox_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sandbox_url": { + "name": "sandbox_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "cloud_workspace_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'provisioning'" + }, + "visibility": { + "name": "visibility", + "type": "cloud_workspace_visibility", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'org'" + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "host_version": { + "name": "host_version", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "boot_agent_credential_digest": { + "name": "boot_agent_credential_digest", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "agent_status": { + "name": "agent_status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "agent_status_at": { + "name": "agent_status_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "prompt": { + "name": "prompt", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "usage_stop_at": { + "name": "usage_stop_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "machine_size": { + "name": "machine_size", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "cloud_workspaces_organization_id_idx": { + "name": "cloud_workspaces_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "cloud_workspaces_organization_id_organizations_id_fk": { + "name": "cloud_workspaces_organization_id_organizations_id_fk", + "tableFrom": "cloud_workspaces", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "cloud_workspaces_environment_id_environments_id_fk": { + "name": "cloud_workspaces_environment_id_environments_id_fk", + "tableFrom": "cloud_workspaces", + "tableTo": "environments", + "columnsFrom": [ + "environment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "cloud_workspaces_project_id_task_projects_id_fk": { + "name": "cloud_workspaces_project_id_task_projects_id_fk", + "tableFrom": "cloud_workspaces", + "tableTo": "task_projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "cloud_workspaces_created_by_user_id_users_id_fk": { + "name": "cloud_workspaces_created_by_user_id_users_id_fk", + "tableFrom": "cloud_workspaces", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "cloud_workspaces_provider_sandbox_id_unique": { + "name": "cloud_workspaces_provider_sandbox_id_unique", + "nullsNotDistinct": false, + "columns": [ + "provider", + "provider_sandbox_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.connections": { + "name": "connections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "connected_by_user_id": { + "name": "connected_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "connector": { + "name": "connector", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "owner_kind": { + "name": "owner_kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "auth_method": { + "name": "auth_method", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "token_expires_at": { + "name": "token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scopes": { + "name": "scopes", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "issuer": { + "name": "issuer", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resource": { + "name": "resource", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "external_account_id": { + "name": "external_account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "external_account_label": { + "name": "external_account_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "external_user_id": { + "name": "external_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "external_user_label": { + "name": "external_user_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "nickname": { + "name": "nickname", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "disconnected_at": { + "name": "disconnected_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "disconnect_reason": { + "name": "disconnect_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "connections_org_connector_unique": { + "name": "connections_org_connector_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connector", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connections\".\"owner_kind\" = 'org'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "connections_user_connector_unique": { + "name": "connections_user_connector_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connector", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connected_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "external_account_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"connections\".\"owner_kind\" = 'user'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "connections_org_idx": { + "name": "connections_org_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "connections_user_connector_idx": { + "name": "connections_user_connector_idx", + "columns": [ + { + "expression": "connected_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connector", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"connections\".\"disconnected_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "connections_external_account_idx": { + "name": "connections_external_account_idx", + "columns": [ + { + "expression": "connector", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "external_account_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "connections_organization_id_organizations_id_fk": { + "name": "connections_organization_id_organizations_id_fk", + "tableFrom": "connections", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "connections_connected_by_user_id_users_id_fk": { + "name": "connections_connected_by_user_id_users_id_fk", + "tableFrom": "connections", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "connected_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "connections_user_identity_present": { + "name": "connections_user_identity_present", + "value": "owner_kind <> 'user' OR external_user_id IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.deal_redemptions": { + "name": "deal_redemptions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "external_redemption_id": { + "name": "external_redemption_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "deal_id": { + "name": "deal_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "company_name": { + "name": "company_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "company_batch": { + "name": "company_batch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "promotion_code": { + "name": "promotion_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "deal_redemptions_source_external_id_unique": { + "name": "deal_redemptions_source_external_id_unique", + "columns": [ + { + "expression": "source", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "external_redemption_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "deal_redemptions_email_idx": { + "name": "deal_redemptions_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "deal_redemptions_organization_id_organizations_id_fk": { + "name": "deal_redemptions_organization_id_organizations_id_fk", + "tableFrom": "deal_redemptions", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.desktop_notices": { + "name": "desktop_notices", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "severity": { + "name": "severity", + "type": "desktop_notice_severity", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "trigger": { + "name": "trigger", + "type": "desktop_notice_trigger", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'immediate'" + }, + "min_version": { + "name": "min_version", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "max_version": { + "name": "max_version", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "platforms": { + "name": "platforms", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "channels": { + "name": "channels", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "starts_at": { + "name": "starts_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "ends_at": { + "name": "ends_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "body": { + "name": "body", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "cta_label": { + "name": "cta_label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cta_action": { + "name": "cta_action", + "type": "desktop_notice_cta_action", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "cta_url": { + "name": "cta_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "dismissible": { + "name": "dismissible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "desktop_notices_active_idx": { + "name": "desktop_notices_active_idx", + "columns": [ + { + "expression": "active", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.environment_projects": { + "name": "environment_projects", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "environment_projects_project_id_idx": { + "name": "environment_projects_project_id_idx", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environment_projects_organization_id_organizations_id_fk": { + "name": "environment_projects_organization_id_organizations_id_fk", + "tableFrom": "environment_projects", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_projects_environment_id_environments_id_fk": { + "name": "environment_projects_environment_id_environments_id_fk", + "tableFrom": "environment_projects", + "tableTo": "environments", + "columnsFrom": [ + "environment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "environment_projects_environment_id_project_id_unique": { + "name": "environment_projects_environment_id_project_id_unique", + "nullsNotDistinct": false, + "columns": [ + "environment_id", + "project_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.environment_repositories": { + "name": "environment_repositories", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "repository_id": { + "name": "repository_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "environment_repositories_environment_id_idx": { + "name": "environment_repositories_environment_id_idx", + "columns": [ + { + "expression": "environment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environment_repositories_environment_id_environments_id_fk": { + "name": "environment_repositories_environment_id_environments_id_fk", + "tableFrom": "environment_repositories", + "tableTo": "environments", + "columnsFrom": [ + "environment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_repositories_repository_id_github_repositories_id_fk": { + "name": "environment_repositories_repository_id_github_repositories_id_fk", + "tableFrom": "environment_repositories", + "tableTo": "github_repositories", + "columnsFrom": [ + "repository_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "environment_repositories_environment_id_repository_id_unique": { + "name": "environment_repositories_environment_id_repository_id_unique", + "nullsNotDistinct": false, + "columns": [ + "environment_id", + "repository_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.environment_secrets": { + "name": "environment_secrets", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "environment_id": { + "name": "environment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "encrypted_value": { + "name": "encrypted_value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sensitive": { + "name": "sensitive", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "environment_secrets_environment_id_idx": { + "name": "environment_secrets_environment_id_idx", + "columns": [ + { + "expression": "environment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "environment_secrets_organization_id_idx": { + "name": "environment_secrets_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environment_secrets_organization_id_organizations_id_fk": { + "name": "environment_secrets_organization_id_organizations_id_fk", + "tableFrom": "environment_secrets", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_secrets_environment_id_environments_id_fk": { + "name": "environment_secrets_environment_id_environments_id_fk", + "tableFrom": "environment_secrets", + "tableTo": "environments", + "columnsFrom": [ + "environment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environment_secrets_created_by_user_id_users_id_fk": { + "name": "environment_secrets_created_by_user_id_users_id_fk", + "tableFrom": "environment_secrets", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "environment_secrets_environment_id_organization_id_key_unique": { + "name": "environment_secrets_environment_id_organization_id_key_unique", + "nullsNotDistinct": false, + "columns": [ + "environment_id", + "organization_id", + "key" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.environments": { + "name": "environments", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'vercel'" + }, + "source_kind": { + "name": "source_kind", + "type": "environment_source_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "source_ref": { + "name": "source_ref", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "region": { + "name": "region", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'sfo1'" + }, + "bundle_sha": { + "name": "bundle_sha", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "primary_repository_id": { + "name": "primary_repository_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "environment_scope", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'organization'" + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "environments_organization_id_idx": { + "name": "environments_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "environments_organization_id_organizations_id_fk": { + "name": "environments_organization_id_organizations_id_fk", + "tableFrom": "environments", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "environments_primary_repository_id_github_repositories_id_fk": { + "name": "environments_primary_repository_id_github_repositories_id_fk", + "tableFrom": "environments", + "tableTo": "github_repositories", + "columnsFrom": [ + "primary_repository_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "environments_created_by_user_id_users_id_fk": { + "name": "environments_created_by_user_id_users_id_fk", + "tableFrom": "environments", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.files": { + "name": "files", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content_type": { + "name": "content_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size_bytes": { + "name": "size_bytes", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "sha256": { + "name": "sha256", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "file_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "files_organization_id_created_at_idx": { + "name": "files_organization_id_created_at_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "\"created_at\" desc", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "files_status_created_at_idx": { + "name": "files_status_created_at_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "files_organization_id_organizations_id_fk": { + "name": "files_organization_id_organizations_id_fk", + "tableFrom": "files", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "files_created_by_user_id_users_id_fk": { + "name": "files_created_by_user_id_users_id_fk", + "tableFrom": "files", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.github_user_connections": { + "name": "github_user_connections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "github_user_id": { + "name": "github_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "login": { + "name": "login", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_access_token": { + "name": "encrypted_access_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "encrypted_refresh_token": { + "name": "encrypted_refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "github_user_connections_user_id_users_id_fk": { + "name": "github_user_connections_user_id_users_id_fk", + "tableFrom": "github_user_connections", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "github_user_connections_user_id_unique": { + "name": "github_user_connections_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.integration_connections": { + "name": "integration_connections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "connected_by_user_id": { + "name": "connected_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "integration_provider", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "token_expires_at": { + "name": "token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "disconnected_at": { + "name": "disconnected_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "disconnect_reason": { + "name": "disconnect_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "external_org_id": { + "name": "external_org_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "external_org_name": { + "name": "external_org_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "integration_connections_org_provider_unique": { + "name": "integration_connections_org_provider_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"integration_connections\".\"provider\" <> 'google'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "integration_connections_google_user_unique": { + "name": "integration_connections_google_user_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "connected_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"integration_connections\".\"provider\" = 'google'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "integration_connections_slack_external_org_active_unique": { + "name": "integration_connections_slack_external_org_active_unique", + "columns": [ + { + "expression": "external_org_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"integration_connections\".\"provider\" = 'slack' AND \"integration_connections\".\"disconnected_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "integration_connections_org_idx": { + "name": "integration_connections_org_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "integration_connections_organization_id_organizations_id_fk": { + "name": "integration_connections_organization_id_organizations_id_fk", + "tableFrom": "integration_connections", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "integration_connections_connected_by_user_id_users_id_fk": { + "name": "integration_connections_connected_by_user_id_users_id_fk", + "tableFrom": "integration_connections", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "connected_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.page_comment_reads": { + "name": "page_comment_reads", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "page_id": { + "name": "page_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "last_seen_at": { + "name": "last_seen_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "page_comment_reads_page_id_idx": { + "name": "page_comment_reads_page_id_idx", + "columns": [ + { + "expression": "page_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "page_comment_reads_user_id_users_id_fk": { + "name": "page_comment_reads_user_id_users_id_fk", + "tableFrom": "page_comment_reads", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_comment_reads_page_id_pages_id_fk": { + "name": "page_comment_reads_page_id_pages_id_fk", + "tableFrom": "page_comment_reads", + "tableTo": "pages", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "page_comment_reads_user_id_page_id_pk": { + "name": "page_comment_reads_user_id_page_id_pk", + "columns": [ + "user_id", + "page_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.page_comment_threads": { + "name": "page_comment_threads", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "page_id": { + "name": "page_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "page_version_id": { + "name": "page_version_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "anchor_kind": { + "name": "anchor_kind", + "type": "page_comment_anchor_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "intent": { + "name": "intent", + "type": "page_comment_intent", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "anchor": { + "name": "anchor", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "anchor_text": { + "name": "anchor_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "agent_activated_at": { + "name": "agent_activated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "agent_activated_by_user_id": { + "name": "agent_activated_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "resolved_at": { + "name": "resolved_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "resolved_by_user_id": { + "name": "resolved_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "page_comment_threads_page_id_idx": { + "name": "page_comment_threads_page_id_idx", + "columns": [ + { + "expression": "page_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_comment_threads_page_version_id_idx": { + "name": "page_comment_threads_page_version_id_idx", + "columns": [ + { + "expression": "page_version_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_comment_threads_open_idx": { + "name": "page_comment_threads_open_idx", + "columns": [ + { + "expression": "page_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "resolved_at IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "page_comment_threads_page_id_pages_id_fk": { + "name": "page_comment_threads_page_id_pages_id_fk", + "tableFrom": "page_comment_threads", + "tableTo": "pages", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_comment_threads_page_version_id_page_versions_id_fk": { + "name": "page_comment_threads_page_version_id_page_versions_id_fk", + "tableFrom": "page_comment_threads", + "tableTo": "page_versions", + "columnsFrom": [ + "page_version_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_comment_threads_created_by_user_id_users_id_fk": { + "name": "page_comment_threads_created_by_user_id_users_id_fk", + "tableFrom": "page_comment_threads", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "page_comment_threads_agent_activated_by_user_id_users_id_fk": { + "name": "page_comment_threads_agent_activated_by_user_id_users_id_fk", + "tableFrom": "page_comment_threads", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "agent_activated_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "page_comment_threads_resolved_by_user_id_users_id_fk": { + "name": "page_comment_threads_resolved_by_user_id_users_id_fk", + "tableFrom": "page_comment_threads", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "resolved_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "page_comment_threads_anchor_matches_kind": { + "name": "page_comment_threads_anchor_matches_kind", + "value": "(anchor_kind = 'page') = (anchor IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.page_comments": { + "name": "page_comments", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "thread_id": { + "name": "thread_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "author_kind": { + "name": "author_kind", + "type": "page_comment_author_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'human'" + }, + "author_user_id": { + "name": "author_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "agent_session_id": { + "name": "agent_session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "body": { + "name": "body", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "page_comments_thread_id_created_at_idx": { + "name": "page_comments_thread_id_created_at_idx", + "columns": [ + { + "expression": "thread_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "page_comments_thread_id_page_comment_threads_id_fk": { + "name": "page_comments_thread_id_page_comment_threads_id_fk", + "tableFrom": "page_comments", + "tableTo": "page_comment_threads", + "columnsFrom": [ + "thread_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_comments_author_user_id_users_id_fk": { + "name": "page_comments_author_user_id_users_id_fk", + "tableFrom": "page_comments", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "author_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "page_comments_agent_has_session": { + "name": "page_comments_agent_has_session", + "value": "author_kind <> 'agent' OR agent_session_id IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.page_reports": { + "name": "page_reports", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "page_id": { + "name": "page_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "reported_version": { + "name": "reported_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "details": { + "name": "details", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "page_report_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'open'" + }, + "reported_by_user_id": { + "name": "reported_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "reporter_email": { + "name": "reporter_email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reporter_ip_hash": { + "name": "reporter_ip_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reviewed_by_user_id": { + "name": "reviewed_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "reviewed_at": { + "name": "reviewed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "review_note": { + "name": "review_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "page_reports_status_created_at_idx": { + "name": "page_reports_status_created_at_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "\"created_at\" desc", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_reports_page_id_idx": { + "name": "page_reports_page_id_idx", + "columns": [ + { + "expression": "page_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_reports_reporter_ip_hash_idx": { + "name": "page_reports_reporter_ip_hash_idx", + "columns": [ + { + "expression": "reporter_ip_hash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "page_reports_page_id_pages_id_fk": { + "name": "page_reports_page_id_pages_id_fk", + "tableFrom": "page_reports", + "tableTo": "pages", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_reports_reported_by_user_id_users_id_fk": { + "name": "page_reports_reported_by_user_id_users_id_fk", + "tableFrom": "page_reports", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "reported_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "page_reports_reviewed_by_user_id_users_id_fk": { + "name": "page_reports_reviewed_by_user_id_users_id_fk", + "tableFrom": "page_reports", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "reviewed_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.page_shares": { + "name": "page_shares", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "invitation_id": { + "name": "invitation_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "shared_by_user_id": { + "name": "shared_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "page_id": { + "name": "page_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "page_share_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'comment'" + } + }, + "indexes": { + "page_shares_user_unique": { + "name": "page_shares_user_unique", + "columns": [ + { + "expression": "page_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_shares_team_unique": { + "name": "page_shares_team_unique", + "columns": [ + { + "expression": "page_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_shares_invitation_unique": { + "name": "page_shares_invitation_unique", + "columns": [ + { + "expression": "page_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "invitation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_shares_user_id_idx": { + "name": "page_shares_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_shares_team_id_idx": { + "name": "page_shares_team_id_idx", + "columns": [ + { + "expression": "team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_shares_invitation_id_idx": { + "name": "page_shares_invitation_id_idx", + "columns": [ + { + "expression": "invitation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "page_shares_shared_by_user_id_idx": { + "name": "page_shares_shared_by_user_id_idx", + "columns": [ + { + "expression": "shared_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "page_shares_user_id_users_id_fk": { + "name": "page_shares_user_id_users_id_fk", + "tableFrom": "page_shares", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_shares_team_id_teams_id_fk": { + "name": "page_shares_team_id_teams_id_fk", + "tableFrom": "page_shares", + "tableTo": "teams", + "schemaTo": "auth", + "columnsFrom": [ + "team_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_shares_invitation_id_invitations_id_fk": { + "name": "page_shares_invitation_id_invitations_id_fk", + "tableFrom": "page_shares", + "tableTo": "invitations", + "schemaTo": "auth", + "columnsFrom": [ + "invitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_shares_shared_by_user_id_users_id_fk": { + "name": "page_shares_shared_by_user_id_users_id_fk", + "tableFrom": "page_shares", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "shared_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "page_shares_page_id_pages_id_fk": { + "name": "page_shares_page_id_pages_id_fk", + "tableFrom": "page_shares", + "tableTo": "pages", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "page_shares_one_grantee": { + "name": "page_shares_one_grantee", + "value": "num_nonnulls(user_id, team_id, invitation_id) = 1" + } + }, + "isRLSEnabled": false + }, + "public.page_tool_grants": { + "name": "page_tool_grants", + "schema": "", + "columns": { + "page_id": { + "name": "page_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "plugin": { + "name": "plugin", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "connection_id": { + "name": "connection_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "page_tool_grants_user_id_idx": { + "name": "page_tool_grants_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "page_tool_grants_page_id_pages_id_fk": { + "name": "page_tool_grants_page_id_pages_id_fk", + "tableFrom": "page_tool_grants", + "tableTo": "pages", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_tool_grants_user_id_users_id_fk": { + "name": "page_tool_grants_user_id_users_id_fk", + "tableFrom": "page_tool_grants", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "page_tool_grants_page_id_user_id_plugin_pk": { + "name": "page_tool_grants_page_id_user_id_plugin_pk", + "columns": [ + "page_id", + "user_id", + "plugin" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.page_versions": { + "name": "page_versions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "page_id": { + "name": "page_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "storage_key": { + "name": "storage_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content_type": { + "name": "content_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size_bytes": { + "name": "size_bytes", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "sha256": { + "name": "sha256", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "page_versions_page_id_idx": { + "name": "page_versions_page_id_idx", + "columns": [ + { + "expression": "page_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "page_versions_page_id_pages_id_fk": { + "name": "page_versions_page_id_pages_id_fk", + "tableFrom": "page_versions", + "tableTo": "pages", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "page_versions_created_by_user_id_users_id_fk": { + "name": "page_versions_created_by_user_id_users_id_fk", + "tableFrom": "page_versions", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "page_versions_page_id_version_unique": { + "name": "page_versions_page_id_version_unique", + "nullsNotDistinct": false, + "columns": [ + "page_id", + "version" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages": { + "name": "pages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "visibility": { + "name": "visibility", + "type": "page_visibility", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'just_me'" + }, + "organization_role": { + "name": "organization_role", + "type": "page_share_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'comment'" + }, + "shared_version": { + "name": "shared_version", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "taken_down_at": { + "name": "taken_down_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "taken_down_by_user_id": { + "name": "taken_down_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "taken_down_note": { + "name": "taken_down_note", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "watched_by_agent": { + "name": "watched_by_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "watch_state": { + "name": "watch_state", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "watch_heartbeat_at": { + "name": "watch_heartbeat_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "pages_slug_unique": { + "name": "pages_slug_unique", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_organization_id_created_at_id_idx": { + "name": "pages_organization_id_created_at_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "\"created_at\" desc", + "asc": true, + "isExpression": true, + "nulls": "last" + }, + { + "expression": "\"id\" desc", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_created_by_user_id_idx": { + "name": "pages_created_by_user_id_idx", + "columns": [ + { + "expression": "created_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_organization_id_organizations_id_fk": { + "name": "pages_organization_id_organizations_id_fk", + "tableFrom": "pages", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "pages_created_by_user_id_users_id_fk": { + "name": "pages_created_by_user_id_users_id_fk", + "tableFrom": "pages", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "pages_taken_down_by_user_id_users_id_fk": { + "name": "pages_taken_down_by_user_id_users_id_fk", + "tableFrom": "pages", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "taken_down_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.projects": { + "name": "projects", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "github_repository_id": { + "name": "github_repository_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "repo_owner": { + "name": "repo_owner", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "repo_name": { + "name": "repo_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "repo_url": { + "name": "repo_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "default_branch": { + "name": "default_branch", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'main'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "projects_organization_id_idx": { + "name": "projects_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "projects_organization_id_organizations_id_fk": { + "name": "projects_organization_id_organizations_id_fk", + "tableFrom": "projects", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "projects_github_repository_id_github_repositories_id_fk": { + "name": "projects_github_repository_id_github_repositories_id_fk", + "tableFrom": "projects", + "tableTo": "github_repositories", + "columnsFrom": [ + "github_repository_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "projects_org_slug_unique": { + "name": "projects_org_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "organization_id", + "slug" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sandbox_bundles": { + "name": "sandbox_bundles", + "schema": "", + "columns": { + "sha": { + "name": "sha", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "image_ref": { + "name": "image_ref", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "released_at": { + "name": "released_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.submitted_prompts": { + "name": "submitted_prompts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "prompt_text": { + "name": "prompt_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "submitter_name": { + "name": "submitter_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "submitted_prompts_user_id_idx": { + "name": "submitted_prompts_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "submitted_prompts_organization_id_idx": { + "name": "submitted_prompts_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "submitted_prompts_created_at_idx": { + "name": "submitted_prompts_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "submitted_prompts_user_id_users_id_fk": { + "name": "submitted_prompts_user_id_users_id_fk", + "tableFrom": "submitted_prompts", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "submitted_prompts_organization_id_organizations_id_fk": { + "name": "submitted_prompts_organization_id_organizations_id_fk", + "tableFrom": "submitted_prompts", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.subscriptions": { + "name": "subscriptions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "plan": { + "name": "plan", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reference_id": { + "name": "reference_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'incomplete'" + }, + "period_start": { + "name": "period_start", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "period_end": { + "name": "period_end", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "trial_start": { + "name": "trial_start", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "trial_end": { + "name": "trial_end", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "cancel_at": { + "name": "cancel_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "canceled_at": { + "name": "canceled_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "ended_at": { + "name": "ended_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "seats": { + "name": "seats", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "billing_interval": { + "name": "billing_interval", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_schedule_id": { + "name": "stripe_schedule_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "subscriptions_reference_id_idx": { + "name": "subscriptions_reference_id_idx", + "columns": [ + { + "expression": "reference_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "subscriptions_stripe_customer_id_idx": { + "name": "subscriptions_stripe_customer_id_idx", + "columns": [ + { + "expression": "stripe_customer_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "subscriptions_status_idx": { + "name": "subscriptions_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "subscriptions_reference_id_organizations_id_fk": { + "name": "subscriptions_reference_id_organizations_id_fk", + "tableFrom": "subscriptions", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "reference_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.suggestions": { + "name": "suggestions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "suggestion_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "subject_type": { + "name": "subject_type", + "type": "suggestion_entity", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "subject_id": { + "name": "subject_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "object_type": { + "name": "object_type", + "type": "suggestion_entity", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "object_id": { + "name": "object_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "payload": { + "name": "payload", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "suggestion_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "proposed_by_kind": { + "name": "proposed_by_kind", + "type": "actor_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "proposed_by_user_id": { + "name": "proposed_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "automation_id": { + "name": "automation_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "decided_by_user_id": { + "name": "decided_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "decided_at": { + "name": "decided_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "suggestions_kind_subject_object_unique": { + "name": "suggestions_kind_subject_object_unique", + "columns": [ + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "subject_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "subject_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "object_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "object_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "suggestions_subject_status_idx": { + "name": "suggestions_subject_status_idx", + "columns": [ + { + "expression": "subject_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "subject_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "suggestions_organization_id_status_idx": { + "name": "suggestions_organization_id_status_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "suggestions_organization_id_organizations_id_fk": { + "name": "suggestions_organization_id_organizations_id_fk", + "tableFrom": "suggestions", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "suggestions_proposed_by_user_id_users_id_fk": { + "name": "suggestions_proposed_by_user_id_users_id_fk", + "tableFrom": "suggestions", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "proposed_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "suggestions_automation_id_automations_id_fk": { + "name": "suggestions_automation_id_automations_id_fk", + "tableFrom": "suggestions", + "tableTo": "automations", + "columnsFrom": [ + "automation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "suggestions_decided_by_user_id_users_id_fk": { + "name": "suggestions_decided_by_user_id_users_id_fk", + "tableFrom": "suggestions", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "decided_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.task_activity": { + "name": "task_activity", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "task_id": { + "name": "task_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "actor_kind": { + "name": "actor_kind", + "type": "actor_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "actor_user_id": { + "name": "actor_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "from_title": { + "name": "from_title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "to_title": { + "name": "to_title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "from_status_id": { + "name": "from_status_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "to_status_id": { + "name": "to_status_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "from_priority": { + "name": "from_priority", + "type": "task_priority", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "to_priority": { + "name": "to_priority", + "type": "task_priority", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "from_assignee_id": { + "name": "from_assignee_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "to_assignee_id": { + "name": "to_assignee_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "from_project_id": { + "name": "from_project_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "to_project_id": { + "name": "to_project_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "from_channel_id": { + "name": "from_channel_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "to_channel_id": { + "name": "to_channel_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "description_edited": { + "name": "description_edited", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "added_label_ids": { + "name": "added_label_ids", + "type": "uuid[]", + "primaryKey": false, + "notNull": false + }, + "removed_label_ids": { + "name": "removed_label_ids", + "type": "uuid[]", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "task_activity_task_created_idx": { + "name": "task_activity_task_created_idx", + "columns": [ + { + "expression": "task_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_activity_actor_user_id_idx": { + "name": "task_activity_actor_user_id_idx", + "columns": [ + { + "expression": "actor_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_activity_from_status_id_idx": { + "name": "task_activity_from_status_id_idx", + "columns": [ + { + "expression": "from_status_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_activity_to_status_id_idx": { + "name": "task_activity_to_status_id_idx", + "columns": [ + { + "expression": "to_status_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_activity_from_assignee_id_idx": { + "name": "task_activity_from_assignee_id_idx", + "columns": [ + { + "expression": "from_assignee_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_activity_to_assignee_id_idx": { + "name": "task_activity_to_assignee_id_idx", + "columns": [ + { + "expression": "to_assignee_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_activity_from_project_id_idx": { + "name": "task_activity_from_project_id_idx", + "columns": [ + { + "expression": "from_project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_activity_to_project_id_idx": { + "name": "task_activity_to_project_id_idx", + "columns": [ + { + "expression": "to_project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_activity_from_channel_id_idx": { + "name": "task_activity_from_channel_id_idx", + "columns": [ + { + "expression": "from_channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_activity_to_channel_id_idx": { + "name": "task_activity_to_channel_id_idx", + "columns": [ + { + "expression": "to_channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "task_activity_task_id_tasks_id_fk": { + "name": "task_activity_task_id_tasks_id_fk", + "tableFrom": "task_activity", + "tableTo": "tasks", + "columnsFrom": [ + "task_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "task_activity_actor_user_id_users_id_fk": { + "name": "task_activity_actor_user_id_users_id_fk", + "tableFrom": "task_activity", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "actor_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "task_activity_from_status_id_task_statuses_id_fk": { + "name": "task_activity_from_status_id_task_statuses_id_fk", + "tableFrom": "task_activity", + "tableTo": "task_statuses", + "columnsFrom": [ + "from_status_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "task_activity_to_status_id_task_statuses_id_fk": { + "name": "task_activity_to_status_id_task_statuses_id_fk", + "tableFrom": "task_activity", + "tableTo": "task_statuses", + "columnsFrom": [ + "to_status_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "task_activity_from_assignee_id_users_id_fk": { + "name": "task_activity_from_assignee_id_users_id_fk", + "tableFrom": "task_activity", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "from_assignee_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "task_activity_to_assignee_id_users_id_fk": { + "name": "task_activity_to_assignee_id_users_id_fk", + "tableFrom": "task_activity", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "to_assignee_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "task_activity_from_project_id_task_projects_id_fk": { + "name": "task_activity_from_project_id_task_projects_id_fk", + "tableFrom": "task_activity", + "tableTo": "task_projects", + "columnsFrom": [ + "from_project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "task_activity_to_project_id_task_projects_id_fk": { + "name": "task_activity_to_project_id_task_projects_id_fk", + "tableFrom": "task_activity", + "tableTo": "task_projects", + "columnsFrom": [ + "to_project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "task_activity_from_channel_id_channels_id_fk": { + "name": "task_activity_from_channel_id_channels_id_fk", + "tableFrom": "task_activity", + "tableTo": "channels", + "columnsFrom": [ + "from_channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "task_activity_to_channel_id_channels_id_fk": { + "name": "task_activity_to_channel_id_channels_id_fk", + "tableFrom": "task_activity", + "tableTo": "channels", + "columnsFrom": [ + "to_channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.task_comments": { + "name": "task_comments", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "task_id": { + "name": "task_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "author_user_id": { + "name": "author_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "parent_comment_id": { + "name": "parent_comment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "body": { + "name": "body", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "edited_at": { + "name": "edited_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "task_comments_task_created_idx": { + "name": "task_comments_task_created_idx", + "columns": [ + { + "expression": "task_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_comments_author_user_id_idx": { + "name": "task_comments_author_user_id_idx", + "columns": [ + { + "expression": "author_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_comments_parent_comment_id_idx": { + "name": "task_comments_parent_comment_id_idx", + "columns": [ + { + "expression": "parent_comment_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "task_comments_task_id_tasks_id_fk": { + "name": "task_comments_task_id_tasks_id_fk", + "tableFrom": "task_comments", + "tableTo": "tasks", + "columnsFrom": [ + "task_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "task_comments_author_user_id_users_id_fk": { + "name": "task_comments_author_user_id_users_id_fk", + "tableFrom": "task_comments", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "author_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "task_comments_parent_comment_id_task_comments_id_fk": { + "name": "task_comments_parent_comment_id_task_comments_id_fk", + "tableFrom": "task_comments", + "tableTo": "task_comments", + "columnsFrom": [ + "parent_comment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.task_imports": { + "name": "task_imports", + "schema": "", + "columns": { + "task_id": { + "name": "task_id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "integration_provider", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "external_url": { + "name": "external_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "imported_by_user_id": { + "name": "imported_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "task_imports_task_id_tasks_id_fk": { + "name": "task_imports_task_id_tasks_id_fk", + "tableFrom": "task_imports", + "tableTo": "tasks", + "columnsFrom": [ + "task_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "task_imports_imported_by_user_id_users_id_fk": { + "name": "task_imports_imported_by_user_id_users_id_fk", + "tableFrom": "task_imports", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "imported_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "task_imports_org_provider_external_unique": { + "name": "task_imports_org_provider_external_unique", + "nullsNotDistinct": false, + "columns": [ + "organization_id", + "provider", + "external_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.task_label_assignments": { + "name": "task_label_assignments", + "schema": "", + "columns": { + "task_id": { + "name": "task_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "label_id": { + "name": "label_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "task_label_assignments_label_id_idx": { + "name": "task_label_assignments_label_id_idx", + "columns": [ + { + "expression": "label_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "task_label_assignments_task_id_tasks_id_fk": { + "name": "task_label_assignments_task_id_tasks_id_fk", + "tableFrom": "task_label_assignments", + "tableTo": "tasks", + "columnsFrom": [ + "task_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "task_label_assignments_label_id_task_labels_id_fk": { + "name": "task_label_assignments_label_id_task_labels_id_fk", + "tableFrom": "task_label_assignments", + "tableTo": "task_labels", + "columnsFrom": [ + "label_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "task_label_assignments_task_id_label_id_pk": { + "name": "task_label_assignments_task_id_label_id_pk", + "columns": [ + "task_id", + "label_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.task_labels": { + "name": "task_labels", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "parent_id": { + "name": "parent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "task_labels_organization_id_name_unique": { + "name": "task_labels_organization_id_name_unique", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "task_labels_organization_id_organizations_id_fk": { + "name": "task_labels_organization_id_organizations_id_fk", + "tableFrom": "task_labels", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "task_labels_team_id_teams_id_fk": { + "name": "task_labels_team_id_teams_id_fk", + "tableFrom": "task_labels", + "tableTo": "teams", + "schemaTo": "auth", + "columnsFrom": [ + "team_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "task_labels_parent_id_task_labels_id_fk": { + "name": "task_labels_parent_id_task_labels_id_fk", + "tableFrom": "task_labels", + "tableTo": "task_labels", + "columnsFrom": [ + "parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.task_project_tasks": { + "name": "task_project_tasks", + "schema": "", + "columns": { + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "task_id": { + "name": "task_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "task_project_tasks_project_id_idx": { + "name": "task_project_tasks_project_id_idx", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "task_project_tasks_project_id_task_projects_id_fk": { + "name": "task_project_tasks_project_id_task_projects_id_fk", + "tableFrom": "task_project_tasks", + "tableTo": "task_projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "task_project_tasks_task_id_tasks_id_fk": { + "name": "task_project_tasks_task_id_tasks_id_fk", + "tableFrom": "task_project_tasks", + "tableTo": "tasks", + "columnsFrom": [ + "task_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "task_project_tasks_task_id_unique": { + "name": "task_project_tasks_task_id_unique", + "nullsNotDistinct": false, + "columns": [ + "task_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.task_projects": { + "name": "task_projects", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "icon": { + "name": "icon", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "task_project_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'planned'" + }, + "lead_user_id": { + "name": "lead_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "start_date": { + "name": "start_date", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "target_date": { + "name": "target_date", + "type": "date", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "task_projects_organization_id_idx": { + "name": "task_projects_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "task_projects_organization_id_organizations_id_fk": { + "name": "task_projects_organization_id_organizations_id_fk", + "tableFrom": "task_projects", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "task_projects_lead_user_id_users_id_fk": { + "name": "task_projects_lead_user_id_users_id_fk", + "tableFrom": "task_projects", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "lead_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.task_sequences": { + "name": "task_sequences", + "schema": "", + "columns": { + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "last_number": { + "name": "last_number", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": { + "task_sequences_team_id_teams_id_fk": { + "name": "task_sequences_team_id_teams_id_fk", + "tableFrom": "task_sequences", + "tableTo": "teams", + "schemaTo": "auth", + "columnsFrom": [ + "team_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "task_sequences_organization_id_organizations_id_fk": { + "name": "task_sequences_organization_id_organizations_id_fk", + "tableFrom": "task_sequences", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "task_sequences_organization_key_unique": { + "name": "task_sequences_organization_key_unique", + "nullsNotDistinct": false, + "columns": [ + "organization_id", + "key" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.task_statuses": { + "name": "task_statuses", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "position": { + "name": "position", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "progress_percent": { + "name": "progress_percent", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "external_provider": { + "name": "external_provider", + "type": "integration_provider", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "task_statuses_organization_id_idx": { + "name": "task_statuses_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "task_statuses_type_idx": { + "name": "task_statuses_type_idx", + "columns": [ + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "task_statuses_organization_id_organizations_id_fk": { + "name": "task_statuses_organization_id_organizations_id_fk", + "tableFrom": "task_statuses", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "task_statuses_org_external_unique": { + "name": "task_statuses_org_external_unique", + "nullsNotDistinct": false, + "columns": [ + "organization_id", + "external_provider", + "external_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.tasks": { + "name": "tasks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "NULL" + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status_id": { + "name": "status_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "priority": { + "name": "priority", + "type": "task_priority", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'none'" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "assignee_id": { + "name": "assignee_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "creator_id": { + "name": "creator_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": false, + "notNull": true, + "default": "NULL" + }, + "number": { + "name": "number", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": "NULL" + }, + "estimate": { + "name": "estimate", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "due_date": { + "name": "due_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "labels": { + "name": "labels", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pr_url": { + "name": "pr_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "tasks_slug_idx": { + "name": "tasks_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "tasks_organization_id_idx": { + "name": "tasks_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "tasks_assignee_id_idx": { + "name": "tasks_assignee_id_idx", + "columns": [ + { + "expression": "assignee_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "tasks_creator_id_idx": { + "name": "tasks_creator_id_idx", + "columns": [ + { + "expression": "creator_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "tasks_status_id_idx": { + "name": "tasks_status_id_idx", + "columns": [ + { + "expression": "status_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "tasks_created_at_idx": { + "name": "tasks_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "tasks_status_id_task_statuses_id_fk": { + "name": "tasks_status_id_task_statuses_id_fk", + "tableFrom": "tasks", + "tableTo": "task_statuses", + "columnsFrom": [ + "status_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "tasks_organization_id_organizations_id_fk": { + "name": "tasks_organization_id_organizations_id_fk", + "tableFrom": "tasks", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "tasks_assignee_id_users_id_fk": { + "name": "tasks_assignee_id_users_id_fk", + "tableFrom": "tasks", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "assignee_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "tasks_creator_id_users_id_fk": { + "name": "tasks_creator_id_users_id_fk", + "tableFrom": "tasks", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "creator_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "tasks_team_id_teams_id_fk": { + "name": "tasks_team_id_teams_id_fk", + "tableFrom": "tasks", + "tableTo": "teams", + "schemaTo": "auth", + "columnsFrom": [ + "team_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "tasks_org_slug_unique": { + "name": "tasks_org_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "organization_id", + "slug" + ] + }, + "tasks_team_number_unique": { + "name": "tasks_team_number_unique", + "nullsNotDistinct": false, + "columns": [ + "team_id", + "number" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_identities": { + "name": "user_identities", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "external_scope_id": { + "name": "external_scope_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "handle": { + "name": "handle", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "user_identities_user_idx": { + "name": "user_identities_user_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "user_identities_org_provider_idx": { + "name": "user_identities_org_provider_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_identities_user_id_users_id_fk": { + "name": "user_identities_user_id_users_id_fk", + "tableFrom": "user_identities", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_identities_organization_id_organizations_id_fk": { + "name": "user_identities_organization_id_organizations_id_fk", + "tableFrom": "user_identities", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_identities_account_unique": { + "name": "user_identities_account_unique", + "nullsNotDistinct": true, + "columns": [ + "organization_id", + "provider", + "external_scope_id", + "external_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.v2_clients": { + "name": "v2_clients", + "schema": "", + "columns": { + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "v2_client_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "v2_clients_organization_id_idx": { + "name": "v2_clients_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "v2_clients_user_id_idx": { + "name": "v2_clients_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "v2_clients_organization_id_organizations_id_fk": { + "name": "v2_clients_organization_id_organizations_id_fk", + "tableFrom": "v2_clients", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "v2_clients_user_id_users_id_fk": { + "name": "v2_clients_user_id_users_id_fk", + "tableFrom": "v2_clients", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "v2_clients_organization_id_user_id_machine_id_pk": { + "name": "v2_clients_organization_id_user_id_machine_id_pk", + "columns": [ + "organization_id", + "user_id", + "machine_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.v2_hosts": { + "name": "v2_hosts", + "schema": "", + "columns": { + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "machine_id": { + "name": "machine_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "wake_command": { + "name": "wake_command", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "platform": { + "name": "platform", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "install_source": { + "name": "install_source", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "v2_hosts_organization_id_idx": { + "name": "v2_hosts_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "v2_hosts_organization_id_organizations_id_fk": { + "name": "v2_hosts_organization_id_organizations_id_fk", + "tableFrom": "v2_hosts", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "v2_hosts_created_by_user_id_users_id_fk": { + "name": "v2_hosts_created_by_user_id_users_id_fk", + "tableFrom": "v2_hosts", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "v2_hosts_organization_id_machine_id_pk": { + "name": "v2_hosts_organization_id_machine_id_pk", + "columns": [ + "organization_id", + "machine_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.v2_projects": { + "name": "v2_projects", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "repo_clone_url": { + "name": "repo_clone_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "github_repository_id": { + "name": "github_repository_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "icon_url": { + "name": "icon_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "v2_projects_organization_id_idx": { + "name": "v2_projects_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "v2_projects_organization_id_organizations_id_fk": { + "name": "v2_projects_organization_id_organizations_id_fk", + "tableFrom": "v2_projects", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "v2_projects_github_repository_id_github_repositories_id_fk": { + "name": "v2_projects_github_repository_id_github_repositories_id_fk", + "tableFrom": "v2_projects", + "tableTo": "github_repositories", + "columnsFrom": [ + "github_repository_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "v2_projects_org_slug_unique": { + "name": "v2_projects_org_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "organization_id", + "slug" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.v2_users_hosts": { + "name": "v2_users_hosts", + "schema": "", + "columns": { + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "host_id": { + "name": "host_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "v2_users_host_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'member'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "v2_users_hosts_organization_id_idx": { + "name": "v2_users_hosts_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "v2_users_hosts_user_id_idx": { + "name": "v2_users_hosts_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "v2_users_hosts_host_id_idx": { + "name": "v2_users_hosts_host_id_idx", + "columns": [ + { + "expression": "host_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "v2_users_hosts_organization_id_organizations_id_fk": { + "name": "v2_users_hosts_organization_id_organizations_id_fk", + "tableFrom": "v2_users_hosts", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "v2_users_hosts_user_id_users_id_fk": { + "name": "v2_users_hosts_user_id_users_id_fk", + "tableFrom": "v2_users_hosts", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "v2_users_hosts_host_fk": { + "name": "v2_users_hosts_host_fk", + "tableFrom": "v2_users_hosts", + "tableTo": "v2_hosts", + "columnsFrom": [ + "organization_id", + "host_id" + ], + "columnsTo": [ + "organization_id", + "machine_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "v2_users_hosts_organization_id_user_id_host_id_pk": { + "name": "v2_users_hosts_organization_id_user_id_host_id_pk", + "columns": [ + "organization_id", + "user_id", + "host_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.v2_workspaces": { + "name": "v2_workspaces", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "host_id": { + "name": "host_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "branch": { + "name": "branch", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "v2_workspace_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'worktree'" + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "task_id": { + "name": "task_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "v2_workspaces_project_id_idx": { + "name": "v2_workspaces_project_id_idx", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "v2_workspaces_organization_id_idx": { + "name": "v2_workspaces_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "v2_workspaces_host_id_idx": { + "name": "v2_workspaces_host_id_idx", + "columns": [ + { + "expression": "host_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "v2_workspaces_task_id_idx": { + "name": "v2_workspaces_task_id_idx", + "columns": [ + { + "expression": "task_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "v2_workspaces_one_main_per_host": { + "name": "v2_workspaces_one_main_per_host", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "host_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"v2_workspaces\".\"type\" = 'main'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "v2_workspaces_organization_id_organizations_id_fk": { + "name": "v2_workspaces_organization_id_organizations_id_fk", + "tableFrom": "v2_workspaces", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "v2_workspaces_created_by_user_id_users_id_fk": { + "name": "v2_workspaces_created_by_user_id_users_id_fk", + "tableFrom": "v2_workspaces", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "v2_workspaces_task_id_tasks_id_fk": { + "name": "v2_workspaces_task_id_tasks_id_fk", + "tableFrom": "v2_workspaces", + "tableTo": "tasks", + "columnsFrom": [ + "task_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "v2_workspaces_host_fk": { + "name": "v2_workspaces_host_fk", + "tableFrom": "v2_workspaces", + "tableTo": "v2_hosts", + "columnsFrom": [ + "organization_id", + "host_id" + ], + "columnsTo": [ + "organization_id", + "machine_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspace_pages": { + "name": "workspace_pages", + "schema": "", + "columns": { + "workspace_id": { + "name": "workspace_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "page_id": { + "name": "page_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "entry_path": { + "name": "entry_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspace_pages_workspace_id_entry_path_unique": { + "name": "workspace_pages_workspace_id_entry_path_unique", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entry_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspace_pages_page_id_idx": { + "name": "workspace_pages_page_id_idx", + "columns": [ + { + "expression": "page_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspace_pages_page_id_pages_id_fk": { + "name": "workspace_pages_page_id_pages_id_fk", + "tableFrom": "workspace_pages", + "tableTo": "pages", + "columnsFrom": [ + "page_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "workspace_pages_workspace_id_page_id_pk": { + "name": "workspace_pages_workspace_id_page_id_pk", + "columns": [ + "workspace_id", + "page_id" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.workspaces": { + "name": "workspaces", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "workspace_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "workspaces_project_id_idx": { + "name": "workspaces_project_id_idx", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspaces_organization_id_idx": { + "name": "workspaces_organization_id_idx", + "columns": [ + { + "expression": "organization_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "workspaces_type_idx": { + "name": "workspaces_type_idx", + "columns": [ + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "workspaces_organization_id_organizations_id_fk": { + "name": "workspaces_organization_id_organizations_id_fk", + "tableFrom": "workspaces", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspaces_project_id_projects_id_fk": { + "name": "workspaces_project_id_projects_id_fk", + "tableFrom": "workspaces", + "tableTo": "projects", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "workspaces_created_by_user_id_users_id_fk": { + "name": "workspaces_created_by_user_id_users_id_fk", + "tableFrom": "workspaces", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "created_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.slack_thread_sessions": { + "name": "slack_thread_sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "organization_id": { + "name": "organization_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "team_id": { + "name": "team_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "thread_ts": { + "name": "thread_ts", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "started_by_user_id": { + "name": "started_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "quiet": { + "name": "quiet", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "stop_requested_at": { + "name": "stop_requested_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_context_ts": { + "name": "last_context_ts", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "entity_log": { + "name": "entity_log", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "queued_events": { + "name": "queued_events", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "last_activity_at": { + "name": "last_activity_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "slack_thread_sessions_organization_id_organizations_id_fk": { + "name": "slack_thread_sessions_organization_id_organizations_id_fk", + "tableFrom": "slack_thread_sessions", + "tableTo": "organizations", + "schemaTo": "auth", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "slack_thread_sessions_started_by_user_id_users_id_fk": { + "name": "slack_thread_sessions_started_by_user_id_users_id_fk", + "tableFrom": "slack_thread_sessions", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "started_by_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "slack_thread_sessions_thread_unique": { + "name": "slack_thread_sessions_thread_unique", + "nullsNotDistinct": false, + "columns": [ + "organization_id", + "team_id", + "channel_id", + "thread_ts" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.agent_session_kind": { + "name": "agent_session_kind", + "schema": "public", + "values": [ + "dm", + "thread", + "main", + "task" + ] + }, + "public.agent_task_role": { + "name": "agent_task_role", + "schema": "public", + "values": [ + "writer", + "reviewer" + ] + }, + "public.agent_task_status": { + "name": "agent_task_status", + "schema": "public", + "values": [ + "queued", + "running", + "done", + "failed", + "stopped" + ] + }, + "public.agent_turn_reason": { + "name": "agent_turn_reason", + "schema": "public", + "values": [ + "direct_message", + "mention", + "thread_reply", + "channel_message", + "task_start", + "task_update", + "routine" + ] + }, + "public.agent_turn_status": { + "name": "agent_turn_status", + "schema": "public", + "values": [ + "running", + "completed", + "failed", + "interrupted" + ] + }, + "auth.task_tracker": { + "name": "task_tracker", + "schema": "auth", + "values": [ + "superset", + "linear" + ] + }, + "public.channel_broadcast": { + "name": "channel_broadcast", + "schema": "public", + "values": [ + "here", + "channel", + "everyone" + ] + }, + "public.channel_kind": { + "name": "channel_kind", + "schema": "public", + "values": [ + "channel", + "dm" + ] + }, + "public.channel_member_role": { + "name": "channel_member_role", + "schema": "public", + "values": [ + "member", + "admin" + ] + }, + "public.channel_message_subtype": { + "name": "channel_message_subtype", + "schema": "public", + "values": [ + "channel_join", + "channel_leave" + ] + }, + "public.channel_notify": { + "name": "channel_notify", + "schema": "public", + "values": [ + "all", + "mentions", + "none" + ] + }, + "public.channel_visibility": { + "name": "channel_visibility", + "schema": "public", + "values": [ + "public", + "private" + ] + }, + "public.dock_bounce": { + "name": "dock_bounce", + "schema": "public", + "values": [ + "off", + "once", + "until_focused" + ] + }, + "public.handle_owner_type": { + "name": "handle_owner_type", + "schema": "public", + "values": [ + "user", + "organization", + "reserved" + ] + }, + "public.leaderboard_visibility": { + "name": "leaderboard_visibility", + "schema": "public", + "values": [ + "public", + "hidden" + ] + }, + "public.actor_kind": { + "name": "actor_kind", + "schema": "public", + "values": [ + "user", + "system" + ] + }, + "public.agent_credential_kind": { + "name": "agent_credential_kind", + "schema": "public", + "values": [ + "subscription", + "api_key" + ] + }, + "public.attachment_parent_kind": { + "name": "attachment_parent_kind", + "schema": "public", + "values": [ + "page_version", + "issue", + "doc", + "chat_session", + "comment", + "page", + "cloud_workspace", + "task_comment", + "project_description", + "channel_message" + ] + }, + "public.automation_prompt_source": { + "name": "automation_prompt_source", + "schema": "public", + "values": [ + "human", + "agent", + "restore" + ] + }, + "public.automation_run_error_code": { + "name": "automation_run_error_code", + "schema": "public", + "values": [ + "no_instructions", + "host_offline", + "agent_not_found", + "workspace_not_found", + "cloud_not_ready", + "cloud_access_denied", + "cloud_environment_unusable", + "cloud_usage_limit_reached" + ] + }, + "public.automation_run_status": { + "name": "automation_run_status", + "schema": "public", + "values": [ + "dispatching", + "dispatched", + "skipped_offline", + "dispatch_failed", + "debounced", + "rejected" + ] + }, + "public.automation_session_kind": { + "name": "automation_session_kind", + "schema": "public", + "values": [ + "chat", + "terminal" + ] + }, + "public.automation_trigger_kind": { + "name": "automation_trigger_kind", + "schema": "public", + "values": [ + "schedule", + "webhook", + "github", + "slack", + "linear", + "sentry", + "microsoft_teams", + "google_calendar", + "gmail", + "notion" + ] + }, + "public.cloud_workspace_activity_event": { + "name": "cloud_workspace_activity_event", + "schema": "public", + "values": [ + "created", + "archived", + "unarchived", + "joined", + "description_edited", + "run_finished", + "run_failed", + "shared", + "unshared" + ] + }, + "public.cloud_workspace_status": { + "name": "cloud_workspace_status", + "schema": "public", + "values": [ + "provisioning", + "ready", + "failed", + "deleted" + ] + }, + "public.cloud_workspace_visibility": { + "name": "cloud_workspace_visibility", + "schema": "public", + "values": [ + "just_me", + "org" + ] + }, + "public.command_status": { + "name": "command_status", + "schema": "public", + "values": [ + "pending", + "completed", + "failed", + "timeout" + ] + }, + "public.desktop_notice_cta_action": { + "name": "desktop_notice_cta_action", + "schema": "public", + "values": [ + "install-update", + "open-url" + ] + }, + "public.desktop_notice_severity": { + "name": "desktop_notice_severity", + "schema": "public", + "values": [ + "info", + "warning", + "blocking" + ] + }, + "public.desktop_notice_trigger": { + "name": "desktop_notice_trigger", + "schema": "public", + "values": [ + "immediate", + "pre-update", + "post-update" + ] + }, + "public.environment_scope": { + "name": "environment_scope", + "schema": "public", + "values": [ + "organization", + "personal" + ] + }, + "public.environment_source_kind": { + "name": "environment_source_kind", + "schema": "public", + "values": [ + "image", + "fork" + ] + }, + "public.file_status": { + "name": "file_status", + "schema": "public", + "values": [ + "pending", + "ready" + ] + }, + "public.integration_provider": { + "name": "integration_provider", + "schema": "public", + "values": [ + "linear", + "github", + "slack", + "sentry", + "microsoft_teams", + "google", + "notion" + ] + }, + "public.page_comment_anchor_kind": { + "name": "page_comment_anchor_kind", + "schema": "public", + "values": [ + "element", + "text", + "page" + ] + }, + "public.page_comment_author_kind": { + "name": "page_comment_author_kind", + "schema": "public", + "values": [ + "human", + "agent" + ] + }, + "public.page_comment_intent": { + "name": "page_comment_intent", + "schema": "public", + "values": [ + "delete", + "approve" + ] + }, + "public.page_report_status": { + "name": "page_report_status", + "schema": "public", + "values": [ + "open", + "upheld", + "dismissed" + ] + }, + "public.page_share_role": { + "name": "page_share_role", + "schema": "public", + "values": [ + "view", + "comment" + ] + }, + "public.page_visibility": { + "name": "page_visibility", + "schema": "public", + "values": [ + "just_me", + "org", + "everyone" + ] + }, + "public.suggestion_entity": { + "name": "suggestion_entity", + "schema": "public", + "values": [ + "cloud_workspace", + "task", + "task_project", + "task_label", + "pull_request" + ] + }, + "public.suggestion_kind": { + "name": "suggestion_kind", + "schema": "public", + "values": [ + "set_field", + "rewrite", + "relate", + "link_task", + "add_link", + "create_task" + ] + }, + "public.suggestion_status": { + "name": "suggestion_status", + "schema": "public", + "values": [ + "pending", + "accepted", + "dismissed", + "stale", + "superseded" + ] + }, + "public.task_priority": { + "name": "task_priority", + "schema": "public", + "values": [ + "urgent", + "high", + "medium", + "low", + "none" + ] + }, + "public.task_project_state": { + "name": "task_project_state", + "schema": "public", + "values": [ + "planned", + "started", + "paused", + "completed", + "canceled" + ] + }, + "public.task_status": { + "name": "task_status", + "schema": "public", + "values": [ + "backlog", + "todo", + "planning", + "working", + "needs-feedback", + "ready-to-merge", + "completed", + "canceled" + ] + }, + "public.v2_client_type": { + "name": "v2_client_type", + "schema": "public", + "values": [ + "desktop", + "mobile", + "web" + ] + }, + "public.v2_users_host_role": { + "name": "v2_users_host_role", + "schema": "public", + "values": [ + "owner", + "member" + ] + }, + "public.v2_workspace_type": { + "name": "v2_workspace_type", + "schema": "public", + "values": [ + "main", + "worktree" + ] + }, + "public.workspace_type": { + "name": "workspace_type", + "schema": "public", + "values": [ + "local", + "cloud" + ] + } + }, + "schemas": { + "auth": "auth", + "authz": "authz", + "ingest": "ingest" + }, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": { + "authz.melange_tuples": { + "columns": { + "subject_type": { + "name": "subject_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "relation": { + "name": "relation", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "object_type": { + "name": "object_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "object_id": { + "name": "object_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "definition": "\n\t\tselect 'agent'::text as subject_type, a.id::text as subject_id, 'member'::text as relation,\n\t\t\t'organization'::text as object_type, a.organization_id::text as object_id\n\t\tfrom public.agents a where a.archived_at is null\n\t\tunion all\n\t\tselect 'agent', a.id::text, 'member', 'channel', m.channel_id::text\n\t\tfrom public.channel_members m\n\t\tjoin public.agents a on a.id = m.actor_id and a.archived_at is null\n\t\tunion all\n\t\tselect 'organization', c.organization_id::text, 'organization', 'channel', c.id::text\n\t\tfrom public.channels c where c.archived_at is null\n\t\tunion all\n\t\tselect 'agent', s.agent_id::text, 'operator', 'cloud_workspace', s.cloud_workspace_id::text\n\t\tfrom public.agent_sessions s\n\t\tjoin public.agents a on a.id = s.agent_id and a.archived_at is null\n\t\twhere s.parent_session_id is not null and s.cloud_workspace_id is not null\n\t", + "name": "melange_tuples", + "schema": "authz", + "isExisting": false, + "materialized": false + } + }, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/packages/db/drizzle/meta/_journal.json b/packages/db/drizzle/meta/_journal.json index efab0730ad7..8b70c53d5b6 100644 --- a/packages/db/drizzle/meta/_journal.json +++ b/packages/db/drizzle/meta/_journal.json @@ -1254,6 +1254,13 @@ "when": 1793333882261, "tag": "0178_agent_routines", "breakpoints": true + }, + { + "idx": 179, + "version": "7", + "when": 1793386969007, + "tag": "0179_users_experimental_chat", + "breakpoints": true } ] } \ No newline at end of file diff --git a/packages/db/src/schema/auth.ts b/packages/db/src/schema/auth.ts index 0fb254a11ad..adeb6efe78d 100644 --- a/packages/db/src/schema/auth.ts +++ b/packages/db/src/schema/auth.ts @@ -38,6 +38,7 @@ export const users = authSchema.table( // web SSR and async surfaces like email, which cannot see a device // setting. plans/20260826-i18n-strategy.md §4. locale: text("locale"), + experimentalChat: boolean("experimental_chat").default(false).notNull(), deletionRequestedAt: timestamp("deletion_requested_at"), // Set when the account is deleted. The row is kept and its PII scrubbed // rather than removed, because tasks, integrations and automations belong From 5b8d5ba022ff3f52296296428b68f2000c541473 Mon Sep 17 00:00:00 2001 From: Harshith Mullapudi <17528887+harshithmullapudi@users.noreply.github.com> Date: Fri, 30 Oct 2026 20:29:08 +0000 Subject: [PATCH 2/9] feat(db): keep the Chat setting in a new user_settings table Per review, account settings stay off auth.users, which every authenticated request reads. user_settings follows channel_notification_prefs: user_id primary key, typed columns with defaults, and no row means the defaults, so Chat stays off for every account without a backfill. Replaces the users.experimental_chat column from the previous commit, which never shipped. --- packages/db/drizzle/0179_user_settings.sql | 7 +++ .../drizzle/0179_users_experimental_chat.sql | 1 - packages/db/drizzle/meta/0179_snapshot.json | 57 ++++++++++++++++--- packages/db/drizzle/meta/_journal.json | 4 +- packages/db/src/schema/auth.ts | 1 - packages/db/src/schema/index.ts | 1 + packages/db/src/schema/user-settings.ts | 19 +++++++ 7 files changed, 78 insertions(+), 12 deletions(-) create mode 100644 packages/db/drizzle/0179_user_settings.sql delete mode 100644 packages/db/drizzle/0179_users_experimental_chat.sql create mode 100644 packages/db/src/schema/user-settings.ts diff --git a/packages/db/drizzle/0179_user_settings.sql b/packages/db/drizzle/0179_user_settings.sql new file mode 100644 index 00000000000..dbccd37e32e --- /dev/null +++ b/packages/db/drizzle/0179_user_settings.sql @@ -0,0 +1,7 @@ +CREATE TABLE "user_settings" ( + "user_id" uuid PRIMARY KEY NOT NULL, + "experimental_chat" boolean DEFAULT false NOT NULL, + "updated_at" timestamp with time zone DEFAULT now() NOT NULL +); +--> statement-breakpoint +ALTER TABLE "user_settings" ADD CONSTRAINT "user_settings_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON DELETE cascade ON UPDATE no action; \ No newline at end of file diff --git a/packages/db/drizzle/0179_users_experimental_chat.sql b/packages/db/drizzle/0179_users_experimental_chat.sql deleted file mode 100644 index b73c9e5cf7e..00000000000 --- a/packages/db/drizzle/0179_users_experimental_chat.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE "auth"."users" ADD COLUMN "experimental_chat" boolean DEFAULT false NOT NULL; \ No newline at end of file diff --git a/packages/db/drizzle/meta/0179_snapshot.json b/packages/db/drizzle/meta/0179_snapshot.json index a4038c61eff..5a693eee74f 100644 --- a/packages/db/drizzle/meta/0179_snapshot.json +++ b/packages/db/drizzle/meta/0179_snapshot.json @@ -1,5 +1,5 @@ { - "id": "5b5c0f1b-ddf4-4fef-a5d0-d613e9eefade", + "id": "44daaf07-b7bd-4a7f-9ee9-0df98dd3196f", "prevId": "2f315a6a-b681-4dfc-955f-f3bc498bc50d", "version": "7", "dialect": "postgresql", @@ -3051,13 +3051,6 @@ "primaryKey": false, "notNull": false }, - "experimental_chat": { - "name": "experimental_chat", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, "deletion_requested_at": { "name": "deletion_requested_at", "type": "timestamp", @@ -16692,6 +16685,54 @@ "policies": {}, "checkConstraints": {}, "isRLSEnabled": false + }, + "public.user_settings": { + "name": "user_settings", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "experimental_chat": { + "name": "experimental_chat", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_settings_user_id_users_id_fk": { + "name": "user_settings_user_id_users_id_fk", + "tableFrom": "user_settings", + "tableTo": "users", + "schemaTo": "auth", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false } }, "enums": { diff --git a/packages/db/drizzle/meta/_journal.json b/packages/db/drizzle/meta/_journal.json index 8b70c53d5b6..212353b540e 100644 --- a/packages/db/drizzle/meta/_journal.json +++ b/packages/db/drizzle/meta/_journal.json @@ -1258,8 +1258,8 @@ { "idx": 179, "version": "7", - "when": 1793386969007, - "tag": "0179_users_experimental_chat", + "when": 1793392134011, + "tag": "0179_user_settings", "breakpoints": true } ] diff --git a/packages/db/src/schema/auth.ts b/packages/db/src/schema/auth.ts index adeb6efe78d..0fb254a11ad 100644 --- a/packages/db/src/schema/auth.ts +++ b/packages/db/src/schema/auth.ts @@ -38,7 +38,6 @@ export const users = authSchema.table( // web SSR and async surfaces like email, which cannot see a device // setting. plans/20260826-i18n-strategy.md §4. locale: text("locale"), - experimentalChat: boolean("experimental_chat").default(false).notNull(), deletionRequestedAt: timestamp("deletion_requested_at"), // Set when the account is deleted. The row is kept and its PII scrubbed // rather than removed, because tasks, integrations and automations belong diff --git a/packages/db/src/schema/index.ts b/packages/db/src/schema/index.ts index 72ee61c6408..6fed88dcc72 100644 --- a/packages/db/src/schema/index.ts +++ b/packages/db/src/schema/index.ts @@ -13,4 +13,5 @@ export * from "./relations"; export * from "./schema"; export * from "./slack"; export * from "./types"; +export * from "./user-settings"; export * from "./zod"; diff --git a/packages/db/src/schema/user-settings.ts b/packages/db/src/schema/user-settings.ts new file mode 100644 index 00000000000..b005822660c --- /dev/null +++ b/packages/db/src/schema/user-settings.ts @@ -0,0 +1,19 @@ +import { boolean, pgTable, timestamp, uuid } from "drizzle-orm/pg-core"; +import { users } from "./auth"; + +/** + * A person's account-wide settings, the same on every device and readable by + * the server. No row means the defaults. + */ +export const userSettings = pgTable("user_settings", { + userId: uuid("user_id") + .primaryKey() + .references(() => users.id, { onDelete: "cascade" }), + experimentalChat: boolean("experimental_chat").notNull().default(false), + updatedAt: timestamp("updated_at", { withTimezone: true }) + .notNull() + .defaultNow() + .$onUpdate(() => new Date()), +}); + +export type SelectUserSettings = typeof userSettings.$inferSelect; From 23461e81d62b6e7426297e91a3923716d4ddf54b Mon Sep 17 00:00:00 2001 From: Harshith Mullapudi <17528887+harshithmullapudi@users.noreply.github.com> Date: Fri, 30 Oct 2026 18:43:07 +0000 Subject: [PATCH 3/9] feat(api): open automations as chat by default, take chat surface from clients Automations no longer read the acp-chat PostHog flag: they ask for a chat whenever the agent supports ACP, and the host still answers with a terminal when it can't chat with that agent. cloudWorkspace.create takes an optional `surface`. Desktop and mobile send their Chat experimental setting; callers that omit it (released builds, CLI, MCP, SDK) keep the old flag lookup, so the input is additive. --- packages/shared/src/constants.ts | 9 ++++----- packages/trpc/src/router/automation/cloudDispatch.ts | 7 ++----- packages/trpc/src/router/automation/dispatch.ts | 4 +--- .../src/router/cloud-workspace/cloud-workspace.ts | 11 +++++++++++ packages/trpc/src/router/cloud-workspace/start.ts | 10 +++++----- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/packages/shared/src/constants.ts b/packages/shared/src/constants.ts index c7b414e4b59..9c82e0f7784 100644 --- a/packages/shared/src/constants.ts +++ b/packages/shared/src/constants.ts @@ -225,11 +225,10 @@ export const FEATURE_FLAGS = { */ MOBILE_LIVE_ACTIVITY: "mobile-live-activity", /** - * Shows the ACP chat pane: a chat UI that attaches to a Claude/Codex - * session in the workspace over the Agent Client Protocol. UI-only: the - * flag decides who sees the pane, not what the host can do. Off, unloaded, - * or offline all mean "no pane" — flips take effect live. Audience is a - * release condition on the flag, so widening never needs a release. + * Legacy gate for the ACP chat pane, now the Chat experimental setting on + * desktop and mobile. Read only by released builds and by + * `cloudWorkspace.create` when a caller sends no `surface`. Remove it once + * no live build reads it. */ ACP_CHAT: "acp-chat", /** diff --git a/packages/trpc/src/router/automation/cloudDispatch.ts b/packages/trpc/src/router/automation/cloudDispatch.ts index 524c2beaa7a..0f109cb38c9 100644 --- a/packages/trpc/src/router/automation/cloudDispatch.ts +++ b/packages/trpc/src/router/automation/cloudDispatch.ts @@ -11,7 +11,6 @@ import { } from "@superset/shared/cloud-agent-launch"; import { SUPERSET_USER_ID_HEADER } from "@superset/shared/host-routing"; import { and, eq } from "drizzle-orm"; -import { acpChatEnabled } from "../../lib/acp-chat"; import { resolveMachineSize } from "../../lib/billing/plan"; import { cloudAccess } from "../../lib/cloud-guards"; import { @@ -79,9 +78,6 @@ export async function runInCloud( const { automation, prompt, placed, runId } = args; if (launch.kind === "pinned") { - const chat = - supportsCloudAgentChat(automation.agent) && - (await acpChatEnabled(automation.ownerUserId)); const target = { baseUrl: launch.hostTarget, headers: launch.headers }; return launchAgentSession( { @@ -94,7 +90,7 @@ export async function runInCloud( workspaceId: launch.row.id, agent: automation.agent, prompt, - chat, + chat: supportsCloudAgentChat(automation.agent), previous: launch.previous, }, ); @@ -107,6 +103,7 @@ export async function runInCloud( name: automation.name.slice(0, 200), branch: launch.branch, launch: { agent: automation.agent, prompt, automationRunId: runId }, + chat: true, machineSize: ( await resolveMachineSize( automation.organizationId, diff --git a/packages/trpc/src/router/automation/dispatch.ts b/packages/trpc/src/router/automation/dispatch.ts index 25556bec78d..6983c468286 100644 --- a/packages/trpc/src/router/automation/dispatch.ts +++ b/packages/trpc/src/router/automation/dispatch.ts @@ -22,7 +22,6 @@ import { slugifyForBranch, } from "@superset/shared/workspace-launch"; import { and, eq, sql } from "drizzle-orm"; -import { acpChatEnabled } from "../../lib/acp-chat"; import { nudge } from "../../lib/realtime"; import { fetchRelayPresence } from "../../lib/relay-presence"; import { runInCloud } from "./cloudDispatch"; @@ -262,7 +261,6 @@ export async function dispatchAutomation( }) : undefined; - const chat = await acpChatEnabled(automation.ownerUserId); const hostCaller = relayHostCaller({ relayUrl, hostId: routingKey, jwt }); const runAgent = (targetWorkspaceId: string) => @@ -270,7 +268,7 @@ export async function dispatchAutomation( workspaceId: targetWorkspaceId, agent: automation.agent, prompt, - chat, + chat: true, // Only the pinned workspace holds that session; the stale-pin // recovery below branches a fresh one, which has none. ...(previous && targetWorkspaceId === automation.v2WorkspaceId diff --git a/packages/trpc/src/router/cloud-workspace/cloud-workspace.ts b/packages/trpc/src/router/cloud-workspace/cloud-workspace.ts index 95c46b606af..1698ae3c35d 100644 --- a/packages/trpc/src/router/cloud-workspace/cloud-workspace.ts +++ b/packages/trpc/src/router/cloud-workspace/cloud-workspace.ts @@ -21,6 +21,7 @@ import type { TRPCRouterRecord } from "@trpc/server"; import { TRPCError } from "@trpc/server"; import { and, asc, desc, eq, inArray, sql } from "drizzle-orm"; import { z } from "zod"; +import { acpChatEnabled } from "../../lib/acp-chat"; import { organizationMachineSizes } from "../../lib/billing/plan"; import { assertCloudAccess, assertMember } from "../../lib/cloud-guards"; import { nudge } from "../../lib/realtime"; @@ -368,6 +369,11 @@ export const cloudWorkspaceRouter = { taskIds: z.array(z.string().uuid()).max(10).optional(), /** A size the organization offers (see `machineSizes`); omitted = its default. */ machineSize: z.enum(MACHINE_SIZES).optional(), + /** + * Where `agent` opens. Omitted by builds older than the chat + * experimental setting; those keep reading the `acp-chat` flag. + */ + surface: z.enum(["chat", "terminal"]).optional(), }), ) .mutation(async ({ ctx, input }) => { @@ -393,6 +399,11 @@ export const cloudWorkspaceRouter = { taskIds: input.taskIds, attachmentFileIds: input.attachmentFileIds, machineSize: input.machineSize, + chat: + input.surface === "chat" || + (!input.surface && + !!input.agent && + (await acpChatEnabled(ctx.userId))), ...(input.agent ? { launch: { diff --git a/packages/trpc/src/router/cloud-workspace/start.ts b/packages/trpc/src/router/cloud-workspace/start.ts index 8965c50a930..465c3f28aa1 100644 --- a/packages/trpc/src/router/cloud-workspace/start.ts +++ b/packages/trpc/src/router/cloud-workspace/start.ts @@ -6,7 +6,6 @@ import { supportsCloudAgentChat, } from "@superset/shared/cloud-agent-launch"; import { and, eq, inArray, isNull } from "drizzle-orm"; -import { acpChatEnabled } from "../../lib/acp-chat"; import { anchorAttachments } from "../../lib/attachments"; import { resolveMachineSize } from "../../lib/billing/plan"; import { @@ -103,14 +102,15 @@ export async function startCloudWorkspace(args: { /** Omitted = the repo's default branch. */ branch?: string; launch?: CloudAgentLaunch; + /** Opens `launch` as a chat when its agent supports one. */ + chat?: boolean; taskIds?: string[]; attachmentFileIds?: string[]; machineSize?: string; beforeProvision?: (workspaceId: string) => Promise; }) { - const openAsChat = supportsCloudAgentChat(args.launch?.agent) - ? acpChatEnabled(args.userId) - : Promise.resolve(false); + const openAsChat = + args.chat === true && supportsCloudAgentChat(args.launch?.agent); const environment = await loadUsableEnvironment(args); const size = await resolveMachineSize(args.organizationId, args.machineSize); if (!size) throw machineSizeNotAvailable(args.machineSize); @@ -222,7 +222,7 @@ export async function startCloudWorkspace(args: { ? { launch: { ...args.launch, - surface: (await openAsChat) ? ("chat" as const) : undefined, + surface: openAsChat ? ("chat" as const) : undefined, }, } : {}), From 5fc8fbc96e21ec5076dae81e6860a2eeb0c5cf71 Mon Sep 17 00:00:00 2001 From: Harshith Mullapudi <17528887+harshithmullapudi@users.noreply.github.com> Date: Fri, 30 Oct 2026 18:43:07 +0000 Subject: [PATCH 4/9] feat(desktop): move chat into Experimental settings, off by default The Chat switch is shown to everyone and is the only gate; the acp-chat PostHog flag is no longer read. A stored null (never touched) now means off. ACP agents open as chat when it is on; every other agent, and every agent when it is off, opens a terminal. - Show the presets bar on chat tabs again; agent presets already pick chat or terminal from the setting and ACP support. - Hide "Fork into chat" while Chat is off. - Cloud workspace creation sends the setting as `surface`. --- .../renderer/hooks/useAcpChatEnabled/index.ts | 6 +-- .../useAcpChatEnabled/useAcpChatEnabled.ts | 38 +------------------ .../useCreateAgentSession.ts | 8 ++-- .../RunInWorkspacePopoverV2.tsx | 3 ++ .../useAgentSessionLauncher.ts | 8 ++-- .../fixtures/checks.tsx | 8 ++-- .../useAutoAdoptChatSessions.ts | 8 ++-- .../useConsumeAutomationRunLink.ts | 9 ++--- .../hooks/useIsChatTabActive/index.ts | 1 - .../useIsChatTabActive.test.ts | 35 ----------------- .../useIsChatTabActive/useIsChatTabActive.ts | 23 ----------- .../useSurfaceForkSource.ts | 3 ++ .../v2-workspace/$workspaceId/page.tsx | 8 ++-- .../useSubmitWorkspace/useSubmitWorkspace.ts | 13 ++++--- .../NewWorkspaceScreen/NewWorkspaceScreen.tsx | 2 +- .../SettingsSidebar/SettingsSidebar.tsx | 2 - .../ExperimentalSettingsList.tsx | 14 +++---- .../routes/_authenticated/settings/layout.tsx | 3 -- .../settings-search/settings-search.test.ts | 32 ++-------------- .../utils/settings-search/settings-search.ts | 2 - apps/desktop/src/renderer/stores/acp-chat.ts | 24 ++++++------ .../renderer/stores/chat-turn-snapshots.ts | 11 +++--- 22 files changed, 68 insertions(+), 193 deletions(-) delete mode 100644 apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useIsChatTabActive/index.ts delete mode 100644 apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useIsChatTabActive/useIsChatTabActive.test.ts delete mode 100644 apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useIsChatTabActive/useIsChatTabActive.ts diff --git a/apps/desktop/src/renderer/hooks/useAcpChatEnabled/index.ts b/apps/desktop/src/renderer/hooks/useAcpChatEnabled/index.ts index fffa5d020ef..a2550a9abef 100644 --- a/apps/desktop/src/renderer/hooks/useAcpChatEnabled/index.ts +++ b/apps/desktop/src/renderer/hooks/useAcpChatEnabled/index.ts @@ -1,5 +1 @@ -export { - type AcpChatAvailability, - useAcpChatEnabled, - useAwaitAcpChatEnabled, -} from "./useAcpChatEnabled"; +export { useAcpChatEnabled } from "./useAcpChatEnabled"; diff --git a/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts b/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts index e8394ba6f78..a88e6ae7d32 100644 --- a/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts +++ b/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts @@ -1,39 +1,5 @@ -import { FEATURE_FLAGS } from "@superset/shared/constants"; -import { useFeatureFlagEnabled, usePostHog } from "posthog-js/react"; -import { useCallback } from "react"; import { useAcpChatStore } from "renderer/stores/acp-chat"; -export type AcpChatAvailability = "enabled" | "disabled" | "resolving"; - -export function useAcpChatEnabled(): AcpChatAvailability { - const flag = useFeatureFlagEnabled(FEATURE_FLAGS.ACP_CHAT); - const chosen = useAcpChatStore((state) => state.enabled); - if (chosen === false) return "disabled"; - if (flag === undefined) return "resolving"; - return flag ? "enabled" : "disabled"; -} - -const RESOLVE_TIMEOUT_MS = 2_000; - -export function useAwaitAcpChatEnabled(): () => Promise { - const availability = useAcpChatEnabled(); - const posthog = usePostHog(); - - return useCallback(() => { - if (availability !== "resolving") - return Promise.resolve(availability === "enabled"); - if (!posthog) return Promise.resolve(false); - return new Promise((resolve) => { - let unsubscribe: (() => void) | undefined; - const settle = (enabled: boolean) => { - clearTimeout(timer); - unsubscribe?.(); - resolve(enabled); - }; - const timer = setTimeout(() => settle(false), RESOLVE_TIMEOUT_MS); - unsubscribe = posthog.onFeatureFlags(() => { - settle(posthog.isFeatureEnabled(FEATURE_FLAGS.ACP_CHAT) === true); - }); - }); - }, [availability, posthog]); +export function useAcpChatEnabled(): boolean { + return useAcpChatStore((state) => state.enabled); } diff --git a/apps/desktop/src/renderer/hooks/useCreateAgentSession/useCreateAgentSession.ts b/apps/desktop/src/renderer/hooks/useCreateAgentSession/useCreateAgentSession.ts index 54dedf18aeb..826677708ea 100644 --- a/apps/desktop/src/renderer/hooks/useCreateAgentSession/useCreateAgentSession.ts +++ b/apps/desktop/src/renderer/hooks/useCreateAgentSession/useCreateAgentSession.ts @@ -4,7 +4,7 @@ import { errorMessage } from "@superset/i18n/errors"; import { toast } from "@superset/ui/sonner"; import { useNavigate } from "@tanstack/react-router"; import { useRef, useState } from "react"; -import { useAwaitAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; +import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; import { useV2AgentChoices } from "renderer/hooks/useV2AgentChoices"; import { AGENT_STORAGE_KEY } from "renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/types"; import { useLocalHostService } from "renderer/routes/_authenticated/providers/LocalHostServiceProvider"; @@ -25,7 +25,7 @@ export function useCreateAgentSession() { const { machineId, activeHostUrl } = useLocalHostService(); const { agents } = useV2AgentChoices(activeHostUrl); const { submit } = useWorkspaceCreates(); - const awaitAcpChatEnabled = useAwaitAcpChatEnabled(); + const acpChatEnabled = useAcpChatEnabled(); const busy = useRef(false); const [isPending, setIsPending] = useState(false); @@ -65,8 +65,8 @@ export function useCreateAgentSession() { try { const openAsChat = options.preferChat === true && - Boolean(acpHarnessForPreset(presetOf(choice))) && - (await awaitAcpChatEnabled()); + acpChatEnabled && + Boolean(acpHarnessForPreset(presetOf(choice))); const { workspaceId, completed } = submit({ hostId: machineId, snapshot: { diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/RunInWorkspacePopoverV2/RunInWorkspacePopoverV2.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/RunInWorkspacePopoverV2/RunInWorkspacePopoverV2.tsx index 721084b0c7a..270aa5fd1cb 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/RunInWorkspacePopoverV2/RunInWorkspacePopoverV2.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/RunInWorkspacePopoverV2/RunInWorkspacePopoverV2.tsx @@ -21,6 +21,7 @@ import { LuBox } from "react-icons/lu"; import { AgentSelect } from "renderer/components/AgentSelect"; import { useRecentProjects } from "renderer/hooks/host-projects/useRecentProjects"; import { useHostUrl } from "renderer/hooks/host-service/useHostTargetUrl"; +import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; import { useActiveOrganizationId } from "renderer/hooks/useActiveOrganizationId"; import { useCloudAgentChoices } from "renderer/hooks/useCloudAgentChoices"; import { useSelectedHostProjectIds } from "renderer/hooks/useSelectedHostProjectIds"; @@ -107,6 +108,7 @@ export function RunInWorkspacePopoverV2({ environments.find((environment) => environment.id === environmentId) ?? environments[0]; const createCloudWorkspace = cloudTrpc.cloudWorkspace.create.useMutation(); + const acpChatEnabled = useAcpChatEnabled(); const launchHostUrl = useHostUrl(isCloud ? null : hostId); const setUpProjectIds = useSelectedHostProjectIds(hostId); @@ -262,6 +264,7 @@ export function RunInWorkspacePopoverV2({ : { agent: selectedAgent, prompt: synthesizeTaskPrompt(task).slice(0, 20_000), + surface: acpChatEnabled ? "chat" : "terminal", }), }), ), diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAgentSessionLauncher/useAgentSessionLauncher.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAgentSessionLauncher/useAgentSessionLauncher.ts index ad6928fa9f4..742170c14ee 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAgentSessionLauncher/useAgentSessionLauncher.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAgentSessionLauncher/useAgentSessionLauncher.ts @@ -6,7 +6,7 @@ import { toast } from "@superset/ui/sonner"; import { useWorkspaceClient, workspaceTrpc } from "@superset/workspace-client"; import { useQueryClient } from "@tanstack/react-query"; import { useCallback } from "react"; -import { useAwaitAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; +import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; import { useTerminalAppearance } from "renderer/hooks/useTerminalAppearance"; import { useV2AgentConfigs, @@ -63,14 +63,14 @@ export function useAgentSessionLauncher({ const { t } = useLingui(); const { mutateAsync: runAgent } = workspaceTrpc.agents.run.useMutation(); const appearance = useTerminalAppearance(); - const awaitAcpChatEnabled = useAwaitAcpChatEnabled(); + const acpChatEnabled = useAcpChatEnabled(); const { hostUrl } = useWorkspaceClient(); const { data: agentConfigs } = useV2AgentConfigs(hostUrl); const queryClient = useQueryClient(); const openAgentChat = useCallback( async (input) => { - if (!(await awaitAcpChatEnabled())) return null; + if (!acpChatEnabled) return null; const configs = await queryClient .ensureQueryData(v2AgentConfigsQueryOptions(hostUrl)) .catch(() => agentConfigs ?? []); @@ -104,7 +104,7 @@ export function useAgentSessionLauncher({ } return { terminalId }; }, - [awaitAcpChatEnabled, queryClient, hostUrl, agentConfigs, store], + [acpChatEnabled, queryClient, hostUrl, agentConfigs, store], ); const openNewChat = useCallback(async () => { diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/fixtures/checks.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/fixtures/checks.tsx index 8d47bcd997e..2a39443dca5 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/fixtures/checks.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/fixtures/checks.tsx @@ -50,7 +50,7 @@ let creates = 0; const changes = new Set<() => void>(); const connectionListeners = new Set<() => void>(); let refs = 0; -let chatAvailability: "enabled" | "disabled" = "enabled"; +let acpChatEnabled = true; type Binding = { terminalId: string; agentId: string; @@ -89,7 +89,7 @@ mock.module("@superset/workspace-client", () => ({ useWorkspaceClient: () => ({ hostUrl }), })); mock.module("renderer/hooks/useAcpChatEnabled", () => ({ - useAcpChatEnabled: () => chatAvailability, + useAcpChatEnabled: () => acpChatEnabled, })); mock.module("renderer/hooks/host-service/useWorkspaceHostUrl", () => ({ useWorkspaceHostUrl: () => hostUrl, @@ -243,7 +243,7 @@ afterEach(() => { reads = 0; outlineReads = 0; creates = 0; - chatAvailability = "enabled"; + acpChatEnabled = true; terminalAgents = new Map(); localStorage.clear(); }); @@ -368,7 +368,7 @@ test("a launch whose stored prompt differs is held back and attached at the dead }); test("turning agent chat off removes the waiting pane instead of leaving it stuck", async () => { - chatAvailability = "disabled"; + acpChatEnabled = false; const pending = await waitingPane(); show(pending.store, "disabled-workspace"); await waitFor(() => expect(pending.store.getState().tabs).toHaveLength(0)); diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/useAutoAdoptChatSessions.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/useAutoAdoptChatSessions.ts index 0e8e066d5f4..8dfe4945b48 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/useAutoAdoptChatSessions.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/useAutoAdoptChatSessions.ts @@ -65,8 +65,8 @@ export function useAutoAdoptChatSessions({ isLayoutReady, pendingTimeoutMs = PENDING_CLOUD_CHAT_TIMEOUT_MS, }: UseAutoAdoptChatSessionsArgs): void { - const chatAvailability = useAcpChatEnabled(); - const enabled = chatAvailability === "enabled" && isLayoutReady; + const acpChatEnabled = useAcpChatEnabled(); + const enabled = acpChatEnabled && isLayoutReady; const { hostUrl } = useWorkspaceClient(); const { transport } = useChatWiring(); const queryClient = useQueryClient(); @@ -140,13 +140,13 @@ export function useAutoAdoptChatSessions({ // biome-ignore lint/correctness/useExhaustiveDependencies: tabs re-runs it when a waiting pane is restored useEffect(() => { - if (chatAvailability !== "disabled" || !isLayoutReady) return; + if (acpChatEnabled || !isLayoutReady) return; for (const pending of pendingPanes([store, ...linkedStores])) { pending.store .getState() .closePane({ tabId: pending.tabId, paneId: pending.paneId }); } - }, [chatAvailability, isLayoutReady, store, linkedStores, tabs]); + }, [acpChatEnabled, isLayoutReady, store, linkedStores, tabs]); useEffect(() => { const result = sessionsQuery.data; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useConsumeAutomationRunLink/useConsumeAutomationRunLink.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useConsumeAutomationRunLink/useConsumeAutomationRunLink.ts index f5fd43ad28c..80c0f7a0a23 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useConsumeAutomationRunLink/useConsumeAutomationRunLink.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useConsumeAutomationRunLink/useConsumeAutomationRunLink.ts @@ -56,14 +56,14 @@ export function useConsumeAutomationRunLink({ : []; return chatSessionTarget({ result, sessions, sessionId, workspaceId }); }, - enabled: !!sessionId && acpChat === "enabled" && isLayoutReady, + enabled: !!sessionId && acpChat && isLayoutReady, refetchOnWindowFocus: false, retry: false, }); useEffect(() => { - if (!sessionId || !isLayoutReady || acpChat === "resolving") return; + if (!sessionId || !isLayoutReady) return; if ( - acpChat === "enabled" && + acpChat && (chatQuery.isFetching || (!chatQuery.isSuccess && !chatQuery.isError)) ) return; @@ -74,8 +74,7 @@ export function useConsumeAutomationRunLink({ })}`; if (consumedRef.current.has(key)) return; consumedRef.current.add(key); - const target = - acpChat === "enabled" && chatQuery.isSuccess ? chatQuery.data : null; + const target = acpChat && chatQuery.isSuccess ? chatQuery.data : null; consumeSearch(target ? ["sessionId", "terminalId"] : ["sessionId"]); if (target) focusChatSession({ store, linkedStores, session: target }); }, [ diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useIsChatTabActive/index.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useIsChatTabActive/index.ts deleted file mode 100644 index 4119d2a8ed3..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useIsChatTabActive/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useIsChatTabActive } from "./useIsChatTabActive"; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useIsChatTabActive/useIsChatTabActive.test.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useIsChatTabActive/useIsChatTabActive.test.ts deleted file mode 100644 index aaa09440e28..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useIsChatTabActive/useIsChatTabActive.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { afterEach, expect, test } from "bun:test"; -import { createWorkspaceStore } from "@superset/panes"; -import { act, cleanup, renderHook } from "@testing-library/react"; -import { attachCloudChatSession } from "renderer/stores/workspace-creates/pendingCloudChat"; -import { type PaneViewerData, PENDING_CLOUD_CHAT_PANE_KIND } from "../../types"; -import { useIsChatTabActive } from "./useIsChatTabActive"; - -afterEach(cleanup); - -test("the waiting chat keeps the chat layout before and after attaching", () => { - const store = createWorkspaceStore(); - store.getState().addTab({ - panes: [ - { - kind: PENDING_CLOUD_CHAT_PANE_KIND, - data: { draftId: "draft", agentId: "claude", promptHash: "hash" }, - }, - ], - }); - const paneId = Object.keys(store.getState().tabs[0]?.panes ?? {})[0]; - if (!paneId) throw new Error("missing pane"); - const hook = renderHook(() => useIsChatTabActive(store)); - expect(hook.result.current).toBe(true); - act(() => - store.getState().replaceState((state) => - attachCloudChatSession(state, paneId, { - sessionId: "chat", - terminalId: "terminal", - harnessSessionId: null, - title: null, - }), - ), - ); - expect(hook.result.current).toBe(true); -}); diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useIsChatTabActive/useIsChatTabActive.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useIsChatTabActive/useIsChatTabActive.ts deleted file mode 100644 index 4e2aab4a653..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useIsChatTabActive/useIsChatTabActive.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { WorkspaceStore } from "@superset/panes"; -import { useStore } from "zustand"; -import type { StoreApi } from "zustand/vanilla"; -import { type PaneViewerData, PENDING_CLOUD_CHAT_PANE_KIND } from "../../types"; - -export function useIsChatTabActive( - store: StoreApi>, -): boolean { - return useStore(store, (state) => { - const tab = state.tabs.find( - (candidate) => candidate.id === state.activeTabId, - ); - if (!tab) return false; - const panes = Object.values(tab.panes); - return ( - panes.length > 0 && - panes.every( - (pane) => - pane.kind === "chat-v3" || pane.kind === PENDING_CLOUD_CHAT_PANE_KIND, - ) - ); - }); -} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/hooks/useSurfaceForkSource/useSurfaceForkSource.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/hooks/useSurfaceForkSource/useSurfaceForkSource.ts index b2574ba9ad3..1c22d0965bc 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/hooks/useSurfaceForkSource/useSurfaceForkSource.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/hooks/useSurfaceForkSource/useSurfaceForkSource.ts @@ -3,6 +3,7 @@ import { FEATURE_FLAGS } from "@superset/shared/constants"; import { useFeatureFlagEnabled } from "posthog-js/react"; import { useTerminalAgentBinding } from "renderer/hooks/host-service/useTerminalAgentBindings"; import { useWorkspaceHostUrl } from "renderer/hooks/host-service/useWorkspaceHostUrl"; +import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; import { useV2AgentConfigs } from "renderer/hooks/useV2AgentConfigs"; import type { ChatPaneData, TerminalPaneData } from "../../../../types"; import type { SurfaceForkSource } from "../useSurfaceFork"; @@ -20,6 +21,7 @@ export function useSurfaceForkSource( ): { enabled: boolean; source: SurfaceForkSource | null } { const enabled = useFeatureFlagEnabled(FEATURE_FLAGS.AGENT_SURFACE_FORK) === true; + const acpChatEnabled = useAcpChatEnabled(); const binding = useTerminalAgentBinding(workspaceId, pane.data.terminalId); const hostUrl = useWorkspaceHostUrl(workspaceId); const { data: configs = [] } = useV2AgentConfigs(hostUrl); @@ -43,6 +45,7 @@ export function useSurfaceForkSource( } if ( + !acpChatEnabled || !binding?.agentSessionId || binding.endedAt || LOCKED_WHILE_CLI_RUNS.has(binding.agentId) || diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/page.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/page.tsx index 8181c2c25ec..f316a0f2df4 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/page.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/page.tsx @@ -66,7 +66,6 @@ import { useDefaultBrowserUrl } from "./hooks/useDefaultBrowserUrl"; import { useDefaultContextMenuActions } from "./hooks/useDefaultContextMenuActions"; import { useDefaultPaneActions } from "./hooks/useDefaultPaneActions"; import { useDiffPaneTarget } from "./hooks/useDiffPaneTarget"; -import { useIsChatTabActive } from "./hooks/useIsChatTabActive"; import { useOpenNewTabWhenRightPaneOpensEmpty } from "./hooks/useOpenNewTabWhenRightPaneOpensEmpty"; import { usePaneAreaMoveActions } from "./hooks/usePaneAreaMoveActions"; import { usePaneRegistry } from "./hooks/usePaneRegistry"; @@ -222,7 +221,6 @@ function V2WorkspaceContent() { const showPresetsBar = v2UserPreferences.showPresetsBar; const { store, isLayoutReady, hasRow } = useV2WorkspacePaneLayout(); useClearActivePaneAttention({ store }); - const isChatTabActive = useIsChatTabActive(store); const rightPaneAreaFlag = useRightPaneAreaEnabled(); const isRightPaneAreaEnabled = rightPaneAreaFlag === true; const { @@ -304,7 +302,7 @@ function V2WorkspaceContent() { const addChatTab = useCallback(() => { void openNewChat(); }, [openNewChat]); - const onAddChat = acpChat === "enabled" ? addChatTab : undefined; + const onAddChat = acpChat ? addChatTab : undefined; const { matchedPresets, newTabPresets, @@ -571,7 +569,7 @@ function V2WorkspaceContent() { isMobilePaneEnabled, }); useHotkey("QUICK_OPEN", handleQuickOpen); - useHotkey("NEW_CHAT", addChatTab, { enabled: acpChat !== "disabled" }); + useHotkey("NEW_CHAT", addChatTab, { enabled: acpChat }); useHotkey("RUN_WORKSPACE_COMMAND", () => { void workspaceRun.toggleWorkspaceRun(); }); @@ -701,7 +699,7 @@ function V2WorkspaceContent() { /> )} renderBelowTabBar={() => - showPresetsBar && !isChatTabActive ? ( + showPresetsBar ? ( state.setEnabled); const showChatTurnSnapshots = - acpChatFlag && + acpChatEnabled && isItemVisible( SETTING_ITEM_ID.EXPERIMENTAL_CHAT_TURN_SNAPSHOTS, visibleItems, diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/layout.tsx b/apps/desktop/src/renderer/routes/_authenticated/settings/layout.tsx index d4b1aa42614..6f3c23f74ff 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/settings/layout.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/layout.tsx @@ -120,7 +120,6 @@ function SettingsLayout() { useFeatureFlagEnabled(FEATURE_FLAGS.MOBILE_LAUNCH) === true; const cloudWorkspacesEnabled = useFeatureFlagEnabled(FEATURE_FLAGS.CLOUD_WORKSPACES) === true; - const acpChatFlag = useFeatureFlagEnabled(FEATURE_FLAGS.ACP_CHAT) === true; const pluginsVisible = usePluginsSettingsVisible(); const searchQuery = useSettingsSearchQuery(); const setSearchQuery = useSetSettingsSearchQuery(); @@ -142,7 +141,6 @@ function SettingsLayout() { isV2CloudEnabled, cloudWorkspacesEnabled, mobileEnabled, - acpChatFlag, pluginsVisible, ) : {}, @@ -152,7 +150,6 @@ function SettingsLayout() { isV2CloudEnabled, cloudWorkspacesEnabled, mobileEnabled, - acpChatFlag, pluginsVisible, ], ); diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/utils/settings-search/settings-search.test.ts b/apps/desktop/src/renderer/routes/_authenticated/settings/utils/settings-search/settings-search.test.ts index 5968aa9788e..262de1b7bf8 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/settings/utils/settings-search/settings-search.test.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/utils/settings-search/settings-search.test.ts @@ -152,39 +152,15 @@ describe("settings search - mobile rollout", () => { }); }); -describe("settings search - chat", () => { - it("counts the Chat switch only when its flag is on", () => { - expect( - getVisibleMatchCountBySection("acp", true, false).experimental, - ).toBeUndefined(); - expect( - getVisibleMatchCountBySection("acp", true, false, false, true) - .experimental, - ).toBe(1); - }); -}); - describe("settings search - plugins visibility", () => { it("excludes plugin matches unless the plugins section is visible", () => { expect( - getVisibleMatchCountBySection( - "marketplace", - true, - false, - false, - false, - false, - ).plugins, + getVisibleMatchCountBySection("marketplace", true, false, false, false) + .plugins, ).toBeUndefined(); expect( - getVisibleMatchCountBySection( - "marketplace", - true, - false, - false, - false, - true, - ).plugins, + getVisibleMatchCountBySection("marketplace", true, false, false, true) + .plugins, ).toBeGreaterThan(0); }); }); diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/utils/settings-search/settings-search.ts b/apps/desktop/src/renderer/routes/_authenticated/settings/utils/settings-search/settings-search.ts index b304c0a660e..0bf84a457a8 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/settings/utils/settings-search/settings-search.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/utils/settings-search/settings-search.ts @@ -2156,14 +2156,12 @@ export function getVisibleMatchCountBySection( isV2: boolean, cloudWorkspaces: boolean, mobileEnabled = false, - acpChatFlag = false, pluginsVisible = false, ): Partial> { const matches = searchSettings(query).filter( (item) => isItemOffered(item, isV2, cloudWorkspaces) && (item.section !== "mobile" || mobileEnabled) && - (item.id !== SETTING_ITEM_ID.EXPERIMENTAL_ACP_CHAT || acpChatFlag) && (item.section !== "plugins" || pluginsVisible), ); const counts: Partial> = {}; diff --git a/apps/desktop/src/renderer/stores/acp-chat.ts b/apps/desktop/src/renderer/stores/acp-chat.ts index 1cd04c36dae..983273342c9 100644 --- a/apps/desktop/src/renderer/stores/acp-chat.ts +++ b/apps/desktop/src/renderer/stores/acp-chat.ts @@ -2,19 +2,14 @@ import { create } from "zustand"; import { devtools, persist } from "zustand/middleware"; /** - * EXPERIMENT: the ACP chat pane. Needs the `acp-chat` flag; with it on, - * `enabled` is null until the person sets it, and null means on. Read it + * EXPERIMENT: the ACP chat pane, opt-in from Settings → Experimental. Read it * through `useAcpChatEnabled`. * - * Desktop only: automations and cloud workspaces open chats from the flag - * alone. - * - * To conclude the experiment, remove: this store, its toggle in - * `ExperimentalSettings` and its `settings-search` entry - * (`EXPERIMENTAL_ACP_CHAT`), and read the flag directly again. + * Desktop only: automations, cloud workspaces and mobile still read the + * `acp-chat` flag. */ interface AcpChatState { - enabled: boolean | null; + enabled: boolean; setEnabled: (enabled: boolean) => void; } @@ -22,10 +17,17 @@ export const useAcpChatStore = create()( devtools( persist( (set) => ({ - enabled: null, + enabled: false, setEnabled: (enabled) => set({ enabled }), }), - { name: "acp-chat" }, + { + name: "acp-chat", + version: 1, + migrate: (persisted) => + ({ + enabled: (persisted as { enabled?: unknown })?.enabled === true, + }) as AcpChatState, + }, ), { name: "AcpChatStore" }, ), diff --git a/apps/desktop/src/renderer/stores/chat-turn-snapshots.ts b/apps/desktop/src/renderer/stores/chat-turn-snapshots.ts index 7a9e89fc43e..628243a6e63 100644 --- a/apps/desktop/src/renderer/stores/chat-turn-snapshots.ts +++ b/apps/desktop/src/renderer/stores/chat-turn-snapshots.ts @@ -1,12 +1,11 @@ -import { FEATURE_FLAGS } from "@superset/shared/constants"; -import { useFeatureFlagEnabled } from "posthog-js/react"; +import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; import { create } from "zustand"; import { devtools, persist } from "zustand/middleware"; /** * EXPERIMENT: snapshot the worktree around each ACP chat turn, for the turn's - * changes card and its Undo. Off by default; the toggle shows only with the - * `acp-chat` flag. + * changes card and its Undo. Off by default; the toggle shows only while the + * chat experiment is on. * * To conclude the experiment, remove: this store, moving its * `chat-turn-snapshots` key to `DEAD_KEYS` in `lib/persisted-keys`; its toggle @@ -33,7 +32,7 @@ export const useChatTurnSnapshotsStore = create()( ); export function useChatTurnSnapshotsEnabled(): boolean { - const flag = useFeatureFlagEnabled(FEATURE_FLAGS.ACP_CHAT) === true; + const chatEnabled = useAcpChatEnabled(); const enabled = useChatTurnSnapshotsStore((state) => state.enabled); - return flag && enabled; + return chatEnabled && enabled; } From a3f2a135e479087a4ac3bfcccb77a4a0ca19da4a Mon Sep 17 00:00:00 2001 From: Harshith Mullapudi <17528887+harshithmullapudi@users.noreply.github.com> Date: Fri, 30 Oct 2026 18:43:07 +0000 Subject: [PATCH 5/9] feat(mobile): add Chat experimental switch, off by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Device-local switch in Settings → Experimental replaces the acp-chat PostHog flag in every mobile chat gate. Cloud workspace creation (composer and voice tool) sends it as `surface`. --- apps/mobile/lib/voice/tools/data.ts | 8 +++++ .../useCreateCloudWorkspace.ts | 7 +++++ .../useHostTerminals/useHostTerminals.ts | 5 ++- .../useCreateTerminalWorkspace.ts | 5 ++- .../settings/SettingsScreen.tsx | 29 ++++++++++++++++- .../stores/acpChatStore/acpChatStore.ts | 31 +++++++++++++++++++ .../stores/acpChatStore/index.ts | 1 + .../[id]/WorkspaceScreen/WorkspaceScreen.tsx | 5 ++- .../[id]/new-session/NewSessionSheet.tsx | 5 ++- .../workspace/[id]/sessions/SessionsSheet.tsx | 5 ++- packages/i18n/locales/cs/messages.po | 3 ++ packages/i18n/locales/de/messages.po | 3 ++ packages/i18n/locales/en/messages.po | 3 ++ packages/i18n/locales/es/messages.po | 3 ++ packages/i18n/locales/fr/messages.po | 3 ++ packages/i18n/locales/id/messages.po | 3 ++ packages/i18n/locales/it/messages.po | 3 ++ packages/i18n/locales/ja/messages.po | 3 ++ packages/i18n/locales/ko/messages.po | 3 ++ packages/i18n/locales/nl/messages.po | 3 ++ packages/i18n/locales/pl/messages.po | 3 ++ packages/i18n/locales/pt-BR/messages.po | 3 ++ packages/i18n/locales/ru/messages.po | 3 ++ packages/i18n/locales/tr/messages.po | 3 ++ packages/i18n/locales/vi/messages.po | 3 ++ packages/i18n/locales/zh-CN/messages.po | 3 ++ packages/i18n/locales/zh-TW/messages.po | 3 ++ 27 files changed, 136 insertions(+), 16 deletions(-) create mode 100644 apps/mobile/screens/(authenticated)/stores/acpChatStore/acpChatStore.ts create mode 100644 apps/mobile/screens/(authenticated)/stores/acpChatStore/index.ts diff --git a/apps/mobile/lib/voice/tools/data.ts b/apps/mobile/lib/voice/tools/data.ts index 705ca8eaf9a..c8c9a447319 100644 --- a/apps/mobile/lib/voice/tools/data.ts +++ b/apps/mobile/lib/voice/tools/data.ts @@ -16,6 +16,7 @@ import { } from "@/lib/host-service/client"; import { ensureSandboxAccess } from "@/lib/sandbox-access"; import { apiClient } from "@/lib/trpc/client"; +import { useAcpChatStore } from "@/screens/(authenticated)/stores/acpChatStore"; import { htmlToText } from "./htmlToText"; import { type VoiceData, @@ -476,6 +477,13 @@ export function createVoiceData({ environmentId, prompt, agent, + ...(agent + ? { + surface: useAcpChatStore.getState().enabled + ? "chat" + : "terminal", + } + : {}), }), HOST_TIMEOUT_MS * 4, "The new workspace", diff --git a/apps/mobile/screens/(authenticated)/(home)/home/components/NewChatWidget/hooks/useCreateCloudWorkspace/useCreateCloudWorkspace.ts b/apps/mobile/screens/(authenticated)/(home)/home/components/NewChatWidget/hooks/useCreateCloudWorkspace/useCreateCloudWorkspace.ts index 4800465af79..baff9e7222e 100644 --- a/apps/mobile/screens/(authenticated)/(home)/home/components/NewChatWidget/hooks/useCreateCloudWorkspace/useCreateCloudWorkspace.ts +++ b/apps/mobile/screens/(authenticated)/(home)/home/components/NewChatWidget/hooks/useCreateCloudWorkspace/useCreateCloudWorkspace.ts @@ -10,6 +10,7 @@ import { useSession } from "@/lib/auth/client"; import { errorCopy, transportFailureKind } from "@/lib/errors"; import { posthog } from "@/lib/posthog"; import { apiClient } from "@/lib/trpc/client"; +import { useAcpChatEnabled } from "@/screens/(authenticated)/stores/acpChatStore"; import { useAppReviewStore } from "@/screens/(authenticated)/stores/appReviewStore"; interface CreateCloudWorkspaceArgs { @@ -38,6 +39,7 @@ export function useCreateCloudWorkspace() { const router = useRouter(); const queryClient = useQueryClient(); const { data: session } = useSession(); + const acpChatEnabled = useAcpChatEnabled(); const organizationId = session?.session?.activeOrganizationId ?? null; return useMutation({ @@ -68,6 +70,11 @@ export function useCreateCloudWorkspace() { agent: launchAgent, model: launchAgent ? (model ?? undefined) : undefined, effort: launchAgent ? (effort ?? undefined) : undefined, + surface: launchAgent + ? acpChatEnabled + ? "chat" + : "terminal" + : undefined, // Only with an agent to hand them to. ...(launchAgent && attachmentFileIds.length > 0 ? { attachmentFileIds } diff --git a/apps/mobile/screens/(authenticated)/(home)/home/hooks/useHostTerminals/useHostTerminals.ts b/apps/mobile/screens/(authenticated)/(home)/home/hooks/useHostTerminals/useHostTerminals.ts index 73629fe020f..9314d8014c9 100644 --- a/apps/mobile/screens/(authenticated)/(home)/home/hooks/useHostTerminals/useHostTerminals.ts +++ b/apps/mobile/screens/(authenticated)/(home)/home/hooks/useHostTerminals/useHostTerminals.ts @@ -1,13 +1,12 @@ import { presetForAnyHarness } from "@superset/chat/core"; -import { FEATURE_FLAGS } from "@superset/shared/constants"; import { useQueries } from "@tanstack/react-query"; -import { useFeatureFlag } from "posthog-react-native"; import { useMemo } from "react"; import { getChatTransport } from "@/lib/chat"; import { getHostServiceClientByUrl, hostServiceUrl, } from "@/lib/host-service/client"; +import { useAcpChatEnabled } from "@/screens/(authenticated)/stores/acpChatStore"; import { useTerminalSeenStore } from "@/screens/(authenticated)/stores/terminalSeenStore"; import { type LiveChat, listLiveChats } from "./utils/listLiveChats"; @@ -133,7 +132,7 @@ export function useHostsTerminals( hosts: TerminalsHost[], ): UseHostTerminalsResult { const terminalSeenAt = useTerminalSeenStore((state) => state.terminalSeenAt); - const acpChat = Boolean(useFeatureFlag(FEATURE_FLAGS.ACP_CHAT)); + const acpChat = useAcpChatEnabled(); const online = useMemo( () => diff --git a/apps/mobile/screens/(authenticated)/hooks/useCreateTerminalWorkspace/useCreateTerminalWorkspace.ts b/apps/mobile/screens/(authenticated)/hooks/useCreateTerminalWorkspace/useCreateTerminalWorkspace.ts index 291683faa79..bcef483a15e 100644 --- a/apps/mobile/screens/(authenticated)/hooks/useCreateTerminalWorkspace/useCreateTerminalWorkspace.ts +++ b/apps/mobile/screens/(authenticated)/hooks/useCreateTerminalWorkspace/useCreateTerminalWorkspace.ts @@ -5,11 +5,9 @@ import { getAgentEfforts, getAgentModelSupport, } from "@superset/shared/agent-models"; -import { FEATURE_FLAGS } from "@superset/shared/constants"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { randomUUID } from "expo-crypto"; import { useRouter } from "expo-router"; -import { useFeatureFlag } from "posthog-react-native"; import { Alert } from "react-native"; import { getHostWorkspacesQueryKey } from "@/hooks/useHostWorkspaces"; import { asAttachmentError } from "@/lib/attachments/errors"; @@ -19,6 +17,7 @@ import { getHostServiceClientByUrl } from "@/lib/host-service/client"; import { isMissingProcedureError } from "@/lib/host-service/errors"; import { posthog } from "@/lib/posthog"; import { getHostTerminalsQueryKey } from "@/screens/(authenticated)/(home)/home/hooks/useHostTerminals"; +import { useAcpChatEnabled } from "@/screens/(authenticated)/stores/acpChatStore"; import { useAppReviewStore } from "@/screens/(authenticated)/stores/appReviewStore"; import { usePendingChatLaunchStore } from "@/screens/(authenticated)/stores/pendingChatLaunchStore"; import { @@ -91,7 +90,7 @@ export function useCreateTerminalWorkspace() { const startPending = usePendingWorkspaceCreatesStore((state) => state.start); const failPending = usePendingWorkspaceCreatesStore((state) => state.fail); const clearPending = usePendingWorkspaceCreatesStore((state) => state.clear); - const acpChat = Boolean(useFeatureFlag(FEATURE_FLAGS.ACP_CHAT)); + const acpChat = useAcpChatEnabled(); const queueChatLaunch = usePendingChatLaunchStore((state) => state.queue); return useMutation({ diff --git a/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx b/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx index af529237c0c..9c928b3a9e4 100644 --- a/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx +++ b/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx @@ -8,7 +8,7 @@ import { } from "@superset/shared/constants"; import * as Application from "expo-application"; import { useRouter } from "expo-router"; -import { Alert, ScrollView, View } from "react-native"; +import { Alert, ScrollView, Switch, View } from "react-native"; import { SafeAreaView, useSafeAreaInsets, @@ -26,6 +26,7 @@ import { ListRow } from "@/screens/(authenticated)/components/ListRow"; import { ListRowValue } from "@/screens/(authenticated)/components/ListRowValue"; import { OrganizationAvatar } from "@/screens/(authenticated)/components/OrganizationAvatar"; import { useOrganizations } from "@/screens/(authenticated)/hooks/useOrganizations"; +import { useAcpChatStore } from "@/screens/(authenticated)/stores/acpChatStore"; import { SettingsSection } from "./components/SettingsSection"; import { UserAvatar } from "./components/UserAvatar"; import { usePlanName } from "./hooks/usePlanName"; @@ -54,6 +55,8 @@ export function SettingsScreen() { const { signOut, isSigningOut } = useSignOut(); const { deleteAccount, isDeleting } = useDeleteAccount(); const github = useGithubConnection(); + const acpChatEnabled = useAcpChatStore((state) => state.enabled); + const setAcpChatEnabled = useAcpChatStore((state) => state.setEnabled); const user = session?.user; const plan = session?.session.plan; @@ -329,6 +332,30 @@ export function SettingsScreen() { /> + + + } + label={t({ message: "Chat" })} + subtitle={t({ + message: "Open Claude and Codex sessions as chats", + })} + trailing={ + + } + isLast + /> + + void; +} + +export const useAcpChatStore = create()( + persist( + (set) => ({ + enabled: false, + setEnabled: (enabled) => set({ enabled }), + }), + { + name: "acp-chat-v1", + storage: createJSONStorage(() => AsyncStorage), + partialize: ({ enabled }) => ({ enabled }), + }, + ), +); + +export function useAcpChatEnabled(): boolean { + return useAcpChatStore((state) => state.enabled); +} diff --git a/apps/mobile/screens/(authenticated)/stores/acpChatStore/index.ts b/apps/mobile/screens/(authenticated)/stores/acpChatStore/index.ts new file mode 100644 index 00000000000..d53a728141a --- /dev/null +++ b/apps/mobile/screens/(authenticated)/stores/acpChatStore/index.ts @@ -0,0 +1 @@ +export { useAcpChatEnabled, useAcpChatStore } from "./acpChatStore"; diff --git a/apps/mobile/screens/(authenticated)/workspace/[id]/WorkspaceScreen/WorkspaceScreen.tsx b/apps/mobile/screens/(authenticated)/workspace/[id]/WorkspaceScreen/WorkspaceScreen.tsx index 167afd1c4c1..b26a1e6d37c 100644 --- a/apps/mobile/screens/(authenticated)/workspace/[id]/WorkspaceScreen/WorkspaceScreen.tsx +++ b/apps/mobile/screens/(authenticated)/workspace/[id]/WorkspaceScreen/WorkspaceScreen.tsx @@ -8,7 +8,6 @@ import type { } from "@superset/composer"; import { i18n } from "@superset/i18n"; import { BRAND } from "@superset/shared/brand"; -import { FEATURE_FLAGS } from "@superset/shared/constants"; import { TitlePress } from "@superset/title-press"; import { useQueryClient } from "@tanstack/react-query"; import * as Clipboard from "expo-clipboard"; @@ -24,7 +23,6 @@ import { SquareTerminal, TriangleAlert, } from "lucide-react-native"; -import { useFeatureFlag } from "posthog-react-native"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import type { ViewInstance } from "react-native"; import { @@ -64,6 +62,7 @@ import { import { useAgentIconUris } from "@/screens/(authenticated)/hooks/useAgentIconUris"; import { useCreateTerminalWorkspace } from "@/screens/(authenticated)/hooks/useCreateTerminalWorkspace"; import { useSlashCommands } from "@/screens/(authenticated)/hooks/useSlashCommands"; +import { useAcpChatEnabled } from "@/screens/(authenticated)/stores/acpChatStore"; import { workspaceDraftKey } from "@/screens/(authenticated)/stores/composerDraftsStore"; import { useLastSessionTabStore } from "@/screens/(authenticated)/stores/lastSessionTabStore"; import { useLastWorkspaceStore } from "@/screens/(authenticated)/stores/lastWorkspaceStore"; @@ -497,7 +496,7 @@ export function WorkspaceScreen() { ); const activeRow = rows.find((row) => row.terminalId === activeTerminalId); const activeIsChat = activeRow?.kind === "chat"; - const acpChat = Boolean(useFeatureFlag(FEATURE_FLAGS.ACP_CHAT)); + const acpChat = useAcpChatEnabled(); const { running: chatRunning, stop: stopChat } = useActiveChat( activeIsChat ? activeTerminalId : null, ); diff --git a/apps/mobile/screens/(authenticated)/workspace/[id]/new-session/NewSessionSheet.tsx b/apps/mobile/screens/(authenticated)/workspace/[id]/new-session/NewSessionSheet.tsx index 24a05450213..42472331375 100644 --- a/apps/mobile/screens/(authenticated)/workspace/[id]/new-session/NewSessionSheet.tsx +++ b/apps/mobile/screens/(authenticated)/workspace/[id]/new-session/NewSessionSheet.tsx @@ -1,11 +1,9 @@ import { Trans, useLingui } from "@lingui/react/macro"; import { acpHarnessForPreset, presetForAnyHarness } from "@superset/chat/core"; -import { FEATURE_FLAGS } from "@superset/shared/constants"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { randomUUID } from "expo-crypto"; import { Stack, useLocalSearchParams, useRouter } from "expo-router"; import { SquareTerminal } from "lucide-react-native"; -import { useFeatureFlag } from "posthog-react-native"; import { useState } from "react"; import { ActivityIndicator, Alert, ScrollView, View } from "react-native"; import { Button } from "@/components/ui/button"; @@ -28,6 +26,7 @@ import { resolveAgentLaunchPreferences, } from "@/screens/(authenticated)/hooks/useAgentLaunchPreferences"; import { useHostAgentConfigs } from "@/screens/(authenticated)/hooks/useHostAgentConfigs"; +import { useAcpChatEnabled } from "@/screens/(authenticated)/stores/acpChatStore"; import { usePendingChatLaunchStore } from "@/screens/(authenticated)/stores/pendingChatLaunchStore"; import { hostStartsChats } from "@/screens/(authenticated)/utils/hostStartsChats"; import { useHostCompatibility } from "../hooks/useHostCompatibility"; @@ -44,7 +43,7 @@ export function NewSessionSheet() { const router = useRouter(); const theme = useTheme(); const queryClient = useQueryClient(); - const acpChat = Boolean(useFeatureFlag(FEATURE_FLAGS.ACP_CHAT)); + const acpChat = useAcpChatEnabled(); const { workspace, host, isResolving } = useWorkspaceHost(id ?? null); const hostUrl = host ? hostServiceUrl(host.organizationId, host.machineId) diff --git a/apps/mobile/screens/(authenticated)/workspace/[id]/sessions/SessionsSheet.tsx b/apps/mobile/screens/(authenticated)/workspace/[id]/sessions/SessionsSheet.tsx index dee94cc50ec..022aba1ba38 100644 --- a/apps/mobile/screens/(authenticated)/workspace/[id]/sessions/SessionsSheet.tsx +++ b/apps/mobile/screens/(authenticated)/workspace/[id]/sessions/SessionsSheet.tsx @@ -1,8 +1,6 @@ import { useLingui } from "@lingui/react/macro"; -import { FEATURE_FLAGS } from "@superset/shared/constants"; import { useQueryClient } from "@tanstack/react-query"; import { Stack, useLocalSearchParams, useRouter } from "expo-router"; -import { useFeatureFlag } from "posthog-react-native"; import { useCallback, useMemo } from "react"; import { Alert } from "react-native"; import { useWorkspaceHost } from "@/hooks/useWorkspaceHost"; @@ -17,6 +15,7 @@ import { type TerminalRowData, useHostTerminals, } from "@/screens/(authenticated)/(home)/home/hooks/useHostTerminals"; +import { useAcpChatEnabled } from "@/screens/(authenticated)/stores/acpChatStore"; import { useTerminalTabOrderStore } from "@/screens/(authenticated)/stores/terminalTabOrderStore"; import { orderTerminalRows } from "../utils/orderTerminalRows"; import { SessionList } from "./components/SessionList"; @@ -30,7 +29,7 @@ import { SessionList } from "./components/SessionList"; export function SessionsSheet() { const { t } = useLingui(); const params = useLocalSearchParams<{ id: string; active?: string }>(); - const acpChat = Boolean(useFeatureFlag(FEATURE_FLAGS.ACP_CHAT)); + const acpChat = useAcpChatEnabled(); const id = params.id; const router = useRouter(); const queryClient = useQueryClient(); diff --git a/packages/i18n/locales/cs/messages.po b/packages/i18n/locales/cs/messages.po index a93a511a104..c71215bc8d7 100644 --- a/packages/i18n/locales/cs/messages.po +++ b/packages/i18n/locales/cs/messages.po @@ -13120,6 +13120,9 @@ msgstr "Otevřít nastavení správce ChatGPT" msgid "Open ChatGPT settings" msgstr "Otevřít nastavení ChatGPT" +msgid "Open Claude and Codex sessions as chats" +msgstr "Otevírat relace Claude a Codex jako chaty" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Otevírejte relace Claude a Codex v panelu chatu místo terminálu." diff --git a/packages/i18n/locales/de/messages.po b/packages/i18n/locales/de/messages.po index 0948b519279..63b1f2b77ff 100644 --- a/packages/i18n/locales/de/messages.po +++ b/packages/i18n/locales/de/messages.po @@ -13120,6 +13120,9 @@ msgstr "ChatGPT-Admin-Einstellungen öffnen" msgid "Open ChatGPT settings" msgstr "ChatGPT-Einstellungen öffnen" +msgid "Open Claude and Codex sessions as chats" +msgstr "Claude- und Codex-Sitzungen als Chats öffnen" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Claude- und Codex-Sitzungen in einem Chat-Bereich statt in einem Terminal öffnen." diff --git a/packages/i18n/locales/en/messages.po b/packages/i18n/locales/en/messages.po index 61a86bdb53a..e8dabfdb11f 100644 --- a/packages/i18n/locales/en/messages.po +++ b/packages/i18n/locales/en/messages.po @@ -13120,6 +13120,9 @@ msgstr "Open ChatGPT admin settings" msgid "Open ChatGPT settings" msgstr "Open ChatGPT settings" +msgid "Open Claude and Codex sessions as chats" +msgstr "Open Claude and Codex sessions as chats" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Open Claude and Codex sessions in a chat pane instead of a terminal." diff --git a/packages/i18n/locales/es/messages.po b/packages/i18n/locales/es/messages.po index 80f4fb56a63..41862b5bc94 100644 --- a/packages/i18n/locales/es/messages.po +++ b/packages/i18n/locales/es/messages.po @@ -13120,6 +13120,9 @@ msgstr "Abrir la configuración de administrador de ChatGPT" msgid "Open ChatGPT settings" msgstr "Abrir ajustes de ChatGPT" +msgid "Open Claude and Codex sessions as chats" +msgstr "Abrir las sesiones de Claude y Codex como chats" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Abre las sesiones de Claude y Codex en un panel de chat en lugar de en una terminal." diff --git a/packages/i18n/locales/fr/messages.po b/packages/i18n/locales/fr/messages.po index 5a42317da36..5be5d225c39 100644 --- a/packages/i18n/locales/fr/messages.po +++ b/packages/i18n/locales/fr/messages.po @@ -13120,6 +13120,9 @@ msgstr "Ouvrir les paramètres d’administration de ChatGPT" msgid "Open ChatGPT settings" msgstr "Ouvrir les réglages ChatGPT" +msgid "Open Claude and Codex sessions as chats" +msgstr "Ouvrir les sessions Claude et Codex sous forme de chats" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Ouvrez les sessions Claude et Codex dans un volet de chat au lieu d'un terminal." diff --git a/packages/i18n/locales/id/messages.po b/packages/i18n/locales/id/messages.po index 312c4b148da..5ef8b7bf19d 100644 --- a/packages/i18n/locales/id/messages.po +++ b/packages/i18n/locales/id/messages.po @@ -13120,6 +13120,9 @@ msgstr "Buka pengaturan admin ChatGPT" msgid "Open ChatGPT settings" msgstr "Buka pengaturan ChatGPT" +msgid "Open Claude and Codex sessions as chats" +msgstr "Buka sesi Claude dan Codex sebagai obrolan" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Buka sesi Claude dan Codex di panel chat, bukan di terminal." diff --git a/packages/i18n/locales/it/messages.po b/packages/i18n/locales/it/messages.po index 4f6fc040f5d..57bb496c073 100644 --- a/packages/i18n/locales/it/messages.po +++ b/packages/i18n/locales/it/messages.po @@ -13120,6 +13120,9 @@ msgstr "Apri le impostazioni di amministrazione di ChatGPT" msgid "Open ChatGPT settings" msgstr "Apri impostazioni ChatGPT" +msgid "Open Claude and Codex sessions as chats" +msgstr "Apri le sessioni di Claude e Codex come chat" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Apri le sessioni di Claude e Codex in un pannello di chat invece che in un terminale." diff --git a/packages/i18n/locales/ja/messages.po b/packages/i18n/locales/ja/messages.po index 5fcfa1e5c70..34d511aae6d 100644 --- a/packages/i18n/locales/ja/messages.po +++ b/packages/i18n/locales/ja/messages.po @@ -13120,6 +13120,9 @@ msgstr "ChatGPT の管理者設定を開く" msgid "Open ChatGPT settings" msgstr "ChatGPT の設定を開く" +msgid "Open Claude and Codex sessions as chats" +msgstr "Claude と Codex のセッションをチャットとして開く" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Claude と Codex のセッションをターミナルではなくチャットペインで開きます。" diff --git a/packages/i18n/locales/ko/messages.po b/packages/i18n/locales/ko/messages.po index d86262be447..b393e88eb67 100644 --- a/packages/i18n/locales/ko/messages.po +++ b/packages/i18n/locales/ko/messages.po @@ -13120,6 +13120,9 @@ msgstr "ChatGPT 관리자 설정 열기" msgid "Open ChatGPT settings" msgstr "ChatGPT 설정 열기" +msgid "Open Claude and Codex sessions as chats" +msgstr "Claude 및 Codex 세션을 채팅으로 열기" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Claude 및 Codex 세션을 터미널 대신 채팅 패널에서 엽니다." diff --git a/packages/i18n/locales/nl/messages.po b/packages/i18n/locales/nl/messages.po index 231bd897cff..64ebcc86337 100644 --- a/packages/i18n/locales/nl/messages.po +++ b/packages/i18n/locales/nl/messages.po @@ -13120,6 +13120,9 @@ msgstr "ChatGPT-beheerdersinstellingen openen" msgid "Open ChatGPT settings" msgstr "ChatGPT-instellingen openen" +msgid "Open Claude and Codex sessions as chats" +msgstr "Claude- en Codex-sessies als chats openen" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Open Claude- en Codex-sessies in een chatpaneel in plaats van in een terminal." diff --git a/packages/i18n/locales/pl/messages.po b/packages/i18n/locales/pl/messages.po index bbeacdfcf6d..cde2cc94d7b 100644 --- a/packages/i18n/locales/pl/messages.po +++ b/packages/i18n/locales/pl/messages.po @@ -13120,6 +13120,9 @@ msgstr "Otwórz ustawienia administratora ChatGPT" msgid "Open ChatGPT settings" msgstr "Otwórz ustawienia ChatGPT" +msgid "Open Claude and Codex sessions as chats" +msgstr "Otwieraj sesje Claude i Codex jako czaty" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Otwieraj sesje Claude i Codex w panelu czatu zamiast w terminalu." diff --git a/packages/i18n/locales/pt-BR/messages.po b/packages/i18n/locales/pt-BR/messages.po index 07a3e330357..1390dfb8b3c 100644 --- a/packages/i18n/locales/pt-BR/messages.po +++ b/packages/i18n/locales/pt-BR/messages.po @@ -13120,6 +13120,9 @@ msgstr "Abrir configurações de administrador do ChatGPT" msgid "Open ChatGPT settings" msgstr "Abrir configurações do ChatGPT" +msgid "Open Claude and Codex sessions as chats" +msgstr "Abrir sessões do Claude e do Codex como chats" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Abra sessões do Claude e do Codex em um painel de chat em vez de um terminal." diff --git a/packages/i18n/locales/ru/messages.po b/packages/i18n/locales/ru/messages.po index 31c31407ed7..a4a84598891 100644 --- a/packages/i18n/locales/ru/messages.po +++ b/packages/i18n/locales/ru/messages.po @@ -13120,6 +13120,9 @@ msgstr "Открыть настройки администратора ChatGPT" msgid "Open ChatGPT settings" msgstr "Открыть настройки ChatGPT" +msgid "Open Claude and Codex sessions as chats" +msgstr "Открывать сеансы Claude и Codex как чаты" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Открывайте сеансы Claude и Codex в панели чата, а не в терминале." diff --git a/packages/i18n/locales/tr/messages.po b/packages/i18n/locales/tr/messages.po index 41d7aca4c11..f7f6a3ad354 100644 --- a/packages/i18n/locales/tr/messages.po +++ b/packages/i18n/locales/tr/messages.po @@ -13120,6 +13120,9 @@ msgstr "ChatGPT yönetici ayarlarını aç" msgid "Open ChatGPT settings" msgstr "ChatGPT ayarlarını aç" +msgid "Open Claude and Codex sessions as chats" +msgstr "Claude ve Codex oturumlarını sohbet olarak aç" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Claude ve Codex oturumlarını terminal yerine bir sohbet panelinde açın." diff --git a/packages/i18n/locales/vi/messages.po b/packages/i18n/locales/vi/messages.po index ff80ddd8d16..290cc335237 100644 --- a/packages/i18n/locales/vi/messages.po +++ b/packages/i18n/locales/vi/messages.po @@ -13120,6 +13120,9 @@ msgstr "Mở cài đặt quản trị ChatGPT" msgid "Open ChatGPT settings" msgstr "Mở cài đặt ChatGPT" +msgid "Open Claude and Codex sessions as chats" +msgstr "Mở phiên Claude và Codex dưới dạng trò chuyện" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "Mở phiên Claude và Codex trong một khung chat thay vì terminal." diff --git a/packages/i18n/locales/zh-CN/messages.po b/packages/i18n/locales/zh-CN/messages.po index 6c01a66e7f0..fcdd40f2178 100644 --- a/packages/i18n/locales/zh-CN/messages.po +++ b/packages/i18n/locales/zh-CN/messages.po @@ -13120,6 +13120,9 @@ msgstr "打开 ChatGPT 管理员设置" msgid "Open ChatGPT settings" msgstr "打开 ChatGPT 设置" +msgid "Open Claude and Codex sessions as chats" +msgstr "以聊天形式打开 Claude 和 Codex 会话" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "在聊天窗格而不是终端中打开 Claude 和 Codex 会话。" diff --git a/packages/i18n/locales/zh-TW/messages.po b/packages/i18n/locales/zh-TW/messages.po index aec2b30fd3f..734410b9c7e 100644 --- a/packages/i18n/locales/zh-TW/messages.po +++ b/packages/i18n/locales/zh-TW/messages.po @@ -13120,6 +13120,9 @@ msgstr "開啟 ChatGPT 管理員設定" msgid "Open ChatGPT settings" msgstr "開啟 ChatGPT 設定" +msgid "Open Claude and Codex sessions as chats" +msgstr "以聊天形式開啟 Claude 和 Codex 工作階段" + msgid "Open Claude and Codex sessions in a chat pane instead of a terminal." msgstr "在聊天窗格而非終端機中開啟 Claude 和 Codex 工作階段。" From 944f2f40ed6d107025238150dde7d6a19d2f933f Mon Sep 17 00:00:00 2001 From: Harshith Mullapudi <17528887+harshithmullapudi@users.noreply.github.com> Date: Fri, 30 Oct 2026 19:19:11 +0000 Subject: [PATCH 6/9] feat: make Chat an account setting and always show existing chats The Chat experimental switch now writes users.experimental_chat through user.updateExperimentalChat and every surface reads it from the session, so desktop, mobile and the server agree. It only decides how new agent sessions open; chats that already exist (from automations, another device, or a released build) are always adopted and listed. - Drop the device-local stores; desktop's acp-chat key moves to DEAD_KEYS. - Drop the unreleased cloudWorkspace.create `surface` input: the server reads the account setting for every caller. - Desktop: chat sessions are adopted and automation run links focus chats regardless of the setting; the switch moves into AcpChatSetting. - Mobile: chats are listed, managed and stoppable regardless of the setting; only new sessions follow it. --- .../useAcpChatEnabled/useAcpChatEnabled.ts | 5 +- .../persisted-key-registry.test-data.ts | 1 - .../lib/persisted-keys/persisted-keys.ts | 2 + .../RunInWorkspacePopoverV2.tsx | 3 -- .../fixtures/checks.tsx | 13 ----- .../useAutoAdoptChatSessions.ts | 14 +---- .../useConsumeAutomationRunLink.ts | 12 ++--- .../useSubmitWorkspace/useSubmitWorkspace.ts | 2 - .../AcpChatSetting/AcpChatSetting.tsx | 51 +++++++++++++++++++ .../components/AcpChatSetting/index.ts | 1 + .../ExperimentalSettingsList.tsx | 30 +---------- apps/desktop/src/renderer/stores/acp-chat.ts | 34 ------------- .../pendingCloudChat/pendingCloudChat.test.ts | 19 +++---- .../pendingCloudChat/pendingCloudChat.ts | 4 +- apps/mobile/lib/voice/tools/data.ts | 8 --- .../useCreateCloudWorkspace.ts | 7 --- .../useHostTerminals/useHostTerminals.ts | 16 +++--- .../hooks/useAcpChatEnabled/index.ts | 1 + .../useAcpChatEnabled/useAcpChatEnabled.ts | 6 +++ .../useCreateTerminalWorkspace.ts | 2 +- .../settings/SettingsScreen.tsx | 23 +++++++-- .../stores/acpChatStore/acpChatStore.ts | 31 ----------- .../stores/acpChatStore/index.ts | 1 - .../[id]/WorkspaceScreen/WorkspaceScreen.tsx | 20 +++----- .../[id]/new-session/NewSessionSheet.tsx | 4 +- .../workspace/[id]/sessions/SessionsSheet.tsx | 26 ++++------ packages/auth/src/server.ts | 7 +++ packages/i18n/locales/cs/messages.po | 3 ++ packages/i18n/locales/de/messages.po | 3 ++ packages/i18n/locales/en/messages.po | 3 ++ packages/i18n/locales/es/messages.po | 3 ++ packages/i18n/locales/fr/messages.po | 3 ++ packages/i18n/locales/id/messages.po | 3 ++ packages/i18n/locales/it/messages.po | 3 ++ packages/i18n/locales/ja/messages.po | 3 ++ packages/i18n/locales/ko/messages.po | 3 ++ packages/i18n/locales/nl/messages.po | 3 ++ packages/i18n/locales/pl/messages.po | 3 ++ packages/i18n/locales/pt-BR/messages.po | 3 ++ packages/i18n/locales/ru/messages.po | 3 ++ packages/i18n/locales/tr/messages.po | 3 ++ packages/i18n/locales/vi/messages.po | 3 ++ packages/i18n/locales/zh-CN/messages.po | 3 ++ packages/i18n/locales/zh-TW/messages.po | 3 ++ packages/shared/src/constants.ts | 7 ++- packages/trpc/src/lib/acp-chat.ts | 16 +++--- .../router/cloud-workspace/cloud-workspace.ts | 11 +--- packages/trpc/src/router/user/user.ts | 11 ++++ 48 files changed, 203 insertions(+), 236 deletions(-) create mode 100644 apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/AcpChatSetting.tsx create mode 100644 apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/index.ts delete mode 100644 apps/desktop/src/renderer/stores/acp-chat.ts create mode 100644 apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/index.ts create mode 100644 apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/useAcpChatEnabled.ts delete mode 100644 apps/mobile/screens/(authenticated)/stores/acpChatStore/acpChatStore.ts delete mode 100644 apps/mobile/screens/(authenticated)/stores/acpChatStore/index.ts diff --git a/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts b/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts index a88e6ae7d32..0cdf7f3323e 100644 --- a/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts +++ b/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts @@ -1,5 +1,6 @@ -import { useAcpChatStore } from "renderer/stores/acp-chat"; +import { authClient } from "renderer/lib/auth-client"; export function useAcpChatEnabled(): boolean { - return useAcpChatStore((state) => state.enabled); + const { data: session } = authClient.useSession(); + return session?.user.experimentalChat === true; } diff --git a/apps/desktop/src/renderer/lib/persisted-keys/persisted-key-registry.test-data.ts b/apps/desktop/src/renderer/lib/persisted-keys/persisted-key-registry.test-data.ts index aa6ec6909a0..b161e545fd6 100644 --- a/apps/desktop/src/renderer/lib/persisted-keys/persisted-key-registry.test-data.ts +++ b/apps/desktop/src/renderer/lib/persisted-keys/persisted-key-registry.test-data.ts @@ -147,7 +147,6 @@ export const PERSISTED_KEY_REGISTRY: ReadonlyArray< ], ], ["src/renderer/stores/workspace-agents-row.ts", ["workspace-agents-row"]], - ["src/renderer/stores/acp-chat.ts", ["acp-chat"]], ["src/renderer/stores/chat-turn-snapshots.ts", ["chat-turn-snapshots"]], [ "src/renderer/routes/_authenticated/settings/usage/utils/usageLastSection/usageLastSection.ts", diff --git a/apps/desktop/src/renderer/lib/persisted-keys/persisted-keys.ts b/apps/desktop/src/renderer/lib/persisted-keys/persisted-keys.ts index b54679a95db..1ccfc53e023 100644 --- a/apps/desktop/src/renderer/lib/persisted-keys/persisted-keys.ts +++ b/apps/desktop/src/renderer/lib/persisted-keys/persisted-keys.ts @@ -9,6 +9,8 @@ interface DeadKey { * the writer. */ export const DEAD_KEYS: DeadKey[] = [ + // Device-local Chat setting; moved to the account (users.experimental_chat) + { key: "acp-chat", match: "exact" }, // The task page's inline agent picker; Start work opens New Workspace instead { key: "lastSelectedV2TaskAgent", match: "exact" }, { key: "getting-started-v1", match: "exact" }, diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/RunInWorkspacePopoverV2/RunInWorkspacePopoverV2.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/RunInWorkspacePopoverV2/RunInWorkspacePopoverV2.tsx index 270aa5fd1cb..721084b0c7a 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/RunInWorkspacePopoverV2/RunInWorkspacePopoverV2.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/RunInWorkspacePopoverV2/RunInWorkspacePopoverV2.tsx @@ -21,7 +21,6 @@ import { LuBox } from "react-icons/lu"; import { AgentSelect } from "renderer/components/AgentSelect"; import { useRecentProjects } from "renderer/hooks/host-projects/useRecentProjects"; import { useHostUrl } from "renderer/hooks/host-service/useHostTargetUrl"; -import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; import { useActiveOrganizationId } from "renderer/hooks/useActiveOrganizationId"; import { useCloudAgentChoices } from "renderer/hooks/useCloudAgentChoices"; import { useSelectedHostProjectIds } from "renderer/hooks/useSelectedHostProjectIds"; @@ -108,7 +107,6 @@ export function RunInWorkspacePopoverV2({ environments.find((environment) => environment.id === environmentId) ?? environments[0]; const createCloudWorkspace = cloudTrpc.cloudWorkspace.create.useMutation(); - const acpChatEnabled = useAcpChatEnabled(); const launchHostUrl = useHostUrl(isCloud ? null : hostId); const setUpProjectIds = useSelectedHostProjectIds(hostId); @@ -264,7 +262,6 @@ export function RunInWorkspacePopoverV2({ : { agent: selectedAgent, prompt: synthesizeTaskPrompt(task).slice(0, 20_000), - surface: acpChatEnabled ? "chat" : "terminal", }), }), ), diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/fixtures/checks.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/fixtures/checks.tsx index 2a39443dca5..4f0aff2049a 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/fixtures/checks.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/fixtures/checks.tsx @@ -50,7 +50,6 @@ let creates = 0; const changes = new Set<() => void>(); const connectionListeners = new Set<() => void>(); let refs = 0; -let acpChatEnabled = true; type Binding = { terminalId: string; agentId: string; @@ -88,9 +87,6 @@ const transport = { mock.module("@superset/workspace-client", () => ({ useWorkspaceClient: () => ({ hostUrl }), })); -mock.module("renderer/hooks/useAcpChatEnabled", () => ({ - useAcpChatEnabled: () => acpChatEnabled, -})); mock.module("renderer/hooks/host-service/useWorkspaceHostUrl", () => ({ useWorkspaceHostUrl: () => hostUrl, })); @@ -243,7 +239,6 @@ afterEach(() => { reads = 0; outlineReads = 0; creates = 0; - acpChatEnabled = true; terminalAgents = new Map(); localStorage.clear(); }); @@ -367,14 +362,6 @@ test("a launch whose stored prompt differs is held back and attached at the dead expect(creates).toBe(0); }); -test("turning agent chat off removes the waiting pane instead of leaving it stuck", async () => { - acpChatEnabled = false; - const pending = await waitingPane(); - show(pending.store, "disabled-workspace"); - await waitFor(() => expect(pending.store.getState().tabs).toHaveLength(0)); - expect(reads).toBe(0); -}); - test("a chat with no message yet backs off, and each first prompt is read once", async () => { const pending = await waitingPane(); sessions = [session("empty")]; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/useAutoAdoptChatSessions.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/useAutoAdoptChatSessions.ts index 8dfe4945b48..8ef5216e0e3 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/useAutoAdoptChatSessions.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAutoAdoptChatSessions/useAutoAdoptChatSessions.ts @@ -6,7 +6,6 @@ import { useEffect, useMemo, useRef } from "react"; import { useTerminalAgentBindings } from "renderer/hooks/host-service/useTerminalAgentBindings"; import { useWorkspaceConnectionRefresh } from "renderer/hooks/host-service/useWorkspaceConnectionRefresh"; import { useWorkspaceEvent } from "renderer/hooks/host-service/useWorkspaceEvent"; -import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; import { attachCloudChatSession, releasePendingCloudChat, @@ -65,8 +64,7 @@ export function useAutoAdoptChatSessions({ isLayoutReady, pendingTimeoutMs = PENDING_CLOUD_CHAT_TIMEOUT_MS, }: UseAutoAdoptChatSessionsArgs): void { - const acpChatEnabled = useAcpChatEnabled(); - const enabled = acpChatEnabled && isLayoutReady; + const enabled = isLayoutReady; const { hostUrl } = useWorkspaceClient(); const { transport } = useChatWiring(); const queryClient = useQueryClient(); @@ -138,16 +136,6 @@ export function useAutoAdoptChatSessions({ const refresh = useWorkspaceConnectionRefresh(workspaceId, queryKey, enabled); useWorkspaceEvent("chat:sessions-changed", workspaceId, refresh, enabled); - // biome-ignore lint/correctness/useExhaustiveDependencies: tabs re-runs it when a waiting pane is restored - useEffect(() => { - if (acpChatEnabled || !isLayoutReady) return; - for (const pending of pendingPanes([store, ...linkedStores])) { - pending.store - .getState() - .closePane({ tabId: pending.tabId, paneId: pending.paneId }); - } - }, [acpChatEnabled, isLayoutReady, store, linkedStores, tabs]); - useEffect(() => { const result = sessionsQuery.data; if (!enabled || !result || sessionsQuery.isFetching) return; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useConsumeAutomationRunLink/useConsumeAutomationRunLink.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useConsumeAutomationRunLink/useConsumeAutomationRunLink.ts index 80c0f7a0a23..a9de8f5fcf1 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useConsumeAutomationRunLink/useConsumeAutomationRunLink.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useConsumeAutomationRunLink/useConsumeAutomationRunLink.ts @@ -2,7 +2,6 @@ import type { WorkspaceStore } from "@superset/panes"; import { useWorkspaceClient, workspaceTrpc } from "@superset/workspace-client"; import { useQuery } from "@tanstack/react-query"; import { useEffect, useRef } from "react"; -import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; import type { StoreApi } from "zustand/vanilla"; import type { ConsumeSearch, PaneViewerData } from "../../types"; import { focusChatSession } from "../../utils/focusChatSession"; @@ -35,7 +34,6 @@ export function useConsumeAutomationRunLink({ consumeSearch, }: UseConsumeAutomationRunLinkArgs): void { const consumedRef = useRef>(new Set()); - const acpChat = useAcpChatEnabled(); const { hostUrl } = useWorkspaceClient(); const { transport } = useChatWiring(); const chatQuery = useQuery({ @@ -56,16 +54,13 @@ export function useConsumeAutomationRunLink({ : []; return chatSessionTarget({ result, sessions, sessionId, workspaceId }); }, - enabled: !!sessionId && acpChat && isLayoutReady, + enabled: !!sessionId && isLayoutReady, refetchOnWindowFocus: false, retry: false, }); useEffect(() => { if (!sessionId || !isLayoutReady) return; - if ( - acpChat && - (chatQuery.isFetching || (!chatQuery.isSuccess && !chatQuery.isError)) - ) + if (chatQuery.isFetching || (!chatQuery.isSuccess && !chatQuery.isError)) return; const key = `${workspaceId}:${getAutomationRunLinkConsumeKey({ type: "chat", @@ -74,13 +69,12 @@ export function useConsumeAutomationRunLink({ })}`; if (consumedRef.current.has(key)) return; consumedRef.current.add(key); - const target = acpChat && chatQuery.isSuccess ? chatQuery.data : null; + const target = chatQuery.isSuccess ? chatQuery.data : null; consumeSearch(target ? ["sessionId", "terminalId"] : ["sessionId"]); if (target) focusChatSession({ store, linkedStores, session: target }); }, [ sessionId, isLayoutReady, - acpChat, chatQuery.isSuccess, chatQuery.isError, chatQuery.isFetching, diff --git a/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/hooks/useSubmitWorkspace/useSubmitWorkspace.ts b/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/hooks/useSubmitWorkspace/useSubmitWorkspace.ts index 5c12856d7f6..aef2b6e102f 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/hooks/useSubmitWorkspace/useSubmitWorkspace.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/hooks/useSubmitWorkspace/useSubmitWorkspace.ts @@ -195,7 +195,6 @@ export function useSubmitWorkspace( model: selectedModel ?? undefined, effort: selectedEffort ?? undefined, mode: selectedMode ?? undefined, - surface: acpChatEnabled ? "chat" : "terminal", } : {}), }); @@ -206,7 +205,6 @@ export function useSubmitWorkspace( workspaceId: created.id, launch: initialLaunch, prompt: prompt.trim(), - chatEnabled: acpChatEnabled, modelId: selectedModel, modeId: selectedMode, }); diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/AcpChatSetting.tsx b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/AcpChatSetting.tsx new file mode 100644 index 00000000000..dee5faa9843 --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/AcpChatSetting.tsx @@ -0,0 +1,51 @@ +import { useLingui } from "@lingui/react/macro"; +import { Label } from "@superset/ui/label"; +import { toast } from "@superset/ui/sonner"; +import { Switch } from "@superset/ui/switch"; +import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; +import { authClient } from "renderer/lib/auth-client"; +import { cloudTrpc } from "renderer/lib/cloud-trpc"; +import { HighlightText } from "renderer/routes/_authenticated/settings/components/HighlightText"; +import { useSettingsSearchQuery } from "renderer/stores/settings-state"; + +export function AcpChatSetting() { + const { t } = useLingui(); + const searchQuery = useSettingsSearchQuery(); + const savedEnabled = useAcpChatEnabled(); + const { refetch: refetchSession } = authClient.useSession(); + const updateExperimentalChat = + cloudTrpc.user.updateExperimentalChat.useMutation({ + onSuccess: () => refetchSession({ query: { disableCookieCache: true } }), + onError: () => + toast.error(t({ message: "Couldn't update the Chat setting" })), + }); + const enabled = updateExperimentalChat.isPending + ? updateExperimentalChat.variables.enabled + : savedEnabled; + + return ( +
+
+ +

+ +

+
+ + updateExperimentalChat.mutate({ enabled: next }) + } + /> +
+ ); +} diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/index.ts b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/index.ts new file mode 100644 index 00000000000..69679884cad --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/index.ts @@ -0,0 +1 @@ +export { AcpChatSetting } from "./AcpChatSetting"; diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ExperimentalSettingsList/ExperimentalSettingsList.tsx b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ExperimentalSettingsList/ExperimentalSettingsList.tsx index 8bb43c0104a..82cb67fbd1e 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ExperimentalSettingsList/ExperimentalSettingsList.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ExperimentalSettingsList/ExperimentalSettingsList.tsx @@ -4,7 +4,6 @@ import { Label } from "@superset/ui/label"; import { Switch } from "@superset/ui/switch"; import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; import { HighlightText } from "renderer/routes/_authenticated/settings/components/HighlightText"; -import { useAcpChatStore } from "renderer/stores/acp-chat"; import { useChatTurnSnapshotsEnabled, useChatTurnSnapshotsStore, @@ -24,6 +23,7 @@ import { SETTING_ITEM_ID, type SettingItemId, } from "../../../../../utils/settings-search"; +import { AcpChatSetting } from "../AcpChatSetting"; import { WaitForSetupBeforeAgentSetting } from "../WaitForSetupBeforeAgentSetting"; interface ExperimentalSettingsListProps { @@ -54,7 +54,6 @@ export function ExperimentalSettingsList({ visibleItems, ); const acpChatEnabled = useAcpChatEnabled(); - const setAcpChatEnabled = useAcpChatStore((state) => state.setEnabled); const showChatTurnSnapshots = acpChatEnabled && isItemVisible( @@ -184,32 +183,7 @@ export function ExperimentalSettingsList({ /> )} - {showAcpChat && ( -
-
- -

- -

-
- -
- )} + {showAcpChat && } {showChatTurnSnapshots && (
diff --git a/apps/desktop/src/renderer/stores/acp-chat.ts b/apps/desktop/src/renderer/stores/acp-chat.ts deleted file mode 100644 index 983273342c9..00000000000 --- a/apps/desktop/src/renderer/stores/acp-chat.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { create } from "zustand"; -import { devtools, persist } from "zustand/middleware"; - -/** - * EXPERIMENT: the ACP chat pane, opt-in from Settings → Experimental. Read it - * through `useAcpChatEnabled`. - * - * Desktop only: automations, cloud workspaces and mobile still read the - * `acp-chat` flag. - */ -interface AcpChatState { - enabled: boolean; - setEnabled: (enabled: boolean) => void; -} - -export const useAcpChatStore = create()( - devtools( - persist( - (set) => ({ - enabled: false, - setEnabled: (enabled) => set({ enabled }), - }), - { - name: "acp-chat", - version: 1, - migrate: (persisted) => - ({ - enabled: (persisted as { enabled?: unknown })?.enabled === true, - }) as AcpChatState, - }, - ), - { name: "AcpChatStore" }, - ), -); diff --git a/apps/desktop/src/renderer/stores/workspace-creates/pendingCloudChat/pendingCloudChat.test.ts b/apps/desktop/src/renderer/stores/workspace-creates/pendingCloudChat/pendingCloudChat.test.ts index b17192cf304..74d9b52a2d5 100644 --- a/apps/desktop/src/renderer/stores/workspace-creates/pendingCloudChat/pendingCloudChat.test.ts +++ b/apps/desktop/src/renderer/stores/workspace-creates/pendingCloudChat/pendingCloudChat.test.ts @@ -48,7 +48,6 @@ test("a confirmed cloud chat has a waiting pane before any host session exists", collections: state.collections, workspaceId: "new-cloud", launch, - chatEnabled: true, }); seed(); seed(); @@ -64,20 +63,18 @@ test("a confirmed cloud chat has a waiting pane before any host session exists", expect(pending?.data).not.toHaveProperty("pendingPrompt"); }); -test("older APIs, terminal launches, and disabled chat do not seed a waiting chat", () => { +test("older APIs and terminal launches do not seed a waiting chat", () => { const state = collections(); - for (const [id, descriptor, chatEnabled] of [ - ["old-api", undefined, true], - ["no-agent", null, true], - ["terminal", { ...launch, surface: "terminal" }, true], - ["empty-prompt", { ...launch, promptHash: null }, true], - ["disabled", launch, false], + for (const [id, descriptor] of [ + ["old-api", undefined], + ["no-agent", null], + ["terminal", { ...launch, surface: "terminal" }], + ["empty-prompt", { ...launch, promptHash: null }], ] as const) { seedPendingCloudChat({ collections: state.collections, workspaceId: id, launch: descriptor, - chatEnabled, }); } expect(state.rows.size).toBe(0); @@ -99,7 +96,6 @@ test("an existing nonempty pane layout is never replaced", () => { collections: state.collections, workspaceId: "existing-cloud", launch, - chatEnabled: true, }); expect(state.rows.get("existing-cloud")?.paneLayout).toEqual(original); }); @@ -110,7 +106,6 @@ test("attaching preserves the pane, tab, draft, queued messages and model withou collections: state.collections, workspaceId: "handoff", launch, - chatEnabled: true, modelId: "chosen-model", modeId: "plan", }); @@ -154,7 +149,6 @@ test("releasing a waiting chat keeps the pane and what was typed but starts its collections: state.collections, workspaceId: "release", launch, - chatEnabled: true, modelId: "chosen-model", }); const layout = state.rows.get("release")?.paneLayout; @@ -184,7 +178,6 @@ test("the typed prompt goes to the chat that got it, not to a fresh one", () => workspaceId: "typed", launch, prompt: "fix the login bug", - chatEnabled: true, }); const layout = state.rows.get("typed")?.paneLayout; const pending = layout && pendingCloudChatPane(layout); diff --git a/apps/desktop/src/renderer/stores/workspace-creates/pendingCloudChat/pendingCloudChat.ts b/apps/desktop/src/renderer/stores/workspace-creates/pendingCloudChat/pendingCloudChat.ts index b993aefbfdf..9b9463ed855 100644 --- a/apps/desktop/src/renderer/stores/workspace-creates/pendingCloudChat/pendingCloudChat.ts +++ b/apps/desktop/src/renderer/stores/workspace-creates/pendingCloudChat/pendingCloudChat.ts @@ -32,7 +32,6 @@ export function seedPendingCloudChat({ workspaceId, launch, prompt, - chatEnabled, modelId, modeId, }: { @@ -40,11 +39,10 @@ export function seedPendingCloudChat({ workspaceId: string; launch: CloudAgentLaunchDescriptor | null | undefined; prompt?: string; - chatEnabled: boolean; modelId?: string | null; modeId?: string | null; }): void { - if (!chatEnabled || launch?.surface !== "chat" || !launch.promptHash) return; + if (launch?.surface !== "chat" || !launch.promptHash) return; const existing = collections.v2WorkspaceLocalState.get(workspaceId) ?.paneLayout as WorkspaceState | undefined; if (existing?.tabs.length) return; diff --git a/apps/mobile/lib/voice/tools/data.ts b/apps/mobile/lib/voice/tools/data.ts index c8c9a447319..705ca8eaf9a 100644 --- a/apps/mobile/lib/voice/tools/data.ts +++ b/apps/mobile/lib/voice/tools/data.ts @@ -16,7 +16,6 @@ import { } from "@/lib/host-service/client"; import { ensureSandboxAccess } from "@/lib/sandbox-access"; import { apiClient } from "@/lib/trpc/client"; -import { useAcpChatStore } from "@/screens/(authenticated)/stores/acpChatStore"; import { htmlToText } from "./htmlToText"; import { type VoiceData, @@ -477,13 +476,6 @@ export function createVoiceData({ environmentId, prompt, agent, - ...(agent - ? { - surface: useAcpChatStore.getState().enabled - ? "chat" - : "terminal", - } - : {}), }), HOST_TIMEOUT_MS * 4, "The new workspace", diff --git a/apps/mobile/screens/(authenticated)/(home)/home/components/NewChatWidget/hooks/useCreateCloudWorkspace/useCreateCloudWorkspace.ts b/apps/mobile/screens/(authenticated)/(home)/home/components/NewChatWidget/hooks/useCreateCloudWorkspace/useCreateCloudWorkspace.ts index baff9e7222e..4800465af79 100644 --- a/apps/mobile/screens/(authenticated)/(home)/home/components/NewChatWidget/hooks/useCreateCloudWorkspace/useCreateCloudWorkspace.ts +++ b/apps/mobile/screens/(authenticated)/(home)/home/components/NewChatWidget/hooks/useCreateCloudWorkspace/useCreateCloudWorkspace.ts @@ -10,7 +10,6 @@ import { useSession } from "@/lib/auth/client"; import { errorCopy, transportFailureKind } from "@/lib/errors"; import { posthog } from "@/lib/posthog"; import { apiClient } from "@/lib/trpc/client"; -import { useAcpChatEnabled } from "@/screens/(authenticated)/stores/acpChatStore"; import { useAppReviewStore } from "@/screens/(authenticated)/stores/appReviewStore"; interface CreateCloudWorkspaceArgs { @@ -39,7 +38,6 @@ export function useCreateCloudWorkspace() { const router = useRouter(); const queryClient = useQueryClient(); const { data: session } = useSession(); - const acpChatEnabled = useAcpChatEnabled(); const organizationId = session?.session?.activeOrganizationId ?? null; return useMutation({ @@ -70,11 +68,6 @@ export function useCreateCloudWorkspace() { agent: launchAgent, model: launchAgent ? (model ?? undefined) : undefined, effort: launchAgent ? (effort ?? undefined) : undefined, - surface: launchAgent - ? acpChatEnabled - ? "chat" - : "terminal" - : undefined, // Only with an agent to hand them to. ...(launchAgent && attachmentFileIds.length > 0 ? { attachmentFileIds } diff --git a/apps/mobile/screens/(authenticated)/(home)/home/hooks/useHostTerminals/useHostTerminals.ts b/apps/mobile/screens/(authenticated)/(home)/home/hooks/useHostTerminals/useHostTerminals.ts index 9314d8014c9..e6b9b95ad68 100644 --- a/apps/mobile/screens/(authenticated)/(home)/home/hooks/useHostTerminals/useHostTerminals.ts +++ b/apps/mobile/screens/(authenticated)/(home)/home/hooks/useHostTerminals/useHostTerminals.ts @@ -6,7 +6,6 @@ import { getHostServiceClientByUrl, hostServiceUrl, } from "@/lib/host-service/client"; -import { useAcpChatEnabled } from "@/screens/(authenticated)/stores/acpChatStore"; import { useTerminalSeenStore } from "@/screens/(authenticated)/stores/terminalSeenStore"; import { type LiveChat, listLiveChats } from "./utils/listLiveChats"; @@ -132,7 +131,6 @@ export function useHostsTerminals( hosts: TerminalsHost[], ): UseHostTerminalsResult { const terminalSeenAt = useTerminalSeenStore((state) => state.terminalSeenAt); - const acpChat = useAcpChatEnabled(); const online = useMemo( () => @@ -149,7 +147,7 @@ export function useHostsTerminals( const queries = useQueries({ queries: online.map((host) => ({ - queryKey: [...getHostTerminalsQueryKey(host.machineId), acpChat], + queryKey: getHostTerminalsQueryKey(host.machineId), refetchInterval: host.refetchIntervalMs, refetchIntervalInBackground: false, refetchOnWindowFocus: false, @@ -161,11 +159,9 @@ export function useHostsTerminals( client.terminal.list.query({}), client.terminalAgents.list.query(), // A host without chat, or one too old to serve it, has no chats. - acpChat - ? listLiveChats(getChatTransport(host.hostUrl)).catch( - (): LiveChat[] => [], - ) - : ([] as LiveChat[]), + listLiveChats(getChatTransport(host.hostUrl)).catch( + (): LiveChat[] => [], + ), ]); return { sessions: listed.sessions, bindings, chats }; }, @@ -221,7 +217,7 @@ export function useHostsTerminals( } } } - for (const chat of acpChat ? (query.data?.chats ?? []) : []) { + for (const chat of query.data?.chats ?? []) { const agentId = presetForAnyHarness(chat.harness) ?? null; const attention = chatAttention(chat, terminalSeenAt[chat.sessionId]); let firstSeenAt = chatFirstSeenAt.get(chat.sessionId); @@ -265,7 +261,7 @@ export function useHostsTerminals( isReady: queries.every((query) => query.isSuccess || query.isError), isError: queries.some((query) => query.isError), }; - }, [queries, terminalSeenAt, acpChat]); + }, [queries, terminalSeenAt]); } /** One host's terminals — see `useHostsTerminals`. */ diff --git a/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/index.ts b/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/index.ts new file mode 100644 index 00000000000..a2550a9abef --- /dev/null +++ b/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/index.ts @@ -0,0 +1 @@ +export { useAcpChatEnabled } from "./useAcpChatEnabled"; diff --git a/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/useAcpChatEnabled.ts b/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/useAcpChatEnabled.ts new file mode 100644 index 00000000000..2d87ef491f2 --- /dev/null +++ b/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/useAcpChatEnabled.ts @@ -0,0 +1,6 @@ +import { useSession } from "@/lib/auth/client"; + +export function useAcpChatEnabled(): boolean { + const { data: session } = useSession(); + return session?.user.experimentalChat === true; +} diff --git a/apps/mobile/screens/(authenticated)/hooks/useCreateTerminalWorkspace/useCreateTerminalWorkspace.ts b/apps/mobile/screens/(authenticated)/hooks/useCreateTerminalWorkspace/useCreateTerminalWorkspace.ts index bcef483a15e..4a8c529c94e 100644 --- a/apps/mobile/screens/(authenticated)/hooks/useCreateTerminalWorkspace/useCreateTerminalWorkspace.ts +++ b/apps/mobile/screens/(authenticated)/hooks/useCreateTerminalWorkspace/useCreateTerminalWorkspace.ts @@ -17,7 +17,7 @@ import { getHostServiceClientByUrl } from "@/lib/host-service/client"; import { isMissingProcedureError } from "@/lib/host-service/errors"; import { posthog } from "@/lib/posthog"; import { getHostTerminalsQueryKey } from "@/screens/(authenticated)/(home)/home/hooks/useHostTerminals"; -import { useAcpChatEnabled } from "@/screens/(authenticated)/stores/acpChatStore"; +import { useAcpChatEnabled } from "@/screens/(authenticated)/hooks/useAcpChatEnabled"; import { useAppReviewStore } from "@/screens/(authenticated)/stores/appReviewStore"; import { usePendingChatLaunchStore } from "@/screens/(authenticated)/stores/pendingChatLaunchStore"; import { diff --git a/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx b/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx index 9c928b3a9e4..0168699afd9 100644 --- a/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx +++ b/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx @@ -6,6 +6,7 @@ import { ACCOUNT_DELETION_GRACE_DAYS, COMPANY, } from "@superset/shared/constants"; +import { useMutation } from "@tanstack/react-query"; import * as Application from "expo-application"; import { useRouter } from "expo-router"; import { Alert, ScrollView, Switch, View } from "react-native"; @@ -21,12 +22,13 @@ import { useTheme } from "@/hooks/useTheme"; import { useSession } from "@/lib/auth/client"; import { useGithubConnection } from "@/lib/github-connection"; import { openUrl } from "@/lib/open-url"; +import { apiClient } from "@/lib/trpc/client"; import { billingSettingsUrl } from "@/lib/web-links"; import { ListRow } from "@/screens/(authenticated)/components/ListRow"; import { ListRowValue } from "@/screens/(authenticated)/components/ListRowValue"; import { OrganizationAvatar } from "@/screens/(authenticated)/components/OrganizationAvatar"; +import { useAcpChatEnabled } from "@/screens/(authenticated)/hooks/useAcpChatEnabled"; import { useOrganizations } from "@/screens/(authenticated)/hooks/useOrganizations"; -import { useAcpChatStore } from "@/screens/(authenticated)/stores/acpChatStore"; import { SettingsSection } from "./components/SettingsSection"; import { UserAvatar } from "./components/UserAvatar"; import { usePlanName } from "./hooks/usePlanName"; @@ -50,13 +52,22 @@ export function SettingsScreen() { const router = useRouter(); const theme = useTheme(); const insets = useSafeAreaInsets(); - const { data: session } = useSession(); + const { data: session, refetch: refetchSession } = useSession(); const { activeOrganization, activeOrganizationId } = useOrganizations(); const { signOut, isSigningOut } = useSignOut(); const { deleteAccount, isDeleting } = useDeleteAccount(); const github = useGithubConnection(); - const acpChatEnabled = useAcpChatStore((state) => state.enabled); - const setAcpChatEnabled = useAcpChatStore((state) => state.setEnabled); + const savedAcpChatEnabled = useAcpChatEnabled(); + const updateExperimentalChat = useMutation({ + mutationFn: (enabled: boolean) => + apiClient.user.updateExperimentalChat.mutate({ enabled }), + onSuccess: () => refetchSession({ query: { disableCookieCache: true } }), + onError: () => + Alert.alert(t({ message: "Couldn't update the Chat setting" })), + }); + const acpChatEnabled = updateExperimentalChat.isPending + ? updateExperimentalChat.variables + : savedAcpChatEnabled; const user = session?.user; const plan = session?.session.plan; @@ -348,7 +359,9 @@ export function SettingsScreen() { trailing={ + updateExperimentalChat.mutate(enabled) + } accessibilityLabel={t({ message: "Chat" })} /> } diff --git a/apps/mobile/screens/(authenticated)/stores/acpChatStore/acpChatStore.ts b/apps/mobile/screens/(authenticated)/stores/acpChatStore/acpChatStore.ts deleted file mode 100644 index 5ad02f37ac3..00000000000 --- a/apps/mobile/screens/(authenticated)/stores/acpChatStore/acpChatStore.ts +++ /dev/null @@ -1,31 +0,0 @@ -import AsyncStorage from "@react-native-async-storage/async-storage"; -import { create } from "zustand"; -import { createJSONStorage, persist } from "zustand/middleware"; - -/** - * EXPERIMENT: open Claude and Codex sessions as chats. Device-local and off - * until the person turns it on in Settings → Experimental; agents without ACP - * support open a terminal either way. - */ -interface AcpChatStore { - enabled: boolean; - setEnabled: (enabled: boolean) => void; -} - -export const useAcpChatStore = create()( - persist( - (set) => ({ - enabled: false, - setEnabled: (enabled) => set({ enabled }), - }), - { - name: "acp-chat-v1", - storage: createJSONStorage(() => AsyncStorage), - partialize: ({ enabled }) => ({ enabled }), - }, - ), -); - -export function useAcpChatEnabled(): boolean { - return useAcpChatStore((state) => state.enabled); -} diff --git a/apps/mobile/screens/(authenticated)/stores/acpChatStore/index.ts b/apps/mobile/screens/(authenticated)/stores/acpChatStore/index.ts deleted file mode 100644 index d53a728141a..00000000000 --- a/apps/mobile/screens/(authenticated)/stores/acpChatStore/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useAcpChatEnabled, useAcpChatStore } from "./acpChatStore"; diff --git a/apps/mobile/screens/(authenticated)/workspace/[id]/WorkspaceScreen/WorkspaceScreen.tsx b/apps/mobile/screens/(authenticated)/workspace/[id]/WorkspaceScreen/WorkspaceScreen.tsx index b26a1e6d37c..4e750ac2bd5 100644 --- a/apps/mobile/screens/(authenticated)/workspace/[id]/WorkspaceScreen/WorkspaceScreen.tsx +++ b/apps/mobile/screens/(authenticated)/workspace/[id]/WorkspaceScreen/WorkspaceScreen.tsx @@ -62,7 +62,6 @@ import { import { useAgentIconUris } from "@/screens/(authenticated)/hooks/useAgentIconUris"; import { useCreateTerminalWorkspace } from "@/screens/(authenticated)/hooks/useCreateTerminalWorkspace"; import { useSlashCommands } from "@/screens/(authenticated)/hooks/useSlashCommands"; -import { useAcpChatEnabled } from "@/screens/(authenticated)/stores/acpChatStore"; import { workspaceDraftKey } from "@/screens/(authenticated)/stores/composerDraftsStore"; import { useLastSessionTabStore } from "@/screens/(authenticated)/stores/lastSessionTabStore"; import { useLastWorkspaceStore } from "@/screens/(authenticated)/stores/lastWorkspaceStore"; @@ -496,7 +495,6 @@ export function WorkspaceScreen() { ); const activeRow = rows.find((row) => row.terminalId === activeTerminalId); const activeIsChat = activeRow?.kind === "chat"; - const acpChat = useAcpChatEnabled(); const { running: chatRunning, stop: stopChat } = useActiveChat( activeIsChat ? activeTerminalId : null, ); @@ -1014,13 +1012,11 @@ export function WorkspaceScreen() { {workspace ? : null} {workspace ? ( - {acpChat ? ( - - ) : null} + ) : null} diff --git a/apps/mobile/screens/(authenticated)/workspace/[id]/new-session/NewSessionSheet.tsx b/apps/mobile/screens/(authenticated)/workspace/[id]/new-session/NewSessionSheet.tsx index 42472331375..2f9aad8dcb0 100644 --- a/apps/mobile/screens/(authenticated)/workspace/[id]/new-session/NewSessionSheet.tsx +++ b/apps/mobile/screens/(authenticated)/workspace/[id]/new-session/NewSessionSheet.tsx @@ -20,13 +20,13 @@ import { useNewSessionPreferencesStore } from "@/screens/(authenticated)/(home)/ import { getHostTerminalsQueryKey } from "@/screens/(authenticated)/(home)/home/hooks/useHostTerminals"; import { AgentMark } from "@/screens/(authenticated)/(home)/new-session/agent"; import { ListRow } from "@/screens/(authenticated)/components/ListRow"; +import { useAcpChatEnabled } from "@/screens/(authenticated)/hooks/useAcpChatEnabled"; import { agentLaunchPresetId, describeAgentLaunchPreferences, resolveAgentLaunchPreferences, } from "@/screens/(authenticated)/hooks/useAgentLaunchPreferences"; import { useHostAgentConfigs } from "@/screens/(authenticated)/hooks/useHostAgentConfigs"; -import { useAcpChatEnabled } from "@/screens/(authenticated)/stores/acpChatStore"; import { usePendingChatLaunchStore } from "@/screens/(authenticated)/stores/pendingChatLaunchStore"; import { hostStartsChats } from "@/screens/(authenticated)/utils/hostStartsChats"; import { useHostCompatibility } from "../hooks/useHostCompatibility"; @@ -57,7 +57,7 @@ export function NewSessionSheet() { const presets = presetsQuery.data ?? []; const endedChatsQuery = useQuery({ queryKey: ["chat-v3", "ended", hostUrl, workspace?.id], - enabled: acpChat && !!hostUrl && !!workspace, + enabled: !!hostUrl && !!workspace, queryFn: async () => { if (!hostUrl || !workspace) return []; const rows = await getChatTransport(hostUrl).listSessions({ diff --git a/apps/mobile/screens/(authenticated)/workspace/[id]/sessions/SessionsSheet.tsx b/apps/mobile/screens/(authenticated)/workspace/[id]/sessions/SessionsSheet.tsx index 022aba1ba38..77639eaf3bf 100644 --- a/apps/mobile/screens/(authenticated)/workspace/[id]/sessions/SessionsSheet.tsx +++ b/apps/mobile/screens/(authenticated)/workspace/[id]/sessions/SessionsSheet.tsx @@ -15,7 +15,6 @@ import { type TerminalRowData, useHostTerminals, } from "@/screens/(authenticated)/(home)/home/hooks/useHostTerminals"; -import { useAcpChatEnabled } from "@/screens/(authenticated)/stores/acpChatStore"; import { useTerminalTabOrderStore } from "@/screens/(authenticated)/stores/terminalTabOrderStore"; import { orderTerminalRows } from "../utils/orderTerminalRows"; import { SessionList } from "./components/SessionList"; @@ -29,7 +28,6 @@ import { SessionList } from "./components/SessionList"; export function SessionsSheet() { const { t } = useLingui(); const params = useLocalSearchParams<{ id: string; active?: string }>(); - const acpChat = useAcpChatEnabled(); const id = params.id; const router = useRouter(); const queryClient = useQueryClient(); @@ -138,19 +136,17 @@ export function SessionsSheet() { onPress={() => router.back()} /> - {acpChat ? ( - - - router.replace(`/(authenticated)/workspace/${id}/new-session`) - } - /> - - ) : null} + + + router.replace(`/(authenticated)/workspace/${id}/new-session`) + } + /> + { - const enabled = await posthog - .isFeatureEnabled(FEATURE_FLAGS.ACP_CHAT, userId, { - sendFeatureFlagEvents: false, - }) - .catch(() => undefined); - return enabled === true; + const user = await db.query.users.findFirst({ + where: eq(users.id, userId), + columns: { experimentalChat: true }, + }); + return user?.experimentalChat === true; } diff --git a/packages/trpc/src/router/cloud-workspace/cloud-workspace.ts b/packages/trpc/src/router/cloud-workspace/cloud-workspace.ts index 1698ae3c35d..d6470e0da48 100644 --- a/packages/trpc/src/router/cloud-workspace/cloud-workspace.ts +++ b/packages/trpc/src/router/cloud-workspace/cloud-workspace.ts @@ -369,11 +369,6 @@ export const cloudWorkspaceRouter = { taskIds: z.array(z.string().uuid()).max(10).optional(), /** A size the organization offers (see `machineSizes`); omitted = its default. */ machineSize: z.enum(MACHINE_SIZES).optional(), - /** - * Where `agent` opens. Omitted by builds older than the chat - * experimental setting; those keep reading the `acp-chat` flag. - */ - surface: z.enum(["chat", "terminal"]).optional(), }), ) .mutation(async ({ ctx, input }) => { @@ -399,11 +394,7 @@ export const cloudWorkspaceRouter = { taskIds: input.taskIds, attachmentFileIds: input.attachmentFileIds, machineSize: input.machineSize, - chat: - input.surface === "chat" || - (!input.surface && - !!input.agent && - (await acpChatEnabled(ctx.userId))), + chat: !!input.agent && (await acpChatEnabled(ctx.userId)), ...(input.agent ? { launch: { diff --git a/packages/trpc/src/router/user/user.ts b/packages/trpc/src/router/user/user.ts index 15e54f7fea7..e98ea9a335d 100644 --- a/packages/trpc/src/router/user/user.ts +++ b/packages/trpc/src/router/user/user.ts @@ -117,6 +117,17 @@ export const userRouter = { return { success: true }; }), + /** The Chat experimental setting: open new ACP agent sessions as chats. */ + updateExperimentalChat: protectedProcedure + .input(z.object({ enabled: z.boolean() })) + .mutation(async ({ ctx, input }) => { + await db + .update(users) + .set({ experimentalChat: input.enabled }) + .where(eq(users.id, ctx.session.user.id)); + return { success: true }; + }), + reactivateAccount: protectedProcedure.mutation(async ({ ctx }) => { const userId = ctx.session.user.id; From 0039ecc06ddbb5b45cac5097aedfce87e7e3cb30 Mon Sep 17 00:00:00 2001 From: Harshith Mullapudi <17528887+harshithmullapudi@users.noreply.github.com> Date: Fri, 30 Oct 2026 19:45:58 +0000 Subject: [PATCH 7/9] feat(api): automations follow the owner's Chat setting Automations open as chat only when the owner has Chat on and the agent supports ACP; otherwise a terminal. Everyone starts with Chat off, so released builds, which hide chats from accounts outside the acp-chat flag, keep seeing every run. --- packages/trpc/src/router/automation/cloudDispatch.ts | 6 ++++-- packages/trpc/src/router/automation/dispatch.ts | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/trpc/src/router/automation/cloudDispatch.ts b/packages/trpc/src/router/automation/cloudDispatch.ts index 0f109cb38c9..7d538cd26fc 100644 --- a/packages/trpc/src/router/automation/cloudDispatch.ts +++ b/packages/trpc/src/router/automation/cloudDispatch.ts @@ -11,6 +11,7 @@ import { } from "@superset/shared/cloud-agent-launch"; import { SUPERSET_USER_ID_HEADER } from "@superset/shared/host-routing"; import { and, eq } from "drizzle-orm"; +import { acpChatEnabled } from "../../lib/acp-chat"; import { resolveMachineSize } from "../../lib/billing/plan"; import { cloudAccess } from "../../lib/cloud-guards"; import { @@ -77,6 +78,7 @@ export async function runInCloud( const launch = await withDeadline(prepareLaunch(args)); const { automation, prompt, placed, runId } = args; + const chat = await acpChatEnabled(automation.ownerUserId); if (launch.kind === "pinned") { const target = { baseUrl: launch.hostTarget, headers: launch.headers }; return launchAgentSession( @@ -90,7 +92,7 @@ export async function runInCloud( workspaceId: launch.row.id, agent: automation.agent, prompt, - chat: supportsCloudAgentChat(automation.agent), + chat: chat && supportsCloudAgentChat(automation.agent), previous: launch.previous, }, ); @@ -103,7 +105,7 @@ export async function runInCloud( name: automation.name.slice(0, 200), branch: launch.branch, launch: { agent: automation.agent, prompt, automationRunId: runId }, - chat: true, + chat, machineSize: ( await resolveMachineSize( automation.organizationId, diff --git a/packages/trpc/src/router/automation/dispatch.ts b/packages/trpc/src/router/automation/dispatch.ts index 6983c468286..25556bec78d 100644 --- a/packages/trpc/src/router/automation/dispatch.ts +++ b/packages/trpc/src/router/automation/dispatch.ts @@ -22,6 +22,7 @@ import { slugifyForBranch, } from "@superset/shared/workspace-launch"; import { and, eq, sql } from "drizzle-orm"; +import { acpChatEnabled } from "../../lib/acp-chat"; import { nudge } from "../../lib/realtime"; import { fetchRelayPresence } from "../../lib/relay-presence"; import { runInCloud } from "./cloudDispatch"; @@ -261,6 +262,7 @@ export async function dispatchAutomation( }) : undefined; + const chat = await acpChatEnabled(automation.ownerUserId); const hostCaller = relayHostCaller({ relayUrl, hostId: routingKey, jwt }); const runAgent = (targetWorkspaceId: string) => @@ -268,7 +270,7 @@ export async function dispatchAutomation( workspaceId: targetWorkspaceId, agent: automation.agent, prompt, - chat: true, + chat, // Only the pinned workspace holds that session; the stale-pin // recovery below branches a fresh one, which has none. ...(previous && targetWorkspaceId === automation.v2WorkspaceId From 703fa73ec25001cab3814b0fbc9f0d3e310b98ff Mon Sep 17 00:00:00 2001 From: Harshith Mullapudi <17528887+harshithmullapudi@users.noreply.github.com> Date: Fri, 30 Oct 2026 20:36:27 +0000 Subject: [PATCH 8/9] feat: read the Chat setting from user_settings, not the session Per review, the setting moves off auth.users into user_settings, so the session and auth stay untouched. - New userSettings router (get/update), mirroring channelNotificationPrefs: no row means the defaults, update upserts only the given fields. - Server reads it through loadUserSettings for automations and cloud workspace starts. - Desktop and mobile read it with a userSettings.get query; the switch writes the returned settings back into that query. - Desktop: the "Track file changes per turn" switch moves into its own component, alongside AcpChatSetting. --- .../useAcpChatEnabled/useAcpChatEnabled.ts | 6 +- .../useCreateAgentSession/fixtures/checks.tsx | 3 + .../AcpChatSetting/AcpChatSetting.tsx | 21 ++++--- .../ChatTurnSnapshotsSetting.tsx | 46 +++++++++++++++ .../ChatTurnSnapshotsSetting/index.ts | 1 + .../ExperimentalSettingsList.tsx | 49 ++-------------- .../hooks/useAcpChatEnabled/index.ts | 5 +- .../useAcpChatEnabled/useAcpChatEnabled.ts | 17 +++++- .../settings/SettingsScreen.tsx | 15 +++-- packages/auth/src/server.ts | 7 --- packages/trpc/src/lib/acp-chat.ts | 11 ---- packages/trpc/src/lib/user-settings.ts | 21 +++++++ packages/trpc/src/root.ts | 2 + .../src/router/automation/cloudDispatch.ts | 2 +- .../trpc/src/router/automation/dispatch.ts | 2 +- .../router/cloud-workspace/cloud-workspace.ts | 2 +- .../trpc/src/router/user-settings/index.ts | 1 + .../user-settings/user-settings.test.ts | 57 +++++++++++++++++++ .../src/router/user-settings/user-settings.ts | 31 ++++++++++ packages/trpc/src/router/user/user.ts | 11 ---- 20 files changed, 211 insertions(+), 99 deletions(-) create mode 100644 apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ChatTurnSnapshotsSetting/ChatTurnSnapshotsSetting.tsx create mode 100644 apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ChatTurnSnapshotsSetting/index.ts delete mode 100644 packages/trpc/src/lib/acp-chat.ts create mode 100644 packages/trpc/src/lib/user-settings.ts create mode 100644 packages/trpc/src/router/user-settings/index.ts create mode 100644 packages/trpc/src/router/user-settings/user-settings.test.ts create mode 100644 packages/trpc/src/router/user-settings/user-settings.ts diff --git a/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts b/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts index 0cdf7f3323e..8c0b4c010f0 100644 --- a/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts +++ b/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts @@ -1,6 +1,6 @@ -import { authClient } from "renderer/lib/auth-client"; +import { cloudTrpc } from "renderer/lib/cloud-trpc"; export function useAcpChatEnabled(): boolean { - const { data: session } = authClient.useSession(); - return session?.user.experimentalChat === true; + const { data } = cloudTrpc.userSettings.get.useQuery(); + return data?.experimentalChat === true; } diff --git a/apps/desktop/src/renderer/hooks/useCreateAgentSession/fixtures/checks.tsx b/apps/desktop/src/renderer/hooks/useCreateAgentSession/fixtures/checks.tsx index 6089d40073d..97511edc494 100644 --- a/apps/desktop/src/renderer/hooks/useCreateAgentSession/fixtures/checks.tsx +++ b/apps/desktop/src/renderer/hooks/useCreateAgentSession/fixtures/checks.tsx @@ -14,6 +14,9 @@ const submit = mock((_args: unknown) => ({ const navigate = mock(() => Promise.resolve()); const showError = mock(() => {}); +mock.module("renderer/hooks/useAcpChatEnabled", () => ({ + useAcpChatEnabled: () => false, +})); mock.module("renderer/hooks/useV2AgentChoices", () => ({ useV2AgentChoices: () => ({ agents }), })); diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/AcpChatSetting.tsx b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/AcpChatSetting.tsx index dee5faa9843..60e432053ec 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/AcpChatSetting.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/AcpChatSetting.tsx @@ -3,7 +3,6 @@ import { Label } from "@superset/ui/label"; import { toast } from "@superset/ui/sonner"; import { Switch } from "@superset/ui/switch"; import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; -import { authClient } from "renderer/lib/auth-client"; import { cloudTrpc } from "renderer/lib/cloud-trpc"; import { HighlightText } from "renderer/routes/_authenticated/settings/components/HighlightText"; import { useSettingsSearchQuery } from "renderer/stores/settings-state"; @@ -12,15 +11,15 @@ export function AcpChatSetting() { const { t } = useLingui(); const searchQuery = useSettingsSearchQuery(); const savedEnabled = useAcpChatEnabled(); - const { refetch: refetchSession } = authClient.useSession(); - const updateExperimentalChat = - cloudTrpc.user.updateExperimentalChat.useMutation({ - onSuccess: () => refetchSession({ query: { disableCookieCache: true } }), - onError: () => - toast.error(t({ message: "Couldn't update the Chat setting" })), - }); - const enabled = updateExperimentalChat.isPending - ? updateExperimentalChat.variables.enabled + const utils = cloudTrpc.useUtils(); + const updateSettings = cloudTrpc.userSettings.update.useMutation({ + onSuccess: (settings) => + utils.userSettings.get.setData(undefined, settings), + onError: () => + toast.error(t({ message: "Couldn't update the Chat setting" })), + }); + const enabled = updateSettings.isPending + ? updateSettings.variables.experimentalChat === true : savedEnabled; return ( @@ -43,7 +42,7 @@ export function AcpChatSetting() { id="acp-chat" checked={enabled} onCheckedChange={(next) => - updateExperimentalChat.mutate({ enabled: next }) + updateSettings.mutate({ experimentalChat: next }) } />
diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ChatTurnSnapshotsSetting/ChatTurnSnapshotsSetting.tsx b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ChatTurnSnapshotsSetting/ChatTurnSnapshotsSetting.tsx new file mode 100644 index 00000000000..a422d173738 --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ChatTurnSnapshotsSetting/ChatTurnSnapshotsSetting.tsx @@ -0,0 +1,46 @@ +import { useLingui } from "@lingui/react/macro"; +import { Label } from "@superset/ui/label"; +import { Switch } from "@superset/ui/switch"; +import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; +import { HighlightText } from "renderer/routes/_authenticated/settings/components/HighlightText"; +import { + useChatTurnSnapshotsEnabled, + useChatTurnSnapshotsStore, +} from "renderer/stores/chat-turn-snapshots"; +import { useSettingsSearchQuery } from "renderer/stores/settings-state"; + +export function ChatTurnSnapshotsSetting() { + const { t } = useLingui(); + const searchQuery = useSettingsSearchQuery(); + const acpChatEnabled = useAcpChatEnabled(); + const enabled = useChatTurnSnapshotsEnabled(); + const setEnabled = useChatTurnSnapshotsStore((state) => state.setEnabled); + if (!acpChatEnabled) return null; + + return ( +
+
+ +

+ +

+
+ +
+ ); +} diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ChatTurnSnapshotsSetting/index.ts b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ChatTurnSnapshotsSetting/index.ts new file mode 100644 index 00000000000..ef4914fd9b8 --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ChatTurnSnapshotsSetting/index.ts @@ -0,0 +1 @@ +export { ChatTurnSnapshotsSetting } from "./ChatTurnSnapshotsSetting"; diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ExperimentalSettingsList/ExperimentalSettingsList.tsx b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ExperimentalSettingsList/ExperimentalSettingsList.tsx index 82cb67fbd1e..eb4696706c4 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ExperimentalSettingsList/ExperimentalSettingsList.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ExperimentalSettingsList/ExperimentalSettingsList.tsx @@ -2,12 +2,7 @@ import { Trans, useLingui } from "@lingui/react/macro"; import { Button } from "@superset/ui/button"; import { Label } from "@superset/ui/label"; import { Switch } from "@superset/ui/switch"; -import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; import { HighlightText } from "renderer/routes/_authenticated/settings/components/HighlightText"; -import { - useChatTurnSnapshotsEnabled, - useChatTurnSnapshotsStore, -} from "renderer/stores/chat-turn-snapshots"; import { useInlineWorkspacePortsStore, usePortsDisplayMode, @@ -24,6 +19,7 @@ import { type SettingItemId, } from "../../../../../utils/settings-search"; import { AcpChatSetting } from "../AcpChatSetting"; +import { ChatTurnSnapshotsSetting } from "../ChatTurnSnapshotsSetting"; import { WaitForSetupBeforeAgentSetting } from "../WaitForSetupBeforeAgentSetting"; interface ExperimentalSettingsListProps { @@ -53,16 +49,9 @@ export function ExperimentalSettingsList({ SETTING_ITEM_ID.EXPERIMENTAL_ACP_CHAT, visibleItems, ); - const acpChatEnabled = useAcpChatEnabled(); - const showChatTurnSnapshots = - acpChatEnabled && - isItemVisible( - SETTING_ITEM_ID.EXPERIMENTAL_CHAT_TURN_SNAPSHOTS, - visibleItems, - ); - const chatTurnSnapshotsEnabled = useChatTurnSnapshotsEnabled(); - const setChatTurnSnapshotsEnabled = useChatTurnSnapshotsStore( - (state) => state.setEnabled, + const showChatTurnSnapshots = isItemVisible( + SETTING_ITEM_ID.EXPERIMENTAL_CHAT_TURN_SNAPSHOTS, + visibleItems, ); const showWaitForSetupBeforeAgent = isItemVisible( SETTING_ITEM_ID.EXPERIMENTAL_WAIT_FOR_SETUP_BEFORE_AGENT, @@ -184,35 +173,7 @@ export function ExperimentalSettingsList({
)} {showAcpChat && } - {showChatTurnSnapshots && ( -
-
- -

- -

-
- -
- )} + {showChatTurnSnapshots && } {showWaitForSetupBeforeAgent && } diff --git a/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/index.ts b/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/index.ts index a2550a9abef..23473d29213 100644 --- a/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/index.ts +++ b/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/index.ts @@ -1 +1,4 @@ -export { useAcpChatEnabled } from "./useAcpChatEnabled"; +export { + USER_SETTINGS_QUERY_KEY, + useAcpChatEnabled, +} from "./useAcpChatEnabled"; diff --git a/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/useAcpChatEnabled.ts b/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/useAcpChatEnabled.ts index 2d87ef491f2..841757618e1 100644 --- a/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/useAcpChatEnabled.ts +++ b/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/useAcpChatEnabled.ts @@ -1,6 +1,17 @@ -import { useSession } from "@/lib/auth/client"; +import { useQuery } from "@tanstack/react-query"; +import { apiClient } from "@/lib/trpc/client"; + +export const USER_SETTINGS_QUERY_KEY = [ + "cloud", + "userSettings", + "get", +] as const; export function useAcpChatEnabled(): boolean { - const { data: session } = useSession(); - return session?.user.experimentalChat === true; + const { data } = useQuery({ + queryKey: USER_SETTINGS_QUERY_KEY, + queryFn: () => apiClient.userSettings.get.query(), + staleTime: 60_000, + }); + return data?.experimentalChat === true; } diff --git a/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx b/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx index 0168699afd9..9dc3c6e0312 100644 --- a/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx +++ b/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx @@ -6,7 +6,7 @@ import { ACCOUNT_DELETION_GRACE_DAYS, COMPANY, } from "@superset/shared/constants"; -import { useMutation } from "@tanstack/react-query"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; import * as Application from "expo-application"; import { useRouter } from "expo-router"; import { Alert, ScrollView, Switch, View } from "react-native"; @@ -27,7 +27,10 @@ import { billingSettingsUrl } from "@/lib/web-links"; import { ListRow } from "@/screens/(authenticated)/components/ListRow"; import { ListRowValue } from "@/screens/(authenticated)/components/ListRowValue"; import { OrganizationAvatar } from "@/screens/(authenticated)/components/OrganizationAvatar"; -import { useAcpChatEnabled } from "@/screens/(authenticated)/hooks/useAcpChatEnabled"; +import { + USER_SETTINGS_QUERY_KEY, + useAcpChatEnabled, +} from "@/screens/(authenticated)/hooks/useAcpChatEnabled"; import { useOrganizations } from "@/screens/(authenticated)/hooks/useOrganizations"; import { SettingsSection } from "./components/SettingsSection"; import { UserAvatar } from "./components/UserAvatar"; @@ -52,7 +55,8 @@ export function SettingsScreen() { const router = useRouter(); const theme = useTheme(); const insets = useSafeAreaInsets(); - const { data: session, refetch: refetchSession } = useSession(); + const { data: session } = useSession(); + const queryClient = useQueryClient(); const { activeOrganization, activeOrganizationId } = useOrganizations(); const { signOut, isSigningOut } = useSignOut(); const { deleteAccount, isDeleting } = useDeleteAccount(); @@ -60,8 +64,9 @@ export function SettingsScreen() { const savedAcpChatEnabled = useAcpChatEnabled(); const updateExperimentalChat = useMutation({ mutationFn: (enabled: boolean) => - apiClient.user.updateExperimentalChat.mutate({ enabled }), - onSuccess: () => refetchSession({ query: { disableCookieCache: true } }), + apiClient.userSettings.update.mutate({ experimentalChat: enabled }), + onSuccess: (settings) => + queryClient.setQueryData(USER_SETTINGS_QUERY_KEY, settings), onError: () => Alert.alert(t({ message: "Couldn't update the Chat setting" })), }); diff --git a/packages/auth/src/server.ts b/packages/auth/src/server.ts index 842c56ce8cd..1ca3f664653 100644 --- a/packages/auth/src/server.ts +++ b/packages/auth/src/server.ts @@ -89,13 +89,6 @@ const userOptions = { input: false, fieldName: "deletion_requested_at", }, - experimentalChat: { - type: "boolean", - required: false, - input: false, - defaultValue: false, - fieldName: "experimental_chat", - }, }, } as const; diff --git a/packages/trpc/src/lib/acp-chat.ts b/packages/trpc/src/lib/acp-chat.ts deleted file mode 100644 index bfce489c4c9..00000000000 --- a/packages/trpc/src/lib/acp-chat.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { db } from "@superset/db/client"; -import { users } from "@superset/db/schema"; -import { eq } from "drizzle-orm"; - -export async function acpChatEnabled(userId: string): Promise { - const user = await db.query.users.findFirst({ - where: eq(users.id, userId), - columns: { experimentalChat: true }, - }); - return user?.experimentalChat === true; -} diff --git a/packages/trpc/src/lib/user-settings.ts b/packages/trpc/src/lib/user-settings.ts new file mode 100644 index 00000000000..36788c090a2 --- /dev/null +++ b/packages/trpc/src/lib/user-settings.ts @@ -0,0 +1,21 @@ +import { db } from "@superset/db/client"; +import { userSettings } from "@superset/db/schema"; +import { eq } from "drizzle-orm"; + +export interface UserSettings { + experimentalChat: boolean; +} + +export const DEFAULT_USER_SETTINGS: UserSettings = { experimentalChat: false }; + +export async function loadUserSettings(userId: string): Promise { + const row = await db.query.userSettings.findFirst({ + where: eq(userSettings.userId, userId), + columns: { experimentalChat: true }, + }); + return row ?? DEFAULT_USER_SETTINGS; +} + +export async function acpChatEnabled(userId: string): Promise { + return (await loadUserSettings(userId)).experimentalChat; +} diff --git a/packages/trpc/src/root.ts b/packages/trpc/src/root.ts index 5b59c8a09c7..c0030edaaea 100644 --- a/packages/trpc/src/root.ts +++ b/packages/trpc/src/root.ts @@ -43,6 +43,7 @@ import { taskProjectRouter } from "./router/task-project"; import { taskRecordRouter } from "./router/task-record"; import { teamRouter } from "./router/team"; import { userRouter } from "./router/user"; +import { userSettingsRouter } from "./router/user-settings"; import { v2ProjectRouter } from "./router/v2-project"; import { v2WorkspaceRouter } from "./router/v2-workspace"; import { voiceRouter } from "./router/voice"; @@ -88,6 +89,7 @@ export const appRouter = createTRPCRouter({ agentCredential: agentCredentialRouter, githubUser: githubUserRouter, user: userRouter, + userSettings: userSettingsRouter, voice: voiceRouter, // TODO(2026-10-11): drop; desktops and phones before 1.29 call these names. v2Host: { diff --git a/packages/trpc/src/router/automation/cloudDispatch.ts b/packages/trpc/src/router/automation/cloudDispatch.ts index 7d538cd26fc..5f1addcf3b7 100644 --- a/packages/trpc/src/router/automation/cloudDispatch.ts +++ b/packages/trpc/src/router/automation/cloudDispatch.ts @@ -11,7 +11,6 @@ import { } from "@superset/shared/cloud-agent-launch"; import { SUPERSET_USER_ID_HEADER } from "@superset/shared/host-routing"; import { and, eq } from "drizzle-orm"; -import { acpChatEnabled } from "../../lib/acp-chat"; import { resolveMachineSize } from "../../lib/billing/plan"; import { cloudAccess } from "../../lib/cloud-guards"; import { @@ -20,6 +19,7 @@ import { SandboxUnavailableError, sandboxHostSecretFor, } from "../../lib/sandbox"; +import { acpChatEnabled } from "../../lib/user-settings"; import { startCloudWorkspace } from "../cloud-workspace/start"; import { transitionCloudWorkspace } from "../cloud-workspace/transition"; import { diff --git a/packages/trpc/src/router/automation/dispatch.ts b/packages/trpc/src/router/automation/dispatch.ts index 25556bec78d..5cd52106895 100644 --- a/packages/trpc/src/router/automation/dispatch.ts +++ b/packages/trpc/src/router/automation/dispatch.ts @@ -22,9 +22,9 @@ import { slugifyForBranch, } from "@superset/shared/workspace-launch"; import { and, eq, sql } from "drizzle-orm"; -import { acpChatEnabled } from "../../lib/acp-chat"; import { nudge } from "../../lib/realtime"; import { fetchRelayPresence } from "../../lib/relay-presence"; +import { acpChatEnabled } from "../../lib/user-settings"; import { runInCloud } from "./cloudDispatch"; import { type HostCaller, launchAgentSession } from "./hostSession"; import { diff --git a/packages/trpc/src/router/cloud-workspace/cloud-workspace.ts b/packages/trpc/src/router/cloud-workspace/cloud-workspace.ts index d6470e0da48..daa3a8fe434 100644 --- a/packages/trpc/src/router/cloud-workspace/cloud-workspace.ts +++ b/packages/trpc/src/router/cloud-workspace/cloud-workspace.ts @@ -21,7 +21,6 @@ import type { TRPCRouterRecord } from "@trpc/server"; import { TRPCError } from "@trpc/server"; import { and, asc, desc, eq, inArray, sql } from "drizzle-orm"; import { z } from "zod"; -import { acpChatEnabled } from "../../lib/acp-chat"; import { organizationMachineSizes } from "../../lib/billing/plan"; import { assertCloudAccess, assertMember } from "../../lib/cloud-guards"; import { nudge } from "../../lib/realtime"; @@ -38,6 +37,7 @@ import { sandboxExists, stopAndSnapshot, } from "../../lib/sandbox"; +import { acpChatEnabled } from "../../lib/user-settings"; import { pushWorkspaceAccess } from "../../lib/workspace-access"; import { jwtProcedure, userError } from "../../trpc"; import { hostServiceMutation } from "../automation/relay-client"; diff --git a/packages/trpc/src/router/user-settings/index.ts b/packages/trpc/src/router/user-settings/index.ts new file mode 100644 index 00000000000..a7b74e89537 --- /dev/null +++ b/packages/trpc/src/router/user-settings/index.ts @@ -0,0 +1 @@ +export { userSettingsRouter } from "./user-settings"; diff --git a/packages/trpc/src/router/user-settings/user-settings.test.ts b/packages/trpc/src/router/user-settings/user-settings.test.ts new file mode 100644 index 00000000000..d4cb421b318 --- /dev/null +++ b/packages/trpc/src/router/user-settings/user-settings.test.ts @@ -0,0 +1,57 @@ +import { describe, expect, test } from "bun:test"; +import { db } from "@superset/db/client"; +import { stub } from "../../../test/stub"; + +let stored: { experimentalChat: boolean } | undefined; +const upserts: Array<{ values: unknown; set: unknown }> = []; + +stub(db.query.userSettings, { findFirst: async () => stored }); +stub(db, { + insert: () => ({ + values: (values: unknown) => ({ + onConflictDoUpdate: async ({ set }: { set: unknown }) => { + upserts.push({ values, set }); + stored = { + experimentalChat: (set as { experimentalChat: boolean }) + .experimentalChat, + }; + }, + }), + }), +}); + +const { userSettingsRouter } = await import("./user-settings"); +const { createCallerFactory, createTRPCContext, createTRPCRouter } = + await import("../../trpc"); + +const caller = createCallerFactory( + createTRPCRouter({ userSettings: userSettingsRouter }), +)( + createTRPCContext({ + session: { user: { id: "user-1" }, session: {} } as never, + auth: {} as never, + headers: new Headers(), + sandboxCaller: null, + }), +); + +describe("userSettings", () => { + test("an account without a row has Chat off, and update stores only what it was given", async () => { + expect(await caller.userSettings.get()).toEqual({ + experimentalChat: false, + }); + + expect( + await caller.userSettings.update({ experimentalChat: true }), + ).toEqual({ experimentalChat: true }); + expect(upserts).toEqual([ + { + values: { experimentalChat: true, userId: "user-1" }, + set: { experimentalChat: true }, + }, + ]); + + await caller.userSettings.update({}); + expect(upserts).toHaveLength(1); + }); +}); diff --git a/packages/trpc/src/router/user-settings/user-settings.ts b/packages/trpc/src/router/user-settings/user-settings.ts new file mode 100644 index 00000000000..96534252cb0 --- /dev/null +++ b/packages/trpc/src/router/user-settings/user-settings.ts @@ -0,0 +1,31 @@ +import { db } from "@superset/db/client"; +import { userSettings } from "@superset/db/schema"; +import type { TRPCRouterRecord } from "@trpc/server"; +import { z } from "zod"; +import { + DEFAULT_USER_SETTINGS, + loadUserSettings, +} from "../../lib/user-settings"; +import { protectedProcedure } from "../../trpc"; + +export const userSettingsRouter = { + get: protectedProcedure.query(({ ctx }) => + loadUserSettings(ctx.session.user.id), + ), + + update: protectedProcedure + .input(z.object({ experimentalChat: z.boolean().optional() })) + .mutation(async ({ ctx, input }) => { + const userId = ctx.session.user.id; + const set = Object.fromEntries( + Object.entries(input).filter(([, value]) => value !== undefined), + ) as Partial; + if (Object.keys(set).length > 0) { + await db + .insert(userSettings) + .values({ ...DEFAULT_USER_SETTINGS, ...set, userId }) + .onConflictDoUpdate({ target: userSettings.userId, set }); + } + return loadUserSettings(userId); + }), +} satisfies TRPCRouterRecord; diff --git a/packages/trpc/src/router/user/user.ts b/packages/trpc/src/router/user/user.ts index e98ea9a335d..15e54f7fea7 100644 --- a/packages/trpc/src/router/user/user.ts +++ b/packages/trpc/src/router/user/user.ts @@ -117,17 +117,6 @@ export const userRouter = { return { success: true }; }), - /** The Chat experimental setting: open new ACP agent sessions as chats. */ - updateExperimentalChat: protectedProcedure - .input(z.object({ enabled: z.boolean() })) - .mutation(async ({ ctx, input }) => { - await db - .update(users) - .set({ experimentalChat: input.enabled }) - .where(eq(users.id, ctx.session.user.id)); - return { success: true }; - }), - reactivateAccount: protectedProcedure.mutation(async ({ ctx }) => { const userId = ctx.session.user.id; From fd92c2cd1863b607a2e79860b936b23cbb7bd4ef Mon Sep 17 00:00:00 2001 From: Harshith Mullapudi <17528887+harshithmullapudi@users.noreply.github.com> Date: Fri, 30 Oct 2026 21:33:28 +0000 Subject: [PATCH 9/9] fix: address review on the account-level Chat setting - Launch paths wait for the setting (useResolveAcpChatEnabled) instead of reading "off" while userSettings.get loads: desktop launcher, new agent session, new workspace; mobile new terminal workspace and new session. - Desktop sign-out resets userSettings.get, so the next account never sees the previous one's value. Mobile already clears its query cache. - The Chat switch is disabled while a save is in flight, so quick toggles cannot land out of order (desktop and mobile). - "Track file changes per turn" stays visible, disabled while Chat is off, so settings search never points at a hidden control. - Comments name user_settings.experimental_chat and the Chat setting. --- .../renderer/hooks/useAcpChatEnabled/index.ts | 5 +++- .../useAcpChatEnabled/useAcpChatEnabled.ts | 14 ++++++++++ .../useCreateAgentSession/fixtures/checks.tsx | 2 +- .../useCreateAgentSession.ts | 8 +++--- .../renderer/hooks/useSignOut/useSignOut.ts | 3 ++ .../lib/persisted-keys/persisted-keys.ts | 2 +- .../useAgentSessionLauncher.ts | 8 +++--- .../useSubmitWorkspace/useSubmitWorkspace.ts | 10 +++---- .../AcpChatSetting/AcpChatSetting.tsx | 1 + .../ChatTurnSnapshotsSetting.tsx | 3 +- .../hooks/useAcpChatEnabled/index.ts | 1 + .../useAcpChatEnabled/useAcpChatEnabled.ts | 28 +++++++++++++++---- .../useCreateTerminalWorkspace.ts | 8 ++++-- .../settings/SettingsScreen.tsx | 1 + .../[id]/new-session/NewSessionSheet.tsx | 6 ++-- packages/shared/src/constants.ts | 4 +-- 16 files changed, 72 insertions(+), 32 deletions(-) diff --git a/apps/desktop/src/renderer/hooks/useAcpChatEnabled/index.ts b/apps/desktop/src/renderer/hooks/useAcpChatEnabled/index.ts index a2550a9abef..032ed40f202 100644 --- a/apps/desktop/src/renderer/hooks/useAcpChatEnabled/index.ts +++ b/apps/desktop/src/renderer/hooks/useAcpChatEnabled/index.ts @@ -1 +1,4 @@ -export { useAcpChatEnabled } from "./useAcpChatEnabled"; +export { + useAcpChatEnabled, + useResolveAcpChatEnabled, +} from "./useAcpChatEnabled"; diff --git a/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts b/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts index 8c0b4c010f0..61fdaad72a5 100644 --- a/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts +++ b/apps/desktop/src/renderer/hooks/useAcpChatEnabled/useAcpChatEnabled.ts @@ -1,6 +1,20 @@ +import { useCallback } from "react"; import { cloudTrpc } from "renderer/lib/cloud-trpc"; export function useAcpChatEnabled(): boolean { const { data } = cloudTrpc.userSettings.get.useQuery(); return data?.experimentalChat === true; } + +/** For choosing chat or terminal at launch: waits for the setting instead of reading "off" while it loads. */ +export function useResolveAcpChatEnabled(): () => Promise { + const utils = cloudTrpc.useUtils(); + return useCallback( + () => + utils.userSettings.get + .ensureData() + .then((settings) => settings.experimentalChat) + .catch(() => false), + [utils], + ); +} diff --git a/apps/desktop/src/renderer/hooks/useCreateAgentSession/fixtures/checks.tsx b/apps/desktop/src/renderer/hooks/useCreateAgentSession/fixtures/checks.tsx index 97511edc494..67b9d4a3121 100644 --- a/apps/desktop/src/renderer/hooks/useCreateAgentSession/fixtures/checks.tsx +++ b/apps/desktop/src/renderer/hooks/useCreateAgentSession/fixtures/checks.tsx @@ -15,7 +15,7 @@ const navigate = mock(() => Promise.resolve()); const showError = mock(() => {}); mock.module("renderer/hooks/useAcpChatEnabled", () => ({ - useAcpChatEnabled: () => false, + useResolveAcpChatEnabled: () => async () => false, })); mock.module("renderer/hooks/useV2AgentChoices", () => ({ useV2AgentChoices: () => ({ agents }), diff --git a/apps/desktop/src/renderer/hooks/useCreateAgentSession/useCreateAgentSession.ts b/apps/desktop/src/renderer/hooks/useCreateAgentSession/useCreateAgentSession.ts index 826677708ea..a138e9ccb50 100644 --- a/apps/desktop/src/renderer/hooks/useCreateAgentSession/useCreateAgentSession.ts +++ b/apps/desktop/src/renderer/hooks/useCreateAgentSession/useCreateAgentSession.ts @@ -4,7 +4,7 @@ import { errorMessage } from "@superset/i18n/errors"; import { toast } from "@superset/ui/sonner"; import { useNavigate } from "@tanstack/react-router"; import { useRef, useState } from "react"; -import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; +import { useResolveAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; import { useV2AgentChoices } from "renderer/hooks/useV2AgentChoices"; import { AGENT_STORAGE_KEY } from "renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/types"; import { useLocalHostService } from "renderer/routes/_authenticated/providers/LocalHostServiceProvider"; @@ -25,7 +25,7 @@ export function useCreateAgentSession() { const { machineId, activeHostUrl } = useLocalHostService(); const { agents } = useV2AgentChoices(activeHostUrl); const { submit } = useWorkspaceCreates(); - const acpChatEnabled = useAcpChatEnabled(); + const resolveAcpChatEnabled = useResolveAcpChatEnabled(); const busy = useRef(false); const [isPending, setIsPending] = useState(false); @@ -65,8 +65,8 @@ export function useCreateAgentSession() { try { const openAsChat = options.preferChat === true && - acpChatEnabled && - Boolean(acpHarnessForPreset(presetOf(choice))); + Boolean(acpHarnessForPreset(presetOf(choice))) && + (await resolveAcpChatEnabled()); const { workspaceId, completed } = submit({ hostId: machineId, snapshot: { diff --git a/apps/desktop/src/renderer/hooks/useSignOut/useSignOut.ts b/apps/desktop/src/renderer/hooks/useSignOut/useSignOut.ts index 8318c9de142..6e454d42f02 100644 --- a/apps/desktop/src/renderer/hooks/useSignOut/useSignOut.ts +++ b/apps/desktop/src/renderer/hooks/useSignOut/useSignOut.ts @@ -1,6 +1,7 @@ import { useLingui } from "@lingui/react/macro"; import { toast } from "@superset/ui/sonner"; import { authClient } from "renderer/lib/auth-client"; +import { cloudTrpc } from "renderer/lib/cloud-trpc"; import { electronTrpc } from "renderer/lib/electron-trpc"; import { posthog } from "renderer/lib/posthog"; @@ -13,6 +14,7 @@ export function useSignOut() { const { t } = useLingui(); const signOutMutation = electronTrpc.auth.signOut.useMutation(); const setAnalyticsUserId = electronTrpc.analytics.setUserId.useMutation(); + const cloudUtils = cloudTrpc.useUtils(); return async () => { posthog.reset(); @@ -24,6 +26,7 @@ export function useSignOut() { window.setTimeout(resolve, SERVER_REVOKE_TIMEOUT_MS), ), ]); + void cloudUtils.userSettings.get.reset(); try { await signOutMutation.mutateAsync(); } catch (error) { diff --git a/apps/desktop/src/renderer/lib/persisted-keys/persisted-keys.ts b/apps/desktop/src/renderer/lib/persisted-keys/persisted-keys.ts index 1ccfc53e023..bcb9037a52a 100644 --- a/apps/desktop/src/renderer/lib/persisted-keys/persisted-keys.ts +++ b/apps/desktop/src/renderer/lib/persisted-keys/persisted-keys.ts @@ -9,7 +9,7 @@ interface DeadKey { * the writer. */ export const DEAD_KEYS: DeadKey[] = [ - // Device-local Chat setting; moved to the account (users.experimental_chat) + // Device-local Chat setting; moved to the account (user_settings.experimental_chat) { key: "acp-chat", match: "exact" }, // The task page's inline agent picker; Start work opens New Workspace instead { key: "lastSelectedV2TaskAgent", match: "exact" }, diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAgentSessionLauncher/useAgentSessionLauncher.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAgentSessionLauncher/useAgentSessionLauncher.ts index 742170c14ee..8b021305524 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAgentSessionLauncher/useAgentSessionLauncher.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useAgentSessionLauncher/useAgentSessionLauncher.ts @@ -6,7 +6,7 @@ import { toast } from "@superset/ui/sonner"; import { useWorkspaceClient, workspaceTrpc } from "@superset/workspace-client"; import { useQueryClient } from "@tanstack/react-query"; import { useCallback } from "react"; -import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; +import { useResolveAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; import { useTerminalAppearance } from "renderer/hooks/useTerminalAppearance"; import { useV2AgentConfigs, @@ -63,14 +63,14 @@ export function useAgentSessionLauncher({ const { t } = useLingui(); const { mutateAsync: runAgent } = workspaceTrpc.agents.run.useMutation(); const appearance = useTerminalAppearance(); - const acpChatEnabled = useAcpChatEnabled(); + const resolveAcpChatEnabled = useResolveAcpChatEnabled(); const { hostUrl } = useWorkspaceClient(); const { data: agentConfigs } = useV2AgentConfigs(hostUrl); const queryClient = useQueryClient(); const openAgentChat = useCallback( async (input) => { - if (!acpChatEnabled) return null; + if (!(await resolveAcpChatEnabled())) return null; const configs = await queryClient .ensureQueryData(v2AgentConfigsQueryOptions(hostUrl)) .catch(() => agentConfigs ?? []); @@ -104,7 +104,7 @@ export function useAgentSessionLauncher({ } return { terminalId }; }, - [acpChatEnabled, queryClient, hostUrl, agentConfigs, store], + [resolveAcpChatEnabled, queryClient, hostUrl, agentConfigs, store], ); const openNewChat = useCallback(async () => { diff --git a/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/hooks/useSubmitWorkspace/useSubmitWorkspace.ts b/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/hooks/useSubmitWorkspace/useSubmitWorkspace.ts index aef2b6e102f..463228b1242 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/hooks/useSubmitWorkspace/useSubmitWorkspace.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/hooks/useSubmitWorkspace/useSubmitWorkspace.ts @@ -11,7 +11,7 @@ import { CLOUD_HOST_ID } from "@superset/shared/host-routing"; import { toast } from "@superset/ui/sonner"; import { useMatchRoute, useNavigate } from "@tanstack/react-router"; import { useCallback, useMemo, useRef, useState } from "react"; -import { useAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; +import { useResolveAcpChatEnabled } from "renderer/hooks/useAcpChatEnabled"; import { useActiveOrganizationId } from "renderer/hooks/useActiveOrganizationId"; import { cloudTrpc, cloudTrpcClient } from "renderer/lib/cloud-trpc"; import { draftLinkedContext } from "renderer/routes/_authenticated/components/AgentComposer/utils/linkedContextChips"; @@ -57,7 +57,7 @@ export function useSubmitWorkspace( const collections = useCollections(); const { machineId } = useLocalHostService(); const activeOrganizationId = useActiveOrganizationId(); - const acpChatEnabled = useAcpChatEnabled(); + const resolveAcpChatEnabled = useResolveAcpChatEnabled(); const createCloudWorkspace = cloudTrpc.cloudWorkspace.create.useMutation(); const utils = cloudTrpc.useUtils(); @@ -284,8 +284,8 @@ export function useSubmitWorkspace( const openAsChat = wantAgent && - acpChatEnabled && - Boolean(acpHarnessForPreset(selectedPresetId)); + Boolean(acpHarnessForPreset(selectedPresetId)) && + (await resolveAcpChatEnabled()); const agents = wantAgent ? [ { @@ -398,7 +398,7 @@ export function useSubmitWorkspace( }); }, [ activeOrganizationId, - acpChatEnabled, + resolveAcpChatEnabled, selectedPresetId, closeAndResetDraft, collections, diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/AcpChatSetting.tsx b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/AcpChatSetting.tsx index 60e432053ec..8dc0e1b8b29 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/AcpChatSetting.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/AcpChatSetting/AcpChatSetting.tsx @@ -41,6 +41,7 @@ export function AcpChatSetting() { updateSettings.mutate({ experimentalChat: next }) } diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ChatTurnSnapshotsSetting/ChatTurnSnapshotsSetting.tsx b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ChatTurnSnapshotsSetting/ChatTurnSnapshotsSetting.tsx index a422d173738..2e41b600b0e 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ChatTurnSnapshotsSetting/ChatTurnSnapshotsSetting.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/experimental/components/ExperimentalSettings/components/ChatTurnSnapshotsSetting/ChatTurnSnapshotsSetting.tsx @@ -15,8 +15,6 @@ export function ChatTurnSnapshotsSetting() { const acpChatEnabled = useAcpChatEnabled(); const enabled = useChatTurnSnapshotsEnabled(); const setEnabled = useChatTurnSnapshotsStore((state) => state.setEnabled); - if (!acpChatEnabled) return null; - return (
@@ -39,6 +37,7 @@ export function ChatTurnSnapshotsSetting() {
diff --git a/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/index.ts b/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/index.ts index 23473d29213..6df1edb001a 100644 --- a/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/index.ts +++ b/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/index.ts @@ -1,4 +1,5 @@ export { USER_SETTINGS_QUERY_KEY, useAcpChatEnabled, + useResolveAcpChatEnabled, } from "./useAcpChatEnabled"; diff --git a/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/useAcpChatEnabled.ts b/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/useAcpChatEnabled.ts index 841757618e1..e7072d53ef9 100644 --- a/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/useAcpChatEnabled.ts +++ b/apps/mobile/screens/(authenticated)/hooks/useAcpChatEnabled/useAcpChatEnabled.ts @@ -1,4 +1,5 @@ -import { useQuery } from "@tanstack/react-query"; +import { useQuery, useQueryClient } from "@tanstack/react-query"; +import { useCallback } from "react"; import { apiClient } from "@/lib/trpc/client"; export const USER_SETTINGS_QUERY_KEY = [ @@ -7,11 +8,26 @@ export const USER_SETTINGS_QUERY_KEY = [ "get", ] as const; +const userSettingsQuery = { + queryKey: USER_SETTINGS_QUERY_KEY, + queryFn: () => apiClient.userSettings.get.query(), + staleTime: 60_000, +}; + export function useAcpChatEnabled(): boolean { - const { data } = useQuery({ - queryKey: USER_SETTINGS_QUERY_KEY, - queryFn: () => apiClient.userSettings.get.query(), - staleTime: 60_000, - }); + const { data } = useQuery(userSettingsQuery); return data?.experimentalChat === true; } + +/** For choosing chat or terminal at launch: waits for the setting instead of reading "off" while it loads. */ +export function useResolveAcpChatEnabled(): () => Promise { + const queryClient = useQueryClient(); + return useCallback( + () => + queryClient + .ensureQueryData(userSettingsQuery) + .then((settings) => settings.experimentalChat) + .catch(() => false), + [queryClient], + ); +} diff --git a/apps/mobile/screens/(authenticated)/hooks/useCreateTerminalWorkspace/useCreateTerminalWorkspace.ts b/apps/mobile/screens/(authenticated)/hooks/useCreateTerminalWorkspace/useCreateTerminalWorkspace.ts index 4a8c529c94e..1dab96421ae 100644 --- a/apps/mobile/screens/(authenticated)/hooks/useCreateTerminalWorkspace/useCreateTerminalWorkspace.ts +++ b/apps/mobile/screens/(authenticated)/hooks/useCreateTerminalWorkspace/useCreateTerminalWorkspace.ts @@ -17,7 +17,7 @@ import { getHostServiceClientByUrl } from "@/lib/host-service/client"; import { isMissingProcedureError } from "@/lib/host-service/errors"; import { posthog } from "@/lib/posthog"; import { getHostTerminalsQueryKey } from "@/screens/(authenticated)/(home)/home/hooks/useHostTerminals"; -import { useAcpChatEnabled } from "@/screens/(authenticated)/hooks/useAcpChatEnabled"; +import { useResolveAcpChatEnabled } from "@/screens/(authenticated)/hooks/useAcpChatEnabled"; import { useAppReviewStore } from "@/screens/(authenticated)/stores/appReviewStore"; import { usePendingChatLaunchStore } from "@/screens/(authenticated)/stores/pendingChatLaunchStore"; import { @@ -90,7 +90,7 @@ export function useCreateTerminalWorkspace() { const startPending = usePendingWorkspaceCreatesStore((state) => state.start); const failPending = usePendingWorkspaceCreatesStore((state) => state.fail); const clearPending = usePendingWorkspaceCreatesStore((state) => state.clear); - const acpChat = useAcpChatEnabled(); + const resolveAcpChatEnabled = useResolveAcpChatEnabled(); const queueChatLaunch = usePendingChatLaunchStore((state) => state.queue); return useMutation({ @@ -100,7 +100,9 @@ export function useCreateTerminalWorkspace() { ...input }: CreateTerminalWorkspaceArgs) => { const { target, baseBranch, agentId, model, effort, message } = input; - const chatHarness = acpChat ? acpHarnessForPreset(agentId) : undefined; + const chatHarness = (await resolveAcpChatEnabled()) + ? acpHarnessForPreset(agentId) + : undefined; const workspaceId = randomUUID(); startPending({ workspaceId, diff --git a/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx b/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx index 9dc3c6e0312..6d537cb1e69 100644 --- a/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx +++ b/apps/mobile/screens/(authenticated)/settings/SettingsScreen.tsx @@ -364,6 +364,7 @@ export function SettingsScreen() { trailing={ updateExperimentalChat.mutate(enabled) } diff --git a/apps/mobile/screens/(authenticated)/workspace/[id]/new-session/NewSessionSheet.tsx b/apps/mobile/screens/(authenticated)/workspace/[id]/new-session/NewSessionSheet.tsx index 2f9aad8dcb0..26199494564 100644 --- a/apps/mobile/screens/(authenticated)/workspace/[id]/new-session/NewSessionSheet.tsx +++ b/apps/mobile/screens/(authenticated)/workspace/[id]/new-session/NewSessionSheet.tsx @@ -20,7 +20,7 @@ import { useNewSessionPreferencesStore } from "@/screens/(authenticated)/(home)/ import { getHostTerminalsQueryKey } from "@/screens/(authenticated)/(home)/home/hooks/useHostTerminals"; import { AgentMark } from "@/screens/(authenticated)/(home)/new-session/agent"; import { ListRow } from "@/screens/(authenticated)/components/ListRow"; -import { useAcpChatEnabled } from "@/screens/(authenticated)/hooks/useAcpChatEnabled"; +import { useResolveAcpChatEnabled } from "@/screens/(authenticated)/hooks/useAcpChatEnabled"; import { agentLaunchPresetId, describeAgentLaunchPreferences, @@ -43,7 +43,7 @@ export function NewSessionSheet() { const router = useRouter(); const theme = useTheme(); const queryClient = useQueryClient(); - const acpChat = useAcpChatEnabled(); + const resolveAcpChatEnabled = useResolveAcpChatEnabled(); const { workspace, host, isResolving } = useWorkspaceHost(id ?? null); const hostUrl = host ? hostServiceUrl(host.organizationId, host.machineId) @@ -125,7 +125,7 @@ export function NewSessionSheet() { const launch = async (preset: (typeof presets)[number] | null) => { if (!workspace || !hostUrl || launchingKey !== null) return; setLaunchingKey(preset?.presetId ?? "shell"); - const chatHarness = acpChat + const chatHarness = (await resolveAcpChatEnabled()) ? acpHarnessForPreset(preset?.presetId) : undefined; try { diff --git a/packages/shared/src/constants.ts b/packages/shared/src/constants.ts index a8ac7defc36..92d2717f30d 100644 --- a/packages/shared/src/constants.ts +++ b/packages/shared/src/constants.ts @@ -226,7 +226,7 @@ export const FEATURE_FLAGS = { MOBILE_LIVE_ACTIVITY: "mobile-live-activity", /** * Legacy gate for the ACP chat pane, replaced by the account's Chat - * experimental setting (`users.experimental_chat`). Read only by released + * experimental setting (`user_settings.experimental_chat`). Read only by released * desktop and mobile builds; remove it once no live build reads it. */ ACP_CHAT: "acp-chat", @@ -240,7 +240,7 @@ export const FEATURE_FLAGS = { MOBILE_PANE: "mobile-pane", /** * Shows the `pdev` agent: in the agent catalog, agent pickers - * and, with ACP_CHAT, as a chat harness (`pdev acp`). Off, unloaded or + * and, with the Chat setting on, as a chat harness (`pdev acp`). Off, unloaded or * offline all hide it. Hosts never seed it, so a user only gets it by * adding it while the flag is on. */