@@ -0,0 +1,105 @@
|
||||
// The tables of the knowledge module. Five.
|
||||
//
|
||||
// `knowledge_collection` is one named collection of documents, project-owned; the collection name
|
||||
// is the slug procedures take (a procedure's input carries slugs, never ids). `knowledge_document`
|
||||
// is one file's indexing state in one collection — the row the UI's progress states read, and the
|
||||
// idempotency key of the index job (a file is indexed into a collection once, and re-indexing the
|
||||
// same pair resumes the one row). `knowledge_config` is the organization's enablement state: the
|
||||
// durable answer to "is document AI on" and which backend serves it. `knowledge_auto_index` is a
|
||||
// project's opt-in to indexing its uploaded PDFs, and `knowledge_passage_set` what one such PDF sent
|
||||
// to the service, so removing it can tombstone each passage. No secret ever lands here.
|
||||
|
||||
import { defineEntity, idSchema, instantSchema } from "@conusai-kit/data"
|
||||
import { z } from "zod"
|
||||
import { DOCUMENT_STATUSES, KNOWLEDGE_BACKENDS } from "./statuses.js"
|
||||
|
||||
export const collections = defineEntity({
|
||||
name: "collection",
|
||||
table: "knowledge_collection",
|
||||
tenancy: "project",
|
||||
fields: {
|
||||
name: z.string().min(1).max(100),
|
||||
createdBy: z.string().min(1).max(128),
|
||||
},
|
||||
unique: [["name"]],
|
||||
})
|
||||
|
||||
export const documents = defineEntity({
|
||||
name: "document",
|
||||
table: "knowledge_document",
|
||||
tenancy: "project",
|
||||
fields: {
|
||||
collectionName: z.string().min(1).max(100),
|
||||
/** The row of the files module this document indexes: an opaque id, never a foreign key. */
|
||||
fileId: idSchema,
|
||||
filename: z.string().min(1).max(255),
|
||||
status: z.enum(DOCUMENT_STATUSES),
|
||||
/** A stable failure code when the indexing failed; null otherwise. */
|
||||
error: z.string().max(200).nullable(),
|
||||
indexedAt: z.string().nullable(),
|
||||
requestedBy: z.string().min(1).max(128),
|
||||
},
|
||||
// One row per (collection, file): a re-index resumes the same row instead of duplicating it.
|
||||
unique: [["collectionName", "fileId"]],
|
||||
indexes: [["collectionName"]],
|
||||
})
|
||||
|
||||
export const config = defineEntity({
|
||||
name: "config",
|
||||
table: "knowledge_config",
|
||||
tenancy: "org",
|
||||
fields: {
|
||||
enabled: z.boolean(),
|
||||
/** Which search backend serves this organization. */
|
||||
backend: z.enum(KNOWLEDGE_BACKENDS),
|
||||
// The three below held the app's own vector store, which is gone (ADR-061); the migration that made
|
||||
// them has run, so they stay as "managed, nothing to link" and nothing reads them.
|
||||
source: z.enum(["managed"]),
|
||||
serviceId: z.string().max(128).nullable(),
|
||||
url: z.string().max(500).nullable(),
|
||||
updatedBy: z.string().min(1).max(128),
|
||||
/** When the configuration last changed; the managed updated_at is the row's own bookkeeping. */
|
||||
configuredAt: instantSchema,
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* A project's opt-in to indexing its uploaded PDFs automatically (core-11): no row means off. It names
|
||||
* the collection the files go into and the administrator who turned it on, whose permission every
|
||||
* indexing job checks again, since the job runs for nobody else.
|
||||
*/
|
||||
export const autoIndex = defineEntity({
|
||||
name: "autoindex",
|
||||
table: "knowledge_auto_index",
|
||||
tenancy: "project",
|
||||
fields: {
|
||||
collectionName: z.string().min(1).max(100),
|
||||
enabledBy: z.string().min(1).max(128),
|
||||
enabledAt: instantSchema,
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* The passages an automatic PDF index sent for one document (core-11). The service indexed one inline
|
||||
* item per passage under the file's reference plus `#p{page}.{index}`, and removes a reference only
|
||||
* exactly, so the row keeps the file's reference (which outlives the file) and the count of passages
|
||||
* on each page, comma-separated from page 1 ("2,0,1": two on page 1, none on page 2, one on page 3).
|
||||
*/
|
||||
export const passageSets = defineEntity({
|
||||
name: "passageset",
|
||||
table: "knowledge_passage_set",
|
||||
tenancy: "project",
|
||||
fields: {
|
||||
collectionName: z.string().min(1).max(100),
|
||||
fileId: idSchema,
|
||||
documentRef: z.string().min(1).max(1024),
|
||||
pages: z.string().max(65_536),
|
||||
},
|
||||
unique: [["collectionName", "fileId"]],
|
||||
})
|
||||
|
||||
/** The tables of the first migration, as first shipped. */
|
||||
export const KNOWLEDGE_ENTITIES_V1 = Object.freeze([collections, documents, config])
|
||||
|
||||
/** Every table this module owns, in the order its migrations create them. */
|
||||
export const KNOWLEDGE_ENTITIES = Object.freeze([...KNOWLEDGE_ENTITIES_V1, autoIndex, passageSets])
|
||||
Reference in New Issue
Block a user