@kortexya/reasoninglayer 1.28.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -18
- package/dist/index.cjs +403 -78
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1116 -372
- package/dist/index.d.ts +1116 -372
- package/dist/index.js +403 -78
- package/dist/index.js.map +1 -1
- package/package.json +13 -10
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// src/config.ts
|
|
8
|
-
var SDK_VERSION = "1.
|
|
8
|
+
var SDK_VERSION = "2.1.0";
|
|
9
9
|
function resolveConfig(config) {
|
|
10
10
|
if (!config.baseUrl) {
|
|
11
11
|
throw new Error("ClientConfig.baseUrl is required");
|
|
@@ -1162,11 +1162,11 @@ var Sorts = class {
|
|
|
1162
1162
|
...params
|
|
1163
1163
|
});
|
|
1164
1164
|
/**
|
|
1165
|
-
* @description Per Definition IV.5 (Milanese & Pasi, IEEE TFS 2024 — CC-BY manuscript in reasoninglayer-sources/pdf_sources/), verbatim: ≺∼· ≝ ((≺∼ .− ∼) ⊍ ⪯)⊕ The combined chain preorder ≺∼ of Definition IV.1 with every DIRECTLY-similar pair deleted (`.−` zeroes the pair — it is not an arithmetic difference), the crisp order unioned back, and the result re-closed. A chain survives when its ENDPOINTS are not directly similar: slasher ⪯ horror ∼₀.₅ thriller keeps 0.5 while (horror, thriller) itself answers 0 — two similar sorts meet through their GLB instead (Fig. 4c: horror ⩏ thriller = slasher). The combined ≺∼ — where a direct ∼ edge IS a step; the coarse retrieval mode of Example V.4 — backs equivalence classes and term substitutability internally. (History: the differencing form here is ORIGINAL and faithful; #203 swapped in the combined semantics, and a 2026-08-23 pass re-documented that as correct from secondary sources. The accepted manuscript settled it the other way.)
|
|
1165
|
+
* @description Omitted, the answer is Def. IV.5 `≾̇` — the default because that is the relation the graded GLB and term substitutability are computed from. `granularity: "combined"` answers Def. IV.1 `≺∼`, where a similarity edge IS a step, so a directly-similar pair reads its similarity degree instead of the `0` the pair deletion gives it. A caller asking "how close are these two sorts" wants the second; a caller asking "does this sort substitute for that one" wants the first (#282). Per Definition IV.5 (Milanese & Pasi, IEEE TFS 2024 — CC-BY manuscript in reasoninglayer-sources/pdf_sources/), verbatim: ≺∼· ≝ ((≺∼ .− ∼) ⊍ ⪯)⊕ The combined chain preorder ≺∼ of Definition IV.1 with every DIRECTLY-similar pair deleted (`.−` zeroes the pair — it is not an arithmetic difference), the crisp order unioned back, and the result re-closed. A chain survives when its ENDPOINTS are not directly similar: slasher ⪯ horror ∼₀.₅ thriller keeps 0.5 while (horror, thriller) itself answers 0 — two similar sorts meet through their GLB instead (Fig. 4c: horror ⩏ thriller = slasher). The combined ≺∼ — where a direct ∼ edge IS a step; the coarse retrieval mode of Example V.4 — backs equivalence classes and term substitutability internally. (History: the differencing form here is ORIGINAL and faithful; #203 swapped in the combined semantics, and a 2026-08-23 pass re-documented that as correct from secondary sources. The accepted manuscript settled it the other way.)
|
|
1166
1166
|
*
|
|
1167
1167
|
* @tags sorts
|
|
1168
1168
|
* @name GetPreorderDegree
|
|
1169
|
-
* @summary Get preorder degree
|
|
1169
|
+
* @summary Get the preorder degree between two sorts, in either of the paper's two readings — `granularity` selects which, exactly as `GET /api/v1/sorts/quotient-order` does, and the answer echoes it back.
|
|
1170
1170
|
* @request POST:/api/v1/sorts/preorder-degree
|
|
1171
1171
|
*/
|
|
1172
1172
|
getPreorderDegree = (data, params = {}) => this.http.request({
|
|
@@ -1867,7 +1867,7 @@ var Inference = class {
|
|
|
1867
1867
|
...params
|
|
1868
1868
|
});
|
|
1869
1869
|
/**
|
|
1870
|
-
* @description # TRUE HOMOICONIC API Request contains a goal term and optional constraints. Response returns solutions with term-based substitutions. ## Temporal Reasoning Use constraints to filter by temporal relations: ```json { "goal": {"sort_name": "Employment", "features": {"valid_to": {"name": "?EndTime"}}}, "constraints": [{"type": "Guard", "left": "?EndTime", "op": "lt", "right": "1583020800000"}] } ``` ## Reading a solution `solutions[].proof.kind` says how the goal was established, and is always present: `proved` (a rule was applied — either it fired in this search, or the goal was a conclusion a forward chain had materialised and the engine recovered the rule from its recorded derivation, so `rule_term_id` and `rule_label` are filled), `fact` (a stored fact with no recorded derivation), `residuated` (an open-world leaf: unknown, never false), `unattributed` (a sound answer whose derivation the engine could not report). A client never has to infer this from the node's shape. A goal that carries `constraints` is a CONJUNCTION: its root node holds one subproof per clause and reports the strongest kind the clauses carry — `proved` when any clause was proved by a rule, else `fact`. `solutions[].substitution.bindings` carries one entry per query variable the engine resolved. A variable left unresolved is ABSENT; it is never bound to itself. # Authorization Requires X-Tenant-Id header. Traced: this is the path the zanzibar gateway hits for every permission check, so it is where an end-to-end trace either explains a slow request or does not. `skip_all` because the request body can be large and has no business in a span attribute.
|
|
1870
|
+
* @description # TRUE HOMOICONIC API Request contains a goal term and optional constraints. Response returns solutions with term-based substitutions. ## Temporal Reasoning Use constraints to filter by temporal relations: ```json { "goal": {"sort_name": "Employment", "features": {"valid_to": {"name": "?EndTime"}}}, "constraints": [{"type": "Guard", "left": "?EndTime", "op": "lt", "right": "1583020800000"}] } ``` ## Reading a solution `solutions[].proof.kind` says how the goal was established, and is always present: `proved` (a rule was applied — either it fired in this search, or the goal was a conclusion a forward chain had materialised and the engine recovered the rule from its recorded derivation, so `rule_term_id` and `rule_label` are filled), `fact` (a stored fact with no recorded derivation), `residuated` (an open-world leaf: unknown, never false), `unattributed` (a sound answer whose derivation the engine could not report). A client never has to infer this from the node's shape. A goal that carries `constraints` is a CONJUNCTION: its root node holds one subproof per clause and reports the strongest kind the clauses carry — `proved` when any clause was proved by a rule, else `fact`. `solutions[].substitution.bindings` carries one entry per query variable the engine resolved. A variable left unresolved is ABSENT; it is never bound to itself. ## Joining a proof to the thing it proves `proof.goal_term_id` is the TermId of the CONCLUSION the node proved. It joins to `POST /api/v1/query/by-sort` and `GET /api/v1/terms/{id}`, and two solutions of one goal share it only when they prove the same conclusion. It is ABSENT when there is no such id — a goal proved without a preceding `CHAIN` materialised no conclusion, and a derivation replayed from a persistent store cannot be attributed to one. A client falls back deliberately there rather than by accident. `proof.rule_head_term_id` names the rule's instantiated HEAD on a rule application, when it differs from the conclusion. ⛔ It is rule scaffolding: `GET /api/v1/terms/{id}` refuses it deliberately (#192). It is a grouping key, not a fetchable id. # Authorization Requires X-Tenant-Id header. Traced: this is the path the zanzibar gateway hits for every permission check, so it is where an end-to-end trace either explains a slow request or does not. `skip_all` because the request body can be large and has no business in a span attribute.
|
|
1871
1871
|
*
|
|
1872
1872
|
* @tags inference
|
|
1873
1873
|
* @name BackwardChain
|
|
@@ -13668,19 +13668,56 @@ function BulkSetSimilaritiesResponseFromApiToFront(dto) {
|
|
|
13668
13668
|
errors: dto.errors
|
|
13669
13669
|
};
|
|
13670
13670
|
}
|
|
13671
|
+
var SORT_PREORDER_GRANULARITIES = [
|
|
13672
|
+
"similarity_deleted",
|
|
13673
|
+
"combined"
|
|
13674
|
+
];
|
|
13675
|
+
function toSortPreorderGranularity(value) {
|
|
13676
|
+
const known = SORT_PREORDER_GRANULARITIES.find((candidate) => candidate === value);
|
|
13677
|
+
if (known === void 0) {
|
|
13678
|
+
throw new ValidationError(
|
|
13679
|
+
`Unknown preorder granularity "${value}" \u2014 expected ${SORT_PREORDER_GRANULARITIES.join(" or ")}.`
|
|
13680
|
+
);
|
|
13681
|
+
}
|
|
13682
|
+
return known;
|
|
13683
|
+
}
|
|
13671
13684
|
function GetPreorderDegreeRequestFromFrontToApi(model) {
|
|
13672
13685
|
return {
|
|
13673
13686
|
sort1_id: model.sort1Id,
|
|
13674
|
-
sort2_id: model.sort2Id
|
|
13687
|
+
sort2_id: model.sort2Id,
|
|
13688
|
+
granularity: model.granularity
|
|
13675
13689
|
};
|
|
13676
13690
|
}
|
|
13677
13691
|
function GetPreorderDegreeResponseFromApiToFront(dto) {
|
|
13678
13692
|
return {
|
|
13679
13693
|
sort1Id: dto.sort1_id,
|
|
13680
13694
|
sort2Id: dto.sort2_id,
|
|
13695
|
+
degree: dto.degree,
|
|
13696
|
+
granularity: toSortPreorderGranularity(dto.granularity)
|
|
13697
|
+
};
|
|
13698
|
+
}
|
|
13699
|
+
function QuotientClassFromApiToFront(dto) {
|
|
13700
|
+
return {
|
|
13701
|
+
sortIds: dto.sort_ids,
|
|
13702
|
+
size: dto.size,
|
|
13703
|
+
alpha: dto.alpha
|
|
13704
|
+
};
|
|
13705
|
+
}
|
|
13706
|
+
function QuotientOrderEdgeFromApiToFront(dto) {
|
|
13707
|
+
return {
|
|
13708
|
+
from: dto.from,
|
|
13709
|
+
to: dto.to,
|
|
13681
13710
|
degree: dto.degree
|
|
13682
13711
|
};
|
|
13683
13712
|
}
|
|
13713
|
+
function GetQuotientOrderResponseFromApiToFront(dto) {
|
|
13714
|
+
return {
|
|
13715
|
+
granularity: toSortPreorderGranularity(dto.granularity),
|
|
13716
|
+
classes: dto.classes.map(QuotientClassFromApiToFront),
|
|
13717
|
+
count: dto.count,
|
|
13718
|
+
orderEdges: dto.order_edges.map(QuotientOrderEdgeFromApiToFront)
|
|
13719
|
+
};
|
|
13720
|
+
}
|
|
13684
13721
|
function EquivalenceClassFromApiToFront(dto) {
|
|
13685
13722
|
return {
|
|
13686
13723
|
sortIds: dto.sort_ids,
|
|
@@ -14527,13 +14564,32 @@ var SortsClient = class {
|
|
|
14527
14564
|
/**
|
|
14528
14565
|
* Compute the preorder degree between two sorts.
|
|
14529
14566
|
*
|
|
14530
|
-
* @param request - Sort pair to compute preorder degree for
|
|
14531
|
-
*
|
|
14532
|
-
* @
|
|
14533
|
-
*
|
|
14534
|
-
* @
|
|
14535
|
-
*
|
|
14536
|
-
*
|
|
14567
|
+
* @param request - Sort pair to compute preorder degree for, and optionally
|
|
14568
|
+
* which of the two preorders to read it from.
|
|
14569
|
+
* @returns The preorder degree response including sort IDs, degree, and the
|
|
14570
|
+
* granularity the degree was read from.
|
|
14571
|
+
* @throws {@link ApiError} If the sorts do not exist, or if `granularity`
|
|
14572
|
+
* carries a spelling the engine does not accept.
|
|
14573
|
+
* @throws {@link ValidationError} If the engine answers a granularity this
|
|
14574
|
+
* SDK version does not know.
|
|
14575
|
+
*
|
|
14576
|
+
* @remarks
|
|
14577
|
+
* Per Definition IV.5 (Milanese and Pasi, IEEE TFS 2024), the dotted preorder
|
|
14578
|
+
* is `preorder_dot = ((combined_preorder .- similarity) union subsumption)^+`,
|
|
14579
|
+
* where `.-` DELETES each directly-similar pair — it is NOT an arithmetic
|
|
14580
|
+
* difference. So a directly-similar pair answers `0` under the default
|
|
14581
|
+
* granularity: two similar sorts meet through their GLB, not through each
|
|
14582
|
+
* other.
|
|
14583
|
+
*
|
|
14584
|
+
* `granularity` selects the reading, with the same two spellings
|
|
14585
|
+
* `GET /api/v1/sorts/quotient-order` uses:
|
|
14586
|
+
* - omitted or `similarity_deleted` — Definition IV.5, the default, and the
|
|
14587
|
+
* relation the graded GLB and term substitutability are computed from.
|
|
14588
|
+
* - `combined` — Definition IV.1, where a similarity edge IS a step, so a
|
|
14589
|
+
* directly-similar pair answers its similarity degree.
|
|
14590
|
+
*
|
|
14591
|
+
* The response always echoes the granularity back, so a `0.0` is never
|
|
14592
|
+
* ambiguous between "no path" and "the pair deletion zeroed it".
|
|
14537
14593
|
*
|
|
14538
14594
|
* Degree interpretation:
|
|
14539
14595
|
* - 1.0 = subsumption (sort1 <= sort2)
|
|
@@ -14544,17 +14600,78 @@ var SortsClient = class {
|
|
|
14544
14600
|
*
|
|
14545
14601
|
* @example
|
|
14546
14602
|
* ```typescript
|
|
14547
|
-
* const
|
|
14603
|
+
* const strict = await client.sorts.getPreorderDegree({
|
|
14604
|
+
* sort1Id: 'uuid-1',
|
|
14605
|
+
* sort2Id: 'uuid-2',
|
|
14606
|
+
* });
|
|
14607
|
+
* console.log(strict.degree, strict.granularity); // 0 'similarity_deleted'
|
|
14608
|
+
*
|
|
14609
|
+
* const coarse = await client.sorts.getPreorderDegree({
|
|
14548
14610
|
* sort1Id: 'uuid-1',
|
|
14549
14611
|
* sort2Id: 'uuid-2',
|
|
14612
|
+
* granularity: 'combined',
|
|
14550
14613
|
* });
|
|
14551
|
-
* console.log(
|
|
14614
|
+
* console.log(coarse.degree, coarse.granularity); // 0.5 'combined'
|
|
14552
14615
|
* ```
|
|
14553
14616
|
*/
|
|
14554
14617
|
async getPreorderDegree(request, requestOptions) {
|
|
14555
14618
|
const response = await this.sorts.getPreorderDegree(GetPreorderDegreeRequestFromFrontToApi(request), toRequestParams(requestOptions));
|
|
14556
14619
|
return GetPreorderDegreeResponseFromApiToFront(response.data);
|
|
14557
14620
|
}
|
|
14621
|
+
/**
|
|
14622
|
+
* Get the Definition IV.9 quotient order over the caller's own lattice.
|
|
14623
|
+
*
|
|
14624
|
+
* @param options - Which of the two fuzzy preorders to quotient. Omitted
|
|
14625
|
+
* means `combined`, the engine's default HERE.
|
|
14626
|
+
* @returns The equivalence classes with their degrees, and the fuzzy partial
|
|
14627
|
+
* order between them.
|
|
14628
|
+
* @throws {@link ApiError} 400 when `granularity` carries a spelling the
|
|
14629
|
+
* engine does not accept.
|
|
14630
|
+
* @throws {@link ValidationError} If the engine answers a granularity this
|
|
14631
|
+
* SDK version does not know.
|
|
14632
|
+
*
|
|
14633
|
+
* @remarks
|
|
14634
|
+
* This is the tenant-scoped companion of
|
|
14635
|
+
* {@link SortsClient.getEquivalenceClasses}: the classes, degrees and order
|
|
14636
|
+
* describe exactly the sorts the caller can see, where the older
|
|
14637
|
+
* equivalence-classes route computes process-wide and then filters. Prefer
|
|
14638
|
+
* this one.
|
|
14639
|
+
*
|
|
14640
|
+
* ⚠️ The default granularity here is `combined`, NOT the
|
|
14641
|
+
* `similarity_deleted` default of {@link SortsClient.getPreorderDegree}. The
|
|
14642
|
+
* two routes take the same two spellings and disagree on which is the
|
|
14643
|
+
* default, so state it when it matters. The response echoes it back either
|
|
14644
|
+
* way.
|
|
14645
|
+
*
|
|
14646
|
+
* `orderEdges` is SPARSE and indexes into `classes`: a pair with no edge has
|
|
14647
|
+
* degree `0`. The order is a partial order — antisymmetric, unlike either
|
|
14648
|
+
* preorder it is built from.
|
|
14649
|
+
*
|
|
14650
|
+
* Uses tagged serialization format.
|
|
14651
|
+
*
|
|
14652
|
+
* @example
|
|
14653
|
+
* ```typescript
|
|
14654
|
+
* const quotient = await client.sorts.getQuotientOrder({
|
|
14655
|
+
* granularity: 'similarity_deleted',
|
|
14656
|
+
* });
|
|
14657
|
+
*
|
|
14658
|
+
* for (const cls of quotient.classes) {
|
|
14659
|
+
* console.log(`class of ${cls.size} sorts, degree ${cls.alpha}`);
|
|
14660
|
+
* }
|
|
14661
|
+
* for (const edge of quotient.orderEdges) {
|
|
14662
|
+
* const lower = quotient.classes[edge.from];
|
|
14663
|
+
* const upper = quotient.classes[edge.to];
|
|
14664
|
+
* console.log(`${lower.sortIds} <= ${upper.sortIds} at ${edge.degree}`);
|
|
14665
|
+
* }
|
|
14666
|
+
* ```
|
|
14667
|
+
*/
|
|
14668
|
+
async getQuotientOrder(options, requestOptions) {
|
|
14669
|
+
const response = await this.sorts.getQuotientOrder(
|
|
14670
|
+
{ granularity: options?.granularity },
|
|
14671
|
+
toRequestParams(requestOptions)
|
|
14672
|
+
);
|
|
14673
|
+
return GetQuotientOrderResponseFromApiToFront(response.data);
|
|
14674
|
+
}
|
|
14558
14675
|
/**
|
|
14559
14676
|
* Get equivalence classes based on the combined preorder.
|
|
14560
14677
|
*
|
|
@@ -14562,8 +14679,16 @@ var SortsClient = class {
|
|
|
14562
14679
|
* @throws {@link ApiError} If the lattice cannot be computed.
|
|
14563
14680
|
*
|
|
14564
14681
|
* @remarks
|
|
14565
|
-
* Per Definition IV.9 (Milanese and Pasi 2024)
|
|
14566
|
-
* s1 ~ s2 iff
|
|
14682
|
+
* Per Definition IV.9 (Milanese and Pasi 2024), two sorts are equivalent when
|
|
14683
|
+
* each reaches the other: `s1 ~ s2` iff `preorder(s1, s2) > 0` AND
|
|
14684
|
+
* `preorder(s2, s1) > 0`. The preorder here is the COMBINED one, where a
|
|
14685
|
+
* similarity edge is itself a step — not the `similarity_deleted` default of
|
|
14686
|
+
* {@link SortsClient.getPreorderDegree}.
|
|
14687
|
+
*
|
|
14688
|
+
* ⚠️ This route computes PROCESS-WIDE and then filters, so its classes can
|
|
14689
|
+
* be shaped by sorts the caller cannot see. {@link SortsClient.getQuotientOrder}
|
|
14690
|
+
* computes on the tenant-visible hierarchy instead, returns the same classes
|
|
14691
|
+
* with their degrees, and adds the partial order between them. Prefer it.
|
|
14567
14692
|
*
|
|
14568
14693
|
* Uses tagged serialization format.
|
|
14569
14694
|
*
|
|
@@ -15744,31 +15869,42 @@ function convertFeatures(features) {
|
|
|
15744
15869
|
}
|
|
15745
15870
|
|
|
15746
15871
|
// src/normalizers/homoiconic.ts
|
|
15747
|
-
function
|
|
15872
|
+
function assertPresent(value, what) {
|
|
15873
|
+
if (value === null || value === void 0) {
|
|
15874
|
+
throw new ValidationError(
|
|
15875
|
+
`${what} is required \u2014 received ${value === null ? "null" : "undefined"}.`,
|
|
15876
|
+
what
|
|
15877
|
+
);
|
|
15878
|
+
}
|
|
15879
|
+
}
|
|
15880
|
+
function FeatureInputValueDtoFromFrontToApi(value, path = "feature value") {
|
|
15881
|
+
assertPresent(value, path);
|
|
15748
15882
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
15749
15883
|
return value;
|
|
15750
15884
|
}
|
|
15751
15885
|
if (Array.isArray(value)) {
|
|
15752
|
-
return value.map(
|
|
15886
|
+
return value.map(
|
|
15887
|
+
(element, index) => FeatureInputValueDtoFromFrontToApi(element, `${path}[${index}]`)
|
|
15888
|
+
);
|
|
15753
15889
|
}
|
|
15754
15890
|
if ("name" in value && "constraint" in value) {
|
|
15755
15891
|
return {
|
|
15756
15892
|
name: value.name,
|
|
15757
|
-
constraint: TermInputDtoFromFrontToApi(value.constraint)
|
|
15893
|
+
constraint: TermInputDtoFromFrontToApi(value.constraint, `${path}.constraint`)
|
|
15758
15894
|
};
|
|
15759
15895
|
}
|
|
15760
15896
|
if ("name" in value) {
|
|
15761
15897
|
return { name: value.name };
|
|
15762
15898
|
}
|
|
15763
15899
|
if ("sortId" in value) {
|
|
15764
|
-
const features = value.features ? featuresInputFromFrontToApi(value.features) : void 0;
|
|
15900
|
+
const features = value.features ? featuresInputFromFrontToApi(value.features, `${path}.features`) : void 0;
|
|
15765
15901
|
return {
|
|
15766
15902
|
sort_id: value.sortId,
|
|
15767
15903
|
...features ? { features } : {}
|
|
15768
15904
|
};
|
|
15769
15905
|
}
|
|
15770
15906
|
if ("sortName" in value) {
|
|
15771
|
-
const features = value.features ? featuresInputFromFrontToApi(value.features) : void 0;
|
|
15907
|
+
const features = value.features ? featuresInputFromFrontToApi(value.features, `${path}.features`) : void 0;
|
|
15772
15908
|
return {
|
|
15773
15909
|
sort_name: value.sortName,
|
|
15774
15910
|
...features ? { features } : {}
|
|
@@ -15779,14 +15915,15 @@ function FeatureInputValueDtoFromFrontToApi(value) {
|
|
|
15779
15915
|
}
|
|
15780
15916
|
return { term_id: value.termId };
|
|
15781
15917
|
}
|
|
15782
|
-
function featuresInputFromFrontToApi(features) {
|
|
15918
|
+
function featuresInputFromFrontToApi(features, path = "features") {
|
|
15783
15919
|
const result = {};
|
|
15784
15920
|
for (const [key, val] of Object.entries(features)) {
|
|
15785
|
-
result[key] = FeatureInputValueDtoFromFrontToApi(val);
|
|
15921
|
+
result[key] = FeatureInputValueDtoFromFrontToApi(val, `${path}.${key}`);
|
|
15786
15922
|
}
|
|
15787
15923
|
return result;
|
|
15788
15924
|
}
|
|
15789
|
-
function TermInputDtoFromFrontToApi(model) {
|
|
15925
|
+
function TermInputDtoFromFrontToApi(model, path = "term") {
|
|
15926
|
+
assertPresent(model, path);
|
|
15790
15927
|
if ("termId" in model) {
|
|
15791
15928
|
return { term_id: model.termId };
|
|
15792
15929
|
}
|
|
@@ -15801,14 +15938,14 @@ function TermInputDtoFromFrontToApi(model) {
|
|
|
15801
15938
|
if ("sortId" in model) {
|
|
15802
15939
|
const inline = {
|
|
15803
15940
|
sort_id: model.sortId,
|
|
15804
|
-
features: featuresInputFromFrontToApi(model.features)
|
|
15941
|
+
features: featuresInputFromFrontToApi(model.features, `${path}.features`)
|
|
15805
15942
|
};
|
|
15806
15943
|
if (model.binding !== void 0) inline.binding = model.binding;
|
|
15807
15944
|
return inline;
|
|
15808
15945
|
}
|
|
15809
15946
|
const byName = {
|
|
15810
15947
|
sort_name: model.sortName,
|
|
15811
|
-
features: model.features ? featuresInputFromFrontToApi(model.features) : void 0
|
|
15948
|
+
features: model.features ? featuresInputFromFrontToApi(model.features, `${path}.features`) : void 0
|
|
15812
15949
|
};
|
|
15813
15950
|
if (model.binding !== void 0) byName.binding = model.binding;
|
|
15814
15951
|
return byName;
|
|
@@ -15870,6 +16007,7 @@ function ProofDtoFromApiToFront(dto) {
|
|
|
15870
16007
|
kind: dto.kind,
|
|
15871
16008
|
goalTermId: dto.goal_term_id,
|
|
15872
16009
|
ruleTermId: dto.rule_term_id,
|
|
16010
|
+
ruleHeadTermId: dto.rule_head_term_id,
|
|
15873
16011
|
goalDisplay: dto.goal_display,
|
|
15874
16012
|
ruleLabel: dto.rule_label,
|
|
15875
16013
|
substitution: HomoiconicSubstitutionDtoFromApiToFront(dto.substitution),
|
|
@@ -16369,7 +16507,9 @@ function RuleAggregatorDtoFromFrontToApi(model) {
|
|
|
16369
16507
|
function AddRuleRequestFromFrontToApi(model) {
|
|
16370
16508
|
return {
|
|
16371
16509
|
term: TermInputDtoFromFrontToApi(model.term),
|
|
16372
|
-
antecedents: model.antecedents?.map(
|
|
16510
|
+
antecedents: model.antecedents?.map(
|
|
16511
|
+
(t, i) => TermInputDtoFromFrontToApi(t, `antecedents[${i}]`)
|
|
16512
|
+
),
|
|
16373
16513
|
certainty: model.certainty,
|
|
16374
16514
|
aggregator: model.aggregator ? RuleAggregatorDtoFromFrontToApi(model.aggregator) : model.aggregator
|
|
16375
16515
|
};
|
|
@@ -16386,7 +16526,7 @@ function BulkAddRulesRequestFromFrontToApi(model) {
|
|
|
16386
16526
|
}
|
|
16387
16527
|
function BulkAddFactsRequestFromFrontToApi(model) {
|
|
16388
16528
|
return {
|
|
16389
|
-
facts: model.facts.map(TermInputDtoFromFrontToApi)
|
|
16529
|
+
facts: model.facts.map((t, i) => TermInputDtoFromFrontToApi(t, `facts[${i}]`))
|
|
16390
16530
|
};
|
|
16391
16531
|
}
|
|
16392
16532
|
function BackwardChainRequestFromFrontToApi(model) {
|
|
@@ -16404,12 +16544,15 @@ function BackwardChainRequestFromFrontToApi(model) {
|
|
|
16404
16544
|
}
|
|
16405
16545
|
function ForwardChainRequestFromFrontToApi(model) {
|
|
16406
16546
|
return {
|
|
16407
|
-
initial_facts: model.initialFacts?.map(
|
|
16547
|
+
initial_facts: model.initialFacts?.map(
|
|
16548
|
+
(t, i) => TermInputDtoFromFrontToApi(t, `initialFacts[${i}]`)
|
|
16549
|
+
),
|
|
16408
16550
|
keep_derived: model.keepDerived,
|
|
16409
16551
|
enable_provenance_tags: model.enableProvenanceTags,
|
|
16410
16552
|
max_iterations: model.maxIterations,
|
|
16411
16553
|
max_facts: model.maxFacts,
|
|
16412
|
-
emit_provenance: model.emitProvenance
|
|
16554
|
+
emit_provenance: model.emitProvenance,
|
|
16555
|
+
timeout_ms: model.timeoutMs ?? void 0
|
|
16413
16556
|
};
|
|
16414
16557
|
}
|
|
16415
16558
|
function FuzzyProveRequestFromFrontToApi(model) {
|
|
@@ -16426,7 +16569,7 @@ function FuzzyProveRequestFromFrontToApi(model) {
|
|
|
16426
16569
|
}
|
|
16427
16570
|
function BulkFuzzyProveRequestFromFrontToApi(model) {
|
|
16428
16571
|
return {
|
|
16429
|
-
goals: model.goals?.map(TermInputDtoFromFrontToApi),
|
|
16572
|
+
goals: model.goals?.map((t, i) => TermInputDtoFromFrontToApi(t, `goals[${i}]`)),
|
|
16430
16573
|
goal_ids: model.goalIds ?? void 0,
|
|
16431
16574
|
max_depth: model.maxDepth,
|
|
16432
16575
|
min_degree: model.minDegree,
|
|
@@ -16449,7 +16592,7 @@ function BayesianPredictRequestFromFrontToApi(model) {
|
|
|
16449
16592
|
}
|
|
16450
16593
|
function CreateGoalRequestFromFrontToApi(model) {
|
|
16451
16594
|
return {
|
|
16452
|
-
clauses: model.clauses.map(TermInputDtoFromFrontToApi),
|
|
16595
|
+
clauses: model.clauses.map((t, i) => TermInputDtoFromFrontToApi(t, `clauses[${i}]`)),
|
|
16453
16596
|
constraints: model.constraints?.map(ConstraintInputDtoFromFrontToApi),
|
|
16454
16597
|
min_degree: model.minDegree ?? void 0
|
|
16455
16598
|
};
|
|
@@ -16749,6 +16892,14 @@ var InferenceClient = class {
|
|
|
16749
16892
|
*
|
|
16750
16893
|
* The `timeout_ms` field on the request is a wall-clock timeout for the search.
|
|
16751
16894
|
* When it fires, the backend returns whatever solutions have been found so far.
|
|
16895
|
+
*
|
|
16896
|
+
* To join a proof node to the thing it proves, read `proof.goalTermId` — the
|
|
16897
|
+
* conclusion's term ID, which `client.terms.getTerm()` and
|
|
16898
|
+
* `client.query.findBySort()` both answer for. It is OPTIONAL: a goal proved
|
|
16899
|
+
* without a preceding forward chain materialises no conclusion, so the node
|
|
16900
|
+
* carries no id and `proof.goalDisplay` renders it instead. Do not read
|
|
16901
|
+
* `proof.ruleHeadTermId` as a fetchable id — it names the rule's instantiated
|
|
16902
|
+
* head, which the term routes refuse.
|
|
16752
16903
|
*/
|
|
16753
16904
|
async backwardChain(request, requestOptions) {
|
|
16754
16905
|
const wireRequest = {
|
|
@@ -16852,13 +17003,37 @@ var InferenceClient = class {
|
|
|
16852
17003
|
/**
|
|
16853
17004
|
* Run negation-as-failure (NAF) proof search.
|
|
16854
17005
|
*
|
|
16855
|
-
* @param request - NAF prove request.
|
|
17006
|
+
* @param request - NAF prove request. Each literal's `term` takes a
|
|
17007
|
+
* {@link psi} term or a wire {@link TermInputDto}, like every other
|
|
17008
|
+
* term-carrying method.
|
|
16856
17009
|
* @returns NAF proof result.
|
|
16857
17010
|
*
|
|
17011
|
+
* @remarks
|
|
17012
|
+
* Uses the untagged (homoiconic) serialization format: a literal's features
|
|
17013
|
+
* are plain scalars and `"?Var"` strings.
|
|
17014
|
+
*
|
|
17015
|
+
* @example
|
|
17016
|
+
* ```typescript
|
|
17017
|
+
* const result = await client.inference.nafProve({
|
|
17018
|
+
* literals: [
|
|
17019
|
+
* { term: psi('employee', { name: '?Name' }) },
|
|
17020
|
+
* { term: psi('senior_engineer', { name: '?Name' }), negated: true },
|
|
17021
|
+
* ],
|
|
17022
|
+
* maxSolutions: 10,
|
|
17023
|
+
* });
|
|
17024
|
+
* ```
|
|
17025
|
+
*
|
|
16858
17026
|
* @see proveWithNegation — friendlier alias for this method.
|
|
16859
17027
|
*/
|
|
16860
17028
|
async nafProve(request, requestOptions) {
|
|
16861
|
-
const
|
|
17029
|
+
const wireRequest = {
|
|
17030
|
+
...request,
|
|
17031
|
+
literals: request.literals?.map((literal) => ({
|
|
17032
|
+
...literal,
|
|
17033
|
+
term: convertTermArg(literal.term)
|
|
17034
|
+
}))
|
|
17035
|
+
};
|
|
17036
|
+
const response = await this.api.nafProve(NafProveRequestFromFrontToApi(wireRequest), toRequestParams(requestOptions));
|
|
16862
17037
|
return NafProveResponseFromApiToFront(response.data);
|
|
16863
17038
|
}
|
|
16864
17039
|
/**
|
|
@@ -23785,7 +23960,7 @@ function EntailmentRequestFromFrontToApi(model) {
|
|
|
23785
23960
|
return {
|
|
23786
23961
|
antecedent: TermInputDtoFromFrontToApi(model.antecedent),
|
|
23787
23962
|
consequent: TermInputDtoFromFrontToApi(model.consequent),
|
|
23788
|
-
facts: model.facts?.map(TermInputDtoFromFrontToApi)
|
|
23963
|
+
facts: model.facts?.map((t, i) => TermInputDtoFromFrontToApi(t, `facts[${i}]`))
|
|
23789
23964
|
};
|
|
23790
23965
|
}
|
|
23791
23966
|
function EntailmentResponseFromApiToFront(dto) {
|
|
@@ -23799,7 +23974,7 @@ function DisentailmentRequestFromFrontToApi(model) {
|
|
|
23799
23974
|
return {
|
|
23800
23975
|
antecedent: TermInputDtoFromFrontToApi(model.antecedent),
|
|
23801
23976
|
consequent: TermInputDtoFromFrontToApi(model.consequent),
|
|
23802
|
-
facts: model.facts?.map(TermInputDtoFromFrontToApi)
|
|
23977
|
+
facts: model.facts?.map((t, i) => TermInputDtoFromFrontToApi(t, `facts[${i}]`))
|
|
23803
23978
|
};
|
|
23804
23979
|
}
|
|
23805
23980
|
function DisentailmentResponseFromApiToFront(dto) {
|
|
@@ -25390,12 +25565,25 @@ function SourceDetailResponseFromApiToFront(dto) {
|
|
|
25390
25565
|
supportedModes: dto.supported_modes
|
|
25391
25566
|
};
|
|
25392
25567
|
}
|
|
25568
|
+
function ConfigFieldDtoFromApiToFront(dto) {
|
|
25569
|
+
return {
|
|
25570
|
+
// `name` is the factory's own JSON key and goes back on the wire
|
|
25571
|
+
// verbatim — never camelCased, in either direction (#14).
|
|
25572
|
+
name: dto.name,
|
|
25573
|
+
type: dto.type,
|
|
25574
|
+
required: dto.required
|
|
25575
|
+
};
|
|
25576
|
+
}
|
|
25393
25577
|
function SourceTypeDtoFromApiToFront(dto) {
|
|
25394
25578
|
return {
|
|
25395
25579
|
sourceType: dto.source_type,
|
|
25396
25580
|
aliases: dto.aliases,
|
|
25397
25581
|
available: dto.available,
|
|
25398
|
-
supportedModes: dto.supported_modes
|
|
25582
|
+
supportedModes: dto.supported_modes,
|
|
25583
|
+
// Defaulted rather than left absent: the field is required on the current
|
|
25584
|
+
// engine, and an empty list reads correctly on an older one — a form built
|
|
25585
|
+
// from no fields is visibly empty, where an absent list is a crash.
|
|
25586
|
+
configFields: (dto.config_fields ?? []).map(ConfigFieldDtoFromApiToFront)
|
|
25399
25587
|
};
|
|
25400
25588
|
}
|
|
25401
25589
|
function ListSourceTypesResponseFromApiToFront(dto) {
|
|
@@ -25415,6 +25603,7 @@ function DiscoverableTypeDtoFromApiToFront(dto) {
|
|
|
25415
25603
|
return {
|
|
25416
25604
|
comment: dto.comment,
|
|
25417
25605
|
estimatedRows: dto.estimated_rows,
|
|
25606
|
+
columnCount: dto.column_count,
|
|
25418
25607
|
name: dto.name
|
|
25419
25608
|
};
|
|
25420
25609
|
}
|
|
@@ -25425,6 +25614,15 @@ function ListTablesResponseFromApiToFront(dto) {
|
|
|
25425
25614
|
total: dto.total
|
|
25426
25615
|
};
|
|
25427
25616
|
}
|
|
25617
|
+
function KeyProvenanceDtoFromApiToFront(dto) {
|
|
25618
|
+
return {
|
|
25619
|
+
source: dto.source,
|
|
25620
|
+
chosenBy: dto.chosen_by,
|
|
25621
|
+
explanation: dto.explanation,
|
|
25622
|
+
guaranteedUnique: dto.guaranteed_unique,
|
|
25623
|
+
durability: dto.durability
|
|
25624
|
+
};
|
|
25625
|
+
}
|
|
25428
25626
|
function DiscoveredFeatureDtoFromApiToFront(dto) {
|
|
25429
25627
|
return {
|
|
25430
25628
|
constraints: dto.constraints,
|
|
@@ -25432,10 +25630,16 @@ function DiscoveredFeatureDtoFromApiToFront(dto) {
|
|
|
25432
25630
|
isIdentifier: dto.is_identifier,
|
|
25433
25631
|
isRelation: dto.is_relation,
|
|
25434
25632
|
name: dto.name,
|
|
25633
|
+
// The engine's own OSFQL-readable spelling. Defaulted to `name`, which it
|
|
25634
|
+
// is identical to, so an older engine that predates it stays usable.
|
|
25635
|
+
featureName: dto.feature_name ?? dto.name,
|
|
25435
25636
|
relationTarget: dto.relation_target,
|
|
25436
25637
|
required: dto.required,
|
|
25437
25638
|
sourceName: dto.source_name,
|
|
25438
|
-
typeHint: dto.type_hint
|
|
25639
|
+
typeHint: dto.type_hint,
|
|
25640
|
+
// The difference between a declared primary key and a guess. Carried
|
|
25641
|
+
// through so a mapping wizard can present the guess as a guess (#14).
|
|
25642
|
+
identifierProvenance: dto.identifier_provenance ? KeyProvenanceDtoFromApiToFront(dto.identifier_provenance) : dto.identifier_provenance
|
|
25439
25643
|
};
|
|
25440
25644
|
}
|
|
25441
25645
|
function DiscoveredSortDtoFromApiToFront(dto) {
|
|
@@ -31285,7 +31489,9 @@ var OptimizeClient = class {
|
|
|
31285
31489
|
}
|
|
31286
31490
|
const ruleResponse = await this.inferenceApi.addRule({
|
|
31287
31491
|
term: TermInputDtoFromFrontToApi(compiled.solutionTerm),
|
|
31288
|
-
antecedents: compiled.antecedents.map(
|
|
31492
|
+
antecedents: compiled.antecedents.map(
|
|
31493
|
+
(t, i) => TermInputDtoFromFrontToApi(t, `antecedents[${i}]`)
|
|
31494
|
+
),
|
|
31289
31495
|
certainty: 1
|
|
31290
31496
|
}, toRequestParams(requestOptions));
|
|
31291
31497
|
ruleTermId = extractRuleTermId(ruleResponse.data);
|
|
@@ -31964,6 +32170,7 @@ function OsfqlResponseFromApiToFront(dto) {
|
|
|
31964
32170
|
bindings,
|
|
31965
32171
|
fetched,
|
|
31966
32172
|
producedTermIds: dto.produced_term_ids,
|
|
32173
|
+
updatedTermIds: dto.updated_term_ids,
|
|
31967
32174
|
definedSortIds: dto.defined_sort_ids,
|
|
31968
32175
|
diagnostics: dto.diagnostics,
|
|
31969
32176
|
statementCount: dto.statement_count
|
|
@@ -32035,11 +32242,25 @@ function OsfqlPreviewAffectedFromApiToFront(dto) {
|
|
|
32035
32242
|
affected.exact = dto.exact;
|
|
32036
32243
|
}
|
|
32037
32244
|
if (dto.sample_rows !== void 0) {
|
|
32038
|
-
const rows =
|
|
32039
|
-
|
|
32040
|
-
|
|
32245
|
+
const rows = [];
|
|
32246
|
+
let unparsed = 0;
|
|
32247
|
+
const wireRows = dto.sample_rows;
|
|
32248
|
+
if (Array.isArray(wireRows)) {
|
|
32249
|
+
for (const row of wireRows) {
|
|
32250
|
+
const parsed = OsfqlBindingFromApiToFront(row);
|
|
32251
|
+
if (parsed === void 0) {
|
|
32252
|
+
unparsed += 1;
|
|
32253
|
+
} else {
|
|
32254
|
+
rows.push(parsed);
|
|
32255
|
+
}
|
|
32256
|
+
}
|
|
32257
|
+
} else {
|
|
32258
|
+
unparsed = 1;
|
|
32041
32259
|
}
|
|
32042
32260
|
affected.sampleRows = rows;
|
|
32261
|
+
if (unparsed > 0) {
|
|
32262
|
+
affected.unparsedSampleRows = unparsed;
|
|
32263
|
+
}
|
|
32043
32264
|
}
|
|
32044
32265
|
if (dto.by_sort !== void 0) {
|
|
32045
32266
|
affected.bySort = dto.by_sort.map(OsfqlPreviewSortCountFromApiToFront);
|
|
@@ -32060,34 +32281,15 @@ function OsfqlPreviewStatementFromApiToFront(dto) {
|
|
|
32060
32281
|
source: dto.source
|
|
32061
32282
|
};
|
|
32062
32283
|
if (dto.affected !== void 0) {
|
|
32063
|
-
|
|
32064
|
-
if (affected === void 0) {
|
|
32065
|
-
return void 0;
|
|
32066
|
-
}
|
|
32067
|
-
statement.affected = affected;
|
|
32284
|
+
statement.affected = OsfqlPreviewAffectedFromApiToFront(dto.affected);
|
|
32068
32285
|
}
|
|
32069
32286
|
if (dto.nested !== void 0) {
|
|
32070
|
-
|
|
32071
|
-
for (const child of dto.nested) {
|
|
32072
|
-
const parsed = OsfqlPreviewStatementFromApiToFront(child);
|
|
32073
|
-
if (parsed === void 0) {
|
|
32074
|
-
return void 0;
|
|
32075
|
-
}
|
|
32076
|
-
nested.push(parsed);
|
|
32077
|
-
}
|
|
32078
|
-
statement.nested = nested;
|
|
32287
|
+
statement.nested = dto.nested.map(OsfqlPreviewStatementFromApiToFront);
|
|
32079
32288
|
}
|
|
32080
32289
|
return statement;
|
|
32081
32290
|
}
|
|
32082
32291
|
function OsfqlPreviewResponseFromApiToFront(dto) {
|
|
32083
|
-
const statements =
|
|
32084
|
-
for (const entry of dto.statements) {
|
|
32085
|
-
const parsed = OsfqlPreviewStatementFromApiToFront(entry);
|
|
32086
|
-
if (parsed === void 0) {
|
|
32087
|
-
return void 0;
|
|
32088
|
-
}
|
|
32089
|
-
statements.push(parsed);
|
|
32090
|
-
}
|
|
32292
|
+
const statements = dto.statements.map(OsfqlPreviewStatementFromApiToFront);
|
|
32091
32293
|
const response = { mutates: dto.mutates, statements };
|
|
32092
32294
|
if (dto.atomic_refusal !== void 0) {
|
|
32093
32295
|
response.atomicRefusal = dto.atomic_refusal ? OsfqlAtomicRefusalFromApiToFront(dto.atomic_refusal) : dto.atomic_refusal;
|
|
@@ -32183,8 +32385,6 @@ var OsfqlClient = class {
|
|
|
32183
32385
|
* atomic refusal when there is one.
|
|
32184
32386
|
* @throws {ApiError} If the program does not parse (HTTP 400, `OsfqlErrorResponse`),
|
|
32185
32387
|
* or the request otherwise fails.
|
|
32186
|
-
* @throws {ReasoningLayerError} If a sample row carries a value that does not satisfy
|
|
32187
|
-
* the published {@link OsfqlValue} contract.
|
|
32188
32388
|
*
|
|
32189
32389
|
* @remarks
|
|
32190
32390
|
* **Why call this instead of classifying the program client-side.** Three
|
|
@@ -32219,9 +32419,16 @@ var OsfqlClient = class {
|
|
|
32219
32419
|
* Two further measured facts. The top-level `mutates` DOES fold nested
|
|
32220
32420
|
* statements now: the `IF` program above answers `true`, and so does an `IF`
|
|
32221
32421
|
* whose only writing branch is the `ELSE` — the earlier defect where an `IF`
|
|
32222
|
-
* with a writing branch answered `false` is fixed. And `affected`
|
|
32223
|
-
*
|
|
32224
|
-
*
|
|
32422
|
+
* with a writing branch answered `false` is fixed. And `affected` is NOT
|
|
32423
|
+
* ambiguous: a destructive statement that matches zero rows answers
|
|
32424
|
+
* `{count: 0, exact: true}` rather than omitting the block. Measured
|
|
32425
|
+
* 2026-09-21 — `preview('RETRACT widget(name: "nobody");')` against an empty
|
|
32426
|
+
* `widget` answers `affected: {"count":0,"exact":true}`, while
|
|
32427
|
+
* `preview('MATCH widget(name: ?N);')` carries no `affected` key at all. So
|
|
32428
|
+
* an ABSENT block means the statement has no affected-row set; `count: 0`
|
|
32429
|
+
* means the rows were counted and there are none. A confirm dialog can tell
|
|
32430
|
+
* the two apart, which is what the block was separated for. See
|
|
32431
|
+
* {@link OsfqlPreviewAffected.count}.
|
|
32225
32432
|
*
|
|
32226
32433
|
* `statement.index` is a single counter over the whole program: an `IF` at
|
|
32227
32434
|
* index 1 carries nested entries at index 2 and 3.
|
|
@@ -32262,13 +32469,7 @@ var OsfqlClient = class {
|
|
|
32262
32469
|
OsfqlRequestFromFrontToApi({ ...options, query }),
|
|
32263
32470
|
toRequestParams(requestOptions)
|
|
32264
32471
|
);
|
|
32265
|
-
|
|
32266
|
-
if (parsed === void 0) {
|
|
32267
|
-
throw new ReasoningLayerError(
|
|
32268
|
-
"osfql/preview returned an affected sample row that does not match the published OsfqlValue contract (expected tagged values with a lowercase `type` discriminator)"
|
|
32269
|
-
);
|
|
32270
|
-
}
|
|
32271
|
-
return parsed;
|
|
32472
|
+
return OsfqlPreviewResponseFromApiToFront(response.data);
|
|
32272
32473
|
}
|
|
32273
32474
|
/**
|
|
32274
32475
|
* Diagnose an OSFQL program for contradictions and inconsistencies.
|
|
@@ -34201,6 +34402,27 @@ function AuditPageFromApiToFront(dto) {
|
|
|
34201
34402
|
offset: dto.offset
|
|
34202
34403
|
};
|
|
34203
34404
|
}
|
|
34405
|
+
function RiskTotalsDtoFromApiToFront(dto) {
|
|
34406
|
+
return {
|
|
34407
|
+
nSafe: dto.n_safe,
|
|
34408
|
+
nWarning: dto.n_warning,
|
|
34409
|
+
nUnsafe: dto.n_unsafe,
|
|
34410
|
+
nUngraded: dto.n_ungraded,
|
|
34411
|
+
nGradedByVerification: dto.n_graded_by_verification,
|
|
34412
|
+
nVerified: dto.n_verified,
|
|
34413
|
+
nRefuted: dto.n_refuted,
|
|
34414
|
+
nAbstained: dto.n_abstained,
|
|
34415
|
+
nFabricationDetected: dto.n_fabrication_detected,
|
|
34416
|
+
nFabricationClean: dto.n_fabrication_clean,
|
|
34417
|
+
nFabricationUnknown: dto.n_fabrication_unknown,
|
|
34418
|
+
nClaimsTotal: dto.n_claims_total,
|
|
34419
|
+
nClaimsRefuted: dto.n_claims_refuted,
|
|
34420
|
+
// Carried through as `null`, never folded to `0`. `null` is "not
|
|
34421
|
+
// measured" — the denominator is checked responses only — and `0` would
|
|
34422
|
+
// report a clean fabrication rate for a ledger nobody checked (#11).
|
|
34423
|
+
fabricationRate: dto.fabrication_rate
|
|
34424
|
+
};
|
|
34425
|
+
}
|
|
34204
34426
|
function SummaryResponseFromApiToFront(dto) {
|
|
34205
34427
|
const out = {
|
|
34206
34428
|
nRecords: dto.n_records,
|
|
@@ -34210,6 +34432,12 @@ function SummaryResponseFromApiToFront(dto) {
|
|
|
34210
34432
|
};
|
|
34211
34433
|
if (dto.ts_first) out.tsFirst = dto.ts_first;
|
|
34212
34434
|
if (dto.ts_last) out.tsLast = dto.ts_last;
|
|
34435
|
+
if (dto.risk !== void 0 && dto.risk !== null) {
|
|
34436
|
+
out.risk = RiskTotalsDtoFromApiToFront(dto.risk);
|
|
34437
|
+
}
|
|
34438
|
+
if (dto.n_oversight_decisions !== void 0 && dto.n_oversight_decisions !== null) {
|
|
34439
|
+
out.nOversightDecisions = dto.n_oversight_decisions;
|
|
34440
|
+
}
|
|
34213
34441
|
return out;
|
|
34214
34442
|
}
|
|
34215
34443
|
function VerifyResponseFromApiToFront(dto) {
|
|
@@ -36436,6 +36664,23 @@ function ImportOwlResponseFromApiToFront(dto) {
|
|
|
36436
36664
|
sortsCreated: dto.sorts_created
|
|
36437
36665
|
};
|
|
36438
36666
|
}
|
|
36667
|
+
function ExecuteTranspiledRequestFromFrontToApi(model) {
|
|
36668
|
+
return {
|
|
36669
|
+
osfql: model.osfql
|
|
36670
|
+
};
|
|
36671
|
+
}
|
|
36672
|
+
function ExecuteTranspiledResponseFromApiToFront(dto) {
|
|
36673
|
+
return {
|
|
36674
|
+
// `rows` are the source's OWN records; their keys are its column names and
|
|
36675
|
+
// are data, carried verbatim. The generated type erases them to `any[]`,
|
|
36676
|
+
// so the shipped surface narrows them to one object per row (#12).
|
|
36677
|
+
rows: dto.rows,
|
|
36678
|
+
rowCount: dto.row_count,
|
|
36679
|
+
query: dto.query,
|
|
36680
|
+
dialect: dto.dialect,
|
|
36681
|
+
sourceId: dto.source_id
|
|
36682
|
+
};
|
|
36683
|
+
}
|
|
36439
36684
|
function TranspileRequestFromFrontToApi(model) {
|
|
36440
36685
|
return {
|
|
36441
36686
|
dialect: model.dialect,
|
|
@@ -36694,6 +36939,46 @@ var OntologyBridgeClient = class {
|
|
|
36694
36939
|
);
|
|
36695
36940
|
return TranspileResponseFromApiToFront(response.data);
|
|
36696
36941
|
}
|
|
36942
|
+
/**
|
|
36943
|
+
* Transpile an OSFQL query AND run it on the source it is bound to.
|
|
36944
|
+
*
|
|
36945
|
+
* @param request - The OSFQL query. No dialect: the binding names the
|
|
36946
|
+
* source, and the source's type decides the dialect.
|
|
36947
|
+
* @param requestOptions - Per-call request options.
|
|
36948
|
+
* @returns The rows the source returned, the native query that fetched them,
|
|
36949
|
+
* its dialect, and the source id.
|
|
36950
|
+
* @throws {ApiError} If the request fails.
|
|
36951
|
+
*
|
|
36952
|
+
* @remarks
|
|
36953
|
+
* Sent to `POST /api/v1/ontology/query`. The response uses the snake_case
|
|
36954
|
+
* wire format (`row_count`, `source_id`); this client normalizes at the
|
|
36955
|
+
* boundary. `rows` are the source's own records, one object per row, and
|
|
36956
|
+
* their KEYS are the source's column names — data, carried verbatim.
|
|
36957
|
+
*
|
|
36958
|
+
* **This is the second half of {@link OntologyBridgeClient.transpile}, and
|
|
36959
|
+
* for a `transpile`-mode source it is the only route that answers.** Such a
|
|
36960
|
+
* source deliberately ingests nothing: its bound sorts are live views over
|
|
36961
|
+
* the operator's own database, so every KB query over them reports no
|
|
36962
|
+
* results. `transpile` emits the native query and stops; this runs it.
|
|
36963
|
+
*
|
|
36964
|
+
* @example
|
|
36965
|
+
* ```typescript
|
|
36966
|
+
* const result = await client.ontologyBridge.executeTranspiled({
|
|
36967
|
+
* osfql: 'MATCH person(name: ?N);',
|
|
36968
|
+
* });
|
|
36969
|
+
* console.log(result.dialect); // "postgres"
|
|
36970
|
+
* console.log(result.query); // the SQL that ran
|
|
36971
|
+
* console.log(result.rowCount); // 12
|
|
36972
|
+
* for (const row of result.rows) console.log(row['name']);
|
|
36973
|
+
* ```
|
|
36974
|
+
*/
|
|
36975
|
+
async executeTranspiled(request, requestOptions) {
|
|
36976
|
+
const response = await this.api.executeTranspiled(
|
|
36977
|
+
ExecuteTranspiledRequestFromFrontToApi(request),
|
|
36978
|
+
toRequestParams(requestOptions)
|
|
36979
|
+
);
|
|
36980
|
+
return ExecuteTranspiledResponseFromApiToFront(response.data);
|
|
36981
|
+
}
|
|
36697
36982
|
/**
|
|
36698
36983
|
* Remove a sort-table binding.
|
|
36699
36984
|
*
|
|
@@ -38939,12 +39224,46 @@ function ConformanceRequestFromFrontToApi(model) {
|
|
|
38939
39224
|
ontology: model.ontology
|
|
38940
39225
|
};
|
|
38941
39226
|
}
|
|
39227
|
+
function stringAt(source, key) {
|
|
39228
|
+
const value = Reflect.get(source, key);
|
|
39229
|
+
return typeof value === "string" ? value : void 0;
|
|
39230
|
+
}
|
|
39231
|
+
function suggestedFixesAt(source) {
|
|
39232
|
+
const value = Reflect.get(source, "suggested_fixes");
|
|
39233
|
+
if (!Array.isArray(value)) return void 0;
|
|
39234
|
+
const fixes = [];
|
|
39235
|
+
for (const entry of value) {
|
|
39236
|
+
if (typeof entry === "object" && entry !== null && !Array.isArray(entry)) {
|
|
39237
|
+
fixes.push({ ...entry });
|
|
39238
|
+
}
|
|
39239
|
+
}
|
|
39240
|
+
return fixes;
|
|
39241
|
+
}
|
|
39242
|
+
function ConformanceViolationDtoFromApiToFront(dto) {
|
|
39243
|
+
if (typeof dto !== "object" || dto === null) return {};
|
|
39244
|
+
const violation = {};
|
|
39245
|
+
const subject = stringAt(dto, "subject");
|
|
39246
|
+
if (subject !== void 0) violation.subject = subject;
|
|
39247
|
+
const object = stringAt(dto, "object");
|
|
39248
|
+
if (object !== void 0) violation.object = object;
|
|
39249
|
+
const feature = stringAt(dto, "feature");
|
|
39250
|
+
if (feature !== void 0) violation.feature = feature;
|
|
39251
|
+
const subjectSort = stringAt(dto, "subject_sort");
|
|
39252
|
+
if (subjectSort !== void 0) violation.subjectSort = subjectSort;
|
|
39253
|
+
const objectSort = stringAt(dto, "object_sort");
|
|
39254
|
+
if (objectSort !== void 0) violation.objectSort = objectSort;
|
|
39255
|
+
const kind = stringAt(dto, "kind");
|
|
39256
|
+
if (kind !== void 0) violation.kind = kind;
|
|
39257
|
+
const suggestedFixes = suggestedFixesAt(dto);
|
|
39258
|
+
if (suggestedFixes !== void 0) violation.suggestedFixes = suggestedFixes;
|
|
39259
|
+
return violation;
|
|
39260
|
+
}
|
|
38942
39261
|
function ConformanceCheckResponseFromApiToFront(dto) {
|
|
38943
39262
|
return {
|
|
38944
39263
|
conformant: dto.conformant,
|
|
38945
39264
|
totalViolations: dto.total_violations,
|
|
38946
39265
|
byKind: ViolationCountsDtoFromApiToFront(dto.by_kind),
|
|
38947
|
-
violations: dto.violations.map(
|
|
39266
|
+
violations: dto.violations.map(ConformanceViolationDtoFromApiToFront)
|
|
38948
39267
|
};
|
|
38949
39268
|
}
|
|
38950
39269
|
function ConformanceRepairResponseFromApiToFront(dto) {
|
|
@@ -38982,6 +39301,11 @@ var ConformanceClient = class {
|
|
|
38982
39301
|
* The ontology travels as an opaque string in the declared RDF format; no
|
|
38983
39302
|
* value serialization is applied to it.
|
|
38984
39303
|
*
|
|
39304
|
+
* Each violation is a {@link ConformanceViolationDto}, NOT the shared
|
|
39305
|
+
* `ViolationDto`. The two share no key, and the route's OpenAPI slot holds
|
|
39306
|
+
* the wrong one — which is why the fields are narrowed from the wire in the
|
|
39307
|
+
* normalizer and why every one of them is optional (#13).
|
|
39308
|
+
*
|
|
38985
39309
|
* @example
|
|
38986
39310
|
* ```typescript
|
|
38987
39311
|
* const result = await client.conformance.check({
|
|
@@ -38993,7 +39317,8 @@ var ConformanceClient = class {
|
|
|
38993
39317
|
* console.log(result.totalViolations, 'violations');
|
|
38994
39318
|
* console.log(result.byKind.v1Inversion, 'subject/object inversions');
|
|
38995
39319
|
* for (const violation of result.violations) {
|
|
38996
|
-
* console.log(violation.
|
|
39320
|
+
* console.log(violation.kind, violation.subject, violation.feature, violation.object);
|
|
39321
|
+
* console.log(violation.suggestedFixes); // [{ action: 'swap' }]
|
|
38997
39322
|
* }
|
|
38998
39323
|
* }
|
|
38999
39324
|
* ```
|