Files
dify/knowledge-fs/apps/admin/lib/api-client.ts
Jyong 4ee43b8afc chore: migrate knowledge-fs source tree
Import the committed KnowledgeFS snapshot dc4072ee302317145612087ce7440851dc329fd0 under knowledge-fs/ without its Git history, local IDE settings, or build artifacts.
2026-07-20 04:54:20 -04:00

4057 lines
122 KiB
TypeScript

export interface AdminApiClientOptions {
readonly baseUrl: string;
readonly fetch?: typeof fetch;
readonly maxAssetBytes?: number;
readonly maxListLimit?: number;
readonly maxGraphDepth?: number;
readonly maxGraphFanout?: number;
readonly maxGraphNodes?: number;
readonly maxGraphTimeoutMs?: number;
readonly maxJsonBytes?: number;
readonly maxQueryBytes?: number;
readonly maxSseBytes?: number;
readonly maxUploadBytes?: number;
}
export interface AdminHealthStatus {
readonly components: Readonly<Record<string, boolean>>;
readonly ok: boolean;
readonly runtime: "cloudflare-workers" | "node-docker";
}
export interface AdminKnowledgeSpace {
readonly createdAt: string;
readonly description?: string | undefined;
readonly id: string;
readonly name: string;
readonly slug: string;
readonly tenantId: string;
readonly updatedAt: string;
}
export interface AdminKnowledgeSpaceList {
readonly items: readonly AdminKnowledgeSpace[];
readonly nextCursor?: string | undefined;
}
export interface AdminKnowledgeSpaceManifest {
readonly consistencyPolicy: Readonly<Record<string, unknown>>;
readonly manifestVersion: number;
readonly objectKeyPrefix: string;
readonly parserPolicyVersion: string;
readonly projectionSetVersion: string;
readonly quotaPolicy: Readonly<Record<string, unknown>>;
readonly storageProvider: string;
}
export interface AdminKnowledgeSpaceStatus {
readonly index?: Readonly<Record<string, unknown>> | undefined;
readonly manifest?: Readonly<Record<string, unknown>> | undefined;
readonly parser?: Readonly<Record<string, unknown>> | undefined;
readonly runtime?: Readonly<Record<string, unknown>> | undefined;
readonly storage?: Readonly<Record<string, unknown>> | undefined;
}
export interface GetKnowledgeSpaceControlPlaneInput {
readonly knowledgeSpaceId: string;
readonly token: string;
}
export interface ListKnowledgeSpaceDiagnosticsInput extends GetKnowledgeSpaceControlPlaneInput {
readonly cursor?: string | undefined;
readonly limit: number;
}
export interface AdminKnowledgeSpaceStagedCommit {
readonly errorCode?: string | undefined;
readonly errorMessage?: string | undefined;
readonly expiresAt?: string | undefined;
readonly id: string;
readonly idempotencyKey: string;
readonly operationType: string;
readonly status: string;
readonly updatedAt: string;
}
export interface AdminKnowledgeSpaceStagedCommitList {
readonly items: readonly AdminKnowledgeSpaceStagedCommit[];
readonly nextCursor?: string | undefined;
}
export interface AdminKnowledgeFsLease {
readonly expiresAt: string;
readonly heartbeatAt: string;
readonly id: string;
readonly leaseType: string;
readonly status: string;
readonly targetId: string;
readonly targetType: string;
readonly virtualPath: string;
}
export interface AdminKnowledgeFsLeaseList {
readonly items: readonly AdminKnowledgeFsLease[];
readonly nextCursor?: string | undefined;
}
export type AdminKnowledgeFsckCheck = "artifact-segments" | "raw-objects" | "references";
export interface GetKnowledgeFsckInput extends GetKnowledgeSpaceControlPlaneInput {
readonly check: AdminKnowledgeFsckCheck;
readonly cursor?: string | undefined;
}
export interface AdminKnowledgeFsckIssue {
readonly code: string;
readonly message: string;
readonly repairability: string;
readonly severity: string;
readonly target: Readonly<Record<string, unknown>>;
readonly type: string;
}
export interface AdminKnowledgeFsckReport {
readonly cursor?: string | undefined;
readonly issues: readonly AdminKnowledgeFsckIssue[];
readonly knowledgeSpaceId: string;
readonly scannedAt: string;
readonly summary: Readonly<Record<string, number>>;
readonly tenantId: string;
}
export interface AdminKnowledgeFsGcCandidate {
readonly candidateType: string;
readonly count: number;
readonly estimatedBytes: number;
readonly idempotencyKey: string;
readonly reason: string;
readonly target: Readonly<Record<string, unknown>>;
}
export interface AdminKnowledgeFsGcDryRunReport {
readonly candidates: readonly AdminKnowledgeFsGcCandidate[];
readonly cursor?: string | undefined;
readonly dryRunId: string;
readonly generatedAt: string;
readonly knowledgeSpaceId: string;
readonly summary: Readonly<Record<string, number>>;
readonly tenantId: string;
}
export interface GetKnowledgeFsStagedObjectGcInput extends GetKnowledgeSpaceControlPlaneInput {
readonly cursor?: string | undefined;
}
export interface ExecuteKnowledgeFsStagedObjectGcInput extends GetKnowledgeSpaceControlPlaneInput {
readonly candidates: readonly AdminKnowledgeFsGcCandidate[];
readonly dryRunId: string;
readonly idempotencyKey: string;
}
export interface AdminKnowledgeFsStagedObjectGcExecuteResult {
readonly deleted: number;
readonly items: readonly {
readonly idempotencyKey: string;
readonly objectKey: string;
readonly status: string;
}[];
readonly skipped: number;
readonly tenantId: string;
}
export interface MaterializeSemanticTopicViewInput extends GetKnowledgeSpaceControlPlaneInput {
readonly generatedVersion?: string | undefined;
readonly limit?: number | undefined;
readonly topicName?: string | undefined;
readonly topicSlug?: string | undefined;
}
export interface AdminSemanticTopicMaterializationResult {
readonly documentCount: number;
readonly generatedVersion: string;
readonly knowledgeSpaceId: string;
readonly pathCount: number;
readonly topicName: string;
readonly topicSlug: string;
}
export interface MaterializeSemanticCommunitiesInput extends GetKnowledgeSpaceControlPlaneInput {
readonly generatedVersion?: string | undefined;
}
export interface AdminSemanticCommunityMaterializationResult {
readonly communityCount: number;
readonly documentCount: number;
readonly entityCount: number;
readonly generatedVersion: string;
readonly knowledgeSpaceId: string;
readonly pathCount: number;
}
export interface ExtractSemanticEntitiesInput extends GetKnowledgeSpaceControlPlaneInput {
readonly limit?: number | undefined;
}
export interface AdminSemanticEntityExtractionResult {
readonly entitiesExtracted: number;
readonly extractionMode: "provider";
readonly graphEntitiesIndexed: number;
readonly graphRelationsIndexed: number;
readonly knowledgeSpaceId: string;
readonly nodesScanned: number;
readonly nodesUpdated: number;
}
export interface AdminGoldenQuestion {
readonly createdAt: string;
readonly expectedEvidenceIds: readonly string[];
readonly id: string;
readonly knowledgeSpaceId: string;
readonly metadata: Readonly<Record<string, unknown>>;
readonly question: string;
readonly tags: readonly string[];
readonly updatedAt: string;
}
export interface AdminGoldenQuestionList {
readonly items: readonly AdminGoldenQuestion[];
readonly nextCursor?: string | undefined;
}
export interface ListKnowledgeSpacesInput {
readonly cursor?: string | undefined;
readonly limit: number;
readonly token: string;
}
export interface ListGoldenQuestionsInput {
readonly cursor?: string | undefined;
readonly knowledgeSpaceId: string;
readonly limit: number;
readonly token: string;
}
export interface CreateGoldenQuestionInput {
readonly expectedEvidenceIds?: readonly string[] | undefined;
readonly knowledgeSpaceId: string;
readonly metadata?: Readonly<Record<string, unknown>> | undefined;
readonly question: string;
readonly tags?: readonly string[] | undefined;
readonly token: string;
}
export interface CaptureProductionBadCaseInput {
readonly knowledgeSpaceId: string;
readonly reason?: string | undefined;
readonly tags?: readonly string[] | undefined;
readonly token: string;
readonly traceId: string;
}
export type AdminAnswerCorrectness =
| "correct"
| "incorrect"
| "not-answerable"
| "partially-correct";
export interface AdminEvidenceRelevanceInput {
readonly evidenceId: string;
readonly note?: string | undefined;
readonly relevant: boolean;
}
export interface GetGoldenQuestionInput {
readonly knowledgeSpaceId: string;
readonly questionId: string;
readonly token: string;
}
export interface AnnotateGoldenQuestionInput extends GetGoldenQuestionInput {
readonly answerCorrectness: AdminAnswerCorrectness;
readonly evidenceRelevance: readonly AdminEvidenceRelevanceInput[];
readonly note?: string | undefined;
}
export interface UpdateGoldenQuestionInput extends GetGoldenQuestionInput {
readonly expectedEvidenceIds?: readonly string[] | undefined;
readonly metadata?: Readonly<Record<string, unknown>> | undefined;
readonly question?: string | undefined;
readonly tags?: readonly string[] | undefined;
}
export type DeleteGoldenQuestionInput = GetGoldenQuestionInput;
export interface StreamQueryInput {
readonly knowledgeSpaceId: string;
readonly mode?: "deep" | "fast" | "research" | undefined;
readonly query: string;
readonly token: string;
}
export interface UploadDocumentInput {
readonly file: File;
readonly knowledgeSpaceId: string;
readonly sourceId?: string | undefined;
readonly token: string;
}
export interface GetDocumentInput {
readonly documentId: string;
readonly knowledgeSpaceId: string;
readonly token: string;
}
export interface GetDocumentMultimodalAssetInput extends GetDocumentInput {
readonly itemId: string;
readonly variant?: string | undefined;
}
export interface ListDocumentsInput {
readonly cursor?: string | undefined;
readonly knowledgeSpaceId: string;
readonly limit: number;
readonly token: string;
}
export interface GetParseArtifactInput extends GetDocumentInput {
readonly version: number;
}
export interface TraverseGraphInput {
readonly depth?: number | undefined;
readonly entityId: string;
readonly fanout?: number | undefined;
readonly knowledgeSpaceId: string;
readonly maxNodes?: number | undefined;
readonly timeoutMs?: number | undefined;
readonly token: string;
}
export interface ListKnowledgeFsInput {
readonly cursor?: string | undefined;
readonly knowledgeSpaceId: string;
readonly limit: number;
readonly path: string;
readonly token: string;
}
export interface ReadKnowledgeFsInput extends Omit<ListKnowledgeFsInput, "limit"> {
readonly limit?: number | undefined;
}
export interface TreeKnowledgeFsInput extends ListKnowledgeFsInput {
readonly depth?: number | undefined;
}
export interface GrepKnowledgeFsInput extends ListKnowledgeFsInput {
readonly q: string;
readonly timeoutMs?: number | undefined;
}
export interface FindKnowledgeFsInput extends ListKnowledgeFsInput {
readonly metadataKey?: string | undefined;
readonly metadataValue?: string | undefined;
readonly nameContains?: string | undefined;
readonly resourceType?: AdminKnowledgeFsEntry["resourceType"] | undefined;
}
export interface OpenKnowledgeFsNodeInput extends GetKnowledgeSpaceControlPlaneInput {
readonly nodeId: string;
}
export type AdminSemanticView = "by-community" | "by-entity" | "by-topic";
export interface ListSemanticViewInput {
readonly cursor?: string | undefined;
readonly key?: string | undefined;
readonly knowledgeSpaceId: string;
readonly limit: number;
readonly token: string;
readonly view: AdminSemanticView;
}
export type AdminKnowledgeFsDiffMode = "line" | "word";
export interface DiffKnowledgeFsInput {
readonly knowledgeSpaceId: string;
readonly mode?: AdminKnowledgeFsDiffMode | undefined;
readonly newPath: string;
readonly oldPath: string;
readonly semantic?: boolean | undefined;
readonly token: string;
}
export interface WriteKnowledgeFsInput extends GetKnowledgeSpaceControlPlaneInput {
readonly path: string;
readonly text: string;
}
export interface AdminDocumentAsset {
readonly createdAt: string;
readonly filename: string;
readonly id: string;
readonly knowledgeSpaceId: string;
readonly metadata: Readonly<Record<string, unknown>>;
readonly mimeType: string;
readonly objectKey: string;
readonly parserStatus: "failed" | "parsed" | "pending";
readonly sha256: string;
readonly sizeBytes: number;
readonly sourceId?: string | undefined;
readonly version: number;
}
export interface AdminDocumentAssetList {
readonly items: readonly AdminDocumentAsset[];
readonly nextCursor?: string | undefined;
}
export interface AdminDocumentOutlineTitleLocation {
readonly confidence: number;
readonly endOffset?: number | undefined;
readonly matchedText?: string | undefined;
readonly pageNumber?: number | undefined;
readonly source: "fallback" | "llm-inferred" | "native-toc" | "parser-heading";
readonly startOffset?: number | undefined;
}
export interface AdminDocumentOutlineNode {
readonly childNodeIds: readonly string[];
readonly children: readonly AdminDocumentOutlineNode[];
readonly endOffset?: number | undefined;
readonly endPage?: number | undefined;
readonly id: string;
readonly level: number;
readonly metadata: Readonly<Record<string, unknown>>;
readonly sectionPath: readonly string[];
readonly sourceElementIds: readonly string[];
readonly sourceNodeIds: readonly string[];
readonly startOffset?: number | undefined;
readonly startPage?: number | undefined;
readonly summary?: string | undefined;
readonly title: string;
readonly titleLocation?: AdminDocumentOutlineTitleLocation | undefined;
readonly tocSource: "fallback" | "llm-inferred" | "native-toc" | "parser-heading";
}
export interface AdminDocumentOutline {
readonly artifactHash: string;
readonly createdAt: string;
readonly documentAssetId: string;
readonly id: string;
readonly knowledgeSpaceId: string;
readonly metadata: Readonly<Record<string, unknown>>;
readonly nodes: readonly AdminDocumentOutlineNode[];
readonly outlineVersion: string;
readonly parseArtifactId: string;
readonly updatedAt?: string | undefined;
readonly version: number;
}
export interface AdminDocumentMultimodalItem {
readonly assetRef?: AdminDocumentMultimodalAssetRef | undefined;
readonly boundingBox?: AdminDocumentMultimodalBoundingBox | undefined;
readonly caption?: string | undefined;
readonly endOffset?: number | undefined;
readonly enrichment: Readonly<Record<string, string>>;
readonly id: string;
readonly modality: "code" | "image" | "page" | "table";
readonly ocrText?: string | undefined;
readonly pageNumber?: number | undefined;
readonly parseElementId: string;
readonly sectionPath: readonly string[];
readonly sourceMetadata: Readonly<Record<string, unknown>>;
readonly startOffset?: number | undefined;
readonly textPreview?: string | undefined;
readonly title?: string | undefined;
}
export interface AdminDocumentMultimodalBoundingBox {
readonly height: number;
readonly width: number;
readonly x: number;
readonly y: number;
}
export interface AdminDocumentMultimodalAssetRef {
readonly contentType?: string | undefined;
readonly objectKey?: string | undefined;
readonly sha256?: string | undefined;
readonly uri?: string | undefined;
readonly variants?: Readonly<Record<string, AdminDocumentMultimodalAssetVariant>> | undefined;
}
export interface AdminDocumentMultimodalAssetVariant {
readonly contentType?: string | undefined;
readonly height?: number | undefined;
readonly objectKey?: string | undefined;
readonly sha256?: string | undefined;
readonly uri?: string | undefined;
readonly width?: number | undefined;
}
export interface AdminDocumentMultimodalManifest {
readonly artifactHash: string;
readonly createdAt: string;
readonly documentAssetId: string;
readonly id: string;
readonly items: readonly AdminDocumentMultimodalItem[];
readonly knowledgeSpaceId: string;
readonly manifestVersion: string;
readonly metadata: Readonly<Record<string, unknown>>;
readonly parseArtifactId: string;
readonly updatedAt?: string | undefined;
readonly version: number;
}
export interface AdminDocumentMultimodalAsset {
readonly bytes: ArrayBuffer;
readonly contentType: string;
readonly itemId?: string | undefined;
}
export interface AdminParseElement {
readonly id: string;
readonly metadata: Readonly<Record<string, unknown>>;
readonly pageNumber?: number | undefined;
readonly sectionPath: readonly string[];
readonly text?: string | undefined;
readonly type:
| "code"
| "heading"
| "image"
| "list"
| "page-break"
| "paragraph"
| "table"
| "title";
}
export interface AdminParseArtifact {
readonly artifactHash: string;
readonly contentType: "mixed" | "structured" | "text";
readonly createdAt: string;
readonly documentAssetId: string;
readonly elements: readonly AdminParseElement[];
readonly id: string;
readonly metadata: Readonly<Record<string, unknown>>;
readonly parser: "native-html" | "native-markdown" | "native-structured" | "unstructured";
readonly version: number;
}
export type AdminGraphEntityType =
| "date"
| "metric"
| "organization"
| "person"
| "policy"
| "product"
| "term";
export type AdminGraphRelationType =
| "contradicts"
| "defines"
| "depends_on"
| "mentions"
| "references"
| "supersedes";
export interface AdminGraphEntity {
readonly aliases: readonly string[];
readonly canonicalKey: string;
readonly confidence: number;
readonly createdAt: string;
readonly depth: number;
readonly extractionVersion: number;
readonly id: string;
readonly knowledgeSpaceId: string;
readonly metadata: Readonly<Record<string, unknown>>;
readonly name: string;
readonly permissionScope: readonly string[];
readonly sourceNodeIds: readonly string[];
readonly type: AdminGraphEntityType;
readonly updatedAt: string;
}
export interface AdminGraphRelation {
readonly confidence: number;
readonly createdAt: string;
readonly depth: number;
readonly extractionVersion: number;
readonly id: string;
readonly knowledgeSpaceId: string;
readonly metadata: Readonly<Record<string, unknown>>;
readonly objectEntityId: string;
readonly permissionScope: readonly string[];
readonly sourceNodeIds: readonly string[];
readonly subjectEntityId: string;
readonly type: AdminGraphRelationType;
readonly updatedAt: string;
}
export interface AdminGraphTraversal {
readonly entities: readonly AdminGraphEntity[];
readonly metrics: {
readonly depthReached: number;
readonly elapsedMs: number;
readonly exploredRelations: number;
readonly fanout: number;
readonly maxDepth: number;
readonly maxNodes: number;
readonly timedOut: boolean;
};
readonly relations: readonly AdminGraphRelation[];
readonly truncated: boolean;
}
export interface AdminKnowledgeFsEntry {
readonly kind: "directory" | "resource";
readonly metadata: Readonly<Record<string, unknown>>;
readonly name: string;
readonly path: string;
readonly resourceType?:
| "answer-trace"
| "document"
| "evidence-bundle"
| "node"
| "knowledge-node"
| "artifact"
| "parse-artifact"
| "source"
| "workspace"
| undefined;
readonly targetId?: string | undefined;
readonly version?: number | undefined;
}
export interface AdminKnowledgeFsList {
readonly items: readonly AdminKnowledgeFsEntry[];
readonly nextCursor?: string | undefined;
readonly path: string;
readonly truncated: boolean;
}
export interface AdminKnowledgeFsTreeNode extends AdminKnowledgeFsEntry {
readonly children?: readonly AdminKnowledgeFsTreeNode[] | undefined;
}
export interface AdminKnowledgeFsTree {
readonly nextCursor?: string | undefined;
readonly path: string;
readonly root: AdminKnowledgeFsTreeNode;
readonly truncated: boolean;
}
export interface AdminKnowledgeFsCat {
readonly contentType: string;
readonly nextCursor?: string | undefined;
readonly path: string;
readonly text: string;
readonly truncated: boolean;
}
export interface AdminKnowledgeFsStat {
readonly contentType?: string | undefined;
readonly metadata: Readonly<Record<string, unknown>>;
readonly parserStatus?: AdminDocumentAsset["parserStatus"] | undefined;
readonly path: string;
readonly resourceType: NonNullable<AdminKnowledgeFsEntry["resourceType"]>;
readonly sha256?: string | undefined;
readonly sizeBytes?: number | undefined;
readonly targetId: string;
readonly version?: number | undefined;
}
export interface AdminKnowledgeFsGrepMatch {
readonly endOffset: number;
readonly kind: "node" | "segment";
readonly metadata: Readonly<Record<string, unknown>>;
readonly nodeId?: string | undefined;
readonly path: string;
readonly segmentId?: string | undefined;
readonly snippet: string;
readonly startOffset: number;
}
export interface AdminKnowledgeFsGrep {
readonly matches: readonly AdminKnowledgeFsGrepMatch[];
readonly nextCursor?: string | undefined;
readonly path: string;
readonly truncated: boolean;
}
export interface AdminKnowledgeFsOpenNode {
readonly citation: {
readonly artifactHash: string;
readonly documentAssetId: string;
readonly endOffset: number;
readonly pageNumber?: number | undefined;
readonly parseArtifactId: string;
readonly sectionPath: readonly string[];
readonly startOffset: number;
};
readonly node: {
readonly id: string;
readonly kind: string;
readonly metadata: Readonly<Record<string, unknown>>;
readonly text: string;
};
}
export interface AdminTextDiffOperation {
readonly kind: "delete" | "equal" | "insert";
readonly newEnd?: number | undefined;
readonly newStart?: number | undefined;
readonly oldEnd?: number | undefined;
readonly oldStart?: number | undefined;
readonly text: string;
}
export interface AdminSemanticDiffSummary {
readonly changes: readonly {
readonly category: string;
readonly evidence: readonly string[];
readonly summary: string;
}[];
readonly metadata: Readonly<Record<string, unknown>>;
readonly model?: string | undefined;
readonly summary: string;
}
export interface AdminKnowledgeFsDiff {
readonly mode: AdminKnowledgeFsDiffMode;
readonly newPath: string;
readonly oldPath: string;
readonly operations: readonly AdminTextDiffOperation[];
readonly semantic?: AdminSemanticDiffSummary | undefined;
readonly stats: {
readonly delete: number;
readonly equal: number;
readonly insert: number;
};
}
export interface AdminKnowledgeFsWrite {
readonly bytesWritten: number;
readonly mode: "append" | "write";
readonly objectKey: string;
readonly path: string;
readonly targetId: string;
readonly version: number;
}
export interface AdminSseEvent {
readonly data: unknown;
readonly event: string;
}
export interface AdminAnswerTraceStep {
readonly endedAt?: string | undefined;
readonly metadata: Readonly<Record<string, unknown>>;
readonly name: string;
readonly startedAt: string;
readonly status: "error" | "ok" | "skipped";
}
export interface AdminAnswerTrace {
readonly createdAt: string;
readonly evidenceBundleId?: string | undefined;
readonly id: string;
readonly knowledgeSpaceId: string;
readonly mode: "auto" | "deep" | "fast" | "research";
readonly query: string;
readonly steps: readonly AdminAnswerTraceStep[];
}
export interface GetAnswerTraceInput {
readonly token: string;
readonly traceId: string;
}
export interface ListQueryVirtualEntriesInput extends GetAnswerTraceInput {
readonly cursor?: string | undefined;
readonly limit: number;
}
export interface AdminApiClient {
annotateGoldenQuestion(input: AnnotateGoldenQuestionInput): Promise<AdminGoldenQuestion>;
captureProductionBadCase(input: CaptureProductionBadCaseInput): Promise<AdminGoldenQuestion>;
createGoldenQuestion(input: CreateGoldenQuestionInput): Promise<AdminGoldenQuestion>;
deleteGoldenQuestion(input: DeleteGoldenQuestionInput): Promise<boolean>;
catKnowledgeFs(input: ReadKnowledgeFsInput): Promise<AdminKnowledgeFsCat>;
diffKnowledgeFs(input: DiffKnowledgeFsInput): Promise<AdminKnowledgeFsDiff>;
executeStagedObjectGc(
input: ExecuteKnowledgeFsStagedObjectGcInput,
): Promise<AdminKnowledgeFsStagedObjectGcExecuteResult>;
getAnswerTrace(input: GetAnswerTraceInput): Promise<AdminAnswerTrace>;
getDocument(input: GetDocumentInput): Promise<AdminDocumentAsset>;
getDocumentMultimodalAsset(
input: GetDocumentMultimodalAssetInput,
): Promise<AdminDocumentMultimodalAsset>;
getDocumentMultimodalManifest(input: GetDocumentInput): Promise<AdminDocumentMultimodalManifest>;
getDocumentOutline(input: GetDocumentInput): Promise<AdminDocumentOutline>;
getGoldenQuestion(input: GetGoldenQuestionInput): Promise<AdminGoldenQuestion>;
getKnowledgeSpaceManifest(
input: GetKnowledgeSpaceControlPlaneInput,
): Promise<AdminKnowledgeSpaceManifest>;
getKnowledgeSpaceStatus(
input: GetKnowledgeSpaceControlPlaneInput,
): Promise<AdminKnowledgeSpaceStatus>;
getKnowledgeFsck(input: GetKnowledgeFsckInput): Promise<AdminKnowledgeFsckReport>;
getStagedObjectGcDryRun(
input: GetKnowledgeFsStagedObjectGcInput,
): Promise<AdminKnowledgeFsGcDryRunReport>;
getParseArtifact(input: GetParseArtifactInput): Promise<AdminParseArtifact>;
health(): Promise<AdminHealthStatus>;
listActiveLeases(input: ListKnowledgeSpaceDiagnosticsInput): Promise<AdminKnowledgeFsLeaseList>;
listDocuments(input: ListDocumentsInput): Promise<AdminDocumentAssetList>;
findKnowledgeFs(input: FindKnowledgeFsInput): Promise<AdminKnowledgeFsList>;
grepKnowledgeFs(input: GrepKnowledgeFsInput): Promise<AdminKnowledgeFsGrep>;
listGoldenQuestions(input: ListGoldenQuestionsInput): Promise<AdminGoldenQuestionList>;
listKnowledgeFs(input: ListKnowledgeFsInput): Promise<AdminKnowledgeFsList>;
listKnowledgeSpaces(input: ListKnowledgeSpacesInput): Promise<AdminKnowledgeSpaceList>;
listStagedCommits(
input: ListKnowledgeSpaceDiagnosticsInput,
): Promise<AdminKnowledgeSpaceStagedCommitList>;
listQueryConflicts(input: ListQueryVirtualEntriesInput): Promise<AdminKnowledgeFsList>;
listQueryEvidence(input: ListQueryVirtualEntriesInput): Promise<AdminKnowledgeFsList>;
listQueryMissing(input: ListQueryVirtualEntriesInput): Promise<AdminKnowledgeFsList>;
listSemanticView(input: ListSemanticViewInput): Promise<AdminKnowledgeFsList>;
openKnowledgeFsNode(input: OpenKnowledgeFsNodeInput): Promise<AdminKnowledgeFsOpenNode>;
statKnowledgeFs(input: ReadKnowledgeFsInput): Promise<AdminKnowledgeFsStat>;
writeKnowledgeFs(input: WriteKnowledgeFsInput): Promise<AdminKnowledgeFsWrite>;
appendKnowledgeFs(input: WriteKnowledgeFsInput): Promise<AdminKnowledgeFsWrite>;
materializeSemanticTopicView(
input: MaterializeSemanticTopicViewInput,
): Promise<AdminSemanticTopicMaterializationResult>;
materializeSemanticCommunities(
input: MaterializeSemanticCommunitiesInput,
): Promise<AdminSemanticCommunityMaterializationResult>;
streamQuery(input: StreamQueryInput): Promise<AdminSseEvent[]>;
treeKnowledgeFs(input: TreeKnowledgeFsInput): Promise<AdminKnowledgeFsTree>;
traverseGraph(input: TraverseGraphInput): Promise<AdminGraphTraversal>;
updateGoldenQuestion(input: UpdateGoldenQuestionInput): Promise<AdminGoldenQuestion>;
uploadDocument(input: UploadDocumentInput): Promise<AdminDocumentAsset>;
extractSemanticEntities(
input: ExtractSemanticEntitiesInput,
): Promise<AdminSemanticEntityExtractionResult>;
}
const defaultMaxListLimit = 100;
const defaultMaxGraphDepth = 2;
const defaultMaxGraphFanout = 50;
const defaultMaxGraphNodes = 200;
const defaultMaxGraphTimeoutMs = 5_000;
const defaultMaxJsonBytes = 1024 * 1024;
const defaultMaxQueryBytes = 4_000;
const defaultMaxSseBytes = 1024 * 1024;
const defaultMaxUploadBytes = 10 * 1024 * 1024;
const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder();
const defaultLocalApiBaseUrl = "http://localhost:8788";
export function getAdminApiBase(): string {
return (
readNonEmptyEnv("KNOWLEDGE_API_BASE_URL") ??
readNonEmptyEnv("NEXT_PUBLIC_API_BASE_URL") ??
defaultLocalApiBaseUrl
);
}
export function getAdminPublicApiBase(): string {
return (
readNonEmptyEnv("NEXT_PUBLIC_API_BASE_URL") ??
readNonEmptyEnv("KNOWLEDGE_API_BASE_URL") ??
defaultLocalApiBaseUrl
);
}
function readNonEmptyEnv(name: string): string | undefined {
const value = process.env[name]?.trim();
return value ? value : undefined;
}
export function createAdminApiClient({
baseUrl,
fetch: fetchImpl = fetch,
maxAssetBytes = defaultMaxUploadBytes,
maxListLimit = defaultMaxListLimit,
maxGraphDepth = defaultMaxGraphDepth,
maxGraphFanout = defaultMaxGraphFanout,
maxGraphNodes = defaultMaxGraphNodes,
maxGraphTimeoutMs = defaultMaxGraphTimeoutMs,
maxJsonBytes = defaultMaxJsonBytes,
maxQueryBytes = defaultMaxQueryBytes,
maxSseBytes = defaultMaxSseBytes,
maxUploadBytes = defaultMaxUploadBytes,
}: AdminApiClientOptions): AdminApiClient {
const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
if (!Number.isInteger(maxListLimit) || maxListLimit < 1) {
throw new Error("Admin API maxListLimit must be at least 1");
}
if (!Number.isInteger(maxGraphDepth) || maxGraphDepth < 1) {
throw new Error("Admin API maxGraphDepth must be at least 1");
}
if (!Number.isInteger(maxGraphFanout) || maxGraphFanout < 1) {
throw new Error("Admin API maxGraphFanout must be at least 1");
}
if (!Number.isInteger(maxGraphNodes) || maxGraphNodes < 1) {
throw new Error("Admin API maxGraphNodes must be at least 1");
}
if (!Number.isInteger(maxGraphTimeoutMs) || maxGraphTimeoutMs < 1) {
throw new Error("Admin API maxGraphTimeoutMs must be at least 1");
}
if (!Number.isInteger(maxJsonBytes) || maxJsonBytes < 1) {
throw new Error("Admin API maxJsonBytes must be at least 1");
}
if (!Number.isInteger(maxAssetBytes) || maxAssetBytes < 1) {
throw new Error("Admin API maxAssetBytes must be at least 1");
}
if (!Number.isInteger(maxQueryBytes) || maxQueryBytes < 1) {
throw new Error("Admin API maxQueryBytes must be at least 1");
}
if (!Number.isInteger(maxSseBytes) || maxSseBytes < 1) {
throw new Error("Admin API maxSseBytes must be at least 1");
}
if (!Number.isInteger(maxUploadBytes) || maxUploadBytes < 1) {
throw new Error("Admin API maxUploadBytes must be at least 1");
}
const readJson = (response: Response) => readJsonResponse(response, maxJsonBytes);
return {
async annotateGoldenQuestion(input) {
validateGoldenQuestionAnnotation(input);
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/golden-questions/${encodePathSegment(input.questionId)}/annotations`,
normalizedBaseUrl,
),
{
body: JSON.stringify({
answerCorrectness: input.answerCorrectness,
evidenceRelevance: input.evidenceRelevance.map((item) => ({
evidenceId: item.evidenceId,
...(item.note ? { note: item.note } : {}),
relevant: item.relevant,
})),
...(input.note ? { note: input.note } : {}),
}),
headers: {
...authHeaders(input.token),
"content-type": "application/json",
},
method: "POST",
},
),
);
return parseGoldenQuestion(await readJson(response));
},
async captureProductionBadCase(input) {
validateProductionBadCaseCapture(input);
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/production-bad-cases`,
normalizedBaseUrl,
),
{
body: JSON.stringify({
...(input.reason ? { reason: input.reason } : {}),
tags: [...(input.tags ?? [])],
traceId: input.traceId,
}),
headers: {
...authHeaders(input.token),
"content-type": "application/json",
},
method: "POST",
},
),
);
return parseGoldenQuestion(await readJson(response));
},
async createGoldenQuestion(input) {
validateGoldenQuestionMutation(input);
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/golden-questions`,
normalizedBaseUrl,
),
{
body: JSON.stringify({
expectedEvidenceIds: [...(input.expectedEvidenceIds ?? [])],
metadata: input.metadata ? { ...input.metadata } : {},
question: input.question,
tags: [...(input.tags ?? [])],
}),
headers: {
...authHeaders(input.token),
"content-type": "application/json",
},
method: "POST",
},
),
);
return parseGoldenQuestion(await readJson(response));
},
async deleteGoldenQuestion(input) {
validateGoldenQuestionLookup(input);
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/golden-questions/${encodePathSegment(input.questionId)}`,
normalizedBaseUrl,
),
{
headers: authHeaders(input.token),
method: "DELETE",
},
),
);
if (!response.ok) {
throw new Error(`Admin API request failed with status ${response.status}`);
}
return response.status === 204;
},
async catKnowledgeFs(input) {
validateToken(input.token);
validateKnowledgeFsPathInput(input.path);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/fs/cat`,
normalizedBaseUrl,
);
url.searchParams.set("path", input.path);
if (input.limit !== undefined) {
url.searchParams.set("limit", String(input.limit));
}
if (input.cursor) {
url.searchParams.set("cursor", input.cursor);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseKnowledgeFsCat(await readJson(response));
},
async diffKnowledgeFs(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateKnowledgeFsPathInput(input.oldPath, "diff paths");
validateKnowledgeFsPathInput(input.newPath, "diff paths");
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/fs/diff`,
normalizedBaseUrl,
);
url.searchParams.set("oldPath", input.oldPath);
url.searchParams.set("newPath", input.newPath);
if (input.mode) {
url.searchParams.set("mode", input.mode);
}
if (input.semantic === true) {
url.searchParams.set("semantic", "true");
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseKnowledgeFsDiff(await readJson(response));
},
async executeStagedObjectGc(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateId("dryRunId", input.dryRunId);
validateId("idempotencyKey", input.idempotencyKey);
if (input.candidates.length < 1) {
throw new Error("Admin API staged-object GC execution requires at least one candidate");
}
if (
!input.candidates.some((candidate) => candidate.idempotencyKey === input.idempotencyKey)
) {
throw new Error("Admin API staged-object GC idempotency key must match a candidate");
}
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/gc/staged-objects/execute`,
normalizedBaseUrl,
),
{
body: JSON.stringify({ candidates: input.candidates }),
headers: {
...authHeaders(input.token),
"content-type": "application/json",
},
method: "POST",
},
),
);
return parseStagedObjectGcExecuteResult(await readJson(response));
},
async extractSemanticEntities(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
if (
input.limit !== undefined &&
(!Number.isInteger(input.limit) || input.limit < 1 || input.limit > maxListLimit)
) {
throw new Error(
`Admin API semantic entity extraction limit must be between 1 and ${maxListLimit}`,
);
}
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/semantic-views/entities/extract`,
normalizedBaseUrl,
),
{
body: JSON.stringify({ ...(input.limit ? { limit: input.limit } : {}) }),
headers: {
...authHeaders(input.token),
"content-type": "application/json",
},
method: "POST",
},
),
);
return parseSemanticEntityExtractionResult(await readJson(response));
},
async getAnswerTrace(input) {
validateTraceLookup(input);
const response = await fetchImpl(
new Request(new URL(`/queries/${encodePathSegment(input.traceId)}`, normalizedBaseUrl), {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseAnswerTrace(await readJson(response));
},
async getDocument(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateId("documentId", input.documentId);
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/documents/${encodePathSegment(input.documentId)}`,
normalizedBaseUrl,
),
{
headers: authHeaders(input.token),
method: "GET",
},
),
);
return parseDocumentAsset(await readJson(response));
},
async getDocumentOutline(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateId("documentId", input.documentId);
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/documents/${encodePathSegment(input.documentId)}/outline`,
normalizedBaseUrl,
),
{
headers: authHeaders(input.token),
method: "GET",
},
),
);
return parseDocumentOutline(await readJson(response));
},
async getDocumentMultimodalManifest(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateId("documentId", input.documentId);
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/documents/${encodePathSegment(input.documentId)}/multimodal`,
normalizedBaseUrl,
),
{
headers: authHeaders(input.token),
method: "GET",
},
),
);
return parseDocumentMultimodalManifest(await readJson(response));
},
async getDocumentMultimodalAsset(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateId("documentId", input.documentId);
if (!input.itemId.trim()) {
throw new Error("Admin API document multimodal itemId must not be empty");
}
if (input.variant !== undefined && !input.variant.trim()) {
throw new Error("Admin API document multimodal asset variant must not be empty");
}
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/documents/${encodePathSegment(input.documentId)}/multimodal/${encodePathSegment(input.itemId)}/asset`,
normalizedBaseUrl,
);
if (input.variant !== undefined) {
url.searchParams.set("variant", input.variant);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return readDocumentMultimodalAssetResponse(response, maxAssetBytes);
},
async listDocuments(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
if (!Number.isInteger(input.limit) || input.limit < 1 || input.limit > maxListLimit) {
throw new Error(`Admin API document list limit must be between 1 and ${maxListLimit}`);
}
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/documents`,
normalizedBaseUrl,
);
url.searchParams.set("limit", String(input.limit));
if (input.cursor) {
url.searchParams.set("cursor", input.cursor);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseDocumentAssetList(await readJson(response));
},
async getGoldenQuestion(input) {
validateGoldenQuestionLookup(input);
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/golden-questions/${encodePathSegment(input.questionId)}`,
normalizedBaseUrl,
),
{
headers: authHeaders(input.token),
method: "GET",
},
),
);
return parseGoldenQuestion(await readJson(response));
},
async getKnowledgeSpaceManifest(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/manifest`,
normalizedBaseUrl,
),
{
headers: authHeaders(input.token),
method: "GET",
},
),
);
return parseKnowledgeSpaceManifest(await readJson(response));
},
async getKnowledgeSpaceStatus(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/status`,
normalizedBaseUrl,
),
{
headers: authHeaders(input.token),
method: "GET",
},
),
);
return parseKnowledgeSpaceStatus(await readJson(response));
},
async getKnowledgeFsck(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/fsck`,
normalizedBaseUrl,
);
url.searchParams.set("check", input.check);
if (input.cursor) {
url.searchParams.set("cursor", input.cursor);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseKnowledgeFsckReport(await readJson(response));
},
async getStagedObjectGcDryRun(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/gc/staged-objects`,
normalizedBaseUrl,
);
if (input.cursor) {
url.searchParams.set("cursor", input.cursor);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseStagedObjectGcDryRunReport(await readJson(response));
},
async getParseArtifact(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateId("documentId", input.documentId);
if (!Number.isInteger(input.version) || input.version < 1) {
throw new Error("Admin API parse artifact version must be at least 1");
}
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/documents/${encodePathSegment(input.documentId)}/parse-artifacts/${input.version}`,
normalizedBaseUrl,
),
{
headers: authHeaders(input.token),
method: "GET",
},
),
);
return parseParseArtifact(await readJson(response));
},
async health() {
const response = await fetchImpl(new URL("/health", normalizedBaseUrl));
return parseHealthStatus(await readJson(response));
},
async listActiveLeases(input) {
validateKnowledgeSpaceDiagnosticsList(input, maxListLimit);
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/leases/active`,
normalizedBaseUrl,
);
url.searchParams.set("limit", String(input.limit));
if (input.cursor) {
url.searchParams.set("cursor", input.cursor);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseKnowledgeFsLeaseList(await readJson(response));
},
async listGoldenQuestions(input) {
validateGoldenQuestionList(input, maxListLimit);
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/golden-questions`,
normalizedBaseUrl,
);
url.searchParams.set("limit", String(input.limit));
if (input.cursor) {
url.searchParams.set("cursor", input.cursor);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseGoldenQuestionList(await readJson(response));
},
async listKnowledgeFs(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateKnowledgeFsPathInput(input.path);
if (!Number.isInteger(input.limit) || input.limit < 1 || input.limit > maxListLimit) {
throw new Error(`Admin API KnowledgeFS list limit must be between 1 and ${maxListLimit}`);
}
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/fs/ls`,
normalizedBaseUrl,
);
url.searchParams.set("path", input.path);
url.searchParams.set("limit", String(input.limit));
if (input.cursor) {
url.searchParams.set("cursor", input.cursor);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseKnowledgeFsList(await readJson(response));
},
async treeKnowledgeFs(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateKnowledgeFsPathInput(input.path);
if (!Number.isInteger(input.limit) || input.limit < 1 || input.limit > maxListLimit) {
throw new Error(`Admin API KnowledgeFS list limit must be between 1 and ${maxListLimit}`);
}
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/fs/tree`,
normalizedBaseUrl,
);
url.searchParams.set("path", input.path);
url.searchParams.set("limit", String(input.limit));
if (input.depth !== undefined) {
url.searchParams.set("depth", String(input.depth));
}
if (input.cursor) {
url.searchParams.set("cursor", input.cursor);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseKnowledgeFsTree(await readJson(response));
},
async grepKnowledgeFs(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateKnowledgeFsPathInput(input.path);
if (!input.q.trim()) {
throw new Error("Admin API KnowledgeFS grep query is required");
}
if (!Number.isInteger(input.limit) || input.limit < 1 || input.limit > maxListLimit) {
throw new Error(`Admin API KnowledgeFS list limit must be between 1 and ${maxListLimit}`);
}
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/fs/grep`,
normalizedBaseUrl,
);
url.searchParams.set("path", input.path);
url.searchParams.set("limit", String(input.limit));
url.searchParams.set("q", input.q);
if (input.timeoutMs !== undefined) {
url.searchParams.set("timeoutMs", String(input.timeoutMs));
}
if (input.cursor) {
url.searchParams.set("cursor", input.cursor);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseKnowledgeFsGrep(await readJson(response));
},
async findKnowledgeFs(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateKnowledgeFsPathInput(input.path);
if (!Number.isInteger(input.limit) || input.limit < 1 || input.limit > maxListLimit) {
throw new Error(`Admin API KnowledgeFS list limit must be between 1 and ${maxListLimit}`);
}
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/fs/find`,
normalizedBaseUrl,
);
url.searchParams.set("path", input.path);
url.searchParams.set("limit", String(input.limit));
if (input.nameContains) {
url.searchParams.set("nameContains", input.nameContains);
}
if (input.resourceType) {
url.searchParams.set("resourceType", input.resourceType);
}
if (input.metadataKey) {
url.searchParams.set("metadataKey", input.metadataKey);
}
if (input.metadataValue) {
url.searchParams.set("metadataValue", input.metadataValue);
}
if (input.cursor) {
url.searchParams.set("cursor", input.cursor);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseKnowledgeFsList(await readJson(response));
},
async listSemanticView(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
if (!Number.isInteger(input.limit) || input.limit < 1 || input.limit > maxListLimit) {
throw new Error(`Admin API KnowledgeFS list limit must be between 1 and ${maxListLimit}`);
}
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/fs/ls`,
normalizedBaseUrl,
);
url.searchParams.set("path", semanticViewPath(input.view, input.key));
url.searchParams.set("limit", String(input.limit));
if (input.cursor) {
url.searchParams.set("cursor", input.cursor);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseKnowledgeFsList(await readJson(response));
},
async materializeSemanticTopicView(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
if (
input.limit !== undefined &&
(!Number.isInteger(input.limit) || input.limit < 1 || input.limit > maxListLimit)
) {
throw new Error(
`Admin API semantic topic materialization limit must be between 1 and ${maxListLimit}`,
);
}
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/semantic-views/topic/materialize`,
normalizedBaseUrl,
),
{
body: JSON.stringify({
...(input.generatedVersion ? { generatedVersion: input.generatedVersion } : {}),
...(input.limit ? { limit: input.limit } : {}),
...(input.topicName ? { topicName: input.topicName } : {}),
...(input.topicSlug ? { topicSlug: input.topicSlug } : {}),
}),
headers: {
...authHeaders(input.token),
"content-type": "application/json",
},
method: "POST",
},
),
);
return parseSemanticTopicMaterializationResult(await readJson(response));
},
async materializeSemanticCommunities(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/semantic-views/communities/materialize`,
normalizedBaseUrl,
),
{
body: JSON.stringify({
...(input.generatedVersion ? { generatedVersion: input.generatedVersion } : {}),
}),
headers: {
...authHeaders(input.token),
"content-type": "application/json",
},
method: "POST",
},
),
);
return parseSemanticCommunityMaterializationResult(await readJson(response));
},
async listKnowledgeSpaces(input) {
validateToken(input.token);
if (!Number.isInteger(input.limit) || input.limit < 1 || input.limit > maxListLimit) {
throw new Error(
`Admin API listKnowledgeSpaces limit must be between 1 and ${maxListLimit}`,
);
}
const url = new URL("/knowledge-spaces", normalizedBaseUrl);
url.searchParams.set("limit", String(input.limit));
if (input.cursor) {
url.searchParams.set("cursor", input.cursor);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseKnowledgeSpaceList(await readJson(response));
},
async listStagedCommits(input) {
validateKnowledgeSpaceDiagnosticsList(input, maxListLimit);
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/staged-commits`,
normalizedBaseUrl,
);
url.searchParams.set("limit", String(input.limit));
if (input.cursor) {
url.searchParams.set("cursor", input.cursor);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseKnowledgeSpaceStagedCommitList(await readJson(response));
},
async listQueryConflicts(input) {
return listQueryVirtualEntries({
input,
normalizedBaseUrl,
readJson,
fetchImpl,
segment: "conflicts",
});
},
async listQueryEvidence(input) {
return listQueryVirtualEntries({
input,
normalizedBaseUrl,
readJson,
fetchImpl,
segment: "evidence",
});
},
async listQueryMissing(input) {
return listQueryVirtualEntries({
input,
normalizedBaseUrl,
readJson,
fetchImpl,
segment: "missing",
});
},
async openKnowledgeFsNode(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateId("nodeId", input.nodeId);
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/fs/open_node`,
normalizedBaseUrl,
);
url.searchParams.set("nodeId", input.nodeId);
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseKnowledgeFsOpenNode(await readJson(response));
},
async statKnowledgeFs(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateKnowledgeFsPathInput(input.path);
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/fs/stat`,
normalizedBaseUrl,
);
url.searchParams.set("path", input.path);
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseKnowledgeFsStat(await readJson(response));
},
async writeKnowledgeFs(input) {
return executeKnowledgeFsWrite({
input,
normalizedBaseUrl,
readJson,
fetchImpl,
command: "write",
});
},
async appendKnowledgeFs(input) {
return executeKnowledgeFsWrite({
input,
normalizedBaseUrl,
readJson,
fetchImpl,
command: "append",
});
},
async streamQuery(input) {
validateToken(input.token);
if (!input.knowledgeSpaceId.trim()) {
throw new Error("Admin API knowledgeSpaceId is required");
}
if (!input.query.trim()) {
throw new Error("Admin API query is required");
}
if (textEncoder.encode(input.query).byteLength > maxQueryBytes) {
throw new Error(`Admin API query exceeds maxQueryBytes=${maxQueryBytes}`);
}
const response = await fetchImpl(
new Request(new URL("/queries", normalizedBaseUrl), {
body: JSON.stringify({
knowledgeSpaceId: input.knowledgeSpaceId,
...(input.mode ? { mode: input.mode } : {}),
query: input.query,
}),
headers: {
...authHeaders(input.token),
"content-type": "application/json",
},
method: "POST",
}),
);
if (!response.ok) {
throw new Error(`Admin API request failed with status ${response.status}`);
}
return parseSseEvents(await readBoundedTextResponse(response, maxSseBytes));
},
async updateGoldenQuestion(input) {
validateGoldenQuestionLookup(input);
if (input.question !== undefined && !input.question.trim()) {
throw new Error("Admin API golden question is required");
}
const body: Record<string, unknown> = {};
if (input.expectedEvidenceIds !== undefined) {
body.expectedEvidenceIds = [...input.expectedEvidenceIds];
}
if (input.metadata !== undefined) {
body.metadata = { ...input.metadata };
}
if (input.question !== undefined) {
body.question = input.question;
}
if (input.tags !== undefined) {
body.tags = [...input.tags];
}
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/golden-questions/${encodePathSegment(input.questionId)}`,
normalizedBaseUrl,
),
{
body: JSON.stringify(body),
headers: {
...authHeaders(input.token),
"content-type": "application/json",
},
method: "PATCH",
},
),
);
return parseGoldenQuestion(await readJson(response));
},
async traverseGraph(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateId("entityId", input.entityId);
const depth = input.depth ?? maxGraphDepth;
const fanout = input.fanout ?? Math.min(20, maxGraphFanout);
const maxNodes = input.maxNodes ?? Math.min(50, maxGraphNodes);
const timeoutMs = input.timeoutMs ?? Math.min(250, maxGraphTimeoutMs);
validateIntegerRange("graph depth", depth, 1, maxGraphDepth);
validateIntegerRange("graph fanout", fanout, 1, maxGraphFanout);
validateIntegerRange("graph maxNodes", maxNodes, 1, maxGraphNodes);
validateIntegerRange("graph timeoutMs", timeoutMs, 1, maxGraphTimeoutMs);
const url = new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/graph/traverse`,
normalizedBaseUrl,
);
url.searchParams.set("entityId", input.entityId);
url.searchParams.set("depth", String(depth));
url.searchParams.set("fanout", String(fanout));
url.searchParams.set("maxNodes", String(maxNodes));
url.searchParams.set("timeoutMs", String(timeoutMs));
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseGraphTraversal(await readJson(response));
},
async uploadDocument(input) {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
if (input.file.size > maxUploadBytes) {
throw new Error(`Admin API upload exceeds maxUploadBytes=${maxUploadBytes}`);
}
const formData = new FormData();
formData.set("file", input.file);
if (input.sourceId) {
formData.set("sourceId", input.sourceId);
}
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/documents`,
normalizedBaseUrl,
),
{
body: formData,
headers: authHeaders(input.token),
method: "POST",
},
),
);
return parseDocumentAsset(await readJson(response));
},
};
}
async function executeKnowledgeFsWrite({
command,
fetchImpl,
input,
normalizedBaseUrl,
readJson,
}: {
readonly command: "append" | "write";
readonly fetchImpl: typeof fetch;
readonly input: WriteKnowledgeFsInput;
readonly normalizedBaseUrl: URL;
readonly readJson: (response: Response) => Promise<unknown>;
}): Promise<AdminKnowledgeFsWrite> {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateKnowledgeFsPathInput(input.path);
if (textEncoder.encode(input.text).byteLength > 256 * 1024) {
throw new Error("Admin API KnowledgeFS write text exceeds 256 KiB");
}
const response = await fetchImpl(
new Request(
new URL(
`/knowledge-spaces/${encodePathSegment(input.knowledgeSpaceId)}/fs/${command}`,
normalizedBaseUrl,
),
{
body: JSON.stringify({
path: input.path,
text: input.text,
}),
headers: {
...authHeaders(input.token),
"content-type": "application/json",
},
method: "POST",
},
),
);
return parseKnowledgeFsWrite(await readJson(response));
}
async function listQueryVirtualEntries({
fetchImpl,
input,
normalizedBaseUrl,
readJson,
segment,
}: {
readonly fetchImpl: typeof fetch;
readonly input: ListQueryVirtualEntriesInput;
readonly normalizedBaseUrl: URL;
readonly readJson: (response: Response) => Promise<unknown>;
readonly segment: "conflicts" | "evidence" | "missing";
}): Promise<AdminKnowledgeFsList> {
validateTraceLookup(input);
if (!Number.isInteger(input.limit) || input.limit < 1) {
throw new Error("Admin API query virtual entry limit must be at least 1");
}
const url = new URL(`/queries/${encodePathSegment(input.traceId)}/${segment}`, normalizedBaseUrl);
url.searchParams.set("limit", String(input.limit));
if (input.cursor) {
url.searchParams.set("cursor", input.cursor);
}
const response = await fetchImpl(
new Request(url, {
headers: authHeaders(input.token),
method: "GET",
}),
);
return parseKnowledgeFsList(await readJson(response));
}
export function parseSseEvents(payload: string): AdminSseEvent[] {
const events: AdminSseEvent[] = [];
for (const block of payload.split(/\n\n+/u)) {
const trimmed = block.trim();
if (!trimmed) {
continue;
}
let event = "message";
const dataLines: string[] = [];
for (const line of trimmed.split(/\n/u)) {
if (line.startsWith("event:")) {
event = line.slice("event:".length).trim();
continue;
}
if (line.startsWith("data:")) {
dataLines.push(line.slice("data:".length).trim());
}
}
const dataText = dataLines.join("\n");
try {
events.push({
data: dataText ? JSON.parse(dataText) : null,
event,
});
} catch (error) {
throw new Error("Admin API SSE event contains invalid JSON", { cause: error });
}
}
return events;
}
function normalizeBaseUrl(baseUrl: string): URL {
const trimmed = baseUrl.trim();
if (!trimmed) {
throw new Error("Admin API baseUrl is required");
}
return new URL(trimmed.endsWith("/") ? trimmed : `${trimmed}/`);
}
function validateToken(token: string): void {
if (!token.trim()) {
throw new Error("Admin API token is required");
}
}
function validateId(label: string, value: string): void {
if (!value.trim()) {
throw new Error(`Admin API ${label} is required`);
}
}
function validateKnowledgeFsPathInput(path: string, label = "path"): void {
if (!path.trim().startsWith("/")) {
throw new Error(`Admin API KnowledgeFS ${label} must be absolute`);
}
}
function validateUuid(label: string, value: string): void {
validateId(label, value);
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)) {
throw new Error(`Admin API ${label} must be a UUID`);
}
}
function validateGoldenQuestionList(input: ListGoldenQuestionsInput, maxListLimit: number): void {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
if (!Number.isInteger(input.limit) || input.limit < 1 || input.limit > maxListLimit) {
throw new Error(`Admin API golden question list limit must be between 1 and ${maxListLimit}`);
}
}
function validateKnowledgeSpaceDiagnosticsList(
input: ListKnowledgeSpaceDiagnosticsInput,
maxListLimit: number,
): void {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
if (!Number.isInteger(input.limit) || input.limit < 1 || input.limit > maxListLimit) {
throw new Error(
`Admin API KnowledgeSpace diagnostics list limit must be between 1 and ${maxListLimit}`,
);
}
}
function validateGoldenQuestionLookup(input: GetGoldenQuestionInput): void {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateId("questionId", input.questionId);
}
function validateGoldenQuestionMutation(input: CreateGoldenQuestionInput): void {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
if (!input.question.trim()) {
throw new Error("Admin API golden question is required");
}
for (const id of input.expectedEvidenceIds ?? []) {
validateUuid("expectedEvidenceId", id);
}
}
function validateGoldenQuestionAnnotation(input: AnnotateGoldenQuestionInput): void {
validateGoldenQuestionLookup(input);
if (
!["correct", "incorrect", "not-answerable", "partially-correct"].includes(
input.answerCorrectness,
)
) {
throw new Error("Admin API answerCorrectness is invalid");
}
if (input.evidenceRelevance.length > 50) {
throw new Error("Admin API annotation evidenceRelevance cannot exceed 50 items");
}
for (const item of input.evidenceRelevance) {
validateUuid("evidenceId", item.evidenceId);
if (item.note !== undefined && !item.note.trim()) {
throw new Error("Admin API annotation evidence note must not be empty");
}
}
if (input.note !== undefined && !input.note.trim()) {
throw new Error("Admin API annotation note must not be empty");
}
}
function validateProductionBadCaseCapture(input: CaptureProductionBadCaseInput): void {
validateToken(input.token);
validateId("knowledgeSpaceId", input.knowledgeSpaceId);
validateUuid("traceId", input.traceId);
if (input.reason !== undefined && !input.reason.trim()) {
throw new Error("Admin API bad-case reason must not be empty");
}
}
function validateTraceLookup(input: GetAnswerTraceInput): void {
validateToken(input.token);
validateUuid("traceId", input.traceId);
}
function validateIntegerRange(label: string, value: number, min: number, max: number): void {
if (!Number.isInteger(value) || value < min || value > max) {
throw new Error(`Admin API ${label} must be between ${min} and ${max}`);
}
}
function semanticViewPath(view: AdminSemanticView, key: string | undefined): string {
const basePath = `/knowledge/${view}`;
if (key === undefined || key.trim() === "") {
return basePath;
}
const trimmed = key.trim();
if (trimmed.includes("/") || trimmed.includes("\\") || trimmed.includes("..")) {
throw new Error("Admin API semantic view key must be a single path segment");
}
return `${basePath}/${trimmed}`;
}
function encodePathSegment(value: string): string {
return encodeURIComponent(value);
}
function authHeaders(token: string): Record<string, string> {
return {
authorization: `Bearer ${token}`,
};
}
async function readJsonResponse(response: Response, maxBytes: number): Promise<unknown> {
if (!response.ok) {
const message = extractApiErrorMessage(
await readBoundedTextResponse(response, maxBytes, "JSON"),
);
throw new Error(
message
? `Admin API request failed with status ${response.status}: ${message}`
: `Admin API request failed with status ${response.status}`,
);
}
const text = await readBoundedTextResponse(response, maxBytes, "JSON");
return JSON.parse(text) as unknown;
}
async function readDocumentMultimodalAssetResponse(
response: Response,
maxBytes: number,
): Promise<AdminDocumentMultimodalAsset> {
if (!response.ok) {
const message = extractApiErrorMessage(
await readBoundedTextResponse(response, defaultMaxJsonBytes, "JSON"),
);
throw new Error(
message
? `Admin API request failed with status ${response.status}: ${message}`
: `Admin API request failed with status ${response.status}`,
);
}
const contentLength = response.headers.get("content-length");
if (contentLength !== null) {
const parsedLength = Number(contentLength);
if (Number.isFinite(parsedLength) && parsedLength > maxBytes) {
throw new Error(`Admin API multimodal asset response exceeds maxAssetBytes=${maxBytes}`);
}
}
const bytes = await response.arrayBuffer();
if (bytes.byteLength > maxBytes) {
throw new Error(`Admin API multimodal asset response exceeds maxAssetBytes=${maxBytes}`);
}
return {
bytes,
contentType: response.headers.get("content-type") ?? "application/octet-stream",
...(response.headers.get("x-document-multimodal-item-id")
? { itemId: response.headers.get("x-document-multimodal-item-id") ?? undefined }
: {}),
};
}
function extractApiErrorMessage(text: string): string | undefined {
if (!text.trim()) {
return undefined;
}
try {
const parsed = JSON.parse(text) as unknown;
if (
parsed &&
typeof parsed === "object" &&
"error" in parsed &&
typeof parsed.error === "string" &&
parsed.error.trim()
) {
return parsed.error.trim();
}
const issueMessage = extractZodIssueMessage(parsed);
if (issueMessage) {
return issueMessage;
}
} catch {
return text.trim().slice(0, 500);
}
return undefined;
}
function extractZodIssueMessage(value: unknown): string | undefined {
const directIssue = firstZodIssueMessage(value);
if (directIssue) {
return directIssue;
}
if (isRecord(value)) {
const nestedIssue = firstZodIssueMessage(value.error);
if (nestedIssue) {
return nestedIssue;
}
}
return undefined;
}
function firstZodIssueMessage(value: unknown): string | undefined {
if (!isRecord(value) || !Array.isArray(value.issues)) {
return undefined;
}
const issue = value.issues.find(isRecord);
if (!issue || typeof issue.message !== "string" || !issue.message.trim()) {
return undefined;
}
const path = Array.isArray(issue.path)
? issue.path.filter((part) => typeof part === "string" || typeof part === "number").join(".")
: "";
return path ? `${path}: ${issue.message}` : issue.message.trim();
}
async function readBoundedTextResponse(
response: Response,
maxBytes: number,
label = "SSE",
): Promise<string> {
if (!response.body) {
return "";
}
const reader = response.body.getReader();
const chunks: Uint8Array[] = [];
let totalBytes = 0;
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
totalBytes += value.byteLength;
if (totalBytes > maxBytes) {
await reader.cancel();
throw new Error(
label === "JSON"
? `Admin API JSON response exceeds maxJsonBytes=${maxBytes}`
: `Admin API SSE response exceeds maxSseBytes=${maxBytes}`,
);
}
chunks.push(value.slice());
}
const merged = new Uint8Array(totalBytes);
let offset = 0;
for (const chunk of chunks) {
merged.set(chunk, offset);
offset += chunk.byteLength;
}
return textDecoder.decode(merged);
}
function parseHealthStatus(value: unknown): AdminHealthStatus {
if (!isRecord(value) || typeof value.ok !== "boolean" || !isRecord(value.components)) {
throw new Error("Admin API health response is invalid");
}
if (value.runtime !== "cloudflare-workers" && value.runtime !== "node-docker") {
throw new Error("Admin API health runtime is invalid");
}
const components: Record<string, boolean> = {};
for (const [key, healthy] of Object.entries(value.components)) {
if (typeof healthy !== "boolean") {
throw new Error("Admin API health component value is invalid");
}
components[key] = healthy;
}
return {
components,
ok: value.ok,
runtime: value.runtime,
};
}
function parseKnowledgeSpaceList(value: unknown): AdminKnowledgeSpaceList {
if (!isRecord(value) || !Array.isArray(value.items)) {
throw new Error("Admin API knowledge-space list response is invalid");
}
return {
items: value.items.map(parseKnowledgeSpace),
...(typeof value.nextCursor === "string" ? { nextCursor: value.nextCursor } : {}),
};
}
function parseKnowledgeSpace(value: unknown): AdminKnowledgeSpace {
if (!isRecord(value)) {
throw new Error("Admin API knowledge-space response item is invalid");
}
const required = ["createdAt", "id", "name", "slug", "tenantId", "updatedAt"] as const;
for (const key of required) {
if (typeof value[key] !== "string") {
throw new Error(`Admin API knowledge-space ${key} is invalid`);
}
}
const createdAt = value.createdAt;
const id = value.id;
const name = value.name;
const slug = value.slug;
const tenantId = value.tenantId;
const updatedAt = value.updatedAt;
if (
typeof createdAt !== "string" ||
typeof id !== "string" ||
typeof name !== "string" ||
typeof slug !== "string" ||
typeof tenantId !== "string" ||
typeof updatedAt !== "string"
) {
throw new Error("Admin API knowledge-space response item is invalid");
}
return {
createdAt,
...(typeof value.description === "string" ? { description: value.description } : {}),
id,
name,
slug,
tenantId,
updatedAt,
};
}
function parseKnowledgeSpaceManifest(value: unknown): AdminKnowledgeSpaceManifest {
if (!isRecord(value)) {
throw new Error("Admin API KnowledgeSpace manifest response is invalid");
}
if (
typeof value.manifestVersion !== "number" ||
typeof value.objectKeyPrefix !== "string" ||
typeof value.parserPolicyVersion !== "string" ||
typeof value.projectionSetVersion !== "string" ||
typeof value.storageProvider !== "string" ||
!isRecord(value.consistencyPolicy) ||
!isRecord(value.quotaPolicy)
) {
throw new Error("Admin API KnowledgeSpace manifest response is invalid");
}
return {
consistencyPolicy: { ...value.consistencyPolicy },
manifestVersion: value.manifestVersion,
objectKeyPrefix: value.objectKeyPrefix,
parserPolicyVersion: value.parserPolicyVersion,
projectionSetVersion: value.projectionSetVersion,
quotaPolicy: { ...value.quotaPolicy },
storageProvider: value.storageProvider,
};
}
function parseKnowledgeSpaceStatus(value: unknown): AdminKnowledgeSpaceStatus {
if (!isRecord(value)) {
throw new Error("Admin API KnowledgeSpace status response is invalid");
}
return {
...(isRecord(value.index) ? { index: { ...value.index } } : {}),
...(isRecord(value.manifest) ? { manifest: { ...value.manifest } } : {}),
...(isRecord(value.parser) ? { parser: { ...value.parser } } : {}),
...(isRecord(value.runtime) ? { runtime: { ...value.runtime } } : {}),
...(isRecord(value.storage) ? { storage: { ...value.storage } } : {}),
};
}
function parseKnowledgeSpaceStagedCommitList(value: unknown): AdminKnowledgeSpaceStagedCommitList {
if (!isRecord(value) || !Array.isArray(value.items)) {
throw new Error("Admin API staged commit diagnostic list response is invalid");
}
return {
items: value.items.map(parseKnowledgeSpaceStagedCommit),
...(typeof value.nextCursor === "string" ? { nextCursor: value.nextCursor } : {}),
};
}
function parseKnowledgeSpaceStagedCommit(value: unknown): AdminKnowledgeSpaceStagedCommit {
if (!isRecord(value)) {
throw new Error("Admin API staged commit diagnostic response item is invalid");
}
if (
typeof value.id !== "string" ||
typeof value.idempotencyKey !== "string" ||
typeof value.operationType !== "string" ||
typeof value.status !== "string" ||
typeof value.updatedAt !== "string"
) {
throw new Error("Admin API staged commit diagnostic response item is invalid");
}
return {
...(typeof value.errorCode === "string" ? { errorCode: value.errorCode } : {}),
...(typeof value.errorMessage === "string" ? { errorMessage: value.errorMessage } : {}),
...(typeof value.expiresAt === "string" ? { expiresAt: value.expiresAt } : {}),
id: value.id,
idempotencyKey: value.idempotencyKey,
operationType: value.operationType,
status: value.status,
updatedAt: value.updatedAt,
};
}
function parseKnowledgeFsLeaseList(value: unknown): AdminKnowledgeFsLeaseList {
if (!isRecord(value) || !Array.isArray(value.items)) {
throw new Error("Admin API active lease diagnostic list response is invalid");
}
return {
items: value.items.map(parseKnowledgeFsLease),
...(typeof value.nextCursor === "string" ? { nextCursor: value.nextCursor } : {}),
};
}
function parseKnowledgeFsLease(value: unknown): AdminKnowledgeFsLease {
if (!isRecord(value)) {
throw new Error("Admin API active lease diagnostic response item is invalid");
}
if (
typeof value.expiresAt !== "string" ||
typeof value.heartbeatAt !== "string" ||
typeof value.id !== "string" ||
typeof value.leaseType !== "string" ||
typeof value.status !== "string" ||
typeof value.targetId !== "string" ||
typeof value.targetType !== "string" ||
typeof value.virtualPath !== "string"
) {
throw new Error("Admin API active lease diagnostic response item is invalid");
}
return {
expiresAt: value.expiresAt,
heartbeatAt: value.heartbeatAt,
id: value.id,
leaseType: value.leaseType,
status: value.status,
targetId: value.targetId,
targetType: value.targetType,
virtualPath: value.virtualPath,
};
}
function parseKnowledgeFsckReport(value: unknown): AdminKnowledgeFsckReport {
if (
!isRecord(value) ||
!Array.isArray(value.issues) ||
typeof value.knowledgeSpaceId !== "string" ||
typeof value.scannedAt !== "string" ||
!isNumberRecord(value.summary) ||
typeof value.tenantId !== "string"
) {
throw new Error("Admin API fsck report response is invalid");
}
return {
...(typeof value.cursor === "string" ? { cursor: value.cursor } : {}),
issues: value.issues.map(parseKnowledgeFsckIssue),
knowledgeSpaceId: value.knowledgeSpaceId,
scannedAt: value.scannedAt,
summary: { ...value.summary },
tenantId: value.tenantId,
};
}
function parseKnowledgeFsckIssue(value: unknown): AdminKnowledgeFsckIssue {
if (
!isRecord(value) ||
typeof value.code !== "string" ||
typeof value.message !== "string" ||
typeof value.repairability !== "string" ||
typeof value.severity !== "string" ||
!isRecord(value.target) ||
typeof value.type !== "string"
) {
throw new Error("Admin API fsck issue response item is invalid");
}
return {
code: value.code,
message: value.message,
repairability: value.repairability,
severity: value.severity,
target: { ...value.target },
type: value.type,
};
}
function parseStagedObjectGcDryRunReport(value: unknown): AdminKnowledgeFsGcDryRunReport {
if (
!isRecord(value) ||
!Array.isArray(value.candidates) ||
typeof value.dryRunId !== "string" ||
typeof value.generatedAt !== "string" ||
typeof value.knowledgeSpaceId !== "string" ||
!isNumberRecord(value.summary) ||
typeof value.tenantId !== "string"
) {
throw new Error("Admin API staged-object GC dry-run response is invalid");
}
return {
candidates: value.candidates.map(parseGcCandidate),
...(typeof value.cursor === "string" ? { cursor: value.cursor } : {}),
dryRunId: value.dryRunId,
generatedAt: value.generatedAt,
knowledgeSpaceId: value.knowledgeSpaceId,
summary: { ...value.summary },
tenantId: value.tenantId,
};
}
function parseGcCandidate(value: unknown): AdminKnowledgeFsGcCandidate {
if (
!isRecord(value) ||
typeof value.candidateType !== "string" ||
typeof value.count !== "number" ||
typeof value.estimatedBytes !== "number" ||
typeof value.idempotencyKey !== "string" ||
typeof value.reason !== "string" ||
!isRecord(value.target)
) {
throw new Error("Admin API GC candidate response item is invalid");
}
return {
candidateType: value.candidateType,
count: value.count,
estimatedBytes: value.estimatedBytes,
idempotencyKey: value.idempotencyKey,
reason: value.reason,
target: { ...value.target },
};
}
function parseStagedObjectGcExecuteResult(
value: unknown,
): AdminKnowledgeFsStagedObjectGcExecuteResult {
if (
!isRecord(value) ||
typeof value.deleted !== "number" ||
!Array.isArray(value.items) ||
typeof value.skipped !== "number" ||
typeof value.tenantId !== "string"
) {
throw new Error("Admin API staged-object GC execute response is invalid");
}
return {
deleted: value.deleted,
items: value.items.map(parseStagedObjectGcExecuteItem),
skipped: value.skipped,
tenantId: value.tenantId,
};
}
function parseStagedObjectGcExecuteItem(value: unknown): {
readonly idempotencyKey: string;
readonly objectKey: string;
readonly status: string;
} {
if (
!isRecord(value) ||
typeof value.idempotencyKey !== "string" ||
typeof value.objectKey !== "string" ||
typeof value.status !== "string"
) {
throw new Error("Admin API staged-object GC execute response item is invalid");
}
return {
idempotencyKey: value.idempotencyKey,
objectKey: value.objectKey,
status: value.status,
};
}
function parseGoldenQuestionList(value: unknown): AdminGoldenQuestionList {
if (!isRecord(value) || !Array.isArray(value.items)) {
throw new Error("Admin API golden question list response is invalid");
}
return {
items: value.items.map(parseGoldenQuestion),
...(typeof value.nextCursor === "string" ? { nextCursor: value.nextCursor } : {}),
};
}
function parseGoldenQuestion(value: unknown): AdminGoldenQuestion {
if (
!isRecord(value) ||
!Array.isArray(value.expectedEvidenceIds) ||
!isRecord(value.metadata) ||
!Array.isArray(value.tags)
) {
throw new Error("Admin API golden question response is invalid");
}
const createdAt = value.createdAt;
const id = value.id;
const knowledgeSpaceId = value.knowledgeSpaceId;
const question = value.question;
const updatedAt = value.updatedAt;
if (
typeof createdAt !== "string" ||
typeof id !== "string" ||
typeof knowledgeSpaceId !== "string" ||
typeof question !== "string" ||
typeof updatedAt !== "string"
) {
throw new Error("Admin API golden question response is invalid");
}
return {
createdAt,
expectedEvidenceIds: parseStringArray(
value.expectedEvidenceIds,
"Admin API golden question expectedEvidenceIds are invalid",
),
id,
knowledgeSpaceId,
metadata: { ...value.metadata },
question,
tags: parseStringArray(value.tags, "Admin API golden question tags are invalid"),
updatedAt,
};
}
function parseKnowledgeFsList(value: unknown): AdminKnowledgeFsList {
if (!isRecord(value) || !Array.isArray(value.items) || typeof value.path !== "string") {
throw new Error("Admin API KnowledgeFS list response is invalid");
}
if (typeof value.truncated !== "boolean") {
throw new Error("Admin API KnowledgeFS list truncated flag is invalid");
}
return {
items: value.items.map(parseKnowledgeFsEntry),
...(typeof value.nextCursor === "string" ? { nextCursor: value.nextCursor } : {}),
path: value.path,
truncated: value.truncated,
};
}
function parseKnowledgeFsEntry(value: unknown): AdminKnowledgeFsEntry {
if (
!isRecord(value) ||
(value.kind !== "directory" && value.kind !== "resource") ||
!isRecord(value.metadata) ||
typeof value.name !== "string" ||
typeof value.path !== "string"
) {
throw new Error("Admin API KnowledgeFS entry is invalid");
}
if (value.resourceType !== undefined && !isKnowledgeFsResourceType(value.resourceType)) {
throw new Error("Admin API KnowledgeFS entry resourceType is invalid");
}
const version = value.version;
if (
version !== undefined &&
(typeof version !== "number" || !Number.isInteger(version) || version < 1)
) {
throw new Error("Admin API KnowledgeFS entry version is invalid");
}
return {
kind: value.kind,
metadata: { ...value.metadata },
name: value.name,
path: value.path,
...(typeof value.resourceType === "string" ? { resourceType: value.resourceType } : {}),
...(typeof value.targetId === "string" ? { targetId: value.targetId } : {}),
...(typeof version === "number" ? { version } : {}),
};
}
function isKnowledgeFsResourceType(
value: unknown,
): value is NonNullable<AdminKnowledgeFsEntry["resourceType"]> {
return (
value === "answer-trace" ||
value === "document" ||
value === "evidence-bundle" ||
value === "node" ||
value === "knowledge-node" ||
value === "artifact" ||
value === "parse-artifact" ||
value === "source" ||
value === "workspace"
);
}
function parseKnowledgeFsTree(value: unknown): AdminKnowledgeFsTree {
if (
!isRecord(value) ||
typeof value.path !== "string" ||
!isRecord(value.root) ||
typeof value.truncated !== "boolean"
) {
throw new Error("Admin API KnowledgeFS tree response is invalid");
}
return {
...(typeof value.nextCursor === "string" ? { nextCursor: value.nextCursor } : {}),
path: value.path,
root: parseKnowledgeFsTreeNode(value.root),
truncated: value.truncated,
};
}
function parseKnowledgeFsTreeNode(value: unknown): AdminKnowledgeFsTreeNode {
const entry = parseKnowledgeFsEntry(value);
const children = isRecord(value) && Array.isArray(value.children) ? value.children : undefined;
return {
...entry,
...(children ? { children: children.map(parseKnowledgeFsTreeNode) } : {}),
};
}
function parseKnowledgeFsCat(value: unknown): AdminKnowledgeFsCat {
if (
!isRecord(value) ||
typeof value.contentType !== "string" ||
typeof value.path !== "string" ||
typeof value.text !== "string" ||
typeof value.truncated !== "boolean"
) {
throw new Error("Admin API KnowledgeFS cat response is invalid");
}
return {
contentType: value.contentType,
...(typeof value.nextCursor === "string" ? { nextCursor: value.nextCursor } : {}),
path: value.path,
text: value.text,
truncated: value.truncated,
};
}
function parseKnowledgeFsStat(value: unknown): AdminKnowledgeFsStat {
if (
!isRecord(value) ||
!isRecord(value.metadata) ||
typeof value.path !== "string" ||
!isKnowledgeFsResourceType(value.resourceType) ||
typeof value.targetId !== "string"
) {
throw new Error("Admin API KnowledgeFS stat response is invalid");
}
const version = value.version;
if (
version !== undefined &&
(typeof version !== "number" || !Number.isInteger(version) || version < 1)
) {
throw new Error("Admin API KnowledgeFS stat version is invalid");
}
return {
...(typeof value.contentType === "string" ? { contentType: value.contentType } : {}),
metadata: { ...value.metadata },
...(isDocumentParserStatus(value.parserStatus) ? { parserStatus: value.parserStatus } : {}),
path: value.path,
resourceType: value.resourceType,
...(typeof value.sha256 === "string" ? { sha256: value.sha256 } : {}),
...(typeof value.sizeBytes === "number" ? { sizeBytes: value.sizeBytes } : {}),
targetId: value.targetId,
...(typeof version === "number" ? { version } : {}),
};
}
function parseKnowledgeFsWrite(value: unknown): AdminKnowledgeFsWrite {
if (
!isRecord(value) ||
typeof value.bytesWritten !== "number" ||
(value.mode !== "append" && value.mode !== "write") ||
typeof value.objectKey !== "string" ||
typeof value.path !== "string" ||
typeof value.targetId !== "string" ||
typeof value.version !== "number"
) {
throw new Error("Admin API KnowledgeFS write response is invalid");
}
if (
!Number.isInteger(value.bytesWritten) ||
value.bytesWritten < 0 ||
!Number.isInteger(value.version) ||
value.version < 1
) {
throw new Error("Admin API KnowledgeFS write response counters are invalid");
}
return {
bytesWritten: value.bytesWritten,
mode: value.mode,
objectKey: value.objectKey,
path: value.path,
targetId: value.targetId,
version: value.version,
};
}
function parseKnowledgeFsGrep(value: unknown): AdminKnowledgeFsGrep {
if (
!isRecord(value) ||
!Array.isArray(value.matches) ||
typeof value.path !== "string" ||
typeof value.truncated !== "boolean"
) {
throw new Error("Admin API KnowledgeFS grep response is invalid");
}
return {
matches: value.matches.map(parseKnowledgeFsGrepMatch),
...(typeof value.nextCursor === "string" ? { nextCursor: value.nextCursor } : {}),
path: value.path,
truncated: value.truncated,
};
}
function parseKnowledgeFsGrepMatch(value: unknown): AdminKnowledgeFsGrepMatch {
if (
!isRecord(value) ||
(value.kind !== "node" && value.kind !== "segment") ||
!isRecord(value.metadata) ||
typeof value.path !== "string" ||
typeof value.snippet !== "string" ||
typeof value.startOffset !== "number" ||
typeof value.endOffset !== "number"
) {
throw new Error("Admin API KnowledgeFS grep match is invalid");
}
return {
endOffset: value.endOffset,
kind: value.kind,
metadata: { ...value.metadata },
...(typeof value.nodeId === "string" ? { nodeId: value.nodeId } : {}),
path: value.path,
...(typeof value.segmentId === "string" ? { segmentId: value.segmentId } : {}),
snippet: value.snippet,
startOffset: value.startOffset,
};
}
function parseKnowledgeFsOpenNode(value: unknown): AdminKnowledgeFsOpenNode {
if (!isRecord(value) || !isRecord(value.citation) || !isRecord(value.node)) {
throw new Error("Admin API KnowledgeFS open_node response is invalid");
}
const citation = value.citation;
const node = value.node;
if (
typeof citation.artifactHash !== "string" ||
typeof citation.documentAssetId !== "string" ||
typeof citation.endOffset !== "number" ||
typeof citation.parseArtifactId !== "string" ||
!Array.isArray(citation.sectionPath) ||
typeof citation.startOffset !== "number" ||
typeof node.id !== "string" ||
typeof node.kind !== "string" ||
!isRecord(node.metadata) ||
typeof node.text !== "string"
) {
throw new Error("Admin API KnowledgeFS open_node response is invalid");
}
return {
citation: {
artifactHash: citation.artifactHash,
documentAssetId: citation.documentAssetId,
endOffset: citation.endOffset,
...(typeof citation.pageNumber === "number" ? { pageNumber: citation.pageNumber } : {}),
parseArtifactId: citation.parseArtifactId,
sectionPath: parseStringArray(
citation.sectionPath,
"Admin API KnowledgeFS open_node sectionPath is invalid",
),
startOffset: citation.startOffset,
},
node: {
id: node.id,
kind: node.kind,
metadata: { ...node.metadata },
text: node.text,
},
};
}
function isDocumentParserStatus(value: unknown): value is AdminDocumentAsset["parserStatus"] {
return value === "failed" || value === "parsed" || value === "pending";
}
function parseKnowledgeFsDiff(value: unknown): AdminKnowledgeFsDiff {
if (!isRecord(value) || !Array.isArray(value.operations) || !isRecord(value.stats)) {
throw new Error("Admin API KnowledgeFS diff response is invalid");
}
const mode = value.mode;
const newPath = value.newPath;
const oldPath = value.oldPath;
if (
(mode !== "line" && mode !== "word") ||
typeof newPath !== "string" ||
typeof oldPath !== "string"
) {
throw new Error("Admin API KnowledgeFS diff response is invalid");
}
return {
mode,
newPath,
oldPath,
operations: value.operations.map(parseTextDiffOperation),
...(value.semantic === undefined ? {} : { semantic: parseSemanticDiffSummary(value.semantic) }),
stats: parseTextDiffStats(value.stats),
};
}
function parseAnswerTrace(value: unknown): AdminAnswerTrace {
if (!isRecord(value) || !Array.isArray(value.steps)) {
throw new Error("Admin API answer trace response is invalid");
}
const createdAt = value.createdAt;
const id = value.id;
const knowledgeSpaceId = value.knowledgeSpaceId;
const mode = value.mode;
const query = value.query;
if (
typeof createdAt !== "string" ||
typeof id !== "string" ||
typeof knowledgeSpaceId !== "string" ||
typeof query !== "string" ||
(mode !== "auto" && mode !== "deep" && mode !== "fast" && mode !== "research")
) {
throw new Error("Admin API answer trace response is invalid");
}
return {
createdAt,
...(typeof value.evidenceBundleId === "string"
? { evidenceBundleId: value.evidenceBundleId }
: {}),
id,
knowledgeSpaceId,
mode,
query,
steps: value.steps.map(parseAnswerTraceStep),
};
}
function parseAnswerTraceStep(value: unknown): AdminAnswerTraceStep {
if (!isRecord(value) || !isRecord(value.metadata)) {
throw new Error("Admin API answer trace step is invalid");
}
const name = value.name;
const startedAt = value.startedAt;
const status = value.status;
if (
typeof name !== "string" ||
typeof startedAt !== "string" ||
(status !== "error" && status !== "ok" && status !== "skipped")
) {
throw new Error("Admin API answer trace step is invalid");
}
return {
...(typeof value.endedAt === "string" ? { endedAt: value.endedAt } : {}),
metadata: { ...value.metadata },
name,
startedAt,
status,
};
}
function parseTextDiffOperation(value: unknown): AdminTextDiffOperation {
if (!isRecord(value) || typeof value.text !== "string") {
throw new Error("Admin API KnowledgeFS diff operation is invalid");
}
if (value.kind !== "equal" && value.kind !== "insert" && value.kind !== "delete") {
throw new Error("Admin API KnowledgeFS diff operation kind is invalid");
}
return {
kind: value.kind,
...(value.newEnd === undefined ? {} : { newEnd: parsePositiveInteger(value.newEnd) }),
...(value.newStart === undefined ? {} : { newStart: parsePositiveInteger(value.newStart) }),
...(value.oldEnd === undefined ? {} : { oldEnd: parsePositiveInteger(value.oldEnd) }),
...(value.oldStart === undefined ? {} : { oldStart: parsePositiveInteger(value.oldStart) }),
text: value.text,
};
}
function parseTextDiffStats(value: Record<string, unknown>): AdminKnowledgeFsDiff["stats"] {
const deleteCount = value.delete;
const equal = value.equal;
const insert = value.insert;
if (
typeof deleteCount !== "number" ||
typeof equal !== "number" ||
typeof insert !== "number" ||
!Number.isInteger(deleteCount) ||
!Number.isInteger(equal) ||
!Number.isInteger(insert) ||
deleteCount < 0 ||
equal < 0 ||
insert < 0
) {
throw new Error("Admin API KnowledgeFS diff stats are invalid");
}
return {
delete: deleteCount,
equal,
insert,
};
}
function parseSemanticDiffSummary(value: unknown): AdminSemanticDiffSummary {
if (
!isRecord(value) ||
!Array.isArray(value.changes) ||
!isRecord(value.metadata) ||
typeof value.summary !== "string"
) {
throw new Error("Admin API semantic diff summary is invalid");
}
if (value.model !== undefined && typeof value.model !== "string") {
throw new Error("Admin API semantic diff model is invalid");
}
return {
changes: value.changes.map(parseSemanticDiffChange),
metadata: { ...value.metadata },
...(typeof value.model === "string" ? { model: value.model } : {}),
summary: value.summary,
};
}
function parseSemanticDiffChange(value: unknown): AdminSemanticDiffSummary["changes"][number] {
if (
!isRecord(value) ||
typeof value.category !== "string" ||
!Array.isArray(value.evidence) ||
typeof value.summary !== "string"
) {
throw new Error("Admin API semantic diff change is invalid");
}
return {
category: value.category,
evidence: parseStringArray(value.evidence, "Admin API semantic diff evidence is invalid"),
summary: value.summary,
};
}
function parseDocumentAsset(value: unknown): AdminDocumentAsset {
if (!isRecord(value)) {
throw new Error("Admin API document asset response is invalid");
}
const createdAt = value.createdAt;
const filename = value.filename;
const id = value.id;
const knowledgeSpaceId = value.knowledgeSpaceId;
const mimeType = value.mimeType;
const objectKey = value.objectKey;
const parserStatus = value.parserStatus;
const sha256 = value.sha256;
const sizeBytes = value.sizeBytes;
const version = value.version;
if (
typeof createdAt !== "string" ||
typeof filename !== "string" ||
typeof id !== "string" ||
typeof knowledgeSpaceId !== "string" ||
typeof mimeType !== "string" ||
typeof objectKey !== "string" ||
typeof sha256 !== "string"
) {
throw new Error("Admin API document asset response is invalid");
}
if (parserStatus !== "pending" && parserStatus !== "parsed" && parserStatus !== "failed") {
throw new Error("Admin API document asset parserStatus is invalid");
}
if (!isRecord(value.metadata)) {
throw new Error("Admin API document asset metadata is invalid");
}
if (!Number.isInteger(sizeBytes) || typeof sizeBytes !== "number" || sizeBytes < 0) {
throw new Error("Admin API document asset sizeBytes is invalid");
}
if (!Number.isInteger(version) || typeof version !== "number" || version < 1) {
throw new Error("Admin API document asset version is invalid");
}
return {
createdAt,
filename,
id,
knowledgeSpaceId,
metadata: { ...value.metadata },
mimeType,
objectKey,
parserStatus,
sha256,
sizeBytes,
...(typeof value.sourceId === "string" ? { sourceId: value.sourceId } : {}),
version,
};
}
function parseDocumentMultimodalManifest(value: unknown): AdminDocumentMultimodalManifest {
if (!isRecord(value) || !Array.isArray(value.items) || !isRecord(value.metadata)) {
throw new Error("Admin API document multimodal manifest response is invalid");
}
const artifactHash = value.artifactHash;
const createdAt = value.createdAt;
const documentAssetId = value.documentAssetId;
const id = value.id;
const knowledgeSpaceId = value.knowledgeSpaceId;
const manifestVersion = value.manifestVersion;
const parseArtifactId = value.parseArtifactId;
const version = value.version;
if (
typeof artifactHash !== "string" ||
typeof createdAt !== "string" ||
typeof documentAssetId !== "string" ||
typeof id !== "string" ||
typeof knowledgeSpaceId !== "string" ||
typeof manifestVersion !== "string" ||
typeof parseArtifactId !== "string" ||
!Number.isInteger(version) ||
typeof version !== "number" ||
version < 1
) {
throw new Error("Admin API document multimodal manifest response is invalid");
}
return {
artifactHash,
createdAt,
documentAssetId,
id,
items: value.items.map(parseDocumentMultimodalItem),
knowledgeSpaceId,
manifestVersion,
metadata: { ...value.metadata },
parseArtifactId,
...(typeof value.updatedAt === "string" ? { updatedAt: value.updatedAt } : {}),
version,
};
}
function parseDocumentMultimodalItem(value: unknown): AdminDocumentMultimodalItem {
if (!isRecord(value) || !isRecord(value.enrichment) || !Array.isArray(value.sectionPath)) {
throw new Error("Admin API document multimodal item is invalid");
}
const id = value.id;
const modality = value.modality;
const parseElementId = value.parseElementId;
if (
typeof id !== "string" ||
typeof parseElementId !== "string" ||
!isDocumentMultimodalModality(modality)
) {
throw new Error("Admin API document multimodal item is invalid");
}
return {
...(isRecord(value.assetRef)
? { assetRef: parseDocumentMultimodalAssetRef(value.assetRef) }
: {}),
...(isRecord(value.boundingBox)
? { boundingBox: parseDocumentMultimodalBoundingBox(value.boundingBox) }
: {}),
...(typeof value.caption === "string" ? { caption: value.caption } : {}),
...(typeof value.endOffset === "number" ? { endOffset: value.endOffset } : {}),
enrichment: parseStringRecord(value.enrichment),
id,
modality,
...(typeof value.ocrText === "string" ? { ocrText: value.ocrText } : {}),
...(typeof value.pageNumber === "number" ? { pageNumber: value.pageNumber } : {}),
parseElementId,
sectionPath: parseStringArray(value.sectionPath, "Admin API multimodal section path invalid"),
sourceMetadata: isRecord(value.sourceMetadata) ? { ...value.sourceMetadata } : {},
...(typeof value.startOffset === "number" ? { startOffset: value.startOffset } : {}),
...(typeof value.textPreview === "string" ? { textPreview: value.textPreview } : {}),
...(typeof value.title === "string" ? { title: value.title } : {}),
};
}
function parseDocumentMultimodalBoundingBox(
value: Readonly<Record<string, unknown>>,
): AdminDocumentMultimodalBoundingBox | undefined {
const height = value.height;
const width = value.width;
const x = value.x;
const y = value.y;
if (
typeof height !== "number" ||
typeof width !== "number" ||
typeof x !== "number" ||
typeof y !== "number"
) {
return undefined;
}
return { height, width, x, y };
}
function parseDocumentMultimodalAssetRef(
value: Readonly<Record<string, unknown>>,
): AdminDocumentMultimodalAssetRef {
return {
...(typeof value.contentType === "string" ? { contentType: value.contentType } : {}),
...(typeof value.objectKey === "string" ? { objectKey: value.objectKey } : {}),
...(typeof value.sha256 === "string" ? { sha256: value.sha256 } : {}),
...(typeof value.uri === "string" ? { uri: value.uri } : {}),
...(isRecord(value.variants)
? { variants: parseDocumentMultimodalAssetVariants(value.variants) }
: {}),
};
}
function parseDocumentMultimodalAssetVariants(
value: Readonly<Record<string, unknown>>,
): Readonly<Record<string, AdminDocumentMultimodalAssetVariant>> {
const variants: Record<string, AdminDocumentMultimodalAssetVariant> = {};
for (const [name, variant] of Object.entries(value)) {
if (!isRecord(variant)) {
continue;
}
variants[name] = {
...(typeof variant.contentType === "string" ? { contentType: variant.contentType } : {}),
...(typeof variant.height === "number" ? { height: variant.height } : {}),
...(typeof variant.objectKey === "string" ? { objectKey: variant.objectKey } : {}),
...(typeof variant.sha256 === "string" ? { sha256: variant.sha256 } : {}),
...(typeof variant.uri === "string" ? { uri: variant.uri } : {}),
...(typeof variant.width === "number" ? { width: variant.width } : {}),
};
}
return variants;
}
function isDocumentMultimodalModality(
value: unknown,
): value is AdminDocumentMultimodalItem["modality"] {
return value === "code" || value === "image" || value === "page" || value === "table";
}
function parseStringRecord(
value: Readonly<Record<string, unknown>>,
): Readonly<Record<string, string>> {
return Object.fromEntries(
Object.entries(value).filter(
(entry): entry is [string, string] => typeof entry[1] === "string",
),
);
}
function parseDocumentOutline(value: unknown): AdminDocumentOutline {
if (!isRecord(value) || !Array.isArray(value.nodes)) {
throw new Error("Admin API document outline response is invalid");
}
const artifactHash = value.artifactHash;
const createdAt = value.createdAt;
const documentAssetId = value.documentAssetId;
const id = value.id;
const knowledgeSpaceId = value.knowledgeSpaceId;
const outlineVersion = value.outlineVersion;
const parseArtifactId = value.parseArtifactId;
const version = value.version;
if (
typeof artifactHash !== "string" ||
typeof createdAt !== "string" ||
typeof documentAssetId !== "string" ||
typeof id !== "string" ||
typeof knowledgeSpaceId !== "string" ||
typeof outlineVersion !== "string" ||
typeof parseArtifactId !== "string"
) {
throw new Error("Admin API document outline response is invalid");
}
if (!isRecord(value.metadata)) {
throw new Error("Admin API document outline metadata is invalid");
}
if (!Number.isInteger(version) || typeof version !== "number" || version < 1) {
throw new Error("Admin API document outline version is invalid");
}
return {
artifactHash,
createdAt,
documentAssetId,
id,
knowledgeSpaceId,
metadata: { ...value.metadata },
nodes: value.nodes.map(parseDocumentOutlineNode),
outlineVersion,
parseArtifactId,
...(typeof value.updatedAt === "string" ? { updatedAt: value.updatedAt } : {}),
version,
};
}
function parseDocumentOutlineNode(value: unknown): AdminDocumentOutlineNode {
if (!isRecord(value) || !Array.isArray(value.children) || !isRecord(value.metadata)) {
throw new Error("Admin API document outline node is invalid");
}
const id = value.id;
const level = value.level;
const title = value.title;
const tocSource = value.tocSource;
if (
typeof id !== "string" ||
typeof title !== "string" ||
!Number.isInteger(level) ||
typeof level !== "number" ||
!isDocumentOutlineTocSource(tocSource)
) {
throw new Error("Admin API document outline node is invalid");
}
const childNodeIds = value.childNodeIds;
const children = value.children;
const sectionPath = value.sectionPath;
const sourceElementIds = value.sourceElementIds;
const sourceNodeIds = value.sourceNodeIds;
if (
!Array.isArray(childNodeIds) ||
!Array.isArray(children) ||
!Array.isArray(sectionPath) ||
!Array.isArray(sourceElementIds) ||
!Array.isArray(sourceNodeIds)
) {
throw new Error("Admin API document outline node arrays are invalid");
}
return {
childNodeIds: parseStringArray(childNodeIds, "Admin API outline child ids invalid"),
children: children.map(parseDocumentOutlineNode),
...(typeof value.endOffset === "number" ? { endOffset: value.endOffset } : {}),
...(typeof value.endPage === "number" ? { endPage: value.endPage } : {}),
id,
level,
metadata: { ...value.metadata },
sectionPath: parseStringArray(sectionPath, "Admin API outline section path invalid"),
sourceElementIds: parseStringArray(
sourceElementIds,
"Admin API outline source element ids invalid",
),
sourceNodeIds: parseStringArray(sourceNodeIds, "Admin API outline source node ids invalid"),
...(typeof value.startOffset === "number" ? { startOffset: value.startOffset } : {}),
...(typeof value.startPage === "number" ? { startPage: value.startPage } : {}),
...(typeof value.summary === "string" ? { summary: value.summary } : {}),
title,
...(value.titleLocation === undefined
? {}
: { titleLocation: parseDocumentOutlineTitleLocation(value.titleLocation) }),
tocSource,
};
}
function parseDocumentOutlineTitleLocation(value: unknown): AdminDocumentOutlineTitleLocation {
if (!isRecord(value) || !isDocumentOutlineTocSource(value.source)) {
throw new Error("Admin API document outline title location is invalid");
}
if (typeof value.confidence !== "number") {
throw new Error("Admin API document outline title location confidence is invalid");
}
return {
confidence: value.confidence,
...(typeof value.endOffset === "number" ? { endOffset: value.endOffset } : {}),
...(typeof value.matchedText === "string" ? { matchedText: value.matchedText } : {}),
...(typeof value.pageNumber === "number" ? { pageNumber: value.pageNumber } : {}),
source: value.source,
...(typeof value.startOffset === "number" ? { startOffset: value.startOffset } : {}),
};
}
function isDocumentOutlineTocSource(
value: unknown,
): value is AdminDocumentOutlineNode["tocSource"] {
return (
value === "fallback" ||
value === "llm-inferred" ||
value === "native-toc" ||
value === "parser-heading"
);
}
function parseDocumentAssetList(value: unknown): AdminDocumentAssetList {
if (!isRecord(value) || !Array.isArray(value.items)) {
throw new Error("Admin API document asset list response is invalid");
}
return {
items: value.items.map(parseDocumentAsset),
...(typeof value.nextCursor === "string" ? { nextCursor: value.nextCursor } : {}),
};
}
function parseSemanticTopicMaterializationResult(
value: unknown,
): AdminSemanticTopicMaterializationResult {
if (!isRecord(value)) {
throw new Error("Admin API semantic topic materialization response is invalid");
}
const documentCount = value.documentCount;
const generatedVersion = value.generatedVersion;
const knowledgeSpaceId = value.knowledgeSpaceId;
const pathCount = value.pathCount;
const topicName = value.topicName;
const topicSlug = value.topicSlug;
if (
!Number.isInteger(documentCount) ||
typeof documentCount !== "number" ||
!Number.isInteger(pathCount) ||
typeof pathCount !== "number" ||
typeof generatedVersion !== "string" ||
typeof knowledgeSpaceId !== "string" ||
typeof topicName !== "string" ||
typeof topicSlug !== "string"
) {
throw new Error("Admin API semantic topic materialization response is invalid");
}
return {
documentCount,
generatedVersion,
knowledgeSpaceId,
pathCount,
topicName,
topicSlug,
};
}
function parseSemanticCommunityMaterializationResult(
value: unknown,
): AdminSemanticCommunityMaterializationResult {
if (!isRecord(value)) {
throw new Error("Admin API semantic community materialization response is invalid");
}
const communityCount = value.communityCount;
const documentCount = value.documentCount;
const entityCount = value.entityCount;
const generatedVersion = value.generatedVersion;
const knowledgeSpaceId = value.knowledgeSpaceId;
const pathCount = value.pathCount;
if (
!Number.isInteger(communityCount) ||
typeof communityCount !== "number" ||
!Number.isInteger(documentCount) ||
typeof documentCount !== "number" ||
!Number.isInteger(entityCount) ||
typeof entityCount !== "number" ||
!Number.isInteger(pathCount) ||
typeof pathCount !== "number" ||
typeof generatedVersion !== "string" ||
typeof knowledgeSpaceId !== "string"
) {
throw new Error("Admin API semantic community materialization response is invalid");
}
return {
communityCount,
documentCount,
entityCount,
generatedVersion,
knowledgeSpaceId,
pathCount,
};
}
function parseSemanticEntityExtractionResult(value: unknown): AdminSemanticEntityExtractionResult {
if (!isRecord(value)) {
throw new Error("Admin API semantic entity extraction response is invalid");
}
const entitiesExtracted = value.entitiesExtracted;
const extractionMode = value.extractionMode;
const graphEntitiesIndexed = value.graphEntitiesIndexed;
const graphRelationsIndexed = value.graphRelationsIndexed;
const knowledgeSpaceId = value.knowledgeSpaceId;
const nodesScanned = value.nodesScanned;
const nodesUpdated = value.nodesUpdated;
if (
!Number.isInteger(entitiesExtracted) ||
typeof entitiesExtracted !== "number" ||
extractionMode !== "provider" ||
!Number.isInteger(graphEntitiesIndexed) ||
typeof graphEntitiesIndexed !== "number" ||
!Number.isInteger(graphRelationsIndexed) ||
typeof graphRelationsIndexed !== "number" ||
typeof knowledgeSpaceId !== "string" ||
!Number.isInteger(nodesScanned) ||
typeof nodesScanned !== "number" ||
!Number.isInteger(nodesUpdated) ||
typeof nodesUpdated !== "number"
) {
throw new Error("Admin API semantic entity extraction response is invalid");
}
return {
entitiesExtracted,
extractionMode,
graphEntitiesIndexed,
graphRelationsIndexed,
knowledgeSpaceId,
nodesScanned,
nodesUpdated,
};
}
function parseGraphTraversal(value: unknown): AdminGraphTraversal {
if (
!isRecord(value) ||
!Array.isArray(value.entities) ||
!Array.isArray(value.relations) ||
!isRecord(value.metrics) ||
typeof value.truncated !== "boolean"
) {
throw new Error("Admin API graph traversal response is invalid");
}
return {
entities: value.entities.map(parseGraphEntity),
metrics: parseGraphMetrics(value.metrics),
relations: value.relations.map(parseGraphRelation),
truncated: value.truncated,
};
}
function parseGraphEntity(value: unknown): AdminGraphEntity {
if (
!isRecord(value) ||
!Array.isArray(value.aliases) ||
!Array.isArray(value.permissionScope) ||
!Array.isArray(value.sourceNodeIds) ||
!isRecord(value.metadata)
) {
throw new Error("Admin API graph entity is invalid");
}
const canonicalKey = value.canonicalKey;
const confidence = value.confidence;
const createdAt = value.createdAt;
const depth = value.depth;
const extractionVersion = value.extractionVersion;
const id = value.id;
const knowledgeSpaceId = value.knowledgeSpaceId;
const name = value.name;
const type = value.type;
const updatedAt = value.updatedAt;
if (
typeof canonicalKey !== "string" ||
typeof confidence !== "number" ||
typeof createdAt !== "string" ||
typeof depth !== "number" ||
typeof extractionVersion !== "number" ||
typeof id !== "string" ||
typeof knowledgeSpaceId !== "string" ||
typeof name !== "string" ||
typeof updatedAt !== "string" ||
!isGraphEntityType(type)
) {
throw new Error("Admin API graph entity is invalid");
}
if (
!Number.isInteger(depth) ||
depth < 0 ||
!Number.isInteger(extractionVersion) ||
extractionVersion < 1
) {
throw new Error("Admin API graph entity numeric fields are invalid");
}
return {
aliases: parseStringArray(value.aliases, "Admin API graph entity aliases are invalid"),
canonicalKey,
confidence,
createdAt,
depth,
extractionVersion,
id,
knowledgeSpaceId,
metadata: { ...value.metadata },
name,
permissionScope: parseStringArray(
value.permissionScope,
"Admin API graph entity permissionScope is invalid",
),
sourceNodeIds: parseStringArray(
value.sourceNodeIds,
"Admin API graph entity sourceNodeIds are invalid",
),
type,
updatedAt,
};
}
function parseGraphRelation(value: unknown): AdminGraphRelation {
if (
!isRecord(value) ||
!Array.isArray(value.permissionScope) ||
!Array.isArray(value.sourceNodeIds) ||
!isRecord(value.metadata)
) {
throw new Error("Admin API graph relation is invalid");
}
const confidence = value.confidence;
const createdAt = value.createdAt;
const depth = value.depth;
const extractionVersion = value.extractionVersion;
const id = value.id;
const knowledgeSpaceId = value.knowledgeSpaceId;
const objectEntityId = value.objectEntityId;
const subjectEntityId = value.subjectEntityId;
const type = value.type;
const updatedAt = value.updatedAt;
if (
typeof confidence !== "number" ||
typeof createdAt !== "string" ||
typeof depth !== "number" ||
typeof extractionVersion !== "number" ||
typeof id !== "string" ||
typeof knowledgeSpaceId !== "string" ||
typeof objectEntityId !== "string" ||
typeof subjectEntityId !== "string" ||
typeof updatedAt !== "string" ||
!isGraphRelationType(type)
) {
throw new Error("Admin API graph relation is invalid");
}
if (
!Number.isInteger(depth) ||
depth < 1 ||
!Number.isInteger(extractionVersion) ||
extractionVersion < 1
) {
throw new Error("Admin API graph relation numeric fields are invalid");
}
return {
confidence,
createdAt,
depth,
extractionVersion,
id,
knowledgeSpaceId,
metadata: { ...value.metadata },
objectEntityId,
permissionScope: parseStringArray(
value.permissionScope,
"Admin API graph relation permissionScope is invalid",
),
sourceNodeIds: parseStringArray(
value.sourceNodeIds,
"Admin API graph relation sourceNodeIds are invalid",
),
subjectEntityId,
type,
updatedAt,
};
}
function parseGraphMetrics(value: Record<string, unknown>): AdminGraphTraversal["metrics"] {
const depthReached = value.depthReached;
const elapsedMs = value.elapsedMs;
const exploredRelations = value.exploredRelations;
const fanout = value.fanout;
const maxDepth = value.maxDepth;
const maxNodes = value.maxNodes;
const timedOut = value.timedOut;
if (
typeof depthReached !== "number" ||
typeof elapsedMs !== "number" ||
typeof exploredRelations !== "number" ||
typeof fanout !== "number" ||
typeof maxDepth !== "number" ||
typeof maxNodes !== "number" ||
!Number.isInteger(depthReached) ||
!Number.isInteger(exploredRelations) ||
!Number.isInteger(fanout) ||
!Number.isInteger(maxDepth) ||
!Number.isInteger(maxNodes) ||
typeof timedOut !== "boolean"
) {
throw new Error("Admin API graph traversal metrics are invalid");
}
return {
depthReached,
elapsedMs,
exploredRelations,
fanout,
maxDepth,
maxNodes,
timedOut,
};
}
function isGraphEntityType(value: unknown): value is AdminGraphEntityType {
return (
value === "date" ||
value === "metric" ||
value === "organization" ||
value === "person" ||
value === "policy" ||
value === "product" ||
value === "term"
);
}
function isGraphRelationType(value: unknown): value is AdminGraphRelationType {
return (
value === "contradicts" ||
value === "defines" ||
value === "depends_on" ||
value === "mentions" ||
value === "references" ||
value === "supersedes"
);
}
function parseParseArtifact(value: unknown): AdminParseArtifact {
if (!isRecord(value) || !Array.isArray(value.elements) || !isRecord(value.metadata)) {
throw new Error("Admin API parse artifact response is invalid");
}
const artifactHash = value.artifactHash;
const contentType = value.contentType;
const createdAt = value.createdAt;
const documentAssetId = value.documentAssetId;
const id = value.id;
const parser = value.parser;
const version = value.version;
if (
typeof artifactHash !== "string" ||
typeof createdAt !== "string" ||
typeof documentAssetId !== "string" ||
typeof id !== "string"
) {
throw new Error("Admin API parse artifact response is invalid");
}
if (contentType !== "text" && contentType !== "structured" && contentType !== "mixed") {
throw new Error("Admin API parse artifact contentType is invalid");
}
if (
parser !== "native-markdown" &&
parser !== "native-html" &&
parser !== "native-structured" &&
parser !== "unstructured"
) {
throw new Error("Admin API parse artifact parser is invalid");
}
if (!Number.isInteger(version) || typeof version !== "number" || version < 1) {
throw new Error("Admin API parse artifact version is invalid");
}
return {
artifactHash,
contentType,
createdAt,
documentAssetId,
elements: value.elements.map(parseParseElement),
id,
metadata: { ...value.metadata },
parser,
version,
};
}
function parseParseElement(value: unknown): AdminParseElement {
if (!isRecord(value) || typeof value.id !== "string" || !isRecord(value.metadata)) {
throw new Error("Admin API parse element is invalid");
}
if (
value.type !== "title" &&
value.type !== "heading" &&
value.type !== "paragraph" &&
value.type !== "table" &&
value.type !== "list" &&
value.type !== "image" &&
value.type !== "code" &&
value.type !== "page-break"
) {
throw new Error("Admin API parse element type is invalid");
}
if (
!Array.isArray(value.sectionPath) ||
value.sectionPath.some((section) => typeof section !== "string")
) {
throw new Error("Admin API parse element sectionPath is invalid");
}
const pageNumber = value.pageNumber;
if (
pageNumber !== undefined &&
(typeof pageNumber !== "number" || !Number.isInteger(pageNumber) || pageNumber < 1)
) {
throw new Error("Admin API parse element pageNumber is invalid");
}
if (value.text !== undefined && typeof value.text !== "string") {
throw new Error("Admin API parse element text is invalid");
}
return {
id: value.id,
metadata: { ...value.metadata },
...(typeof pageNumber === "number" ? { pageNumber } : {}),
sectionPath: [...value.sectionPath],
...(typeof value.text === "string" ? { text: value.text } : {}),
type: value.type,
};
}
function parseStringArray(value: readonly unknown[], errorMessage: string): string[] {
if (value.some((item) => typeof item !== "string")) {
throw new Error(errorMessage);
}
return [...value] as string[];
}
function parsePositiveInteger(value: unknown): number {
if (typeof value !== "number" || !Number.isInteger(value) || value < 1) {
throw new Error("Admin API positive integer field is invalid");
}
return value;
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function isNumberRecord(value: unknown): value is Record<string, number> {
return isRecord(value) && Object.values(value).every((item) => typeof item === "number");
}