Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions apps/web/hooks/use-document-mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,8 @@ export function useDocumentMutations({
const data = (await response.json()) as { id: string }

if (applyMeta && (title || description)) {
await $fetch(`@patch/documents/${data.id}`, {
await $fetch("@patch/documents/:id", {
params: { id: data.id },
body: {
metadata: {
...(title && { title }),
Expand Down Expand Up @@ -642,7 +643,8 @@ export function useDocumentMutations({
documentId: string
content: string
}) => {
const response = await $fetch(`@patch/documents/${documentId}`, {
const response = await $fetch("@patch/documents/:id", {
params: { id: documentId },
body: {
content,
metadata: { sm_source: "consumer" },
Expand Down
14 changes: 14 additions & 0 deletions packages/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@ import {
CreateProjectSchema,
DeleteProjectResponseSchema,
DeleteProjectSchema,
DocumentFacetsQuerySchema,
DocumentFacetsResponseSchema,
DocumentsWithMemoriesQuerySchema,
DocumentsWithMemoriesResponseSchema,
ListContainerTagsResponseSchema,
ListMemoriesResponseSchema,
ListProjectsResponseSchema,
MemoryAddSchema,
MemoryResponseSchema,
MemoryUpdateSchema,
MigrateMCPRequestSchema,
MigrateMCPResponseSchema,
ProcessingDocumentsResponseSchema,
Expand Down Expand Up @@ -265,6 +268,10 @@ export const apiSchema = createSchema({
input: DocumentsWithMemoriesQuerySchema,
output: DocumentsWithMemoriesResponseSchema,
},
"@post/documents/documents/facets": {
input: DocumentFacetsQuerySchema,
output: DocumentFacetsResponseSchema,
},
"@post/documents/documents/by-ids": {
input: z.object({
ids: z.array(z.string()),
Expand All @@ -291,6 +298,13 @@ export const apiSchema = createSchema({
output: z.any(),
},

// Update a memory
"@patch/documents/:id": {
input: MemoryUpdateSchema,
output: MemoryResponseSchema,
params: z.object({ id: z.string() }),
},

// Delete a memory
"@delete/documents/:id": {
output: z.any(), // 204 No-Content
Expand Down
35 changes: 34 additions & 1 deletion packages/validation/api.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { describe, expect, it } from "bun:test"
import { readFileSync } from "node:fs"
import { SearchRequestSchema, Searchv4RequestSchema } from "./api"
import {
DocumentFacetsResponseSchema,
DocumentsWithMemoriesQuerySchema,
SearchRequestSchema,
Searchv4RequestSchema,
} from "./api"

describe("search threshold schemas", () => {
it("do not contain redundant number transforms or unreachable range guards", () => {
Expand Down Expand Up @@ -80,3 +85,31 @@ describe("search threshold schemas", () => {
).toBe(false)
})
})

describe("documents contract schemas", () => {
it("DocumentsWithMemoriesQuerySchema accepts the categories filter", () => {
const parsed = DocumentsWithMemoriesQuerySchema.parse({
categories: ["webpage", "tweet"],
})
expect(parsed.categories).toEqual(["webpage", "tweet"])
})

it("DocumentsWithMemoriesQuerySchema leaves categories undefined when omitted", () => {
expect(
DocumentsWithMemoriesQuerySchema.parse({}).categories,
).toBeUndefined()
})

it("DocumentFacetsResponseSchema parses a facets payload", () => {
const parsed = DocumentFacetsResponseSchema.parse({
facets: [{ category: "webpage", count: 42, label: "Web pages" }],
total: 42,
})
expect(parsed.facets[0]?.category).toBe("webpage")
})

it("DocumentFacetsResponseSchema tolerates a missing total", () => {
const parsed = DocumentFacetsResponseSchema.parse({ facets: [] })
expect(parsed.total).toBeUndefined()
})
})
34 changes: 34 additions & 0 deletions packages/validation/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,13 @@ export const DocumentsWithMemoriesQuerySchema = z
description: "Number of items per page",
example: 10,
}),
categories: z
.array(z.string())
.optional()
.openapi({
description: "Optional document categories to filter by",
example: ["webpage", "tweet"],
}),
sort: z.enum(["createdAt", "updatedAt"]).default("createdAt").openapi({
description: "Field to sort by",
example: "createdAt",
Expand Down Expand Up @@ -1134,6 +1141,33 @@ export const DocumentFacetsQuerySchema = z
description: "Query parameters for getting document facets",
})

export const DocumentFacetSchema = z
.object({
category: z.string().openapi({
description: "Document category identifier",
example: "webpage",
}),
count: z.number().openapi({
description: "Number of documents in this category",
example: 42,
}),
label: z.string().openapi({
description: "Human-readable category label",
example: "Web pages",
}),
})
.openapi({ description: "A single document-category facet" })

export const DocumentFacetsResponseSchema = z
.object({
facets: z.array(DocumentFacetSchema),
total: z.number().optional().openapi({
description: "Total number of documents across all categories",
example: 120,
}),
})
.openapi({ description: "Document category facets" })

export const MigrateMCPRequestSchema = z
.object({
userId: z.string().openapi({
Expand Down
Loading