@babav/knowledge-core-client 0.23.3 → 0.25.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
@@ -224,6 +224,94 @@ export interface BatchUploadUrls {
224
224
  }>;
225
225
  expires_in: number;
226
226
  }
227
+ /** One RESUMABLE GCS upload session (corpora.createUploadSessions). Hand `upload_url` to the
228
+ * browser: it PUTs bytes straight to GCS there, needing NO KC/tenant credential (the URI is the
229
+ * per-object write capability). Resumable → a dropped connection resumes, not restarts. */
230
+ export interface UploadSession {
231
+ filename: string;
232
+ document_id: UUID;
233
+ upload_url: string;
234
+ gcs_uri: string;
235
+ method: "PUT";
236
+ headers: Record<string, string>;
237
+ expires_at: string;
238
+ }
239
+ /** Per-item result of corpora.finalizeUploads (idempotent registration). */
240
+ export interface FinalizeResult {
241
+ document_id: UUID;
242
+ status: "ingesting" | "failed";
243
+ error?: string;
244
+ }
245
+ export type AnalyticsBand = "frequent" | "occasional" | "rare" | "never" | "insufficient_data";
246
+ export interface UsageSeries {
247
+ corpus_id: UUID;
248
+ granularity: string;
249
+ points: Array<{
250
+ bucket: string;
251
+ queries: number;
252
+ }>;
253
+ }
254
+ export interface DocumentAnalytics {
255
+ document_id: UUID;
256
+ filename: string | null;
257
+ chunks_retrieved: number;
258
+ chunks_reranked: number;
259
+ citation_count: number;
260
+ best_rerank_rank: number | null;
261
+ best_rerank_score: number | null;
262
+ exposure_queries: number;
263
+ retrieved_reach: number;
264
+ citation_reach: number;
265
+ conversion: number;
266
+ band: AnalyticsBand;
267
+ }
268
+ export interface SectionAnalytics {
269
+ parent_id: UUID;
270
+ ordinal: number;
271
+ chunks_retrieved: number;
272
+ chunks_reranked: number;
273
+ citation_count: number;
274
+ best_rerank_score: number | null;
275
+ band: AnalyticsBand;
276
+ }
277
+ export interface SectionsResponse {
278
+ document_id: UUID;
279
+ sections: SectionAnalytics[];
280
+ }
281
+ export interface MonthlyCorpus {
282
+ corpus_id: UUID;
283
+ yyyy_mm: string;
284
+ queries: number;
285
+ documents_retrieved: number;
286
+ chunks_retrieved: number;
287
+ citations: number;
288
+ revenue_share: number;
289
+ }
290
+ export interface CorpusMonthSlice {
291
+ corpus_id: UUID;
292
+ queries: number;
293
+ documents_retrieved: number;
294
+ chunks_retrieved: number;
295
+ citations: number;
296
+ revenue_share: number;
297
+ }
298
+ export interface MonthTotals {
299
+ yyyy_mm: string;
300
+ queries: number;
301
+ documents_retrieved: number;
302
+ chunks_retrieved: number;
303
+ citations: number;
304
+ unattributed_share: number;
305
+ corpora: CorpusMonthSlice[];
306
+ }
307
+ export interface RetrievalEventRow {
308
+ id: UUID;
309
+ created_at: string;
310
+ corpus_ids: UUID[];
311
+ pool_size: number;
312
+ message_id: UUID | null;
313
+ documents: Array<Record<string, unknown>>;
314
+ }
227
315
  export interface Conversation {
228
316
  id: UUID;
229
317
  title: string | null;
@@ -498,6 +586,43 @@ export declare class KnowledgeCoreClient extends HttpBase {
498
586
  custom_metadata?: Record<string, unknown>;
499
587
  concurrency?: number;
500
588
  }) => Promise<Document[]>;
589
+ /** (server-side) Mint one RESUMABLE GCS upload session per file. Return only the sessions to the
590
+ * browser; the browser PUTs bytes to each `upload_url` and needs NO KC/tenant credential (the
591
+ * session URI IS the per-object write capability). `origin` = the browser app origin (scopes the
592
+ * session; the bucket CORS must allow PUT/POST from it). */
593
+ createUploadSessions: (id: UUID, files: Array<{
594
+ filename: string;
595
+ content_type?: string;
596
+ size?: number;
597
+ }>, opts?: {
598
+ origin?: string;
599
+ }) => Promise<{
600
+ items: UploadSession[];
601
+ }>;
602
+ /** (server-side) Register documents whose bytes the browser already PUT to GCS. IDEMPOTENT +
603
+ * PER-ITEM — safe to retry; each result is { document_id, status: 'ingesting' | 'failed' }. Call
604
+ * after the browser reports its PUTs done. folder_id/visibility/custom_metadata apply to all
605
+ * items. `document_id` is stable from createUploadSessions, so documents.events (SSE) tracks it. */
606
+ finalizeUploads: (id: UUID, items: Array<{
607
+ document_id: UUID;
608
+ filename: string;
609
+ content_type?: string;
610
+ }>, opts?: {
611
+ folder_id?: UUID;
612
+ visibility?: Visibility;
613
+ custom_metadata?: Record<string, unknown>;
614
+ }) => Promise<{
615
+ results: FinalizeResult[];
616
+ }>;
617
+ /** (server-side) Cancel upload sessions the browser gave up on (idempotent cleanup). Pass the
618
+ * `upload_url` from createUploadSessions so the resumable session is dropped; any pending row is
619
+ * removed too. Safe to call repeatedly. */
620
+ abortUploadSessions: (id: UUID, items: Array<{
621
+ document_id: UUID;
622
+ upload_url?: string;
623
+ }>) => Promise<{
624
+ aborted: UUID[];
625
+ }>;
501
626
  };
502
627
  parse(a: {
503
628
  file: FileData;
@@ -630,6 +755,48 @@ export declare class KnowledgeCoreClient extends HttpBase {
630
755
  listAll: () => Promise<Agent[]>;
631
756
  get: (id: UUID) => Promise<Agent>;
632
757
  };
758
+ analytics: {
759
+ /** Query-volume time series for a corpus (the denominator for everything). */
760
+ corpusUsage: (corpusId: UUID, q?: {
761
+ from?: string;
762
+ to?: string;
763
+ granularity?: "day" | "week" | "month";
764
+ }) => Promise<UsageSeries>;
765
+ /** Per-document analytics for a corpus (feeds the document list + the quadrant scatter). */
766
+ corpusDocuments: (corpusId: UUID, q?: {
767
+ sort?: "citations" | "reranked" | "retrieved" | "best_score";
768
+ limit?: number;
769
+ cursor?: string;
770
+ from?: string;
771
+ to?: string;
772
+ }) => Promise<{
773
+ items: DocumentAnalytics[];
774
+ next_cursor: string | null;
775
+ }>;
776
+ /** One document's lifetime rollup (headline reach is CITATION reach). */
777
+ document: (documentId: UUID) => Promise<DocumentAnalytics>;
778
+ /** Parent-section grain for a document (never exposes chunk ids). */
779
+ documentSections: (documentId: UUID) => Promise<SectionsResponse>;
780
+ /** A corpus's monthly metrics + revenue_share (YYYY-MM). */
781
+ corpusMonthly: (corpusId: UUID, yyyyMm: string) => Promise<MonthlyCorpus>;
782
+ /** Cross-corpus monthly totals + per-corpus breakdown + unattributed share (YYYY-MM). */
783
+ month: (yyyyMm: string) => Promise<MonthTotals>;
784
+ /** Raw immutable events + document rollups (escape hatch for custom formulas). */
785
+ events: (q?: {
786
+ from?: string;
787
+ to?: string;
788
+ limit?: number;
789
+ cursor?: string;
790
+ }) => Promise<{
791
+ items: RetrievalEventRow[];
792
+ next_cursor: string | null;
793
+ }>;
794
+ /** Flush pending events into the read tables NOW (idempotent; read-your-writes). The Cloud
795
+ * Scheduler drain is the authoritative periodic driver — this is a convenience trigger. */
796
+ drain: () => Promise<{
797
+ processed: number;
798
+ }>;
799
+ };
633
800
  }
634
801
  export declare class AdminClient extends HttpBase {
635
802
  /** @param opts.apiKey the ADMIN key, supplied by the caller. */
package/dist/index.js CHANGED
@@ -283,6 +283,33 @@ export class KnowledgeCoreClient extends HttpBase {
283
283
  } });
284
284
  return res.documents;
285
285
  },
286
+ // --- browser direct-to-GCS uploads (ANY size; the browser NEVER needs an API key) ---
287
+ // Split flow so the browser uploads bytes ITSELF while the tenant key stays server-side:
288
+ // 1. (server) createUploadSessions -> returns a resumable GCS session URI per file
289
+ // 2. (browser) PUT the bytes straight to each session URI (resumable; no credential)
290
+ // 3. (server) finalizeUploads -> register + enqueue; or abortUploadSessions to cancel
291
+ // Use this instead of uploadMany when bytes must not pass through your worker (browser -> GCS
292
+ // direct), e.g. multi-GB files or a browser that can't hold the tenant key.
293
+ /** (server-side) Mint one RESUMABLE GCS upload session per file. Return only the sessions to the
294
+ * browser; the browser PUTs bytes to each `upload_url` and needs NO KC/tenant credential (the
295
+ * session URI IS the per-object write capability). `origin` = the browser app origin (scopes the
296
+ * session; the bucket CORS must allow PUT/POST from it). */
297
+ createUploadSessions: (id, files, opts) => this.request("POST", `/v1/corpora/${id}/documents/upload-sessions`, { json: {
298
+ items: files.map((f) => ({ filename: f.filename, content_type: f.content_type })),
299
+ origin: opts?.origin,
300
+ } }),
301
+ /** (server-side) Register documents whose bytes the browser already PUT to GCS. IDEMPOTENT +
302
+ * PER-ITEM — safe to retry; each result is { document_id, status: 'ingesting' | 'failed' }. Call
303
+ * after the browser reports its PUTs done. folder_id/visibility/custom_metadata apply to all
304
+ * items. `document_id` is stable from createUploadSessions, so documents.events (SSE) tracks it. */
305
+ finalizeUploads: (id, items, opts) => this.request("POST", `/v1/corpora/${id}/documents/finalize`, { json: {
306
+ items, folder_id: opts?.folder_id, visibility: opts?.visibility,
307
+ custom_metadata: opts?.custom_metadata,
308
+ } }),
309
+ /** (server-side) Cancel upload sessions the browser gave up on (idempotent cleanup). Pass the
310
+ * `upload_url` from createUploadSessions so the resumable session is dropped; any pending row is
311
+ * removed too. Safe to call repeatedly. */
312
+ abortUploadSessions: (id, items) => this.request("POST", `/v1/corpora/${id}/documents/abort-uploads`, { json: { items } }),
286
313
  };
287
314
  // --- parsing (utility: file -> text, stores nothing) ---
288
315
  parse(a) {
@@ -383,6 +410,26 @@ export class KnowledgeCoreClient extends HttpBase {
383
410
  listAll: () => this.pageAll("/v1/agents"),
384
411
  get: (id) => this.request("GET", `/v1/agents/${id}`),
385
412
  };
413
+ // --- retrieval analytics (read-only, tenant-scoped, aggregate-on-read) ---
414
+ analytics = {
415
+ /** Query-volume time series for a corpus (the denominator for everything). */
416
+ corpusUsage: (corpusId, q) => this.request("GET", `/v1/analytics/corpora/${corpusId}/usage`, { query: q }),
417
+ /** Per-document analytics for a corpus (feeds the document list + the quadrant scatter). */
418
+ corpusDocuments: (corpusId, q) => this.request("GET", `/v1/analytics/corpora/${corpusId}/documents`, { query: q }),
419
+ /** One document's lifetime rollup (headline reach is CITATION reach). */
420
+ document: (documentId) => this.request("GET", `/v1/analytics/documents/${documentId}`),
421
+ /** Parent-section grain for a document (never exposes chunk ids). */
422
+ documentSections: (documentId) => this.request("GET", `/v1/analytics/documents/${documentId}/sections`),
423
+ /** A corpus's monthly metrics + revenue_share (YYYY-MM). */
424
+ corpusMonthly: (corpusId, yyyyMm) => this.request("GET", `/v1/analytics/corpora/${corpusId}/monthly/${yyyyMm}`),
425
+ /** Cross-corpus monthly totals + per-corpus breakdown + unattributed share (YYYY-MM). */
426
+ month: (yyyyMm) => this.request("GET", `/v1/analytics/months/${yyyyMm}`),
427
+ /** Raw immutable events + document rollups (escape hatch for custom formulas). */
428
+ events: (q) => this.request("GET", "/v1/analytics/events", { query: q }),
429
+ /** Flush pending events into the read tables NOW (idempotent; read-your-writes). The Cloud
430
+ * Scheduler drain is the authoritative periodic driver — this is a convenience trigger. */
431
+ drain: () => this.request("POST", "/v1/analytics/drain"),
432
+ };
386
433
  }
387
434
  // ---------------------------------------------------------------------------
388
435
  // Admin client (tenant + key + agent management) — use the ADMIN key
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babav/knowledge-core-client",
3
- "version": "0.23.3",
3
+ "version": "0.25.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
@@ -240,6 +240,59 @@ export interface BatchUploadUrls {
240
240
  items: Array<{ filename: string; document_id: UUID; upload_url: string; gcs_uri: string }>;
241
241
  expires_in: number;
242
242
  }
243
+ /** One RESUMABLE GCS upload session (corpora.createUploadSessions). Hand `upload_url` to the
244
+ * browser: it PUTs bytes straight to GCS there, needing NO KC/tenant credential (the URI is the
245
+ * per-object write capability). Resumable → a dropped connection resumes, not restarts. */
246
+ export interface UploadSession {
247
+ filename: string;
248
+ document_id: UUID;
249
+ upload_url: string;
250
+ gcs_uri: string;
251
+ method: "PUT";
252
+ headers: Record<string, string>;
253
+ expires_at: string;
254
+ }
255
+ /** Per-item result of corpora.finalizeUploads (idempotent registration). */
256
+ export interface FinalizeResult {
257
+ document_id: UUID;
258
+ status: "ingesting" | "failed";
259
+ error?: string;
260
+ }
261
+ // --- retrieval analytics ---
262
+ export type AnalyticsBand = "frequent" | "occasional" | "rare" | "never" | "insufficient_data";
263
+ export interface UsageSeries {
264
+ corpus_id: UUID;
265
+ granularity: string;
266
+ points: Array<{ bucket: string; queries: number }>;
267
+ }
268
+ export interface DocumentAnalytics {
269
+ document_id: UUID; filename: string | null;
270
+ chunks_retrieved: number; chunks_reranked: number; citation_count: number;
271
+ best_rerank_rank: number | null; best_rerank_score: number | null;
272
+ exposure_queries: number; retrieved_reach: number; citation_reach: number;
273
+ conversion: number; band: AnalyticsBand;
274
+ }
275
+ export interface SectionAnalytics {
276
+ parent_id: UUID; ordinal: number; chunks_retrieved: number; chunks_reranked: number;
277
+ citation_count: number; best_rerank_score: number | null; band: AnalyticsBand;
278
+ }
279
+ export interface SectionsResponse { document_id: UUID; sections: SectionAnalytics[] }
280
+ export interface MonthlyCorpus {
281
+ corpus_id: UUID; yyyy_mm: string; queries: number; documents_retrieved: number;
282
+ chunks_retrieved: number; citations: number; revenue_share: number;
283
+ }
284
+ export interface CorpusMonthSlice {
285
+ corpus_id: UUID; queries: number; documents_retrieved: number;
286
+ chunks_retrieved: number; citations: number; revenue_share: number;
287
+ }
288
+ export interface MonthTotals {
289
+ yyyy_mm: string; queries: number; documents_retrieved: number; chunks_retrieved: number;
290
+ citations: number; unattributed_share: number; corpora: CorpusMonthSlice[];
291
+ }
292
+ export interface RetrievalEventRow {
293
+ id: UUID; created_at: string; corpus_ids: UUID[]; pool_size: number;
294
+ message_id: UUID | null; documents: Array<Record<string, unknown>>;
295
+ }
243
296
  export interface Conversation {
244
297
  id: UUID;
245
298
  title: string | null;
@@ -669,6 +722,58 @@ export class KnowledgeCoreClient extends HttpBase {
669
722
  );
670
723
  return res.documents;
671
724
  },
725
+
726
+ // --- browser direct-to-GCS uploads (ANY size; the browser NEVER needs an API key) ---
727
+ // Split flow so the browser uploads bytes ITSELF while the tenant key stays server-side:
728
+ // 1. (server) createUploadSessions -> returns a resumable GCS session URI per file
729
+ // 2. (browser) PUT the bytes straight to each session URI (resumable; no credential)
730
+ // 3. (server) finalizeUploads -> register + enqueue; or abortUploadSessions to cancel
731
+ // Use this instead of uploadMany when bytes must not pass through your worker (browser -> GCS
732
+ // direct), e.g. multi-GB files or a browser that can't hold the tenant key.
733
+
734
+ /** (server-side) Mint one RESUMABLE GCS upload session per file. Return only the sessions to the
735
+ * browser; the browser PUTs bytes to each `upload_url` and needs NO KC/tenant credential (the
736
+ * session URI IS the per-object write capability). `origin` = the browser app origin (scopes the
737
+ * session; the bucket CORS must allow PUT/POST from it). */
738
+ createUploadSessions: (
739
+ id: UUID,
740
+ files: Array<{ filename: string; content_type?: string; size?: number }>,
741
+ opts?: { origin?: string },
742
+ ): Promise<{ items: UploadSession[] }> =>
743
+ this.request<{ items: UploadSession[] }>(
744
+ "POST", `/v1/corpora/${id}/documents/upload-sessions`,
745
+ { json: {
746
+ items: files.map((f) => ({ filename: f.filename, content_type: f.content_type })),
747
+ origin: opts?.origin,
748
+ } },
749
+ ),
750
+
751
+ /** (server-side) Register documents whose bytes the browser already PUT to GCS. IDEMPOTENT +
752
+ * PER-ITEM — safe to retry; each result is { document_id, status: 'ingesting' | 'failed' }. Call
753
+ * after the browser reports its PUTs done. folder_id/visibility/custom_metadata apply to all
754
+ * items. `document_id` is stable from createUploadSessions, so documents.events (SSE) tracks it. */
755
+ finalizeUploads: (
756
+ id: UUID,
757
+ items: Array<{ document_id: UUID; filename: string; content_type?: string }>,
758
+ opts?: { folder_id?: UUID; visibility?: Visibility; custom_metadata?: Record<string, unknown> },
759
+ ): Promise<{ results: FinalizeResult[] }> =>
760
+ this.request<{ results: FinalizeResult[] }>(
761
+ "POST", `/v1/corpora/${id}/documents/finalize`,
762
+ { json: {
763
+ items, folder_id: opts?.folder_id, visibility: opts?.visibility,
764
+ custom_metadata: opts?.custom_metadata,
765
+ } },
766
+ ),
767
+
768
+ /** (server-side) Cancel upload sessions the browser gave up on (idempotent cleanup). Pass the
769
+ * `upload_url` from createUploadSessions so the resumable session is dropped; any pending row is
770
+ * removed too. Safe to call repeatedly. */
771
+ abortUploadSessions: (
772
+ id: UUID,
773
+ items: Array<{ document_id: UUID; upload_url?: string }>,
774
+ ): Promise<{ aborted: UUID[] }> =>
775
+ this.request<{ aborted: UUID[] }>(
776
+ "POST", `/v1/corpora/${id}/documents/abort-uploads`, { json: { items } }),
672
777
  };
673
778
 
674
779
  // --- parsing (utility: file -> text, stores nothing) ---
@@ -793,6 +898,30 @@ export class KnowledgeCoreClient extends HttpBase {
793
898
  listAll: () => this.pageAll<Agent>("/v1/agents"),
794
899
  get: (id: UUID) => this.request<Agent>("GET", `/v1/agents/${id}`),
795
900
  };
901
+
902
+ // --- retrieval analytics (read-only, tenant-scoped, aggregate-on-read) ---
903
+ analytics = {
904
+ /** Query-volume time series for a corpus (the denominator for everything). */
905
+ corpusUsage: (corpusId: UUID, q?: { from?: string; to?: string; granularity?: "day" | "week" | "month" }) =>
906
+ this.request<UsageSeries>("GET", `/v1/analytics/corpora/${corpusId}/usage`, { query: q }),
907
+ /** Per-document analytics for a corpus (feeds the document list + the quadrant scatter). */
908
+ corpusDocuments: (corpusId: UUID, q?: { sort?: "citations" | "reranked" | "retrieved" | "best_score"; limit?: number; cursor?: string; from?: string; to?: string }) =>
909
+ this.request<{ items: DocumentAnalytics[]; next_cursor: string | null }>("GET", `/v1/analytics/corpora/${corpusId}/documents`, { query: q }),
910
+ /** One document's lifetime rollup (headline reach is CITATION reach). */
911
+ document: (documentId: UUID) => this.request<DocumentAnalytics>("GET", `/v1/analytics/documents/${documentId}`),
912
+ /** Parent-section grain for a document (never exposes chunk ids). */
913
+ documentSections: (documentId: UUID) => this.request<SectionsResponse>("GET", `/v1/analytics/documents/${documentId}/sections`),
914
+ /** A corpus's monthly metrics + revenue_share (YYYY-MM). */
915
+ corpusMonthly: (corpusId: UUID, yyyyMm: string) => this.request<MonthlyCorpus>("GET", `/v1/analytics/corpora/${corpusId}/monthly/${yyyyMm}`),
916
+ /** Cross-corpus monthly totals + per-corpus breakdown + unattributed share (YYYY-MM). */
917
+ month: (yyyyMm: string) => this.request<MonthTotals>("GET", `/v1/analytics/months/${yyyyMm}`),
918
+ /** Raw immutable events + document rollups (escape hatch for custom formulas). */
919
+ events: (q?: { from?: string; to?: string; limit?: number; cursor?: string }) =>
920
+ this.request<{ items: RetrievalEventRow[]; next_cursor: string | null }>("GET", "/v1/analytics/events", { query: q }),
921
+ /** Flush pending events into the read tables NOW (idempotent; read-your-writes). The Cloud
922
+ * Scheduler drain is the authoritative periodic driver — this is a convenience trigger. */
923
+ drain: () => this.request<{ processed: number }>("POST", "/v1/analytics/drain"),
924
+ };
796
925
  }
797
926
 
798
927
  // ---------------------------------------------------------------------------