@babav/knowledge-core-client 0.38.1 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +76 -6
- package/dist/index.js +33 -3
- package/package.json +1 -1
- package/src/index.ts +87 -8
package/dist/index.d.ts
CHANGED
|
@@ -211,6 +211,40 @@ export interface Corpus {
|
|
|
211
211
|
name: string;
|
|
212
212
|
description: string | null;
|
|
213
213
|
custom_metadata: Record<string, unknown>;
|
|
214
|
+
profile_id: UUID | null;
|
|
215
|
+
}
|
|
216
|
+
/** Build-time knob bundle that DEFINES an index. Defaults are today's blessed config, so a
|
|
217
|
+
* profile created with no params is the blessed profile. Change any knob => different vectors
|
|
218
|
+
* => a different physical collection. Embedding/indexing/chunking is SYSTEM-level, never a
|
|
219
|
+
* query knob — this is the build-side counterpart to an Agent, not an agent. */
|
|
220
|
+
export interface IngestionProfileParams {
|
|
221
|
+
chunker: string;
|
|
222
|
+
chunk_child_max_tokens: number;
|
|
223
|
+
chunk_parent_max_tokens: number;
|
|
224
|
+
contextualize: boolean;
|
|
225
|
+
embedding_provider: string;
|
|
226
|
+
embedding_model: string;
|
|
227
|
+
embedding_dimensions: number;
|
|
228
|
+
distance: string;
|
|
229
|
+
sparse: boolean;
|
|
230
|
+
quantization: string;
|
|
231
|
+
hnsw_m: number | null;
|
|
232
|
+
hnsw_ef_construct: number | null;
|
|
233
|
+
}
|
|
234
|
+
export interface IngestionProfile {
|
|
235
|
+
id: UUID;
|
|
236
|
+
tenant_id: UUID;
|
|
237
|
+
name: string;
|
|
238
|
+
params: IngestionProfileParams;
|
|
239
|
+
fingerprint: string;
|
|
240
|
+
is_default: boolean;
|
|
241
|
+
}
|
|
242
|
+
/** Fields settable when creating/updating a profile. `params` may be partial on create
|
|
243
|
+
* (omitted knobs take the blessed default). The owning tenant is the key's — never in the body. */
|
|
244
|
+
export interface IngestionProfileWrite {
|
|
245
|
+
name?: string;
|
|
246
|
+
params?: Partial<IngestionProfileParams>;
|
|
247
|
+
is_default?: boolean;
|
|
214
248
|
}
|
|
215
249
|
export interface Folder {
|
|
216
250
|
id: UUID;
|
|
@@ -342,16 +376,22 @@ export interface ChunkHeat {
|
|
|
342
376
|
bbox: [number, number, number, number];
|
|
343
377
|
}[] | null;
|
|
344
378
|
}
|
|
345
|
-
/** Everything to overlay retrieval heat on the original document
|
|
346
|
-
*
|
|
379
|
+
/** Everything to overlay retrieval heat on the original document. Fetch the view-PDF BYTES
|
|
380
|
+
* via `analytics.documentViewPdf(id)` from YOUR BACKEND (KC serves them; the browser never
|
|
381
|
+
* touches GCS), render with pdf.js, and shade chunks by heat. `insufficient_data` (with
|
|
382
|
+
* `retrieval_events` as the sample size) is the document-level analogue of the corpus heat
|
|
383
|
+
* view's insufficient_data band — show a clear "not enough data yet" indication instead of
|
|
384
|
+
* misleading shading when it's true. */
|
|
347
385
|
export interface ChunkHeatmapResponse {
|
|
348
386
|
document_id: UUID;
|
|
349
|
-
|
|
387
|
+
has_view_pdf: boolean;
|
|
350
388
|
page_dims: {
|
|
351
389
|
w: number;
|
|
352
390
|
h: number;
|
|
353
391
|
rotation: number;
|
|
354
392
|
}[] | null;
|
|
393
|
+
retrieval_events: number;
|
|
394
|
+
insufficient_data: boolean;
|
|
355
395
|
chunks: ChunkHeat[];
|
|
356
396
|
}
|
|
357
397
|
export interface MonthlyCorpus {
|
|
@@ -563,6 +603,8 @@ declare class HttpBase {
|
|
|
563
603
|
protected url(path: string, query?: RequestOpts["query"]): string;
|
|
564
604
|
protected raw(method: string, path: string, opts?: RequestOpts): Promise<Response>;
|
|
565
605
|
protected request<T>(method: string, path: string, opts?: RequestOpts): Promise<T>;
|
|
606
|
+
/** GET binary bytes as a Blob (error bodies are JSON, so decode+throw on !ok). */
|
|
607
|
+
protected rawBytes(method: string, path: string, signal?: AbortSignal): Promise<Blob>;
|
|
566
608
|
/** Auto-paginate a list endpoint into a single array. */
|
|
567
609
|
protected pageAll<T>(path: string, query?: RequestOpts["query"]): Promise<T[]>;
|
|
568
610
|
}
|
|
@@ -673,6 +715,7 @@ export declare class KnowledgeCoreClient extends HttpBase {
|
|
|
673
715
|
name: string;
|
|
674
716
|
description?: string;
|
|
675
717
|
custom_metadata?: Record<string, unknown>;
|
|
718
|
+
profile_id?: UUID;
|
|
676
719
|
}) => Promise<Corpus>;
|
|
677
720
|
list: (q?: {
|
|
678
721
|
limit?: number;
|
|
@@ -686,11 +729,13 @@ export declare class KnowledgeCoreClient extends HttpBase {
|
|
|
686
729
|
cursor?: string;
|
|
687
730
|
}) => Promise<Page<Corpus>>;
|
|
688
731
|
get: (id: UUID) => Promise<Corpus>;
|
|
689
|
-
/** `custom_metadata` merges (provided keys upsert, a null value deletes a key).
|
|
732
|
+
/** `custom_metadata` merges (provided keys upsert, a null value deletes a key). `profile_id`
|
|
733
|
+
* reassigns the ingestion profile (does NOT re-index; applies on next (re)ingest). */
|
|
690
734
|
update: (id: UUID, b: {
|
|
691
735
|
name?: string;
|
|
692
736
|
description?: string;
|
|
693
737
|
custom_metadata?: Record<string, unknown>;
|
|
738
|
+
profile_id?: UUID | null;
|
|
694
739
|
}) => Promise<Corpus>;
|
|
695
740
|
delete: (id: UUID, confirmName: string) => Promise<void>;
|
|
696
741
|
listFolders: (id: UUID) => Promise<Folder[]>;
|
|
@@ -940,6 +985,25 @@ export declare class KnowledgeCoreClient extends HttpBase {
|
|
|
940
985
|
* capabilities (`supports_reasoning`), and mode↔model dependencies. */
|
|
941
986
|
modelOptions: () => Promise<ModelOptions>;
|
|
942
987
|
};
|
|
988
|
+
/** Ingestion profiles — the build-side config object (counterpart to `agents`). A profile
|
|
989
|
+
* DEFINES an index (chunking + embedding + sparse + quant); its `fingerprint` is the physical
|
|
990
|
+
* collection identity. Attach one to a corpus via `corpora.create/update({ profile_id })`. */
|
|
991
|
+
profiles: {
|
|
992
|
+
/** List this tenant's ingestion profiles. */
|
|
993
|
+
list: (q?: {
|
|
994
|
+
limit?: number;
|
|
995
|
+
cursor?: string;
|
|
996
|
+
}) => Promise<Page<IngestionProfile>>;
|
|
997
|
+
listAll: () => Promise<IngestionProfile[]>;
|
|
998
|
+
get: (id: UUID) => Promise<IngestionProfile>;
|
|
999
|
+
/** Create a profile owned by this tenant. Omit `params` for the blessed profile (all defaults). */
|
|
1000
|
+
create: (b: IngestionProfileWrite & {
|
|
1001
|
+
name: string;
|
|
1002
|
+
}) => Promise<IngestionProfile>;
|
|
1003
|
+
update: (id: UUID, b: IngestionProfileWrite) => Promise<IngestionProfile>;
|
|
1004
|
+
/** Delete a profile. 409 if any corpus still references it. */
|
|
1005
|
+
delete: (id: UUID) => Promise<void>;
|
|
1006
|
+
};
|
|
943
1007
|
analytics: {
|
|
944
1008
|
/** Query-volume time series for a corpus (the denominator for everything). */
|
|
945
1009
|
corpusUsage: (corpusId: UUID, q?: {
|
|
@@ -962,9 +1026,15 @@ export declare class KnowledgeCoreClient extends HttpBase {
|
|
|
962
1026
|
document: (documentId: UUID) => Promise<DocumentAnalytics>;
|
|
963
1027
|
/** Parent-section grain for a document (never exposes chunk ids). */
|
|
964
1028
|
documentSections: (documentId: UUID) => Promise<SectionsResponse>;
|
|
965
|
-
/** Per-chunk retrieval heat + position
|
|
966
|
-
*
|
|
1029
|
+
/** Per-chunk retrieval heat + position + `has_view_pdf` + the `insufficient_data`
|
|
1030
|
+
* indication — everything to overlay heat on the ORIGINAL document with pdf.js. Fetch the
|
|
1031
|
+
* view-PDF bytes with `documentViewPdf(id)` (below). */
|
|
967
1032
|
documentChunks: (documentId: UUID) => Promise<ChunkHeatmapResponse>;
|
|
1033
|
+
/** Fetch the document's canonical view-PDF BYTES (the surface for the heat overlay).
|
|
1034
|
+
* Call this from YOUR BACKEND — KC serves the bytes, so the browser never fetches from
|
|
1035
|
+
* GCS (no bucket CORS). Returns a Blob (Node: `Buffer.from(await blob.arrayBuffer())`;
|
|
1036
|
+
* browser: `URL.createObjectURL(blob)`). Rejects 404 when `has_view_pdf` is false. */
|
|
1037
|
+
documentViewPdf: (documentId: UUID, signal?: AbortSignal) => Promise<Blob>;
|
|
968
1038
|
/** Whole-corpus scatter payload: every document with x=retrieved_reach, y=conversion,
|
|
969
1039
|
* bubble=chunk_count, and a server-computed quadrant. No pagination (`truncated` if capped). */
|
|
970
1040
|
corpusScatter: (corpusId: UUID) => Promise<ScatterResponse>;
|
package/dist/index.js
CHANGED
|
@@ -102,6 +102,15 @@ class HttpBase {
|
|
|
102
102
|
throw new KnowledgeCoreError(res.status, parsed ?? text, path);
|
|
103
103
|
return parsed;
|
|
104
104
|
}
|
|
105
|
+
/** GET binary bytes as a Blob (error bodies are JSON, so decode+throw on !ok). */
|
|
106
|
+
async rawBytes(method, path, signal) {
|
|
107
|
+
const res = await this.raw(method, path, { signal });
|
|
108
|
+
if (!res.ok) {
|
|
109
|
+
const t = await res.text();
|
|
110
|
+
throw new KnowledgeCoreError(res.status, safeJson(t), path);
|
|
111
|
+
}
|
|
112
|
+
return await res.blob();
|
|
113
|
+
}
|
|
105
114
|
/** Auto-paginate a list endpoint into a single array. */
|
|
106
115
|
async pageAll(path, query = {}) {
|
|
107
116
|
const out = [];
|
|
@@ -259,7 +268,8 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
259
268
|
/** Filter corpora by custom_metadata using the same metadata filter as documents. */
|
|
260
269
|
search: (b) => this.request("POST", "/v1/corpora/search", { json: b }),
|
|
261
270
|
get: (id) => this.request("GET", `/v1/corpora/${id}`),
|
|
262
|
-
/** `custom_metadata` merges (provided keys upsert, a null value deletes a key).
|
|
271
|
+
/** `custom_metadata` merges (provided keys upsert, a null value deletes a key). `profile_id`
|
|
272
|
+
* reassigns the ingestion profile (does NOT re-index; applies on next (re)ingest). */
|
|
263
273
|
update: (id, b) => this.request("PATCH", `/v1/corpora/${id}`, { json: b }),
|
|
264
274
|
delete: (id, confirmName) => this.request("DELETE", `/v1/corpora/${id}`, { query: { confirm: confirmName } }),
|
|
265
275
|
listFolders: (id) => this.pageAll(`/v1/corpora/${id}/folders`),
|
|
@@ -458,6 +468,20 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
458
468
|
* capabilities (`supports_reasoning`), and mode↔model dependencies. */
|
|
459
469
|
modelOptions: () => this.request("GET", "/v1/agents/model-options"),
|
|
460
470
|
};
|
|
471
|
+
/** Ingestion profiles — the build-side config object (counterpart to `agents`). A profile
|
|
472
|
+
* DEFINES an index (chunking + embedding + sparse + quant); its `fingerprint` is the physical
|
|
473
|
+
* collection identity. Attach one to a corpus via `corpora.create/update({ profile_id })`. */
|
|
474
|
+
profiles = {
|
|
475
|
+
/** List this tenant's ingestion profiles. */
|
|
476
|
+
list: (q) => this.request("GET", "/v1/profiles", { query: q }),
|
|
477
|
+
listAll: () => this.pageAll("/v1/profiles"),
|
|
478
|
+
get: (id) => this.request("GET", `/v1/profiles/${id}`),
|
|
479
|
+
/** Create a profile owned by this tenant. Omit `params` for the blessed profile (all defaults). */
|
|
480
|
+
create: (b) => this.request("POST", "/v1/profiles", { json: b }),
|
|
481
|
+
update: (id, b) => this.request("PATCH", `/v1/profiles/${id}`, { json: b }),
|
|
482
|
+
/** Delete a profile. 409 if any corpus still references it. */
|
|
483
|
+
delete: (id) => this.request("DELETE", `/v1/profiles/${id}`),
|
|
484
|
+
};
|
|
461
485
|
// --- retrieval analytics (read-only, tenant-scoped, aggregate-on-read) ---
|
|
462
486
|
analytics = {
|
|
463
487
|
/** Query-volume time series for a corpus (the denominator for everything). */
|
|
@@ -468,9 +492,15 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
468
492
|
document: (documentId) => this.request("GET", `/v1/analytics/documents/${documentId}`),
|
|
469
493
|
/** Parent-section grain for a document (never exposes chunk ids). */
|
|
470
494
|
documentSections: (documentId) => this.request("GET", `/v1/analytics/documents/${documentId}/sections`),
|
|
471
|
-
/** Per-chunk retrieval heat + position
|
|
472
|
-
*
|
|
495
|
+
/** Per-chunk retrieval heat + position + `has_view_pdf` + the `insufficient_data`
|
|
496
|
+
* indication — everything to overlay heat on the ORIGINAL document with pdf.js. Fetch the
|
|
497
|
+
* view-PDF bytes with `documentViewPdf(id)` (below). */
|
|
473
498
|
documentChunks: (documentId) => this.request("GET", `/v1/analytics/documents/${documentId}/chunks`),
|
|
499
|
+
/** Fetch the document's canonical view-PDF BYTES (the surface for the heat overlay).
|
|
500
|
+
* Call this from YOUR BACKEND — KC serves the bytes, so the browser never fetches from
|
|
501
|
+
* GCS (no bucket CORS). Returns a Blob (Node: `Buffer.from(await blob.arrayBuffer())`;
|
|
502
|
+
* browser: `URL.createObjectURL(blob)`). Rejects 404 when `has_view_pdf` is false. */
|
|
503
|
+
documentViewPdf: (documentId, signal) => this.rawBytes("GET", `/v1/analytics/documents/${documentId}/view-pdf`, signal),
|
|
474
504
|
/** Whole-corpus scatter payload: every document with x=retrieved_reach, y=conversion,
|
|
475
505
|
* bubble=chunk_count, and a server-computed quadrant. No pagination (`truncated` if capped). */
|
|
476
506
|
corpusScatter: (corpusId) => this.request("GET", `/v1/analytics/corpora/${corpusId}/scatter`),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@babav/knowledge-core-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.0",
|
|
4
4
|
"description": "TypeScript client for the Babav Knowledge Core API (Deno + Node 18+, zero deps). Includes the babav.visual grammar TYPES at the ./visual subpath (types only; all visual rendering is server-side).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
package/src/index.ts
CHANGED
|
@@ -244,6 +244,43 @@ export interface Corpus {
|
|
|
244
244
|
name: string;
|
|
245
245
|
description: string | null;
|
|
246
246
|
custom_metadata: Record<string, unknown>;
|
|
247
|
+
profile_id: UUID | null; // ingestion profile the corpus is indexed under (null => tenant's blessed default)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** Build-time knob bundle that DEFINES an index. Defaults are today's blessed config, so a
|
|
251
|
+
* profile created with no params is the blessed profile. Change any knob => different vectors
|
|
252
|
+
* => a different physical collection. Embedding/indexing/chunking is SYSTEM-level, never a
|
|
253
|
+
* query knob — this is the build-side counterpart to an Agent, not an agent. */
|
|
254
|
+
export interface IngestionProfileParams {
|
|
255
|
+
chunker: string; // "hybrid"
|
|
256
|
+
chunk_child_max_tokens: number;
|
|
257
|
+
chunk_parent_max_tokens: number;
|
|
258
|
+
contextualize: boolean;
|
|
259
|
+
embedding_provider: string; // "voyage_context" | "voyage" | "gemini"
|
|
260
|
+
embedding_model: string;
|
|
261
|
+
embedding_dimensions: number;
|
|
262
|
+
distance: string; // "cosine" | "dot" | "euclid"
|
|
263
|
+
sparse: boolean;
|
|
264
|
+
quantization: string; // "int8" | "none"
|
|
265
|
+
hnsw_m: number | null; // null => Qdrant default
|
|
266
|
+
hnsw_ef_construct: number | null; // null => Qdrant default
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export interface IngestionProfile {
|
|
270
|
+
id: UUID;
|
|
271
|
+
tenant_id: UUID; // owning tenant (every profile belongs to one; no globals)
|
|
272
|
+
name: string;
|
|
273
|
+
params: IngestionProfileParams;
|
|
274
|
+
fingerprint: string; // stable hash of params — the physical collection identity
|
|
275
|
+
is_default: boolean; // at most one blessed profile per tenant
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/** Fields settable when creating/updating a profile. `params` may be partial on create
|
|
279
|
+
* (omitted knobs take the blessed default). The owning tenant is the key's — never in the body. */
|
|
280
|
+
export interface IngestionProfileWrite {
|
|
281
|
+
name?: string;
|
|
282
|
+
params?: Partial<IngestionProfileParams>;
|
|
283
|
+
is_default?: boolean;
|
|
247
284
|
}
|
|
248
285
|
export interface Folder {
|
|
249
286
|
id: UUID;
|
|
@@ -346,12 +383,18 @@ export interface ChunkHeat {
|
|
|
346
383
|
method: string | null;
|
|
347
384
|
regions: { page: number; bbox: [number, number, number, number] }[] | null;
|
|
348
385
|
}
|
|
349
|
-
/** Everything to overlay retrieval heat on the original document
|
|
350
|
-
*
|
|
386
|
+
/** Everything to overlay retrieval heat on the original document. Fetch the view-PDF BYTES
|
|
387
|
+
* via `analytics.documentViewPdf(id)` from YOUR BACKEND (KC serves them; the browser never
|
|
388
|
+
* touches GCS), render with pdf.js, and shade chunks by heat. `insufficient_data` (with
|
|
389
|
+
* `retrieval_events` as the sample size) is the document-level analogue of the corpus heat
|
|
390
|
+
* view's insufficient_data band — show a clear "not enough data yet" indication instead of
|
|
391
|
+
* misleading shading when it's true. */
|
|
351
392
|
export interface ChunkHeatmapResponse {
|
|
352
393
|
document_id: UUID;
|
|
353
|
-
|
|
394
|
+
has_view_pdf: boolean; // a view-PDF exists -> fetch bytes with analytics.documentViewPdf(id)
|
|
354
395
|
page_dims: { w: number; h: number; rotation: number }[] | null;
|
|
396
|
+
retrieval_events: number; // distinct retrievals this doc appeared in (heat sample size)
|
|
397
|
+
insufficient_data: boolean; // too few retrievals to trust per-chunk heat yet
|
|
355
398
|
chunks: ChunkHeat[];
|
|
356
399
|
}
|
|
357
400
|
export interface MonthlyCorpus {
|
|
@@ -589,6 +632,16 @@ class HttpBase {
|
|
|
589
632
|
return parsed as T;
|
|
590
633
|
}
|
|
591
634
|
|
|
635
|
+
/** GET binary bytes as a Blob (error bodies are JSON, so decode+throw on !ok). */
|
|
636
|
+
protected async rawBytes(method: string, path: string, signal?: AbortSignal): Promise<Blob> {
|
|
637
|
+
const res = await this.raw(method, path, { signal });
|
|
638
|
+
if (!res.ok) {
|
|
639
|
+
const t = await res.text();
|
|
640
|
+
throw new KnowledgeCoreError(res.status, safeJson(t), path);
|
|
641
|
+
}
|
|
642
|
+
return await res.blob();
|
|
643
|
+
}
|
|
644
|
+
|
|
592
645
|
/** Auto-paginate a list endpoint into a single array. */
|
|
593
646
|
protected async pageAll<T>(path: string, query: RequestOpts["query"] = {}): Promise<T[]> {
|
|
594
647
|
const out: T[] = [];
|
|
@@ -803,7 +856,7 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
803
856
|
|
|
804
857
|
// --- corpora ---
|
|
805
858
|
corpora = {
|
|
806
|
-
create: (b: { name: string; description?: string; custom_metadata?: Record<string, unknown
|
|
859
|
+
create: (b: { name: string; description?: string; custom_metadata?: Record<string, unknown>; profile_id?: UUID }) =>
|
|
807
860
|
this.request<Corpus>("POST", "/v1/corpora", { json: b }),
|
|
808
861
|
list: (q?: { limit?: number; cursor?: string }) => this.request<Page<Corpus>>("GET", "/v1/corpora", { query: q }),
|
|
809
862
|
listAll: () => this.pageAll<Corpus>("/v1/corpora"),
|
|
@@ -811,8 +864,9 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
811
864
|
search: (b: { filter?: MetadataFilter; limit?: number; cursor?: string }) =>
|
|
812
865
|
this.request<Page<Corpus>>("POST", "/v1/corpora/search", { json: b }),
|
|
813
866
|
get: (id: UUID) => this.request<Corpus>("GET", `/v1/corpora/${id}`),
|
|
814
|
-
/** `custom_metadata` merges (provided keys upsert, a null value deletes a key).
|
|
815
|
-
|
|
867
|
+
/** `custom_metadata` merges (provided keys upsert, a null value deletes a key). `profile_id`
|
|
868
|
+
* reassigns the ingestion profile (does NOT re-index; applies on next (re)ingest). */
|
|
869
|
+
update: (id: UUID, b: { name?: string; description?: string; custom_metadata?: Record<string, unknown>; profile_id?: UUID | null }) =>
|
|
816
870
|
this.request<Corpus>("PATCH", `/v1/corpora/${id}`, { json: b }),
|
|
817
871
|
delete: (id: UUID, confirmName: string) => this.request<void>("DELETE", `/v1/corpora/${id}`, { query: { confirm: confirmName } }),
|
|
818
872
|
listFolders: (id: UUID) => this.pageAll<Folder>(`/v1/corpora/${id}/folders`),
|
|
@@ -1076,6 +1130,24 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
1076
1130
|
modelOptions: () => this.request<ModelOptions>("GET", "/v1/agents/model-options"),
|
|
1077
1131
|
};
|
|
1078
1132
|
|
|
1133
|
+
/** Ingestion profiles — the build-side config object (counterpart to `agents`). A profile
|
|
1134
|
+
* DEFINES an index (chunking + embedding + sparse + quant); its `fingerprint` is the physical
|
|
1135
|
+
* collection identity. Attach one to a corpus via `corpora.create/update({ profile_id })`. */
|
|
1136
|
+
profiles = {
|
|
1137
|
+
/** List this tenant's ingestion profiles. */
|
|
1138
|
+
list: (q?: { limit?: number; cursor?: string }) =>
|
|
1139
|
+
this.request<Page<IngestionProfile>>("GET", "/v1/profiles", { query: q }),
|
|
1140
|
+
listAll: () => this.pageAll<IngestionProfile>("/v1/profiles"),
|
|
1141
|
+
get: (id: UUID) => this.request<IngestionProfile>("GET", `/v1/profiles/${id}`),
|
|
1142
|
+
/** Create a profile owned by this tenant. Omit `params` for the blessed profile (all defaults). */
|
|
1143
|
+
create: (b: IngestionProfileWrite & { name: string }) =>
|
|
1144
|
+
this.request<IngestionProfile>("POST", "/v1/profiles", { json: b }),
|
|
1145
|
+
update: (id: UUID, b: IngestionProfileWrite) =>
|
|
1146
|
+
this.request<IngestionProfile>("PATCH", `/v1/profiles/${id}`, { json: b }),
|
|
1147
|
+
/** Delete a profile. 409 if any corpus still references it. */
|
|
1148
|
+
delete: (id: UUID) => this.request<void>("DELETE", `/v1/profiles/${id}`),
|
|
1149
|
+
};
|
|
1150
|
+
|
|
1079
1151
|
// --- retrieval analytics (read-only, tenant-scoped, aggregate-on-read) ---
|
|
1080
1152
|
analytics = {
|
|
1081
1153
|
/** Query-volume time series for a corpus (the denominator for everything). */
|
|
@@ -1088,9 +1160,16 @@ export class KnowledgeCoreClient extends HttpBase {
|
|
|
1088
1160
|
document: (documentId: UUID) => this.request<DocumentAnalytics>("GET", `/v1/analytics/documents/${documentId}`),
|
|
1089
1161
|
/** Parent-section grain for a document (never exposes chunk ids). */
|
|
1090
1162
|
documentSections: (documentId: UUID) => this.request<SectionsResponse>("GET", `/v1/analytics/documents/${documentId}/sections`),
|
|
1091
|
-
/** Per-chunk retrieval heat + position
|
|
1092
|
-
*
|
|
1163
|
+
/** Per-chunk retrieval heat + position + `has_view_pdf` + the `insufficient_data`
|
|
1164
|
+
* indication — everything to overlay heat on the ORIGINAL document with pdf.js. Fetch the
|
|
1165
|
+
* view-PDF bytes with `documentViewPdf(id)` (below). */
|
|
1093
1166
|
documentChunks: (documentId: UUID) => this.request<ChunkHeatmapResponse>("GET", `/v1/analytics/documents/${documentId}/chunks`),
|
|
1167
|
+
/** Fetch the document's canonical view-PDF BYTES (the surface for the heat overlay).
|
|
1168
|
+
* Call this from YOUR BACKEND — KC serves the bytes, so the browser never fetches from
|
|
1169
|
+
* GCS (no bucket CORS). Returns a Blob (Node: `Buffer.from(await blob.arrayBuffer())`;
|
|
1170
|
+
* browser: `URL.createObjectURL(blob)`). Rejects 404 when `has_view_pdf` is false. */
|
|
1171
|
+
documentViewPdf: (documentId: UUID, signal?: AbortSignal): Promise<Blob> =>
|
|
1172
|
+
this.rawBytes("GET", `/v1/analytics/documents/${documentId}/view-pdf`, signal),
|
|
1094
1173
|
/** Whole-corpus scatter payload: every document with x=retrieved_reach, y=conversion,
|
|
1095
1174
|
* bubble=chunk_count, and a server-computed quadrant. No pagination (`truncated` if capped). */
|
|
1096
1175
|
corpusScatter: (corpusId: UUID) => this.request<ScatterResponse>("GET", `/v1/analytics/corpora/${corpusId}/scatter`),
|