aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDhravya Shah <[email protected]>2025-02-18 21:51:26 -0700
committerDhravya Shah <[email protected]>2025-02-18 21:51:26 -0700
commitd5477b4ef3f1486f4de438b1582e80544ff62db0 (patch)
tree426eea9bd21d5d3a8163a1c93e95a16628b739da
parentimplemented proper hybrid search with date relevancy into consideration (diff)
downloadsupermemory-d5477b4ef3f1486f4de438b1582e80544ff62db0.tar.xz
supermemory-d5477b4ef3f1486f4de438b1582e80544ff62db0.zip
hybrid rag looks good now
-rw-r--r--apps/backend/drizzle/0018_past_inertia.sql7
-rw-r--r--apps/backend/drizzle/meta/0017_snapshot.json1222
-rw-r--r--apps/backend/drizzle/meta/0018_snapshot.json1222
-rw-r--r--apps/backend/drizzle/meta/_journal.json14
-rw-r--r--apps/backend/src/routes/actions.ts319
5 files changed, 2666 insertions, 118 deletions
diff --git a/apps/backend/drizzle/0018_past_inertia.sql b/apps/backend/drizzle/0018_past_inertia.sql
new file mode 100644
index 00000000..a7d2e321
--- /dev/null
+++ b/apps/backend/drizzle/0018_past_inertia.sql
@@ -0,0 +1,7 @@
+DROP INDEX IF EXISTS "documents_search_idx";--> statement-breakpoint
+CREATE INDEX IF NOT EXISTS "documents_search_idx" ON "documents" USING gin ((
+ setweight(to_tsvector('english', coalesce("content", '')),'A') ||
+ setweight(to_tsvector('english', coalesce("title", '')),'B') ||
+ setweight(to_tsvector('english', coalesce("description", '')),'C') ||
+ setweight(to_tsvector('english', coalesce("url", '')),'D')
+ )); \ No newline at end of file
diff --git a/apps/backend/drizzle/meta/0017_snapshot.json b/apps/backend/drizzle/meta/0017_snapshot.json
new file mode 100644
index 00000000..efd17477
--- /dev/null
+++ b/apps/backend/drizzle/meta/0017_snapshot.json
@@ -0,0 +1,1222 @@
+{
+ "id": "f8d9da82-e3be-46a9-b52e-a70dc2d24505",
+ "prevId": "23a39e70-a9c2-44cd-a3fb-22b19efef79e",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.chat_threads": {
+ "name": "chat_threads",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "bigserial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "uuid": {
+ "name": "uuid",
+ "type": "varchar(36)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "firstMessage": {
+ "name": "firstMessage",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "messages": {
+ "name": "messages",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "chat_threads_user_idx": {
+ "name": "chat_threads_user_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "chat_threads_user_id_users_id_fk": {
+ "name": "chat_threads_user_id_users_id_fk",
+ "tableFrom": "chat_threads",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "chat_threads_uuid_unique": {
+ "name": "chat_threads_uuid_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "uuid"
+ ]
+ }
+ }
+ },
+ "public.chunks": {
+ "name": "chunks",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "document_id": {
+ "name": "document_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "text_content": {
+ "name": "text_content",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "order_in_document": {
+ "name": "order_in_document",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "embeddings": {
+ "name": "embeddings",
+ "type": "vector(768)",
+ "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": {
+ "chunk_id_idx": {
+ "name": "chunk_id_idx",
+ "columns": [
+ {
+ "expression": "id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "chunk_document_id_idx": {
+ "name": "chunk_document_id_idx",
+ "columns": [
+ {
+ "expression": "document_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "embeddingIndex": {
+ "name": "embeddingIndex",
+ "columns": [
+ {
+ "expression": "embeddings",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last",
+ "opclass": "vector_cosine_ops"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "hnsw",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "chunks_document_id_documents_id_fk": {
+ "name": "chunks_document_id_documents_id_fk",
+ "tableFrom": "chunks",
+ "tableTo": "documents",
+ "columnsFrom": [
+ "document_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.content_to_space": {
+ "name": "content_to_space",
+ "schema": "",
+ "columns": {
+ "content_id": {
+ "name": "content_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "space_id": {
+ "name": "space_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "content_id_space_id_unique": {
+ "name": "content_id_space_id_unique",
+ "columns": [
+ {
+ "expression": "content_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "space_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "content_to_space_content_id_documents_id_fk": {
+ "name": "content_to_space_content_id_documents_id_fk",
+ "tableFrom": "content_to_space",
+ "tableTo": "documents",
+ "columnsFrom": [
+ "content_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "content_to_space_space_id_spaces_id_fk": {
+ "name": "content_to_space_space_id_spaces_id_fk",
+ "tableFrom": "content_to_space",
+ "tableTo": "spaces",
+ "columnsFrom": [
+ "space_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.document_type": {
+ "name": "document_type",
+ "schema": "",
+ "columns": {
+ "type": {
+ "name": "type",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.documents": {
+ "name": "documents",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "bigserial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "uuid": {
+ "name": "uuid",
+ "type": "varchar(36)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "url": {
+ "name": "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": false
+ },
+ "type": {
+ "name": "type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "title": {
+ "name": "title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "og_image": {
+ "name": "og_image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "raw": {
+ "name": "raw",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "content": {
+ "name": "content",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "is_successfully_processed": {
+ "name": "is_successfully_processed",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false,
+ "default": false
+ },
+ "error_message": {
+ "name": "error_message",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "content_hash": {
+ "name": "content_hash",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "document_id_idx": {
+ "name": "document_id_idx",
+ "columns": [
+ {
+ "expression": "id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "document_uuid_idx": {
+ "name": "document_uuid_idx",
+ "columns": [
+ {
+ "expression": "uuid",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "document_type_idx": {
+ "name": "document_type_idx",
+ "columns": [
+ {
+ "expression": "type",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "document_raw_user_idx": {
+ "name": "document_raw_user_idx",
+ "columns": [
+ {
+ "expression": "raw",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "documents_search_idx": {
+ "name": "documents_search_idx",
+ "columns": [
+ {
+ "expression": "(\n setweight(to_tsvector('english', coalesce(preprocess_for_text_search(\"content\"), '')),'A') ||\n setweight(to_tsvector('english', coalesce(preprocess_for_text_search(\"title\"), '')),'B') ||\n setweight(to_tsvector('english', coalesce(preprocess_for_text_search(\"description\"), '')),'C') ||\n setweight(to_tsvector('english', coalesce(preprocess_for_text_search(\"url\"), '')),'D')\n )",
+ "asc": true,
+ "isExpression": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "gin",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "documents_type_document_type_type_fk": {
+ "name": "documents_type_document_type_type_fk",
+ "tableFrom": "documents",
+ "tableTo": "document_type",
+ "columnsFrom": [
+ "type"
+ ],
+ "columnsTo": [
+ "type"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "documents_user_id_users_id_fk": {
+ "name": "documents_user_id_users_id_fk",
+ "tableFrom": "documents",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "documents_uuid_unique": {
+ "name": "documents_uuid_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "uuid"
+ ]
+ }
+ }
+ },
+ "public.job": {
+ "name": "job",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "url": {
+ "name": "url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "attempts": {
+ "name": "attempts",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "lastAttemptAt": {
+ "name": "lastAttemptAt",
+ "type": "timestamp with time zone",
+ "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": false
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "user_id_url_idx": {
+ "name": "user_id_url_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "url",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "job_user_id_users_id_fk": {
+ "name": "job_user_id_users_id_fk",
+ "tableFrom": "job",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.saved_spaces": {
+ "name": "saved_spaces",
+ "schema": "",
+ "columns": {
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "space_id": {
+ "name": "space_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "saved_at": {
+ "name": "saved_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "saved_spaces_user_space_idx": {
+ "name": "saved_spaces_user_space_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "space_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "saved_spaces_user_id_users_id_fk": {
+ "name": "saved_spaces_user_id_users_id_fk",
+ "tableFrom": "saved_spaces",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "saved_spaces_space_id_spaces_id_fk": {
+ "name": "saved_spaces_space_id_spaces_id_fk",
+ "tableFrom": "saved_spaces",
+ "tableTo": "spaces",
+ "columnsFrom": [
+ "space_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.space_access": {
+ "name": "space_access",
+ "schema": "",
+ "columns": {
+ "space_id": {
+ "name": "space_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_email": {
+ "name": "user_email",
+ "type": "varchar(512)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "access_type": {
+ "name": "access_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'read'"
+ }
+ },
+ "indexes": {
+ "space_id_user_email_idx": {
+ "name": "space_id_user_email_idx",
+ "columns": [
+ {
+ "expression": "space_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "user_email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "space_access_space_id_spaces_id_fk": {
+ "name": "space_access_space_id_spaces_id_fk",
+ "tableFrom": "space_access",
+ "tableTo": "spaces",
+ "columnsFrom": [
+ "space_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "space_access_status_space_access_status_status_fk": {
+ "name": "space_access_status_space_access_status_status_fk",
+ "tableFrom": "space_access",
+ "tableTo": "space_access_status",
+ "columnsFrom": [
+ "status"
+ ],
+ "columnsTo": [
+ "status"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.space_access_status": {
+ "name": "space_access_status",
+ "schema": "",
+ "columns": {
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.space_members": {
+ "name": "space_members",
+ "schema": "",
+ "columns": {
+ "spaceId": {
+ "name": "spaceId",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "space_members_space_user_idx": {
+ "name": "space_members_space_user_idx",
+ "columns": [
+ {
+ "expression": "spaceId",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "space_members_spaceId_users_id_fk": {
+ "name": "space_members_spaceId_users_id_fk",
+ "tableFrom": "space_members",
+ "tableTo": "users",
+ "columnsFrom": [
+ "spaceId"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "restrict",
+ "onUpdate": "no action"
+ },
+ "space_members_user_id_users_id_fk": {
+ "name": "space_members_user_id_users_id_fk",
+ "tableFrom": "space_members",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "restrict",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.spaces": {
+ "name": "spaces",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "bigserial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "uuid": {
+ "name": "uuid",
+ "type": "varchar(36)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "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,
+ "default": "now()"
+ },
+ "ownerId": {
+ "name": "ownerId",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "is_public": {
+ "name": "is_public",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ }
+ },
+ "indexes": {
+ "spaces_id_idx": {
+ "name": "spaces_id_idx",
+ "columns": [
+ {
+ "expression": "id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "spaces_owner_id_idx": {
+ "name": "spaces_owner_id_idx",
+ "columns": [
+ {
+ "expression": "ownerId",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "spaces_name_idx": {
+ "name": "spaces_name_idx",
+ "columns": [
+ {
+ "expression": "name",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "spaces_uuid_unique": {
+ "name": "spaces_uuid_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "uuid"
+ ]
+ }
+ }
+ },
+ "public.users": {
+ "name": "users",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "uuid": {
+ "name": "uuid",
+ "type": "varchar(36)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "first_name": {
+ "name": "first_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "last_name": {
+ "name": "last_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email_verified": {
+ "name": "email_verified",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "profile_picture_url": {
+ "name": "profile_picture_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "telegram_id": {
+ "name": "telegram_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "has_onboarded": {
+ "name": "has_onboarded",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "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()"
+ },
+ "last_api_key_generated_at": {
+ "name": "last_api_key_generated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false,
+ "default": "now()"
+ },
+ "stripe_customer_id": {
+ "name": "stripe_customer_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "tier": {
+ "name": "tier",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'free'"
+ }
+ },
+ "indexes": {
+ "users_id_idx": {
+ "name": "users_id_idx",
+ "columns": [
+ {
+ "expression": "id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "users_uuid_idx": {
+ "name": "users_uuid_idx",
+ "columns": [
+ {
+ "expression": "uuid",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "users_email_idx": {
+ "name": "users_email_idx",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "users_name_idx": {
+ "name": "users_name_idx",
+ "columns": [
+ {
+ "expression": "first_name",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "last_name",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "users_created_at_idx": {
+ "name": "users_created_at_idx",
+ "columns": [
+ {
+ "expression": "created_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "users_telegram_id_idx": {
+ "name": "users_telegram_id_idx",
+ "columns": [
+ {
+ "expression": "telegram_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "users_uuid_unique": {
+ "name": "users_uuid_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "uuid"
+ ]
+ },
+ "users_email_unique": {
+ "name": "users_email_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "email"
+ ]
+ }
+ }
+ },
+ "public.waitlist": {
+ "name": "waitlist",
+ "schema": "",
+ "columns": {
+ "email": {
+ "name": "email",
+ "type": "varchar(512)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+} \ No newline at end of file
diff --git a/apps/backend/drizzle/meta/0018_snapshot.json b/apps/backend/drizzle/meta/0018_snapshot.json
new file mode 100644
index 00000000..6b11027b
--- /dev/null
+++ b/apps/backend/drizzle/meta/0018_snapshot.json
@@ -0,0 +1,1222 @@
+{
+ "id": "af318033-5cb6-41bf-9f68-2ebd75bd0a47",
+ "prevId": "f8d9da82-e3be-46a9-b52e-a70dc2d24505",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.chat_threads": {
+ "name": "chat_threads",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "bigserial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "uuid": {
+ "name": "uuid",
+ "type": "varchar(36)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "firstMessage": {
+ "name": "firstMessage",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "messages": {
+ "name": "messages",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "chat_threads_user_idx": {
+ "name": "chat_threads_user_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "chat_threads_user_id_users_id_fk": {
+ "name": "chat_threads_user_id_users_id_fk",
+ "tableFrom": "chat_threads",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "chat_threads_uuid_unique": {
+ "name": "chat_threads_uuid_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "uuid"
+ ]
+ }
+ }
+ },
+ "public.chunks": {
+ "name": "chunks",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "document_id": {
+ "name": "document_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "text_content": {
+ "name": "text_content",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "order_in_document": {
+ "name": "order_in_document",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "embeddings": {
+ "name": "embeddings",
+ "type": "vector(768)",
+ "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": {
+ "chunk_id_idx": {
+ "name": "chunk_id_idx",
+ "columns": [
+ {
+ "expression": "id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "chunk_document_id_idx": {
+ "name": "chunk_document_id_idx",
+ "columns": [
+ {
+ "expression": "document_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "embeddingIndex": {
+ "name": "embeddingIndex",
+ "columns": [
+ {
+ "expression": "embeddings",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last",
+ "opclass": "vector_cosine_ops"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "hnsw",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "chunks_document_id_documents_id_fk": {
+ "name": "chunks_document_id_documents_id_fk",
+ "tableFrom": "chunks",
+ "tableTo": "documents",
+ "columnsFrom": [
+ "document_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.content_to_space": {
+ "name": "content_to_space",
+ "schema": "",
+ "columns": {
+ "content_id": {
+ "name": "content_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "space_id": {
+ "name": "space_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "content_id_space_id_unique": {
+ "name": "content_id_space_id_unique",
+ "columns": [
+ {
+ "expression": "content_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "space_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "content_to_space_content_id_documents_id_fk": {
+ "name": "content_to_space_content_id_documents_id_fk",
+ "tableFrom": "content_to_space",
+ "tableTo": "documents",
+ "columnsFrom": [
+ "content_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "content_to_space_space_id_spaces_id_fk": {
+ "name": "content_to_space_space_id_spaces_id_fk",
+ "tableFrom": "content_to_space",
+ "tableTo": "spaces",
+ "columnsFrom": [
+ "space_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.document_type": {
+ "name": "document_type",
+ "schema": "",
+ "columns": {
+ "type": {
+ "name": "type",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.documents": {
+ "name": "documents",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "bigserial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "uuid": {
+ "name": "uuid",
+ "type": "varchar(36)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "url": {
+ "name": "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": false
+ },
+ "type": {
+ "name": "type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "title": {
+ "name": "title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "og_image": {
+ "name": "og_image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "raw": {
+ "name": "raw",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "content": {
+ "name": "content",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "is_successfully_processed": {
+ "name": "is_successfully_processed",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false,
+ "default": false
+ },
+ "error_message": {
+ "name": "error_message",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "content_hash": {
+ "name": "content_hash",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "document_id_idx": {
+ "name": "document_id_idx",
+ "columns": [
+ {
+ "expression": "id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "document_uuid_idx": {
+ "name": "document_uuid_idx",
+ "columns": [
+ {
+ "expression": "uuid",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "document_type_idx": {
+ "name": "document_type_idx",
+ "columns": [
+ {
+ "expression": "type",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "document_raw_user_idx": {
+ "name": "document_raw_user_idx",
+ "columns": [
+ {
+ "expression": "raw",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "documents_search_idx": {
+ "name": "documents_search_idx",
+ "columns": [
+ {
+ "expression": "(\n setweight(to_tsvector('english', coalesce(\"content\", '')),'A') ||\n setweight(to_tsvector('english', coalesce(\"title\", '')),'B') ||\n setweight(to_tsvector('english', coalesce(\"description\", '')),'C') ||\n setweight(to_tsvector('english', coalesce(\"url\", '')),'D')\n )",
+ "asc": true,
+ "isExpression": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "gin",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "documents_type_document_type_type_fk": {
+ "name": "documents_type_document_type_type_fk",
+ "tableFrom": "documents",
+ "tableTo": "document_type",
+ "columnsFrom": [
+ "type"
+ ],
+ "columnsTo": [
+ "type"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "documents_user_id_users_id_fk": {
+ "name": "documents_user_id_users_id_fk",
+ "tableFrom": "documents",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "documents_uuid_unique": {
+ "name": "documents_uuid_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "uuid"
+ ]
+ }
+ }
+ },
+ "public.job": {
+ "name": "job",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "url": {
+ "name": "url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "attempts": {
+ "name": "attempts",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "lastAttemptAt": {
+ "name": "lastAttemptAt",
+ "type": "timestamp with time zone",
+ "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": false
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "user_id_url_idx": {
+ "name": "user_id_url_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "url",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "job_user_id_users_id_fk": {
+ "name": "job_user_id_users_id_fk",
+ "tableFrom": "job",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.saved_spaces": {
+ "name": "saved_spaces",
+ "schema": "",
+ "columns": {
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "space_id": {
+ "name": "space_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "saved_at": {
+ "name": "saved_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "saved_spaces_user_space_idx": {
+ "name": "saved_spaces_user_space_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "space_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "saved_spaces_user_id_users_id_fk": {
+ "name": "saved_spaces_user_id_users_id_fk",
+ "tableFrom": "saved_spaces",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "saved_spaces_space_id_spaces_id_fk": {
+ "name": "saved_spaces_space_id_spaces_id_fk",
+ "tableFrom": "saved_spaces",
+ "tableTo": "spaces",
+ "columnsFrom": [
+ "space_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.space_access": {
+ "name": "space_access",
+ "schema": "",
+ "columns": {
+ "space_id": {
+ "name": "space_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_email": {
+ "name": "user_email",
+ "type": "varchar(512)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "access_type": {
+ "name": "access_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'read'"
+ }
+ },
+ "indexes": {
+ "space_id_user_email_idx": {
+ "name": "space_id_user_email_idx",
+ "columns": [
+ {
+ "expression": "space_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "user_email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "space_access_space_id_spaces_id_fk": {
+ "name": "space_access_space_id_spaces_id_fk",
+ "tableFrom": "space_access",
+ "tableTo": "spaces",
+ "columnsFrom": [
+ "space_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "space_access_status_space_access_status_status_fk": {
+ "name": "space_access_status_space_access_status_status_fk",
+ "tableFrom": "space_access",
+ "tableTo": "space_access_status",
+ "columnsFrom": [
+ "status"
+ ],
+ "columnsTo": [
+ "status"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.space_access_status": {
+ "name": "space_access_status",
+ "schema": "",
+ "columns": {
+ "status": {
+ "name": "status",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.space_members": {
+ "name": "space_members",
+ "schema": "",
+ "columns": {
+ "spaceId": {
+ "name": "spaceId",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "space_members_space_user_idx": {
+ "name": "space_members_space_user_idx",
+ "columns": [
+ {
+ "expression": "spaceId",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "space_members_spaceId_users_id_fk": {
+ "name": "space_members_spaceId_users_id_fk",
+ "tableFrom": "space_members",
+ "tableTo": "users",
+ "columnsFrom": [
+ "spaceId"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "restrict",
+ "onUpdate": "no action"
+ },
+ "space_members_user_id_users_id_fk": {
+ "name": "space_members_user_id_users_id_fk",
+ "tableFrom": "space_members",
+ "tableTo": "users",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "restrict",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ },
+ "public.spaces": {
+ "name": "spaces",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "bigserial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "uuid": {
+ "name": "uuid",
+ "type": "varchar(36)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "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,
+ "default": "now()"
+ },
+ "ownerId": {
+ "name": "ownerId",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "is_public": {
+ "name": "is_public",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ }
+ },
+ "indexes": {
+ "spaces_id_idx": {
+ "name": "spaces_id_idx",
+ "columns": [
+ {
+ "expression": "id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "spaces_owner_id_idx": {
+ "name": "spaces_owner_id_idx",
+ "columns": [
+ {
+ "expression": "ownerId",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "spaces_name_idx": {
+ "name": "spaces_name_idx",
+ "columns": [
+ {
+ "expression": "name",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "spaces_uuid_unique": {
+ "name": "spaces_uuid_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "uuid"
+ ]
+ }
+ }
+ },
+ "public.users": {
+ "name": "users",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "serial",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "uuid": {
+ "name": "uuid",
+ "type": "varchar(36)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "first_name": {
+ "name": "first_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "last_name": {
+ "name": "last_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email_verified": {
+ "name": "email_verified",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "profile_picture_url": {
+ "name": "profile_picture_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "telegram_id": {
+ "name": "telegram_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "has_onboarded": {
+ "name": "has_onboarded",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "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()"
+ },
+ "last_api_key_generated_at": {
+ "name": "last_api_key_generated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false,
+ "default": "now()"
+ },
+ "stripe_customer_id": {
+ "name": "stripe_customer_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "tier": {
+ "name": "tier",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'free'"
+ }
+ },
+ "indexes": {
+ "users_id_idx": {
+ "name": "users_id_idx",
+ "columns": [
+ {
+ "expression": "id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "users_uuid_idx": {
+ "name": "users_uuid_idx",
+ "columns": [
+ {
+ "expression": "uuid",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "users_email_idx": {
+ "name": "users_email_idx",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "users_name_idx": {
+ "name": "users_name_idx",
+ "columns": [
+ {
+ "expression": "first_name",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "last_name",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "users_created_at_idx": {
+ "name": "users_created_at_idx",
+ "columns": [
+ {
+ "expression": "created_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "users_telegram_id_idx": {
+ "name": "users_telegram_id_idx",
+ "columns": [
+ {
+ "expression": "telegram_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "users_uuid_unique": {
+ "name": "users_uuid_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "uuid"
+ ]
+ },
+ "users_email_unique": {
+ "name": "users_email_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "email"
+ ]
+ }
+ }
+ },
+ "public.waitlist": {
+ "name": "waitlist",
+ "schema": "",
+ "columns": {
+ "email": {
+ "name": "email",
+ "type": "varchar(512)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {}
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+} \ No newline at end of file
diff --git a/apps/backend/drizzle/meta/_journal.json b/apps/backend/drizzle/meta/_journal.json
index 7f777651..53be1a68 100644
--- a/apps/backend/drizzle/meta/_journal.json
+++ b/apps/backend/drizzle/meta/_journal.json
@@ -120,6 +120,20 @@
"when": 1739937938319,
"tag": "0016_good_deathbird",
"breakpoints": true
+ },
+ {
+ "idx": 17,
+ "version": "7",
+ "when": 1739939067023,
+ "tag": "0017_oval_misty_knight",
+ "breakpoints": true
+ },
+ {
+ "idx": 18,
+ "version": "7",
+ "when": 1739939254444,
+ "tag": "0018_past_inertia",
+ "breakpoints": true
}
]
} \ No newline at end of file
diff --git a/apps/backend/src/routes/actions.ts b/apps/backend/src/routes/actions.ts
index 0bc26052..37cc18e4 100644
--- a/apps/backend/src/routes/actions.ts
+++ b/apps/backend/src/routes/actions.ts
@@ -89,7 +89,8 @@ const actions = new Hono<{ Variables: Variables; Bindings: Env }>()
});
const googleClient = wrapAISDKModel(
- openai(c.env).chat("gpt-4o-mini-2024-07-18"));
+ openai(c.env).chat("gpt-4o-mini-2024-07-18")
+ );
// Get last user message and generate embedding in parallel with thread creation
let lastUserMessage = coreMessages.findLast((i) => i.role === "user");
@@ -124,96 +125,137 @@ const actions = new Hono<{ Variables: Variables; Bindings: Env }>()
return c.json({ error: "Failed to generate embedding" }, 500);
}
- // Pre-compute the vector similarity expression to avoid multiple calculations
- const vectorSimilarity = sql<number>`1 - (embeddings <=> ${JSON.stringify(embedding[0])}::vector)`;
- const textSearchRank = sql<number>`ts_rank_cd((
- setweight(to_tsvector('english', coalesce(${documents.content}, '')),'A') ||
- setweight(to_tsvector('english', coalesce(${documents.title}, '')),'B') ||
- setweight(to_tsvector('english', coalesce(${documents.description}, '')),'C') ||
- setweight(to_tsvector('english', coalesce(${documents.url}, '')),'D')
- ), plainto_tsquery('english', ${queryText}))`;
-
- const finalResults = await db
- .select({
- id: documents.id,
- content: documents.content,
- type: documents.type,
- url: documents.url,
- title: documents.title,
- createdAt: documents.createdAt,
- updatedAt: documents.updatedAt,
- userId: documents.userId,
- description: documents.description,
- ogImage: documents.ogImage,
- similarity: vectorSimilarity,
- textRank: textSearchRank,
- })
- .from(chunk)
- .innerJoin(documents, eq(chunk.documentId, documents.id))
- .where(
- and(
- eq(documents.userId, user.id),
- sql`${vectorSimilarity} > 0.5`
- )
- )
- .orderBy(
- desc(sql<number>`(
- 0.6 * ${vectorSimilarity} +
- 0.25 * ${textSearchRank} +
- 0.15 * (1.0 / (1.0 + extract(epoch from age(${documents.updatedAt})) / (90 * 24 * 60 * 60)))
- )::float`)
- )
- .limit(15);
-
- const cleanDocumentsForContext = finalResults.map((d) => ({
- title: d.title,
- description: d.description,
- url: d.url,
- type: d.type,
- content: d.content,
- }));
-
- if (lastUserMessage) {
- lastUserMessage.content =
- typeof lastUserMessage.content === "string"
- ? lastUserMessage.content +
- `<context>${JSON.stringify(cleanDocumentsForContext)}</context>`
- : [
- ...lastUserMessage.content,
- {
- type: "text",
- text: `<context>${JSON.stringify(cleanDocumentsForContext)}</context>`,
- },
- ];
- coreMessages[coreMessages.length - 1] = lastUserMessage;
- }
-
try {
const data = new StreamData();
- // De-duplicate chunks by URL to avoid showing duplicate content
- const uniqueResults = finalResults.reduce((acc, current) => {
- const existingResult = acc.find(item => item.id === current.id);
- if (!existingResult) {
- acc.push(current);
- }
- return acc;
- }, [] as typeof finalResults);
-
- data.appendMessageAnnotation(
- uniqueResults.map((r) => ({
- id: r.id,
- content: r.content,
- type: r.type,
- url: r.url,
- title: r.title,
- description: r.description,
- ogImage: r.ogImage,
- userId: r.userId,
- createdAt: r.createdAt.toISOString(),
- updatedAt: r.updatedAt?.toISOString() || null,
- }))
+
+ // Pre-compute the vector similarity expression
+ const vectorSimilarity = sql<number>`1 - (embeddings <=> ${JSON.stringify(embedding[0])}::vector)`;
+ const textSearchRank = sql<number>`ts_rank_cd(
+ to_tsvector('english', coalesce(${chunk.textContent}, '')),
+ plainto_tsquery('english', ${queryText})
+ )`;
+
+ // Get matching chunks with document info
+ const matchingChunks = await db
+ .select({
+ chunkId: chunk.id,
+ documentId: chunk.documentId,
+ textContent: chunk.textContent,
+ orderInDocument: chunk.orderInDocument,
+ metadata: chunk.metadata,
+ similarity: vectorSimilarity,
+ textRank: textSearchRank,
+ // Document fields
+ docId: documents.id,
+ docUuid: documents.uuid,
+ docContent: documents.content,
+ docType: documents.type,
+ docUrl: documents.url,
+ docTitle: documents.title,
+ docDescription: documents.description,
+ docOgImage: documents.ogImage,
+ })
+ .from(chunk)
+ .innerJoin(documents, eq(chunk.documentId, documents.id))
+ .where(
+ and(eq(documents.userId, user.id), sql`${vectorSimilarity} > 0.5`)
+ )
+ .orderBy(
+ desc(sql<number>`(
+ 0.6 * ${vectorSimilarity} +
+ 0.25 * ${textSearchRank} +
+ 0.15 * (1.0 / (1.0 + extract(epoch from age(${documents.updatedAt})) / (90 * 24 * 60 * 60)))
+ )::float`)
+ )
+ .limit(15);
+
+ // Get unique document IDs from matching chunks
+ const uniqueDocIds = [
+ ...new Set(matchingChunks.map((c) => c.documentId)),
+ ];
+
+ // Fetch all chunks for these documents to get context
+ const contextChunks = await db
+ .select({
+ id: chunk.id,
+ documentId: chunk.documentId,
+ textContent: chunk.textContent,
+ orderInDocument: chunk.orderInDocument,
+ metadata: chunk.metadata,
+ })
+ .from(chunk)
+ .where(inArray(chunk.documentId, uniqueDocIds))
+ .orderBy(chunk.documentId, chunk.orderInDocument);
+
+ // Group chunks by document
+ const chunksByDocument = new Map<number, typeof contextChunks>();
+ for (const chunk of contextChunks) {
+ const docChunks = chunksByDocument.get(chunk.documentId) || [];
+ docChunks.push(chunk);
+ chunksByDocument.set(chunk.documentId, docChunks);
+ }
+
+ // Create context with surrounding chunks
+ const contextualResults = matchingChunks.map((match) => {
+ const docChunks = chunksByDocument.get(match.documentId) || [];
+ const matchIndex = docChunks.findIndex((c) => c.id === match.chunkId);
+
+ // Get surrounding chunks (1 before and 1 after)
+ const start = Math.max(0, matchIndex - 1);
+ const end = Math.min(docChunks.length, matchIndex + 2);
+ const relevantChunks = docChunks.slice(start, end);
+
+ return {
+ id: match.docId,
+ title: match.docTitle,
+ description: match.docDescription,
+ url: match.docUrl,
+ type: match.docType,
+ content: relevantChunks.map((c) => c.textContent).join("\n"),
+ similarity: Number(match.similarity.toFixed(4)),
+ chunks: relevantChunks.map((c) => ({
+ id: c.id,
+ content: c.textContent,
+ orderInDocument: c.orderInDocument,
+ metadata: c.metadata,
+ isMatch: c.id === match.chunkId,
+ })),
+ };
+ });
+
+ // Remove duplicates based on document ID
+ const uniqueResults = contextualResults.reduce(
+ (acc, current) => {
+ const existingDoc = acc.find((doc) => doc.id === current.id);
+ if (!existingDoc) {
+ acc.push(current);
+ } else if (current.similarity > existingDoc.similarity) {
+ // Replace if current match is better
+ const index = acc.findIndex((doc) => doc.id === current.id);
+ acc[index] = current;
+ }
+ return acc;
+ },
+ [] as typeof contextualResults
);
+ data.appendMessageAnnotation(uniqueResults);
+
+ if (lastUserMessage) {
+ lastUserMessage.content =
+ typeof lastUserMessage.content === "string"
+ ? lastUserMessage.content +
+ `<context>${JSON.stringify(uniqueResults)}</context>`
+ : [
+ ...lastUserMessage.content,
+ {
+ type: "text",
+ text: `<context>${JSON.stringify(uniqueResults)}</context>`,
+ },
+ ];
+ coreMessages[coreMessages.length - 1] = lastUserMessage;
+ }
+
const result = await streamText({
model: googleClient,
experimental_providerMetadata: {
@@ -267,7 +309,7 @@ const actions = new Hono<{ Variables: Variables; Bindings: Env }>()
role: "assistant",
content:
completion.text +
- `<context>[${JSON.stringify(finalResults)}]</context>`,
+ `<context>[${JSON.stringify(uniqueResults)}]</context>`,
},
];
@@ -279,6 +321,8 @@ const actions = new Hono<{ Variables: Variables; Bindings: Env }>()
}
} catch (error) {
console.error("Failed to update thread:", error);
+ } finally {
+ await data.close();
}
},
});
@@ -510,32 +554,38 @@ const actions = new Hono<{ Variables: Variables; Bindings: Env }>()
.from(spaceInDb)
.where(eq(spaceInDb.uuid, spaceId))
.limit(1);
-
+
if (space.length === 0) return null;
return {
id: space[0].id,
ownerId: space[0].ownerId,
- uuid: space[0].uuid
+ uuid: space[0].uuid,
};
})
);
// Filter out any null values and check permissions
- const validSpaces = spaceDetails.filter((s): s is NonNullable<typeof s> => s !== null);
- const unauthorized = validSpaces.filter(s => s.ownerId !== user.id);
+ const validSpaces = spaceDetails.filter(
+ (s): s is NonNullable<typeof s> => s !== null
+ );
+ const unauthorized = validSpaces.filter((s) => s.ownerId !== user.id);
if (unauthorized.length > 0) {
return c.json(
{
error: "Space permission denied",
- details: unauthorized.map(s => s.uuid).join(", "),
+ details: unauthorized.map((s) => s.uuid).join(", "),
},
403
);
}
// Replace UUIDs with IDs for the database query
- spaces.splice(0, spaces.length, ...validSpaces.map(s => s.id.toString()));
+ spaces.splice(
+ 0,
+ spaces.length,
+ ...validSpaces.map((s) => s.id.toString())
+ );
}
try {
@@ -553,28 +603,32 @@ const actions = new Hono<{ Variables: Variables; Bindings: Env }>()
// Pre-compute the vector similarity expression to avoid multiple calculations
const vectorSimilarity = sql<number>`1 - (embeddings <=> ${JSON.stringify(embeddings.data[0])}::vector)`;
- const textSearchRank = sql<number>`ts_rank_cd((
- setweight(to_tsvector('english', coalesce(${documents.content}, '')),'A') ||
- setweight(to_tsvector('english', coalesce(${documents.title}, '')),'B') ||
- setweight(to_tsvector('english', coalesce(${documents.description}, '')),'C') ||
- setweight(to_tsvector('english', coalesce(${documents.url}, '')),'D')
- ), plainto_tsquery('english', ${query}))`;
-
+ const textSearchRank = sql<number>`ts_rank_cd(
+ to_tsvector('english', coalesce(${chunk.textContent}, '')),
+ plainto_tsquery('english', ${query})
+ )`;
+
+ // First get the top matching chunks
const results = await db
.select({
- id: documents.id,
- uuid: documents.uuid,
- content: documents.content,
- type: documents.type,
- url: documents.url,
- title: documents.title,
- createdAt: documents.createdAt,
- updatedAt: documents.updatedAt,
- userId: documents.userId,
- description: documents.description,
- ogImage: documents.ogImage,
+ chunkId: chunk.id,
+ documentId: chunk.documentId,
+ textContent: chunk.textContent,
+ orderInDocument: chunk.orderInDocument,
+ metadata: chunk.metadata,
similarity: vectorSimilarity,
textRank: textSearchRank,
+ // Document fields
+ docUuid: documents.uuid,
+ docContent: documents.content,
+ docType: documents.type,
+ docUrl: documents.url,
+ docTitle: documents.title,
+ docCreatedAt: documents.createdAt,
+ docUpdatedAt: documents.updatedAt,
+ docUserId: documents.userId,
+ docDescription: documents.description,
+ docOgImage: documents.ogImage,
})
.from(chunk)
.innerJoin(documents, eq(chunk.documentId, documents.id))
@@ -611,12 +665,41 @@ const actions = new Hono<{ Variables: Variables; Bindings: Env }>()
)
.limit(limit);
- return c.json({
- results: results.map((r) => ({
- ...r,
- similarity: Number(r.similarity.toFixed(4)),
- })),
- });
+ // Group results by document and take the best matching chunk
+ const documentResults = new Map<number, (typeof results)[0]>();
+ for (const result of results) {
+ const existingResult = documentResults.get(result.documentId);
+ if (
+ !existingResult ||
+ result.similarity > existingResult.similarity
+ ) {
+ documentResults.set(result.documentId, result);
+ }
+ }
+
+ // Convert back to array and format response
+ const finalResults = Array.from(documentResults.values()).map((r) => ({
+ id: r.documentId,
+ uuid: r.docUuid,
+ content: r.docContent,
+ type: r.docType,
+ url: r.docUrl,
+ title: r.docTitle,
+ createdAt: r.docCreatedAt,
+ updatedAt: r.docUpdatedAt,
+ userId: r.docUserId,
+ description: r.docDescription,
+ ogImage: r.docOgImage,
+ similarity: Number(r.similarity.toFixed(4)),
+ matchingChunk: {
+ id: r.chunkId,
+ content: r.textContent,
+ orderInDocument: r.orderInDocument,
+ metadata: r.metadata,
+ },
+ }));
+
+ return c.json({ results: finalResults });
} catch (error) {
console.error("[Search Error]", error);
return c.json(