@babav/knowledge-core-client 0.38.1 → 0.39.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 CHANGED
@@ -342,16 +342,22 @@ export interface ChunkHeat {
342
342
  bbox: [number, number, number, number];
343
343
  }[] | null;
344
344
  }
345
- /** Everything to overlay retrieval heat on the original document: a signed view-PDF URL
346
- * (render with pdf.js), its per-page geometry, and every chunk's heat + boxes. */
345
+ /** Everything to overlay retrieval heat on the original document. Fetch the view-PDF BYTES
346
+ * via `analytics.documentViewPdf(id)` from YOUR BACKEND (KC serves them; the browser never
347
+ * touches GCS), render with pdf.js, and shade chunks by heat. `insufficient_data` (with
348
+ * `retrieval_events` as the sample size) is the document-level analogue of the corpus heat
349
+ * view's insufficient_data band — show a clear "not enough data yet" indication instead of
350
+ * misleading shading when it's true. */
347
351
  export interface ChunkHeatmapResponse {
348
352
  document_id: UUID;
349
- view_pdf_url: string | null;
353
+ has_view_pdf: boolean;
350
354
  page_dims: {
351
355
  w: number;
352
356
  h: number;
353
357
  rotation: number;
354
358
  }[] | null;
359
+ retrieval_events: number;
360
+ insufficient_data: boolean;
355
361
  chunks: ChunkHeat[];
356
362
  }
357
363
  export interface MonthlyCorpus {
@@ -563,6 +569,8 @@ declare class HttpBase {
563
569
  protected url(path: string, query?: RequestOpts["query"]): string;
564
570
  protected raw(method: string, path: string, opts?: RequestOpts): Promise<Response>;
565
571
  protected request<T>(method: string, path: string, opts?: RequestOpts): Promise<T>;
572
+ /** GET binary bytes as a Blob (error bodies are JSON, so decode+throw on !ok). */
573
+ protected rawBytes(method: string, path: string, signal?: AbortSignal): Promise<Blob>;
566
574
  /** Auto-paginate a list endpoint into a single array. */
567
575
  protected pageAll<T>(path: string, query?: RequestOpts["query"]): Promise<T[]>;
568
576
  }
@@ -962,9 +970,15 @@ export declare class KnowledgeCoreClient extends HttpBase {
962
970
  document: (documentId: UUID) => Promise<DocumentAnalytics>;
963
971
  /** Parent-section grain for a document (never exposes chunk ids). */
964
972
  documentSections: (documentId: UUID) => Promise<SectionsResponse>;
965
- /** Per-chunk retrieval heat + position in the document's view-PDF, plus a signed
966
- * view-PDF URL — everything to overlay heat on the ORIGINAL document with pdf.js. */
973
+ /** Per-chunk retrieval heat + position + `has_view_pdf` + the `insufficient_data`
974
+ * indication — everything to overlay heat on the ORIGINAL document with pdf.js. Fetch the
975
+ * view-PDF bytes with `documentViewPdf(id)` (below). */
967
976
  documentChunks: (documentId: UUID) => Promise<ChunkHeatmapResponse>;
977
+ /** Fetch the document's canonical view-PDF BYTES (the surface for the heat overlay).
978
+ * Call this from YOUR BACKEND — KC serves the bytes, so the browser never fetches from
979
+ * GCS (no bucket CORS). Returns a Blob (Node: `Buffer.from(await blob.arrayBuffer())`;
980
+ * browser: `URL.createObjectURL(blob)`). Rejects 404 when `has_view_pdf` is false. */
981
+ documentViewPdf: (documentId: UUID, signal?: AbortSignal) => Promise<Blob>;
968
982
  /** Whole-corpus scatter payload: every document with x=retrieved_reach, y=conversion,
969
983
  * bubble=chunk_count, and a server-computed quadrant. No pagination (`truncated` if capped). */
970
984
  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 = [];
@@ -468,9 +477,15 @@ export class KnowledgeCoreClient extends HttpBase {
468
477
  document: (documentId) => this.request("GET", `/v1/analytics/documents/${documentId}`),
469
478
  /** Parent-section grain for a document (never exposes chunk ids). */
470
479
  documentSections: (documentId) => this.request("GET", `/v1/analytics/documents/${documentId}/sections`),
471
- /** Per-chunk retrieval heat + position in the document's view-PDF, plus a signed
472
- * view-PDF URL — everything to overlay heat on the ORIGINAL document with pdf.js. */
480
+ /** Per-chunk retrieval heat + position + `has_view_pdf` + the `insufficient_data`
481
+ * indication — everything to overlay heat on the ORIGINAL document with pdf.js. Fetch the
482
+ * view-PDF bytes with `documentViewPdf(id)` (below). */
473
483
  documentChunks: (documentId) => this.request("GET", `/v1/analytics/documents/${documentId}/chunks`),
484
+ /** Fetch the document's canonical view-PDF BYTES (the surface for the heat overlay).
485
+ * Call this from YOUR BACKEND — KC serves the bytes, so the browser never fetches from
486
+ * GCS (no bucket CORS). Returns a Blob (Node: `Buffer.from(await blob.arrayBuffer())`;
487
+ * browser: `URL.createObjectURL(blob)`). Rejects 404 when `has_view_pdf` is false. */
488
+ documentViewPdf: (documentId, signal) => this.rawBytes("GET", `/v1/analytics/documents/${documentId}/view-pdf`, signal),
474
489
  /** Whole-corpus scatter payload: every document with x=retrieved_reach, y=conversion,
475
490
  * bubble=chunk_count, and a server-computed quadrant. No pagination (`truncated` if capped). */
476
491
  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.38.1",
3
+ "version": "0.39.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
@@ -346,12 +346,18 @@ export interface ChunkHeat {
346
346
  method: string | null;
347
347
  regions: { page: number; bbox: [number, number, number, number] }[] | null;
348
348
  }
349
- /** Everything to overlay retrieval heat on the original document: a signed view-PDF URL
350
- * (render with pdf.js), its per-page geometry, and every chunk's heat + boxes. */
349
+ /** Everything to overlay retrieval heat on the original document. Fetch the view-PDF BYTES
350
+ * via `analytics.documentViewPdf(id)` from YOUR BACKEND (KC serves them; the browser never
351
+ * touches GCS), render with pdf.js, and shade chunks by heat. `insufficient_data` (with
352
+ * `retrieval_events` as the sample size) is the document-level analogue of the corpus heat
353
+ * view's insufficient_data band — show a clear "not enough data yet" indication instead of
354
+ * misleading shading when it's true. */
351
355
  export interface ChunkHeatmapResponse {
352
356
  document_id: UUID;
353
- view_pdf_url: string | null;
357
+ has_view_pdf: boolean; // a view-PDF exists -> fetch bytes with analytics.documentViewPdf(id)
354
358
  page_dims: { w: number; h: number; rotation: number }[] | null;
359
+ retrieval_events: number; // distinct retrievals this doc appeared in (heat sample size)
360
+ insufficient_data: boolean; // too few retrievals to trust per-chunk heat yet
355
361
  chunks: ChunkHeat[];
356
362
  }
357
363
  export interface MonthlyCorpus {
@@ -589,6 +595,16 @@ class HttpBase {
589
595
  return parsed as T;
590
596
  }
591
597
 
598
+ /** GET binary bytes as a Blob (error bodies are JSON, so decode+throw on !ok). */
599
+ protected async rawBytes(method: string, path: string, signal?: AbortSignal): Promise<Blob> {
600
+ const res = await this.raw(method, path, { signal });
601
+ if (!res.ok) {
602
+ const t = await res.text();
603
+ throw new KnowledgeCoreError(res.status, safeJson(t), path);
604
+ }
605
+ return await res.blob();
606
+ }
607
+
592
608
  /** Auto-paginate a list endpoint into a single array. */
593
609
  protected async pageAll<T>(path: string, query: RequestOpts["query"] = {}): Promise<T[]> {
594
610
  const out: T[] = [];
@@ -1088,9 +1104,16 @@ export class KnowledgeCoreClient extends HttpBase {
1088
1104
  document: (documentId: UUID) => this.request<DocumentAnalytics>("GET", `/v1/analytics/documents/${documentId}`),
1089
1105
  /** Parent-section grain for a document (never exposes chunk ids). */
1090
1106
  documentSections: (documentId: UUID) => this.request<SectionsResponse>("GET", `/v1/analytics/documents/${documentId}/sections`),
1091
- /** Per-chunk retrieval heat + position in the document's view-PDF, plus a signed
1092
- * view-PDF URL — everything to overlay heat on the ORIGINAL document with pdf.js. */
1107
+ /** Per-chunk retrieval heat + position + `has_view_pdf` + the `insufficient_data`
1108
+ * indication — everything to overlay heat on the ORIGINAL document with pdf.js. Fetch the
1109
+ * view-PDF bytes with `documentViewPdf(id)` (below). */
1093
1110
  documentChunks: (documentId: UUID) => this.request<ChunkHeatmapResponse>("GET", `/v1/analytics/documents/${documentId}/chunks`),
1111
+ /** Fetch the document's canonical view-PDF BYTES (the surface for the heat overlay).
1112
+ * Call this from YOUR BACKEND — KC serves the bytes, so the browser never fetches from
1113
+ * GCS (no bucket CORS). Returns a Blob (Node: `Buffer.from(await blob.arrayBuffer())`;
1114
+ * browser: `URL.createObjectURL(blob)`). Rejects 404 when `has_view_pdf` is false. */
1115
+ documentViewPdf: (documentId: UUID, signal?: AbortSignal): Promise<Blob> =>
1116
+ this.rawBytes("GET", `/v1/analytics/documents/${documentId}/view-pdf`, signal),
1094
1117
  /** Whole-corpus scatter payload: every document with x=retrieved_reach, y=conversion,
1095
1118
  * bubble=chunk_count, and a server-computed quadrant. No pagination (`truncated` if capped). */
1096
1119
  corpusScatter: (corpusId: UUID) => this.request<ScatterResponse>("GET", `/v1/analytics/corpora/${corpusId}/scatter`),