// The handlers of the knowledge module's procedures: each resolves its ports from the request's // container and calls one use case. No rule lives here. import type { Container } from "@conusai-kit/core" import { implement } from "@conusai-kit/core" import { DATA_SOURCE } from "@conusai-kit/data" import { filesDeps } from "@conusai-kit/files" import { autoIndexGet, autoIndexSet, collectionCreate, collectionList, documentGetMany, documentIndex, documentList, documentRemove, knowledgeSearch, knowledgeStatus, settingsDisableDocumentAi, settingsEnableDocumentAi, settingsGet, } from "../contract/index.js" import { getAutoIndex, setAutoIndex } from "../core/auto-index.js" import { createCollection, listCollections } from "../core/collections.js" import { getManyDocuments, listDocuments, requestIndex, requestRemove } from "../core/documents.js" import { flagsOf, KNOWLEDGE_ENABLEMENT, KNOWLEDGE_PASSAGES, KNOWLEDGE_READER, KNOWLEDGE_READINESS, KNOWLEDGE_SEARCH, type KnowledgeDeps, } from "../core/ports.js" import { searchKnowledge } from "../core/search.js" import { disableDocumentAi, enableDocumentAi, getSettings, type SettingsDeps } from "../core/settings.js" import { type KnowledgeStatusDeps, knowledgeStatusOf } from "../core/status.js" import { knowledgeRefusal } from "./refusals.js" /** The ports a write or read handler needs. Never the search service: that port is an effect, and * resolving it from either is a kind violation. */ export function knowledgeDeps(container: Container): KnowledgeDeps { const data = container.resolve(DATA_SOURCE) return { data, files: filesDeps(container), flags: flagsOf(container, data) } } /** * The effect handler's deps: the search service, bound in the processes that may leave the process, and the * PDF intake's reader, passage index and enablement checks where the worker binds the reader (the jobs; a * request never reads a PDF). */ export function knowledgeSearchDeps(container: Container): KnowledgeDeps { return { ...knowledgeDeps(container), search: container.resolve(KNOWLEDGE_SEARCH), ...(container.has(KNOWLEDGE_READER) ? { reader: container.resolve(KNOWLEDGE_READER) } : {}), ...(container.has(KNOWLEDGE_PASSAGES) ? { passages: container.resolve(KNOWLEDGE_PASSAGES) } : {}), ...(container.has(KNOWLEDGE_READER) ? { enablement: container.resolve(KNOWLEDGE_ENABLEMENT) } : {}), } } /** The status read's deps: the backend's readiness, which a read may resolve, instead of the search service. */ function knowledgeStatusDeps(container: Container): KnowledgeStatusDeps { const data = container.resolve(DATA_SOURCE) return { data, flags: flagsOf(container, data), ...(container.has(KNOWLEDGE_READINESS) ? { readiness: container.resolve(KNOWLEDGE_READINESS) } : {}), } } /** The enablement flow's deps, for the effect that leaves the process. The other settings procedures read and write the module's own row. */ function settingsDeps(container: Container): SettingsDeps { return { data: container.resolve(DATA_SOURCE), platform: container.resolve(KNOWLEDGE_ENABLEMENT) } } const settingsDataOf = (container: Container) => ({ data: container.resolve(DATA_SOURCE) }) export const collectionListImpl = implement(collectionList, ({ ctx }) => listCollections(knowledgeDeps(ctx.container), ctx.scope), ) export const collectionCreateImpl = implement(collectionCreate, ({ input, ctx }) => createCollection(knowledgeDeps(ctx.container), ctx.scope, input.name), ) export const documentIndexImpl = implement(documentIndex, ({ input, ctx }) => requestIndex(knowledgeDeps(ctx.container), ctx.scope, input), ) export const documentListImpl = implement(documentList, ({ input, ctx }) => listDocuments(knowledgeDeps(ctx.container), ctx.scope, input.collectionName), ) export const documentGetManyImpl = implement(documentGetMany, async ({ input, ctx }) => ({ items: await getManyDocuments(knowledgeDeps(ctx.container), ctx.scope, input.ids), })) export const documentRemoveImpl = implement(documentRemove, ({ input, ctx }) => requestRemove(knowledgeDeps(ctx.container), ctx.scope, input), ) export const knowledgeSearchImpl = implement(knowledgeSearch, async ({ input, ctx }) => { try { return await searchKnowledge(knowledgeSearchDeps(ctx.container), ctx.scope, { collectionName: input.collectionName, query: input.query, ...(input.limit === undefined ? {} : { limit: input.limit }), }) } catch (error) { throw knowledgeRefusal(error) } }) export const knowledgeStatusImpl = implement(knowledgeStatus, ({ ctx }) => knowledgeStatusOf(knowledgeStatusDeps(ctx.container), ctx.scope), ) export const settingsGetImpl = implement(settingsGet, ({ ctx }) => getSettings(settingsDataOf(ctx.container), ctx.scope), ) export const settingsEnableDocumentAiImpl = implement(settingsEnableDocumentAi, async ({ ctx }) => { const settings = await enableDocumentAi(settingsDeps(ctx.container), ctx.scope) return { enabled: settings.enabled, backend: settings.backend ?? "platform" } }) export const settingsDisableDocumentAiImpl = implement(settingsDisableDocumentAi, ({ ctx }) => disableDocumentAi(settingsDataOf(ctx.container), ctx.scope), ) export const autoIndexGetImpl = implement(autoIndexGet, ({ ctx }) => getAutoIndex(settingsDataOf(ctx.container), ctx.scope), ) export const autoIndexSetImpl = implement(autoIndexSet, ({ input, ctx }) => setAutoIndex(knowledgeDeps(ctx.container), ctx.scope, input.collectionName), ) export const KNOWLEDGE_PROCEDURE_IMPLS = [ collectionListImpl, collectionCreateImpl, documentIndexImpl, documentListImpl, documentGetManyImpl, documentRemoveImpl, knowledgeSearchImpl, knowledgeStatusImpl, settingsGetImpl, settingsEnableDocumentAiImpl, settingsDisableDocumentAiImpl, autoIndexGetImpl, autoIndexSetImpl, ]