@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.cjs
CHANGED
|
@@ -7,7 +7,7 @@ var __export = (target, all) => {
|
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
// src/config.ts
|
|
10
|
-
var SDK_VERSION = "1.
|
|
10
|
+
var SDK_VERSION = "2.1.0";
|
|
11
11
|
function resolveConfig(config) {
|
|
12
12
|
if (!config.baseUrl) {
|
|
13
13
|
throw new Error("ClientConfig.baseUrl is required");
|
|
@@ -1164,11 +1164,11 @@ var Sorts = class {
|
|
|
1164
1164
|
...params
|
|
1165
1165
|
});
|
|
1166
1166
|
/**
|
|
1167
|
-
* @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.)
|
|
1167
|
+
* @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.)
|
|
1168
1168
|
*
|
|
1169
1169
|
* @tags sorts
|
|
1170
1170
|
* @name GetPreorderDegree
|
|
1171
|
-
* @summary Get preorder degree
|
|
1171
|
+
* @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.
|
|
1172
1172
|
* @request POST:/api/v1/sorts/preorder-degree
|
|
1173
1173
|
*/
|
|
1174
1174
|
getPreorderDegree = (data, params = {}) => this.http.request({
|
|
@@ -1869,7 +1869,7 @@ var Inference = class {
|
|
|
1869
1869
|
...params
|
|
1870
1870
|
});
|
|
1871
1871
|
/**
|
|
1872
|
-
* @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.
|
|
1872
|
+
* @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.
|
|
1873
1873
|
*
|
|
1874
1874
|
* @tags inference
|
|
1875
1875
|
* @name BackwardChain
|
|
@@ -13670,19 +13670,56 @@ function BulkSetSimilaritiesResponseFromApiToFront(dto) {
|
|
|
13670
13670
|
errors: dto.errors
|
|
13671
13671
|
};
|
|
13672
13672
|
}
|
|
13673
|
+
var SORT_PREORDER_GRANULARITIES = [
|
|
13674
|
+
"similarity_deleted",
|
|
13675
|
+
"combined"
|
|
13676
|
+
];
|
|
13677
|
+
function toSortPreorderGranularity(value) {
|
|
13678
|
+
const known = SORT_PREORDER_GRANULARITIES.find((candidate) => candidate === value);
|
|
13679
|
+
if (known === void 0) {
|
|
13680
|
+
throw new ValidationError(
|
|
13681
|
+
`Unknown preorder granularity "${value}" \u2014 expected ${SORT_PREORDER_GRANULARITIES.join(" or ")}.`
|
|
13682
|
+
);
|
|
13683
|
+
}
|
|
13684
|
+
return known;
|
|
13685
|
+
}
|
|
13673
13686
|
function GetPreorderDegreeRequestFromFrontToApi(model) {
|
|
13674
13687
|
return {
|
|
13675
13688
|
sort1_id: model.sort1Id,
|
|
13676
|
-
sort2_id: model.sort2Id
|
|
13689
|
+
sort2_id: model.sort2Id,
|
|
13690
|
+
granularity: model.granularity
|
|
13677
13691
|
};
|
|
13678
13692
|
}
|
|
13679
13693
|
function GetPreorderDegreeResponseFromApiToFront(dto) {
|
|
13680
13694
|
return {
|
|
13681
13695
|
sort1Id: dto.sort1_id,
|
|
13682
13696
|
sort2Id: dto.sort2_id,
|
|
13697
|
+
degree: dto.degree,
|
|
13698
|
+
granularity: toSortPreorderGranularity(dto.granularity)
|
|
13699
|
+
};
|
|
13700
|
+
}
|
|
13701
|
+
function QuotientClassFromApiToFront(dto) {
|
|
13702
|
+
return {
|
|
13703
|
+
sortIds: dto.sort_ids,
|
|
13704
|
+
size: dto.size,
|
|
13705
|
+
alpha: dto.alpha
|
|
13706
|
+
};
|
|
13707
|
+
}
|
|
13708
|
+
function QuotientOrderEdgeFromApiToFront(dto) {
|
|
13709
|
+
return {
|
|
13710
|
+
from: dto.from,
|
|
13711
|
+
to: dto.to,
|
|
13683
13712
|
degree: dto.degree
|
|
13684
13713
|
};
|
|
13685
13714
|
}
|
|
13715
|
+
function GetQuotientOrderResponseFromApiToFront(dto) {
|
|
13716
|
+
return {
|
|
13717
|
+
granularity: toSortPreorderGranularity(dto.granularity),
|
|
13718
|
+
classes: dto.classes.map(QuotientClassFromApiToFront),
|
|
13719
|
+
count: dto.count,
|
|
13720
|
+
orderEdges: dto.order_edges.map(QuotientOrderEdgeFromApiToFront)
|
|
13721
|
+
};
|
|
13722
|
+
}
|
|
13686
13723
|
function EquivalenceClassFromApiToFront(dto) {
|
|
13687
13724
|
return {
|
|
13688
13725
|
sortIds: dto.sort_ids,
|
|
@@ -14529,13 +14566,32 @@ var SortsClient = class {
|
|
|
14529
14566
|
/**
|
|
14530
14567
|
* Compute the preorder degree between two sorts.
|
|
14531
14568
|
*
|
|
14532
|
-
* @param request - Sort pair to compute preorder degree for
|
|
14533
|
-
*
|
|
14534
|
-
* @
|
|
14535
|
-
*
|
|
14536
|
-
* @
|
|
14537
|
-
*
|
|
14538
|
-
*
|
|
14569
|
+
* @param request - Sort pair to compute preorder degree for, and optionally
|
|
14570
|
+
* which of the two preorders to read it from.
|
|
14571
|
+
* @returns The preorder degree response including sort IDs, degree, and the
|
|
14572
|
+
* granularity the degree was read from.
|
|
14573
|
+
* @throws {@link ApiError} If the sorts do not exist, or if `granularity`
|
|
14574
|
+
* carries a spelling the engine does not accept.
|
|
14575
|
+
* @throws {@link ValidationError} If the engine answers a granularity this
|
|
14576
|
+
* SDK version does not know.
|
|
14577
|
+
*
|
|
14578
|
+
* @remarks
|
|
14579
|
+
* Per Definition IV.5 (Milanese and Pasi, IEEE TFS 2024), the dotted preorder
|
|
14580
|
+
* is `preorder_dot = ((combined_preorder .- similarity) union subsumption)^+`,
|
|
14581
|
+
* where `.-` DELETES each directly-similar pair — it is NOT an arithmetic
|
|
14582
|
+
* difference. So a directly-similar pair answers `0` under the default
|
|
14583
|
+
* granularity: two similar sorts meet through their GLB, not through each
|
|
14584
|
+
* other.
|
|
14585
|
+
*
|
|
14586
|
+
* `granularity` selects the reading, with the same two spellings
|
|
14587
|
+
* `GET /api/v1/sorts/quotient-order` uses:
|
|
14588
|
+
* - omitted or `similarity_deleted` — Definition IV.5, the default, and the
|
|
14589
|
+
* relation the graded GLB and term substitutability are computed from.
|
|
14590
|
+
* - `combined` — Definition IV.1, where a similarity edge IS a step, so a
|
|
14591
|
+
* directly-similar pair answers its similarity degree.
|
|
14592
|
+
*
|
|
14593
|
+
* The response always echoes the granularity back, so a `0.0` is never
|
|
14594
|
+
* ambiguous between "no path" and "the pair deletion zeroed it".
|
|
14539
14595
|
*
|
|
14540
14596
|
* Degree interpretation:
|
|
14541
14597
|
* - 1.0 = subsumption (sort1 <= sort2)
|
|
@@ -14546,17 +14602,78 @@ var SortsClient = class {
|
|
|
14546
14602
|
*
|
|
14547
14603
|
* @example
|
|
14548
14604
|
* ```typescript
|
|
14549
|
-
* const
|
|
14605
|
+
* const strict = await client.sorts.getPreorderDegree({
|
|
14606
|
+
* sort1Id: 'uuid-1',
|
|
14607
|
+
* sort2Id: 'uuid-2',
|
|
14608
|
+
* });
|
|
14609
|
+
* console.log(strict.degree, strict.granularity); // 0 'similarity_deleted'
|
|
14610
|
+
*
|
|
14611
|
+
* const coarse = await client.sorts.getPreorderDegree({
|
|
14550
14612
|
* sort1Id: 'uuid-1',
|
|
14551
14613
|
* sort2Id: 'uuid-2',
|
|
14614
|
+
* granularity: 'combined',
|
|
14552
14615
|
* });
|
|
14553
|
-
* console.log(
|
|
14616
|
+
* console.log(coarse.degree, coarse.granularity); // 0.5 'combined'
|
|
14554
14617
|
* ```
|
|
14555
14618
|
*/
|
|
14556
14619
|
async getPreorderDegree(request, requestOptions) {
|
|
14557
14620
|
const response = await this.sorts.getPreorderDegree(GetPreorderDegreeRequestFromFrontToApi(request), toRequestParams(requestOptions));
|
|
14558
14621
|
return GetPreorderDegreeResponseFromApiToFront(response.data);
|
|
14559
14622
|
}
|
|
14623
|
+
/**
|
|
14624
|
+
* Get the Definition IV.9 quotient order over the caller's own lattice.
|
|
14625
|
+
*
|
|
14626
|
+
* @param options - Which of the two fuzzy preorders to quotient. Omitted
|
|
14627
|
+
* means `combined`, the engine's default HERE.
|
|
14628
|
+
* @returns The equivalence classes with their degrees, and the fuzzy partial
|
|
14629
|
+
* order between them.
|
|
14630
|
+
* @throws {@link ApiError} 400 when `granularity` carries a spelling the
|
|
14631
|
+
* engine does not accept.
|
|
14632
|
+
* @throws {@link ValidationError} If the engine answers a granularity this
|
|
14633
|
+
* SDK version does not know.
|
|
14634
|
+
*
|
|
14635
|
+
* @remarks
|
|
14636
|
+
* This is the tenant-scoped companion of
|
|
14637
|
+
* {@link SortsClient.getEquivalenceClasses}: the classes, degrees and order
|
|
14638
|
+
* describe exactly the sorts the caller can see, where the older
|
|
14639
|
+
* equivalence-classes route computes process-wide and then filters. Prefer
|
|
14640
|
+
* this one.
|
|
14641
|
+
*
|
|
14642
|
+
* ⚠️ The default granularity here is `combined`, NOT the
|
|
14643
|
+
* `similarity_deleted` default of {@link SortsClient.getPreorderDegree}. The
|
|
14644
|
+
* two routes take the same two spellings and disagree on which is the
|
|
14645
|
+
* default, so state it when it matters. The response echoes it back either
|
|
14646
|
+
* way.
|
|
14647
|
+
*
|
|
14648
|
+
* `orderEdges` is SPARSE and indexes into `classes`: a pair with no edge has
|
|
14649
|
+
* degree `0`. The order is a partial order — antisymmetric, unlike either
|
|
14650
|
+
* preorder it is built from.
|
|
14651
|
+
*
|
|
14652
|
+
* Uses tagged serialization format.
|
|
14653
|
+
*
|
|
14654
|
+
* @example
|
|
14655
|
+
* ```typescript
|
|
14656
|
+
* const quotient = await client.sorts.getQuotientOrder({
|
|
14657
|
+
* granularity: 'similarity_deleted',
|
|
14658
|
+
* });
|
|
14659
|
+
*
|
|
14660
|
+
* for (const cls of quotient.classes) {
|
|
14661
|
+
* console.log(`class of ${cls.size} sorts, degree ${cls.alpha}`);
|
|
14662
|
+
* }
|
|
14663
|
+
* for (const edge of quotient.orderEdges) {
|
|
14664
|
+
* const lower = quotient.classes[edge.from];
|
|
14665
|
+
* const upper = quotient.classes[edge.to];
|
|
14666
|
+
* console.log(`${lower.sortIds} <= ${upper.sortIds} at ${edge.degree}`);
|
|
14667
|
+
* }
|
|
14668
|
+
* ```
|
|
14669
|
+
*/
|
|
14670
|
+
async getQuotientOrder(options, requestOptions) {
|
|
14671
|
+
const response = await this.sorts.getQuotientOrder(
|
|
14672
|
+
{ granularity: options?.granularity },
|
|
14673
|
+
toRequestParams(requestOptions)
|
|
14674
|
+
);
|
|
14675
|
+
return GetQuotientOrderResponseFromApiToFront(response.data);
|
|
14676
|
+
}
|
|
14560
14677
|
/**
|
|
14561
14678
|
* Get equivalence classes based on the combined preorder.
|
|
14562
14679
|
*
|
|
@@ -14564,8 +14681,16 @@ var SortsClient = class {
|
|
|
14564
14681
|
* @throws {@link ApiError} If the lattice cannot be computed.
|
|
14565
14682
|
*
|
|
14566
14683
|
* @remarks
|
|
14567
|
-
* Per Definition IV.9 (Milanese and Pasi 2024)
|
|
14568
|
-
* s1 ~ s2 iff
|
|
14684
|
+
* Per Definition IV.9 (Milanese and Pasi 2024), two sorts are equivalent when
|
|
14685
|
+
* each reaches the other: `s1 ~ s2` iff `preorder(s1, s2) > 0` AND
|
|
14686
|
+
* `preorder(s2, s1) > 0`. The preorder here is the COMBINED one, where a
|
|
14687
|
+
* similarity edge is itself a step — not the `similarity_deleted` default of
|
|
14688
|
+
* {@link SortsClient.getPreorderDegree}.
|
|
14689
|
+
*
|
|
14690
|
+
* ⚠️ This route computes PROCESS-WIDE and then filters, so its classes can
|
|
14691
|
+
* be shaped by sorts the caller cannot see. {@link SortsClient.getQuotientOrder}
|
|
14692
|
+
* computes on the tenant-visible hierarchy instead, returns the same classes
|
|
14693
|
+
* with their degrees, and adds the partial order between them. Prefer it.
|
|
14569
14694
|
*
|
|
14570
14695
|
* Uses tagged serialization format.
|
|
14571
14696
|
*
|
|
@@ -15746,31 +15871,42 @@ function convertFeatures(features) {
|
|
|
15746
15871
|
}
|
|
15747
15872
|
|
|
15748
15873
|
// src/normalizers/homoiconic.ts
|
|
15749
|
-
function
|
|
15874
|
+
function assertPresent(value, what) {
|
|
15875
|
+
if (value === null || value === void 0) {
|
|
15876
|
+
throw new ValidationError(
|
|
15877
|
+
`${what} is required \u2014 received ${value === null ? "null" : "undefined"}.`,
|
|
15878
|
+
what
|
|
15879
|
+
);
|
|
15880
|
+
}
|
|
15881
|
+
}
|
|
15882
|
+
function FeatureInputValueDtoFromFrontToApi(value, path = "feature value") {
|
|
15883
|
+
assertPresent(value, path);
|
|
15750
15884
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
15751
15885
|
return value;
|
|
15752
15886
|
}
|
|
15753
15887
|
if (Array.isArray(value)) {
|
|
15754
|
-
return value.map(
|
|
15888
|
+
return value.map(
|
|
15889
|
+
(element, index) => FeatureInputValueDtoFromFrontToApi(element, `${path}[${index}]`)
|
|
15890
|
+
);
|
|
15755
15891
|
}
|
|
15756
15892
|
if ("name" in value && "constraint" in value) {
|
|
15757
15893
|
return {
|
|
15758
15894
|
name: value.name,
|
|
15759
|
-
constraint: TermInputDtoFromFrontToApi(value.constraint)
|
|
15895
|
+
constraint: TermInputDtoFromFrontToApi(value.constraint, `${path}.constraint`)
|
|
15760
15896
|
};
|
|
15761
15897
|
}
|
|
15762
15898
|
if ("name" in value) {
|
|
15763
15899
|
return { name: value.name };
|
|
15764
15900
|
}
|
|
15765
15901
|
if ("sortId" in value) {
|
|
15766
|
-
const features = value.features ? featuresInputFromFrontToApi(value.features) : void 0;
|
|
15902
|
+
const features = value.features ? featuresInputFromFrontToApi(value.features, `${path}.features`) : void 0;
|
|
15767
15903
|
return {
|
|
15768
15904
|
sort_id: value.sortId,
|
|
15769
15905
|
...features ? { features } : {}
|
|
15770
15906
|
};
|
|
15771
15907
|
}
|
|
15772
15908
|
if ("sortName" in value) {
|
|
15773
|
-
const features = value.features ? featuresInputFromFrontToApi(value.features) : void 0;
|
|
15909
|
+
const features = value.features ? featuresInputFromFrontToApi(value.features, `${path}.features`) : void 0;
|
|
15774
15910
|
return {
|
|
15775
15911
|
sort_name: value.sortName,
|
|
15776
15912
|
...features ? { features } : {}
|
|
@@ -15781,14 +15917,15 @@ function FeatureInputValueDtoFromFrontToApi(value) {
|
|
|
15781
15917
|
}
|
|
15782
15918
|
return { term_id: value.termId };
|
|
15783
15919
|
}
|
|
15784
|
-
function featuresInputFromFrontToApi(features) {
|
|
15920
|
+
function featuresInputFromFrontToApi(features, path = "features") {
|
|
15785
15921
|
const result = {};
|
|
15786
15922
|
for (const [key, val] of Object.entries(features)) {
|
|
15787
|
-
result[key] = FeatureInputValueDtoFromFrontToApi(val);
|
|
15923
|
+
result[key] = FeatureInputValueDtoFromFrontToApi(val, `${path}.${key}`);
|
|
15788
15924
|
}
|
|
15789
15925
|
return result;
|
|
15790
15926
|
}
|
|
15791
|
-
function TermInputDtoFromFrontToApi(model) {
|
|
15927
|
+
function TermInputDtoFromFrontToApi(model, path = "term") {
|
|
15928
|
+
assertPresent(model, path);
|
|
15792
15929
|
if ("termId" in model) {
|
|
15793
15930
|
return { term_id: model.termId };
|
|
15794
15931
|
}
|
|
@@ -15803,14 +15940,14 @@ function TermInputDtoFromFrontToApi(model) {
|
|
|
15803
15940
|
if ("sortId" in model) {
|
|
15804
15941
|
const inline = {
|
|
15805
15942
|
sort_id: model.sortId,
|
|
15806
|
-
features: featuresInputFromFrontToApi(model.features)
|
|
15943
|
+
features: featuresInputFromFrontToApi(model.features, `${path}.features`)
|
|
15807
15944
|
};
|
|
15808
15945
|
if (model.binding !== void 0) inline.binding = model.binding;
|
|
15809
15946
|
return inline;
|
|
15810
15947
|
}
|
|
15811
15948
|
const byName = {
|
|
15812
15949
|
sort_name: model.sortName,
|
|
15813
|
-
features: model.features ? featuresInputFromFrontToApi(model.features) : void 0
|
|
15950
|
+
features: model.features ? featuresInputFromFrontToApi(model.features, `${path}.features`) : void 0
|
|
15814
15951
|
};
|
|
15815
15952
|
if (model.binding !== void 0) byName.binding = model.binding;
|
|
15816
15953
|
return byName;
|
|
@@ -15872,6 +16009,7 @@ function ProofDtoFromApiToFront(dto) {
|
|
|
15872
16009
|
kind: dto.kind,
|
|
15873
16010
|
goalTermId: dto.goal_term_id,
|
|
15874
16011
|
ruleTermId: dto.rule_term_id,
|
|
16012
|
+
ruleHeadTermId: dto.rule_head_term_id,
|
|
15875
16013
|
goalDisplay: dto.goal_display,
|
|
15876
16014
|
ruleLabel: dto.rule_label,
|
|
15877
16015
|
substitution: HomoiconicSubstitutionDtoFromApiToFront(dto.substitution),
|
|
@@ -16371,7 +16509,9 @@ function RuleAggregatorDtoFromFrontToApi(model) {
|
|
|
16371
16509
|
function AddRuleRequestFromFrontToApi(model) {
|
|
16372
16510
|
return {
|
|
16373
16511
|
term: TermInputDtoFromFrontToApi(model.term),
|
|
16374
|
-
antecedents: model.antecedents?.map(
|
|
16512
|
+
antecedents: model.antecedents?.map(
|
|
16513
|
+
(t, i) => TermInputDtoFromFrontToApi(t, `antecedents[${i}]`)
|
|
16514
|
+
),
|
|
16375
16515
|
certainty: model.certainty,
|
|
16376
16516
|
aggregator: model.aggregator ? RuleAggregatorDtoFromFrontToApi(model.aggregator) : model.aggregator
|
|
16377
16517
|
};
|
|
@@ -16388,7 +16528,7 @@ function BulkAddRulesRequestFromFrontToApi(model) {
|
|
|
16388
16528
|
}
|
|
16389
16529
|
function BulkAddFactsRequestFromFrontToApi(model) {
|
|
16390
16530
|
return {
|
|
16391
|
-
facts: model.facts.map(TermInputDtoFromFrontToApi)
|
|
16531
|
+
facts: model.facts.map((t, i) => TermInputDtoFromFrontToApi(t, `facts[${i}]`))
|
|
16392
16532
|
};
|
|
16393
16533
|
}
|
|
16394
16534
|
function BackwardChainRequestFromFrontToApi(model) {
|
|
@@ -16406,12 +16546,15 @@ function BackwardChainRequestFromFrontToApi(model) {
|
|
|
16406
16546
|
}
|
|
16407
16547
|
function ForwardChainRequestFromFrontToApi(model) {
|
|
16408
16548
|
return {
|
|
16409
|
-
initial_facts: model.initialFacts?.map(
|
|
16549
|
+
initial_facts: model.initialFacts?.map(
|
|
16550
|
+
(t, i) => TermInputDtoFromFrontToApi(t, `initialFacts[${i}]`)
|
|
16551
|
+
),
|
|
16410
16552
|
keep_derived: model.keepDerived,
|
|
16411
16553
|
enable_provenance_tags: model.enableProvenanceTags,
|
|
16412
16554
|
max_iterations: model.maxIterations,
|
|
16413
16555
|
max_facts: model.maxFacts,
|
|
16414
|
-
emit_provenance: model.emitProvenance
|
|
16556
|
+
emit_provenance: model.emitProvenance,
|
|
16557
|
+
timeout_ms: model.timeoutMs ?? void 0
|
|
16415
16558
|
};
|
|
16416
16559
|
}
|
|
16417
16560
|
function FuzzyProveRequestFromFrontToApi(model) {
|
|
@@ -16428,7 +16571,7 @@ function FuzzyProveRequestFromFrontToApi(model) {
|
|
|
16428
16571
|
}
|
|
16429
16572
|
function BulkFuzzyProveRequestFromFrontToApi(model) {
|
|
16430
16573
|
return {
|
|
16431
|
-
goals: model.goals?.map(TermInputDtoFromFrontToApi),
|
|
16574
|
+
goals: model.goals?.map((t, i) => TermInputDtoFromFrontToApi(t, `goals[${i}]`)),
|
|
16432
16575
|
goal_ids: model.goalIds ?? void 0,
|
|
16433
16576
|
max_depth: model.maxDepth,
|
|
16434
16577
|
min_degree: model.minDegree,
|
|
@@ -16451,7 +16594,7 @@ function BayesianPredictRequestFromFrontToApi(model) {
|
|
|
16451
16594
|
}
|
|
16452
16595
|
function CreateGoalRequestFromFrontToApi(model) {
|
|
16453
16596
|
return {
|
|
16454
|
-
clauses: model.clauses.map(TermInputDtoFromFrontToApi),
|
|
16597
|
+
clauses: model.clauses.map((t, i) => TermInputDtoFromFrontToApi(t, `clauses[${i}]`)),
|
|
16455
16598
|
constraints: model.constraints?.map(ConstraintInputDtoFromFrontToApi),
|
|
16456
16599
|
min_degree: model.minDegree ?? void 0
|
|
16457
16600
|
};
|
|
@@ -16751,6 +16894,14 @@ var InferenceClient = class {
|
|
|
16751
16894
|
*
|
|
16752
16895
|
* The `timeout_ms` field on the request is a wall-clock timeout for the search.
|
|
16753
16896
|
* When it fires, the backend returns whatever solutions have been found so far.
|
|
16897
|
+
*
|
|
16898
|
+
* To join a proof node to the thing it proves, read `proof.goalTermId` — the
|
|
16899
|
+
* conclusion's term ID, which `client.terms.getTerm()` and
|
|
16900
|
+
* `client.query.findBySort()` both answer for. It is OPTIONAL: a goal proved
|
|
16901
|
+
* without a preceding forward chain materialises no conclusion, so the node
|
|
16902
|
+
* carries no id and `proof.goalDisplay` renders it instead. Do not read
|
|
16903
|
+
* `proof.ruleHeadTermId` as a fetchable id — it names the rule's instantiated
|
|
16904
|
+
* head, which the term routes refuse.
|
|
16754
16905
|
*/
|
|
16755
16906
|
async backwardChain(request, requestOptions) {
|
|
16756
16907
|
const wireRequest = {
|
|
@@ -16854,13 +17005,37 @@ var InferenceClient = class {
|
|
|
16854
17005
|
/**
|
|
16855
17006
|
* Run negation-as-failure (NAF) proof search.
|
|
16856
17007
|
*
|
|
16857
|
-
* @param request - NAF prove request.
|
|
17008
|
+
* @param request - NAF prove request. Each literal's `term` takes a
|
|
17009
|
+
* {@link psi} term or a wire {@link TermInputDto}, like every other
|
|
17010
|
+
* term-carrying method.
|
|
16858
17011
|
* @returns NAF proof result.
|
|
16859
17012
|
*
|
|
17013
|
+
* @remarks
|
|
17014
|
+
* Uses the untagged (homoiconic) serialization format: a literal's features
|
|
17015
|
+
* are plain scalars and `"?Var"` strings.
|
|
17016
|
+
*
|
|
17017
|
+
* @example
|
|
17018
|
+
* ```typescript
|
|
17019
|
+
* const result = await client.inference.nafProve({
|
|
17020
|
+
* literals: [
|
|
17021
|
+
* { term: psi('employee', { name: '?Name' }) },
|
|
17022
|
+
* { term: psi('senior_engineer', { name: '?Name' }), negated: true },
|
|
17023
|
+
* ],
|
|
17024
|
+
* maxSolutions: 10,
|
|
17025
|
+
* });
|
|
17026
|
+
* ```
|
|
17027
|
+
*
|
|
16860
17028
|
* @see proveWithNegation — friendlier alias for this method.
|
|
16861
17029
|
*/
|
|
16862
17030
|
async nafProve(request, requestOptions) {
|
|
16863
|
-
const
|
|
17031
|
+
const wireRequest = {
|
|
17032
|
+
...request,
|
|
17033
|
+
literals: request.literals?.map((literal) => ({
|
|
17034
|
+
...literal,
|
|
17035
|
+
term: convertTermArg(literal.term)
|
|
17036
|
+
}))
|
|
17037
|
+
};
|
|
17038
|
+
const response = await this.api.nafProve(NafProveRequestFromFrontToApi(wireRequest), toRequestParams(requestOptions));
|
|
16864
17039
|
return NafProveResponseFromApiToFront(response.data);
|
|
16865
17040
|
}
|
|
16866
17041
|
/**
|
|
@@ -23787,7 +23962,7 @@ function EntailmentRequestFromFrontToApi(model) {
|
|
|
23787
23962
|
return {
|
|
23788
23963
|
antecedent: TermInputDtoFromFrontToApi(model.antecedent),
|
|
23789
23964
|
consequent: TermInputDtoFromFrontToApi(model.consequent),
|
|
23790
|
-
facts: model.facts?.map(TermInputDtoFromFrontToApi)
|
|
23965
|
+
facts: model.facts?.map((t, i) => TermInputDtoFromFrontToApi(t, `facts[${i}]`))
|
|
23791
23966
|
};
|
|
23792
23967
|
}
|
|
23793
23968
|
function EntailmentResponseFromApiToFront(dto) {
|
|
@@ -23801,7 +23976,7 @@ function DisentailmentRequestFromFrontToApi(model) {
|
|
|
23801
23976
|
return {
|
|
23802
23977
|
antecedent: TermInputDtoFromFrontToApi(model.antecedent),
|
|
23803
23978
|
consequent: TermInputDtoFromFrontToApi(model.consequent),
|
|
23804
|
-
facts: model.facts?.map(TermInputDtoFromFrontToApi)
|
|
23979
|
+
facts: model.facts?.map((t, i) => TermInputDtoFromFrontToApi(t, `facts[${i}]`))
|
|
23805
23980
|
};
|
|
23806
23981
|
}
|
|
23807
23982
|
function DisentailmentResponseFromApiToFront(dto) {
|
|
@@ -25392,12 +25567,25 @@ function SourceDetailResponseFromApiToFront(dto) {
|
|
|
25392
25567
|
supportedModes: dto.supported_modes
|
|
25393
25568
|
};
|
|
25394
25569
|
}
|
|
25570
|
+
function ConfigFieldDtoFromApiToFront(dto) {
|
|
25571
|
+
return {
|
|
25572
|
+
// `name` is the factory's own JSON key and goes back on the wire
|
|
25573
|
+
// verbatim — never camelCased, in either direction (#14).
|
|
25574
|
+
name: dto.name,
|
|
25575
|
+
type: dto.type,
|
|
25576
|
+
required: dto.required
|
|
25577
|
+
};
|
|
25578
|
+
}
|
|
25395
25579
|
function SourceTypeDtoFromApiToFront(dto) {
|
|
25396
25580
|
return {
|
|
25397
25581
|
sourceType: dto.source_type,
|
|
25398
25582
|
aliases: dto.aliases,
|
|
25399
25583
|
available: dto.available,
|
|
25400
|
-
supportedModes: dto.supported_modes
|
|
25584
|
+
supportedModes: dto.supported_modes,
|
|
25585
|
+
// Defaulted rather than left absent: the field is required on the current
|
|
25586
|
+
// engine, and an empty list reads correctly on an older one — a form built
|
|
25587
|
+
// from no fields is visibly empty, where an absent list is a crash.
|
|
25588
|
+
configFields: (dto.config_fields ?? []).map(ConfigFieldDtoFromApiToFront)
|
|
25401
25589
|
};
|
|
25402
25590
|
}
|
|
25403
25591
|
function ListSourceTypesResponseFromApiToFront(dto) {
|
|
@@ -25417,6 +25605,7 @@ function DiscoverableTypeDtoFromApiToFront(dto) {
|
|
|
25417
25605
|
return {
|
|
25418
25606
|
comment: dto.comment,
|
|
25419
25607
|
estimatedRows: dto.estimated_rows,
|
|
25608
|
+
columnCount: dto.column_count,
|
|
25420
25609
|
name: dto.name
|
|
25421
25610
|
};
|
|
25422
25611
|
}
|
|
@@ -25427,6 +25616,15 @@ function ListTablesResponseFromApiToFront(dto) {
|
|
|
25427
25616
|
total: dto.total
|
|
25428
25617
|
};
|
|
25429
25618
|
}
|
|
25619
|
+
function KeyProvenanceDtoFromApiToFront(dto) {
|
|
25620
|
+
return {
|
|
25621
|
+
source: dto.source,
|
|
25622
|
+
chosenBy: dto.chosen_by,
|
|
25623
|
+
explanation: dto.explanation,
|
|
25624
|
+
guaranteedUnique: dto.guaranteed_unique,
|
|
25625
|
+
durability: dto.durability
|
|
25626
|
+
};
|
|
25627
|
+
}
|
|
25430
25628
|
function DiscoveredFeatureDtoFromApiToFront(dto) {
|
|
25431
25629
|
return {
|
|
25432
25630
|
constraints: dto.constraints,
|
|
@@ -25434,10 +25632,16 @@ function DiscoveredFeatureDtoFromApiToFront(dto) {
|
|
|
25434
25632
|
isIdentifier: dto.is_identifier,
|
|
25435
25633
|
isRelation: dto.is_relation,
|
|
25436
25634
|
name: dto.name,
|
|
25635
|
+
// The engine's own OSFQL-readable spelling. Defaulted to `name`, which it
|
|
25636
|
+
// is identical to, so an older engine that predates it stays usable.
|
|
25637
|
+
featureName: dto.feature_name ?? dto.name,
|
|
25437
25638
|
relationTarget: dto.relation_target,
|
|
25438
25639
|
required: dto.required,
|
|
25439
25640
|
sourceName: dto.source_name,
|
|
25440
|
-
typeHint: dto.type_hint
|
|
25641
|
+
typeHint: dto.type_hint,
|
|
25642
|
+
// The difference between a declared primary key and a guess. Carried
|
|
25643
|
+
// through so a mapping wizard can present the guess as a guess (#14).
|
|
25644
|
+
identifierProvenance: dto.identifier_provenance ? KeyProvenanceDtoFromApiToFront(dto.identifier_provenance) : dto.identifier_provenance
|
|
25441
25645
|
};
|
|
25442
25646
|
}
|
|
25443
25647
|
function DiscoveredSortDtoFromApiToFront(dto) {
|
|
@@ -31287,7 +31491,9 @@ var OptimizeClient = class {
|
|
|
31287
31491
|
}
|
|
31288
31492
|
const ruleResponse = await this.inferenceApi.addRule({
|
|
31289
31493
|
term: TermInputDtoFromFrontToApi(compiled.solutionTerm),
|
|
31290
|
-
antecedents: compiled.antecedents.map(
|
|
31494
|
+
antecedents: compiled.antecedents.map(
|
|
31495
|
+
(t, i) => TermInputDtoFromFrontToApi(t, `antecedents[${i}]`)
|
|
31496
|
+
),
|
|
31291
31497
|
certainty: 1
|
|
31292
31498
|
}, toRequestParams(requestOptions));
|
|
31293
31499
|
ruleTermId = extractRuleTermId(ruleResponse.data);
|
|
@@ -31966,6 +32172,7 @@ function OsfqlResponseFromApiToFront(dto) {
|
|
|
31966
32172
|
bindings,
|
|
31967
32173
|
fetched,
|
|
31968
32174
|
producedTermIds: dto.produced_term_ids,
|
|
32175
|
+
updatedTermIds: dto.updated_term_ids,
|
|
31969
32176
|
definedSortIds: dto.defined_sort_ids,
|
|
31970
32177
|
diagnostics: dto.diagnostics,
|
|
31971
32178
|
statementCount: dto.statement_count
|
|
@@ -32037,11 +32244,25 @@ function OsfqlPreviewAffectedFromApiToFront(dto) {
|
|
|
32037
32244
|
affected.exact = dto.exact;
|
|
32038
32245
|
}
|
|
32039
32246
|
if (dto.sample_rows !== void 0) {
|
|
32040
|
-
const rows =
|
|
32041
|
-
|
|
32042
|
-
|
|
32247
|
+
const rows = [];
|
|
32248
|
+
let unparsed = 0;
|
|
32249
|
+
const wireRows = dto.sample_rows;
|
|
32250
|
+
if (Array.isArray(wireRows)) {
|
|
32251
|
+
for (const row of wireRows) {
|
|
32252
|
+
const parsed = OsfqlBindingFromApiToFront(row);
|
|
32253
|
+
if (parsed === void 0) {
|
|
32254
|
+
unparsed += 1;
|
|
32255
|
+
} else {
|
|
32256
|
+
rows.push(parsed);
|
|
32257
|
+
}
|
|
32258
|
+
}
|
|
32259
|
+
} else {
|
|
32260
|
+
unparsed = 1;
|
|
32043
32261
|
}
|
|
32044
32262
|
affected.sampleRows = rows;
|
|
32263
|
+
if (unparsed > 0) {
|
|
32264
|
+
affected.unparsedSampleRows = unparsed;
|
|
32265
|
+
}
|
|
32045
32266
|
}
|
|
32046
32267
|
if (dto.by_sort !== void 0) {
|
|
32047
32268
|
affected.bySort = dto.by_sort.map(OsfqlPreviewSortCountFromApiToFront);
|
|
@@ -32062,34 +32283,15 @@ function OsfqlPreviewStatementFromApiToFront(dto) {
|
|
|
32062
32283
|
source: dto.source
|
|
32063
32284
|
};
|
|
32064
32285
|
if (dto.affected !== void 0) {
|
|
32065
|
-
|
|
32066
|
-
if (affected === void 0) {
|
|
32067
|
-
return void 0;
|
|
32068
|
-
}
|
|
32069
|
-
statement.affected = affected;
|
|
32286
|
+
statement.affected = OsfqlPreviewAffectedFromApiToFront(dto.affected);
|
|
32070
32287
|
}
|
|
32071
32288
|
if (dto.nested !== void 0) {
|
|
32072
|
-
|
|
32073
|
-
for (const child of dto.nested) {
|
|
32074
|
-
const parsed = OsfqlPreviewStatementFromApiToFront(child);
|
|
32075
|
-
if (parsed === void 0) {
|
|
32076
|
-
return void 0;
|
|
32077
|
-
}
|
|
32078
|
-
nested.push(parsed);
|
|
32079
|
-
}
|
|
32080
|
-
statement.nested = nested;
|
|
32289
|
+
statement.nested = dto.nested.map(OsfqlPreviewStatementFromApiToFront);
|
|
32081
32290
|
}
|
|
32082
32291
|
return statement;
|
|
32083
32292
|
}
|
|
32084
32293
|
function OsfqlPreviewResponseFromApiToFront(dto) {
|
|
32085
|
-
const statements =
|
|
32086
|
-
for (const entry of dto.statements) {
|
|
32087
|
-
const parsed = OsfqlPreviewStatementFromApiToFront(entry);
|
|
32088
|
-
if (parsed === void 0) {
|
|
32089
|
-
return void 0;
|
|
32090
|
-
}
|
|
32091
|
-
statements.push(parsed);
|
|
32092
|
-
}
|
|
32294
|
+
const statements = dto.statements.map(OsfqlPreviewStatementFromApiToFront);
|
|
32093
32295
|
const response = { mutates: dto.mutates, statements };
|
|
32094
32296
|
if (dto.atomic_refusal !== void 0) {
|
|
32095
32297
|
response.atomicRefusal = dto.atomic_refusal ? OsfqlAtomicRefusalFromApiToFront(dto.atomic_refusal) : dto.atomic_refusal;
|
|
@@ -32185,8 +32387,6 @@ var OsfqlClient = class {
|
|
|
32185
32387
|
* atomic refusal when there is one.
|
|
32186
32388
|
* @throws {ApiError} If the program does not parse (HTTP 400, `OsfqlErrorResponse`),
|
|
32187
32389
|
* or the request otherwise fails.
|
|
32188
|
-
* @throws {ReasoningLayerError} If a sample row carries a value that does not satisfy
|
|
32189
|
-
* the published {@link OsfqlValue} contract.
|
|
32190
32390
|
*
|
|
32191
32391
|
* @remarks
|
|
32192
32392
|
* **Why call this instead of classifying the program client-side.** Three
|
|
@@ -32221,9 +32421,16 @@ var OsfqlClient = class {
|
|
|
32221
32421
|
* Two further measured facts. The top-level `mutates` DOES fold nested
|
|
32222
32422
|
* statements now: the `IF` program above answers `true`, and so does an `IF`
|
|
32223
32423
|
* whose only writing branch is the `ELSE` — the earlier defect where an `IF`
|
|
32224
|
-
* with a writing branch answered `false` is fixed. And `affected`
|
|
32225
|
-
*
|
|
32226
|
-
*
|
|
32424
|
+
* with a writing branch answered `false` is fixed. And `affected` is NOT
|
|
32425
|
+
* ambiguous: a destructive statement that matches zero rows answers
|
|
32426
|
+
* `{count: 0, exact: true}` rather than omitting the block. Measured
|
|
32427
|
+
* 2026-09-21 — `preview('RETRACT widget(name: "nobody");')` against an empty
|
|
32428
|
+
* `widget` answers `affected: {"count":0,"exact":true}`, while
|
|
32429
|
+
* `preview('MATCH widget(name: ?N);')` carries no `affected` key at all. So
|
|
32430
|
+
* an ABSENT block means the statement has no affected-row set; `count: 0`
|
|
32431
|
+
* means the rows were counted and there are none. A confirm dialog can tell
|
|
32432
|
+
* the two apart, which is what the block was separated for. See
|
|
32433
|
+
* {@link OsfqlPreviewAffected.count}.
|
|
32227
32434
|
*
|
|
32228
32435
|
* `statement.index` is a single counter over the whole program: an `IF` at
|
|
32229
32436
|
* index 1 carries nested entries at index 2 and 3.
|
|
@@ -32264,13 +32471,7 @@ var OsfqlClient = class {
|
|
|
32264
32471
|
OsfqlRequestFromFrontToApi({ ...options, query }),
|
|
32265
32472
|
toRequestParams(requestOptions)
|
|
32266
32473
|
);
|
|
32267
|
-
|
|
32268
|
-
if (parsed === void 0) {
|
|
32269
|
-
throw new ReasoningLayerError(
|
|
32270
|
-
"osfql/preview returned an affected sample row that does not match the published OsfqlValue contract (expected tagged values with a lowercase `type` discriminator)"
|
|
32271
|
-
);
|
|
32272
|
-
}
|
|
32273
|
-
return parsed;
|
|
32474
|
+
return OsfqlPreviewResponseFromApiToFront(response.data);
|
|
32274
32475
|
}
|
|
32275
32476
|
/**
|
|
32276
32477
|
* Diagnose an OSFQL program for contradictions and inconsistencies.
|
|
@@ -34203,6 +34404,27 @@ function AuditPageFromApiToFront(dto) {
|
|
|
34203
34404
|
offset: dto.offset
|
|
34204
34405
|
};
|
|
34205
34406
|
}
|
|
34407
|
+
function RiskTotalsDtoFromApiToFront(dto) {
|
|
34408
|
+
return {
|
|
34409
|
+
nSafe: dto.n_safe,
|
|
34410
|
+
nWarning: dto.n_warning,
|
|
34411
|
+
nUnsafe: dto.n_unsafe,
|
|
34412
|
+
nUngraded: dto.n_ungraded,
|
|
34413
|
+
nGradedByVerification: dto.n_graded_by_verification,
|
|
34414
|
+
nVerified: dto.n_verified,
|
|
34415
|
+
nRefuted: dto.n_refuted,
|
|
34416
|
+
nAbstained: dto.n_abstained,
|
|
34417
|
+
nFabricationDetected: dto.n_fabrication_detected,
|
|
34418
|
+
nFabricationClean: dto.n_fabrication_clean,
|
|
34419
|
+
nFabricationUnknown: dto.n_fabrication_unknown,
|
|
34420
|
+
nClaimsTotal: dto.n_claims_total,
|
|
34421
|
+
nClaimsRefuted: dto.n_claims_refuted,
|
|
34422
|
+
// Carried through as `null`, never folded to `0`. `null` is "not
|
|
34423
|
+
// measured" — the denominator is checked responses only — and `0` would
|
|
34424
|
+
// report a clean fabrication rate for a ledger nobody checked (#11).
|
|
34425
|
+
fabricationRate: dto.fabrication_rate
|
|
34426
|
+
};
|
|
34427
|
+
}
|
|
34206
34428
|
function SummaryResponseFromApiToFront(dto) {
|
|
34207
34429
|
const out = {
|
|
34208
34430
|
nRecords: dto.n_records,
|
|
@@ -34212,6 +34434,12 @@ function SummaryResponseFromApiToFront(dto) {
|
|
|
34212
34434
|
};
|
|
34213
34435
|
if (dto.ts_first) out.tsFirst = dto.ts_first;
|
|
34214
34436
|
if (dto.ts_last) out.tsLast = dto.ts_last;
|
|
34437
|
+
if (dto.risk !== void 0 && dto.risk !== null) {
|
|
34438
|
+
out.risk = RiskTotalsDtoFromApiToFront(dto.risk);
|
|
34439
|
+
}
|
|
34440
|
+
if (dto.n_oversight_decisions !== void 0 && dto.n_oversight_decisions !== null) {
|
|
34441
|
+
out.nOversightDecisions = dto.n_oversight_decisions;
|
|
34442
|
+
}
|
|
34215
34443
|
return out;
|
|
34216
34444
|
}
|
|
34217
34445
|
function VerifyResponseFromApiToFront(dto) {
|
|
@@ -36438,6 +36666,23 @@ function ImportOwlResponseFromApiToFront(dto) {
|
|
|
36438
36666
|
sortsCreated: dto.sorts_created
|
|
36439
36667
|
};
|
|
36440
36668
|
}
|
|
36669
|
+
function ExecuteTranspiledRequestFromFrontToApi(model) {
|
|
36670
|
+
return {
|
|
36671
|
+
osfql: model.osfql
|
|
36672
|
+
};
|
|
36673
|
+
}
|
|
36674
|
+
function ExecuteTranspiledResponseFromApiToFront(dto) {
|
|
36675
|
+
return {
|
|
36676
|
+
// `rows` are the source's OWN records; their keys are its column names and
|
|
36677
|
+
// are data, carried verbatim. The generated type erases them to `any[]`,
|
|
36678
|
+
// so the shipped surface narrows them to one object per row (#12).
|
|
36679
|
+
rows: dto.rows,
|
|
36680
|
+
rowCount: dto.row_count,
|
|
36681
|
+
query: dto.query,
|
|
36682
|
+
dialect: dto.dialect,
|
|
36683
|
+
sourceId: dto.source_id
|
|
36684
|
+
};
|
|
36685
|
+
}
|
|
36441
36686
|
function TranspileRequestFromFrontToApi(model) {
|
|
36442
36687
|
return {
|
|
36443
36688
|
dialect: model.dialect,
|
|
@@ -36696,6 +36941,46 @@ var OntologyBridgeClient = class {
|
|
|
36696
36941
|
);
|
|
36697
36942
|
return TranspileResponseFromApiToFront(response.data);
|
|
36698
36943
|
}
|
|
36944
|
+
/**
|
|
36945
|
+
* Transpile an OSFQL query AND run it on the source it is bound to.
|
|
36946
|
+
*
|
|
36947
|
+
* @param request - The OSFQL query. No dialect: the binding names the
|
|
36948
|
+
* source, and the source's type decides the dialect.
|
|
36949
|
+
* @param requestOptions - Per-call request options.
|
|
36950
|
+
* @returns The rows the source returned, the native query that fetched them,
|
|
36951
|
+
* its dialect, and the source id.
|
|
36952
|
+
* @throws {ApiError} If the request fails.
|
|
36953
|
+
*
|
|
36954
|
+
* @remarks
|
|
36955
|
+
* Sent to `POST /api/v1/ontology/query`. The response uses the snake_case
|
|
36956
|
+
* wire format (`row_count`, `source_id`); this client normalizes at the
|
|
36957
|
+
* boundary. `rows` are the source's own records, one object per row, and
|
|
36958
|
+
* their KEYS are the source's column names — data, carried verbatim.
|
|
36959
|
+
*
|
|
36960
|
+
* **This is the second half of {@link OntologyBridgeClient.transpile}, and
|
|
36961
|
+
* for a `transpile`-mode source it is the only route that answers.** Such a
|
|
36962
|
+
* source deliberately ingests nothing: its bound sorts are live views over
|
|
36963
|
+
* the operator's own database, so every KB query over them reports no
|
|
36964
|
+
* results. `transpile` emits the native query and stops; this runs it.
|
|
36965
|
+
*
|
|
36966
|
+
* @example
|
|
36967
|
+
* ```typescript
|
|
36968
|
+
* const result = await client.ontologyBridge.executeTranspiled({
|
|
36969
|
+
* osfql: 'MATCH person(name: ?N);',
|
|
36970
|
+
* });
|
|
36971
|
+
* console.log(result.dialect); // "postgres"
|
|
36972
|
+
* console.log(result.query); // the SQL that ran
|
|
36973
|
+
* console.log(result.rowCount); // 12
|
|
36974
|
+
* for (const row of result.rows) console.log(row['name']);
|
|
36975
|
+
* ```
|
|
36976
|
+
*/
|
|
36977
|
+
async executeTranspiled(request, requestOptions) {
|
|
36978
|
+
const response = await this.api.executeTranspiled(
|
|
36979
|
+
ExecuteTranspiledRequestFromFrontToApi(request),
|
|
36980
|
+
toRequestParams(requestOptions)
|
|
36981
|
+
);
|
|
36982
|
+
return ExecuteTranspiledResponseFromApiToFront(response.data);
|
|
36983
|
+
}
|
|
36699
36984
|
/**
|
|
36700
36985
|
* Remove a sort-table binding.
|
|
36701
36986
|
*
|
|
@@ -38941,12 +39226,46 @@ function ConformanceRequestFromFrontToApi(model) {
|
|
|
38941
39226
|
ontology: model.ontology
|
|
38942
39227
|
};
|
|
38943
39228
|
}
|
|
39229
|
+
function stringAt(source, key) {
|
|
39230
|
+
const value = Reflect.get(source, key);
|
|
39231
|
+
return typeof value === "string" ? value : void 0;
|
|
39232
|
+
}
|
|
39233
|
+
function suggestedFixesAt(source) {
|
|
39234
|
+
const value = Reflect.get(source, "suggested_fixes");
|
|
39235
|
+
if (!Array.isArray(value)) return void 0;
|
|
39236
|
+
const fixes = [];
|
|
39237
|
+
for (const entry of value) {
|
|
39238
|
+
if (typeof entry === "object" && entry !== null && !Array.isArray(entry)) {
|
|
39239
|
+
fixes.push({ ...entry });
|
|
39240
|
+
}
|
|
39241
|
+
}
|
|
39242
|
+
return fixes;
|
|
39243
|
+
}
|
|
39244
|
+
function ConformanceViolationDtoFromApiToFront(dto) {
|
|
39245
|
+
if (typeof dto !== "object" || dto === null) return {};
|
|
39246
|
+
const violation = {};
|
|
39247
|
+
const subject = stringAt(dto, "subject");
|
|
39248
|
+
if (subject !== void 0) violation.subject = subject;
|
|
39249
|
+
const object = stringAt(dto, "object");
|
|
39250
|
+
if (object !== void 0) violation.object = object;
|
|
39251
|
+
const feature = stringAt(dto, "feature");
|
|
39252
|
+
if (feature !== void 0) violation.feature = feature;
|
|
39253
|
+
const subjectSort = stringAt(dto, "subject_sort");
|
|
39254
|
+
if (subjectSort !== void 0) violation.subjectSort = subjectSort;
|
|
39255
|
+
const objectSort = stringAt(dto, "object_sort");
|
|
39256
|
+
if (objectSort !== void 0) violation.objectSort = objectSort;
|
|
39257
|
+
const kind = stringAt(dto, "kind");
|
|
39258
|
+
if (kind !== void 0) violation.kind = kind;
|
|
39259
|
+
const suggestedFixes = suggestedFixesAt(dto);
|
|
39260
|
+
if (suggestedFixes !== void 0) violation.suggestedFixes = suggestedFixes;
|
|
39261
|
+
return violation;
|
|
39262
|
+
}
|
|
38944
39263
|
function ConformanceCheckResponseFromApiToFront(dto) {
|
|
38945
39264
|
return {
|
|
38946
39265
|
conformant: dto.conformant,
|
|
38947
39266
|
totalViolations: dto.total_violations,
|
|
38948
39267
|
byKind: ViolationCountsDtoFromApiToFront(dto.by_kind),
|
|
38949
|
-
violations: dto.violations.map(
|
|
39268
|
+
violations: dto.violations.map(ConformanceViolationDtoFromApiToFront)
|
|
38950
39269
|
};
|
|
38951
39270
|
}
|
|
38952
39271
|
function ConformanceRepairResponseFromApiToFront(dto) {
|
|
@@ -38984,6 +39303,11 @@ var ConformanceClient = class {
|
|
|
38984
39303
|
* The ontology travels as an opaque string in the declared RDF format; no
|
|
38985
39304
|
* value serialization is applied to it.
|
|
38986
39305
|
*
|
|
39306
|
+
* Each violation is a {@link ConformanceViolationDto}, NOT the shared
|
|
39307
|
+
* `ViolationDto`. The two share no key, and the route's OpenAPI slot holds
|
|
39308
|
+
* the wrong one — which is why the fields are narrowed from the wire in the
|
|
39309
|
+
* normalizer and why every one of them is optional (#13).
|
|
39310
|
+
*
|
|
38987
39311
|
* @example
|
|
38988
39312
|
* ```typescript
|
|
38989
39313
|
* const result = await client.conformance.check({
|
|
@@ -38995,7 +39319,8 @@ var ConformanceClient = class {
|
|
|
38995
39319
|
* console.log(result.totalViolations, 'violations');
|
|
38996
39320
|
* console.log(result.byKind.v1Inversion, 'subject/object inversions');
|
|
38997
39321
|
* for (const violation of result.violations) {
|
|
38998
|
-
* console.log(violation.
|
|
39322
|
+
* console.log(violation.kind, violation.subject, violation.feature, violation.object);
|
|
39323
|
+
* console.log(violation.suggestedFixes); // [{ action: 'swap' }]
|
|
38999
39324
|
* }
|
|
39000
39325
|
* }
|
|
39001
39326
|
* ```
|