ConusAI vendor v0.1.0-dev.20261027+9b1131fb
ci / gate (push) Waiting to run

This commit is contained in:
ConusAI vendor v0.1.0-dev.20261027+9b1131fb
2026-10-27 18:05:17 +00:00
commit 3102273ec7
538 changed files with 80203 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
// The constants of the knowledge module: its feature flag, jobs, events, audit actions and the
// indexable content types.
/** The module flag: knowledge retrieval and indexing, off until an administrator enables it. */
export const KNOWLEDGE_FLAG = "knowledge.enabled"
export const KNOWLEDGE_FLAG_DEFAULTS = {
[KNOWLEDGE_FLAG]: false,
} as const
/** The worker job that indexes one document's chunks into the vector store. */
export const INDEX_JOB = "knowledge.index"
/** The worker job that removes one document's chunks from the vector store. */
export const REMOVE_JOB = "knowledge.remove"
export const COLLECTION_CREATED = "knowledge.collection.created"
export const DOCUMENT_INDEX_REQUESTED = "knowledge.document.index_requested"
export const DOCUMENT_REMOVE_REQUESTED = "knowledge.document.remove_requested"
export const DOCUMENT_AI_ENABLED = "knowledge.settings.document_ai_enabled"
export const DOCUMENT_AI_DISABLED = "knowledge.settings.document_ai_disabled"
/**
* What the indexer reads as text. PDFs and scans are the documents module's worked example; this
* module indexes text-shaped files, and refuses anything else at the door with a named field.
*/
export const INDEXABLE_CONTENT_TYPES = ["text/plain", "text/markdown", "application/json", "text/csv"] as const
/** A search query's ceiling; a retrieval question is a sentence, not a document. */
export const MAX_QUERY_LENGTH = 500
/** What one search returns at most, however much the caller asks (the retrieval limit contract). */
export const MAX_SEARCH_RESULTS = 25
/** An indexed file's ceiling: one megabyte of text is already far past useful chunking. */
export const MAX_INDEX_BYTES = 1_048_576
+68
View File
@@ -0,0 +1,68 @@
// The tables of the knowledge module. Three.
//
// `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", which backend serves it and where the managed vector
// service was linked. No secret ever lands here: the Qdrant API key lives in the deployment
// environment, not in a tenant row.
import { defineEntity, idSchema, instantSchema } from "@conusai-kit/data"
import { z } from "zod"
import { DOCUMENT_STATUSES } 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: the local vector store or the managed service. */
backend: z.enum(["vectors", "platform"]),
/** Where the vector backing came from: an operator-configured endpoint or a managed link. */
source: z.enum(["operator", "managed"]),
/** The linked managed service's id, when source is managed. */
serviceId: z.string().max(128).nullable(),
/** The operator- or link-configured endpoint, when there is one to show. Never a key. */
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,
},
})
/** Every table this module owns, in the order a migration creates them. */
export const KNOWLEDGE_ENTITIES = Object.freeze([collections, documents, config])
+36
View File
@@ -0,0 +1,36 @@
// The events of the knowledge module. A write procedure publishes the request; the module's own
// subscriber (running in the worker's outbox relay) enqueues the job, which is how a web request
// never waits on chunking, embeddings or a vector store.
import { defineEvent } from "@conusai-kit/core"
import { z } from "zod"
const inProject = {
orgId: z.string(),
workspaceId: z.string(),
projectId: z.string(),
}
/** A document was asked to be indexed: the subscriber enqueues the index job. */
export const documentIndexRequested = defineEvent(
"knowledge.documentIndexRequested",
z.object({
...inProject,
documentId: z.string(),
collectionName: z.string(),
fileId: z.string(),
}),
)
/** A document was asked to be removed: the subscriber enqueues the remove job. */
export const documentRemoveRequested = defineEvent(
"knowledge.documentRemoveRequested",
z.object({
...inProject,
documentId: z.string(),
collectionName: z.string(),
fileId: z.string(),
}),
)
export const KNOWLEDGE_EVENTS = [documentIndexRequested, documentRemoveRequested]
+45
View File
@@ -0,0 +1,45 @@
// The public API of the knowledge module: what a page, another module and the OpenAPI document may
// import. Nothing here reaches core/, adapters/ or a driver.
export {
COLLECTION_CREATED,
DOCUMENT_AI_DISABLED,
DOCUMENT_AI_ENABLED,
DOCUMENT_INDEX_REQUESTED,
DOCUMENT_REMOVE_REQUESTED,
INDEX_JOB,
INDEXABLE_CONTENT_TYPES,
KNOWLEDGE_FLAG,
KNOWLEDGE_FLAG_DEFAULTS,
MAX_INDEX_BYTES,
MAX_QUERY_LENGTH,
MAX_SEARCH_RESULTS,
REMOVE_JOB,
} from "./constants.js"
export { collections, config, documents, KNOWLEDGE_ENTITIES } from "./entities.js"
export { documentIndexRequested, documentRemoveRequested, KNOWLEDGE_EVENTS } from "./events.js"
export type { CollectionView, DocumentView, SearchResult } from "./procedures.js"
export {
collectionCreate,
collectionList,
collectionName,
collectionViewSchema,
documentIndex,
documentList,
documentRemove,
documentViewSchema,
KNOWLEDGE_PROCEDURES,
knowledgeSearch,
knowledgeStatus,
searchResultSchema,
settingsDisableDocumentAi,
settingsEnableDocumentAi,
settingsGet,
} from "./procedures.js"
export type { DocumentStatus, EnablementReason, IndexFailure, KnowledgeBackend, ServiceState } from "./statuses.js"
export {
ENABLEMENT_REASONS,
INDEX_FAILURES,
KNOWLEDGE_BACKENDS,
SERVICE_STATES,
} from "./statuses.js"
+187
View File
@@ -0,0 +1,187 @@
// The procedure contracts of the knowledge module: schemas and names, no handler and no port.
//
// The module is a retrieval layer over the app's documents: a collection of text files is indexed
// (in the worker: chunk, embed through the AI gateway, upsert into the vector store), searched
// with cited snippets, and managed through an explicit, idempotent enablement flow. The enablement
// procedure is named enableDocumentAi per the Document AI enablement contract; its permission is the module's
// manage permission, so the admin gate is one line in the manifest.
import { procedure } from "@conusai-kit/core"
import { z } from "zod"
import { COLLECTION_CREATED, DOCUMENT_AI_DISABLED, DOCUMENT_AI_ENABLED } from "./constants.js"
import type { DocumentStatus, ServiceState } from "./statuses.js"
const inProject = { org: z.string(), workspace: z.string(), project: z.string() }
const inOrg = { org: z.string() }
export const collectionName = z
.string()
.min(1)
.max(100)
.regex(/^[a-z][a-z0-9-]*$/, "lower-case letters, digits and dashes")
export const collectionViewSchema = z.object({
name: collectionName,
documentCount: z.number().int(),
indexedCount: z.number().int(),
createdBy: z.string(),
})
export type CollectionView = z.output<typeof collectionViewSchema>
export const documentViewSchema = z.object({
documentId: z.string(),
collectionName: collectionName,
fileId: z.string(),
filename: z.string(),
status: z.enum(["queued", "indexing", "indexed", "failed", "cancelled"]),
error: z.string().nullable(),
indexedAt: z.string().nullable(),
requestedBy: z.string(),
})
export type DocumentView = z.output<typeof documentViewSchema>
export const searchResultSchema = z.object({
fileId: z.string(),
filename: z.string(),
collectionName: collectionName,
snippet: z.string(),
/** 0..1; higher is closer. */
score: z.number(),
/** 1-based chunk position in the document: where a citation points. */
chunk: z.number().int().min(1),
})
export type SearchResult = z.output<typeof searchResultSchema>
export const collectionList = procedure("knowledge.collection.list")
.kind("read")
.scope("project")
.permission("knowledge.knowledge.search")
.input(z.object({ ...inProject }))
.output(z.object({ collections: z.array(collectionViewSchema) }))
.contract()
export const collectionCreate = procedure("knowledge.collection.create")
.kind("write")
.scope("project")
.permission("knowledge.collection.manage")
.input(z.object({ ...inProject, name: collectionName }))
.output(collectionViewSchema)
.audit(COLLECTION_CREATED)
.contract()
export const documentIndex = procedure("knowledge.document.index")
.kind("write")
.scope("project")
.permission("knowledge.knowledge.manage")
.input(z.object({ ...inProject, collectionName: collectionName, fileId: z.string() }))
.output(documentViewSchema)
.contract()
export const documentList = procedure("knowledge.document.list")
.kind("read")
.scope("project")
.permission("knowledge.knowledge.search")
.input(z.object({ ...inProject, collectionName: collectionName }))
.output(z.object({ documents: z.array(documentViewSchema) }))
.contract()
export const documentRemove = procedure("knowledge.document.remove")
.kind("write")
.scope("project")
.permission("knowledge.knowledge.manage")
.input(z.object({ ...inProject, collectionName: collectionName, fileId: z.string() }))
.output(documentViewSchema)
.contract()
/**
* The retrieval call. It embeds the query through the AI gateway before it searches, so it is an
* effect: a read procedure cannot leave the process. Exposed as an MCP tool on purpose (`.tool()`).
*/
export const knowledgeSearch = procedure("knowledge.search")
.kind("effect")
.scope("project")
.permission("knowledge.knowledge.search")
.tool()
.input(
z.object({
...inProject,
collectionName: collectionName,
query: z.string().min(1).max(500),
limit: z.number().int().min(1).max(25).optional(),
}),
)
.output(z.object({ results: z.array(searchResultSchema) }))
.contract()
export const knowledgeStatus = procedure("knowledge.status")
.kind("read")
.scope("project")
.permission("knowledge.knowledge.search")
.input(z.object({ ...inProject }))
.output(
z.object({
/** The module flag's answer for this project. */
enabled: z.boolean(),
/** The service readiness, kept separate from the indexing indicator below. */
service: z.object({
state: z.enum(["registered", "indexing", "ready", "degraded", "disabled", "unavailable"]),
reasons: z.array(z.string()),
}),
documents: z.object({
queued: z.number().int(),
indexing: z.number().int(),
indexed: z.number().int(),
failed: z.number().int(),
cancelled: z.number().int(),
}),
}),
)
.contract()
export const settingsGet = procedure("knowledge.settings.get")
.kind("read")
.scope("org")
.permission("knowledge.settings.manage")
.input(z.object({ ...inOrg }))
.output(
z.object({
enabled: z.boolean(),
backend: z.enum(["vectors", "platform"]).nullable(),
source: z.enum(["operator", "managed"]).nullable(),
url: z.string().nullable(),
}),
)
.contract()
export const settingsEnableDocumentAi = procedure("knowledge.settings.enableDocumentAi")
.kind("write")
.scope("org")
.permission("knowledge.settings.manage")
.input(z.object({ ...inOrg }))
.output(z.object({ enabled: z.boolean(), backend: z.enum(["vectors", "platform"]) }))
.audit(DOCUMENT_AI_ENABLED)
.contract()
export const settingsDisableDocumentAi = procedure("knowledge.settings.disableDocumentAi")
.kind("write")
.scope("org")
.permission("knowledge.settings.manage")
.input(z.object({ ...inOrg }))
.output(z.object({ enabled: z.boolean() }))
.audit(DOCUMENT_AI_DISABLED)
.contract()
export const KNOWLEDGE_PROCEDURES = [
collectionList,
collectionCreate,
documentIndex,
documentList,
documentRemove,
knowledgeSearch,
knowledgeStatus,
settingsGet,
settingsEnableDocumentAi,
settingsDisableDocumentAi,
]
export type { DocumentStatus, ServiceState }
+22
View File
@@ -0,0 +1,22 @@
// The statuses a knowledge document moves through. `unavailable` and `disabled` are not rows: they
// are the module's and the service's answers, and the UI maps all eight states from what a page
// reads (the module flag, the service readiness, the document row).
export const DOCUMENT_STATUSES = ["queued", "indexing", "indexed", "failed", "cancelled"] as const
export type DocumentStatus = (typeof DOCUMENT_STATUSES)[number]
/** The search backend a deployment binds: the local vector adapters, or the managed service. */
export const KNOWLEDGE_BACKENDS = ["vectors", "platform"] as const
export type KnowledgeBackend = (typeof KNOWLEDGE_BACKENDS)[number]
/** The readiness states the search port answers (the managed toolset's readiness + unavailable). */
export const SERVICE_STATES = ["registered", "indexing", "ready", "degraded", "disabled", "unavailable"] as const
export type ServiceState = (typeof SERVICE_STATES)[number]
/** The enablement flow's typed refusal reasons, surfaced in the UI as states. */
export const ENABLEMENT_REASONS = ["plan_required", "feature_disabled", "quota_exhausted"] as const
export type EnablementReason = (typeof ENABLEMENT_REASONS)[number]
/** The indexing failure codes a document row records. */
export const INDEX_FAILURES = ["not_indexable", "too_large", "not_text", "vector_store_unavailable"] as const
export type IndexFailure = (typeof INDEX_FAILURES)[number]