diff --git a/apps/web/src/actions/evaluations/create.ts b/apps/web/src/actions/evaluations/create.ts index a494806c3..6412ce0e7 100644 --- a/apps/web/src/actions/evaluations/create.ts +++ b/apps/web/src/actions/evaluations/create.ts @@ -1,6 +1,9 @@ 'use server' -import { EvaluationMetadataType } from '@latitude-data/core/browser' +import { + EvaluationMetadataType, + EvaluationResultableType, +} from '@latitude-data/core/browser' import { createEvaluation } from '@latitude-data/core/services/evaluations/create' import { z } from 'zod' @@ -16,6 +19,12 @@ export const createEvaluationAction = authProcedure .nativeEnum(EvaluationMetadataType) .optional() .default(EvaluationMetadataType.LlmAsJudge), + configuration: z.object({ + type: z.nativeEnum(EvaluationResultableType), + detail: z + .object({ range: z.object({ from: z.number(), to: z.number() }) }) + .optional(), + }), metadata: z .object({ prompt: z.string(), @@ -30,6 +39,7 @@ export const createEvaluationAction = authProcedure name: input.name, description: input.description, metadata: input.metadata, + configuration: input.configuration, type: input.type, }) diff --git a/apps/web/src/app/(private)/error.tsx b/apps/web/src/app/(private)/error.tsx index 986ea6946..84dec548a 100644 --- a/apps/web/src/app/(private)/error.tsx +++ b/apps/web/src/app/(private)/error.tsx @@ -4,7 +4,9 @@ import { useEffect } from 'react' import { ErrorComponent, useSession } from '@latitude-data/web-ui/browser' import { NAV_LINKS } from '$/app/(private)/_lib/constants' +import BreadcrumpLink from '$/components/BreadcrumpLink' import { AppLayout } from '$/components/layouts' +import { ROUTES } from '$/services/routes' export default function Error({ error, @@ -19,7 +21,14 @@ export default function Error({ return ( + ), + }, + { name: 'Error' }, + ]} navigationLinks={NAV_LINKS} > (() => { if (!title) return 'Please enter a name for your evaluation.' @@ -82,8 +94,7 @@ export default function CreateEvaluationModal({ }} > - - Name + - - - Description + + - + + + + + {configuration.type === EvaluationResultableType.Number && ( + + + + + + + )} ) } + +function useEvaluationConfiguration() { + const [configuration, setConfiguration] = + useState({ + type: EvaluationResultableType.Text, + }) + + const handleTypeChange = useCallback((value: EvaluationResultableType) => { + if (value === EvaluationResultableType.Number) { + setConfiguration({ + type: value, + detail: { range: { from: 0, to: 1 } }, + }) + } else { + setConfiguration({ type: value }) + } + }, []) + + const handleRangeFromChange = useCallback( + (e: ChangeEvent) => { + setConfiguration((prev) => { + const next = { ...prev } + const value = e.target.value + + if (value === '') { + next.detail = { + range: { from: 0, to: next.detail?.range.to || 0 }, + } + return next + } + + const from = parseInt(value) + if (next.detail?.range) { + next.detail.range.from = from + if (from > next.detail.range.to) { + next.detail.range.to = from + 1 + } + } else { + next.detail = { + range: { from, to: from + 1 }, + } + } + + return next + }) + }, + [], + ) + + const handleRangeToChange = useCallback( + (e: ChangeEvent) => { + setConfiguration((prev) => { + const next = { ...prev } + const value = e.target.value + + if (value === '') { + next.detail = { + range: { from: 0, to: 0 }, + } + return next + } + + const to = parseInt(value) + if (next.detail?.range) { + next.detail.range.to = to + if (to < next.detail.range.from) { + next.detail.range.from = to - 1 + } + } else { + next.detail = { + range: { from: to - 1, to }, + } + } + + return next + }) + }, + [], + ) + + return { + configuration, + handleTypeChange, + handleRangeFromChange, + handleRangeToChange, + } +} diff --git a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/logs/_components/DocumentLogs/DocumentLogInfo/Metadata.tsx b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/logs/_components/DocumentLogs/DocumentLogInfo/Metadata.tsx index 7bdf0edd3..827d9bce1 100644 --- a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/logs/_components/DocumentLogs/DocumentLogInfo/Metadata.tsx +++ b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/logs/_components/DocumentLogs/DocumentLogInfo/Metadata.tsx @@ -75,7 +75,7 @@ export function DocumentLogMetadata({ providerLogs?.reduce( (acc, log) => { const key = String(log.providerId) - acc[key] = (acc[key] ?? 0) + log.cost_in_millicents + acc[key] = (acc[key] ?? 0) + log.costInMillicents return acc }, {} as Record, diff --git a/apps/web/src/stores/evaluationTemplates.ts b/apps/web/src/stores/evaluationTemplates.ts index 7f05d5377..c16a52c92 100644 --- a/apps/web/src/stores/evaluationTemplates.ts +++ b/apps/web/src/stores/evaluationTemplates.ts @@ -2,7 +2,7 @@ import { compact, flatten } from 'lodash-es' -import type { EvaluationTemplateWithCategory } from '@latitude-data/core/browser' +import { EvaluationTemplateWithCategory } from '@latitude-data/core/browser' import { useToast } from '@latitude-data/web-ui' import { fetchEvaluationTemplatesAction } from '$/actions/evaluationTemplates/fetch' import useSWR, { SWRConfiguration } from 'swr' diff --git a/packages/core/drizzle/0051_colorful_lightspeed.sql b/packages/core/drizzle/0051_colorful_lightspeed.sql new file mode 100644 index 000000000..ace1d6f1b --- /dev/null +++ b/packages/core/drizzle/0051_colorful_lightspeed.sql @@ -0,0 +1,33 @@ +DO $$ BEGIN + CREATE TYPE "public"."evaluation_result_types" AS ENUM('evaluation_resultable_booleans', 'evaluation_resultable_texts', 'evaluation_resultable_numbers'); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "latitude"."evaluation_resultable_numbers" ( + "id" bigserial PRIMARY KEY NOT NULL, + "result" bigint NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "latitude"."evaluation_resultable_texts" ( + "id" bigserial PRIMARY KEY NOT NULL, + "result" text NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "latitude"."evaluation_resultable_booleans" ( + "id" bigserial PRIMARY KEY NOT NULL, + "result" boolean NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +ALTER TABLE "latitude"."evaluations" ADD COLUMN "configuration" jsonb NOT NULL;--> statement-breakpoint +ALTER TABLE "latitude"."evaluation_results" ADD COLUMN "resultable_type" "evaluation_result_types" NOT NULL;--> statement-breakpoint +ALTER TABLE "latitude"."evaluation_results" ADD COLUMN "resultable_id" bigint NOT NULL;--> statement-breakpoint +ALTER TABLE "latitude"."evaluations_templates" ADD COLUMN "configuration" jsonb NOT NULL;--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "resultable_idx" ON "latitude"."evaluation_results" USING btree ("resultable_id","resultable_type");--> statement-breakpoint +ALTER TABLE "latitude"."evaluation_results" DROP COLUMN IF EXISTS "result"; \ No newline at end of file diff --git a/packages/core/drizzle/meta/0051_snapshot.json b/packages/core/drizzle/meta/0051_snapshot.json new file mode 100644 index 000000000..ba141560a --- /dev/null +++ b/packages/core/drizzle/meta/0051_snapshot.json @@ -0,0 +1,2189 @@ +{ + "id": "eb7ce322-fe62-4bd3-b181-5386c6db6c01", + "prevId": "b4086f8b-2346-46e0-9742-dcb0b6f8a47c", + "version": "7", + "dialect": "postgresql", + "tables": { + "latitude.users": { + "name": "users", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "confirmed_at": { + "name": "confirmed_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "encrypted_password": { + "name": "encrypted_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, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + } + }, + "latitude.sessions": { + "name": "sessions", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "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": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "schemaTo": "latitude", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "latitude.workspaces": { + "name": "workspaces", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "creator_id": { + "name": "creator_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": {}, + "foreignKeys": { + "workspaces_creator_id_users_id_fk": { + "name": "workspaces_creator_id_users_id_fk", + "tableFrom": "workspaces", + "tableTo": "users", + "schemaTo": "latitude", + "columnsFrom": [ + "creator_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "latitude.memberships": { + "name": "memberships", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "invitation_token": { + "name": "invitation_token", + "type": "uuid", + "primaryKey": false, + "notNull": true, + "default": "gen_random_uuid()" + }, + "confirmed_at": { + "name": "confirmed_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": { + "memberships_workspace_id_user_id_index": { + "name": "memberships_workspace_id_user_id_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "memberships_invitation_token_index": { + "name": "memberships_invitation_token_index", + "columns": [ + { + "expression": "invitation_token", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "memberships_workspace_id_workspaces_id_fk": { + "name": "memberships_workspace_id_workspaces_id_fk", + "tableFrom": "memberships", + "tableTo": "workspaces", + "schemaTo": "latitude", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "memberships_user_id_users_id_fk": { + "name": "memberships_user_id_users_id_fk", + "tableFrom": "memberships", + "tableTo": "users", + "schemaTo": "latitude", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "memberships_invitation_token_unique": { + "name": "memberships_invitation_token_unique", + "nullsNotDistinct": false, + "columns": [ + "invitation_token" + ] + } + } + }, + "latitude.api_keys": { + "name": "api_keys", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "token": { + "name": "token", + "type": "uuid", + "primaryKey": false, + "notNull": true, + "default": "gen_random_uuid()" + }, + "workspace_id": { + "name": "workspace_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(256)", + "primaryKey": false, + "notNull": false + }, + "last_used_at": { + "name": "last_used_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": { + "workspace_id_idx": { + "name": "workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "api_keys_workspace_id_workspaces_id_fk": { + "name": "api_keys_workspace_id_workspaces_id_fk", + "tableFrom": "api_keys", + "tableTo": "workspaces", + "schemaTo": "latitude", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "api_keys_token_unique": { + "name": "api_keys_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + } + }, + "latitude.projects": { + "name": "projects", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "workspace_id": { + "name": "workspace_id", + "type": "bigint", + "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": { + "workspace_idx": { + "name": "workspace_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "projects_workspace_id_workspaces_id_fk": { + "name": "projects_workspace_id_workspaces_id_fk", + "tableFrom": "projects", + "tableTo": "workspaces", + "schemaTo": "latitude", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "latitude.commits": { + "name": "commits", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "uuid": { + "name": "uuid", + "type": "uuid", + "primaryKey": false, + "notNull": true, + "default": "gen_random_uuid()" + }, + "title": { + "name": "title", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "project_id": { + "name": "project_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "merged_at": { + "name": "merged_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": { + "project_commit_order_idx": { + "name": "project_commit_order_idx", + "columns": [ + { + "expression": "merged_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "commits_project_id_projects_id_fk": { + "name": "commits_project_id_projects_id_fk", + "tableFrom": "commits", + "tableTo": "projects", + "schemaTo": "latitude", + "columnsFrom": [ + "project_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "commits_user_id_users_id_fk": { + "name": "commits_user_id_users_id_fk", + "tableFrom": "commits", + "tableTo": "users", + "schemaTo": "latitude", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "commits_uuid_unique": { + "name": "commits_uuid_unique", + "nullsNotDistinct": false, + "columns": [ + "uuid" + ] + }, + "unique_commit_version": { + "name": "unique_commit_version", + "nullsNotDistinct": false, + "columns": [ + "version", + "project_id" + ] + } + } + }, + "latitude.document_versions": { + "name": "document_versions", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "document_uuid": { + "name": "document_uuid", + "type": "uuid", + "primaryKey": false, + "notNull": true, + "default": "gen_random_uuid()" + }, + "path": { + "name": "path", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "resolved_content": { + "name": "resolved_content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "commit_id": { + "name": "commit_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "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": {}, + "foreignKeys": { + "document_versions_commit_id_commits_id_fk": { + "name": "document_versions_commit_id_commits_id_fk", + "tableFrom": "document_versions", + "tableTo": "commits", + "schemaTo": "latitude", + "columnsFrom": [ + "commit_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "unique_document_uuid_commit_id": { + "name": "unique_document_uuid_commit_id", + "nullsNotDistinct": false, + "columns": [ + "document_uuid", + "commit_id" + ] + }, + "unique_path_commit_id_deleted_at": { + "name": "unique_path_commit_id_deleted_at", + "nullsNotDistinct": false, + "columns": [ + "path", + "commit_id", + "deleted_at" + ] + } + } + }, + "latitude.provider_api_keys": { + "name": "provider_api_keys", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "provider", + "typeSchema": "latitude", + "primaryKey": false, + "notNull": true + }, + "author_id": { + "name": "author_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "last_used_at": { + "name": "last_used_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": { + "provider_apikeys_workspace_id_idx": { + "name": "provider_apikeys_workspace_id_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "provider_apikeys_name_idx": { + "name": "provider_apikeys_name_idx", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "provider_apikeys_user_id_idx": { + "name": "provider_apikeys_user_id_idx", + "columns": [ + { + "expression": "author_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "provider_api_keys_author_id_users_id_fk": { + "name": "provider_api_keys_author_id_users_id_fk", + "tableFrom": "provider_api_keys", + "tableTo": "users", + "schemaTo": "latitude", + "columnsFrom": [ + "author_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "provider_api_keys_workspace_id_workspaces_id_fk": { + "name": "provider_api_keys_workspace_id_workspaces_id_fk", + "tableFrom": "provider_api_keys", + "tableTo": "workspaces", + "schemaTo": "latitude", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "provider_apikeys_token_provider_unique": { + "name": "provider_apikeys_token_provider_unique", + "nullsNotDistinct": false, + "columns": [ + "token", + "provider", + "workspace_id" + ] + } + } + }, + "latitude.document_logs": { + "name": "document_logs", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "uuid": { + "name": "uuid", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "document_uuid": { + "name": "document_uuid", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "commit_id": { + "name": "commit_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "resolved_content": { + "name": "resolved_content", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parameters": { + "name": "parameters", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "custom_identifier": { + "name": "custom_identifier", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duration": { + "name": "duration", + "type": "bigint", + "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": { + "document_log_uuid_idx": { + "name": "document_log_uuid_idx", + "columns": [ + { + "expression": "document_uuid", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "commit_id_idx": { + "name": "commit_id_idx", + "columns": [ + { + "expression": "commit_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "document_logs_commit_id_commits_id_fk": { + "name": "document_logs_commit_id_commits_id_fk", + "tableFrom": "document_logs", + "tableTo": "commits", + "schemaTo": "latitude", + "columnsFrom": [ + "commit_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "document_logs_uuid_unique": { + "name": "document_logs_uuid_unique", + "nullsNotDistinct": false, + "columns": [ + "uuid" + ] + } + } + }, + "latitude.provider_logs": { + "name": "provider_logs", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "uuid": { + "name": "uuid", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "document_log_uuid": { + "name": "document_log_uuid", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "provider_id": { + "name": "provider_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "model": { + "name": "model", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "config": { + "name": "config", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "messages": { + "name": "messages", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "response_text": { + "name": "response_text", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "tool_calls": { + "name": "tool_calls", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'[]'::json" + }, + "tokens": { + "name": "tokens", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "cost_in_millicents": { + "name": "cost_in_millicents", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "duration": { + "name": "duration", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "source": { + "name": "source", + "type": "log_source", + "typeSchema": "latitude", + "primaryKey": false, + "notNull": true + }, + "apiKeyId": { + "name": "apiKeyId", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "generated_at": { + "name": "generated_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": {}, + "foreignKeys": { + "provider_logs_provider_id_provider_api_keys_id_fk": { + "name": "provider_logs_provider_id_provider_api_keys_id_fk", + "tableFrom": "provider_logs", + "tableTo": "provider_api_keys", + "schemaTo": "latitude", + "columnsFrom": [ + "provider_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "provider_logs_apiKeyId_api_keys_id_fk": { + "name": "provider_logs_apiKeyId_api_keys_id_fk", + "tableFrom": "provider_logs", + "tableTo": "api_keys", + "schemaTo": "latitude", + "columnsFrom": [ + "apiKeyId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "provider_logs_uuid_unique": { + "name": "provider_logs_uuid_unique", + "nullsNotDistinct": false, + "columns": [ + "uuid" + ] + } + } + }, + "latitude.datasets": { + "name": "datasets", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "csv_delimiter": { + "name": "csv_delimiter", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "author_id": { + "name": "author_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "file_key": { + "name": "file_key", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "file_metadata": { + "name": "file_metadata", + "type": "jsonb", + "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": { + "datasets_workspace_idx": { + "name": "datasets_workspace_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "datasets_author_idx": { + "name": "datasets_author_idx", + "columns": [ + { + "expression": "author_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "datasets_workspace_id_name_index": { + "name": "datasets_workspace_id_name_index", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "datasets_workspace_id_workspaces_id_fk": { + "name": "datasets_workspace_id_workspaces_id_fk", + "tableFrom": "datasets", + "tableTo": "workspaces", + "schemaTo": "latitude", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "datasets_author_id_users_id_fk": { + "name": "datasets_author_id_users_id_fk", + "tableFrom": "datasets", + "tableTo": "users", + "schemaTo": "latitude", + "columnsFrom": [ + "author_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "latitude.evaluations": { + "name": "evaluations", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "uuid": { + "name": "uuid", + "type": "uuid", + "primaryKey": false, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "metadata_id": { + "name": "metadata_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "configuration": { + "name": "configuration", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "metadata_type": { + "name": "metadata_type", + "type": "metadata_type", + "typeSchema": "latitude", + "primaryKey": false, + "notNull": true + }, + "workspace_id": { + "name": "workspace_id", + "type": "bigint", + "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": { + "evaluation_workspace_idx": { + "name": "evaluation_workspace_idx", + "columns": [ + { + "expression": "workspace_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "evaluation_metadata_idx": { + "name": "evaluation_metadata_idx", + "columns": [ + { + "expression": "metadata_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "metadata_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "evaluations_workspace_id_workspaces_id_fk": { + "name": "evaluations_workspace_id_workspaces_id_fk", + "tableFrom": "evaluations", + "tableTo": "workspaces", + "schemaTo": "latitude", + "columnsFrom": [ + "workspace_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "evaluations_uuid_unique": { + "name": "evaluations_uuid_unique", + "nullsNotDistinct": false, + "columns": [ + "uuid" + ] + } + } + }, + "latitude.llm_as_judge_evaluation_metadatas": { + "name": "llm_as_judge_evaluation_metadatas", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "metadata_type": { + "name": "metadata_type", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true, + "default": "'llm_as_judge'" + }, + "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()" + }, + "prompt": { + "name": "prompt", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "template_id": { + "name": "template_id", + "type": "bigint", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "llm_as_judge_evaluation_metadatas_template_id_idx": { + "name": "llm_as_judge_evaluation_metadatas_template_id_idx", + "columns": [ + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "llm_as_judge_evaluation_metadatas_template_id_evaluations_templates_id_fk": { + "name": "llm_as_judge_evaluation_metadatas_template_id_evaluations_templates_id_fk", + "tableFrom": "llm_as_judge_evaluation_metadatas", + "tableTo": "evaluations_templates", + "schemaTo": "latitude", + "columnsFrom": [ + "template_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "latitude.connected_evaluations": { + "name": "connected_evaluations", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "document_uuid": { + "name": "document_uuid", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "evaluation_mode": { + "name": "evaluation_mode", + "type": "evaluation_mode_enum", + "typeSchema": "latitude", + "primaryKey": false, + "notNull": true + }, + "evaluation_id": { + "name": "evaluation_id", + "type": "bigint", + "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": { + "connected_evaluations_evaluation_idx": { + "name": "connected_evaluations_evaluation_idx", + "columns": [ + { + "expression": "evaluation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "connected_evaluations_evaluation_id_evaluations_id_fk": { + "name": "connected_evaluations_evaluation_id_evaluations_id_fk", + "tableFrom": "connected_evaluations", + "tableTo": "evaluations", + "schemaTo": "latitude", + "columnsFrom": [ + "evaluation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "connected_evaluations_unique_idx": { + "name": "connected_evaluations_unique_idx", + "nullsNotDistinct": false, + "columns": [ + "document_uuid", + "evaluation_id" + ] + } + } + }, + "latitude.evaluation_results": { + "name": "evaluation_results", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "evaluation_id": { + "name": "evaluation_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "document_log_id": { + "name": "document_log_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "provider_log_id": { + "name": "provider_log_id", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "resultable_type": { + "name": "resultable_type", + "type": "evaluation_result_types", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "resultable_id": { + "name": "resultable_id", + "type": "bigint", + "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": { + "evaluation_idx": { + "name": "evaluation_idx", + "columns": [ + { + "expression": "evaluation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "document_log_idx": { + "name": "document_log_idx", + "columns": [ + { + "expression": "document_log_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "provider_log_idx": { + "name": "provider_log_idx", + "columns": [ + { + "expression": "provider_log_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "resultable_idx": { + "name": "resultable_idx", + "columns": [ + { + "expression": "resultable_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "resultable_type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "evaluation_results_evaluation_id_evaluations_id_fk": { + "name": "evaluation_results_evaluation_id_evaluations_id_fk", + "tableFrom": "evaluation_results", + "tableTo": "evaluations", + "schemaTo": "latitude", + "columnsFrom": [ + "evaluation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "evaluation_results_document_log_id_document_logs_id_fk": { + "name": "evaluation_results_document_log_id_document_logs_id_fk", + "tableFrom": "evaluation_results", + "tableTo": "document_logs", + "schemaTo": "latitude", + "columnsFrom": [ + "document_log_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "evaluation_results_provider_log_id_provider_logs_id_fk": { + "name": "evaluation_results_provider_log_id_provider_logs_id_fk", + "tableFrom": "evaluation_results", + "tableTo": "provider_logs", + "schemaTo": "latitude", + "columnsFrom": [ + "provider_log_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "latitude.evaluations_templates": { + "name": "evaluations_templates", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "category": { + "name": "category", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "configuration": { + "name": "configuration", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "prompt": { + "name": "prompt", + "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()" + } + }, + "indexes": {}, + "foreignKeys": { + "evaluations_templates_category_evaluations_template_categories_id_fk": { + "name": "evaluations_templates_category_evaluations_template_categories_id_fk", + "tableFrom": "evaluations_templates", + "tableTo": "evaluations_template_categories", + "schemaTo": "latitude", + "columnsFrom": [ + "category" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "latitude.evaluations_template_categories": { + "name": "evaluations_template_categories", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(256)", + "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": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "latitude.magic_link_tokens": { + "name": "magic_link_tokens", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "token": { + "name": "token", + "type": "uuid", + "primaryKey": false, + "notNull": true, + "default": "gen_random_uuid()" + }, + "expired_at": { + "name": "expired_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "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()" + } + }, + "indexes": {}, + "foreignKeys": { + "magic_link_tokens_user_id_users_id_fk": { + "name": "magic_link_tokens_user_id_users_id_fk", + "tableFrom": "magic_link_tokens", + "tableTo": "users", + "schemaTo": "latitude", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "magic_link_tokens_token_unique": { + "name": "magic_link_tokens_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + } + }, + "latitude.events": { + "name": "events", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "varchar(256)", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "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": { + "event_type_idx": { + "name": "event_type_idx", + "columns": [ + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "latitude.evaluation_resultable_numbers": { + "name": "evaluation_resultable_numbers", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "result": { + "name": "result", + "type": "bigint", + "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": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "latitude.evaluation_resultable_texts": { + "name": "evaluation_resultable_texts", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "result": { + "name": "result", + "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()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "latitude.evaluation_resultable_booleans": { + "name": "evaluation_resultable_booleans", + "schema": "latitude", + "columns": { + "id": { + "name": "id", + "type": "bigserial", + "primaryKey": true, + "notNull": true + }, + "result": { + "name": "result", + "type": "boolean", + "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": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "latitude.provider": { + "name": "provider", + "schema": "latitude", + "values": [ + "openai", + "anthropic", + "groq", + "mistral", + "azure", + "google" + ] + }, + "latitude.log_source": { + "name": "log_source", + "schema": "latitude", + "values": [ + "playground", + "api", + "evaluation" + ] + }, + "latitude.metadata_type": { + "name": "metadata_type", + "schema": "latitude", + "values": [ + "llm_as_judge" + ] + }, + "public.evaluation_result_types": { + "name": "evaluation_result_types", + "schema": "public", + "values": [ + "evaluation_resultable_booleans", + "evaluation_resultable_texts", + "evaluation_resultable_numbers" + ] + } + }, + "schemas": { + "latitude": "latitude" + }, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/packages/core/drizzle/meta/_journal.json b/packages/core/drizzle/meta/_journal.json index 7f17bf7b5..2b594cf46 100644 --- a/packages/core/drizzle/meta/_journal.json +++ b/packages/core/drizzle/meta/_journal.json @@ -358,6 +358,13 @@ "when": 1726065747521, "tag": "0050_elite_marvel_boy", "breakpoints": true + }, + { + "idx": 51, + "version": "7", + "when": 1726148717688, + "tag": "0051_colorful_lightspeed", + "breakpoints": true } ] } \ No newline at end of file diff --git a/packages/core/src/constants.ts b/packages/core/src/constants.ts index 2574fc5ce..911d063f3 100644 --- a/packages/core/src/constants.ts +++ b/packages/core/src/constants.ts @@ -112,3 +112,9 @@ export enum EvaluationMode { Live = 'live', Batch = 'batch', } + +export enum EvaluationResultableType { + Boolean = 'evaluation_resultable_booleans', + Text = 'evaluation_resultable_texts', + Number = 'evaluation_resultable_numbers', +} diff --git a/packages/core/src/data-access/evaluationTemplates.ts b/packages/core/src/data-access/evaluationTemplates.ts index d73bc3954..29796b878 100644 --- a/packages/core/src/data-access/evaluationTemplates.ts +++ b/packages/core/src/data-access/evaluationTemplates.ts @@ -1,15 +1,11 @@ import { asc, eq, getTableColumns, inArray } from 'drizzle-orm' -import { EvaluationTemplate } from '../browser' +import { EvaluationTemplate, EvaluationTemplateWithCategory } from '../browser' import { database } from '../client' import { NotFoundError } from '../lib/errors' import { Result, TypedResult } from '../lib/Result' import { evaluationTemplateCategories, evaluationTemplates } from '../schema' -export type EvaluationTemplateWithCategory = EvaluationTemplate & { - category: string -} - export async function findAllEvaluationTemplates(): Promise< TypedResult > { diff --git a/packages/core/src/repositories/connectedEvaluationsRepository/getConnectedDocumentsWithMetadata.test.ts b/packages/core/src/repositories/connectedEvaluationsRepository/getConnectedDocumentsWithMetadata.test.ts index 361beb9ca..6379b116c 100644 --- a/packages/core/src/repositories/connectedEvaluationsRepository/getConnectedDocumentsWithMetadata.test.ts +++ b/packages/core/src/repositories/connectedEvaluationsRepository/getConnectedDocumentsWithMetadata.test.ts @@ -233,8 +233,7 @@ describe('getConnectedDocumentsWithMetadata', () => { ) const totalCost = results.reduce( (acc, r) => - acc + - r.providerLogs.reduce((acc2, l) => acc2 + l.cost_in_millicents, 0), + acc + r.providerLogs.reduce((acc2, l) => acc2 + l.costInMillicents, 0), 0, ) diff --git a/packages/core/src/repositories/connectedEvaluationsRepository/index.ts b/packages/core/src/repositories/connectedEvaluationsRepository/index.ts index f04b89d5f..7bca3ad8f 100644 --- a/packages/core/src/repositories/connectedEvaluationsRepository/index.ts +++ b/packages/core/src/repositories/connectedEvaluationsRepository/index.ts @@ -20,6 +20,7 @@ import { providerLogs, } from '../../schema' import { DocumentVersionsRepository } from '../documentVersionsRepository' +import { EvaluationResultsRepository } from '../evaluationResultsRepository' import { EvaluationsRepository } from '../evaluationsRepository' import Repository from '../repository' @@ -121,16 +122,14 @@ export class ConnectedEvaluationsRepository extends Repository< ), ) + // TODO: figure out proper type for this const selectedEvaluationResults = this.db .$with('selected_evaluation_results') .as( - this.db - .select({ - ...getTableColumns(evaluationResults), - ...getTableColumns(documentLogs), - ...getTableColumns(providerLogs), - }) - .from(evaluationResults) + EvaluationResultsRepository.baseQuery(this.db, { + ...getTableColumns(documentLogs), + ...getTableColumns(providerLogs), + }) .innerJoin( documentLogs, eq(documentLogs.id, evaluationResults.documentLogId), @@ -145,12 +144,15 @@ export class ConnectedEvaluationsRepository extends Repository< const aggregatedResults = this.db .with(selectedEvaluationResults) .select({ + // @ts-expect-error documentUuid: selectedEvaluationResults.documentUuid, evaluationLogs: count(selectedEvaluationResults.id).as( 'evaluation_logs', ), + // @ts-expect-error totalTokens: sum(selectedEvaluationResults.tokens).as('total_tokens'), - costInMillicents: sum(selectedEvaluationResults.cost_in_millicents).as( + // @ts-expect-error + costInMillicents: sum(selectedEvaluationResults.costInMillicents).as( 'cost_in_millicents', ), modalValue: sql< @@ -160,6 +162,7 @@ export class ConnectedEvaluationsRepository extends Repository< ), }) .from(selectedEvaluationResults) + // @ts-expect-error .groupBy(selectedEvaluationResults.documentUuid) .as('aggregated_results') @@ -177,6 +180,7 @@ export class ConnectedEvaluationsRepository extends Repository< selectedEvaluationResults, eq( aggregatedResults.documentUuid, + // @ts-expect-error selectedEvaluationResults.documentUuid, ), ) diff --git a/packages/core/src/repositories/documentLogsRepository/index.ts b/packages/core/src/repositories/documentLogsRepository/index.ts index be2c0cd14..a0dd2bf08 100644 --- a/packages/core/src/repositories/documentLogsRepository/index.ts +++ b/packages/core/src/repositories/documentLogsRepository/index.ts @@ -9,7 +9,7 @@ import Repository from '../repository' export type DocumentLogWithMetadata = DocumentLog & { commit: Commit tokens: number | null - durationInMs: number | null + duration: number | null costInMillicents: number | null } diff --git a/packages/core/src/repositories/evaluationResultsRepository/findByDocumentUuid.test.ts b/packages/core/src/repositories/evaluationResultsRepository/findByDocumentUuid.test.ts index 3cd64cfe8..0e9ce153f 100644 --- a/packages/core/src/repositories/evaluationResultsRepository/findByDocumentUuid.test.ts +++ b/packages/core/src/repositories/evaluationResultsRepository/findByDocumentUuid.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest' import { EvaluationResultsRepository } from '.' -import { Providers } from '../../constants' +import { EvaluationResultableType, Providers } from '../../constants' import { mergeCommit } from '../../services/commits' import * as factories from '../../tests/factories' @@ -17,6 +17,12 @@ describe('findEvaluationResultsByDocumentUuid', () => { const evaluation = await factories.createLlmAsJudgeEvaluation({ workspace, prompt: factories.helpers.createPrompt({ provider }), + configuration: { + type: EvaluationResultableType.Number, + detail: { + range: { from: 0, to: 100 }, + }, + }, }) const { commit: draft } = await factories.createDraft({ project, user }) diff --git a/packages/core/src/repositories/evaluationResultsRepository/index.ts b/packages/core/src/repositories/evaluationResultsRepository/index.ts index a988297a8..f2c35c7a3 100644 --- a/packages/core/src/repositories/evaluationResultsRepository/index.ts +++ b/packages/core/src/repositories/evaluationResultsRepository/index.ts @@ -1,25 +1,69 @@ -import { eq, getTableColumns } from 'drizzle-orm' +import { eq, getTableColumns, sql } from 'drizzle-orm' +import { NodePgDatabase } from 'drizzle-orm/node-postgres' -import { EvaluationResult } from '../../browser' +import { EvaluationResult, EvaluationResultableType } from '../../browser' import { Result } from '../../lib' -import { documentLogs, evaluationResults, evaluations } from '../../schema' +import { + documentLogs, + evaluationResultableBooleans, + evaluationResultableNumbers, + evaluationResultableTexts, + evaluationResults, + evaluations, +} from '../../schema' import Repository from '../repository' -const tt = getTableColumns(evaluationResults) +export const evaluationResultDto = { + ...getTableColumns(evaluationResults), + result: sql` + CASE + WHEN ${evaluationResults.resultableType} = ${EvaluationResultableType.Boolean} THEN ${evaluationResultableBooleans.result}::text + WHEN ${evaluationResults.resultableType} = ${EvaluationResultableType.Number} THEN ${evaluationResultableNumbers.result}::text + WHEN ${evaluationResults.resultableType} = ${EvaluationResultableType.Text} THEN ${evaluationResultableTexts.result} + END + `.as('result'), +} + +export type EvaluationResultDto = EvaluationResult & { + result: string | number | boolean +} export class EvaluationResultsRepository extends Repository< - typeof tt, - EvaluationResult + typeof evaluationResultDto, + EvaluationResultDto > { - get scope() { - return this.db - .select(tt) + static baseQuery( + db: NodePgDatabase, + selectStatements?: Record, + ) { + return db + .select({ + ...evaluationResultDto, + ...selectStatements, + }) .from(evaluationResults) .innerJoin( evaluations, eq(evaluations.id, evaluationResults.evaluationId), ) - .as('evaluationResultsScope') + .leftJoin( + evaluationResultableBooleans, + sql`${evaluationResults.resultableType} = ${EvaluationResultableType.Boolean} AND ${evaluationResults.resultableId} = ${evaluationResultableBooleans.id}`, + ) + .leftJoin( + evaluationResultableNumbers, + sql`${evaluationResults.resultableType} = ${EvaluationResultableType.Number} AND ${evaluationResults.resultableId} = ${evaluationResultableNumbers.id}`, + ) + .leftJoin( + evaluationResultableTexts, + sql`${evaluationResults.resultableType} = ${EvaluationResultableType.Text} AND ${evaluationResults.resultableId} = ${evaluationResultableTexts.id}`, + ) + } + + get scope() { + return EvaluationResultsRepository.baseQuery(this.db).as( + 'evaluationResultsScope', + ) } async findByDocumentUuid(uuid: string) { @@ -29,6 +73,28 @@ export class EvaluationResultsRepository extends Repository< .innerJoin(documentLogs, eq(documentLogs.id, this.scope.documentLogId)) .where(eq(documentLogs.documentUuid, uuid)) - return Result.ok(result) + return Result.ok(result.map(this.parseResult)) + } + + private parseResult(row: EvaluationResult & { result: string }) { + const { result, resultableType, ...rest } = row + + let parsedResult + switch (resultableType) { + case EvaluationResultableType.Boolean: + parsedResult = result.toLowerCase() === 'true' + break + case EvaluationResultableType.Number: + parsedResult = parseFloat(result) + break + default: + parsedResult = result + } + + return { + ...rest, + resultableType, + result: parsedResult, + } } } diff --git a/packages/core/src/schema/index.ts b/packages/core/src/schema/index.ts index fbaa7d20b..3d6b052ed 100644 --- a/packages/core/src/schema/index.ts +++ b/packages/core/src/schema/index.ts @@ -29,3 +29,7 @@ export * from './models/evaluationTemplateCategories' export * from './models/magicLinkTokens' export * from './models/events' + +export * from './models/evaluationResultableNumbers' +export * from './models/evaluationResultableTexts' +export * from './models/evaluationResultableBooleans' diff --git a/packages/core/src/schema/models/evaluationResultableBooleans.ts b/packages/core/src/schema/models/evaluationResultableBooleans.ts new file mode 100644 index 000000000..72c9ca0f7 --- /dev/null +++ b/packages/core/src/schema/models/evaluationResultableBooleans.ts @@ -0,0 +1,13 @@ +import { bigserial, boolean } from 'drizzle-orm/pg-core' + +import { latitudeSchema } from '../db-schema' +import { timestamps } from '../schemaHelpers' + +export const evaluationResultableBooleans = latitudeSchema.table( + 'evaluation_resultable_booleans', + { + id: bigserial('id', { mode: 'number' }).notNull().primaryKey(), + result: boolean('result').notNull(), + ...timestamps(), + }, +) diff --git a/packages/core/src/schema/models/evaluationResultableNumbers.ts b/packages/core/src/schema/models/evaluationResultableNumbers.ts new file mode 100644 index 000000000..cbe301d40 --- /dev/null +++ b/packages/core/src/schema/models/evaluationResultableNumbers.ts @@ -0,0 +1,13 @@ +import { bigint, bigserial } from 'drizzle-orm/pg-core' + +import { latitudeSchema } from '../db-schema' +import { timestamps } from '../schemaHelpers' + +export const evaluationResultableNumbers = latitudeSchema.table( + 'evaluation_resultable_numbers', + { + id: bigserial('id', { mode: 'number' }).notNull().primaryKey(), + result: bigint('result', { mode: 'number' }).notNull(), + ...timestamps(), + }, +) diff --git a/packages/core/src/schema/models/evaluationResultableTexts.ts b/packages/core/src/schema/models/evaluationResultableTexts.ts new file mode 100644 index 000000000..51e81775a --- /dev/null +++ b/packages/core/src/schema/models/evaluationResultableTexts.ts @@ -0,0 +1,13 @@ +import { bigserial, text } from 'drizzle-orm/pg-core' + +import { latitudeSchema } from '../db-schema' +import { timestamps } from '../schemaHelpers' + +export const evaluationResultableTexts = latitudeSchema.table( + 'evaluation_resultable_texts', + { + id: bigserial('id', { mode: 'number' }).notNull().primaryKey(), + result: text('result').notNull(), + ...timestamps(), + }, +) diff --git a/packages/core/src/schema/models/evaluationResults.ts b/packages/core/src/schema/models/evaluationResults.ts index 5e6da78bf..96c901fcf 100644 --- a/packages/core/src/schema/models/evaluationResults.ts +++ b/packages/core/src/schema/models/evaluationResults.ts @@ -1,11 +1,18 @@ -import { bigint, bigserial, index, text } from 'drizzle-orm/pg-core' +import { bigint, bigserial, index, pgEnum } from 'drizzle-orm/pg-core' +import { EvaluationResultableType } from '../../constants' import { latitudeSchema } from '../db-schema' import { documentLogs } from '../models/documentLogs' import { providerLogs } from '../models/providerLogs' import { timestamps } from '../schemaHelpers' import { evaluations } from './evaluations' +export const evaluationResultTypes = pgEnum('evaluation_result_types', [ + EvaluationResultableType.Boolean, + EvaluationResultableType.Text, + EvaluationResultableType.Number, +]) + export const evaluationResults = latitudeSchema.table( 'evaluation_results', { @@ -19,7 +26,8 @@ export const evaluationResults = latitudeSchema.table( providerLogId: bigint('provider_log_id', { mode: 'number' }) .notNull() .references(() => providerLogs.id), - result: text('result').notNull(), + resultableType: evaluationResultTypes('resultable_type').notNull(), + resultableId: bigint('resultable_id', { mode: 'number' }).notNull(), ...timestamps(), }, (table) => ({ @@ -30,5 +38,9 @@ export const evaluationResults = latitudeSchema.table( evaluationResultProviderLogIdx: index('provider_log_idx').on( table.providerLogId, ), + evaluationResultMetadataIdx: index('resultable_idx').on( + table.resultableId, + table.resultableType, + ), }), ) diff --git a/packages/core/src/schema/models/evaluationTemplates.ts b/packages/core/src/schema/models/evaluationTemplates.ts index b52130cbb..e5fe5d32f 100644 --- a/packages/core/src/schema/models/evaluationTemplates.ts +++ b/packages/core/src/schema/models/evaluationTemplates.ts @@ -1,8 +1,9 @@ import { relations } from 'drizzle-orm' -import { bigint, bigserial, text, varchar } from 'drizzle-orm/pg-core' +import { bigint, bigserial, jsonb, text, varchar } from 'drizzle-orm/pg-core' import { evaluationTemplateCategories, latitudeSchema } from '..' import { timestamps } from '../schemaHelpers' +import { EvaluationResultConfiguration } from '../types' export const evaluationTemplates = latitudeSchema.table( 'evaluations_templates', @@ -14,6 +15,9 @@ export const evaluationTemplates = latitudeSchema.table( () => evaluationTemplateCategories.id, { onDelete: 'restrict', onUpdate: 'cascade' }, ), + configuration: jsonb('configuration') + .notNull() + .$type(), prompt: text('prompt').notNull(), ...timestamps(), }, diff --git a/packages/core/src/schema/models/evaluations.ts b/packages/core/src/schema/models/evaluations.ts index 3f256b730..23455a42b 100644 --- a/packages/core/src/schema/models/evaluations.ts +++ b/packages/core/src/schema/models/evaluations.ts @@ -2,6 +2,7 @@ import { bigint, bigserial, index, + jsonb, text, uuid, varchar, @@ -11,6 +12,7 @@ import { EvaluationMetadataType } from '../../constants' import { latitudeSchema } from '../db-schema' import { workspaces } from '../models/workspaces' import { timestamps } from '../schemaHelpers' +import { EvaluationResultConfiguration } from '../types' export const metadataTypesEnum = latitudeSchema.enum('metadata_type', [ EvaluationMetadataType.LlmAsJudge, @@ -23,11 +25,14 @@ export const evaluations = latitudeSchema.table( uuid: uuid('uuid').notNull().unique().defaultRandom(), name: varchar('name', { length: 256 }).notNull(), description: text('description').notNull(), + metadataId: bigint('metadata_id', { mode: 'number' }).notNull(), + configuration: jsonb('configuration') + .notNull() + .$type(), + metadataType: metadataTypesEnum('metadata_type').notNull(), workspaceId: bigint('workspace_id', { mode: 'number' }) .notNull() .references(() => workspaces.id, { onDelete: 'cascade' }), - metadataId: bigint('metadata_id', { mode: 'number' }).notNull(), - metadataType: metadataTypesEnum('metadata_type').notNull(), ...timestamps(), }, (table) => ({ diff --git a/packages/core/src/schema/models/providerLogs.ts b/packages/core/src/schema/models/providerLogs.ts index fd7f3ca87..0118367b1 100644 --- a/packages/core/src/schema/models/providerLogs.ts +++ b/packages/core/src/schema/models/providerLogs.ts @@ -39,7 +39,7 @@ export const providerLogs = latitudeSchema.table('provider_logs', { responseText: text('response_text').$type().notNull().default(''), toolCalls: json('tool_calls').$type().notNull().default([]), tokens: bigint('tokens', { mode: 'number' }).notNull(), - cost_in_millicents: integer('cost_in_millicents').notNull().default(0), + costInMillicents: integer('cost_in_millicents').notNull().default(0), duration: bigint('duration', { mode: 'number' }).notNull(), // in milliseconds! source: logSourcesEnum('source').notNull(), apiKeyId: bigint('apiKeyId', { mode: 'number' }).references( diff --git a/packages/core/src/schema/types.ts b/packages/core/src/schema/types.ts index e055118d1..a3009e2e1 100644 --- a/packages/core/src/schema/types.ts +++ b/packages/core/src/schema/types.ts @@ -1,6 +1,7 @@ import { ToolCall } from '@latitude-data/compiler' import { type InferSelectModel } from 'drizzle-orm' +import { EvaluationResultableType } from '../constants' import { apiKeys } from './models/apiKeys' import { commits } from './models/commits' import { connectedEvaluations } from './models/connectedEvaluations' @@ -56,8 +57,6 @@ export type LlmAsJudgeEvaluationMetadata = InferSelectModel< typeof llmAsJudgeEvaluationMetadatas > -export type { EvaluationTemplateWithCategory } from '../data-access/evaluationTemplates' - export type EvaluationDto = Evaluation & { metadata: Omit< LlmAsJudgeEvaluationMetadata, @@ -68,3 +67,16 @@ export type EvaluationDto = Evaluation & { export type Dataset = InferSelectModel & { author: Pick | undefined } + +type EvaluationResultNumberConfiguration = { + range: { from: number; to: number } +} + +export type EvaluationResultConfiguration = { + type: EvaluationResultableType + detail?: EvaluationResultNumberConfiguration +} + +export type EvaluationTemplateWithCategory = EvaluationTemplate & { + category: string +} diff --git a/packages/core/src/services/documentLogs/_createDocumentLogQuery.ts b/packages/core/src/services/documentLogs/_createDocumentLogQuery.ts index 68132a666..19b01d652 100644 --- a/packages/core/src/services/documentLogs/_createDocumentLogQuery.ts +++ b/packages/core/src/services/documentLogs/_createDocumentLogQuery.ts @@ -13,10 +13,8 @@ export function createDocumentLogQuery(workspaceId: number, db = database) { .select({ id: scope.id, tokens: sum(providerLogs.tokens).mapWith(Number).as('tokens'), - durationInMs: sum(providerLogs.duration) - .mapWith(Number) - .as('duration_in_ms'), - costInMillicents: sum(providerLogs.cost_in_millicents) + duration: sum(providerLogs.duration).mapWith(Number).as('duration_in_ms'), + costInMillicents: sum(providerLogs.costInMillicents) .mapWith(Number) .as('cost_in_millicents'), }) @@ -33,7 +31,7 @@ export function createDocumentLogQuery(workspaceId: number, db = database) { ...scope._.selectedFields, commit: commits, tokens: aggregatedFieldsSubQuery.tokens, - durationInMs: aggregatedFieldsSubQuery.durationInMs, + duration: aggregatedFieldsSubQuery.duration, costInMillicents: aggregatedFieldsSubQuery.costInMillicents, }) .from(scope) diff --git a/packages/core/src/services/documentLogs/computeDocumentLogWithMetadata.test.ts b/packages/core/src/services/documentLogs/computeDocumentLogWithMetadata.test.ts index d6015f232..2d407f5e8 100644 --- a/packages/core/src/services/documentLogs/computeDocumentLogWithMetadata.test.ts +++ b/packages/core/src/services/documentLogs/computeDocumentLogWithMetadata.test.ts @@ -79,12 +79,9 @@ describe('computeDocumentLogWithMetadata', () => { uuid: documentLog.uuid, documentUuid: documentLog.documentUuid, tokens: totalProviderLogs.reduce((acc, log) => acc + log.tokens, 0), - durationInMs: totalProviderLogs.reduce( - (acc, log) => acc + log.duration, - 0, - ), + duration: totalProviderLogs.reduce((acc, log) => acc + log.duration, 0), costInMillicents: totalProviderLogs.reduce( - (acc, log) => acc + log.cost_in_millicents, + (acc, log) => acc + log.costInMillicents, 0, ), }) diff --git a/packages/core/src/services/evaluationResults/create.test.ts b/packages/core/src/services/evaluationResults/create.test.ts new file mode 100644 index 000000000..5b683494d --- /dev/null +++ b/packages/core/src/services/evaluationResults/create.test.ts @@ -0,0 +1,179 @@ +import { eq } from 'drizzle-orm' +import { describe, expect, it } from 'vitest' + +import { database } from '../../client' +import { EvaluationResultableType, Providers } from '../../constants' +import { + evaluationResultableBooleans, + evaluationResultableNumbers, + evaluationResultableTexts, + evaluationResults, +} from '../../schema' +import * as factories from '../../tests/factories' +import { createEvaluationResult } from './create' + +async function setupTest(configurationType: EvaluationResultableType) { + const { workspace, project, user, providers } = await factories.createProject( + { providers: [{ name: 'foo', type: Providers.OpenAI }] }, + ) + const provider = providers[0] + const evaluation = await factories.createLlmAsJudgeEvaluation({ + workspace, + configuration: { + type: configurationType, + ...(configurationType === EvaluationResultableType.Number + ? { detail: { range: { from: 0, to: 100 } } } + : {}), + }, + }) + const { commit } = await factories.createDraft({ project, user }) + const { documentVersion } = await factories.createDocumentVersion({ + commit, + content: ` + --- + provider: ${provider!.name} + model: 'gpt-4o-mini' + --- + `, + }) + const { documentLog } = await factories.createDocumentLog({ + document: documentVersion, + commit, + }) + const providerLog = await factories.createProviderLog({ + providerId: provider!.id, + providerType: provider!.provider, + documentLogUuid: documentLog.uuid, + }) + + return { evaluation, documentLog, providerLog } +} + +describe('createEvaluationResult', () => { + it('creates a boolean evaluation result', async () => { + const { evaluation, documentLog, providerLog } = await setupTest( + EvaluationResultableType.Boolean, + ) + + const result = await createEvaluationResult({ + evaluation, + documentLog, + providerLog, + result: true, + }) + + expect(result.ok).toBe(true) + if (result.error) return + + expect(result.value.evaluationId).toBe(evaluation.id) + expect(result.value.documentLogId).toBe(documentLog.id) + expect(result.value.providerLogId).toBe(providerLog.id) + expect(result.value.resultableType).toBe(EvaluationResultableType.Boolean) + expect(result.value.result).toBe(true) + + // Verify in database + const dbResult = await database.query.evaluationResults.findFirst({ + where: eq(evaluationResults.id, result.value.id), + }) + expect(dbResult).toBeDefined() + expect(dbResult?.resultableType).toBe(EvaluationResultableType.Boolean) + + const booleanResult = + await database.query.evaluationResultableBooleans.findFirst({ + where: eq(evaluationResultableBooleans.id, dbResult!.resultableId), + }) + expect(booleanResult).toBeDefined() + expect(booleanResult?.result).toBe(true) + }) + + it('creates a number evaluation result', async () => { + const { evaluation, documentLog, providerLog } = await setupTest( + EvaluationResultableType.Number, + ) + + const result = await createEvaluationResult({ + evaluation, + documentLog, + providerLog, + result: 75, + }) + + expect(result.ok).toBe(true) + if (result.error) return + + expect(result.value.evaluationId).toBe(evaluation.id) + expect(result.value.documentLogId).toBe(documentLog.id) + expect(result.value.providerLogId).toBe(providerLog.id) + expect(result.value.resultableType).toBe(EvaluationResultableType.Number) + expect(result.value.result).toBe(75) + + // Verify in database + const dbResult = await database.query.evaluationResults.findFirst({ + where: eq(evaluationResults.id, result.value.id), + }) + expect(dbResult).toBeDefined() + expect(dbResult?.resultableType).toBe(EvaluationResultableType.Number) + + const numberResult = + await database.query.evaluationResultableNumbers.findFirst({ + where: eq(evaluationResultableNumbers.id, dbResult!.resultableId), + }) + expect(numberResult).toBeDefined() + expect(numberResult?.result).toBe(75) + }) + + it('creates a text evaluation result', async () => { + const { evaluation, documentLog, providerLog } = await setupTest( + EvaluationResultableType.Text, + ) + + const result = await createEvaluationResult({ + evaluation, + documentLog, + providerLog, + result: 'This is a text result', + }) + + expect(result.ok).toBe(true) + if (result.error) return + + expect(result.value.evaluationId).toBe(evaluation.id) + expect(result.value.documentLogId).toBe(documentLog.id) + expect(result.value.providerLogId).toBe(providerLog.id) + expect(result.value.resultableType).toBe(EvaluationResultableType.Text) + expect(result.value.result).toBe('This is a text result') + + // Verify in database + const dbResult = await database.query.evaluationResults.findFirst({ + where: eq(evaluationResults.id, result.value.id), + }) + expect(dbResult).toBeDefined() + expect(dbResult?.resultableType).toBe(EvaluationResultableType.Text) + + const textResult = await database.query.evaluationResultableTexts.findFirst( + { + where: eq(evaluationResultableTexts.id, dbResult!.resultableId), + }, + ) + expect(textResult).toBeDefined() + expect(textResult?.result).toBe('This is a text result') + }) + + it('returns an error for unsupported result type', async () => { + const { evaluation, documentLog, providerLog } = await setupTest( + 'UnsupportedType' as any, + ) + + const result = await createEvaluationResult({ + evaluation, + documentLog, + providerLog, + result: 'Some result', + }) + + expect(result.ok).toBe(false) + if (result.error) { + expect(result.error.message).toContain('Unsupported result type') + } + }) +}) diff --git a/packages/core/src/services/evaluationResults/create.ts b/packages/core/src/services/evaluationResults/create.ts index 7100af4d8..bcc4d871d 100644 --- a/packages/core/src/services/evaluationResults/create.ts +++ b/packages/core/src/services/evaluationResults/create.ts @@ -2,37 +2,65 @@ import { DocumentLog, Evaluation, EvaluationDto, - EvaluationResult, + EvaluationResultableType, ProviderLog, } from '../../browser' import { database } from '../../client' -import { Result, Transaction } from '../../lib' +import { BadRequestError, Result, Transaction } from '../../lib' +import { EvaluationResultDto } from '../../repositories/evaluationResultsRepository' import { evaluationResults } from '../../schema' +import { evaluationResultableBooleans } from '../../schema/models/evaluationResultableBooleans' +import { evaluationResultableNumbers } from '../../schema/models/evaluationResultableNumbers' +import { evaluationResultableTexts } from '../../schema/models/evaluationResultableTexts' export type CreateEvaluationResultProps = { evaluation: Evaluation | EvaluationDto documentLog: DocumentLog providerLog: ProviderLog - result: string + result: number | string | boolean } export async function createEvaluationResult( { evaluation, documentLog, providerLog, result }: CreateEvaluationResultProps, db = database, ) { - return Transaction.call(async (trx) => { + return Transaction.call(async (trx) => { + let table + switch (evaluation.configuration.type) { + case EvaluationResultableType.Boolean: + table = evaluationResultableBooleans + break + case EvaluationResultableType.Number: + table = evaluationResultableNumbers + break + case EvaluationResultableType.Text: + table = evaluationResultableTexts + break + default: + return Result.error( + new BadRequestError( + `Unsupported result type: ${evaluation.configuration.type}`, + ), + ) + } + + const metadata = await trx.insert(table).values({ result }).returning() const inserts = await trx .insert(evaluationResults) .values({ evaluationId: evaluation.id, documentLogId: documentLog.id, providerLogId: providerLog.id, - result, + resultableType: evaluation.configuration.type, + resultableId: metadata[0]!.id, }) .returning() const evaluationResult = inserts[0]! - return Result.ok(evaluationResult) + return Result.ok({ + ...evaluationResult, + result: metadata[0]!.result, + }) }, db) } diff --git a/packages/core/src/services/evaluationTemplates/create.test.ts b/packages/core/src/services/evaluationTemplates/create.test.ts index 6a6727ccb..e703be354 100644 --- a/packages/core/src/services/evaluationTemplates/create.test.ts +++ b/packages/core/src/services/evaluationTemplates/create.test.ts @@ -1,5 +1,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' +import { EvaluationResultableType } from '../../constants' import { findEvaluationTemplateCategoryById } from '../../data-access/evaluationTemplateCategories' import { NotFoundError, Result } from '../../lib' import * as evaluationTemplateCategoriesService from '../evaluationTemplateCategories/create' @@ -22,6 +23,7 @@ describe('createEvaluationTemplate', () => { description: 'Test Description', categoryId: category.id, prompt: 'Test Prompt', + configuration: { type: EvaluationResultableType.Text }, }) expect(result.ok).toBe(true) @@ -40,6 +42,7 @@ describe('createEvaluationTemplate', () => { categoryId: 999, categoryName: 'New Category', prompt: 'Test Prompt', + configuration: { type: EvaluationResultableType.Text }, }) expect(result.ok).toBe(true) @@ -63,6 +66,7 @@ describe('createEvaluationTemplate', () => { name: 'Test Template', description: 'Test Description', prompt: 'Test Prompt', + configuration: { type: EvaluationResultableType.Text }, }) expect(result.ok).toBe(true) @@ -80,6 +84,34 @@ describe('createEvaluationTemplate', () => { } }) + it('creates a configurable number table when configuration is of type number with a range', async () => { + const result = await createEvaluationTemplate({ + name: 'Test Template', + description: 'Test Description', + prompt: 'Test Prompt', + categoryId: 999, + categoryName: 'New Category', + configuration: { + type: EvaluationResultableType.Number, + detail: { range: { from: 1, to: 10 } }, + }, + }) + + expect(result.ok).toBe(true) + if (result.ok) { + expect(result.value).toMatchObject({ + name: 'Test Template', + description: 'Test Description', + prompt: 'Test Prompt', + }) + + expect(result.value?.configuration).toMatchObject({ + type: EvaluationResultableType.Number, + detail: { range: { from: 1, to: 10 } }, + }) + } + }) + it('handles errors when category creation fails', async () => { vi.spyOn( evaluationTemplateCategoriesService, @@ -93,6 +125,7 @@ describe('createEvaluationTemplate', () => { description: 'Test Description', categoryName: 'New Category', prompt: 'Test Prompt', + configuration: { type: EvaluationResultableType.Text }, }) expect(result.ok).toBe(false) diff --git a/packages/core/src/services/evaluationTemplates/create.ts b/packages/core/src/services/evaluationTemplates/create.ts index 5215fcb6f..d7e11f0fb 100644 --- a/packages/core/src/services/evaluationTemplates/create.ts +++ b/packages/core/src/services/evaluationTemplates/create.ts @@ -1,3 +1,4 @@ +import { EvaluationResultConfiguration } from '../../browser' import { database } from '../../client' import { findEvaluationTemplateCategoryById } from '../../data-access/evaluationTemplateCategories' import { NotFoundError, Result, Transaction } from '../../lib' @@ -12,10 +13,11 @@ type Props = { categoryId?: number categoryName?: string prompt: string + configuration: EvaluationResultConfiguration } export async function createEvaluationTemplate( - { name, description, categoryId, categoryName, prompt }: Props, + { name, description, categoryId, categoryName, configuration, prompt }: Props, db = database, ) { return await Transaction.call(async (tx) => { @@ -44,11 +46,15 @@ export async function createEvaluationTemplate( name, description, categoryId: category.id, + configuration, prompt, }) .returning() - return Result.ok(result[0]!) + return Result.ok({ + ...result[0]!, + category, + }) }, db) } @@ -57,5 +63,6 @@ async function createCategory(categoryName: string | undefined, tx = database) { { name: categoryName || DEFAULT_CATEGORY_NAME }, tx, ) + return newCategoryResult.unwrap() } diff --git a/packages/core/src/services/evaluations/create.test.ts b/packages/core/src/services/evaluations/create.test.ts new file mode 100644 index 000000000..4d987bb4d --- /dev/null +++ b/packages/core/src/services/evaluations/create.test.ts @@ -0,0 +1,141 @@ +import { beforeEach, describe, expect, it } from 'vitest' + +import { + EvaluationMetadataType, + EvaluationResultableType, +} from '../../constants' +import * as factories from '../../tests/factories' +import { createEvaluation } from './create' + +describe('createEvaluation', () => { + let workspace: any + + beforeEach(async () => { + const setup = await factories.createWorkspace() + workspace = setup.workspace + }) + + it('creates an LLM as Judge evaluation with number configuration', async () => { + const name = 'Test Evaluation' + const description = 'Test Description' + const metadata = { prompt: 'Test prompt' } + + const result = await createEvaluation({ + workspace, + name, + description, + type: EvaluationMetadataType.LlmAsJudge, + configuration: { + type: EvaluationResultableType.Number, + }, + metadata, + }) + + expect(result.ok).toBe(true) + + if (result.ok) { + const evaluation = result.value! + expect(evaluation.name).toBe(name) + expect(evaluation.description).toBe(description) + expect(evaluation.configuration.type).toBe( + EvaluationResultableType.Number, + ) + expect(evaluation.metadataType).toBe(EvaluationMetadataType.LlmAsJudge) + expect(evaluation.workspaceId).toBe(workspace.id) + } + }) + + it('creates an LLM as Judge evaluation with text configuration', async () => { + const name = 'Test Evaluation' + const description = 'Test Description' + const metadata = { prompt: 'Test prompt' } + + const result = await createEvaluation({ + workspace, + name, + description, + configuration: { + type: EvaluationResultableType.Text, + }, + type: EvaluationMetadataType.LlmAsJudge, + metadata, + }) + + expect(result.ok).toBe(true) + if (result.ok) { + const evaluation = result.value! + expect(evaluation.configuration.type).toBe(EvaluationResultableType.Text) + } + }) + + it('creates an LLM as Judge evaluation with boolean configuration', async () => { + const name = 'Test Evaluation' + const description = 'Test Description' + const metadata = { prompt: 'Test prompt' } + + const result = await createEvaluation({ + workspace, + name, + description, + type: EvaluationMetadataType.LlmAsJudge, + configuration: { + type: EvaluationResultableType.Boolean, + }, + metadata, + }) + + expect(result.ok).toBe(true) + if (result.ok) { + const evaluation = result.value! + expect(evaluation.configuration.type).toBe( + EvaluationResultableType.Boolean, + ) + } + }) + + it('returns an error for invalid evaluation type', async () => { + const result = await createEvaluation({ + workspace, + name: 'Test Evaluation', + description: 'Test Description', + type: 'InvalidType' as EvaluationMetadataType, + configuration: { + type: EvaluationResultableType.Text, + }, + metadata: {}, + }) + + expect(result.ok).toBe(false) + if (result.error) { + expect(result.error.message).toContain('Invalid evaluation type') + } + }) + + it('creates an evaluation with a template', async () => { + const template = await factories.createEvaluationTemplate({ + name: 'Test Template', + description: 'Test Description', + prompt: 'Test prompt', + categoryId: 1, + categoryName: 'Test Category', + }) + const metadata = { prompt: 'Test prompt', templateId: template.id } + + const result = await createEvaluation({ + workspace, + name: 'Test Evaluation', + description: 'Test Description', + type: EvaluationMetadataType.LlmAsJudge, + configuration: { + type: EvaluationResultableType.Text, + }, + metadata, + }) + + expect(result.ok).toBe(true) + if (result.ok) { + const evaluation = result.value! + expect(evaluation.metadata.templateId).toBe(template.id) + } + }) +}) diff --git a/packages/core/src/services/evaluations/create.ts b/packages/core/src/services/evaluations/create.ts index d6187fea2..cdfcd9e73 100644 --- a/packages/core/src/services/evaluations/create.ts +++ b/packages/core/src/services/evaluations/create.ts @@ -1,7 +1,12 @@ -import { EvaluationMetadataType, SafeWorkspace, Workspace } from '../../browser' +import { + EvaluationMetadataType, + EvaluationResultConfiguration, + SafeWorkspace, + Workspace, +} from '../../browser' import { database } from '../../client' import { findEvaluationTemplateById } from '../../data-access' -import { Result, Transaction } from '../../lib' +import { BadRequestError, Result, Transaction } from '../../lib' import { evaluations, llmAsJudgeEvaluationMetadatas } from '../../schema' type Props = { @@ -9,11 +14,12 @@ type Props = { name: string description: string type: EvaluationMetadataType + configuration: EvaluationResultConfiguration metadata?: Record } export async function createEvaluation( - { workspace, name, description, type, metadata = {} }: Props, + { workspace, name, description, type, configuration, metadata = {} }: Props, db = database, ) { return await Transaction.call(async (tx) => { @@ -26,22 +32,30 @@ export async function createEvaluation( .returning() break + default: + return Result.error( + new BadRequestError(`Invalid evaluation type ${type}`), + ) } const result = await tx .insert(evaluations) .values([ { + configuration, description, metadataId: metadataTable[0]!.id, - name, metadataType: type, + name, workspaceId: workspace.id, }, ]) .returning() - return Result.ok({ ...result[0]!, metadata: metadataTable[0]! }) + return Result.ok({ + ...result[0]!, + metadata: metadataTable[0]!, + }) }, db) } @@ -62,6 +76,7 @@ export async function importLlmAsJudgeEvaluation( name: template.name, description: template.description, type: EvaluationMetadataType.LlmAsJudge, + configuration: template.configuration, metadata: { prompt: template.prompt, templateId: template.id, diff --git a/packages/core/src/services/evaluations/run.ts b/packages/core/src/services/evaluations/run.ts index 139eecc89..20afcbd29 100644 --- a/packages/core/src/services/evaluations/run.ts +++ b/packages/core/src/services/evaluations/run.ts @@ -48,7 +48,7 @@ export const runEvaluation = async ( prompt: documentLog.resolvedContent, parameters: documentLog.parameters, config: metadata.config, - duration: documentLogWithMetadata.durationInMs, + duration: documentLogWithMetadata.duration, cost: documentLogWithMetadata.costInMillicents ? documentLogWithMetadata.costInMillicents * 1000 : 0, diff --git a/packages/core/src/services/providerLogs/create.ts b/packages/core/src/services/providerLogs/create.ts index 3a346c5ec..73a4cb057 100644 --- a/packages/core/src/services/providerLogs/create.ts +++ b/packages/core/src/services/providerLogs/create.ts @@ -69,7 +69,7 @@ export async function createProviderLog( responseText, toolCalls, tokens: isNaN(usage.totalTokens) ? 0 : (usage.totalTokens ?? 0), - cost_in_millicents: cost, + costInMillicents: cost, duration, source, apiKeyId, diff --git a/packages/core/src/tests/factories/evaluationTemplates.ts b/packages/core/src/tests/factories/evaluationTemplates.ts index 6081d44ca..78d21afe2 100644 --- a/packages/core/src/tests/factories/evaluationTemplates.ts +++ b/packages/core/src/tests/factories/evaluationTemplates.ts @@ -1,5 +1,6 @@ import { faker } from '@faker-js/faker' +import { EvaluationResultableType } from '../../constants' import { createEvaluationTemplate as createEvaluationTemplateService } from '../../services/evaluationTemplates/create' export type IEvaluationTemplateData = { @@ -23,6 +24,9 @@ export async function createEvaluationTemplate({ categoryId, categoryName: categoryName ?? faker.lorem.word(), prompt, + configuration: { + type: EvaluationResultableType.Text, + }, }) return evaluationTemplateResult.unwrap() diff --git a/packages/core/src/tests/factories/evaluations.ts b/packages/core/src/tests/factories/evaluations.ts index 91d548a75..86ea7af14 100644 --- a/packages/core/src/tests/factories/evaluations.ts +++ b/packages/core/src/tests/factories/evaluations.ts @@ -1,6 +1,11 @@ import { faker } from '@faker-js/faker' -import { EvaluationMetadataType, Workspace } from '../../browser' +import { + EvaluationMetadataType, + EvaluationResultableType, + EvaluationResultConfiguration, + Workspace, +} from '../../browser' import { createEvaluation as createEvaluationService } from '../../services/evaluations' export type IEvaluationData = { @@ -8,6 +13,7 @@ export type IEvaluationData = { name?: string description?: string prompt?: string + configuration?: EvaluationResultConfiguration } export async function createLlmAsJudgeEvaluation({ @@ -15,6 +21,9 @@ export async function createLlmAsJudgeEvaluation({ name, description, prompt, + configuration = { + type: EvaluationResultableType.Text, + }, }: IEvaluationData) { const evaluationResult = await createEvaluationService({ workspace, @@ -22,6 +31,7 @@ export async function createLlmAsJudgeEvaluation({ type: EvaluationMetadataType.LlmAsJudge, name: name ?? faker.company.catchPhrase(), description: description ?? faker.lorem.sentence(), + configuration, }) return evaluationResult.unwrap() diff --git a/packages/jobs/package.json b/packages/jobs/package.json index 86bd23beb..8baa45c6a 100644 --- a/packages/jobs/package.json +++ b/packages/jobs/package.json @@ -15,6 +15,7 @@ "@latitude-data/env": "workspace:*" }, "devDependencies": { + "@latitude-data/core": "workspace:^", "@latitude-data/eslint-config": "workspace:*", "@latitude-data/typescript-config": "workspace:*", "@types/node": "*", diff --git a/packages/jobs/tests/setup.ts b/packages/jobs/tests/setup.ts new file mode 100644 index 000000000..d21c7adb5 --- /dev/null +++ b/packages/jobs/tests/setup.ts @@ -0,0 +1,4 @@ +// vitest-env.d.ts +import useTestDatabase from '@latitude-data/core/test' + +useTestDatabase() diff --git a/packages/jobs/vitest.config.mjs b/packages/jobs/vitest.config.mjs new file mode 100644 index 000000000..4c5522c7f --- /dev/null +++ b/packages/jobs/vitest.config.mjs @@ -0,0 +1,12 @@ +/// +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + globals: true, + testTimeout: 5000, + environment: 'node', + setupFiles: ['./tests/setup.ts'], + include: ['./src/**/*.test.ts'], + }, +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4fe8c6e88..c157ace41 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -311,7 +311,7 @@ importers: version: 4.6.0(monaco-editor@0.50.0)(react-dom@19.0.0-rc-f994737d14-20240522(react@19.0.0-rc-f994737d14-20240522))(react@19.0.0-rc-f994737d14-20240522) '@sentry/nextjs': specifier: ^8 - version: 8.29.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.53.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.26.0(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@14.3.0-canary.87(@opentelemetry/api@1.9.0)(react-dom@19.0.0-rc-f994737d14-20240522(react@19.0.0-rc-f994737d14-20240522))(react@19.0.0-rc-f994737d14-20240522))(react@19.0.0-rc-f994737d14-20240522)(webpack@5.94.0) + version: 8.29.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.53.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.26.0(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@14.3.0-canary.87(@opentelemetry/api@1.9.0)(react-dom@19.0.0-rc-f994737d14-20240522(react@19.0.0-rc-f994737d14-20240522))(react@19.0.0-rc-f994737d14-20240522))(react@19.0.0-rc-f994737d14-20240522)(webpack@5.94.0(esbuild@0.19.12)) '@t3-oss/env-nextjs': specifier: ^0.10.1 version: 0.10.1(typescript@5.5.4)(zod@3.23.8) @@ -650,13 +650,13 @@ importers: packages/jobs: dependencies: - '@latitude-data/core': - specifier: workspace:^ - version: link:../core '@latitude-data/env': specifier: workspace:* version: link:../env devDependencies: + '@latitude-data/core': + specifier: workspace:^ + version: link:../core '@latitude-data/eslint-config': specifier: workspace:* version: link:../../tools/eslint @@ -2283,9 +2283,6 @@ packages: peerDependencies: drizzle-orm: '>= 0.29 <1' lucia: 3.x - peerDependenciesMeta: - drizzle-orm: - optional: true '@lukeed/ms@2.0.2': resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} @@ -10470,9 +10467,8 @@ snapshots: '@lucia-auth/adapter-drizzle@1.1.0(drizzle-orm@0.33.0(@opentelemetry/api@1.9.0)(@types/pg@8.11.8)(@types/react@18.3.0)(pg@8.12.0)(react@19.0.0-rc-f994737d14-20240522))(lucia@3.2.0)': dependencies: - lucia: 3.2.0 - optionalDependencies: drizzle-orm: 0.33.0(@opentelemetry/api@1.9.0)(@types/pg@8.11.8)(@types/react@18.3.0)(pg@8.12.0)(react@19.0.0-rc-f994737d14-20240522) + lucia: 3.2.0 '@lukeed/ms@2.0.2': {} @@ -12384,7 +12380,7 @@ snapshots: '@sentry/types': 8.29.0 '@sentry/utils': 8.29.0 - '@sentry/nextjs@8.29.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.53.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.26.0(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@14.3.0-canary.87(@opentelemetry/api@1.9.0)(react-dom@19.0.0-rc-f994737d14-20240522(react@19.0.0-rc-f994737d14-20240522))(react@19.0.0-rc-f994737d14-20240522))(react@19.0.0-rc-f994737d14-20240522)(webpack@5.94.0)': + '@sentry/nextjs@8.29.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.53.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.26.0(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@14.3.0-canary.87(@opentelemetry/api@1.9.0)(react-dom@19.0.0-rc-f994737d14-20240522(react@19.0.0-rc-f994737d14-20240522))(react@19.0.0-rc-f994737d14-20240522))(react@19.0.0-rc-f994737d14-20240522)(webpack@5.94.0(esbuild@0.19.12))': dependencies: '@opentelemetry/instrumentation-http': 0.53.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.27.0 @@ -12396,14 +12392,14 @@ snapshots: '@sentry/types': 8.29.0 '@sentry/utils': 8.29.0 '@sentry/vercel-edge': 8.29.0 - '@sentry/webpack-plugin': 2.22.3(encoding@0.1.13)(webpack@5.94.0) + '@sentry/webpack-plugin': 2.22.3(encoding@0.1.13)(webpack@5.94.0(esbuild@0.19.12)) chalk: 3.0.0 next: 14.3.0-canary.87(@opentelemetry/api@1.9.0)(react-dom@19.0.0-rc-f994737d14-20240522(react@19.0.0-rc-f994737d14-20240522))(react@19.0.0-rc-f994737d14-20240522) resolve: 1.22.8 rollup: 3.29.4 stacktrace-parser: 0.1.10 optionalDependencies: - webpack: 5.94.0 + webpack: 5.94.0(esbuild@0.19.12) transitivePeerDependencies: - '@opentelemetry/api' - '@opentelemetry/core' @@ -12482,12 +12478,12 @@ snapshots: '@sentry/types': 8.29.0 '@sentry/utils': 8.29.0 - '@sentry/webpack-plugin@2.22.3(encoding@0.1.13)(webpack@5.94.0)': + '@sentry/webpack-plugin@2.22.3(encoding@0.1.13)(webpack@5.94.0(esbuild@0.19.12))': dependencies: '@sentry/bundler-plugin-core': 2.22.3(encoding@0.1.13) unplugin: 1.0.1 uuid: 9.0.1 - webpack: 5.94.0 + webpack: 5.94.0(esbuild@0.19.12) transitivePeerDependencies: - encoding - supports-color @@ -17713,14 +17709,16 @@ snapshots: mkdirp: 1.0.4 yallist: 4.0.0 - terser-webpack-plugin@5.3.10(webpack@5.94.0): + terser-webpack-plugin@5.3.10(esbuild@0.19.12)(webpack@5.94.0(esbuild@0.19.12)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.32.0 - webpack: 5.94.0 + webpack: 5.94.0(esbuild@0.19.12) + optionalDependencies: + esbuild: 0.19.12 terser@5.32.0: dependencies: @@ -18375,7 +18373,7 @@ snapshots: webpack-virtual-modules@0.5.0: {} - webpack@5.94.0: + webpack@5.94.0(esbuild@0.19.12): dependencies: '@types/estree': 1.0.5 '@webassemblyjs/ast': 1.12.1 @@ -18397,7 +18395,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(webpack@5.94.0) + terser-webpack-plugin: 5.3.10(esbuild@0.19.12)(webpack@5.94.0(esbuild@0.19.12)) watchpack: 2.4.2 webpack-sources: 3.2.3 transitivePeerDependencies: