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
+118
View File
@@ -0,0 +1,118 @@
// The ports the knowledge module's use cases are written against, and the tokens the composition
// roots bind. Core imports no SDK and no adapter (spec §2): the search service and the enablement
// platform are shapes, and adapters/ is the only place an SDK exists.
import { type Container, type TenantScope, token } from "@conusai-kit/core"
import type { DataSource } from "@conusai-kit/data"
import type { FilesDeps } from "@conusai-kit/files"
import type { EnablementReason, ServiceState } from "../contract/index.js"
import { KNOWLEDGE_FLAG_DEFAULTS } from "../contract/index.js"
/** A project scope: collections and documents live at this level. */
export type KnowledgeScope = TenantScope & { workspaceId: string; projectId: string }
/** An org scope: the enablement configuration is the organization's own. */
export type KnowledgeOrgScope = TenantScope & { orgId: string }
export interface KnowledgeDeps {
readonly data: DataSource
readonly files: FilesDeps
readonly flags: KnowledgeFlags
/**
* The search service. Present for the effect procedure (search) and the status read; a write
* procedure's deps never carry it, because resolving an effect port from a write is a kind
* violation — the write only records the row and publishes the event.
*/
readonly search?: KnowledgeSearchService | undefined
}
/** What a chunk knows about where it came from: the citation a search result carries. */
export interface KnowledgeChunk {
/** 1-based position of the chunk in the document. */
position: number
text: string
}
/** One cited search answer. */
export interface KnowledgeHit {
fileId: string
filename: string
collectionName: string
/** 0..1; higher is closer. */
score: number
chunk: number
snippet: string
}
/**
* The search service: index a document's chunks, search a collection with citations, remove a
* document, and report readiness. Two adapters ship with the module: the local vector store
* (embeddings through the AI gateway, chunks in the bound vector adapter) and the platform's
* managed documents-index service. Embedding leaves the process, so this port is an effect.
*/
export interface KnowledgeSearchService {
readiness(scope: KnowledgeScope): Promise<{ state: ServiceState; reasons: string[] }>
index(
scope: KnowledgeScope,
input: { collectionName: string; fileId: string; filename: string; bytes: Uint8Array },
): Promise<void>
search(
scope: KnowledgeScope,
input: { collectionName: string; query: string; limit: number; actorId: string },
): Promise<readonly KnowledgeHit[]>
remove(scope: KnowledgeScope, input: { collectionName: string; fileId: string }): Promise<void>
}
/**
* The enablement platform: the checks and the provisioning the enablement flow needs, over the
* platform's own APIs. `checkEligibility` is where the plan capability and the rollout flags
* surface as typed reasons; `indexingQuota` answers today's remaining indexing volume;
* `linkManagedQdrant` provisions (or returns the existing) managed Qdrant backing service;
* `probeQdrant` validates an operator-configured endpoint before its configuration is persisted.
*/
export interface DocumentAiPlatform {
checkEligibility(
scope: KnowledgeOrgScope,
): Promise<{ ok: true } | { ok: false; reason: EnablementReason; detail?: string }>
indexingQuota(scope: KnowledgeOrgScope): Promise<number>
linkManagedQdrant(scope: KnowledgeOrgScope): Promise<{ serviceId: string; url: string | null }>
probeQdrant(url: string, apiKey: string): Promise<{ ok: true } | { ok: false; detail: string }>
/** The operator-configured endpoint+key the deployment carries, when it carries one. */
operatorQdrant(): { url: string; apiKey: string } | null
}
/** What a flag service answers for the project a call runs in. */
export interface KnowledgeFlags {
enabled(flag: keyof typeof KNOWLEDGE_FLAG_DEFAULTS, scope: KnowledgeScope): boolean | Promise<boolean>
}
/** Bound by an app that evaluates flags (the platform's flag service). Unbound: the manifest default. */
export const KNOWLEDGE_FLAGS = token<KnowledgeFlags>("knowledge.flags")
export const defaultFlags: KnowledgeFlags = { enabled: (flag) => KNOWLEDGE_FLAG_DEFAULTS[flag] }
export const flagsOf = (container: Container): KnowledgeFlags =>
container.has(KNOWLEDGE_FLAGS) ? container.resolve(KNOWLEDGE_FLAGS) : defaultFlags
/** Bound by the worker and the web shell with the module's search backend adapter. */
export const KNOWLEDGE_SEARCH = token<KnowledgeSearchService>("knowledge.search", { access: "effect" })
/**
* The embeddings the local vector backend chunks and queries with: the platform's embeddings
* endpoint through the AI gateway. Declared here (not reached through another module's token) so
* the module's boundary stays its own; the composition root binds it to the gateway client.
*/
export interface KnowledgeEmbeddings {
embed(texts: readonly string[], options?: { inputType?: "passage" | "query" }): Promise<readonly number[][]>
}
export const KNOWLEDGE_EMBEDDINGS = token<KnowledgeEmbeddings>("knowledge.embeddings", { access: "effect" })
/** Bound by the web shell (the enablement flow runs in a request). */
export const KNOWLEDGE_ENABLEMENT = token<DocumentAiPlatform>("knowledge.enablement", { access: "effect" })
/** The per-run scope, under the module's own name (decision AT-F6). */
export const KNOWLEDGE_SCOPE = token<TenantScope>("knowledge.scope")
export const knowledgeEnabled = async (deps: KnowledgeDeps, scope: KnowledgeScope): Promise<boolean> =>
deps.flags.enabled("knowledge.enabled", scope)