Skip to content

Commit

Permalink
feat: improve typescript sdk and publish it
Browse files Browse the repository at this point in the history
  • Loading branch information
geclos committed Sep 24, 2024
1 parent 0ca8f76 commit ddfcf19
Show file tree
Hide file tree
Showing 34 changed files with 1,352 additions and 634 deletions.
8 changes: 8 additions & 0 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Changesets

Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)

We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
11 changes: 11 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/[email protected]/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
5 changes: 5 additions & 0 deletions .changeset/rare-cougars-yell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@latitude-data/sdk-js': patch
---

First release! Introduces `run` and `chat` commands in order interact with Latitude's Gateway
2 changes: 2 additions & 0 deletions apps/gateway/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@
"drizzle-orm": "^0.33.0",
"hono": "^4.5.3",
"jet-paths": "^1.0.6",
"lodash-es": "^4.17.21",
"zod": "^3.23.8"
},
"devDependencies": {
"@latitude-data/eslint-config": "workspace:^",
"@latitude-data/typescript-config": "workspace:^",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.5.1",
"@types/uuid": "^10.0.0",
"tsup": "^8.2.4",
Expand Down
2 changes: 1 addition & 1 deletion apps/gateway/src/common/parseSSEEvent.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export function parseSSEEvent(data?: string) {
export function parseSSEvent(data?: string) {
if (!data) return

const event = data
Expand Down
16 changes: 8 additions & 8 deletions apps/gateway/src/routes/api/v1/chats/handlers/addMessage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { database } from '@latitude-data/core/client'
import { createProject } from '@latitude-data/core/factories'
import { Result } from '@latitude-data/core/lib/Result'
import { apiKeys } from '@latitude-data/core/schema'
import { parseSSEEvent } from '$/common/parseSSEEvent'
import { parseSSEvent } from '$/common/parseSSEEvent'
import app from '$/routes/app'
import { eq } from 'drizzle-orm'
import { testConsumeStream } from 'test/helpers'
Expand Down Expand Up @@ -77,7 +77,7 @@ describe('POST /add-message', () => {
const res = await app.request('/api/v1/chats/add-message', {
method: 'POST',
body: JSON.stringify({
documentPath: '/path/to/document',
path: '/path/to/document',
}),
})

Expand All @@ -101,8 +101,7 @@ describe('POST /add-message', () => {
route = '/api/v1/chats/add-message'
body = JSON.stringify({
messages: [],
source: LogSources.Playground,
documentLogUuid: 'fake-document-log-uuid',
uuid: 'fake-document-log-uuid',
})
headers = {
Authorization: `Bearer ${token}`,
Expand All @@ -118,13 +117,14 @@ describe('POST /add-message', () => {
})

let { done, value } = await testConsumeStream(res.body as ReadableStream)
value = parseSSEEvent(value!)!.data
const event = parseSSEvent(value!)

expect(mocks.queues)
expect(res.status).toBe(200)
expect(res.body).toBeInstanceOf(ReadableStream)
expect(done).toBe(true)
expect(value).toEqual({
expect(event).toEqual({
id: 0,
event: StreamEventTypes.Latitude,
data: {
type: ChainEventTypes.Complete,
Expand All @@ -136,14 +136,14 @@ describe('POST /add-message', () => {
})
})

it('calls addMessages provider', async () => {
it('calls chat provider', async () => {
await app.request(route, { method: 'POST', body, headers })

expect(mocks.addMessages).toHaveBeenCalledWith({
workspace,
documentLogUuid: 'fake-document-log-uuid',
messages: [],
source: LogSources.Playground,
source: LogSources.API,
})
})
})
Expand Down
24 changes: 17 additions & 7 deletions apps/gateway/src/routes/api/v1/chats/handlers/addMessage.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { zValidator } from '@hono/zod-validator'
import { LogSources } from '@latitude-data/core/browser'
import { streamToGenerator } from '@latitude-data/core/lib/streamToGenerator'
import { addMessages } from '@latitude-data/core/services/documentLogs/index'
import { captureException } from '@sentry/node'
import { messageSchema } from '$/common/messageSchema'
import { pipeToStream } from '$/common/pipeToStream'
import { Factory } from 'hono/factory'
import { streamSSE } from 'hono/streaming'
import { z } from 'zod'

import { chainEventPresenter } from '../../projects/:projectId/commits/:commitUuid/documents/handlers/_shared'

const factory = new Factory()

const schema = z.object({
messages: z.array(messageSchema),
documentLogUuid: z.string(),
source: z.nativeEnum(LogSources).optional().default(LogSources.API),
uuid: z.string(),
})

export const addMessageHandler = factory.createHandlers(
Expand All @@ -22,17 +23,26 @@ export const addMessageHandler = factory.createHandlers(
return streamSSE(
c,
async (stream) => {
const { documentLogUuid, messages, source } = c.req.valid('json')
const { uuid, messages } = c.req.valid('json')
const workspace = c.get('workspace')

const result = await addMessages({
workspace,
documentLogUuid,
documentLogUuid: uuid,
messages,
source,
source: LogSources.API,
}).then((r) => r.unwrap())

await pipeToStream(stream, result.stream)
let id = 0
for await (const event of streamToGenerator(result.stream)) {
const data = chainEventPresenter(event)

stream.writeSSE({
id: String(id++),
event: event.event,
data: typeof data === 'string' ? data : JSON.stringify(data),
})
}
},
(error: Error) => {
captureException(error)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import type { Workspace } from '@latitude-data/core/browser'
import { omit } from 'lodash-es'

import { Message } from '@latitude-data/compiler'
import {
ChainEventDto,
ChainEventTypes,
LatitudeEventData,
StreamEventTypes,
type ChainEvent,
type Workspace,
} from '@latitude-data/core/browser'
import { BadRequestError } from '@latitude-data/core/lib/errors'
import { Result } from '@latitude-data/core/lib/Result'
import {
CommitsRepository,
DocumentVersionsRepository,
ProjectsRepository,
} from '@latitude-data/core/repositories'
import { Config } from '@latitude-data/core/services/ai/helpers'

export const getData = async ({
workspace,
Expand All @@ -19,16 +32,65 @@ export const getData = async ({
const projectsScope = new ProjectsRepository(workspace.id)
const commitsScope = new CommitsRepository(workspace.id)
const docsScope = new DocumentVersionsRepository(workspace.id)
const project = await projectsScope
.getProjectById(projectId)
.then((r) => r.unwrap())
const commit = await commitsScope
.getCommitByUuid({ projectId: project.id, uuid: commitUuid })
.then((r) => r.unwrap())

const document = await docsScope
.getDocumentByPath({ commit, path: documentPath })
.then((r) => r.unwrap())

return { project, commit, document }

const projectResult = await projectsScope.getProjectById(projectId)
if (projectResult.error) return projectResult
const project = projectResult.value

const commitResult = await commitsScope.getCommitByUuid({
projectId: project.id,
uuid: commitUuid,
})
if (commitResult.error) return commitResult
const commit = commitResult.value

const documentResult = await docsScope.getDocumentByPath({
commit,
path: documentPath,
})
if (documentResult.error) return documentResult
const document = documentResult.value

return Result.ok({ project, commit, document })
}

export function chainEventPresenter(event: ChainEvent) {
switch (event.event) {
case StreamEventTypes.Provider:
return event.data
case StreamEventTypes.Latitude:
return latitudeEventPresenter(event)
}
}

function latitudeEventPresenter(event: {
data: LatitudeEventData
event: StreamEventTypes.Latitude
}): ChainEventDto | string {
switch (event.data.type) {
case ChainEventTypes.Step:
case ChainEventTypes.StepComplete:
return {
...omit(event.data, 'documentLogUuid'),
uuid: event.data.documentLogUuid!,
} as {
type: ChainEventTypes.Step
config: Config
isLastStep: boolean
messages: Message[]
uuid?: string
}
case ChainEventTypes.Complete:
return {
...omit(event.data, 'documentLogUuid'),
uuid: event.data.response.documentLogUuid!,
response: omit(event.data.response, 'providerLog', 'documentLogUuid'),
}
case ChainEventTypes.Error:
return event.data
default:
throw new BadRequestError(
`Unknown event type in chainEventPresenter ${JSON.stringify(event)}`,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const getHandler = factory.createHandlers(async (c) => {
projectId: Number(projectId!),
commitUuid: commitUuid!,
documentPath: documentPath!,
})
}).then((r) => r.unwrap())

return c.json(document)
})
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import { Result } from '@latitude-data/core/lib/Result'
import { apiKeys } from '@latitude-data/core/schema'
import { mergeCommit } from '@latitude-data/core/services/commits/merge'
import { parseSSEEvent } from '$/common/parseSSEEvent'
import { parseSSEvent } from '$/common/parseSSEEvent'
import app from '$/routes/app'
import { eq } from 'drizzle-orm'
import { testConsumeStream } from 'test/helpers'
Expand Down Expand Up @@ -104,7 +104,7 @@ describe('POST /run', () => {

route = `/api/v1/projects/${project!.id}/commits/${commit!.uuid}/documents/run`
body = JSON.stringify({
documentPath: document.documentVersion.path,
path: document.documentVersion.path,
parameters: {},
})
headers = {
Expand Down Expand Up @@ -153,12 +153,13 @@ describe('POST /run', () => {
})

let { done, value } = await testConsumeStream(res.body as ReadableStream)
value = parseSSEEvent(value)!.data
const event = parseSSEvent(value)
expect(mocks.queues)
expect(res.status).toBe(200)
expect(res.body).toBeInstanceOf(ReadableStream)
expect(done).toBe(true)
expect(value).toEqual({
expect(event).toEqual({
id: 0,
event: StreamEventTypes.Latitude,
data: {
type: ChainEventTypes.Complete,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import { zValidator } from '@hono/zod-validator'
import { LogSources } from '@latitude-data/core/browser'
import { streamToGenerator } from '@latitude-data/core/lib/streamToGenerator'
import { runDocumentAtCommit } from '@latitude-data/core/services/commits/runDocumentAtCommit'
import { pipeToStream } from '$/common/pipeToStream'
import { captureException } from '$/common/sentry'
import { Factory } from 'hono/factory'
import { streamSSE } from 'hono/streaming'
import { z } from 'zod'

import { getData } from './_shared'
import { chainEventPresenter, getData } from './_shared'

const factory = new Factory()

const runSchema = z.object({
documentPath: z.string(),
path: z.string(),
parameters: z.record(z.any()).optional().default({}),
source: z.nativeEnum(LogSources).optional().default(LogSources.API),
})

export const runHandler = factory.createHandlers(
Expand All @@ -24,23 +23,32 @@ export const runHandler = factory.createHandlers(
c,
async (stream) => {
const { projectId, commitUuid } = c.req.param()
const { documentPath, parameters, source } = c.req.valid('json')
const { path, parameters } = c.req.valid('json')
const workspace = c.get('workspace')
const { document, commit } = await getData({
workspace,
projectId: Number(projectId!),
commitUuid: commitUuid!,
documentPath: documentPath!,
})
documentPath: path!,
}).then((r) => r.unwrap())
const result = await runDocumentAtCommit({
workspace,
document,
commit,
parameters,
source,
source: LogSources.API,
}).then((r) => r.unwrap())

await pipeToStream(stream, result.stream)
let id = 0
for await (const event of streamToGenerator(result.stream)) {
const data = chainEventPresenter(event)

stream.writeSSE({
id: String(id++),
event: event.event,
data: typeof data === 'string' ? data : JSON.stringify(data),
})
}
},
(error: Error) => {
captureException(error)
Expand Down
10 changes: 10 additions & 0 deletions apps/gateway/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { serve } from '@hono/node-server'
import env from '$/common/env'
import app from '$/routes/app'

import { captureException, captureMessage } from './common/sentry'

serve(
{
fetch: app.fetch,
Expand All @@ -21,3 +23,11 @@ function gracefulShutdown() {

process.on('SIGTERM', gracefulShutdown)
process.on('SIGINT', gracefulShutdown)

process.on('uncaughtException', function (err) {
captureException(err)
})

process.on('unhandledRejection', (reason: string) => {
captureMessage(reason)
})
Loading

0 comments on commit ddfcf19

Please sign in to comment.