@littlebigbrain/client 0.4.2 → 0.5.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/README.md CHANGED
@@ -1,169 +1,112 @@
1
1
  # @littlebigbrain/client
2
2
 
3
- TypeScript client for the [little big brain](https://littlebigbrain.com) graph + hybrid search HTTP
4
- API. Request and response types are generated from the committed
5
- [`contracts/openapi.json`](https://github.com/littlebigbrains/lbb-typescript/blob/main/contracts/openapi.json) (the single source of
6
- truth, derived from the Rust `lbb-api` types); the client itself is a thin,
7
- dependency-free wrapper over the platform `fetch`.
3
+ Typed TypeScript client for little big brain: ingest, BM25/vector/graph index,
4
+ authorized hybrid search, traversal, ontology, feedback, and training jobs.
5
+ Runs on Node 18+, browsers, and edge workers using the platform `fetch`.
8
6
 
9
7
  ```sh
10
8
  npm install @littlebigbrain/client
11
9
  ```
12
10
 
13
- ## Usage
11
+ ## Five-minute start
14
12
 
15
13
  ```ts
16
- import { LbbClient, LbbError } from "@littlebigbrain/client";
14
+ import { LbbClient } from "@littlebigbrain/client";
17
15
 
18
16
  const lbb = new LbbClient({
19
17
  baseUrl: "https://db.eu.littlebigbrain.com",
20
- apiKey: process.env.LBB_API_KEY, // lbb_sk_test_… or lbb_sk_live_…
18
+ apiKey: process.env.LBB_API_KEY,
21
19
  });
22
-
23
20
  const graph = lbb.graph("main");
24
21
 
25
22
  await graph.facts.create({
26
- triplets: [
27
- {
28
- source: { type: "SERVICE", name: "auth-service" },
29
- relation: "WRITES_TO",
30
- target: { type: "DATABASE", name: "user-db" },
31
- confidence: 0.93,
32
- evidence: "auth-service writes identity records to user-db",
33
- },
34
- ],
35
- }, {
36
- idempotencyKey: "import-2026-06-13",
37
- });
23
+ triplets: [{
24
+ source: { type: "CONCEPT", name: "policy-42" },
25
+ relation: "RELATED_TO",
26
+ target: { type: "CONCEPT", name: "seven-year retention" },
27
+ evidence: "Customer records are retained for seven years.",
28
+ }],
29
+ }, { idempotencyKey: "policy-42-v1" });
38
30
 
39
31
  await graph.indexes.run({ wait: true });
40
32
 
41
- const results = await graph.search.hybrid("which systems store customer identity data", {
42
- topK: 5,
43
- source: "persisted",
44
- consistency: "strong",
45
- targets: ["entities", "assertions"],
46
- });
47
- for (const assertion of results.assertions ?? []) {
48
- console.log(assertion.relation?.name, assertion.score);
49
- }
33
+ const results = await graph.search.hybrid(
34
+ "How long are customer records retained?",
35
+ { topK: 10, source: "persisted", consistency: "strong" },
36
+ );
50
37
  ```
51
38
 
52
- Use `client.graph("name")` to scope graph writes and `client.rawRequest(...)`
53
- when you need response metadata (`requestId`, `version`, headers). Every method
54
- returns parsed JSON and throws `LbbError` with `status`, `type`, `code`,
55
- `message`, `param`, `requestId`, and `docUrl` on a non-2xx response.
56
-
57
- Requests have a 120-second per-attempt timeout by default (`timeoutMs: 0`
58
- disables it). Safe reads and idempotency-keyed writes retry `429`/`5xx` and
59
- network failures up to twice, honoring `Retry-After` with a one-minute cap.
60
- Bulk NDJSON and RDF imports receive an idempotency key automatically unless you
61
- provide one explicitly. The preferred namespaced surface accepts the same final
62
- request options everywhere: `timeoutMs`, `maxRetries`, `signal`, `headers`, and
63
- `idempotencyKey` for mutations.
39
+ Methods return parsed JSON and throw `LbbError` on non-2xx responses. Safe
40
+ reads and idempotency-keyed writes retry transient failures and honor
41
+ `Retry-After`. Keep live stack keys on the server, never in browser bundles.
64
42
 
65
- ## Preferred surface
43
+ ## Enterprise search integrations
66
44
 
67
- Scope once with `client.graph("name", { branch })`; its `facts`, `search`,
68
- `entities`, `indexes`, `schema`, `ontology`, `query`, and `context` namespaces
69
- all carry that graph and branch. The original flat methods remain available for
70
- compatibility.
45
+ Keep the host product's users, connectors, tasks, and cursors in its existing
46
+ database. Put searchable documents, passages, facts, embeddings, indexes,
47
+ feedback, and model runs in little big brain:
71
48
 
72
- ```ts
73
- const graph = lbb.graph("main", { branch: "review" });
74
-
75
- const answer = await graph.context.ask({ question: "what stores identity data?" });
76
- const ontology = await graph.ontology.view({ counts: true });
77
- const rows = await graph.query.sparql({ query: "SELECT ?s WHERE { ?s ?p ?o }" });
49
+ 1. Give every document/chunk/passage a stable external key.
50
+ 2. Bulk-import content, provenance, and native ACL/tag/project sets.
51
+ 3. Configure managed embeddings; build ANN, BM25, and adjacency once per batch.
52
+ 4. Filter by ACL inside the search request before ranking and return projected
53
+ fields on the ranked hits.
54
+ 5. Grade cited results, reconnect to durable trainer jobs, and require a
55
+ held-out quality plus latency gate before promotion.
78
56
 
79
- for await (const entity of graph.entities.iterate({ fields: ["owner", "status"] })) {
80
- console.log(entity.name, entity.attributes);
81
- }
82
- ```
57
+ `suggestionShown`, `suggestionAdopted`, `externalPlannerTrace`, and
58
+ `askFeedback` use generated versioned payload types and idempotency keys. Their
59
+ acknowledgements expose stable receipt/event identity, replay state, and why an
60
+ event is or is not trainable.
83
61
 
84
- Use `entities.pages(...)` when page metadata matters, or `entities.iterate(...)`
85
- to yield rows directly. Both follow the server cursor and fail if a cursor
86
- repeats instead of looping forever.
87
-
88
- For instrumentation, `onRequest` fires before each attempt and `onResponse`
89
- fires once for the final response; neither event contains bodies or
90
- credentials. `rawRequest(...)` additionally reports `attempts`, `retryCount`,
91
- and `elapsedMs`.
92
-
93
- ## Methods
94
-
95
- | Area | Methods |
96
- | --- | --- |
97
- | Write | `graph("main").facts.create` |
98
- | Managed embeddings | `graph("main").embeddingConfig`, `graph("main").setEmbeddingConfig`, `graph("main").backfillEmbeddings`, `graph("main").promoteEmbedding` |
99
- | Search | `search.hybrid`, `search.multi`, `search.fullText`, `search.vector` |
100
- | Context substrate | `context.ask`, `context.suggest`, `context.resolve`, `context.decode`, `context.groundability` |
101
- | Search feedback (training data) | `search.feedback`, `search.feedbackExport` |
102
- | Traversal | `traverse`, `semanticTraverse` |
103
- | Temporal / lineage / shapes | `currentState`, `history`, `why`, `shacl` |
104
- | Query | `query.sparql`, `query.structured`, `query.analytics`, `query.shacl`, `query.infer`, `query.premises` |
105
- | Ontology | `ontology.view`, `ontology.conformance`, `ontology.search`, `ontology.resolve`, `ontology.define`, `ontology.evolve`, `ontology.induce` |
106
- | Index lifecycle | `indexes.run`, `indexes.build`, `indexes.delta`, `indexes.gc`, `compact` |
107
- | Inspection | `entities.list`, `entities.filterByAttributes`, `status`, `metadata`, `summary` |
108
- | Schema activation | `schema.view`, `schema.preview`, `schema.publish`, `schema.audit` |
109
-
110
- Common request/response shapes have direct imports such as `SearchRequest`,
111
- `SearchResponse`, `Entity`, `GraphSummary`, `CommitRequest`, `AskResponse`, and
112
- `SchemaView`. Every generated shape remains available as `Schemas["TypeName"]`;
113
- the raw `components`, `paths`, and `operations` are exported too.
62
+ For an LLM query planner, call `lbb.context.suggest(...)` to fill grounded
63
+ schema/value prefixes, then `lbb.context.resolve(...)` to snap free-text guesses
64
+ onto real vocabulary. `resolve` uses managed embeddings when configured. Record
65
+ adopted suggestions and accepted/rejected/corrected plans so a smaller planner
66
+ and suggest ranker can be trained on the product's actual workload.
114
67
 
115
- ## SPARQL
68
+ The [enterprise-search integration guide](https://docs.littlebigbrain.com/guides/enterprise-search/)
69
+ contains the graph model, migration sequence, and acceptance tests.
116
70
 
117
- `client.sparqlRows(...)` runs a SPARQL 1.1 text query (SELECT or ASK) and
118
- returns parsed results, so you never have to `JSON.parse` the results string or
119
- zip `head.vars` with binding values yourself:
71
+ ## Main surface
120
72
 
121
73
  ```ts
122
- const { vars, rows } = await client.sparqlRows({
123
- query: `SELECT ?service ?db WHERE {
124
- ?service <https://littlebigbrain.com/r/writes_to> ?db
125
- } LIMIT 10`,
126
- reason: true, // optional: fold in rule-derived edges
127
- });
128
- for (const row of rows) console.log(row.service, "->", row.db);
129
-
130
- const exists = (await client.sparqlRows({ query: "ASK { ?s ?p ?o }" })).boolean;
74
+ graph.facts.create(...)
75
+ graph.facts.import(...)
76
+ graph.search.hybrid(...)
77
+ graph.entities.iterate(...)
78
+ graph.context.ask(...)
79
+ graph.ontology.view(...)
80
+ graph.query.sparql(...)
81
+ graph.schema.audit(...)
131
82
  ```
132
83
 
133
- For app code that already has relation patterns but just needs typed attribute
134
- predicates, `client.entities.filterByAttributes(...)` builds the structured
135
- SPARQL filter body without exposing RDF property IRIs:
84
+ Other focused methods cover managed embeddings, full-text/vector search,
85
+ multi-query fusion, traversal, temporal state/history, SHACL, ontology
86
+ evolution, feedback, indexing, and graph inspection. Request/response types are
87
+ generated from `contracts/openapi.json`; common aliases and the complete
88
+ `Schemas` map are exported from the package.
89
+
90
+ Use `rawRequest()` when you need response headers, request ID, retry count, or
91
+ elapsed time. `onRequest` and `onResponse` provide body-free instrumentation.
92
+
93
+ ## SPARQL
136
94
 
137
95
  ```ts
138
- await client.entities.filterByAttributes({
139
- patterns: [{ subject: { var: "service" }, predicate: "WRITES_TO", object: { var: "db" } }],
140
- where: [{ field: "slo", op: "ge", value: 0.99 }, { var: "db", field: "tier", value: "prod" }],
141
- select: ["service"],
96
+ const { rows } = await lbb.sparqlRows({
97
+ query: `SELECT ?doc WHERE { ?doc ?p ?o } LIMIT 10`,
142
98
  });
143
99
  ```
144
100
 
145
- `sparqlRows` returns `{ vars, boolean, bindings, rows }`: `rows` is the bindings
146
- flattened to `{ variable: lexicalValue }`, `bindings` keeps the raw typed term
147
- objects, and `boolean` is the ASK answer (or `null` for a SELECT). `client.sparqlText(...)`
148
- returns the unparsed envelope, and the standalone `parseSparqlResults(response)`
149
- helper (also exported) parses it. For the structured BGP form use
150
- `client.sparql(body)` (`SparqlSelectRequest`).
151
-
152
- A standalone stack also serves the **native SPARQL 1.1 Protocol** at `/sparql`
153
- (`GET ?query=`, `POST` form or `application/sparql-query` body,
154
- `Accept`-negotiated JSON/XML/CSV/TSV) for off-the-shelf SPARQL clients (YASGUI,
155
- Protégé); `sparqlRows` returns parsed JSON rows for in-process use.
101
+ `sparqlRows` parses SELECT/ASK results. The native SPARQL 1.1 Protocol is also
102
+ available at `/sparql` for standard RDF clients.
156
103
 
157
104
  ## Develop
158
105
 
159
106
  ```sh
160
107
  npm install
161
- npm run generate # regenerate src/schema.ts from ../../contracts/openapi.json
162
- npm run build # tsc -> dist/
163
- npm test # build + node:test (mocked fetch)
164
- npm run test:coverage
165
- npm run pack:check # exact tarball: publint + ATTW
108
+ npm run generate
109
+ npm run typecheck
110
+ npm test
111
+ npm run pack:check
166
112
  ```
167
-
168
- `runtime`: any environment with a global `fetch` (Node 18+, browsers, edge
169
- workers), or pass your own via the `fetch` option.
package/dist/client.d.ts CHANGED
@@ -7,6 +7,15 @@ export { LbbError } from "./transport.js";
7
7
  export type { CallOptions, Query, QueryValue, RequestOptions, } from "./transport.js";
8
8
  export type { EntityListOptions, HybridSearchOptions } from "./namespaces.js";
9
9
  export { ContextNamespace, EntityNamespace, FactsNamespace, GraphNamespace, IndexNamespace, OntologyNamespace, QueryNamespace, SchemaNamespace, SearchNamespace, } from "./namespaces.js";
10
+ export interface IndexLineageObservation {
11
+ metadata: Schemas["GraphMetadataResponse"];
12
+ lineage: Schemas["IndexLineage"];
13
+ buildCommit?: string;
14
+ replica?: string;
15
+ requestId?: string;
16
+ attempts: number;
17
+ elapsedMs: number;
18
+ }
10
19
  /**
11
20
  * A typed HTTP client for a little big brain graph server. One instance is scoped to a
12
21
  * single graph/branch; construct another for a different scope. All methods
@@ -133,10 +142,21 @@ export declare class LbbClient {
133
142
  }): Promise<unknown>;
134
143
  embeddingConfig(): Promise<Schemas["ManagedEmbeddingConfigResponse"]>;
135
144
  setEmbeddingConfig(body: Schemas["ManagedEmbeddingConfigRequest"]): Promise<Schemas["ManagedEmbeddingConfigResponse"]>;
145
+ submitEmbeddingBackfill(opts?: {
146
+ batchSize?: number;
147
+ limit?: number;
148
+ full?: boolean;
149
+ idempotencyKey?: string;
150
+ }): Promise<Schemas["ManagedEmbeddingBackfillJobStatusResponse"]>;
151
+ embeddingBackfillJob(jobId: string): Promise<Schemas["ManagedEmbeddingBackfillJobStatusResponse"]>;
152
+ cancelEmbeddingBackfill(jobId: string): Promise<Schemas["ManagedEmbeddingBackfillJobStatusResponse"]>;
136
153
  backfillEmbeddings(opts?: {
137
154
  batchSize?: number;
138
155
  limit?: number;
139
156
  full?: boolean;
157
+ idempotencyKey?: string;
158
+ timeoutMs?: number;
159
+ pollIntervalMs?: number;
140
160
  }): Promise<Schemas["ManagedEmbeddingBackfillResponse"]>;
141
161
  promoteEmbedding(opts: {
142
162
  runId: string;
@@ -224,7 +244,21 @@ export declare class LbbClient {
224
244
  * explicit feedback capture. `accepted: false` in the response means
225
245
  * signal capture is off on this deployment (the contract is identical).
226
246
  */
227
- askFeedback(body: Schemas["AskFeedbackRequest"]): Promise<Schemas["AskFeedbackResponse"]>;
247
+ askFeedback(body: Schemas["AskFeedbackRequest"], opts?: {
248
+ idempotencyKey?: string;
249
+ }): Promise<Schemas["AskFeedbackResponse"]>;
250
+ ingestSignals(body: Schemas["SignalIngestRequest"], opts?: {
251
+ idempotencyKey?: string;
252
+ }): Promise<Schemas["SignalIngestResponse"]>;
253
+ suggestionShown(payload: Schemas["SuggestionShownV1"], opts?: {
254
+ idempotencyKey?: string;
255
+ }): Promise<Schemas["SignalIngestResponse"]>;
256
+ suggestionAdopted(payload: Schemas["SuggestionAdoptedV1"], opts?: {
257
+ idempotencyKey?: string;
258
+ }): Promise<Schemas["SignalIngestResponse"]>;
259
+ externalPlannerTrace(payload: Schemas["ExternalPlannerTraceV1"], opts?: {
260
+ idempotencyKey?: string;
261
+ }): Promise<Schemas["SignalIngestResponse"]>;
228
262
  /**
229
263
  * The planner fine-tune's training feed: accepted/corrected feedback
230
264
  * joined to its traces (signals ≤ the split pin), topped up with
@@ -521,6 +555,10 @@ export declare class LbbClient {
521
555
  status(): Promise<unknown>;
522
556
  /** Graph footprint, WAL tail, and index coverage. */
523
557
  metadata(): Promise<Schemas["GraphMetadataResponse"]>;
558
+ waitForIndexLineage(targetSeq: number, opts?: {
559
+ timeoutMs?: number;
560
+ pollIntervalMs?: number;
561
+ }): Promise<IndexLineageObservation>;
524
562
  /** Graph counts and type/relation buckets. */
525
563
  summary(): Promise<Schemas["GraphSummaryResponse"]>;
526
564
  /** List the graphs (and branches) under the scoped tenant. */
package/dist/client.js CHANGED
@@ -395,11 +395,40 @@ export class LbbClient {
395
395
  setEmbeddingConfig(body) {
396
396
  return this.request("POST", "/v1/graph/embedding", { body });
397
397
  }
398
- backfillEmbeddings(opts = {}) {
399
- return this.request("POST", "/v1/graph/embedding/backfill", {
400
- query: { batch_size: opts.batchSize, limit: opts.limit, full: opts.full },
398
+ submitEmbeddingBackfill(opts = {}) {
399
+ return this.request("POST", "/v1/graph/embedding/backfill-jobs", {
400
+ body: {
401
+ batch_size: opts.batchSize,
402
+ limit: opts.limit,
403
+ full: opts.full ?? false,
404
+ },
405
+ idempotencyKey: opts.idempotencyKey ?? this.idempotencyKey("embedding-backfill"),
406
+ });
407
+ }
408
+ embeddingBackfillJob(jobId) {
409
+ return this.request("GET", "/v1/graph/embedding/backfill-jobs", {
410
+ query: { job_id: jobId },
411
+ });
412
+ }
413
+ cancelEmbeddingBackfill(jobId) {
414
+ return this.request("DELETE", "/v1/graph/embedding/backfill-jobs", {
415
+ query: { job_id: jobId },
401
416
  });
402
417
  }
418
+ async backfillEmbeddings(opts = {}) {
419
+ let status = await this.submitEmbeddingBackfill(opts);
420
+ const deadline = Date.now() + (opts.timeoutMs ?? 30 * 60_000);
421
+ while (status.status === "pending" || status.status === "running") {
422
+ if (Date.now() >= deadline)
423
+ throw new Error(`embedding backfill ${status.job_id} did not finish before timeout`);
424
+ await sleep(opts.pollIntervalMs ?? 2_000);
425
+ status = await this.embeddingBackfillJob(status.job_id);
426
+ }
427
+ if (status.status !== "succeeded" || status.result == null)
428
+ throw new Error(status.terminal_error ??
429
+ `embedding backfill ${status.job_id} ended ${status.status}`);
430
+ return status.result;
431
+ }
403
432
  promoteEmbedding(opts) {
404
433
  return this.request("POST", "/v1/graph/embedding/promote", {
405
434
  query: { run_id: opts.runId, allow_regression: opts.allowRegression },
@@ -506,8 +535,35 @@ export class LbbClient {
506
535
  * explicit feedback capture. `accepted: false` in the response means
507
536
  * signal capture is off on this deployment (the contract is identical).
508
537
  */
509
- askFeedback(body) {
510
- return this.request("POST", "/v1/ask/feedback", { body });
538
+ askFeedback(body, opts = {}) {
539
+ return this.request("POST", "/v1/ask/feedback", {
540
+ body,
541
+ idempotencyKey: opts.idempotencyKey ?? this.idempotencyKey("ask-feedback"),
542
+ });
543
+ }
544
+ ingestSignals(body, opts = {}) {
545
+ return this.request("POST", "/v1/signals", {
546
+ body,
547
+ idempotencyKey: opts.idempotencyKey ?? this.idempotencyKey("signals"),
548
+ });
549
+ }
550
+ suggestionShown(payload, opts = {}) {
551
+ return this.ingestSignals({ signals: [{ kind: "suggestion_shown", payload }] }, opts);
552
+ }
553
+ suggestionAdopted(payload, opts = {}) {
554
+ return this.ingestSignals({ signals: [{ kind: "suggestion_adopted", payload }] }, opts);
555
+ }
556
+ externalPlannerTrace(payload, opts = {}) {
557
+ return this.ingestSignals({
558
+ signals: [
559
+ {
560
+ kind: "external_planner_trace",
561
+ request_id: payload.ask_id,
562
+ snapshot_token: payload.snapshot_token,
563
+ payload,
564
+ },
565
+ ],
566
+ }, opts);
511
567
  }
512
568
  /**
513
569
  * The planner fine-tune's training feed: accepted/corrected feedback
@@ -923,6 +979,37 @@ export class LbbClient {
923
979
  metadata() {
924
980
  return this.request("GET", "/v1/graph/metadata");
925
981
  }
982
+ async waitForIndexLineage(targetSeq, opts = {}) {
983
+ const deadline = Date.now() + (opts.timeoutMs ?? 30_000);
984
+ let last;
985
+ while (true) {
986
+ last = await this.rawRequest("GET", "/v1/graph/metadata");
987
+ const lineage = last.data.index_lineage;
988
+ if (lineage != null &&
989
+ lineage.bm25_indexed_commit_seq != null &&
990
+ lineage.bm25_indexed_commit_seq >= targetSeq &&
991
+ lineage.ann_indexed_commit_seq != null &&
992
+ lineage.ann_indexed_commit_seq >= targetSeq &&
993
+ lineage.adjacency_indexed_commit_seq != null &&
994
+ lineage.adjacency_indexed_commit_seq >= targetSeq) {
995
+ return {
996
+ metadata: last.data,
997
+ lineage,
998
+ buildCommit: last.headers?.get("lbb-build-commit") ?? undefined,
999
+ replica: last.headers?.get("lbb-replica") ?? undefined,
1000
+ requestId: last.requestId,
1001
+ attempts: last.attempts,
1002
+ elapsedMs: last.elapsedMs,
1003
+ };
1004
+ }
1005
+ if (Date.now() >= deadline) {
1006
+ const build = last.headers?.get("lbb-build-commit") ?? "unknown";
1007
+ const replica = last.headers?.get("lbb-replica") ?? "unknown";
1008
+ throw new Error(`index lineage did not reach ${targetSeq} before timeout (build=${build}, replica=${replica}, last=${JSON.stringify(last.data.index_lineage)})`);
1009
+ }
1010
+ await sleep(opts.pollIntervalMs ?? 250);
1011
+ }
1012
+ }
926
1013
  /** Graph counts and type/relation buckets. */
927
1014
  summary() {
928
1015
  return this.request("GET", "/v1/graph/summary");
@@ -39,7 +39,15 @@ export declare class GraphNamespace {
39
39
  batchSize?: number;
40
40
  limit?: number;
41
41
  full?: boolean;
42
+ pollIntervalMs?: number;
42
43
  }): Promise<Schemas["ManagedEmbeddingBackfillResponse"]>;
44
+ submitEmbeddingBackfill(options?: CallOptions & {
45
+ batchSize?: number;
46
+ limit?: number;
47
+ full?: boolean;
48
+ }): Promise<Schemas["ManagedEmbeddingBackfillJobStatusResponse"]>;
49
+ embeddingBackfillJob(jobId: string): Promise<Schemas["ManagedEmbeddingBackfillJobStatusResponse"]>;
50
+ cancelEmbeddingBackfill(jobId: string): Promise<Schemas["ManagedEmbeddingBackfillJobStatusResponse"]>;
43
51
  promoteEmbedding(options: CallOptions & {
44
52
  runId: string;
45
53
  allowRegression?: boolean;
@@ -77,6 +85,7 @@ export declare class SearchNamespace {
77
85
  multi(body: Schemas["HybridMultiSearchRequest"], opts?: CallOptions): Promise<Schemas["HybridMultiSearchResponse"]>;
78
86
  feedback(body: Schemas["SearchFeedbackRequest"], opts?: CallOptions): Promise<Schemas["SearchFeedbackResponse"]>;
79
87
  feedbackExport(opts?: CallOptions): Promise<Schemas["SearchFeedbackExportResponse"]>;
88
+ feedbackSummary(opts?: CallOptions): Promise<Schemas["SearchFeedbackSummaryResponse"]>;
80
89
  fullText(body: Schemas["FullTextSearchRequest"], opts?: CallOptions): Promise<Schemas["FullTextSearchResponse"]>;
81
90
  vector(body: Schemas["EmbeddingSearchRequest"], opts?: CallOptions): Promise<Schemas["EmbeddingSearchResponse"]>;
82
91
  }
@@ -53,12 +53,29 @@ export class GraphNamespace {
53
53
  });
54
54
  }
55
55
  backfillEmbeddings(options = {}) {
56
- const { batchSize, limit, full, ...request } = options;
57
- return this.client.request("POST", "/v1/graph/embedding/backfill", {
58
- ...request,
59
- query: { batch_size: batchSize, limit, full },
56
+ return this.client.backfillEmbeddings({
57
+ batchSize: options.batchSize,
58
+ limit: options.limit,
59
+ full: options.full,
60
+ idempotencyKey: options.idempotencyKey,
61
+ timeoutMs: options.timeoutMs,
62
+ pollIntervalMs: options.pollIntervalMs,
63
+ });
64
+ }
65
+ submitEmbeddingBackfill(options = {}) {
66
+ return this.client.submitEmbeddingBackfill({
67
+ batchSize: options.batchSize,
68
+ limit: options.limit,
69
+ full: options.full,
70
+ idempotencyKey: options.idempotencyKey,
60
71
  });
61
72
  }
73
+ embeddingBackfillJob(jobId) {
74
+ return this.client.embeddingBackfillJob(jobId);
75
+ }
76
+ cancelEmbeddingBackfill(jobId) {
77
+ return this.client.cancelEmbeddingBackfill(jobId);
78
+ }
62
79
  promoteEmbedding(options) {
63
80
  const { runId, allowRegression, ...request } = options;
64
81
  return this.client.request("POST", "/v1/graph/embedding/promote", {
@@ -184,6 +201,9 @@ export class SearchNamespace {
184
201
  feedbackExport(opts = {}) {
185
202
  return this.client.request("GET", "/v1/search/feedback/export", opts);
186
203
  }
204
+ feedbackSummary(opts = {}) {
205
+ return this.client.request("GET", "/v1/search/feedback/summary", opts);
206
+ }
187
207
  fullText(body, opts = {}) {
188
208
  return this.client.request("POST", "/v1/search/full-text", {
189
209
  ...opts,