@kortexya/reasoninglayer 1.16.0 → 1.17.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 CHANGED
@@ -263,4 +263,4 @@ pnpm run docs:build # Build documentation site
263
263
 
264
264
  ## License
265
265
 
266
- MIT
266
+ Proprietary — © Kortexya. All rights reserved. Not for redistribution.
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.16.0";
10
+ var SDK_VERSION = "1.17.0";
11
11
  function resolveConfig(config) {
12
12
  if (!config.baseUrl) {
13
13
  throw new Error("ClientConfig.baseUrl is required");
@@ -587,6 +587,8 @@ var USER_DATA_FIELDS = /* @__PURE__ */ new Set([
587
587
  "per_strategy_taxonomies",
588
588
  "propsOverride",
589
589
  "props_override",
590
+ "referencedTerms",
591
+ "referenced_terms",
590
592
  "roleMinimums",
591
593
  "role_minimums",
592
594
  "scope",
@@ -594,6 +596,8 @@ var USER_DATA_FIELDS = /* @__PURE__ */ new Set([
594
596
  "scores_by_name",
595
597
  "sortNames",
596
598
  "sort_names",
599
+ "toolResults",
600
+ "tool_results",
597
601
  "topK",
598
602
  "top_k",
599
603
  "values"
@@ -996,6 +1000,22 @@ var Sorts = class {
996
1000
  format: "json",
997
1001
  ...params
998
1002
  });
1003
+ /**
1004
+ * No description
1005
+ *
1006
+ * @tags sorts
1007
+ * @name GetFuzzySubsumption
1008
+ * @summary Get the fuzzy subsumption degree `sub ⊑· sup` between two sorts
1009
+ * @request POST:/api/v1/sorts/subsumption/get
1010
+ */
1011
+ getFuzzySubsumption = (data, params = {}) => this.http.request({
1012
+ path: `/api/v1/sorts/subsumption/get`,
1013
+ method: "POST",
1014
+ body: data,
1015
+ type: "application/json" /* Json */,
1016
+ format: "json",
1017
+ ...params
1018
+ });
999
1019
  /**
1000
1020
  * @description Per Definition IV.5 (Milanese & Pasi 2024): ≾̇ = ((≾̃ .− ∼) ⊍ ≤)⁺
1001
1021
  *
@@ -1013,16 +1033,17 @@ var Sorts = class {
1013
1033
  ...params
1014
1034
  });
1015
1035
  /**
1016
- * No description
1036
+ * @description With `?format=osfql` the sort is returned as its commented OSFQL `DEFINE` block (`text/plain`, `ETag` = SHA-256 of the body) instead of the JSON DTO — the single-sort companion of `GET /api/v1/sorts/schema`.
1017
1037
  *
1018
1038
  * @tags sorts
1019
1039
  * @name GetSort
1020
1040
  * @summary Get a sort by ID
1021
1041
  * @request GET:/api/v1/sorts/{id}
1022
1042
  */
1023
- getSort = (id, params = {}) => this.http.request({
1043
+ getSort = (id, query, params = {}) => this.http.request({
1024
1044
  path: `/api/v1/sorts/${id}`,
1025
1045
  method: "GET",
1046
+ query,
1026
1047
  format: "json",
1027
1048
  ...params
1028
1049
  });
@@ -1042,6 +1063,22 @@ var Sorts = class {
1042
1063
  format: "json",
1043
1064
  ...params
1044
1065
  });
1066
+ /**
1067
+ * @description The bulk companion of `?format=osfql` on the by-id route: a single deterministic, re-parseable `text/plain` block of commented `DEFINE` statements (one per sort, ordered by name) for LLM prompt conditioning and replayable export. Supports the tenant listing's filters (`name_prefix`, `include_system`, `needs_review`, `llm_extracted`, and `offset`/`limit`, applied after the deterministic ordering so pages are stable). The `ETag` is the SHA-256 of the body, so prompt-conditioning consumers get a stable cache key for "schema unchanged".
1068
+ *
1069
+ * @tags sorts
1070
+ * @name GetSortsSchema
1071
+ * @summary Export the authenticated tenant's schema as one OSFQL DDL block
1072
+ * @request GET:/api/v1/sorts/schema
1073
+ * @secure
1074
+ */
1075
+ getSortsSchema = (query, params = {}) => this.http.request({
1076
+ path: `/api/v1/sorts/schema`,
1077
+ method: "GET",
1078
+ query,
1079
+ secure: true,
1080
+ ...params
1081
+ });
1045
1082
  /**
1046
1083
  * No description
1047
1084
  *
@@ -1148,6 +1185,22 @@ var Sorts = class {
1148
1185
  format: "json",
1149
1186
  ...params
1150
1187
  });
1188
+ /**
1189
+ * @description Subsumption is **directional**: ⊑·(s₁, s₂) and ⊑·(s₂, s₁) are different assertions. For the symmetric relation use `/api/v1/sorts/similarity`. The degree must be in [0, 1] and the assignment must keep the relation a fuzzy partial order (max–min transitivity, antisymmetry); one that does not is rejected rather than stored.
1190
+ *
1191
+ * @tags sorts
1192
+ * @name SetFuzzySubsumption
1193
+ * @summary Set the fuzzy subsumption degree `sub ⊑· sup` between two sorts
1194
+ * @request POST:/api/v1/sorts/subsumption
1195
+ */
1196
+ setFuzzySubsumption = (data, params = {}) => this.http.request({
1197
+ path: `/api/v1/sorts/subsumption`,
1198
+ method: "POST",
1199
+ body: data,
1200
+ type: "application/json" /* Json */,
1201
+ format: "json",
1202
+ ...params
1203
+ });
1151
1204
  /**
1152
1205
  * @description Similarity is symmetric: ∼(s₁, s₂) = ∼(s₂, s₁) Degree must be in [0, 1] range.
1153
1206
  *
@@ -1623,11 +1676,11 @@ var Inference = class {
1623
1676
  ...params
1624
1677
  });
1625
1678
  /**
1626
- * @description # DEPRECATED This endpoint is deprecated. Use `DELETE /api/v1/terms/{term_id}` for individual terms. # TRUE HOMOICONIC API # Authorization Requires X-Tenant-Id header.
1679
+ * @description This drops the hydrated base facts, the forward-chain `persist_derived` facts and the residuation store, then forgets the hydration flag so the next request reloads the base facts from PostgreSQL. **It does not delete durable data.** The terms are the authority; this is their cache. That makes it the retraction primitive forward chaining otherwise lacks. Chaining is monotonic — delete a `blocks` edge and the derived "A blocks B" survives every later pass, so the KB keeps asserting a relationship the user removed. Clearing and re-chaining rebuilds the closure from the terms that actually exist. # History Until 2026-07-28 this handler enumerated every term in the tenant and deleted it from PostgreSQL, while calling itself "clear facts" and reporting `"Cleared N facts/rules"`. It is reachable with an ordinary tenant credential — unlike `/api/v1/admin/clear-tenant/{tenant_id}`, which gateways block — so a caller reading the name, the path or the response body had no way to know it was a tenant wipe. It destroyed a live tenant that way. Use `DELETE /api/v1/terms/{term_id}` to delete a term, and the admin route to wipe a tenant; deleting durable data must not be something an endpoint does as a side effect of its name. # Authorization Requires X-Tenant-Id header, and the path tenant must match it.
1627
1680
  *
1628
1681
  * @tags inference
1629
1682
  * @name ClearFacts
1630
- * @summary Clear all facts and rules for a tenant
1683
+ * @summary Clear a tenant's in-memory inference working set.
1631
1684
  * @request DELETE:/api/v1/inference/facts/{tenant_id}
1632
1685
  * @secure
1633
1686
  */
@@ -3043,6 +3096,21 @@ var StructuredIngestion = class {
3043
3096
  secure: true,
3044
3097
  ...params
3045
3098
  });
3099
+ /**
3100
+ * @description Refused with 409 while a registered source still references the file's path (the source's adapter would otherwise hold a dangling `file_path`). After that source is unregistered, the delete succeeds (204). A missing sidecar (no such upload id) is 404.
3101
+ *
3102
+ * @tags structured_ingestion
3103
+ * @name DeleteSourceFile
3104
+ * @summary Delete a tenant-uploaded source file (#107).
3105
+ * @request DELETE:/api/v1/sources/files/{id}
3106
+ * @secure
3107
+ */
3108
+ deleteSourceFile = (id, params = {}) => this.http.request({
3109
+ path: `/api/v1/sources/files/${id}`,
3110
+ method: "DELETE",
3111
+ secure: true,
3112
+ ...params
3113
+ });
3046
3114
  /**
3047
3115
  * @description Performs schema introspection on the source to discover types (sorts), features (fields), and relations. This is a preview operation - no data is ingested. `type_filter` narrows the discovery to a named subset **without re-registering the source** — the escape hatch a client uses after `/tables` when the source is over the discovery cap (#66, Gap 2). It conjoins with the source config's own `include_tables`: a request narrows *within* the registration, it cannot widen past it.
3048
3116
  *
@@ -3095,6 +3163,22 @@ var StructuredIngestion = class {
3095
3163
  format: "json",
3096
3164
  ...params
3097
3165
  });
3166
+ /**
3167
+ * @description Walks `{base}/{tenant_id}/*\/​.meta.json`. A missing tenant dir yields an empty list (200), not 404 — a tenant that never uploaded is not an error.
3168
+ *
3169
+ * @tags structured_ingestion
3170
+ * @name ListSourceFiles
3171
+ * @summary List the calling tenant's uploaded source files (#107).
3172
+ * @request GET:/api/v1/sources/files
3173
+ * @secure
3174
+ */
3175
+ listSourceFiles = (params = {}) => this.http.request({
3176
+ path: `/api/v1/sources/files`,
3177
+ method: "GET",
3178
+ secure: true,
3179
+ format: "json",
3180
+ ...params
3181
+ });
3098
3182
  /**
3099
3183
  * No description
3100
3184
  *
@@ -3161,6 +3245,24 @@ var StructuredIngestion = class {
3161
3245
  format: "json",
3162
3246
  ...params
3163
3247
  });
3248
+ /**
3249
+ * @description Multipart, one field named `file`. Streamed to disk under `{base}/{tenant_id}/{id}/{safe_name}` with a `.meta.json` sidecar. The response `path` is the engine-internal location handed to `POST /api/v1/sources` as `config.file_path` (csv/parquet) or `config.database_path` (sqlite).
3250
+ *
3251
+ * @tags structured_ingestion
3252
+ * @name UploadSourceFile
3253
+ * @summary Upload a file-based source artifact for the calling tenant (#107).
3254
+ * @request POST:/api/v1/sources/files
3255
+ * @secure
3256
+ */
3257
+ uploadSourceFile = (data, params = {}) => this.http.request({
3258
+ path: `/api/v1/sources/files`,
3259
+ method: "POST",
3260
+ body: data,
3261
+ secure: true,
3262
+ type: "multipart/form-data" /* FormData */,
3263
+ format: "json",
3264
+ ...params
3265
+ });
3164
3266
  };
3165
3267
 
3166
3268
  // src/api-spec/generated/NeuroSymbolic.ts
@@ -5864,6 +5966,22 @@ var Extraction = class {
5864
5966
  constructor(http) {
5865
5967
  this.http = http;
5866
5968
  }
5969
+ /**
5970
+ * @description Read-only with respect to the knowledge base: certification inspects the tenant's sort lattice and never writes a term. Certificates *are* written to the verification certificate store, so the batch is auditable afterwards.
5971
+ *
5972
+ * @tags extraction
5973
+ * @name CertifyExtraction
5974
+ * @summary `POST /api/v1/extraction/certify` — gate a batch of extraction candidates through the OSF well-sortedness certifier before they may become durable KB content.
5975
+ * @request POST:/api/v1/extraction/certify
5976
+ */
5977
+ certifyExtraction = (data, params = {}) => this.http.request({
5978
+ path: `/api/v1/extraction/certify`,
5979
+ method: "POST",
5980
+ body: data,
5981
+ type: "application/json" /* Json */,
5982
+ format: "json",
5983
+ ...params
5984
+ });
5867
5985
  /**
5868
5986
  * @description Uses GLiNER2 (zero-shot NER) with sort names from the tenant's knowledge base, guaranteeing that all returned entity labels are valid sort names. Label selection (when no explicit labels provided): Embed the input text and ANN-search the pre-computed sort embedding index (Qdrant) for the most semantically similar HPO sorts. This is O(log n) and typically returns 20-100 highly relevant labels from 19K+ HPO sorts. Requires: - GLiNER2 NER service (`GLINER_NER_URL`) - Qdrant vector store for semantic label selection If either is not configured, returns a 500 error.
5869
5987
  *
@@ -6655,7 +6773,7 @@ var Reasoning = class {
6655
6773
  this.http = http;
6656
6774
  }
6657
6775
  /**
6658
- * @description POST /api/v1/reasoning/disentailment Disentailment A =/=> B means: "if A holds, then B must NOT hold" Returns whether the disentailment is violated (conflict: both A and B hold)
6776
+ * @description POST /api/v1/reasoning/disentailment Disentailment A =/=> B means: "if A holds, then B must NOT hold". Returns whether the disentailment is violated — the conflict where the facts establish A and B follows anyway. This is hierarchy-aware and graded on the same footing as the entailment route, so a conflict reachable only through the sort lattice (a `contaminated` clause held by a `lead_paint` fact that subsumes it) is detected without that clause being supplied as a fact. `A ⇏ B` is violated exactly to the degree `A ⇒ B` is established, so `degree` here reports the complement: how strongly the disentailment still holds.
6659
6777
  *
6660
6778
  * @tags reasoning
6661
6779
  * @name Disentailment
@@ -6671,7 +6789,7 @@ var Reasoning = class {
6671
6789
  ...params
6672
6790
  });
6673
6791
  /**
6674
- * @description POST /api/v1/reasoning/entailment Returns whether antecedent entails consequent
6792
+ * @description POST /api/v1/reasoning/entailment Answers `facts antecedent ⇒ consequent`, hierarchy-aware and graded. A clause holds in the fact base to the degree that some fact *witnesses* it — that is, to the degree the clause subsumes a fact — so a `sparrow` fact establishes the clause `animal` without an `animal` fact being supplied. The consequent is additionally established when it subsumes the antecedent it would follow from. See [`osfkb_domain::operations::homoiconic_entailment`] for the full semantics. `entails` is the crisp reading of `degree`; `degree`, `antecedent_degree` and `consequent_degree` are computed from the sort lattice (crisply, and through explicit fuzzy `⊑·` relations and approved sort similarity), never cast from the boolean.
6675
6793
  *
6676
6794
  * @tags reasoning
6677
6795
  * @name Entailment
@@ -8700,6 +8818,20 @@ var Health = class {
8700
8818
  format: "json",
8701
8819
  ...params
8702
8820
  });
8821
+ /**
8822
+ * No description
8823
+ *
8824
+ * @tags health
8825
+ * @name HealthCheckApi
8826
+ * @summary `GET /api/v1/health` — the same enriched health check under the `/api/v1` prefix. The playground front proxy forwards only `/api/*` to the engine (and answers the bare `/health` itself with a static OK), so THIS is the path that makes the deployed `build_info.version` publicly readable — a stale rollout must never be indistinguishable from a fresh one.
8827
+ * @request GET:/api/v1/health
8828
+ */
8829
+ healthCheckApi = (params = {}) => this.http.request({
8830
+ path: `/api/v1/health`,
8831
+ method: "GET",
8832
+ format: "json",
8833
+ ...params
8834
+ });
8703
8835
  };
8704
8836
 
8705
8837
  // src/api-spec/generated/Scheduling.ts
@@ -9040,6 +9172,24 @@ var Generation = class {
9040
9172
  format: "json",
9041
9173
  ...params
9042
9174
  });
9175
+ /**
9176
+ * @description POST /api/v1/text/generate
9177
+ *
9178
+ * @tags generation
9179
+ * @name GenerateText
9180
+ * @summary Run the caller's system prompt over their text.
9181
+ * @request POST:/api/v1/text/generate
9182
+ * @secure
9183
+ */
9184
+ generateText = (data, params = {}) => this.http.request({
9185
+ path: `/api/v1/text/generate`,
9186
+ method: "POST",
9187
+ body: data,
9188
+ secure: true,
9189
+ type: "application/json" /* Json */,
9190
+ format: "json",
9191
+ ...params
9192
+ });
9043
9193
  /**
9044
9194
  * @description Returns `503` when no in-process Gemma is loaded (server started without `OSFKB_OSFQL_GEMMA_DIR`), `400` on an empty prompt, and `422` when the tenant has no persisted lattice to constrain to (ingest a theory with `persist:true` first).
9045
9195
  *
@@ -9376,6 +9526,58 @@ var Compliance = class {
9376
9526
  format: "json",
9377
9527
  ...params
9378
9528
  });
9529
+ /**
9530
+ * No description
9531
+ *
9532
+ * @tags compliance
9533
+ * @name CreateDsr
9534
+ * @summary File a GDPR data subject request
9535
+ * @request POST:/api/v1/dsr
9536
+ * @secure
9537
+ */
9538
+ createDsr = (data, params = {}) => this.http.request({
9539
+ path: `/api/v1/dsr`,
9540
+ method: "POST",
9541
+ body: data,
9542
+ secure: true,
9543
+ type: "application/json" /* Json */,
9544
+ format: "json",
9545
+ ...params
9546
+ });
9547
+ /**
9548
+ * @description **Dry run by default.** An exact match on an identifying feature is the only deterministic way to resolve a person to terms, but exactness is not uniqueness — two people share a name. Erasing on a bare match would silently destroy a homonym's data, and erasure is irreversible, so the plan has to be inspectable before it runs. Pass `confirm: true` once the match has been reviewed.
9549
+ *
9550
+ * @tags compliance
9551
+ * @name EraseSubject
9552
+ * @summary Plan or execute erasure of a data subject's terms
9553
+ * @request POST:/api/v1/dsr/{id}/erase
9554
+ * @secure
9555
+ */
9556
+ eraseSubject = (id, data, params = {}) => this.http.request({
9557
+ path: `/api/v1/dsr/${id}/erase`,
9558
+ method: "POST",
9559
+ body: data,
9560
+ secure: true,
9561
+ type: "application/json" /* Json */,
9562
+ format: "json",
9563
+ ...params
9564
+ });
9565
+ /**
9566
+ * No description
9567
+ *
9568
+ * @tags compliance
9569
+ * @name GetDsr
9570
+ * @summary Read a data subject request
9571
+ * @request GET:/api/v1/dsr/{id}
9572
+ * @secure
9573
+ */
9574
+ getDsr = (id, params = {}) => this.http.request({
9575
+ path: `/api/v1/dsr/${id}`,
9576
+ method: "GET",
9577
+ secure: true,
9578
+ format: "json",
9579
+ ...params
9580
+ });
9379
9581
  /**
9380
9582
  * No description
9381
9583
  *
@@ -9409,6 +9611,22 @@ var Compliance = class {
9409
9611
  format: "json",
9410
9612
  ...params
9411
9613
  });
9614
+ /**
9615
+ * No description
9616
+ *
9617
+ * @tags compliance
9618
+ * @name ListDsr
9619
+ * @summary List a data subject's requests
9620
+ * @request GET:/api/v1/dsr
9621
+ * @secure
9622
+ */
9623
+ listDsr = (params = {}) => this.http.request({
9624
+ path: `/api/v1/dsr`,
9625
+ method: "GET",
9626
+ secure: true,
9627
+ format: "json",
9628
+ ...params
9629
+ });
9412
9630
  /**
9413
9631
  * No description
9414
9632
  *
@@ -9890,6 +10108,24 @@ var OntologyBridge = class {
9890
10108
  format: "json",
9891
10109
  ...params
9892
10110
  });
10111
+ /**
10112
+ * @description The gap this closes (#133): the engine could lower OSFQL to a source's native language and could execute native queries, and the two were never reachable together over HTTP. `POST /api/v1/osfql` runs against the knowledge base and never consults a binding; `POST /api/v1/ontology/transpile` emits the query text and stops. A `transpile`-mode source — which deliberately ingests nothing — therefore had no way to be queried at all, and asking about its data returned an empty result indistinguishable from a broken connector. The dialect is derived from the source's type, never taken from the caller: the binding says which source answers for the sort, and that source's type is the only dialect that could run. Letting a caller name one would let them ask for Cypher against Postgres. The emitted query is returned with the rows. Transpile mode's claim is that OSFQL becomes a native query against the operator's own database; returning only rows leaves that unverifiable.
10113
+ *
10114
+ * @tags ontology_bridge
10115
+ * @name ExecuteTranspiled
10116
+ * @summary Transpile an OSFQL MATCH and execute it on the source it is bound to.
10117
+ * @request POST:/api/v1/ontology/query
10118
+ * @secure
10119
+ */
10120
+ executeTranspiled = (data, params = {}) => this.http.request({
10121
+ path: `/api/v1/ontology/query`,
10122
+ method: "POST",
10123
+ body: data,
10124
+ secure: true,
10125
+ type: "application/json" /* Json */,
10126
+ format: "json",
10127
+ ...params
10128
+ });
9893
10129
  /**
9894
10130
  * @description Produces query tools, write tools, and inference tools from the current sort hierarchy and SQL bindings, along with a system prompt suitable for grounding an LLM.
9895
10131
  *
@@ -9959,7 +10195,7 @@ var OntologyBridge = class {
9959
10195
  ...params
9960
10196
  });
9961
10197
  /**
9962
- * @description Parses the OSFQL query, compiles it, and transpiles the first `ScanBySort` operation to SQL using the current sort-table bindings.
10198
+ * @description Parses the OSFQL query, compiles it, and transpiles EVERY `ScanBySort` operation into one statement using the current sort-table bindings — a JOIN for the SQL dialects, a multi-pattern MATCH for Cypher. A plan operation that is not a scan is refused by name rather than dropped: `fully_transpilable` is what a caller checks to decide whether the emitted text is the whole question, and it reported `true` for a query half of which was never emitted (#134).
9963
10199
  *
9964
10200
  * @tags ontology_bridge
9965
10201
  * @name Transpile
@@ -10258,6 +10494,24 @@ var Speakers = class {
10258
10494
  format: "json",
10259
10495
  ...params
10260
10496
  });
10497
+ /**
10498
+ * @description POST /api/v1/speakers/identify
10499
+ *
10500
+ * @tags speakers
10501
+ * @name IdentifySpeakers
10502
+ * @summary Identify which enrolled voices speak in a piece of audio — no transcript.
10503
+ * @request POST:/api/v1/speakers/identify
10504
+ * @secure
10505
+ */
10506
+ identifySpeakers = (data, params = {}) => this.http.request({
10507
+ path: `/api/v1/speakers/identify`,
10508
+ method: "POST",
10509
+ body: data,
10510
+ secure: true,
10511
+ type: "application/json" /* Json */,
10512
+ format: "json",
10513
+ ...params
10514
+ });
10261
10515
  /**
10262
10516
  * @description GET /api/v1/speakers
10263
10517
  *
@@ -10524,6 +10778,22 @@ var Documents = class {
10524
10778
  constructor(http) {
10525
10779
  this.http = http;
10526
10780
  }
10781
+ /**
10782
+ * No description
10783
+ *
10784
+ * @tags documents
10785
+ * @name EraseDocument
10786
+ * @summary Erase a document and everything extracted from it
10787
+ * @request DELETE:/api/v1/documents/{id}
10788
+ * @secure
10789
+ */
10790
+ eraseDocument = (id, params = {}) => this.http.request({
10791
+ path: `/api/v1/documents/${id}`,
10792
+ method: "DELETE",
10793
+ secure: true,
10794
+ format: "json",
10795
+ ...params
10796
+ });
10527
10797
  /**
10528
10798
  * No description
10529
10799
  *
@@ -19742,20 +20012,21 @@ var IngestionSession = class {
19742
20012
  }));
19743
20013
  return;
19744
20014
  }
19745
- const timer = setTimeout(resolve, ms);
20015
+ let onAbort;
20016
+ const timer = setTimeout(() => {
20017
+ if (signal && onAbort) {
20018
+ signal.removeEventListener("abort", onAbort);
20019
+ }
20020
+ resolve();
20021
+ }, ms);
19746
20022
  if (signal) {
19747
- const onAbort = () => {
20023
+ onAbort = () => {
19748
20024
  clearTimeout(timer);
19749
20025
  reject(new ReasoningLayerError("Ingestion polling was aborted", {
19750
20026
  cause: signal.reason
19751
20027
  }));
19752
20028
  };
19753
20029
  signal.addEventListener("abort", onAbort, { once: true });
19754
- const originalResolve = resolve;
19755
- resolve = () => {
19756
- signal.removeEventListener("abort", onAbort);
19757
- originalResolve();
19758
- };
19759
20030
  }
19760
20031
  });
19761
20032
  }
@@ -28750,7 +29021,15 @@ function PaperMetadataFromApiToFront(dto) {
28750
29021
  abstractText: dto.abstract_text ?? null,
28751
29022
  citationCount: dto.citation_count ?? null,
28752
29023
  source: dto.source,
28753
- fullTextUrl: dto.full_text_url ?? null
29024
+ fullTextUrl: dto.full_text_url ?? null,
29025
+ paperKey: dto.paper_key ?? null
29026
+ };
29027
+ }
29028
+ function PaperRefFromApiToFront(dto) {
29029
+ return {
29030
+ paperKey: dto.paper_key,
29031
+ doi: dto.doi ?? null,
29032
+ title: dto.title
28754
29033
  };
28755
29034
  }
28756
29035
  function PaperSearchResultFromApiToFront(dto) {
@@ -28784,6 +29063,8 @@ function ResearchCycleResultFromApiToFront(dto) {
28784
29063
  papersIngested: dto.papers_ingested,
28785
29064
  claimsVerified: dto.claims_verified,
28786
29065
  contradictionsDetected: dto.contradictions_detected,
29066
+ contradictionsResolved: dto.contradictions_resolved ?? 0,
29067
+ claimsMerged: dto.claims_merged ?? 0,
28787
29068
  processingTimeMs: dto.processing_time_ms,
28788
29069
  searchQueries: dto.search_queries ?? []
28789
29070
  };
@@ -28796,6 +29077,7 @@ function ResearchSessionResponseFromApiToFront(raw) {
28796
29077
  status: dto.status,
28797
29078
  error: dto.error ?? null,
28798
29079
  cycles: (dto.cycles ?? []).map(ResearchCycleResultFromApiToFront),
29080
+ papers: (dto.papers ?? []).map(PaperMetadataFromApiToFront),
28799
29081
  totalPapersIngested: dto.total_papers_ingested,
28800
29082
  totalFindings: dto.total_findings,
28801
29083
  totalContradictions: dto.total_contradictions,
@@ -28840,7 +29122,9 @@ function EvidenceItemSummaryFromApiToFront(dto) {
28840
29122
  qualityWeight: dto.quality_weight,
28841
29123
  supports: dto.supports,
28842
29124
  contribution: dto.contribution,
28843
- paperDoi: dto.paper_doi ?? null
29125
+ paperDoi: dto.paper_doi ?? null,
29126
+ paperKey: dto.paper_key ?? null,
29127
+ paperTitle: dto.paper_title ?? null
28844
29128
  };
28845
29129
  }
28846
29130
  function ProvenanceStepFromApiToFront(dto) {
@@ -28851,6 +29135,13 @@ function ProvenanceStepFromApiToFront(dto) {
28851
29135
  timestamp: dto.timestamp ?? null
28852
29136
  };
28853
29137
  }
29138
+ function ResiduatedFeatureFromApiToFront(dto) {
29139
+ return {
29140
+ featureName: dto.feature_name,
29141
+ neededSort: dto.needed_sort ?? null,
29142
+ infoGain: dto.info_gain
29143
+ };
29144
+ }
28854
29145
  function ResearchFindingFromApiToFront(dto) {
28855
29146
  return {
28856
29147
  claimId: dto.claim_id,
@@ -28861,7 +29152,9 @@ function ResearchFindingFromApiToFront(dto) {
28861
29152
  contradictingEvidence: (dto.contradicting_evidence ?? []).map(EvidenceItemSummaryFromApiToFront),
28862
29153
  provenanceChain: (dto.provenance_chain ?? []).map(ProvenanceStepFromApiToFront),
28863
29154
  residuated: dto.residuated,
28864
- residuationReason: dto.residuation_reason ?? null
29155
+ residuationReason: dto.residuation_reason ?? null,
29156
+ residuatedFeatures: (dto.residuated_features ?? []).map(ResiduatedFeatureFromApiToFront),
29157
+ sources: (dto.sources ?? []).map(PaperRefFromApiToFront)
28865
29158
  };
28866
29159
  }
28867
29160
  function ResearchFindingsResponseFromApiToFront(raw) {
@@ -28889,6 +29182,17 @@ function ResearchGapsResponseFromApiToFront(raw) {
28889
29182
  total: dto.total
28890
29183
  };
28891
29184
  }
29185
+ function ContradictionResolutionFromApiToFront(dto) {
29186
+ return {
29187
+ preferredClaimId: dto.preferred_claim_id,
29188
+ dismissedClaimId: dto.dismissed_claim_id,
29189
+ preferredTruthfulness: dto.preferred_truthfulness,
29190
+ dismissedTruthfulness: dto.dismissed_truthfulness,
29191
+ strategy: dto.strategy,
29192
+ confidence: dto.confidence,
29193
+ explanation: dto.explanation
29194
+ };
29195
+ }
28892
29196
  function ContradictionFromApiToFront(dto) {
28893
29197
  return {
28894
29198
  claimAId: dto.claim_a_id,
@@ -28896,7 +29200,10 @@ function ContradictionFromApiToFront(dto) {
28896
29200
  statementA: dto.statement_a,
28897
29201
  statementB: dto.statement_b,
28898
29202
  confidence: dto.confidence,
28899
- explanation: dto.explanation
29203
+ explanation: dto.explanation,
29204
+ resolution: dto.resolution ? ContradictionResolutionFromApiToFront(dto.resolution) : null,
29205
+ claimASources: (dto.claim_a_sources ?? []).map(PaperRefFromApiToFront),
29206
+ claimBSources: (dto.claim_b_sources ?? []).map(PaperRefFromApiToFront)
28900
29207
  };
28901
29208
  }
28902
29209
  function ResearchContradictionsResponseFromApiToFront(raw) {
@@ -28917,7 +29224,9 @@ function ResearchStatisticsFromApiToFront(dto) {
28917
29224
  totalContradictions: dto.total_contradictions,
28918
29225
  totalProcessingTimeMs: dto.total_processing_time_ms,
28919
29226
  gapsResolved: dto.gaps_resolved,
28920
- gapsRemaining: dto.gaps_remaining
29227
+ gapsRemaining: dto.gaps_remaining,
29228
+ claimsMerged: dto.claims_merged ?? 0,
29229
+ contradictionsResolved: dto.contradictions_resolved ?? 0
28921
29230
  };
28922
29231
  }
28923
29232
  function ReportVerificationFromApiToFront(dto) {