@littlebigbrain/client 0.6.1 → 0.8.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/client.d.ts +80 -18
- package/dist/client.js +142 -28
- package/dist/index.d.ts +1 -1
- package/dist/namespaces.d.ts +19 -6
- package/dist/namespaces.js +46 -6
- package/dist/schema.d.ts +754 -88
- package/dist/types.d.ts +26 -76
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { ImportLine, LbbClientOptions,
|
|
2
|
-
import { type RequestOptions } from "./transport.js";
|
|
1
|
+
import type { ImportLine, LbbClientOptions, ListResponse, RawLbbResponse, ReadConsistencyOptions, RdfExportOptions, RdfImportOptions, Schemas, SearchConsistency, SparqlResults } from "./types.js";
|
|
2
|
+
import { type CallOptions, 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, LbbRetryEvent, LbbErrorPayload,
|
|
5
|
+
export type { AttributeFilter, AttributeFilterOp, AttributeFilterValue, EntityAttributeFilterOptions, EntityPropertiesLine, FetchLike, FlatProperties, ImportLine, LbbClientOptions, LbbRequestEvent, LbbResponseEvent, LbbRetryEvent, LbbErrorPayload, ListResponse, RawLbbResponse, ReadConsistencyOptions, RdfExportOptions, RdfImportOptions, Schemas, SearchConsistency, 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";
|
|
@@ -36,6 +36,8 @@ export declare class LbbClient {
|
|
|
36
36
|
private readonly onRequest?;
|
|
37
37
|
private readonly onResponse?;
|
|
38
38
|
private readonly onRetry?;
|
|
39
|
+
/** A5 default read consistency applied when a read omits its own value. */
|
|
40
|
+
readonly defaultConsistency?: SearchConsistency;
|
|
39
41
|
readonly context: ContextNamespace;
|
|
40
42
|
readonly search: SearchNamespace;
|
|
41
43
|
readonly indexes: IndexNamespace;
|
|
@@ -58,6 +60,17 @@ export declare class LbbClient {
|
|
|
58
60
|
branch?: string;
|
|
59
61
|
stack?: string;
|
|
60
62
|
}): LbbClient;
|
|
63
|
+
/**
|
|
64
|
+
* A5: fold read-consistency options into a request body's own `consistency` /
|
|
65
|
+
* `min_indexed_seq` fields (the shape used by full-text, embedding, and
|
|
66
|
+
* structured-SPARQL bodies). A per-call value wins over the client
|
|
67
|
+
* `defaultConsistency`; an explicit body field wins over both.
|
|
68
|
+
*/
|
|
69
|
+
resolveConsistency(opts?: ReadConsistencyOptions): SearchConsistency | undefined;
|
|
70
|
+
private mergeReadConsistency;
|
|
71
|
+
/** A5: read-consistency options rendered as URL query params, for the routes
|
|
72
|
+
* that carry consistency on the URL (SPARQL-text, graph summary). */
|
|
73
|
+
private readConsistencyQuery;
|
|
61
74
|
private buildUrl;
|
|
62
75
|
rawRequest<T>(method: string, path: string, opts?: RequestOptions): Promise<RawLbbResponse<T>>;
|
|
63
76
|
request<T>(method: string, path: string, opts?: RequestOptions): Promise<T>;
|
|
@@ -66,7 +79,9 @@ export declare class LbbClient {
|
|
|
66
79
|
/** Commit triplets and optional entity embeddings. Prefer `client.graph("main").facts.create(...)`. */
|
|
67
80
|
commit(body: Schemas["TripletCommitFile"], opts?: {
|
|
68
81
|
idempotencyKey?: string;
|
|
69
|
-
}): Promise<Schemas["GraphCommitResponse"]
|
|
82
|
+
}): Promise<Schemas["GraphCommitResponse"] & {
|
|
83
|
+
commitSeq: number;
|
|
84
|
+
}>;
|
|
70
85
|
/**
|
|
71
86
|
* Validate-only preflight: run the same ontology/schema validation a real
|
|
72
87
|
* commit would and report the would-be effect (`op_count`, `written_properties`,
|
|
@@ -95,7 +110,9 @@ export declare class LbbClient {
|
|
|
95
110
|
observedAt?: string;
|
|
96
111
|
index?: boolean;
|
|
97
112
|
idempotencyKey?: string;
|
|
98
|
-
}): Promise<Schemas["GraphImportResponse"]
|
|
113
|
+
}): Promise<Schemas["GraphImportResponse"] & {
|
|
114
|
+
commitSeq: number | null;
|
|
115
|
+
}>;
|
|
99
116
|
/**
|
|
100
117
|
* Bulk-ingest N-Triples, Turtle, N-Quads, or TriG without client-side conversion. Resource-object
|
|
101
118
|
* triples become keyed Resource edges; literal-object triples become text
|
|
@@ -115,6 +132,42 @@ export declare class LbbClient {
|
|
|
115
132
|
}): Promise<Schemas["GraphRetractResponse"]>;
|
|
116
133
|
/** Create the scoped graph/branch. Construct the client with the desired graph/branch first. */
|
|
117
134
|
createGraph(): Promise<Schemas["CreateGraphResponse"]>;
|
|
135
|
+
/**
|
|
136
|
+
* Fork a whole graph into a brand-new destination graph in the same tenant.
|
|
137
|
+
* The copy runs as a durable background job (`confirm` is fixed to `dst`, which
|
|
138
|
+
* the route requires to authorize the fork); the destination must not already
|
|
139
|
+
* exist, so the create-only CAS on the server side makes the call safe to
|
|
140
|
+
* retry. The response only acknowledges the enqueue — poll the destination
|
|
141
|
+
* graph's metadata (see `response.poll`) to observe the fork completing: the
|
|
142
|
+
* destination becomes readable once its head is published.
|
|
143
|
+
*/
|
|
144
|
+
forkGraph(opts: {
|
|
145
|
+
src: string;
|
|
146
|
+
dst: string;
|
|
147
|
+
}): Promise<Schemas["GraphForkResponse"]>;
|
|
148
|
+
/**
|
|
149
|
+
* Declarative full-state replace: reconcile the scoped graph so its current
|
|
150
|
+
* state matches exactly the NDJSON payload (same line grammar as
|
|
151
|
+
* {@link import} — triplets or `{type,name,properties}` entity records; pass an
|
|
152
|
+
* array, serialized here, or a pre-built NDJSON string). The whole
|
|
153
|
+
* reconciliation lands as one atomic cutover: payload records are upserted, and
|
|
154
|
+
* entities present at the pre-reload head but absent from the payload leave
|
|
155
|
+
* current state (retraction semantics — history is preserved, so an `as_of`
|
|
156
|
+
* read pinned before the cutover still sees the old state). `confirm` must
|
|
157
|
+
* equal the target graph id (reload is semi-destructive). `dryRun` previews the
|
|
158
|
+
* full delta with zero durable changes. The response carries
|
|
159
|
+
* `prior_commit_seq` / `prior_snapshot_token` as the rollback anchor — read
|
|
160
|
+
* them back with `?as_of_commit_seq=<prior_commit_seq>` to see the pre-reload
|
|
161
|
+
* state. An Idempotency-Key scopes the single cutover commit, so a retry
|
|
162
|
+
* replays rather than re-applying.
|
|
163
|
+
*/
|
|
164
|
+
reload(lines: ImportLine[] | string, opts: {
|
|
165
|
+
confirm: string;
|
|
166
|
+
dryRun?: boolean;
|
|
167
|
+
strict?: boolean;
|
|
168
|
+
observedAt?: string;
|
|
169
|
+
idempotencyKey?: string;
|
|
170
|
+
}): Promise<Schemas["GraphReloadResponse"]>;
|
|
118
171
|
/** Fork the scoped branch from an existing branch in the same graph. */
|
|
119
172
|
createBranch(body: Schemas["GraphBranchCreateRequest"]): Promise<Schemas["GraphBranchCreateResponse"]>;
|
|
120
173
|
/**
|
|
@@ -324,7 +377,7 @@ export declare class LbbClient {
|
|
|
324
377
|
allowRegression?: boolean;
|
|
325
378
|
}): Promise<unknown>;
|
|
326
379
|
/** Full semantic hybrid search from a request body (`POST /v1/graph/search`). */
|
|
327
|
-
graphSearch(body: Schemas["SemanticGraphSearchRequest"]): Promise<Schemas["SemanticGraphSearchResponse"]>;
|
|
380
|
+
graphSearch(body: Schemas["SemanticGraphSearchRequest"], opts?: ReadConsistencyOptions): Promise<Schemas["SemanticGraphSearchResponse"]>;
|
|
328
381
|
/** Reciprocal-rank-fusion across sub-queries. */
|
|
329
382
|
multiSearch(body: Schemas["HybridMultiSearchRequest"]): Promise<Schemas["HybridMultiSearchResponse"]>;
|
|
330
383
|
/**
|
|
@@ -371,9 +424,9 @@ export declare class LbbClient {
|
|
|
371
424
|
/** Export the stored relevance labels as qrels-style rows for training. */
|
|
372
425
|
searchFeedbackExport(): Promise<Schemas["SearchFeedbackExportResponse"]>;
|
|
373
426
|
/** BM25 search. */
|
|
374
|
-
fullTextSearch(body: Schemas["FullTextSearchRequest"]): Promise<Schemas["FullTextSearchResponse"]>;
|
|
427
|
+
fullTextSearch(body: Schemas["FullTextSearchRequest"], opts?: ReadConsistencyOptions): Promise<Schemas["FullTextSearchResponse"]>;
|
|
375
428
|
/** ANN/vector search. */
|
|
376
|
-
embeddingSearch(body: Schemas["EmbeddingSearchRequest"]): Promise<Schemas["EmbeddingSearchResponse"]>;
|
|
429
|
+
embeddingSearch(body: Schemas["EmbeddingSearchRequest"], opts?: ReadConsistencyOptions): Promise<Schemas["EmbeddingSearchResponse"]>;
|
|
377
430
|
/** Bounded k-hop graph traversal. */
|
|
378
431
|
traverse(body: Schemas["TraverseRequest"]): Promise<Schemas["TraverseResponse"]>;
|
|
379
432
|
/** Resolve a query to seed entities, then return bounded paths. */
|
|
@@ -385,7 +438,14 @@ export declare class LbbClient {
|
|
|
385
438
|
name?: string;
|
|
386
439
|
relations?: string[];
|
|
387
440
|
asOf?: string;
|
|
441
|
+
/** Require the bounded ranged-adjacency path; returns `index_busy` while unavailable. */
|
|
442
|
+
indexed?: boolean;
|
|
388
443
|
}): Promise<Schemas["EntityNeighborhoodResponse"]>;
|
|
444
|
+
/** Exact type cardinality plus a bounded deterministic sample from ranged adjacency. */
|
|
445
|
+
entityTypeSample(opts: {
|
|
446
|
+
type: string;
|
|
447
|
+
limit?: number;
|
|
448
|
+
} & CallOptions): Promise<Schemas["EntityTypeSampleResponse"]>;
|
|
389
449
|
/** Stored entity object-ref status and index-coverage metadata (no
|
|
390
450
|
* attributes — read those from `entityDetail`'s top-level `attributes`). */
|
|
391
451
|
entityMetadata(opts: {
|
|
@@ -459,9 +519,9 @@ export declare class LbbClient {
|
|
|
459
519
|
* keys come back per group in `groups[].value_keys[<as>]`, entity keys in
|
|
460
520
|
* `groups[].keys`.
|
|
461
521
|
*/
|
|
462
|
-
sparql(body: Schemas["SparqlSelectRequest"]): Promise<Schemas["SparqlSelectResponse"]>;
|
|
463
|
-
/** SPARQL 1.1 query from text (SELECT/ASK) over the live graph; `results` is SPARQL 1.1 Query Results JSON. */
|
|
464
|
-
sparqlText(body: Schemas["SparqlTextRequest"]): Promise<Schemas["SparqlTextResponse"]>;
|
|
522
|
+
sparql(body: Schemas["SparqlSelectRequest"], opts?: ReadConsistencyOptions): Promise<Schemas["SparqlSelectResponse"]>;
|
|
523
|
+
/** SPARQL 1.1 query from text (SELECT/ASK) over the live graph; `results` is SPARQL 1.1 Query Results JSON. The text dialect carries `consistency`/`min_indexed_seq` on the URL. */
|
|
524
|
+
sparqlText(body: Schemas["SparqlTextRequest"], opts?: ReadConsistencyOptions): Promise<Schemas["SparqlTextResponse"]>;
|
|
465
525
|
/**
|
|
466
526
|
* Run a SPARQL 1.1 text query and return parsed results — the ergonomic
|
|
467
527
|
* complement to {@link sparqlText} (which hands back the raw results string).
|
|
@@ -469,7 +529,7 @@ export declare class LbbClient {
|
|
|
469
529
|
* `rows` is the bindings flattened to `{ variable: lexicalValue }`, `boolean`
|
|
470
530
|
* is the ASK answer (or `null` for a SELECT).
|
|
471
531
|
*/
|
|
472
|
-
sparqlRows(body: Schemas["SparqlTextRequest"]): Promise<SparqlResults>;
|
|
532
|
+
sparqlRows(body: Schemas["SparqlTextRequest"], opts?: ReadConsistencyOptions): Promise<SparqlResults>;
|
|
473
533
|
/**
|
|
474
534
|
* Basic-graph-pattern query with group-graph-pattern combinators
|
|
475
535
|
* (UNION / OPTIONAL / MINUS / EXISTS / NOT EXISTS) folded over the base
|
|
@@ -581,16 +641,18 @@ export declare class LbbClient {
|
|
|
581
641
|
}): Promise<Schemas["WalCompactResponse"]>;
|
|
582
642
|
/** Server, graph, and persisted-index status. */
|
|
583
643
|
status(): Promise<unknown>;
|
|
584
|
-
/** Graph footprint, WAL tail, and index coverage. */
|
|
585
|
-
metadata(
|
|
644
|
+
/** Graph footprint, WAL tail, and index coverage. Exact object inventory is opt-in. */
|
|
645
|
+
metadata(opts?: {
|
|
646
|
+
includeObjects?: boolean;
|
|
647
|
+
includeIndexes?: boolean;
|
|
648
|
+
includeTemporalCoverage?: boolean;
|
|
649
|
+
}): Promise<Schemas["GraphMetadataResponse"]>;
|
|
586
650
|
waitForIndexLineage(targetSeq: number, opts?: {
|
|
587
651
|
timeoutMs?: number;
|
|
588
652
|
pollIntervalMs?: number;
|
|
589
653
|
}): Promise<IndexLineageObservation>;
|
|
590
|
-
/** Graph counts and type/relation buckets. */
|
|
591
|
-
summary(): Promise<Schemas["GraphSummaryResponse"]>;
|
|
654
|
+
/** Graph counts and type/relation buckets. Carries `consistency`/`min_indexed_seq` on the URL. */
|
|
655
|
+
summary(opts?: ReadConsistencyOptions): Promise<Schemas["GraphSummaryResponse"]>;
|
|
592
656
|
/** List the graphs (and branches) under the scoped tenant. */
|
|
593
657
|
listGraphs(): Promise<Schemas["GraphListResponse"]>;
|
|
594
|
-
/** Activity for the stack selected by the bearer stack key or session. */
|
|
595
|
-
stackActivity(window?: LbbStackActivityWindow): Promise<LbbStackActivityResponse>;
|
|
596
658
|
}
|
package/dist/client.js
CHANGED
|
@@ -24,6 +24,8 @@ export class LbbClient {
|
|
|
24
24
|
onRequest;
|
|
25
25
|
onResponse;
|
|
26
26
|
onRetry;
|
|
27
|
+
/** A5 default read consistency applied when a read omits its own value. */
|
|
28
|
+
defaultConsistency;
|
|
27
29
|
context;
|
|
28
30
|
search;
|
|
29
31
|
indexes;
|
|
@@ -49,6 +51,7 @@ export class LbbClient {
|
|
|
49
51
|
this.onRequest = options.onRequest;
|
|
50
52
|
this.onResponse = options.onResponse;
|
|
51
53
|
this.onRetry = options.onRetry;
|
|
54
|
+
this.defaultConsistency = options.defaultConsistency;
|
|
52
55
|
if (!Number.isInteger(this.maxRetries) || this.maxRetries < 0) {
|
|
53
56
|
throw new RangeError("maxRetries must be a non-negative integer");
|
|
54
57
|
}
|
|
@@ -103,8 +106,38 @@ export class LbbClient {
|
|
|
103
106
|
onRequest: this.onRequest,
|
|
104
107
|
onResponse: this.onResponse,
|
|
105
108
|
onRetry: this.onRetry,
|
|
109
|
+
defaultConsistency: this.defaultConsistency,
|
|
106
110
|
});
|
|
107
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* A5: fold read-consistency options into a request body's own `consistency` /
|
|
114
|
+
* `min_indexed_seq` fields (the shape used by full-text, embedding, and
|
|
115
|
+
* structured-SPARQL bodies). A per-call value wins over the client
|
|
116
|
+
* `defaultConsistency`; an explicit body field wins over both.
|
|
117
|
+
*/
|
|
118
|
+
resolveConsistency(opts) {
|
|
119
|
+
return opts?.consistency ?? this.defaultConsistency;
|
|
120
|
+
}
|
|
121
|
+
mergeReadConsistency(body, opts) {
|
|
122
|
+
const consistency = this.resolveConsistency(opts);
|
|
123
|
+
const merged = { ...body };
|
|
124
|
+
if (consistency !== undefined && merged.consistency === undefined) {
|
|
125
|
+
merged.consistency = consistency;
|
|
126
|
+
}
|
|
127
|
+
if (opts?.minIndexedSeq !== undefined &&
|
|
128
|
+
merged.min_indexed_seq === undefined) {
|
|
129
|
+
merged.min_indexed_seq = opts.minIndexedSeq;
|
|
130
|
+
}
|
|
131
|
+
return merged;
|
|
132
|
+
}
|
|
133
|
+
/** A5: read-consistency options rendered as URL query params, for the routes
|
|
134
|
+
* that carry consistency on the URL (SPARQL-text, graph summary). */
|
|
135
|
+
readConsistencyQuery(opts) {
|
|
136
|
+
return {
|
|
137
|
+
consistency: this.resolveConsistency(opts),
|
|
138
|
+
min_indexed_seq: opts?.minIndexedSeq,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
108
141
|
buildUrl(path, query) {
|
|
109
142
|
const params = [];
|
|
110
143
|
const push = (key, value) => params.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
|
@@ -292,11 +325,14 @@ export class LbbClient {
|
|
|
292
325
|
}
|
|
293
326
|
// --- writes ---
|
|
294
327
|
/** Commit triplets and optional entity embeddings. Prefer `client.graph("main").facts.create(...)`. */
|
|
295
|
-
commit(body, opts = {}) {
|
|
296
|
-
|
|
328
|
+
async commit(body, opts = {}) {
|
|
329
|
+
const response = await this.request("POST", "/v1/graph/commit", {
|
|
297
330
|
body,
|
|
298
331
|
idempotencyKey: opts.idempotencyKey ?? this.idempotencyKey("facts.create"),
|
|
299
332
|
});
|
|
333
|
+
// A5: surface the committed sequence as `commitSeq` so the write→floor→read
|
|
334
|
+
// loop reads naturally: `const { commitSeq } = await client.commit(…)`.
|
|
335
|
+
return { ...response, commitSeq: response.commit_seq };
|
|
300
336
|
}
|
|
301
337
|
/**
|
|
302
338
|
* Validate-only preflight: run the same ontology/schema validation a real
|
|
@@ -325,11 +361,11 @@ export class LbbClient {
|
|
|
325
361
|
* the throttle): import the whole dataset, index once. The response's `index`
|
|
326
362
|
* object reports whether the build ran or was skipped.
|
|
327
363
|
*/
|
|
328
|
-
import(lines, opts = {}) {
|
|
364
|
+
async import(lines, opts = {}) {
|
|
329
365
|
const ndjson = typeof lines === "string"
|
|
330
366
|
? lines
|
|
331
367
|
: lines.map((line) => JSON.stringify(line)).join("\n");
|
|
332
|
-
|
|
368
|
+
const response = await this.request("POST", "/v1/graph/import", {
|
|
333
369
|
rawBody: ndjson,
|
|
334
370
|
contentType: "application/x-ndjson",
|
|
335
371
|
query: {
|
|
@@ -340,6 +376,9 @@ export class LbbClient {
|
|
|
340
376
|
},
|
|
341
377
|
idempotencyKey: opts.idempotencyKey ?? this.idempotencyKey("import"),
|
|
342
378
|
});
|
|
379
|
+
// A5: surface the last committed sequence (null for an empty import) so the
|
|
380
|
+
// write→floor→read loop reads naturally after a bulk load.
|
|
381
|
+
return { ...response, commitSeq: response.committed_commit_seq ?? null };
|
|
343
382
|
}
|
|
344
383
|
/**
|
|
345
384
|
* Bulk-ingest N-Triples, Turtle, N-Quads, or TriG without client-side conversion. Resource-object
|
|
@@ -400,6 +439,53 @@ export class LbbClient {
|
|
|
400
439
|
createGraph() {
|
|
401
440
|
return this.request("POST", "/v1/graph/create");
|
|
402
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* Fork a whole graph into a brand-new destination graph in the same tenant.
|
|
444
|
+
* The copy runs as a durable background job (`confirm` is fixed to `dst`, which
|
|
445
|
+
* the route requires to authorize the fork); the destination must not already
|
|
446
|
+
* exist, so the create-only CAS on the server side makes the call safe to
|
|
447
|
+
* retry. The response only acknowledges the enqueue — poll the destination
|
|
448
|
+
* graph's metadata (see `response.poll`) to observe the fork completing: the
|
|
449
|
+
* destination becomes readable once its head is published.
|
|
450
|
+
*/
|
|
451
|
+
forkGraph(opts) {
|
|
452
|
+
return this.request("POST", "/v1/graph/fork", {
|
|
453
|
+
query: { src: opts.src, dst: opts.dst, confirm: opts.dst },
|
|
454
|
+
retry: true,
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Declarative full-state replace: reconcile the scoped graph so its current
|
|
459
|
+
* state matches exactly the NDJSON payload (same line grammar as
|
|
460
|
+
* {@link import} — triplets or `{type,name,properties}` entity records; pass an
|
|
461
|
+
* array, serialized here, or a pre-built NDJSON string). The whole
|
|
462
|
+
* reconciliation lands as one atomic cutover: payload records are upserted, and
|
|
463
|
+
* entities present at the pre-reload head but absent from the payload leave
|
|
464
|
+
* current state (retraction semantics — history is preserved, so an `as_of`
|
|
465
|
+
* read pinned before the cutover still sees the old state). `confirm` must
|
|
466
|
+
* equal the target graph id (reload is semi-destructive). `dryRun` previews the
|
|
467
|
+
* full delta with zero durable changes. The response carries
|
|
468
|
+
* `prior_commit_seq` / `prior_snapshot_token` as the rollback anchor — read
|
|
469
|
+
* them back with `?as_of_commit_seq=<prior_commit_seq>` to see the pre-reload
|
|
470
|
+
* state. An Idempotency-Key scopes the single cutover commit, so a retry
|
|
471
|
+
* replays rather than re-applying.
|
|
472
|
+
*/
|
|
473
|
+
reload(lines, opts) {
|
|
474
|
+
const ndjson = typeof lines === "string"
|
|
475
|
+
? lines
|
|
476
|
+
: lines.map((line) => JSON.stringify(line)).join("\n");
|
|
477
|
+
return this.request("POST", "/v1/graph/reload", {
|
|
478
|
+
rawBody: ndjson,
|
|
479
|
+
contentType: "application/x-ndjson",
|
|
480
|
+
query: {
|
|
481
|
+
confirm: opts.confirm,
|
|
482
|
+
dry_run: opts.dryRun,
|
|
483
|
+
strict: opts.strict,
|
|
484
|
+
observed_at: opts.observedAt,
|
|
485
|
+
},
|
|
486
|
+
idempotencyKey: opts.idempotencyKey ?? this.idempotencyKey("reload"),
|
|
487
|
+
});
|
|
488
|
+
}
|
|
403
489
|
/** Fork the scoped branch from an existing branch in the same graph. */
|
|
404
490
|
createBranch(body) {
|
|
405
491
|
return this.request("POST", "/v1/graph/branch", { body });
|
|
@@ -692,8 +778,15 @@ export class LbbClient {
|
|
|
692
778
|
}
|
|
693
779
|
// --- search ---
|
|
694
780
|
/** Full semantic hybrid search from a request body (`POST /v1/graph/search`). */
|
|
695
|
-
graphSearch(body) {
|
|
696
|
-
|
|
781
|
+
graphSearch(body, opts) {
|
|
782
|
+
// Consistency for hybrid graph search lives on the nested `search` options.
|
|
783
|
+
const consistency = this.resolveConsistency(opts);
|
|
784
|
+
const search = consistency !== undefined || opts?.minIndexedSeq !== undefined
|
|
785
|
+
? this.mergeReadConsistency(body.search ?? {}, opts)
|
|
786
|
+
: body.search;
|
|
787
|
+
return this.request("POST", "/v1/graph/search", {
|
|
788
|
+
body: { ...body, search },
|
|
789
|
+
});
|
|
697
790
|
}
|
|
698
791
|
/** Reciprocal-rank-fusion across sub-queries. */
|
|
699
792
|
multiSearch(body) {
|
|
@@ -758,12 +851,16 @@ export class LbbClient {
|
|
|
758
851
|
return this.request("GET", "/v1/search/feedback/export");
|
|
759
852
|
}
|
|
760
853
|
/** BM25 search. */
|
|
761
|
-
fullTextSearch(body) {
|
|
762
|
-
return this.request("POST", "/v1/search/full-text", {
|
|
854
|
+
fullTextSearch(body, opts) {
|
|
855
|
+
return this.request("POST", "/v1/search/full-text", {
|
|
856
|
+
body: this.mergeReadConsistency(body, opts),
|
|
857
|
+
});
|
|
763
858
|
}
|
|
764
859
|
/** ANN/vector search. */
|
|
765
|
-
embeddingSearch(body) {
|
|
766
|
-
return this.request("POST", "/v1/search/embedding", {
|
|
860
|
+
embeddingSearch(body, opts) {
|
|
861
|
+
return this.request("POST", "/v1/search/embedding", {
|
|
862
|
+
body: this.mergeReadConsistency(body, opts),
|
|
863
|
+
});
|
|
767
864
|
}
|
|
768
865
|
// --- traversal ---
|
|
769
866
|
/** Bounded k-hop graph traversal. */
|
|
@@ -783,9 +880,18 @@ export class LbbClient {
|
|
|
783
880
|
name: opts.name,
|
|
784
881
|
relations: opts.relations?.join(","),
|
|
785
882
|
as_of: opts.asOf,
|
|
883
|
+
indexed: opts.indexed,
|
|
786
884
|
},
|
|
787
885
|
});
|
|
788
886
|
}
|
|
887
|
+
/** Exact type cardinality plus a bounded deterministic sample from ranged adjacency. */
|
|
888
|
+
entityTypeSample(opts) {
|
|
889
|
+
const { type, limit, ...request } = opts;
|
|
890
|
+
return this.request("GET", "/v1/graph/entities/sample", {
|
|
891
|
+
...request,
|
|
892
|
+
query: { type, limit },
|
|
893
|
+
});
|
|
894
|
+
}
|
|
789
895
|
/** Stored entity object-ref status and index-coverage metadata (no
|
|
790
896
|
* attributes — read those from `entityDetail`'s top-level `attributes`). */
|
|
791
897
|
entityMetadata(opts) {
|
|
@@ -890,12 +996,17 @@ export class LbbClient {
|
|
|
890
996
|
* keys come back per group in `groups[].value_keys[<as>]`, entity keys in
|
|
891
997
|
* `groups[].keys`.
|
|
892
998
|
*/
|
|
893
|
-
sparql(body) {
|
|
894
|
-
return this.request("POST", "/v1/query/sparql", {
|
|
999
|
+
sparql(body, opts) {
|
|
1000
|
+
return this.request("POST", "/v1/query/sparql", {
|
|
1001
|
+
body: this.mergeReadConsistency(body, opts),
|
|
1002
|
+
});
|
|
895
1003
|
}
|
|
896
|
-
/** SPARQL 1.1 query from text (SELECT/ASK) over the live graph; `results` is SPARQL 1.1 Query Results JSON. */
|
|
897
|
-
sparqlText(body) {
|
|
898
|
-
return this.request("POST", "/v1/query/sparql-text", {
|
|
1004
|
+
/** SPARQL 1.1 query from text (SELECT/ASK) over the live graph; `results` is SPARQL 1.1 Query Results JSON. The text dialect carries `consistency`/`min_indexed_seq` on the URL. */
|
|
1005
|
+
sparqlText(body, opts) {
|
|
1006
|
+
return this.request("POST", "/v1/query/sparql-text", {
|
|
1007
|
+
body,
|
|
1008
|
+
query: this.readConsistencyQuery(opts),
|
|
1009
|
+
});
|
|
899
1010
|
}
|
|
900
1011
|
/**
|
|
901
1012
|
* Run a SPARQL 1.1 text query and return parsed results — the ergonomic
|
|
@@ -904,8 +1015,8 @@ export class LbbClient {
|
|
|
904
1015
|
* `rows` is the bindings flattened to `{ variable: lexicalValue }`, `boolean`
|
|
905
1016
|
* is the ASK answer (or `null` for a SELECT).
|
|
906
1017
|
*/
|
|
907
|
-
async sparqlRows(body) {
|
|
908
|
-
return parseSparqlResults(await this.sparqlText(body));
|
|
1018
|
+
async sparqlRows(body, opts) {
|
|
1019
|
+
return parseSparqlResults(await this.sparqlText(body, opts));
|
|
909
1020
|
}
|
|
910
1021
|
/**
|
|
911
1022
|
* Basic-graph-pattern query with group-graph-pattern combinators
|
|
@@ -1078,9 +1189,15 @@ export class LbbClient {
|
|
|
1078
1189
|
status() {
|
|
1079
1190
|
return this.request("GET", "/v1/status");
|
|
1080
1191
|
}
|
|
1081
|
-
/** Graph footprint, WAL tail, and index coverage. */
|
|
1082
|
-
metadata() {
|
|
1083
|
-
return this.request("GET", "/v1/graph/metadata"
|
|
1192
|
+
/** Graph footprint, WAL tail, and index coverage. Exact object inventory is opt-in. */
|
|
1193
|
+
metadata(opts = {}) {
|
|
1194
|
+
return this.request("GET", "/v1/graph/metadata", {
|
|
1195
|
+
query: {
|
|
1196
|
+
include_objects: opts.includeObjects,
|
|
1197
|
+
include_indexes: opts.includeIndexes,
|
|
1198
|
+
include_temporal_coverage: opts.includeTemporalCoverage,
|
|
1199
|
+
},
|
|
1200
|
+
});
|
|
1084
1201
|
}
|
|
1085
1202
|
async waitForIndexLineage(targetSeq, opts = {}) {
|
|
1086
1203
|
const deadline = Date.now() + (opts.timeoutMs ?? 30_000);
|
|
@@ -1113,17 +1230,14 @@ export class LbbClient {
|
|
|
1113
1230
|
await sleep(opts.pollIntervalMs ?? 250);
|
|
1114
1231
|
}
|
|
1115
1232
|
}
|
|
1116
|
-
/** Graph counts and type/relation buckets. */
|
|
1117
|
-
summary() {
|
|
1118
|
-
return this.request("GET", "/v1/graph/summary"
|
|
1233
|
+
/** Graph counts and type/relation buckets. Carries `consistency`/`min_indexed_seq` on the URL. */
|
|
1234
|
+
summary(opts) {
|
|
1235
|
+
return this.request("GET", "/v1/graph/summary", {
|
|
1236
|
+
query: this.readConsistencyQuery(opts),
|
|
1237
|
+
});
|
|
1119
1238
|
}
|
|
1120
1239
|
/** List the graphs (and branches) under the scoped tenant. */
|
|
1121
1240
|
listGraphs() {
|
|
1122
1241
|
return this.request("GET", "/v1/graphs");
|
|
1123
1242
|
}
|
|
1124
|
-
// --- stack activity ---
|
|
1125
|
-
/** Activity for the stack selected by the bearer stack key or session. */
|
|
1126
|
-
stackActivity(window = "24h") {
|
|
1127
|
-
return this.request("GET", "/v1/stack/activity", { query: { window } });
|
|
1128
|
-
}
|
|
1129
1243
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { LbbClient, LbbError, parseSparqlResults } from "./client.js";
|
|
2
|
-
export type { LbbClientOptions, CallOptions, RequestOptions, EntityListOptions, HybridSearchOptions, LbbRequestEvent, LbbResponseEvent,
|
|
2
|
+
export type { LbbClientOptions, CallOptions, RequestOptions, EntityListOptions, HybridSearchOptions, LbbRequestEvent, LbbResponseEvent, FetchLike, ReadConsistencyOptions, SearchConsistency, Schemas, SparqlResults, SparqlResultsJson, SparqlTerm, AskRequest, AskResponse, CommitRequest, CommitResponse, Entity, EntitySelector, GraphMetadata, GraphSummary, SchemaView, SearchRequest, SearchResponse, SearchResult, Snapshot, } from "./client.js";
|
|
3
3
|
export type { components, paths, operations } from "./schema.js";
|
package/dist/namespaces.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import type { LbbClient } from "./client.js";
|
|
2
2
|
import type { CallOptions } from "./transport.js";
|
|
3
|
-
import { type EntityAttributeFilterOptions, type ImportLine, type ListResponse, type RdfExportOptions, type RdfImportOptions, type Schemas } from "./types.js";
|
|
3
|
+
import { type EntityAttributeFilterOptions, type ImportLine, type ListResponse, type ReadConsistencyOptions, type RdfExportOptions, type RdfImportOptions, type Schemas } from "./types.js";
|
|
4
4
|
export interface HybridSearchOptions extends CallOptions {
|
|
5
5
|
topK?: number;
|
|
6
6
|
source?: string;
|
|
7
7
|
consistency?: string;
|
|
8
|
+
/** A5 read-your-writes floor (`min_indexed_seq`): the committed sequence a
|
|
9
|
+
* write returned; under eventual, an uncovered floor yields a retryable
|
|
10
|
+
* `read_your_writes_pending` 429. */
|
|
11
|
+
minIndexedSeq?: number;
|
|
8
12
|
lexical?: boolean;
|
|
9
13
|
bm25?: boolean;
|
|
10
14
|
vector?: boolean;
|
|
@@ -96,8 +100,8 @@ export declare class SearchNamespace {
|
|
|
96
100
|
feedback(body: Schemas["SearchFeedbackRequest"], opts?: CallOptions): Promise<Schemas["SearchFeedbackResponse"]>;
|
|
97
101
|
feedbackExport(opts?: CallOptions): Promise<Schemas["SearchFeedbackExportResponse"]>;
|
|
98
102
|
feedbackSummary(opts?: CallOptions): Promise<Schemas["SearchFeedbackSummaryResponse"]>;
|
|
99
|
-
fullText(body: Schemas["FullTextSearchRequest"], opts?: CallOptions): Promise<Schemas["FullTextSearchResponse"]>;
|
|
100
|
-
vector(body: Schemas["EmbeddingSearchRequest"], opts?: CallOptions): Promise<Schemas["EmbeddingSearchResponse"]>;
|
|
103
|
+
fullText(body: Schemas["FullTextSearchRequest"], opts?: CallOptions & ReadConsistencyOptions): Promise<Schemas["FullTextSearchResponse"]>;
|
|
104
|
+
vector(body: Schemas["EmbeddingSearchRequest"], opts?: CallOptions & ReadConsistencyOptions): Promise<Schemas["EmbeddingSearchResponse"]>;
|
|
101
105
|
}
|
|
102
106
|
export declare class SchemaNamespace {
|
|
103
107
|
private readonly client;
|
|
@@ -143,6 +147,15 @@ export declare class IndexNamespace {
|
|
|
143
147
|
export declare class EntityNamespace {
|
|
144
148
|
private readonly client;
|
|
145
149
|
constructor(client: LbbClient);
|
|
150
|
+
/**
|
|
151
|
+
* Return the exact type cardinality and a bounded deterministic sample from
|
|
152
|
+
* the ranged adjacency index. The server returns `index_busy` rather than
|
|
153
|
+
* falling back to an exhaustive snapshot scan when the index is unavailable.
|
|
154
|
+
*/
|
|
155
|
+
sample(opts: {
|
|
156
|
+
type: string;
|
|
157
|
+
limit?: number;
|
|
158
|
+
} & CallOptions): Promise<Schemas["EntityTypeSampleResponse"]>;
|
|
146
159
|
/**
|
|
147
160
|
* Browse entities as the unified list envelope. Pass `fields` (names or `*`)
|
|
148
161
|
* to inline each row's typed attributes as native JSON (under `attributes`) —
|
|
@@ -216,9 +229,9 @@ export declare class OntologyNamespace {
|
|
|
216
229
|
export declare class QueryNamespace {
|
|
217
230
|
private readonly client;
|
|
218
231
|
constructor(client: LbbClient);
|
|
219
|
-
structured(body: Schemas["SparqlSelectRequest"], opts?: CallOptions): Promise<Schemas["SparqlSelectResponse"]>;
|
|
220
|
-
sparql(body: Schemas["SparqlTextRequest"], opts?: CallOptions): Promise<import("./types.js").SparqlResults>;
|
|
221
|
-
sparqlRaw(body: Schemas["SparqlTextRequest"], opts?: CallOptions): Promise<Schemas["SparqlTextResponse"]>;
|
|
232
|
+
structured(body: Schemas["SparqlSelectRequest"], opts?: CallOptions & ReadConsistencyOptions): Promise<Schemas["SparqlSelectResponse"]>;
|
|
233
|
+
sparql(body: Schemas["SparqlTextRequest"], opts?: CallOptions & ReadConsistencyOptions): Promise<import("./types.js").SparqlResults>;
|
|
234
|
+
sparqlRaw(body: Schemas["SparqlTextRequest"], opts?: CallOptions & ReadConsistencyOptions): Promise<Schemas["SparqlTextResponse"]>;
|
|
222
235
|
analytics(body: Schemas["AnalyticQueryRequest"], opts?: CallOptions): Promise<Schemas["AnalyticQueryResponse"]>;
|
|
223
236
|
shacl(body: Schemas["ShaclQueryRequest"], opts?: CallOptions): Promise<Schemas["ShaclQueryResponse"]>;
|
|
224
237
|
infer(body: Schemas["InferenceRunRequest"], opts?: CallOptions): Promise<Schemas["InferenceRunResponse"]>;
|
package/dist/namespaces.js
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
import { attributeFilter, firstPatternVariable, parseSparqlResults, } from "./types.js";
|
|
2
|
+
/** A5: fold read-consistency options into a request body's `consistency` /
|
|
3
|
+
* `min_indexed_seq` fields; a per-call value wins over the client default. */
|
|
4
|
+
function withReadConsistency(client, body, opts) {
|
|
5
|
+
const consistency = opts.consistency ?? client.defaultConsistency;
|
|
6
|
+
const merged = { ...body };
|
|
7
|
+
if (consistency !== undefined && merged.consistency === undefined) {
|
|
8
|
+
merged.consistency = consistency;
|
|
9
|
+
}
|
|
10
|
+
if (opts.minIndexedSeq !== undefined &&
|
|
11
|
+
merged.min_indexed_seq === undefined) {
|
|
12
|
+
merged.min_indexed_seq = opts.minIndexedSeq;
|
|
13
|
+
}
|
|
14
|
+
return merged;
|
|
15
|
+
}
|
|
2
16
|
function transportOptions(options) {
|
|
3
17
|
return {
|
|
4
18
|
idempotencyKey: options.idempotencyKey,
|
|
@@ -186,10 +200,14 @@ export class SearchNamespace {
|
|
|
186
200
|
}
|
|
187
201
|
hybrid(input, opts = {}) {
|
|
188
202
|
if (typeof input !== "string") {
|
|
203
|
+
const search = withReadConsistency(this.client, input.search ?? {}, {
|
|
204
|
+
consistency: opts.consistency,
|
|
205
|
+
minIndexedSeq: opts.minIndexedSeq,
|
|
206
|
+
});
|
|
189
207
|
return this.client.request("POST", "/v1/graph/search", {
|
|
190
208
|
...transportOptions(opts),
|
|
191
209
|
retry: opts.retry ?? true,
|
|
192
|
-
body: input,
|
|
210
|
+
body: { ...input, search },
|
|
193
211
|
});
|
|
194
212
|
}
|
|
195
213
|
return this.client.request("GET", "/v1/search", {
|
|
@@ -198,7 +216,8 @@ export class SearchNamespace {
|
|
|
198
216
|
query: input,
|
|
199
217
|
top_k: opts.topK,
|
|
200
218
|
source: opts.source,
|
|
201
|
-
consistency: opts.consistency,
|
|
219
|
+
consistency: opts.consistency ?? this.client.defaultConsistency,
|
|
220
|
+
min_indexed_seq: opts.minIndexedSeq,
|
|
202
221
|
lexical: opts.lexical,
|
|
203
222
|
bm25: opts.bm25,
|
|
204
223
|
vector: opts.vector,
|
|
@@ -233,14 +252,14 @@ export class SearchNamespace {
|
|
|
233
252
|
return this.client.request("POST", "/v1/search/full-text", {
|
|
234
253
|
...opts,
|
|
235
254
|
retry: opts.retry ?? true,
|
|
236
|
-
body,
|
|
255
|
+
body: withReadConsistency(this.client, body, opts),
|
|
237
256
|
});
|
|
238
257
|
}
|
|
239
258
|
vector(body, opts = {}) {
|
|
240
259
|
return this.client.request("POST", "/v1/search/embedding", {
|
|
241
260
|
...opts,
|
|
242
261
|
retry: opts.retry ?? true,
|
|
243
|
-
body,
|
|
262
|
+
body: withReadConsistency(this.client, body, opts),
|
|
244
263
|
});
|
|
245
264
|
}
|
|
246
265
|
}
|
|
@@ -344,6 +363,14 @@ export class EntityNamespace {
|
|
|
344
363
|
constructor(client) {
|
|
345
364
|
this.client = client;
|
|
346
365
|
}
|
|
366
|
+
/**
|
|
367
|
+
* Return the exact type cardinality and a bounded deterministic sample from
|
|
368
|
+
* the ranged adjacency index. The server returns `index_busy` rather than
|
|
369
|
+
* falling back to an exhaustive snapshot scan when the index is unavailable.
|
|
370
|
+
*/
|
|
371
|
+
sample(opts) {
|
|
372
|
+
return this.client.entityTypeSample(opts);
|
|
373
|
+
}
|
|
347
374
|
/**
|
|
348
375
|
* Browse entities as the unified list envelope. Pass `fields` (names or `*`)
|
|
349
376
|
* to inline each row's typed attributes as native JSON (under `attributes`) —
|
|
@@ -529,11 +556,20 @@ export class QueryNamespace {
|
|
|
529
556
|
return this.client.request("POST", "/v1/query/sparql", {
|
|
530
557
|
...opts,
|
|
531
558
|
retry: opts.retry ?? true,
|
|
532
|
-
body,
|
|
559
|
+
body: withReadConsistency(this.client, body, opts),
|
|
533
560
|
});
|
|
534
561
|
}
|
|
535
562
|
async sparql(body, opts = {}) {
|
|
536
|
-
|
|
563
|
+
// The text dialect carries consistency/floor on the URL, not the body.
|
|
564
|
+
const response = await this.client.request("POST", "/v1/query/sparql-text", {
|
|
565
|
+
...opts,
|
|
566
|
+
retry: opts.retry ?? true,
|
|
567
|
+
body,
|
|
568
|
+
query: {
|
|
569
|
+
consistency: opts.consistency ?? this.client.defaultConsistency,
|
|
570
|
+
min_indexed_seq: opts.minIndexedSeq,
|
|
571
|
+
},
|
|
572
|
+
});
|
|
537
573
|
return parseSparqlResults(response);
|
|
538
574
|
}
|
|
539
575
|
sparqlRaw(body, opts = {}) {
|
|
@@ -541,6 +577,10 @@ export class QueryNamespace {
|
|
|
541
577
|
...opts,
|
|
542
578
|
retry: opts.retry ?? true,
|
|
543
579
|
body,
|
|
580
|
+
query: {
|
|
581
|
+
consistency: opts.consistency ?? this.client.defaultConsistency,
|
|
582
|
+
min_indexed_seq: opts.minIndexedSeq,
|
|
583
|
+
},
|
|
544
584
|
});
|
|
545
585
|
}
|
|
546
586
|
analytics(body, opts = {}) {
|