@littlebigbrain/client 0.11.0 → 0.11.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 +10 -2
- package/dist/client.d.ts +23 -2
- package/dist/client.js +57 -8
- package/dist/namespaces.d.ts +4 -0
- package/dist/namespaces.js +4 -0
- package/dist/schema.d.ts +32 -5
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -68,12 +68,18 @@ const accepted = await lbb.submitImport(records(), {
|
|
|
68
68
|
});
|
|
69
69
|
const completed = await lbb.waitForImportJob(accepted.job_id);
|
|
70
70
|
console.log(completed.state, completed.committed_commit_seq);
|
|
71
|
+
if (completed.committed_commit_seq != null) {
|
|
72
|
+
await lbb.waitForIndexLineage(completed.committed_commit_seq);
|
|
73
|
+
}
|
|
71
74
|
```
|
|
72
75
|
|
|
73
76
|
`records()` may be an iterable or async iterable. Success means every grouped
|
|
74
77
|
commit is durable and final publication was enqueued; it does not mean indexes
|
|
75
|
-
have already reached `committed_commit_seq`.
|
|
76
|
-
|
|
78
|
+
have already reached `committed_commit_seq`. Wait once after the final commit,
|
|
79
|
+
not after each source row or chunk. The lineage waiter polls normal
|
|
80
|
+
`index_caught_up=false` metadata until its own deadline, including on an
|
|
81
|
+
RDF-only deployment. An empty iterable is rejected locally before an import
|
|
82
|
+
POST is sent.
|
|
77
83
|
|
|
78
84
|
**Time-travel read.** Pin a SPARQL read to a past instant — results reflect the graph as it was then:
|
|
79
85
|
|
|
@@ -95,6 +101,8 @@ const { rows } = await lbb.sparqlRows({
|
|
|
95
101
|
## Errors & retries
|
|
96
102
|
|
|
97
103
|
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.
|
|
104
|
+
`waitForIndexLineage(...)` is a separate deadline-bounded poller, so the generic
|
|
105
|
+
request retry-count cap cannot end publication waiting early.
|
|
98
106
|
|
|
99
107
|
## More
|
|
100
108
|
|
package/dist/client.d.ts
CHANGED
|
@@ -146,7 +146,11 @@ export declare class LbbClient {
|
|
|
146
146
|
retract(body: Schemas["GraphRetractRequest"], opts?: {
|
|
147
147
|
idempotencyKey?: string;
|
|
148
148
|
}): Promise<Schemas["GraphRetractResponse"]>;
|
|
149
|
-
/**
|
|
149
|
+
/**
|
|
150
|
+
* Create the scoped graph/branch with an empty ontology. Construct the client
|
|
151
|
+
* with the desired graph/branch first, then call `ontology.define` before
|
|
152
|
+
* writing typed data.
|
|
153
|
+
*/
|
|
150
154
|
createGraph(): Promise<Schemas["CreateGraphResponse"]>;
|
|
151
155
|
/**
|
|
152
156
|
* Fork a whole graph into a brand-new destination graph in the same tenant.
|
|
@@ -432,7 +436,17 @@ export declare class LbbClient {
|
|
|
432
436
|
ontologySearch(body: Schemas["OntologySearchRequest"]): Promise<Schemas["OntologySearchResponse"]>;
|
|
433
437
|
/** Resolve mentions to concepts/entities. */
|
|
434
438
|
ontologyResolve(body: Schemas["OntologyResolveRequest"]): Promise<Schemas["OntologyResolveResponse"]>;
|
|
435
|
-
/**
|
|
439
|
+
/**
|
|
440
|
+
* Put the scoped graph on an imported ontology, creating the graph when it
|
|
441
|
+
* does not exist yet. Safe to repeat: an unchanged ontology answers
|
|
442
|
+
* `changed: false` without writing. An additive difference is applied,
|
|
443
|
+
* including a wider relation domain or range and a new property field, and
|
|
444
|
+
* `changed` reports what was written. A document that narrows or drops what
|
|
445
|
+
* the graph already defines, or states a change no additive operation
|
|
446
|
+
* expresses, is refused with `ontology_restrictive_change`,
|
|
447
|
+
* `ontology_identity_breaking_change`, or `ontology_unsupported_change`, and
|
|
448
|
+
* writes nothing.
|
|
449
|
+
*/
|
|
436
450
|
ontologyDefine(body: Schemas["OntologyDefineRequest"]): Promise<Schemas["OntologyDefineResponse"]>;
|
|
437
451
|
/**
|
|
438
452
|
* Additively evolve the active ontology of an existing graph: widen relation
|
|
@@ -454,6 +468,13 @@ export declare class LbbClient {
|
|
|
454
468
|
metadata(opts?: {
|
|
455
469
|
includeIndexes?: boolean;
|
|
456
470
|
}): Promise<Schemas["GraphMetadataResponse"]>;
|
|
471
|
+
/**
|
|
472
|
+
* Wait until one published generation covers `targetSeq`.
|
|
473
|
+
*
|
|
474
|
+
* The returned lineage may name absent BM25/ANN families on an RDF-only
|
|
475
|
+
* deployment; `metadata.index_caught_up` is the generation-level readiness
|
|
476
|
+
* signal used by bulk loaders.
|
|
477
|
+
*/
|
|
457
478
|
waitForIndexLineage(targetSeq: number, opts?: {
|
|
458
479
|
timeoutMs?: number;
|
|
459
480
|
pollIntervalMs?: number;
|
package/dist/client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { parseSparqlResults } from "./types.js";
|
|
2
2
|
import { bodyMarksTerminal, errorCodeFromBody, fullJitterBackoffMs, parseLbbError, parseResponseJson, retryAllowed, retryableStatus, retryDelayMs, sleep, } from "./transport.js";
|
|
3
|
-
import { LbbCapabilityError } from "./transport.js";
|
|
3
|
+
import { LbbCapabilityError, LbbError } from "./transport.js";
|
|
4
4
|
import { EntityNamespace, GraphNamespace, OntologyNamespace, QueryNamespace, SchemaNamespace, SearchNamespace, } from "./namespaces.js";
|
|
5
5
|
export { parseSparqlResults } from "./types.js";
|
|
6
6
|
export { LbbCapabilityError, LbbError } from "./transport.js";
|
|
@@ -575,7 +575,11 @@ export class LbbClient {
|
|
|
575
575
|
idempotencyKey: opts.idempotencyKey ?? this.idempotencyKey("retract"),
|
|
576
576
|
});
|
|
577
577
|
}
|
|
578
|
-
/**
|
|
578
|
+
/**
|
|
579
|
+
* Create the scoped graph/branch with an empty ontology. Construct the client
|
|
580
|
+
* with the desired graph/branch first, then call `ontology.define` before
|
|
581
|
+
* writing typed data.
|
|
582
|
+
*/
|
|
579
583
|
createGraph() {
|
|
580
584
|
return this.request("POST", "/v1/graph/create");
|
|
581
585
|
}
|
|
@@ -985,7 +989,17 @@ export class LbbClient {
|
|
|
985
989
|
ontologyResolve(body) {
|
|
986
990
|
return this.request("POST", "/v1/ontology/resolve", { body });
|
|
987
991
|
}
|
|
988
|
-
/**
|
|
992
|
+
/**
|
|
993
|
+
* Put the scoped graph on an imported ontology, creating the graph when it
|
|
994
|
+
* does not exist yet. Safe to repeat: an unchanged ontology answers
|
|
995
|
+
* `changed: false` without writing. An additive difference is applied,
|
|
996
|
+
* including a wider relation domain or range and a new property field, and
|
|
997
|
+
* `changed` reports what was written. A document that narrows or drops what
|
|
998
|
+
* the graph already defines, or states a change no additive operation
|
|
999
|
+
* expresses, is refused with `ontology_restrictive_change`,
|
|
1000
|
+
* `ontology_identity_breaking_change`, or `ontology_unsupported_change`, and
|
|
1001
|
+
* writes nothing.
|
|
1002
|
+
*/
|
|
989
1003
|
ontologyDefine(body) {
|
|
990
1004
|
return this.request("POST", "/v1/ontology/define", { body });
|
|
991
1005
|
}
|
|
@@ -1024,17 +1038,52 @@ export class LbbClient {
|
|
|
1024
1038
|
},
|
|
1025
1039
|
});
|
|
1026
1040
|
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Wait until one published generation covers `targetSeq`.
|
|
1043
|
+
*
|
|
1044
|
+
* The returned lineage may name absent BM25/ANN families on an RDF-only
|
|
1045
|
+
* deployment; `metadata.index_caught_up` is the generation-level readiness
|
|
1046
|
+
* signal used by bulk loaders.
|
|
1047
|
+
*/
|
|
1027
1048
|
async waitForIndexLineage(targetSeq, opts = {}) {
|
|
1028
1049
|
const deadline = Date.now() + (opts.timeoutMs ?? 30_000);
|
|
1029
1050
|
let last;
|
|
1030
1051
|
while (true) {
|
|
1031
|
-
|
|
1052
|
+
try {
|
|
1053
|
+
// This method is already an explicit, deadline-bounded poller. Avoid
|
|
1054
|
+
// nesting the generic request retry count inside it: publication may
|
|
1055
|
+
// legitimately take longer than that secondary cap.
|
|
1056
|
+
last = await this.rawRequest("GET", "/v1/graph/metadata", {
|
|
1057
|
+
maxRetries: 0,
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
catch (error) {
|
|
1061
|
+
const retryableHttpError = error instanceof LbbError &&
|
|
1062
|
+
retryableStatus(error.status) &&
|
|
1063
|
+
error.retryable !== false;
|
|
1064
|
+
const retryableTransportError = error instanceof Error && !(error instanceof LbbError);
|
|
1065
|
+
if (!retryableHttpError && !retryableTransportError)
|
|
1066
|
+
throw error;
|
|
1067
|
+
const now = Date.now();
|
|
1068
|
+
if (now >= deadline) {
|
|
1069
|
+
throw new Error(`index lineage did not reach ${targetSeq} before timeout (last_error=${error.message})`, { cause: error });
|
|
1070
|
+
}
|
|
1071
|
+
const retryAfterMs = error instanceof LbbError
|
|
1072
|
+
? (error.retryAfterSeconds ?? 0) * 1_000
|
|
1073
|
+
: 0;
|
|
1074
|
+
await sleep(Math.min(Math.max(opts.pollIntervalMs ?? 250, retryAfterMs), deadline - now));
|
|
1075
|
+
continue;
|
|
1076
|
+
}
|
|
1032
1077
|
const lineage = last.data.index_lineage;
|
|
1078
|
+
const servedAt = last.data.snapshot.served_at_seq;
|
|
1033
1079
|
if (lineage != null &&
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1080
|
+
servedAt != null &&
|
|
1081
|
+
servedAt >= targetSeq &&
|
|
1082
|
+
(last.data.index_caught_up === true ||
|
|
1083
|
+
(lineage.bm25_indexed_commit_seq != null &&
|
|
1084
|
+
lineage.bm25_indexed_commit_seq >= targetSeq &&
|
|
1085
|
+
lineage.ann_indexed_commit_seq != null &&
|
|
1086
|
+
lineage.ann_indexed_commit_seq >= targetSeq))) {
|
|
1038
1087
|
return {
|
|
1039
1088
|
metadata: last.data,
|
|
1040
1089
|
lineage,
|
package/dist/namespaces.d.ts
CHANGED
|
@@ -100,6 +100,10 @@ export declare class OntologyNamespace {
|
|
|
100
100
|
conformance(opts?: CallOptions & Pick<ReadConsistencyOptions, "consistency">): Promise<Schemas["SchemaAuditReport"]>;
|
|
101
101
|
search(body: Schemas["OntologySearchRequest"], opts?: CallOptions): Promise<Schemas["OntologySearchResponse"]>;
|
|
102
102
|
resolve(body: Schemas["OntologyResolveRequest"], opts?: CallOptions): Promise<Schemas["OntologyResolveResponse"]>;
|
|
103
|
+
/**
|
|
104
|
+
* Put the scoped graph on an imported ontology, creating the graph when it
|
|
105
|
+
* does not exist yet. Safe to repeat. See {@link LbbClient.ontologyDefine}.
|
|
106
|
+
*/
|
|
103
107
|
define(body: Schemas["OntologyDefineRequest"], opts?: CallOptions): Promise<Schemas["OntologyDefineResponse"]>;
|
|
104
108
|
evolve(body: Schemas["OntologyEvolveRequest"], opts?: CallOptions): Promise<Schemas["OntologyEvolveResponse"]>;
|
|
105
109
|
induce(body: Schemas["OntologyInduceRequest"], opts?: CallOptions): Promise<Schemas["OntologyInduceResponse"]>;
|
package/dist/namespaces.js
CHANGED
|
@@ -241,6 +241,10 @@ export class OntologyNamespace {
|
|
|
241
241
|
body,
|
|
242
242
|
});
|
|
243
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* Put the scoped graph on an imported ontology, creating the graph when it
|
|
246
|
+
* does not exist yet. Safe to repeat. See {@link LbbClient.ontologyDefine}.
|
|
247
|
+
*/
|
|
244
248
|
define(body, opts = {}) {
|
|
245
249
|
return this.client.request("POST", "/v1/ontology/define", {
|
|
246
250
|
...opts,
|
package/dist/schema.d.ts
CHANGED
|
@@ -183,7 +183,7 @@ export interface paths {
|
|
|
183
183
|
};
|
|
184
184
|
get?: never;
|
|
185
185
|
put?: never;
|
|
186
|
-
/** Create the scoped graph and branch */
|
|
186
|
+
/** Create the scoped graph and branch with an empty ontology */
|
|
187
187
|
post: operations["post_v1_graph_create"];
|
|
188
188
|
delete?: never;
|
|
189
189
|
options?: never;
|
|
@@ -3786,10 +3786,15 @@ export interface components {
|
|
|
3786
3786
|
subject: string;
|
|
3787
3787
|
};
|
|
3788
3788
|
/**
|
|
3789
|
-
* @description Define
|
|
3790
|
-
*
|
|
3791
|
-
*
|
|
3792
|
-
*
|
|
3789
|
+
* @description Define the scoped graph's ontology. Imports `source` (any
|
|
3790
|
+
* [`crate`]-supported format), optionally merges the built-in default so the
|
|
3791
|
+
* standard entity types/relations stay available, and creates the graph head
|
|
3792
|
+
* with the result.
|
|
3793
|
+
*
|
|
3794
|
+
* The call is re-runnable on a graph that already exists. An unchanged
|
|
3795
|
+
* ontology is a no-op; an additive difference is applied, including a widened
|
|
3796
|
+
* relation domain or range and a new property field; a narrowing or removing
|
|
3797
|
+
* difference is refused with a typed error naming the route that applies it.
|
|
3793
3798
|
*/
|
|
3794
3799
|
OntologyDefineRequest: {
|
|
3795
3800
|
/** @description Import format hint. `auto` (the default) sniffs the content. */
|
|
@@ -3806,9 +3811,31 @@ export interface components {
|
|
|
3806
3811
|
source: string;
|
|
3807
3812
|
};
|
|
3808
3813
|
OntologyDefineResponse: {
|
|
3814
|
+
/**
|
|
3815
|
+
* @description True when this call wrote a new ontology version, either by creating the
|
|
3816
|
+
* graph or by applying an additive difference. False when the proposed
|
|
3817
|
+
* ontology already matched the active one, which is what makes re-running
|
|
3818
|
+
* the same bootstrap request a no-op.
|
|
3819
|
+
*
|
|
3820
|
+
* This tracks what was written, so it never reports `false` for a call
|
|
3821
|
+
* that changed the ontology: a widened relation domain or range and a new
|
|
3822
|
+
* property field both set it, even though neither appears in the
|
|
3823
|
+
* class-and-relation schema diff.
|
|
3824
|
+
*/
|
|
3825
|
+
changed?: boolean;
|
|
3826
|
+
/**
|
|
3827
|
+
* @description The additive changes this call applied to an existing graph's ontology.
|
|
3828
|
+
* Empty when the graph was created and when nothing changed.
|
|
3829
|
+
*/
|
|
3830
|
+
changes?: components["schemas"]["SchemaDiffEntry"][];
|
|
3809
3831
|
entity_types: components["schemas"]["OntologyTermView"][];
|
|
3810
3832
|
format: string;
|
|
3811
3833
|
graph: components["schemas"]["GraphKey"];
|
|
3834
|
+
/**
|
|
3835
|
+
* @description True when this call created the graph head. False when the graph already
|
|
3836
|
+
* existed, whether the ontology then changed or not. This is the `created`
|
|
3837
|
+
* signal for the define route.
|
|
3838
|
+
*/
|
|
3812
3839
|
graph_created: boolean;
|
|
3813
3840
|
merged_default: boolean;
|
|
3814
3841
|
/** Format: int64 */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@littlebigbrain/client",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "TypeScript client for the little big brain graph + hybrid search HTTP API",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -53,5 +53,13 @@
|
|
|
53
53
|
"openapi-typescript": "^7",
|
|
54
54
|
"publint": "^0.3.21",
|
|
55
55
|
"typescript": "^5.6"
|
|
56
|
+
},
|
|
57
|
+
"overrides": {
|
|
58
|
+
"@redocly/openapi-core": {
|
|
59
|
+
"js-yaml": "^4.3.1"
|
|
60
|
+
},
|
|
61
|
+
"minimatch": {
|
|
62
|
+
"brace-expansion": "^2.1.2"
|
|
63
|
+
}
|
|
56
64
|
}
|
|
57
65
|
}
|