Skip to content

Commit

Permalink
feature: connect evaluations to documents
Browse files Browse the repository at this point in the history
  • Loading branch information
geclos committed Sep 9, 2024
1 parent 7dabfcb commit fed831a
Show file tree
Hide file tree
Showing 70 changed files with 7,611 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const getData = async ({
.getProjectById(projectId)
.then((r) => r.unwrap())
const commit = await commitsScope
.getCommitByUuid({ project, uuid: commitUuid })
.getCommitByUuid({ projectId: project.id, uuid: commitUuid })
.then((r) => r.unwrap())

const document = await docsScope
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/actions/documents/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const createDocumentVersionAction = withProject
.handler(async ({ input, ctx }) => {
const commitsScope = new CommitsRepository(ctx.project.workspaceId)
const commit = await commitsScope
.getCommitByUuid({ uuid: input.commitUuid, project: ctx.project })
.getCommitByUuid({ uuid: input.commitUuid, projectId: ctx.project.id })
.then((r) => r.unwrap())

const result = await createNewDocument({
Expand Down
5 changes: 3 additions & 2 deletions apps/web/src/actions/documents/destroyDocumentAction/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ export const destroyDocumentAction = withProject
.handler(async ({ input, ctx }) => {
const commitsScope = new CommitsRepository(ctx.project.workspaceId)
const commit = await commitsScope
.getCommitByUuid({ uuid: input.commitUuid, project: ctx.project })
.getCommitByUuid({ uuid: input.commitUuid, projectId: ctx.project.id })
.then((r) => r.unwrap())
const docsScope = new DocumentVersionsRepository(ctx.project.workspaceId)
const document = await docsScope
.getDocumentAtCommit({
commit,
commitUuid: input.commitUuid,
projectId: ctx.project.id,
documentUuid: input.documentUuid,
})
.then((r) => r.unwrap())
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/actions/documents/destroyFolderAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const destroyFolderAction = withProject
.handler(async ({ input, ctx }) => {
const commitsScope = new CommitsRepository(ctx.project.workspaceId)
const commit = await commitsScope
.getCommitByUuid({ uuid: input.commitUuid, project: ctx.project })
.getCommitByUuid({ uuid: input.commitUuid, projectId: ctx.project.id })
.then((r) => r.unwrap())
const result = await destroyFolder({
path: input.path,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const getDocumentsAtCommitAction = withProject
.input(z.object({ commitUuid: z.string() }))
.handler(async ({ input, ctx }) => {
const commit = await new CommitsRepository(ctx.project.workspaceId)
.getCommitByUuid({ uuid: input.commitUuid, project: ctx.project })
.getCommitByUuid({ uuid: input.commitUuid, projectId: ctx.project.id })
.then((r) => r.unwrap())
const docsScope = new DocumentVersionsRepository(ctx.project.workspaceId)
const result = await docsScope.getDocumentsAtCommit(commit)
Expand Down
5 changes: 3 additions & 2 deletions apps/web/src/actions/documents/updateContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ export const updateDocumentContentAction = withProject
.handler(async ({ input, ctx }) => {
const commitsScope = new CommitsRepository(ctx.project.workspaceId)
const commit = await commitsScope
.getCommitByUuid({ uuid: input.commitUuid, project: ctx.project })
.getCommitByUuid({ uuid: input.commitUuid, projectId: ctx.project.id })
.then((r) => r.unwrap())
const docsScope = new DocumentVersionsRepository(ctx.project.workspaceId)
const document = await docsScope
.getDocumentAtCommit({
commit,
commitUuid: input.commitUuid,
projectId: ctx.project.id,
documentUuid: input.documentUuid,
})
.then((r) => r.unwrap())
Expand Down
12 changes: 12 additions & 0 deletions apps/web/src/actions/evaluationTemplates/fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use server'

import { findAllEvaluationTemplates } from '@latitude-data/core/data-access'

import { authProcedure } from '../procedures'

export const fetchEvaluationTemplatesAction = authProcedure
.createServerAction()
.handler(async () => {
const result = await findAllEvaluationTemplates()
return result.unwrap()
})
146 changes: 146 additions & 0 deletions apps/web/src/actions/evaluations/connect.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { randomUUID } from 'crypto'

import {
Commit,
DocumentVersion,
Project,
ProviderApiKey,
Providers,
User,
Workspace,
} from '@latitude-data/core/browser'
import * as factories from '@latitude-data/core/factories'
import { beforeEach, describe, expect, it, vi } from 'vitest'

import { connectEvaluationsAction } from './connect'

const mocks = vi.hoisted(() => {
return {
getSession: vi.fn(),
}
})

vi.mock('$/services/auth/getSession', () => ({
getSession: mocks.getSession,
}))

describe('connectEvaluationsAction', () => {
describe('unauthorized', () => {
it('errors when the user is not authenticated', async () => {
const [_, error] = await connectEvaluationsAction({
projectId: 1,
documentUuid: 'fake-document-uuid',
commitUuid: 'fake-commit-uuid',
templateIds: [1],
evaluationUuids: ['fake-evaluation-uuid'],
})

expect(error!.name).toEqual('UnauthorizedError')
})
})

describe('authorized', () => {
let workspace: Workspace,
user: User,
document: DocumentVersion,
commit: Commit,
provider: ProviderApiKey,
project: Project

beforeEach(async () => {
const setup = await factories.createProject({
documents: { 'test-doc': 'Test content' },
})
workspace = setup.workspace
user = setup.user
document = setup.documents[0]!
commit = setup.commit
project = setup.project

provider = await factories.createProviderApiKey({
workspace,
type: Providers.OpenAI,
name: 'Test Provider',
user,
})

mocks.getSession.mockReturnValue({
user,
workspace: { id: workspace.id, name: workspace.name },
})
})

it('connects evaluations and templates to a document', async () => {
const evaluation = await factories.createEvaluation({
provider,
name: 'Test Evaluation',
})

const template = await factories.createEvaluationTemplate({
name: 'Test Template',
description: 'Test description',
prompt: 'Test prompt',
})

const [result, error] = await connectEvaluationsAction({
projectId: project.id,
documentUuid: document.documentUuid,
commitUuid: commit.uuid,
templateIds: [template.id],
evaluationUuids: [evaluation.uuid],
})

expect(error).toBeNull()
expect(result).toHaveLength(2)
expect(result).toEqual(
expect.arrayContaining([
expect.objectContaining({
documentUuid: document.documentUuid,
evaluationId: evaluation.id,
}),
expect.objectContaining({
documentUuid: document.documentUuid,
evaluationId: expect.any(Number),
}),
]),
)
})

it('returns an empty array when no evaluations or templates are provided', async () => {
const [result, error] = await connectEvaluationsAction({
projectId: project.id,
documentUuid: document.documentUuid,
commitUuid: commit.uuid,
templateIds: [],
evaluationUuids: [],
})

expect(error).toBeNull()
expect(result).toHaveLength(0)
})

it('fails when the document does not exist', async () => {
const [_, error] = await connectEvaluationsAction({
projectId: project.id,
documentUuid: 'non-existent-uuid',
commitUuid: randomUUID(),
templateIds: [],
evaluationUuids: [],
})

expect(error!.name).toEqual('NotFoundError')
})

it('fails when the commit does not exist', async () => {
const [_, error] = await connectEvaluationsAction({
projectId: project.id,
documentUuid: document.documentUuid,
commitUuid: randomUUID(),
templateIds: [],
evaluationUuids: [],
})

expect(error!.name).toEqual('NotFoundError')
})
})
})
53 changes: 53 additions & 0 deletions apps/web/src/actions/evaluations/connect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use server'

import { findAllEvaluationTemplates } from '@latitude-data/core/data-access'
import {
DocumentVersionsRepository,
EvaluationsRepository,
} from '@latitude-data/core/repositories'
import { connectEvaluations } from '@latitude-data/core/services/evaluations/connect'
import { z } from 'zod'

import { withProject } from '../procedures'

export const connectEvaluationsAction = withProject
.createServerAction()
.input(
z.object({
documentUuid: z.string(),
commitUuid: z.string(),
templateIds: z.array(z.number()),
evaluationUuids: z.array(z.string()),
}),
)
.handler(async ({ ctx, input }) => {
const evaluationTemplates = await findAllEvaluationTemplates().then((r) =>
r.unwrap(),
)
const scope = new EvaluationsRepository(ctx.workspace.id)
const evaluations = await scope.findAll().then((r) => r.unwrap())

const selectedTemplates = evaluationTemplates.filter((template) =>
input.templateIds.includes(template.id),
)
const selectedEvaluations = evaluations.filter((evaluation) =>
input.evaluationUuids.includes(evaluation.uuid),
)

const documentsScope = new DocumentVersionsRepository(ctx.workspace.id)
const document = await documentsScope
.getDocumentAtCommit({
projectId: ctx.project.id,
commitUuid: input.commitUuid,
documentUuid: input.documentUuid,
})
.then((r) => r.unwrap())

const connectedEvaluations = await connectEvaluations({
document,
templates: selectedTemplates,
evaluations: selectedEvaluations,
}).then((r) => r.unwrap())

return connectedEvaluations
})
15 changes: 11 additions & 4 deletions apps/web/src/actions/evaluations/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
'use server'

import { EvaluationsRepository } from '@latitude-data/core/repositories'
import { z } from 'zod'

import { authProcedure } from '../procedures'

export const fetchEvaluationsAction = authProcedure
.createServerAction()
.handler(async ({ ctx }) => {
const evaluationsScope = new EvaluationsRepository(ctx.workspace.id)
const evaluations = await evaluationsScope.findAll().then((r) => r.unwrap())
.input(() => z.object({ documentUuid: z.string().optional() }).optional())
.handler(async ({ ctx, input }) => {
const scope = new EvaluationsRepository(ctx.workspace.id)
let result
if (input?.documentUuid) {
result = await scope.findByDocumentUuid(input.documentUuid)
} else {
result = await scope.findAll()
}

return evaluations
return result.unwrap()
})
30 changes: 23 additions & 7 deletions apps/web/src/app/(private)/_data-access/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { cache } from 'react'

import { type Commit, type Project } from '@latitude-data/core/browser'
import { type Commit } from '@latitude-data/core/browser'
import { findAllEvaluationTemplates } from '@latitude-data/core/data-access'
import { NotFoundError } from '@latitude-data/core/lib/errors'
import {
Expand Down Expand Up @@ -51,9 +51,10 @@ export const findProjectCached = cache(
)

export const findCommitCached = cache(
async ({ uuid, project }: { uuid: string; project: Project }) => {
const commitsScope = new CommitsRepository(project.workspaceId)
const result = await commitsScope.getCommitByUuid({ project, uuid })
async ({ uuid, projectId }: { uuid: string; projectId: number }) => {
const { workspace } = await getCurrentUser()
const commitsScope = new CommitsRepository(workspace.id)
const result = await commitsScope.getCommitByUuid({ projectId, uuid })
const commit = result.unwrap()

return commit
Expand All @@ -62,15 +63,21 @@ export const findCommitCached = cache(

export const getDocumentByUuidCached = cache(
async ({
projectId,
documentUuid,
commit,
commitUuid,
}: {
projectId: number
documentUuid: string
commit: Commit
commitUuid: string
}) => {
const { workspace } = await getCurrentUser()
const scope = new DocumentVersionsRepository(workspace.id)
const result = await scope.getDocumentAtCommit({ documentUuid, commit })
const result = await scope.getDocumentAtCommit({
documentUuid,
commitUuid,
projectId,
})
if (result.error) {
const error = result.error
if (error instanceof NotFoundError) {
Expand Down Expand Up @@ -170,3 +177,12 @@ export const getProviderLogCached = cache(async (uuid: string) => {
const scope = new ProviderLogsRepository(workspace.id)
return await scope.findByUuid(uuid).then((r) => r.unwrap())
})

export const getEvaluationsByDocumentUuidCached = cache(
async (documentUuid: string) => {
const { workspace } = await getCurrentUser()
const scope = new EvaluationsRepository(workspace.id)
const result = await scope.findByDocumentUuid(documentUuid)
return result.unwrap()
},
)
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use client'

import { Evaluation } from '@latitude-data/core/browser'
import {
Icon,
Expand Down
9 changes: 3 additions & 6 deletions apps/web/src/app/(private)/projects/[projectId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { HEAD_COMMIT, type Project } from '@latitude-data/core/browser'
import { type Project } from '@latitude-data/core/browser'
import { NotFoundError } from '@latitude-data/core/lib/errors'
import {
findCommitCached,
findProjectCached,
} from '$/app/(private)/_data-access'
import { findProjectCached } from '$/app/(private)/_data-access'
import { getCurrentUser, SessionData } from '$/services/auth/getCurrentUser'
import { ROUTES } from '$/services/routes'
import { notFound, redirect } from 'next/navigation'
Expand All @@ -25,7 +22,7 @@ export default async function ProjectPage({ params }: ProjectPageParams) {
projectId: Number(params.projectId),
workspaceId: session.workspace.id,
})
await findCommitCached({ uuid: HEAD_COMMIT, project })

url = PROJECT_ROUTE({ id: +project.id }).commits.latest
} catch (error) {
if (error instanceof NotFoundError) {
Expand Down
Loading

0 comments on commit fed831a

Please sign in to comment.