@littlebigbrain/client 0.7.0 → 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 +30 -13
- package/dist/client.js +77 -20
- package/dist/index.d.ts +1 -1
- package/dist/namespaces.d.ts +10 -6
- package/dist/namespaces.js +38 -6
- package/dist/schema.d.ts +23 -3
- package/dist/types.d.ts +26 -0
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { ImportLine, LbbClientOptions, ListResponse, RawLbbResponse, RdfExportOptions, RdfImportOptions, Schemas, SparqlResults } from "./types.js";
|
|
1
|
+
import type { ImportLine, LbbClientOptions, ListResponse, RawLbbResponse, ReadConsistencyOptions, RdfExportOptions, RdfImportOptions, Schemas, SearchConsistency, SparqlResults } from "./types.js";
|
|
2
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, 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, 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
|
|
@@ -360,7 +377,7 @@ export declare class LbbClient {
|
|
|
360
377
|
allowRegression?: boolean;
|
|
361
378
|
}): Promise<unknown>;
|
|
362
379
|
/** Full semantic hybrid search from a request body (`POST /v1/graph/search`). */
|
|
363
|
-
graphSearch(body: Schemas["SemanticGraphSearchRequest"]): Promise<Schemas["SemanticGraphSearchResponse"]>;
|
|
380
|
+
graphSearch(body: Schemas["SemanticGraphSearchRequest"], opts?: ReadConsistencyOptions): Promise<Schemas["SemanticGraphSearchResponse"]>;
|
|
364
381
|
/** Reciprocal-rank-fusion across sub-queries. */
|
|
365
382
|
multiSearch(body: Schemas["HybridMultiSearchRequest"]): Promise<Schemas["HybridMultiSearchResponse"]>;
|
|
366
383
|
/**
|
|
@@ -407,9 +424,9 @@ export declare class LbbClient {
|
|
|
407
424
|
/** Export the stored relevance labels as qrels-style rows for training. */
|
|
408
425
|
searchFeedbackExport(): Promise<Schemas["SearchFeedbackExportResponse"]>;
|
|
409
426
|
/** BM25 search. */
|
|
410
|
-
fullTextSearch(body: Schemas["FullTextSearchRequest"]): Promise<Schemas["FullTextSearchResponse"]>;
|
|
427
|
+
fullTextSearch(body: Schemas["FullTextSearchRequest"], opts?: ReadConsistencyOptions): Promise<Schemas["FullTextSearchResponse"]>;
|
|
411
428
|
/** ANN/vector search. */
|
|
412
|
-
embeddingSearch(body: Schemas["EmbeddingSearchRequest"]): Promise<Schemas["EmbeddingSearchResponse"]>;
|
|
429
|
+
embeddingSearch(body: Schemas["EmbeddingSearchRequest"], opts?: ReadConsistencyOptions): Promise<Schemas["EmbeddingSearchResponse"]>;
|
|
413
430
|
/** Bounded k-hop graph traversal. */
|
|
414
431
|
traverse(body: Schemas["TraverseRequest"]): Promise<Schemas["TraverseResponse"]>;
|
|
415
432
|
/** Resolve a query to seed entities, then return bounded paths. */
|
|
@@ -502,9 +519,9 @@ export declare class LbbClient {
|
|
|
502
519
|
* keys come back per group in `groups[].value_keys[<as>]`, entity keys in
|
|
503
520
|
* `groups[].keys`.
|
|
504
521
|
*/
|
|
505
|
-
sparql(body: Schemas["SparqlSelectRequest"]): Promise<Schemas["SparqlSelectResponse"]>;
|
|
506
|
-
/** SPARQL 1.1 query from text (SELECT/ASK) over the live graph; `results` is SPARQL 1.1 Query Results JSON. */
|
|
507
|
-
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"]>;
|
|
508
525
|
/**
|
|
509
526
|
* Run a SPARQL 1.1 text query and return parsed results — the ergonomic
|
|
510
527
|
* complement to {@link sparqlText} (which hands back the raw results string).
|
|
@@ -512,7 +529,7 @@ export declare class LbbClient {
|
|
|
512
529
|
* `rows` is the bindings flattened to `{ variable: lexicalValue }`, `boolean`
|
|
513
530
|
* is the ASK answer (or `null` for a SELECT).
|
|
514
531
|
*/
|
|
515
|
-
sparqlRows(body: Schemas["SparqlTextRequest"]): Promise<SparqlResults>;
|
|
532
|
+
sparqlRows(body: Schemas["SparqlTextRequest"], opts?: ReadConsistencyOptions): Promise<SparqlResults>;
|
|
516
533
|
/**
|
|
517
534
|
* Basic-graph-pattern query with group-graph-pattern combinators
|
|
518
535
|
* (UNION / OPTIONAL / MINUS / EXISTS / NOT EXISTS) folded over the base
|
|
@@ -634,8 +651,8 @@ export declare class LbbClient {
|
|
|
634
651
|
timeoutMs?: number;
|
|
635
652
|
pollIntervalMs?: number;
|
|
636
653
|
}): Promise<IndexLineageObservation>;
|
|
637
|
-
/** Graph counts and type/relation buckets. */
|
|
638
|
-
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"]>;
|
|
639
656
|
/** List the graphs (and branches) under the scoped tenant. */
|
|
640
657
|
listGraphs(): Promise<Schemas["GraphListResponse"]>;
|
|
641
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
|
|
@@ -739,8 +778,15 @@ export class LbbClient {
|
|
|
739
778
|
}
|
|
740
779
|
// --- search ---
|
|
741
780
|
/** Full semantic hybrid search from a request body (`POST /v1/graph/search`). */
|
|
742
|
-
graphSearch(body) {
|
|
743
|
-
|
|
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
|
+
});
|
|
744
790
|
}
|
|
745
791
|
/** Reciprocal-rank-fusion across sub-queries. */
|
|
746
792
|
multiSearch(body) {
|
|
@@ -805,12 +851,16 @@ export class LbbClient {
|
|
|
805
851
|
return this.request("GET", "/v1/search/feedback/export");
|
|
806
852
|
}
|
|
807
853
|
/** BM25 search. */
|
|
808
|
-
fullTextSearch(body) {
|
|
809
|
-
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
|
+
});
|
|
810
858
|
}
|
|
811
859
|
/** ANN/vector search. */
|
|
812
|
-
embeddingSearch(body) {
|
|
813
|
-
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
|
+
});
|
|
814
864
|
}
|
|
815
865
|
// --- traversal ---
|
|
816
866
|
/** Bounded k-hop graph traversal. */
|
|
@@ -946,12 +996,17 @@ export class LbbClient {
|
|
|
946
996
|
* keys come back per group in `groups[].value_keys[<as>]`, entity keys in
|
|
947
997
|
* `groups[].keys`.
|
|
948
998
|
*/
|
|
949
|
-
sparql(body) {
|
|
950
|
-
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
|
+
});
|
|
951
1003
|
}
|
|
952
|
-
/** SPARQL 1.1 query from text (SELECT/ASK) over the live graph; `results` is SPARQL 1.1 Query Results JSON. */
|
|
953
|
-
sparqlText(body) {
|
|
954
|
-
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
|
+
});
|
|
955
1010
|
}
|
|
956
1011
|
/**
|
|
957
1012
|
* Run a SPARQL 1.1 text query and return parsed results — the ergonomic
|
|
@@ -960,8 +1015,8 @@ export class LbbClient {
|
|
|
960
1015
|
* `rows` is the bindings flattened to `{ variable: lexicalValue }`, `boolean`
|
|
961
1016
|
* is the ASK answer (or `null` for a SELECT).
|
|
962
1017
|
*/
|
|
963
|
-
async sparqlRows(body) {
|
|
964
|
-
return parseSparqlResults(await this.sparqlText(body));
|
|
1018
|
+
async sparqlRows(body, opts) {
|
|
1019
|
+
return parseSparqlResults(await this.sparqlText(body, opts));
|
|
965
1020
|
}
|
|
966
1021
|
/**
|
|
967
1022
|
* Basic-graph-pattern query with group-graph-pattern combinators
|
|
@@ -1175,9 +1230,11 @@ export class LbbClient {
|
|
|
1175
1230
|
await sleep(opts.pollIntervalMs ?? 250);
|
|
1176
1231
|
}
|
|
1177
1232
|
}
|
|
1178
|
-
/** Graph counts and type/relation buckets. */
|
|
1179
|
-
summary() {
|
|
1180
|
-
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
|
+
});
|
|
1181
1238
|
}
|
|
1182
1239
|
/** List the graphs (and branches) under the scoped tenant. */
|
|
1183
1240
|
listGraphs() {
|
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, FetchLike, Schemas, SparqlResults, SparqlResultsJson, SparqlTerm, AskRequest, AskResponse, CommitRequest, CommitResponse, Entity, EntitySelector, GraphMetadata, GraphSummary, SchemaView, SearchRequest, SearchResponse, SearchResult, Snapshot, } from "./client.js";
|
|
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;
|
|
@@ -225,9 +229,9 @@ export declare class OntologyNamespace {
|
|
|
225
229
|
export declare class QueryNamespace {
|
|
226
230
|
private readonly client;
|
|
227
231
|
constructor(client: LbbClient);
|
|
228
|
-
structured(body: Schemas["SparqlSelectRequest"], opts?: CallOptions): Promise<Schemas["SparqlSelectResponse"]>;
|
|
229
|
-
sparql(body: Schemas["SparqlTextRequest"], opts?: CallOptions): Promise<import("./types.js").SparqlResults>;
|
|
230
|
-
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"]>;
|
|
231
235
|
analytics(body: Schemas["AnalyticQueryRequest"], opts?: CallOptions): Promise<Schemas["AnalyticQueryResponse"]>;
|
|
232
236
|
shacl(body: Schemas["ShaclQueryRequest"], opts?: CallOptions): Promise<Schemas["ShaclQueryResponse"]>;
|
|
233
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
|
}
|
|
@@ -537,11 +556,20 @@ export class QueryNamespace {
|
|
|
537
556
|
return this.client.request("POST", "/v1/query/sparql", {
|
|
538
557
|
...opts,
|
|
539
558
|
retry: opts.retry ?? true,
|
|
540
|
-
body,
|
|
559
|
+
body: withReadConsistency(this.client, body, opts),
|
|
541
560
|
});
|
|
542
561
|
}
|
|
543
562
|
async sparql(body, opts = {}) {
|
|
544
|
-
|
|
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
|
+
});
|
|
545
573
|
return parseSparqlResults(response);
|
|
546
574
|
}
|
|
547
575
|
sparqlRaw(body, opts = {}) {
|
|
@@ -549,6 +577,10 @@ export class QueryNamespace {
|
|
|
549
577
|
...opts,
|
|
550
578
|
retry: opts.retry ?? true,
|
|
551
579
|
body,
|
|
580
|
+
query: {
|
|
581
|
+
consistency: opts.consistency ?? this.client.defaultConsistency,
|
|
582
|
+
min_indexed_seq: opts.minIndexedSeq,
|
|
583
|
+
},
|
|
552
584
|
});
|
|
553
585
|
}
|
|
554
586
|
analytics(body, opts = {}) {
|
package/dist/schema.d.ts
CHANGED
|
@@ -2969,6 +2969,7 @@ export interface components {
|
|
|
2969
2969
|
facets?: components["schemas"]["FacetRequest"][] | null;
|
|
2970
2970
|
filters?: null | components["schemas"]["SearchFilterExpr"];
|
|
2971
2971
|
max_clusters?: number | null;
|
|
2972
|
+
min_indexed_seq?: null | components["schemas"]["CommitSeq"];
|
|
2972
2973
|
probe_count?: number | null;
|
|
2973
2974
|
provider?: null | components["schemas"]["EmbeddingProviderConfig"];
|
|
2974
2975
|
query: string;
|
|
@@ -3474,6 +3475,7 @@ export interface components {
|
|
|
3474
3475
|
explain: boolean;
|
|
3475
3476
|
facets?: components["schemas"]["FacetRequest"][] | null;
|
|
3476
3477
|
filters?: null | components["schemas"]["SearchFilterExpr"];
|
|
3478
|
+
min_indexed_seq?: null | components["schemas"]["CommitSeq"];
|
|
3477
3479
|
/**
|
|
3478
3480
|
* @description Number of leading results to skip after ordering, for stateless paging:
|
|
3479
3481
|
* `offset = page * top_k` walks pages deterministically. Defaults to 0.
|
|
@@ -6347,7 +6349,19 @@ export interface components {
|
|
|
6347
6349
|
/** Format: float */
|
|
6348
6350
|
weighted_score: number;
|
|
6349
6351
|
};
|
|
6350
|
-
/**
|
|
6352
|
+
/**
|
|
6353
|
+
* @description Read consistency for a query surface (search, graph summary, SPARQL).
|
|
6354
|
+
*
|
|
6355
|
+
* A5 (2026-07-21 product decision): `Eventual` is the **default**. It serves the
|
|
6356
|
+
* last published index/dataset state at its watermark with no in-memory fold of
|
|
6357
|
+
* the un-indexed tail — the lowest-latency mode and the availability floor
|
|
6358
|
+
* during any indexing backlog. The served watermark rides back on
|
|
6359
|
+
* `SnapshotView::served_at_seq`. `Strong` (fold the un-indexed tail up to the
|
|
6360
|
+
* query head) is now explicit opt-in; the precise read-your-writes contract
|
|
6361
|
+
* (`min_indexed_seq`) replaces most former uses of strong. See
|
|
6362
|
+
* `docs/architecture/segment-native-indexing.md` §6.
|
|
6363
|
+
* @enum {string}
|
|
6364
|
+
*/
|
|
6351
6365
|
SearchConsistency: "strong" | "eventual";
|
|
6352
6366
|
SearchEngineOptions: {
|
|
6353
6367
|
bm25?: boolean;
|
|
@@ -6360,6 +6374,7 @@ export interface components {
|
|
|
6360
6374
|
graph_anchor?: null | components["schemas"]["GraphAnchor"];
|
|
6361
6375
|
lexical?: boolean;
|
|
6362
6376
|
max_clusters?: number | null;
|
|
6377
|
+
min_indexed_seq?: null | components["schemas"]["CommitSeq"];
|
|
6363
6378
|
probe_count?: number | null;
|
|
6364
6379
|
profile?: null | components["schemas"]["RetrievalProfileId"];
|
|
6365
6380
|
provider?: null | components["schemas"]["EmbeddingProviderConfig"];
|
|
@@ -7688,6 +7703,7 @@ export interface components {
|
|
|
7688
7703
|
* `GET /v1/graph/metadata` and on the entity read's metadata.
|
|
7689
7704
|
*/
|
|
7690
7705
|
compacted_seq: components["schemas"]["CommitSeq"];
|
|
7706
|
+
served_at_seq?: null | components["schemas"]["CommitSeq"];
|
|
7691
7707
|
/**
|
|
7692
7708
|
* @description F2 (roadmap 18.3): true when this snapshot was served from the in-memory
|
|
7693
7709
|
* cache while storage was degraded and the latest head could not be
|
|
@@ -7697,8 +7713,9 @@ export interface components {
|
|
|
7697
7713
|
*/
|
|
7698
7714
|
stale?: boolean;
|
|
7699
7715
|
/**
|
|
7700
|
-
* @description The reason a read is `stale
|
|
7701
|
-
*
|
|
7716
|
+
* @description The reason a read is `stale`. `"storage_degraded"` (F2) or
|
|
7717
|
+
* `"eventual_consistency"` (A3: served from the last published index/dataset
|
|
7718
|
+
* state at [`Self::served_at_seq`], not head); omitted when not stale.
|
|
7702
7719
|
*/
|
|
7703
7720
|
stale_reason?: string | null;
|
|
7704
7721
|
};
|
|
@@ -7875,6 +7892,7 @@ export interface components {
|
|
|
7875
7892
|
* Projection, DISTINCT, and limit/offset are ignored.
|
|
7876
7893
|
*/
|
|
7877
7894
|
ask?: boolean;
|
|
7895
|
+
consistency?: null | components["schemas"]["SearchConsistency"];
|
|
7878
7896
|
/** @description `SELECT DISTINCT`: drop duplicate projected rows. */
|
|
7879
7897
|
distinct?: boolean;
|
|
7880
7898
|
/**
|
|
@@ -7919,6 +7937,7 @@ export interface components {
|
|
|
7919
7937
|
* (see `AnalyticQueryRequest::max_solutions`).
|
|
7920
7938
|
*/
|
|
7921
7939
|
max_solutions?: number | null;
|
|
7940
|
+
min_indexed_seq?: null | components["schemas"]["CommitSeq"];
|
|
7922
7941
|
/** @description Skip this many rows before `limit`. */
|
|
7923
7942
|
offset?: number | null;
|
|
7924
7943
|
/**
|
|
@@ -8035,6 +8054,7 @@ export interface components {
|
|
|
8035
8054
|
/** @description SPARQL 1.1 Query Results JSON, serialized. */
|
|
8036
8055
|
results: string;
|
|
8037
8056
|
row_page: components["schemas"]["RowPage"];
|
|
8057
|
+
snapshot?: null | components["schemas"]["SnapshotView"];
|
|
8038
8058
|
};
|
|
8039
8059
|
/**
|
|
8040
8060
|
* @description A literal constant operand in a FILTER. Scalars compare by typed value;
|
package/dist/types.d.ts
CHANGED
|
@@ -192,6 +192,32 @@ export interface LbbClientOptions {
|
|
|
192
192
|
onResponse?: (event: LbbResponseEvent) => void;
|
|
193
193
|
/** Called before each backoff sleep, so absorbed retries are observable. Bodies and credentials are never included. */
|
|
194
194
|
onRetry?: (event: LbbRetryEvent) => void;
|
|
195
|
+
/**
|
|
196
|
+
* A5 default read consistency, applied when a read call omits its own
|
|
197
|
+
* `consistency`. Since A5 the server default is `eventual`; set `"strong"`
|
|
198
|
+
* here to keep every read head-exact by default (carried across `withScope`).
|
|
199
|
+
* A per-call `consistency` always wins.
|
|
200
|
+
*/
|
|
201
|
+
defaultConsistency?: SearchConsistency;
|
|
202
|
+
}
|
|
203
|
+
/** A5 read consistency level. Since A5 the server default is `eventual`. */
|
|
204
|
+
export type SearchConsistency = "strong" | "eventual";
|
|
205
|
+
/**
|
|
206
|
+
* A5 read-consistency options shared by the query / search / summary surfaces.
|
|
207
|
+
* Merged into the request as `consistency` / `min_indexed_seq`; a per-call value
|
|
208
|
+
* wins over the client's `defaultConsistency`.
|
|
209
|
+
*/
|
|
210
|
+
export interface ReadConsistencyOptions {
|
|
211
|
+
/** Read consistency. Omit to use the client's `defaultConsistency`, else the
|
|
212
|
+
* server default (`eventual`). */
|
|
213
|
+
consistency?: SearchConsistency;
|
|
214
|
+
/**
|
|
215
|
+
* Read-your-writes floor: require the read to be served from state whose
|
|
216
|
+
* watermark ≥ this `commit_seq` (the committed sequence a write returned).
|
|
217
|
+
* Under eventual, a floor not yet covered yields a retryable
|
|
218
|
+
* `read_your_writes_pending` `429` — poll until the write lands.
|
|
219
|
+
*/
|
|
220
|
+
minIndexedSeq?: number;
|
|
195
221
|
}
|
|
196
222
|
export interface LbbRequestEvent {
|
|
197
223
|
method: string;
|