@littlebigbrain/client 0.5.2 → 0.6.1

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,96 +1,89 @@
1
1
  # @littlebigbrain/client
2
2
 
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`.
3
+ The typed TypeScript client for [Little Big Brain](https://littlebigbrain.com) — write graph facts, build indexes, and run hybrid search over one snapshot. Request and response types are generated from the API contract, so every call is fully typed. Runs anywhere there's a global `fetch`: Node 18+, browsers, and edge workers.
6
4
 
7
5
  ```sh
8
6
  npm install @littlebigbrain/client
9
7
  ```
10
8
 
11
- ## Five-minute start
9
+ ## Quickstart
12
10
 
13
11
  ```ts
14
12
  import { LbbClient } from "@littlebigbrain/client";
15
13
 
16
14
  const lbb = new LbbClient({
17
- baseUrl: "https://db.eu.littlebigbrain.com",
18
- apiKey: process.env.LBB_API_KEY,
15
+ baseUrl: "https://0abc1def--production.db.eu.littlebigbrain.com",
16
+ apiKey: process.env.LBB_API_KEY, // lbb_sk_live_… — keep it server-side
19
17
  });
20
18
  const graph = lbb.graph("main");
21
19
 
22
- await graph.facts.create({
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" });
20
+ // 1. Write a fact.
21
+ await graph.facts.create(
22
+ {
23
+ triplets: [
24
+ {
25
+ source: { type: "CONCEPT", name: "policy-42" },
26
+ relation: "RELATED_TO",
27
+ target: { type: "CONCEPT", name: "seven-year retention" },
28
+ evidence: "Customer records are retained for seven years.",
29
+ },
30
+ ],
31
+ },
32
+ { idempotencyKey: "policy-42-v1" },
33
+ );
30
34
 
35
+ // 2. Build persisted BM25 + vector + adjacency indexes and wait.
31
36
  await graph.indexes.run({ wait: true });
32
37
 
38
+ // 3. Hybrid search over the snapshot.
33
39
  const results = await graph.search.hybrid(
34
40
  "How long are customer records retained?",
35
41
  { topK: 10, source: "persisted", consistency: "strong" },
36
42
  );
37
43
  ```
38
44
 
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.
42
-
43
- ## Enterprise search integrations
44
-
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:
48
-
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.
45
+ For hosted use, `baseUrl` is required and must be the exact `endpoint_url`
46
+ shown on the stack's Connect page. Graph and branch remain client scope
47
+ parameters; they are not encoded in the hostname.
56
48
 
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.
49
+ ## Examples
61
50
 
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.
51
+ **Search with filters.** Pass the request body to filter before ranking — here, only facts an ACL principal may see:
67
52
 
68
- The [enterprise-search integration guide](https://docs.littlebigbrain.com/guides/enterprise-search/)
69
- contains the graph model, migration sequence, and acceptance tests.
53
+ ```ts
54
+ const results = await graph.search.hybrid({
55
+ query: "incident response runbook",
56
+ targets: ["entities"],
57
+ search: {
58
+ filters: {
59
+ op: "overlaps",
60
+ field: "acl",
61
+ values: ["user:rino@example.com", "group:engineering"],
62
+ },
63
+ },
64
+ top_k: 20,
65
+ });
66
+ ```
70
67
 
71
- ## Main surface
68
+ **Bulk import.** Load an array of records (or an NDJSON string) in one call:
72
69
 
73
70
  ```ts
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(...)
71
+ await graph.facts.import(
72
+ [
73
+ { source: { type: "DOC", name: "handbook", key: "doc:42" }, relation: "HAS_PASSAGE", target: { type: "PASSAGE", name: "leave-policy", key: "p:42:1" } },
74
+ // …one record per line
75
+ ],
76
+ { idempotencyKey: "handbook-batch-1" },
77
+ );
82
78
  ```
83
79
 
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.
80
+ **Time-travel read.** Pin any search to a past instant — results reflect the graph as it was then:
89
81
 
90
- Use `rawRequest()` when you need response headers, request ID, retry count, or
91
- elapsed time. `onRequest` and `onResponse` provide body-free instrumentation.
82
+ ```ts
83
+ const asOf = await graph.search.hybrid("retention policy", { asOf: "2026-01-01T00:00:00Z" });
84
+ ```
92
85
 
93
- ## SPARQL
86
+ **SPARQL.** `sparqlRows` runs a SPARQL 1.1 SELECT/ASK and returns parsed rows:
94
87
 
95
88
  ```ts
96
89
  const { rows } = await lbb.sparqlRows({
@@ -98,15 +91,21 @@ const { rows } = await lbb.sparqlRows({
98
91
  });
99
92
  ```
100
93
 
101
- `sparqlRows` parses SELECT/ASK results. The native SPARQL 1.1 Protocol is also
102
- available at `/sparql` for standard RDF clients.
94
+ ## Errors & retries
95
+
96
+ Methods return parsed JSON and throw `LbbError` (with `status`, `code`, `message`, `param`, `requestId`, `docUrl`) on any non-2xx response. Safe reads and idempotency-keyed writes retry `429`/`5xx` and network failures with full-jitter backoff, bounded by a retry budget (`retryBudgetMs`, default 60s) rather than a fixed count, and honor `Retry-After` — a terminal error the server marks non-retryable surfaces immediately. Use `rawRequest()` for response headers, request id, and retry/timing metadata.
97
+
98
+ ## More
99
+
100
+ The `graph(...)` scope exposes `facts`, `search`, `entities`, `indexes`, `ontology`, `query`, `schema`, and `context` namespaces — covering managed embeddings, multi-query fusion, traversal, temporal state and history, SHACL, ontology evolution, and durable index jobs. Every generated shape is available as `Schemas["TypeName"]`.
101
+
102
+ Full reference and guides: [docs.littlebigbrain.com/sdks/typescript](https://docs.littlebigbrain.com/sdks/typescript/).
103
103
 
104
104
  ## Develop
105
105
 
106
106
  ```sh
107
107
  npm install
108
- npm run generate
108
+ npm run generate # regenerate types from contracts/openapi.json
109
109
  npm run typecheck
110
110
  npm test
111
- npm run pack:check
112
111
  ```
package/dist/client.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { ImportLine, LbbClientOptions, LbbStackActivityResponse, LbbStackAc
2
2
  import { type RequestOptions } from "./transport.js";
3
3
  import { ContextNamespace, EntityNamespace, GraphNamespace, IndexNamespace, OntologyNamespace, QueryNamespace, SchemaNamespace, SearchNamespace } from "./namespaces.js";
4
4
  export { parseSparqlResults } from "./types.js";
5
- export type { AttributeFilter, AttributeFilterOp, AttributeFilterValue, EntityAttributeFilterOptions, EntityPropertiesLine, FetchLike, FlatProperties, ImportLine, LbbClientOptions, LbbRequestEvent, LbbResponseEvent, LbbErrorPayload, LbbStackActivityResponse, LbbStackActivityWindow, ListResponse, RawLbbResponse, RdfExportOptions, RdfImportOptions, Schemas, SparqlResults, SparqlResultsJson, SparqlTerm, AskRequest, AskResponse, CommitRequest, CommitResponse, Entity, EntitySelector, GraphMetadata, GraphSummary, SchemaView, SearchRequest, SearchResponse, SearchResult, Snapshot, } from "./types.js";
5
+ export type { AttributeFilter, AttributeFilterOp, AttributeFilterValue, EntityAttributeFilterOptions, EntityPropertiesLine, FetchLike, FlatProperties, ImportLine, LbbClientOptions, LbbRequestEvent, LbbResponseEvent, LbbRetryEvent, LbbErrorPayload, LbbStackActivityResponse, LbbStackActivityWindow, ListResponse, RawLbbResponse, RdfExportOptions, RdfImportOptions, Schemas, SparqlResults, SparqlResultsJson, SparqlTerm, AskRequest, AskResponse, CommitRequest, CommitResponse, Entity, EntitySelector, GraphMetadata, GraphSummary, SchemaView, SearchRequest, SearchResponse, SearchResult, Snapshot, } from "./types.js";
6
6
  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";
@@ -31,9 +31,11 @@ export declare class LbbClient {
31
31
  private readonly apiVersion;
32
32
  private readonly maxRetries;
33
33
  private readonly retryDelayMs;
34
+ private readonly retryBudgetMs;
34
35
  private readonly timeoutMs;
35
36
  private readonly onRequest?;
36
37
  private readonly onResponse?;
38
+ private readonly onRetry?;
37
39
  readonly context: ContextNamespace;
38
40
  readonly search: SearchNamespace;
39
41
  readonly indexes: IndexNamespace;
@@ -132,15 +134,25 @@ export declare class LbbClient {
132
134
  observe(body: Schemas["ObserveRequest"], opts?: {
133
135
  idempotencyKey?: string;
134
136
  }): Promise<Schemas["ObserveResponse"]>;
135
- /**
136
- * Delete every object under the scoped graph/branch — a destructive reset.
137
- * `confirm` must equal the scoped graph id; the next commit re-initializes the
138
- * graph. Branch-scoped: sibling branches are untouched.
139
- */
137
+ /** Delete the scoped graph, including every branch, feedback, and active graph-scoped job. */
140
138
  deleteGraph(opts: {
141
139
  confirm: string;
142
- }): Promise<unknown>;
140
+ }): Promise<Schemas["GraphDeleteResponse"]>;
141
+ /** Delete only the scoped branch. The server refuses to delete a graph's final live branch. */
142
+ deleteBranch(opts: {
143
+ confirm: string;
144
+ }): Promise<Schemas["GraphBranchDeleteResponse"]>;
143
145
  embeddingConfig(): Promise<Schemas["ManagedEmbeddingConfigResponse"]>;
146
+ /** List the embedding models available on this deployment. */
147
+ embeddingModels(): Promise<Schemas["ManagedEmbeddingModelsResponse"]>;
148
+ /**
149
+ * Choose the model used automatically for writes and vector queries.
150
+ * Provider credentials and native dimension discovery stay server-side.
151
+ */
152
+ setEmbeddingModel(modelId: string, opts?: {
153
+ autoEmbedQuery?: boolean;
154
+ }): Promise<Schemas["ManagedEmbeddingConfigResponse"]>;
155
+ /** Advanced configuration escape hatch. Prefer `setEmbeddingModel`. */
144
156
  setEmbeddingConfig(body: Schemas["ManagedEmbeddingConfigRequest"]): Promise<Schemas["ManagedEmbeddingConfigResponse"]>;
145
157
  submitEmbeddingBackfill(opts?: {
146
158
  batchSize?: number;
@@ -539,6 +551,14 @@ export declare class LbbClient {
539
551
  indexRun(opts?: {
540
552
  background?: boolean;
541
553
  }): Promise<unknown>;
554
+ /** Submit a durable full-index build. Requires a reconnect-safe idempotency key. */
555
+ indexSubmit(body: Partial<Schemas["IndexBuildOptions"]> | undefined, opts: {
556
+ idempotencyKey: string;
557
+ }): Promise<Schemas["SearchIndexJobStatusResponse"]>;
558
+ /** Poll a durable full-index build. */
559
+ indexJob(jobId: string): Promise<Schemas["SearchIndexJobStatusResponse"]>;
560
+ /** Cancel a durable full-index build. Repeated cancellation returns its current terminal status. */
561
+ cancelIndexJob(jobId: string): Promise<Schemas["SearchIndexJobStatusResponse"]>;
542
562
  /** Append a BM25 delta segment for the unindexed WAL tail. */
543
563
  indexDelta(): Promise<Schemas["IndexDeltaResponse"]>;
544
564
  /** Preview or delete superseded persisted index runs. */
@@ -546,6 +566,14 @@ export declare class LbbClient {
546
566
  keepRuns?: number;
547
567
  dryRun?: boolean;
548
568
  }): Promise<Schemas["IndexGcResponse"]>;
569
+ /** Submit durable, cancellable index garbage collection. */
570
+ indexGcSubmit(body: Schemas["IndexGcRequest"] | undefined, opts: {
571
+ idempotencyKey: string;
572
+ }): Promise<Schemas["IndexGcJobStatusResponse"]>;
573
+ /** Poll exact planning/deletion progress for durable index garbage collection. */
574
+ indexGcJob(jobId: string): Promise<Schemas["IndexGcJobStatusResponse"]>;
575
+ /** Cancel durable index garbage collection. */
576
+ cancelIndexGcJob(jobId: string): Promise<Schemas["IndexGcJobStatusResponse"]>;
549
577
  /** Fold the WAL tail into snapshot segments. */
550
578
  compact(opts?: {
551
579
  minTailCommits?: number;
package/dist/client.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { parseSparqlResults } from "./types.js";
2
- import { parseLbbError, parseResponseJson, retryAllowed, retryDelayForAttempt, retryableStatus, sleep, } from "./transport.js";
2
+ import { bodyMarksTerminal, errorCodeFromBody, fullJitterBackoffMs, parseLbbError, parseResponseJson, retryAllowed, retryableStatus, retryDelayMs, sleep, } from "./transport.js";
3
3
  import { ContextNamespace, EntityNamespace, GraphNamespace, IndexNamespace, OntologyNamespace, QueryNamespace, SchemaNamespace, SearchNamespace, } from "./namespaces.js";
4
4
  export { parseSparqlResults } from "./types.js";
5
5
  export { LbbError } from "./transport.js";
@@ -19,9 +19,11 @@ export class LbbClient {
19
19
  apiVersion;
20
20
  maxRetries;
21
21
  retryDelayMs;
22
+ retryBudgetMs;
22
23
  timeoutMs;
23
24
  onRequest;
24
25
  onResponse;
26
+ onRetry;
25
27
  context;
26
28
  search;
27
29
  indexes;
@@ -30,23 +32,32 @@ export class LbbClient {
30
32
  ontology;
31
33
  query;
32
34
  constructor(options) {
33
- this.baseUrl = options.baseUrl.replace(/\/+$/, "");
35
+ const baseUrl = options.baseUrl?.trim();
36
+ if (!baseUrl) {
37
+ throw new Error("baseUrl is required; copy endpoint_url from the stack's Connect page for hosted use");
38
+ }
39
+ this.baseUrl = baseUrl.replace(/\/+$/, "");
34
40
  this.apiKey = options.apiKey;
35
41
  this.graphName = options.graph;
36
42
  this.branchName = options.branch;
37
43
  this.stack = options.stack;
38
44
  this.apiVersion = options.apiVersion ?? "2026-06-22";
39
- this.maxRetries = options.maxRetries ?? 2;
45
+ this.maxRetries = options.maxRetries ?? 6;
40
46
  this.retryDelayMs = options.retryDelayMs ?? 100;
47
+ this.retryBudgetMs = options.retryBudgetMs ?? 60_000;
41
48
  this.timeoutMs = options.timeoutMs ?? 120_000;
42
49
  this.onRequest = options.onRequest;
43
50
  this.onResponse = options.onResponse;
51
+ this.onRetry = options.onRetry;
44
52
  if (!Number.isInteger(this.maxRetries) || this.maxRetries < 0) {
45
53
  throw new RangeError("maxRetries must be a non-negative integer");
46
54
  }
47
55
  if (!Number.isFinite(this.retryDelayMs) || this.retryDelayMs < 0) {
48
56
  throw new RangeError("retryDelayMs must be a non-negative number");
49
57
  }
58
+ if (!Number.isFinite(this.retryBudgetMs) || this.retryBudgetMs < 0) {
59
+ throw new RangeError("retryBudgetMs must be a non-negative number");
60
+ }
50
61
  if (!Number.isFinite(this.timeoutMs) || this.timeoutMs < 0) {
51
62
  throw new RangeError("timeoutMs must be a non-negative number");
52
63
  }
@@ -87,9 +98,11 @@ export class LbbClient {
87
98
  apiVersion: this.apiVersion,
88
99
  maxRetries: this.maxRetries,
89
100
  retryDelayMs: this.retryDelayMs,
101
+ retryBudgetMs: this.retryBudgetMs,
90
102
  timeoutMs: this.timeoutMs,
91
103
  onRequest: this.onRequest,
92
104
  onResponse: this.onResponse,
105
+ onRetry: this.onRetry,
93
106
  });
94
107
  }
95
108
  buildUrl(path, query) {
@@ -135,6 +148,8 @@ export class LbbClient {
135
148
  throw new RangeError("maxRetries must be a non-negative integer");
136
149
  }
137
150
  const startedAt = Date.now();
151
+ // Deadline is the binding limit; `maxRetries` is a secondary safety cap.
152
+ const deadline = startedAt + Math.max(0, opts.retryBudgetMs ?? this.retryBudgetMs);
138
153
  const url = this.buildUrl(path, opts.query);
139
154
  let attempts = 0;
140
155
  let response;
@@ -175,8 +190,19 @@ export class LbbClient {
175
190
  }), { name: "TimeoutError" })
176
191
  : error;
177
192
  if (!callerAborted && canRetry && attempt < maxRetries) {
178
- await sleep(this.retryDelayMs * (attempt + 1));
179
- continue;
193
+ const delayMs = fullJitterBackoffMs(this.retryDelayMs, attempt);
194
+ if (Date.now() + delayMs <= deadline) {
195
+ this.onRetry?.({
196
+ method: method.toUpperCase(),
197
+ url,
198
+ attempt: attempts,
199
+ status: undefined,
200
+ delayMs,
201
+ elapsedMs: Math.max(0, Date.now() - startedAt),
202
+ });
203
+ await sleep(delayMs);
204
+ continue;
205
+ }
180
206
  }
181
207
  throw requestError;
182
208
  }
@@ -193,7 +219,29 @@ export class LbbClient {
193
219
  if (!canRetry) {
194
220
  break;
195
221
  }
196
- await sleep(retryDelayForAttempt(this.retryDelayMs, attempt, response.headers?.get("retry-after")));
222
+ // Honor the server's typed body verdict: a terminal error
223
+ // (`retryable: false`, e.g. an exhausted quota) is surfaced at once
224
+ // rather than retried to the budget.
225
+ if (bodyMarksTerminal(text)) {
226
+ break;
227
+ }
228
+ const delayMs = retryDelayMs(this.retryDelayMs, attempt, {
229
+ retryAfterHeader: response.headers?.get("retry-after"),
230
+ body: text,
231
+ });
232
+ if (Date.now() + delayMs > deadline) {
233
+ break;
234
+ }
235
+ this.onRetry?.({
236
+ method: method.toUpperCase(),
237
+ url,
238
+ attempt: attempts,
239
+ status: response.status,
240
+ errorCode: errorCodeFromBody(text),
241
+ delayMs,
242
+ elapsedMs: Math.max(0, Date.now() - startedAt),
243
+ });
244
+ await sleep(delayMs);
197
245
  }
198
246
  if (response === undefined)
199
247
  throw new Error("request did not produce a response");
@@ -379,19 +427,38 @@ export class LbbClient {
379
427
  idempotencyKey: opts.idempotencyKey ?? this.idempotencyKey("observe"),
380
428
  });
381
429
  }
382
- /**
383
- * Delete every object under the scoped graph/branch — a destructive reset.
384
- * `confirm` must equal the scoped graph id; the next commit re-initializes the
385
- * graph. Branch-scoped: sibling branches are untouched.
386
- */
430
+ /** Delete the scoped graph, including every branch, feedback, and active graph-scoped job. */
387
431
  deleteGraph(opts) {
388
432
  return this.request("POST", "/v1/graph/delete", {
389
433
  query: { confirm: opts.confirm },
434
+ retry: true,
435
+ });
436
+ }
437
+ /** Delete only the scoped branch. The server refuses to delete a graph's final live branch. */
438
+ deleteBranch(opts) {
439
+ return this.request("DELETE", "/v1/graph/branch", {
440
+ query: { confirm: opts.confirm },
390
441
  });
391
442
  }
392
443
  embeddingConfig() {
393
444
  return this.request("GET", "/v1/graph/embedding");
394
445
  }
446
+ /** List the embedding models available on this deployment. */
447
+ embeddingModels() {
448
+ return this.request("GET", "/v1/graph/embedding/models");
449
+ }
450
+ /**
451
+ * Choose the model used automatically for writes and vector queries.
452
+ * Provider credentials and native dimension discovery stay server-side.
453
+ */
454
+ setEmbeddingModel(modelId, opts = {}) {
455
+ return this.setEmbeddingConfig({
456
+ model_id: modelId,
457
+ service: "open_router",
458
+ auto_embed_query: opts.autoEmbedQuery ?? true,
459
+ });
460
+ }
461
+ /** Advanced configuration escape hatch. Prefer `setEmbeddingModel`. */
395
462
  setEmbeddingConfig(body) {
396
463
  return this.request("POST", "/v1/graph/embedding", { body });
397
464
  }
@@ -951,6 +1018,23 @@ export class LbbClient {
951
1018
  query: { background: opts.background || undefined },
952
1019
  });
953
1020
  }
1021
+ /** Submit a durable full-index build. Requires a reconnect-safe idempotency key. */
1022
+ indexSubmit(body = {}, opts) {
1023
+ return this.request("POST", "/v1/index/jobs", {
1024
+ body,
1025
+ idempotencyKey: opts.idempotencyKey,
1026
+ });
1027
+ }
1028
+ /** Poll a durable full-index build. */
1029
+ indexJob(jobId) {
1030
+ return this.request("GET", "/v1/index/jobs", { query: { job_id: jobId } });
1031
+ }
1032
+ /** Cancel a durable full-index build. Repeated cancellation returns its current terminal status. */
1033
+ cancelIndexJob(jobId) {
1034
+ return this.request("DELETE", "/v1/index/jobs", {
1035
+ query: { job_id: jobId },
1036
+ });
1037
+ }
954
1038
  /** Append a BM25 delta segment for the unindexed WAL tail. */
955
1039
  indexDelta() {
956
1040
  return this.request("POST", "/v1/index/delta");
@@ -961,6 +1045,25 @@ export class LbbClient {
961
1045
  query: { keep_runs: opts.keepRuns, dry_run: opts.dryRun },
962
1046
  });
963
1047
  }
1048
+ /** Submit durable, cancellable index garbage collection. */
1049
+ indexGcSubmit(body = {}, opts) {
1050
+ return this.request("POST", "/v1/index/gc-jobs", {
1051
+ body,
1052
+ idempotencyKey: opts.idempotencyKey,
1053
+ });
1054
+ }
1055
+ /** Poll exact planning/deletion progress for durable index garbage collection. */
1056
+ indexGcJob(jobId) {
1057
+ return this.request("GET", "/v1/index/gc-jobs", {
1058
+ query: { job_id: jobId },
1059
+ });
1060
+ }
1061
+ /** Cancel durable index garbage collection. */
1062
+ cancelIndexGcJob(jobId) {
1063
+ return this.request("DELETE", "/v1/index/gc-jobs", {
1064
+ query: { job_id: jobId },
1065
+ });
1066
+ }
964
1067
  /** Fold the WAL tail into snapshot segments. */
965
1068
  compact(opts = {}) {
966
1069
  return this.request("POST", "/v1/graph/compact", {
@@ -32,8 +32,18 @@ export declare class GraphNamespace {
32
32
  create(opts?: CallOptions): Promise<Schemas["CreateGraphResponse"]>;
33
33
  delete(opts: {
34
34
  confirm: string;
35
- } & CallOptions): Promise<unknown>;
35
+ } & CallOptions): Promise<Schemas["GraphDeleteResponse"]>;
36
+ deleteBranch(opts: {
37
+ confirm: string;
38
+ } & CallOptions): Promise<Schemas["GraphBranchDeleteResponse"]>;
36
39
  embeddingConfig(opts?: CallOptions): Promise<Schemas["ManagedEmbeddingConfigResponse"]>;
40
+ /** List the embedding models available on this deployment. */
41
+ embeddingModels(opts?: CallOptions): Promise<Schemas["ManagedEmbeddingModelsResponse"]>;
42
+ /** Choose the model used automatically for writes and vector queries. */
43
+ setEmbeddingModel(modelId: string, options?: CallOptions & {
44
+ autoEmbedQuery?: boolean;
45
+ }): Promise<Schemas["ManagedEmbeddingConfigResponse"]>;
46
+ /** Advanced configuration escape hatch. Prefer `setEmbeddingModel`. */
37
47
  setEmbeddingConfig(body: Schemas["ManagedEmbeddingConfigRequest"], opts?: CallOptions): Promise<Schemas["ManagedEmbeddingConfigResponse"]>;
38
48
  backfillEmbeddings(options?: CallOptions & {
39
49
  batchSize?: number;
@@ -115,10 +125,20 @@ export declare class IndexNamespace {
115
125
  background?: boolean;
116
126
  } & CallOptions): Promise<unknown>;
117
127
  delta(opts?: CallOptions): Promise<Schemas["IndexDeltaResponse"]>;
128
+ submit(body: Partial<Schemas["IndexBuildOptions"]> | undefined, opts: CallOptions & {
129
+ idempotencyKey: string;
130
+ }): Promise<Schemas["SearchIndexJobStatusResponse"]>;
131
+ job(jobId: string, opts?: CallOptions): Promise<Schemas["SearchIndexJobStatusResponse"]>;
132
+ cancel(jobId: string, opts?: CallOptions): Promise<Schemas["SearchIndexJobStatusResponse"]>;
118
133
  gc(opts?: {
119
134
  keepRuns?: number;
120
135
  dryRun?: boolean;
121
136
  } & CallOptions): Promise<Schemas["IndexGcResponse"]>;
137
+ submitGc(body: Schemas["IndexGcRequest"] | undefined, opts: CallOptions & {
138
+ idempotencyKey: string;
139
+ }): Promise<Schemas["IndexGcJobStatusResponse"]>;
140
+ gcJob(jobId: string, opts?: CallOptions): Promise<Schemas["IndexGcJobStatusResponse"]>;
141
+ cancelGc(jobId: string, opts?: CallOptions): Promise<Schemas["IndexGcJobStatusResponse"]>;
122
142
  }
123
143
  export declare class EntityNamespace {
124
144
  private readonly client;
@@ -41,11 +41,36 @@ export class GraphNamespace {
41
41
  return this.client.request("POST", "/v1/graph/delete", {
42
42
  ...request,
43
43
  query: { confirm },
44
+ retry: request.retry ?? true,
45
+ });
46
+ }
47
+ deleteBranch(opts) {
48
+ const { confirm, ...request } = opts;
49
+ return this.client.request("DELETE", "/v1/graph/branch", {
50
+ ...request,
51
+ query: { confirm },
44
52
  });
45
53
  }
46
54
  embeddingConfig(opts = {}) {
47
55
  return this.client.request("GET", "/v1/graph/embedding", opts);
48
56
  }
57
+ /** List the embedding models available on this deployment. */
58
+ embeddingModels(opts = {}) {
59
+ return this.client.request("GET", "/v1/graph/embedding/models", opts);
60
+ }
61
+ /** Choose the model used automatically for writes and vector queries. */
62
+ setEmbeddingModel(modelId, options = {}) {
63
+ const { autoEmbedQuery, ...request } = options;
64
+ return this.client.request("POST", "/v1/graph/embedding", {
65
+ ...request,
66
+ body: {
67
+ model_id: modelId,
68
+ service: "open_router",
69
+ auto_embed_query: autoEmbedQuery ?? true,
70
+ },
71
+ });
72
+ }
73
+ /** Advanced configuration escape hatch. Prefer `setEmbeddingModel`. */
49
74
  setEmbeddingConfig(body, opts = {}) {
50
75
  return this.client.request("POST", "/v1/graph/embedding", {
51
76
  ...opts,
@@ -276,6 +301,21 @@ export class IndexNamespace {
276
301
  delta(opts = {}) {
277
302
  return this.client.request("POST", "/v1/index/delta", opts);
278
303
  }
304
+ submit(body = {}, opts) {
305
+ return this.client.request("POST", "/v1/index/jobs", { ...opts, body });
306
+ }
307
+ job(jobId, opts = {}) {
308
+ return this.client.request("GET", "/v1/index/jobs", {
309
+ ...opts,
310
+ query: { job_id: jobId },
311
+ });
312
+ }
313
+ cancel(jobId, opts = {}) {
314
+ return this.client.request("DELETE", "/v1/index/jobs", {
315
+ ...opts,
316
+ query: { job_id: jobId },
317
+ });
318
+ }
279
319
  gc(opts = {}) {
280
320
  const { keepRuns, dryRun, ...request } = opts;
281
321
  return this.client.request("POST", "/v1/index/gc", {
@@ -283,6 +323,21 @@ export class IndexNamespace {
283
323
  query: { keep_runs: keepRuns, dry_run: dryRun },
284
324
  });
285
325
  }
326
+ submitGc(body = {}, opts) {
327
+ return this.client.request("POST", "/v1/index/gc-jobs", { ...opts, body });
328
+ }
329
+ gcJob(jobId, opts = {}) {
330
+ return this.client.request("GET", "/v1/index/gc-jobs", {
331
+ ...opts,
332
+ query: { job_id: jobId },
333
+ });
334
+ }
335
+ cancelGc(jobId, opts = {}) {
336
+ return this.client.request("DELETE", "/v1/index/gc-jobs", {
337
+ ...opts,
338
+ query: { job_id: jobId },
339
+ });
340
+ }
286
341
  }
287
342
  export class EntityNamespace {
288
343
  client;