@kortexya/reasoninglayer 1.13.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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.13.0";
10
+ var SDK_VERSION = "1.15.0";
11
11
  function resolveConfig(config) {
12
12
  if (!config.baseUrl) {
13
13
  throw new Error("ClientConfig.baseUrl is required");
@@ -543,29 +543,61 @@ var HttpClient = class {
543
543
  };
544
544
  };
545
545
 
546
- // src/serialization.ts
546
+ // src/user-data-fields.ts
547
547
  var USER_DATA_FIELDS = /* @__PURE__ */ new Set([
548
- // features — term/query feature maps (Record<string, ValueDto>)
549
- "features",
550
- // bindings — variable binding maps
548
+ "annotations",
549
+ "answers",
550
+ "antecedentFeatures",
551
+ "antecedent_features",
551
552
  "bindings",
552
- // evidence — causal evidence maps
553
+ "coefficients",
554
+ "conceptValues",
555
+ "concept_values",
556
+ "contextDependentRelations",
557
+ "context_dependent_relations",
558
+ "correctPattern",
559
+ "correct_pattern",
560
+ "currentValues",
561
+ "current_values",
562
+ "dataVersions",
563
+ "data_versions",
553
564
  "evidence",
554
- // exogenous values — causal intervention values
555
- "exogenous_values",
556
- "exogenousValues",
557
- // modified/suggested params — action review params
558
- "modified_params",
565
+ "extra",
566
+ "extracted",
567
+ "features",
568
+ "fieldTypes",
569
+ "field_types",
570
+ "filter",
571
+ "initialBindings",
572
+ "initial_bindings",
573
+ "inputs",
574
+ "interventions",
559
575
  "modifiedParams",
560
- "suggested_params",
561
- "suggestedParams",
562
- // match key — row matching keys
563
- "match_key",
564
- "matchKey",
565
- // concept values — RAG concept values
566
- "concept_values",
567
- "conceptValues"
576
+ "modified_params",
577
+ "observations",
578
+ "optionalInputs",
579
+ "optional_inputs",
580
+ "original",
581
+ "originalValues",
582
+ "original_values",
583
+ "outputs",
584
+ "perStrategyTaxonomies",
585
+ "per_strategy_taxonomies",
586
+ "propsOverride",
587
+ "props_override",
588
+ "roleMinimums",
589
+ "role_minimums",
590
+ "scope",
591
+ "scoresByName",
592
+ "scores_by_name",
593
+ "sortNames",
594
+ "sort_names",
595
+ "topK",
596
+ "top_k",
597
+ "values"
568
598
  ]);
599
+
600
+ // src/serialization.ts
569
601
  function camelToSnake(str) {
570
602
  return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
571
603
  }
@@ -632,11 +664,11 @@ function buildAuthHeaders(config) {
632
664
  return headers;
633
665
  }
634
666
  function transformRequestInit(init) {
635
- if (!init?.body || typeof init.body !== "string") return init;
636
- const headers = init.headers;
637
- if (hasRawBodyHeader(headers)) {
638
- return { ...init, headers: withoutRawBodyHeader(headers) };
667
+ if (!init) return init;
668
+ if (hasRawBodyHeader(init.headers)) {
669
+ return { ...init, headers: withoutRawBodyHeader(init.headers) };
639
670
  }
671
+ if (!init.body || typeof init.body !== "string") return init;
640
672
  try {
641
673
  const parsed = JSON.parse(init.body);
642
674
  const snaked = toSnakeCase(parsed);
@@ -645,15 +677,14 @@ function transformRequestInit(init) {
645
677
  return init;
646
678
  }
647
679
  }
680
+ var RAW_BODY_HEADER_LOWER = RAW_BODY_HEADER.toLowerCase();
648
681
  function hasRawBodyHeader(headers) {
649
682
  if (!headers) return false;
650
683
  if (headers instanceof Headers) return headers.get(RAW_BODY_HEADER) !== null;
651
684
  if (Array.isArray(headers)) {
652
- return headers.some(([name]) => name.toLowerCase() === RAW_BODY_HEADER.toLowerCase());
685
+ return headers.some(([name]) => name.toLowerCase() === RAW_BODY_HEADER_LOWER);
653
686
  }
654
- return Object.keys(headers).some(
655
- (name) => name.toLowerCase() === RAW_BODY_HEADER.toLowerCase()
656
- );
687
+ return Object.keys(headers).some((name) => name.toLowerCase() === RAW_BODY_HEADER_LOWER);
657
688
  }
658
689
  function withoutRawBodyHeader(headers) {
659
690
  if (headers instanceof Headers) {
@@ -662,12 +693,12 @@ function withoutRawBodyHeader(headers) {
662
693
  return copy;
663
694
  }
664
695
  if (Array.isArray(headers)) {
665
- return headers.filter(([name]) => name.toLowerCase() !== RAW_BODY_HEADER.toLowerCase());
696
+ return headers.filter(([name]) => name.toLowerCase() !== RAW_BODY_HEADER_LOWER);
666
697
  }
667
698
  if (headers) {
668
699
  const rest = {};
669
700
  for (const [name, value] of Object.entries(headers)) {
670
- if (name.toLowerCase() !== RAW_BODY_HEADER.toLowerCase()) {
701
+ if (name.toLowerCase() !== RAW_BODY_HEADER_LOWER) {
671
702
  rest[name] = value;
672
703
  }
673
704
  }
@@ -1383,9 +1414,10 @@ var Terms = class {
1383
1414
  * @request GET:/api/v1/terms
1384
1415
  * @secure
1385
1416
  */
1386
- listTerms = (params = {}) => this.http.request({
1417
+ listTerms = (query, params = {}) => this.http.request({
1387
1418
  path: `/api/v1/terms`,
1388
1419
  method: "GET",
1420
+ query,
1389
1421
  secure: true,
1390
1422
  format: "json",
1391
1423
  ...params
@@ -1465,7 +1497,7 @@ var Inference = class {
1465
1497
  ...params
1466
1498
  });
1467
1499
  /**
1468
- * @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"}] } ``` # Authorization Requires X-Tenant-Id header.
1500
+ * @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"}] } ``` # 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.
1469
1501
  *
1470
1502
  * @tags inference
1471
1503
  * @name BackwardChain
@@ -1722,9 +1754,10 @@ var Inference = class {
1722
1754
  * @request GET:/api/v1/inference/facts/{tenant_id}
1723
1755
  * @secure
1724
1756
  */
1725
- getFacts = (tenantId, params = {}) => this.http.request({
1757
+ getFacts = (tenantId, query, params = {}) => this.http.request({
1726
1758
  path: `/api/v1/inference/facts/${tenantId}`,
1727
1759
  method: "GET",
1760
+ query,
1728
1761
  secure: true,
1729
1762
  format: "json",
1730
1763
  ...params
@@ -2614,7 +2647,7 @@ var Ingestion = class {
2614
2647
  ...params
2615
2648
  });
2616
2649
  /**
2617
- * @description POST /api/v1/ingest/document This endpoint accepts a document (as base64 or URL) and: 1. Parses it to Markdown using the document parser service (Docling) 2. Processes the Markdown through the existing ingestion pipeline 3. Returns combined statistics from both stages # Headers - `X-Tenant-Id`: Tenant ID for multi-tenancy isolation (required) # Request Body - `document`: Document source (base64 or URL) - `document_type`: Optional type hint (auto-detected if not provided) - `owner_id`: User ID who owns the ingested data - `ocr_config`: Optional OCR/parsing configuration - `ingestion_config`: Optional markdown ingestion configuration # Response - `success`: Whether ingestion completed successfully - `parse_stats`: Statistics from document parsing - `metadata`: Extracted document metadata - `ingestion_stats`: Statistics from markdown ingestion - `pending_review`: Entities that need human review
2650
+ * @description POST /api/v1/ingest/document This endpoint accepts a document (as base64 or URL) and: 1. Parses it to Markdown using the document parser service (Docling) 2. Returns the generated Markdown to the caller 3. Unless `parse_only` is true, processes the Markdown through ingestion 4. Returns combined statistics from the completed stages # Headers - `X-Tenant-Id`: Tenant ID for multi-tenancy isolation (required) # Request Body - `document`: Document source (base64 or URL) - `document_type`: Optional type hint (auto-detected if not provided) - `owner_id`: User ID who owns the ingested data - `ocr_config`: Optional OCR/parsing configuration - `ingestion_config`: Optional markdown ingestion configuration - `parse_only`: Return Markdown without creating sessions or semantic terms # Response - `success`: Whether ingestion completed successfully - `parse_stats`: Statistics from document parsing - `metadata`: Extracted document metadata - `markdown`: Markdown generated by Docling/OCR - `ingestion_stats`: Statistics from markdown ingestion - `pending_review`: Entities that need human review
2618
2651
  *
2619
2652
  * @tags ingestion
2620
2653
  * @name IngestDocument
@@ -2949,6 +2982,22 @@ var StructuredIngestion = class {
2949
2982
  format: "json",
2950
2983
  ...params
2951
2984
  });
2985
+ /**
2986
+ * @description The pre-registration half of #71's mode-discovery surface: a client rendering a "new source" picker learns, at type-selection time, which types registration would accept and which write-path modes each would serve — without constructing a source (postgres, for example, opens a connection pool eagerly). Static per build, so no tenant state is consulted; auth is still required, as for every route under `/api/v1`.
2987
+ *
2988
+ * @tags structured_ingestion
2989
+ * @name ListSourceTypesCatalog
2990
+ * @summary List the source types this build can register, with their mode capabilities.
2991
+ * @request GET:/api/v1/sources/types
2992
+ * @secure
2993
+ */
2994
+ listSourceTypesCatalog = (params = {}) => this.http.request({
2995
+ path: `/api/v1/sources/types`,
2996
+ method: "GET",
2997
+ secure: true,
2998
+ format: "json",
2999
+ ...params
3000
+ });
2952
3001
  /**
2953
3002
  * @description Creates a connector instance from the provided configuration and registers it with the structured ingestion service for subsequent schema discovery and data ingestion.
2954
3003
  *
@@ -12091,7 +12140,8 @@ function ProofDtoFromApiToFront(dto) {
12091
12140
  ruleLabel: dto.rule_label,
12092
12141
  substitution: HomoiconicSubstitutionDtoFromApiToFront(dto.substitution),
12093
12142
  subproofs: dto.subproofs?.map(ProofDtoFromApiToFront),
12094
- certainty: dto.certainty
12143
+ certainty: dto.certainty,
12144
+ residuated: dto.residuated
12095
12145
  };
12096
12146
  }
12097
12147
  function ProvenanceTagDtoFromApiToFront(dto) {
@@ -12107,6 +12157,7 @@ function SolutionDtoFromApiToFront(dto) {
12107
12157
  certainty: dto.certainty,
12108
12158
  evidenceMatched: dto.evidence_matched ?? void 0,
12109
12159
  evidenceRatio: dto.evidence_ratio ?? void 0,
12160
+ evidenceSupport: dto.evidence_support ?? void 0,
12110
12161
  residuatedSorts: dto.residuated_sorts
12111
12162
  };
12112
12163
  }
@@ -12485,11 +12536,19 @@ function TaggedForwardChainResponseFromApiToFront(dto) {
12485
12536
  totalFacts: dto.total_facts
12486
12537
  };
12487
12538
  }
12539
+ function RuleAggregatorDtoFromFrontToApi(model) {
12540
+ return {
12541
+ group_by: model.groupBy,
12542
+ op: model.op,
12543
+ target: model.target
12544
+ };
12545
+ }
12488
12546
  function AddRuleRequestFromFrontToApi(model) {
12489
12547
  return {
12490
12548
  term: TermInputDtoFromFrontToApi(model.term),
12491
12549
  antecedents: model.antecedents?.map(TermInputDtoFromFrontToApi),
12492
- certainty: model.certainty
12550
+ certainty: model.certainty,
12551
+ aggregator: model.aggregator ? RuleAggregatorDtoFromFrontToApi(model.aggregator) : model.aggregator
12493
12552
  };
12494
12553
  }
12495
12554
  function AddFactRequestFromFrontToApi(model) {
@@ -12526,7 +12585,8 @@ function ForwardChainRequestFromFrontToApi(model) {
12526
12585
  persist_derived: model.persistDerived,
12527
12586
  enable_provenance_tags: model.enableProvenanceTags,
12528
12587
  max_iterations: model.maxIterations,
12529
- max_facts: model.maxFacts
12588
+ max_facts: model.maxFacts,
12589
+ emit_provenance: model.emitProvenance
12530
12590
  };
12531
12591
  }
12532
12592
  function FuzzyProveRequestFromFrontToApi(model) {
@@ -12537,7 +12597,8 @@ function FuzzyProveRequestFromFrontToApi(model) {
12537
12597
  max_solutions: model.maxSolutions,
12538
12598
  open_world: model.openWorld,
12539
12599
  save_goal: model.saveGoal,
12540
- tnorm: model.tnorm
12600
+ tnorm: model.tnorm,
12601
+ scope: model.scope
12541
12602
  };
12542
12603
  }
12543
12604
  function BulkFuzzyProveRequestFromFrontToApi(model) {
@@ -12643,14 +12704,29 @@ var InferenceClient = class {
12643
12704
  /**
12644
12705
  * Add an inference rule.
12645
12706
  *
12646
- * @param request - Rule definition using TermInputDto.
12707
+ * @param request - Rule definition using TermInputDto. Set `aggregator` to declare an
12708
+ * engine-side head aggregator (see {@link RuleAggregatorDto}).
12647
12709
  * @returns The created rule wrapped in an AddRuleResponse.
12710
+ * @throws {ApiError} If the rule is rejected or the request fails.
12711
+ *
12712
+ * @remarks
12713
+ * **Serialization format**: untagged `TermInputDto` / `FeatureInputValueDto`.
12714
+ *
12715
+ * @example
12716
+ * ```typescript
12717
+ * await client.inference.addRule({
12718
+ * term: psi('total_spend', { customer_id: Var('C'), amount: Var('A') }),
12719
+ * antecedents: [psi('order', { customer_id: Var('C'), amount: Var('A') })],
12720
+ * aggregator: { groupBy: ['customer_id'], op: 'sum', target: 'amount' },
12721
+ * });
12722
+ * ```
12648
12723
  */
12649
12724
  async addRule(request) {
12650
12725
  const wireRequest = {
12651
12726
  term: convertTermArg(request.term),
12652
12727
  antecedents: request.antecedents?.map(convertTermArg),
12653
- certainty: request.certainty
12728
+ certainty: request.certainty,
12729
+ aggregator: request.aggregator
12654
12730
  };
12655
12731
  const response = await this.api.addRule(AddRuleRequestFromFrontToApi(wireRequest));
12656
12732
  return AddRuleResponseFromApiToFront(response.data);
@@ -17267,6 +17343,22 @@ function CausalAnalyzeRequestFromFrontToApi(model) {
17267
17343
  question: CausalAnalyzeQuestionDtoFromFrontToApi(model.question)
17268
17344
  };
17269
17345
  }
17346
+ function DiDValidationRequestFromFrontToApi(model) {
17347
+ return {
17348
+ covariates: model.covariates,
17349
+ outcome_post: model.outcomePost,
17350
+ outcome_pre: model.outcomePre,
17351
+ treatment: model.treatment
17352
+ };
17353
+ }
17354
+ function DiDValidationResponseFromApiToFront(dto) {
17355
+ return {
17356
+ badControls: dto.bad_controls,
17357
+ explanation: dto.explanation,
17358
+ framework: dto.framework,
17359
+ isValid: dto.is_valid
17360
+ };
17361
+ }
17270
17362
 
17271
17363
  // src/resources/causal.ts
17272
17364
  var CausalClient = class {
@@ -18057,6 +18149,53 @@ var CausalClient = class {
18057
18149
  );
18058
18150
  return RefuteEstimateResponseFromApiToFront(response.data);
18059
18151
  }
18152
+ // ===========================================================================
18153
+ // Design validation
18154
+ // ===========================================================================
18155
+ /**
18156
+ * Validate a Difference-in-Differences (DiD) design.
18157
+ *
18158
+ * @param request - The treatment variable, the pre- and post-treatment outcome
18159
+ * variables, and an optional conditioning set.
18160
+ * @returns Whether the design is theoretically sound, an explanation, the bad
18161
+ * controls found in the conditioning set, and the framework used.
18162
+ * @throws {BadRequestError} If the request is malformed.
18163
+ * @throws {ApiError} If the request otherwise fails.
18164
+ *
18165
+ * @remarks
18166
+ * Checks the design against the causal structure the backend builds from the
18167
+ * tenant's homoiconic rules, using the Transformed SWIG (Delta-SWIG) framework
18168
+ * of Knaus & Pfleiderer (2026). This is a design check over the *graph*: no
18169
+ * sample data is submitted and nothing is estimated — validate the design here,
18170
+ * then estimate the effect with {@link CausalClient.ateEstimate}.
18171
+ *
18172
+ * A design can be invalid even with an empty conditioning set (parallel trends
18173
+ * unsupported by the structure); `badControls` names the covariates that induce
18174
+ * bias if conditioned on, so an invalid design is often repaired by dropping
18175
+ * them and re-validating.
18176
+ *
18177
+ * Plain scalar JSON — no value serialization (`ValueDto` / `FeatureValueDto`)
18178
+ * is involved.
18179
+ *
18180
+ * @example
18181
+ * ```typescript
18182
+ * const did = await client.causal.validateDid({
18183
+ * treatment: 'minimum_wage_hike',
18184
+ * outcomePre: 'employment_2025',
18185
+ * outcomePost: 'employment_2026',
18186
+ * covariates: ['county_gdp'],
18187
+ * });
18188
+ * console.log(did.isValid); // false
18189
+ * console.log(did.badControls); // ['county_gdp']
18190
+ * console.log(did.framework); // 'Delta-SWIG (Knaus & Pfleiderer, 2026)'
18191
+ * ```
18192
+ */
18193
+ async validateDid(request) {
18194
+ const response = await this.api.validateDid(
18195
+ DiDValidationRequestFromFrontToApi(request)
18196
+ );
18197
+ return DiDValidationResponseFromApiToFront(response.data);
18198
+ }
18060
18199
  };
18061
18200
 
18062
18201
  // src/normalizers/ingestion.ts
@@ -20965,7 +21104,8 @@ function RegisterSourceRequestFromFrontToApi(model) {
20965
21104
  source_id: model.sourceId,
20966
21105
  source_name: model.sourceName,
20967
21106
  source_type: model.sourceType,
20968
- config: model.config
21107
+ config: model.config,
21108
+ mode: model.mode
20969
21109
  };
20970
21110
  }
20971
21111
  function RegisterSourceResponseFromApiToFront(dto) {
@@ -20973,12 +21113,15 @@ function RegisterSourceResponseFromApiToFront(dto) {
20973
21113
  success: dto.success,
20974
21114
  sourceId: dto.source_id,
20975
21115
  sourceType: dto.source_type,
21116
+ mode: dto.mode,
21117
+ supportedModes: dto.supported_modes,
20976
21118
  message: dto.message
20977
21119
  };
20978
21120
  }
20979
21121
  function SourceSummaryDtoFromApiToFront(dto) {
20980
21122
  return {
20981
21123
  available: dto.available,
21124
+ mode: dto.mode,
20982
21125
  sourceId: dto.source_id,
20983
21126
  sourceType: dto.source_type
20984
21127
  };
@@ -20993,7 +21136,22 @@ function SourceDetailResponseFromApiToFront(dto) {
20993
21136
  return {
20994
21137
  sourceId: dto.source_id,
20995
21138
  sourceType: dto.source_type,
20996
- available: dto.available
21139
+ available: dto.available,
21140
+ mode: dto.mode,
21141
+ supportedModes: dto.supported_modes
21142
+ };
21143
+ }
21144
+ function SourceTypeDtoFromApiToFront(dto) {
21145
+ return {
21146
+ sourceType: dto.source_type,
21147
+ aliases: dto.aliases,
21148
+ available: dto.available,
21149
+ supportedModes: dto.supported_modes
21150
+ };
21151
+ }
21152
+ function ListSourceTypesResponseFromApiToFront(dto) {
21153
+ return {
21154
+ types: dto.types.map(SourceTypeDtoFromApiToFront)
20997
21155
  };
20998
21156
  }
20999
21157
  function DiscoverSchemaRequestFromFrontToApi(model) {
@@ -21073,6 +21231,7 @@ function IngestFromSourceRequestFromFrontToApi(model) {
21073
21231
  function StructuredIngestionStatsDtoFromApiToFront(dto) {
21074
21232
  return {
21075
21233
  columnsDiscovered: dto.columns_discovered,
21234
+ columnsDropped: dto.columns_dropped,
21076
21235
  documentsRendered: dto.documents_rendered,
21077
21236
  elapsedMs: dto.elapsed_ms,
21078
21237
  entitiesCreated: dto.entities_created,
@@ -21082,7 +21241,8 @@ function StructuredIngestionStatsDtoFromApiToFront(dto) {
21082
21241
  relationsDiscovered: dto.relations_discovered,
21083
21242
  sortsCreated: dto.sorts_created,
21084
21243
  tablesDiscovered: dto.tables_discovered,
21085
- termsCreated: dto.terms_created
21244
+ termsCreated: dto.terms_created,
21245
+ termsProjected: dto.terms_projected
21086
21246
  };
21087
21247
  }
21088
21248
  function IngestFromSourceResponseFromApiToFront(dto) {
@@ -21106,13 +21266,72 @@ var SourcesClient = class {
21106
21266
  /**
21107
21267
  * Register a new data source.
21108
21268
  *
21109
- * @param request - Source registration request.
21110
- * @returns Registration result.
21269
+ * @param request - Source registration request. Set `mode` to declare the write-path
21270
+ * intent (`'transpile'` for live SQL views, `'ingest'` to materialize rows as
21271
+ * Ψ-term facts); omit it to take the default, which is `'ingest'` for every
21272
+ * source type (#71).
21273
+ * @returns Registration result. `mode` always carries the **resolved** write-path
21274
+ * mode, including when the default applied; `supportedModes` advertises which
21275
+ * modes this source's adapter can serve.
21276
+ * @throws {ApiError} If registration fails, with **422** if `mode` is not one of
21277
+ * `transpile` / `ingest`, or with **422** if `mode: 'transpile'` is requested
21278
+ * for a source whose adapter cannot execute transpiled SQL (a live view over it
21279
+ * could never be queried).
21280
+ *
21281
+ * @remarks
21282
+ * Registering with `mode: 'transpile'` makes {@link SourcesClient.ingest} refuse this
21283
+ * source with a **409** — materializing a transpiled source would create a second,
21284
+ * divergent namespace over the same rows. To learn which types accept `transpile`
21285
+ * before registering, call {@link SourcesClient.listSourceTypes}.
21286
+ *
21287
+ * @example
21288
+ * ```typescript
21289
+ * const result = await client.sources.register({
21290
+ * sourceId: 'crm_postgres',
21291
+ * sourceName: 'CRM PostgreSQL',
21292
+ * sourceType: 'postgres',
21293
+ * config: { connection_string: 'postgres://user:pass@host/db' },
21294
+ * mode: 'ingest',
21295
+ * });
21296
+ * console.log(result.mode); // 'ingest'
21297
+ * console.log(result.supportedModes); // ['ingest', 'transpile']
21298
+ * ```
21111
21299
  */
21112
21300
  async register(request) {
21113
21301
  const response = await this.api.registerSource(RegisterSourceRequestFromFrontToApi(request));
21114
21302
  return RegisterSourceResponseFromApiToFront(response.data);
21115
21303
  }
21304
+ /**
21305
+ * List the source types this build can register, with their mode capabilities.
21306
+ *
21307
+ * @returns Every registrable source type, its availability in this build, and the
21308
+ * write-path modes each would serve — before any source exists.
21309
+ * @throws {ApiError} If the request fails.
21310
+ *
21311
+ * @remarks
21312
+ * Sent to `GET /api/v1/sources/types`. The pre-registration half of #71's
21313
+ * mode-discovery surface: a client rendering a "new source" picker learns, at
21314
+ * type-selection time, which types registration would accept (`available` — a
21315
+ * type behind an uncompiled cargo feature is `false`) and which modes each
21316
+ * would serve (`supportedModes` — always `'ingest'`, plus `'transpile'` only
21317
+ * for the SQL engines). Static per build, so no tenant state is consulted.
21318
+ *
21319
+ * Drive a mode selector from `supportedModes` rather than a hard-coded list of
21320
+ * source types: the set is the adapter's declared capability, so it stays
21321
+ * correct as adapters gain the ability (MySQL and SQLite did in #70).
21322
+ *
21323
+ * @example
21324
+ * ```typescript
21325
+ * const { types } = await client.sources.listSourceTypes();
21326
+ * const postgres = types.find((t) => t.sourceType === 'postgres');
21327
+ * console.log(postgres?.supportedModes); // ['ingest', 'transpile']
21328
+ * console.log(postgres?.aliases); // ['postgresql']
21329
+ * ```
21330
+ */
21331
+ async listSourceTypes() {
21332
+ const response = await this.api.listSourceTypesCatalog();
21333
+ return ListSourceTypesResponseFromApiToFront(response.data);
21334
+ }
21116
21335
  /**
21117
21336
  * List all registered data sources.
21118
21337
  *
@@ -22283,13 +22502,35 @@ function mapEntity(e) {
22283
22502
  sourceText: e.source_text ?? null
22284
22503
  };
22285
22504
  }
22505
+ function toRuleSeverity(severity) {
22506
+ switch (severity) {
22507
+ case "critical":
22508
+ case "major":
22509
+ case "minor":
22510
+ case "informational":
22511
+ return severity;
22512
+ default:
22513
+ return "informational";
22514
+ }
22515
+ }
22516
+ function toRuleStatus(status) {
22517
+ switch (status) {
22518
+ case "pass":
22519
+ case "fail":
22520
+ case "inconclusive":
22521
+ case "not_applicable":
22522
+ return status;
22523
+ default:
22524
+ return "inconclusive";
22525
+ }
22526
+ }
22286
22527
  function mapRuleResult(r) {
22287
22528
  return {
22288
22529
  ruleId: r.rule_id ?? "",
22289
22530
  ruleDescription: r.rule_description ?? "",
22290
22531
  ruleSort: r.rule_sort ?? "",
22291
- severity: r.severity ?? "informational",
22292
- status: r.status ?? "inconclusive",
22532
+ severity: toRuleSeverity(r.severity),
22533
+ status: toRuleStatus(r.status),
22293
22534
  confidence: r.confidence ?? 0,
22294
22535
  evidence: r.evidence ?? [],
22295
22536
  proofTrace: r.proof_trace ? r.proof_trace.map(mapProofStep) : null,
@@ -26539,11 +26780,112 @@ var FlowNetworksClient = class {
26539
26780
  };
26540
26781
 
26541
26782
  // src/normalizers/osfql.ts
26783
+ function isRecord(value) {
26784
+ return typeof value === "object" && value !== null && !Array.isArray(value);
26785
+ }
26786
+ function OsfqlValueFromApiToFront(value) {
26787
+ if (!isRecord(value)) {
26788
+ return void 0;
26789
+ }
26790
+ const payload = value["value"];
26791
+ switch (value["type"]) {
26792
+ case "null":
26793
+ return { type: "null" };
26794
+ case "integer":
26795
+ return typeof payload === "number" ? { type: "integer", value: payload } : void 0;
26796
+ case "float":
26797
+ return typeof payload === "number" ? { type: "float", value: payload } : void 0;
26798
+ case "string":
26799
+ return typeof payload === "string" ? { type: "string", value: payload } : void 0;
26800
+ case "boolean":
26801
+ return typeof payload === "boolean" ? { type: "boolean", value: payload } : void 0;
26802
+ case "term_ref":
26803
+ return typeof payload === "string" ? { type: "term_ref", value: payload } : void 0;
26804
+ case "list": {
26805
+ if (!Array.isArray(payload)) {
26806
+ return void 0;
26807
+ }
26808
+ const items = payload;
26809
+ const parsed = [];
26810
+ for (const item of items) {
26811
+ const element = OsfqlValueFromApiToFront(item);
26812
+ if (element === void 0) {
26813
+ return void 0;
26814
+ }
26815
+ parsed.push(element);
26816
+ }
26817
+ return { type: "list", value: parsed };
26818
+ }
26819
+ case "term": {
26820
+ const term = OsfqlTermValueFromApiToFront(payload);
26821
+ return term === void 0 ? void 0 : { type: "term", value: term };
26822
+ }
26823
+ default:
26824
+ return void 0;
26825
+ }
26826
+ }
26827
+ function OsfqlTermValueFromApiToFront(value) {
26828
+ if (!isRecord(value)) {
26829
+ return void 0;
26830
+ }
26831
+ const sort = value["sort"];
26832
+ if (typeof sort !== "string") {
26833
+ return void 0;
26834
+ }
26835
+ const features = OsfqlBindingFromApiToFront(value["features"]);
26836
+ return features === void 0 ? void 0 : { sort, features };
26837
+ }
26838
+ function OsfqlBindingFromApiToFront(value) {
26839
+ if (!isRecord(value)) {
26840
+ return void 0;
26841
+ }
26842
+ const out = {};
26843
+ for (const [name, raw] of Object.entries(value)) {
26844
+ const parsed = OsfqlValueFromApiToFront(raw);
26845
+ if (parsed === void 0) {
26846
+ return void 0;
26847
+ }
26848
+ out[name] = parsed;
26849
+ }
26850
+ return out;
26851
+ }
26852
+ function OsfqlBindingsFromApiToFront(value) {
26853
+ if (!Array.isArray(value)) {
26854
+ return void 0;
26855
+ }
26856
+ const rows = value;
26857
+ const out = [];
26858
+ for (const row of rows) {
26859
+ const parsed = OsfqlBindingFromApiToFront(row);
26860
+ if (parsed === void 0) {
26861
+ return void 0;
26862
+ }
26863
+ out.push(parsed);
26864
+ }
26865
+ return out;
26866
+ }
26867
+ function OsfqlRequestFromFrontToApi(model) {
26868
+ return {
26869
+ query: model.query,
26870
+ reactive: model.reactive
26871
+ };
26872
+ }
26542
26873
  function OsfqlResponseFromApiToFront(dto) {
26874
+ const bindings = OsfqlBindingsFromApiToFront(dto.bindings);
26875
+ if (bindings === void 0) {
26876
+ return void 0;
26877
+ }
26878
+ let fetched;
26879
+ if (dto.fetched !== void 0 && dto.fetched !== null) {
26880
+ fetched = OsfqlBindingsFromApiToFront(dto.fetched);
26881
+ if (fetched === void 0) {
26882
+ return void 0;
26883
+ }
26884
+ }
26543
26885
  return {
26544
26886
  success: dto.success,
26545
- bindings: dto.bindings,
26546
- fetched: dto.fetched,
26887
+ bindings,
26888
+ fetched,
26547
26889
  producedTermIds: dto.produced_term_ids,
26548
26890
  definedSortIds: dto.defined_sort_ids,
26549
26891
  diagnostics: dto.diagnostics,
@@ -26589,15 +26931,28 @@ var OsfqlClient = class {
26589
26931
  * Execute an OSFQL program.
26590
26932
  *
26591
26933
  * @param query - The OSFQL program text (one or more statements separated by `;`).
26934
+ * @param options - Optional execution options. Set `reactive` to fire suspended
26935
+ * `AWAIT` demons whose triggers the program has just satisfied.
26592
26936
  * @returns The execution result including variable bindings, produced term IDs,
26593
26937
  * defined sort IDs, diagnostics, and statement count.
26594
26938
  * @throws {ApiError} If the request fails.
26939
+ * @throws {ReasoningLayerError} If the server returns bindings that do not satisfy the
26940
+ * published {@link OsfqlValue} contract.
26595
26941
  *
26596
26942
  * @remarks
26597
26943
  * The query is parsed, compiled, and executed against the caller's tenant-isolated
26598
26944
  * knowledge base. Results include variable bindings from MATCH queries and IDs of
26599
26945
  * any terms or sorts created by INSERT, DERIVE, or DEFINE statements.
26600
26946
  *
26947
+ * Bindings use the **tagged** {@link OsfqlValue} format with lowercase `type`
26948
+ * discriminators — not the PascalCase `ValueDto` term-CRUD format.
26949
+ *
26950
+ * `reactive` opts into **reactive (streaming) mode**: once the program has run,
26951
+ * any suspended `AWAIT` demon whose trigger is now satisfied fires
26952
+ * automatically, with no explicit `RELEASE RESIDUATIONS` statement. It defaults
26953
+ * to `false` — demons stay suspended until an explicit RELEASE — so omitting it
26954
+ * leaves the request byte-identical to before.
26955
+ *
26601
26956
  * @example
26602
26957
  * ```typescript
26603
26958
  * // Insert a record and query it back
@@ -26608,11 +26963,27 @@ var OsfqlClient = class {
26608
26963
  * console.log(result.bindings); // [{ N: { type: "string", value: "Alice" } }]
26609
26964
  * console.log(result.producedTermIds); // ["<uuid>"]
26610
26965
  * console.log(result.statementCount); // 2
26966
+ *
26967
+ * // Let an AWAIT demon fire as soon as its trigger is satisfied
26968
+ * await client.osfql.execute('AWAIT person(name: "Bob");');
26969
+ * const reactive = await client.osfql.execute(
26970
+ * 'INSERT person(name: "Bob", age: 41);',
26971
+ * { reactive: true },
26972
+ * );
26973
+ * console.log(reactive.producedTermIds); // includes the demon's own output
26611
26974
  * ```
26612
26975
  */
26613
- async execute(query) {
26614
- const response = await this.api.executeOsfql({ query });
26615
- return OsfqlResponseFromApiToFront(response.data);
26976
+ async execute(query, options) {
26977
+ const response = await this.api.executeOsfql(
26978
+ OsfqlRequestFromFrontToApi({ query, reactive: options?.reactive })
26979
+ );
26980
+ const parsed = OsfqlResponseFromApiToFront(response.data);
26981
+ if (parsed === void 0) {
26982
+ throw new ReasoningLayerError(
26983
+ "osfql/execute returned bindings that do not match the published OsfqlValue contract (expected tagged values with a lowercase `type` discriminator)"
26984
+ );
26985
+ }
26986
+ return parsed;
26616
26987
  }
26617
26988
  /**
26618
26989
  * Diagnose an OSFQL program for contradictions and inconsistencies.
@@ -26699,7 +27070,9 @@ function ConversationMessageRequestFromFrontToApi(model) {
26699
27070
  conversation_id: model.conversationId,
26700
27071
  session_id: model.sessionId,
26701
27072
  current_sort_context: model.currentSortContext,
26702
- generate_certificate: model.generateCertificate
27073
+ generate_certificate: model.generateCertificate,
27074
+ constrained_decode: model.constrainedDecode,
27075
+ model: model.model
26703
27076
  };
26704
27077
  }
26705
27078
  function DerivationSummaryDtoFromApiToFront(dto) {
@@ -26807,7 +27180,12 @@ function ConversationMessageResponseFromApiToFront(dto) {
26807
27180
  cognitiveStrategy: dto.cognitive_strategy ? CognitiveStrategyDtoFromApiToFront(dto.cognitive_strategy) : void 0,
26808
27181
  reasoningTrace: dto.reasoning_trace ? ReasoningTraceDtoFromApiToFront(dto.reasoning_trace) : void 0,
26809
27182
  validityCertificateHash: dto.validity_certificate_hash ?? void 0,
26810
- validityCertificateId: dto.validity_certificate_id ?? void 0
27183
+ validityCertificateId: dto.validity_certificate_id ?? void 0,
27184
+ validityCertificateRuleProgramHash: dto.validity_certificate_rule_program_hash ?? void 0,
27185
+ validityCertificateRuleRevision: dto.validity_certificate_rule_revision ?? void 0,
27186
+ modelId: dto.model_id ?? void 0,
27187
+ prefillMs: dto.prefill_ms ?? void 0,
27188
+ tokensPerSec: dto.tokens_per_sec ?? void 0
26811
27189
  };
26812
27190
  }
26813
27191
  function TurnDtoFromApiToFront(dto) {
@@ -30653,12 +31031,16 @@ function PropertyGraphQueryRequestFromFrontToApi(model) {
30653
31031
  };
30654
31032
  }
30655
31033
  function PropertyGraphExecuteResponseFromApiToFront(dto) {
31034
+ const bindings = OsfqlBindingsFromApiToFront(dto.bindings);
31035
+ if (bindings === void 0) {
31036
+ return void 0;
31037
+ }
30656
31038
  return {
30657
31039
  success: dto.success,
30658
31040
  language: dto.language,
30659
31041
  operation: dto.operation,
30660
31042
  osfql: dto.osfql,
30661
- bindings: dto.bindings,
31043
+ bindings,
30662
31044
  producedTermIds: dto.produced_term_ids,
30663
31045
  definedSortIds: dto.defined_sort_ids,
30664
31046
  diagnostics: dto.diagnostics,
@@ -30676,13 +31058,27 @@ function PropertyGraphTranslateResponseFromApiToFront(dto) {
30676
31058
  }
30677
31059
 
30678
31060
  // src/resources/property-graph.ts
30679
- var PropertyGraphClient = class {
31061
+ var PropertyGraphClient = class _PropertyGraphClient {
30680
31062
  /** @internal */
30681
31063
  api;
30682
31064
  /** @internal */
30683
31065
  constructor(api) {
30684
31066
  this.api = api;
30685
31067
  }
31068
+ /**
31069
+ * Parse an execution response, failing loudly on a contract violation.
31070
+ *
31071
+ * @internal
31072
+ */
31073
+ static parseExecuteResponse(dto) {
31074
+ const parsed = PropertyGraphExecuteResponseFromApiToFront(dto);
31075
+ if (parsed === void 0) {
31076
+ throw new ReasoningLayerError(
31077
+ "the property-graph endpoint returned bindings that do not match the published PropertyGraphValue contract (expected tagged values with a lowercase `type` discriminator)"
31078
+ );
31079
+ }
31080
+ return parsed;
31081
+ }
30686
31082
  /**
30687
31083
  * Execute a Cypher query.
30688
31084
  *
@@ -30690,6 +31086,8 @@ var PropertyGraphClient = class {
30690
31086
  * @returns Execution result: bindings, the OSFQL program that ran, produced term IDs,
30691
31087
  * defined sort IDs, diagnostics, compatibility notes, and the statement count.
30692
31088
  * @throws {ApiError} If the query cannot be parsed, cannot be lowered to OSFQL, or fails to execute.
31089
+ * @throws {ReasoningLayerError} If the server returns bindings that do not satisfy the
31090
+ * published {@link PropertyGraphValue} contract.
30693
31091
  *
30694
31092
  * @remarks
30695
31093
  * The query is parsed as Cypher, lowered to OSFQL, and executed against the
@@ -30709,7 +31107,7 @@ var PropertyGraphClient = class {
30709
31107
  const response = await this.api.executeCypherPost(
30710
31108
  PropertyGraphQueryRequestFromFrontToApi({ query })
30711
31109
  );
30712
- return PropertyGraphExecuteResponseFromApiToFront(response.data);
31110
+ return _PropertyGraphClient.parseExecuteResponse(response.data);
30713
31111
  }
30714
31112
  /**
30715
31113
  * Execute a GQL (ISO/IEC 39075) query.
@@ -30718,6 +31116,8 @@ var PropertyGraphClient = class {
30718
31116
  * @returns Execution result: bindings, the OSFQL program that ran, produced term IDs,
30719
31117
  * defined sort IDs, diagnostics, compatibility notes, and the statement count.
30720
31118
  * @throws {ApiError} If the query cannot be parsed, cannot be lowered to OSFQL, or fails to execute.
31119
+ * @throws {ReasoningLayerError} If the server returns bindings that do not satisfy the
31120
+ * published {@link PropertyGraphValue} contract.
30721
31121
  *
30722
31122
  * @remarks
30723
31123
  * The query is parsed as GQL, lowered to OSFQL, and executed against the
@@ -30737,7 +31137,7 @@ var PropertyGraphClient = class {
30737
31137
  const response = await this.api.executeGqlPost(
30738
31138
  PropertyGraphQueryRequestFromFrontToApi({ query })
30739
31139
  );
30740
- return PropertyGraphExecuteResponseFromApiToFront(response.data);
31140
+ return _PropertyGraphClient.parseExecuteResponse(response.data);
30741
31141
  }
30742
31142
  /**
30743
31143
  * Execute a Gremlin traversal.
@@ -30746,6 +31146,8 @@ var PropertyGraphClient = class {
30746
31146
  * @returns Execution result: bindings, the OSFQL program that ran, produced term IDs,
30747
31147
  * defined sort IDs, diagnostics, compatibility notes, and the statement count.
30748
31148
  * @throws {ApiError} If the traversal cannot be parsed, cannot be lowered to OSFQL, or fails to execute.
31149
+ * @throws {ReasoningLayerError} If the server returns bindings that do not satisfy the
31150
+ * published {@link PropertyGraphValue} contract.
30749
31151
  *
30750
31152
  * @remarks
30751
31153
  * The traversal is parsed as Gremlin, lowered to OSFQL, and executed against the
@@ -30764,7 +31166,7 @@ var PropertyGraphClient = class {
30764
31166
  const response = await this.api.executeGremlinPost(
30765
31167
  PropertyGraphQueryRequestFromFrontToApi({ query })
30766
31168
  );
30767
- return PropertyGraphExecuteResponseFromApiToFront(response.data);
31169
+ return _PropertyGraphClient.parseExecuteResponse(response.data);
30768
31170
  }
30769
31171
  /**
30770
31172
  * Translate a Cypher query to OSFQL without executing it.
@@ -30850,14 +31252,14 @@ var PropertyGraphClient = class {
30850
31252
  };
30851
31253
 
30852
31254
  // src/normalizers/sparql.ts
30853
- function isRecord(value) {
31255
+ function isRecord2(value) {
30854
31256
  return typeof value === "object" && value !== null && !Array.isArray(value);
30855
31257
  }
30856
31258
  function isString(value) {
30857
31259
  return typeof value === "string";
30858
31260
  }
30859
31261
  function headVars(head) {
30860
- if (!isRecord(head)) {
31262
+ if (!isRecord2(head)) {
30861
31263
  throw new Error('Malformed SPARQL results: "head" is not an object');
30862
31264
  }
30863
31265
  const vars = head["vars"];
@@ -30870,7 +31272,7 @@ function headVars(head) {
30870
31272
  return vars;
30871
31273
  }
30872
31274
  function SparqlRdfTermFromApiToFront(raw) {
30873
- if (!isRecord(raw)) {
31275
+ if (!isRecord2(raw)) {
30874
31276
  throw new Error("Malformed SPARQL results: a solution binding is not an object");
30875
31277
  }
30876
31278
  const termType = raw["type"];
@@ -30895,7 +31297,7 @@ function SparqlRdfTermFromApiToFront(raw) {
30895
31297
  };
30896
31298
  }
30897
31299
  if (termType === "triple") {
30898
- if (!isRecord(value)) {
31300
+ if (!isRecord2(value)) {
30899
31301
  throw new Error('Malformed SPARQL results: "triple" binding has a non-object value');
30900
31302
  }
30901
31303
  return {
@@ -30912,7 +31314,7 @@ function SparqlRdfTermFromApiToFront(raw) {
30912
31314
  );
30913
31315
  }
30914
31316
  function SparqlBindingSetFromApiToFront(raw) {
30915
- if (!isRecord(raw)) {
31317
+ if (!isRecord2(raw)) {
30916
31318
  throw new Error("Malformed SPARQL results: a solution is not an object");
30917
31319
  }
30918
31320
  const bindings = {};
@@ -30922,7 +31324,7 @@ function SparqlBindingSetFromApiToFront(raw) {
30922
31324
  return bindings;
30923
31325
  }
30924
31326
  function bindingsFromResultSet(results) {
30925
- if (!isRecord(results)) {
31327
+ if (!isRecord2(results)) {
30926
31328
  throw new Error('Malformed SPARQL results: "results" is not an object');
30927
31329
  }
30928
31330
  const bindings = results["bindings"];
@@ -30954,7 +31356,7 @@ function SparqlEntailmentRegimeFromApiToFront(entailment) {
30954
31356
  }
30955
31357
  }
30956
31358
  function SparqlQueryResultsFromApiToFront(raw) {
30957
- if (!isRecord(raw)) {
31359
+ if (!isRecord2(raw)) {
30958
31360
  throw new Error(
30959
31361
  "Malformed SPARQL results: the response body is not a SPARQL 1.1 Query Results JSON document (a CONSTRUCT or DESCRIBE query answers with an RDF graph document instead)"
30960
31362
  );
@@ -30981,7 +31383,7 @@ function GraphSparqlQueryRequestFromFrontToApi(model) {
30981
31383
  };
30982
31384
  }
30983
31385
  function GraphSparqlResultsFromApiToFront(raw) {
30984
- if (!isRecord(raw)) {
31386
+ if (!isRecord2(raw)) {
30985
31387
  throw new Error(
30986
31388
  "Malformed SPARQL results: the co-located store response is not a SPARQL 1.1 Query Results JSON document"
30987
31389
  );
@@ -31269,6 +31671,38 @@ var SparqlClient = class {
31269
31671
  };
31270
31672
 
31271
31673
  // src/normalizers/osf-diff.ts
31674
+ function TermSetSelectorFromFrontToApi(selector) {
31675
+ switch (selector.type) {
31676
+ case "document":
31677
+ return { type: "document", document_id: selector.documentId };
31678
+ case "document_version":
31679
+ return { type: "document_version", document_id: selector.documentId };
31680
+ case "collection":
31681
+ return { type: "collection", path: selector.path };
31682
+ case "term_ids":
31683
+ return { type: "term_ids", ids: selector.ids };
31684
+ case "sort":
31685
+ return {
31686
+ type: "sort",
31687
+ sort_name: selector.sortName,
31688
+ include_descendants: selector.includeDescendants
31689
+ };
31690
+ case "query":
31691
+ return { type: "query", osfql: selector.osfql };
31692
+ case "snapshot":
31693
+ return {
31694
+ type: "snapshot",
31695
+ snapshot_id: selector.snapshotId,
31696
+ filter: selector.filter === void 0 ? void 0 : TermSetSelectorFromFrontToApi(selector.filter)
31697
+ };
31698
+ case "as_of":
31699
+ return {
31700
+ type: "as_of",
31701
+ at: selector.at,
31702
+ filter: selector.filter === void 0 ? void 0 : TermSetSelectorFromFrontToApi(selector.filter)
31703
+ };
31704
+ }
31705
+ }
31272
31706
  function TemporalPointFromFrontToApi(model) {
31273
31707
  return {
31274
31708
  at: model.at,
@@ -31277,8 +31711,8 @@ function TemporalPointFromFrontToApi(model) {
31277
31711
  }
31278
31712
  function OsfDiffRequestFromFrontToApi(model) {
31279
31713
  return {
31280
- a: model.a,
31281
- b: model.b,
31714
+ a: TermSetSelectorFromFrontToApi(model.a),
31715
+ b: TermSetSelectorFromFrontToApi(model.b),
31282
31716
  include_clause_diff: model.includeClauseDiff,
31283
31717
  include_entity_diff: model.includeEntityDiff,
31284
31718
  threshold: model.threshold
@@ -31292,7 +31726,7 @@ function OsfDiffResponseFromApiToFront(dto) {
31292
31726
  function OsfDiffSequenceRequestFromFrontToApi(model) {
31293
31727
  return {
31294
31728
  document_family_id: model.documentFamilyId,
31295
- selectors: model.selectors,
31729
+ selectors: model.selectors?.map(TermSetSelectorFromFrontToApi),
31296
31730
  threshold: model.threshold
31297
31731
  };
31298
31732
  }
@@ -31303,7 +31737,7 @@ function OsfDiffSequenceResponseFromApiToFront(dto) {
31303
31737
  }
31304
31738
  function OsfDiffTemporalRequestFromFrontToApi(model) {
31305
31739
  return {
31306
- filter: model.filter,
31740
+ filter: model.filter === void 0 ? void 0 : TermSetSelectorFromFrontToApi(model.filter),
31307
31741
  from: TemporalPointFromFrontToApi(model.from),
31308
31742
  to: TemporalPointFromFrontToApi(model.to),
31309
31743
  threshold: model.threshold
@@ -31338,13 +31772,14 @@ var OsfDiffClient = class {
31338
31772
  * Entities are matched by OSF unification; `threshold` (default 0.7) is the
31339
31773
  * minimum match degree at which two entities are considered the same. Set
31340
31774
  * `includeClauseDiff` / `includeEntityDiff` to control which deltas the report
31341
- * carries. Selectors and the report are opaque wire-format JSON objects.
31775
+ * carries. Each side is a typed {@link OsfDiffSelector}; the report is an opaque
31776
+ * wire-format JSON object.
31342
31777
  *
31343
31778
  * @example
31344
31779
  * ```typescript
31345
31780
  * const result = await client.osfDiff.diff({
31346
- * a: { type: 'document', document_id: 'a1b2c3d4-...' },
31347
- * b: { type: 'document', document_id: 'e5f6a7b8-...' },
31781
+ * a: { type: 'document', documentId: 'a1b2c3d4-...' },
31782
+ * b: { type: 'document', documentId: 'e5f6a7b8-...' },
31348
31783
  * includeClauseDiff: true,
31349
31784
  * threshold: 0.8,
31350
31785
  * });
@@ -31404,7 +31839,7 @@ var OsfDiffClient = class {
31404
31839
  * const result = await client.osfDiff.diffTemporal({
31405
31840
  * from: { at: '2026-01-01T00:00:00Z' },
31406
31841
  * to: {}, // live
31407
- * filter: { type: 'document', document_id: 'a1b2c3d4-...' },
31842
+ * filter: { type: 'document', documentId: 'a1b2c3d4-...' },
31408
31843
  * });
31409
31844
  * console.log(result.report);
31410
31845
  * ```
@@ -31777,13 +32212,22 @@ function SatSolverStatsDtoFromApiToFront(dto) {
31777
32212
  }
31778
32213
  function modelFromApiToFront(raw) {
31779
32214
  if (!Array.isArray(raw)) {
31780
- return [];
32215
+ throw new ValidationError(
32216
+ "SAT solver returned a 'satisfiable' verdict without a model; the endpoint contract requires one. Refusing to report an assignment the solver did not give.",
32217
+ "model"
32218
+ );
31781
32219
  }
32220
+ const entries = raw;
31782
32221
  const model = [];
31783
- for (const entry of raw) {
31784
- if (typeof entry === "boolean") {
31785
- model.push(entry);
32222
+ for (let index = 0; index < entries.length; index += 1) {
32223
+ const entry = entries[index];
32224
+ if (typeof entry !== "boolean") {
32225
+ throw new ValidationError(
32226
+ `SAT model entry at index ${index} is ${typeof entry}, not a Boolean. The assignment vector is positional, so this entry cannot be dropped without corrupting every later variable.`,
32227
+ "model"
32228
+ );
31786
32229
  }
32230
+ model.push(entry);
31787
32231
  }
31788
32232
  return model;
31789
32233
  }
@@ -31834,12 +32278,19 @@ var SatClient = class {
31834
32278
  * Solver statistics are attached to every branch.
31835
32279
  * @throws {ApiError} If the request fails (e.g. a literal references a variable
31836
32280
  * index `>= numVars`, or a clause is empty).
32281
+ * @throws {ValidationError} If a `satisfiable` verdict arrives without a
32282
+ * well-formed Boolean model, which violates the endpoint contract.
31837
32283
  *
31838
32284
  * @remarks
31839
32285
  * Narrow on `result` to reach the model — it exists only on the `satisfiable`
31840
32286
  * branch. `maxConflicts: 0` (the default) means an unlimited budget, in which
31841
32287
  * case `unknown` cannot be returned.
31842
32288
  *
32289
+ * The model is index-aligned with the variables (`model[i]` is the value of
32290
+ * variable `i`). A `satisfiable` response whose model is missing or holds a
32291
+ * non-Boolean is reported as a {@link ValidationError} rather than silently
32292
+ * shortened — dropping an entry would shift every later variable's assignment.
32293
+ *
31843
32294
  * Plain JSON serialization: literals are `{ var, negated }` objects and the
31844
32295
  * model is a `boolean[]` indexed by variable number. No tagged `ValueDto` or
31845
32296
  * untagged `FeatureValueDto` encoding is used.
@@ -31891,12 +32342,12 @@ function EqLiteralDtoFromFrontToApi(model) {
31891
32342
  negated: model.negated
31892
32343
  };
31893
32344
  }
31894
- function isRecord2(value) {
32345
+ function isRecord3(value) {
31895
32346
  return typeof value === "object" && value !== null;
31896
32347
  }
31897
32348
  function assignmentsFromApiToFront(raw) {
31898
32349
  const assignments = {};
31899
- if (!isRecord2(raw)) {
32350
+ if (!isRecord3(raw)) {
31900
32351
  return assignments;
31901
32352
  }
31902
32353
  for (const [key, value] of Object.entries(raw)) {
@@ -32098,7 +32549,9 @@ var ChaseClient = class {
32098
32549
  * ```
32099
32550
  */
32100
32551
  async run(request) {
32101
- const response = await this.api.runChase(ChaseRunRequestFromFrontToApi(request));
32552
+ const response = await this.api.runChase(ChaseRunRequestFromFrontToApi(request), {
32553
+ headers: { [RAW_BODY_HEADER]: "1" }
32554
+ });
32102
32555
  return ChaseRunResponseFromApiToFront(response.data);
32103
32556
  }
32104
32557
  };
@@ -32228,7 +32681,7 @@ var ConformanceClient = class {
32228
32681
  };
32229
32682
 
32230
32683
  // src/normalizers/temporal.ts
32231
- function isRecord3(value) {
32684
+ function isRecord4(value) {
32232
32685
  return typeof value === "object" && value !== null && !Array.isArray(value);
32233
32686
  }
32234
32687
  function asNumber(value) {
@@ -32288,38 +32741,6 @@ function TemporalModelCheckResponseFromApiToFront(dto) {
32288
32741
  counterexample
32289
32742
  };
32290
32743
  }
32291
- function TermSetSelectorFromFrontToApi(selector) {
32292
- switch (selector.type) {
32293
- case "document":
32294
- return { type: "document", document_id: selector.documentId };
32295
- case "document_version":
32296
- return { type: "document_version", document_id: selector.documentId };
32297
- case "collection":
32298
- return { type: "collection", path: selector.path };
32299
- case "term_ids":
32300
- return { type: "term_ids", ids: selector.ids };
32301
- case "sort":
32302
- return {
32303
- type: "sort",
32304
- sort_name: selector.sortName,
32305
- include_descendants: selector.includeDescendants
32306
- };
32307
- case "query":
32308
- return { type: "query", osfql: selector.osfql };
32309
- case "snapshot":
32310
- return {
32311
- type: "snapshot",
32312
- snapshot_id: selector.snapshotId,
32313
- filter: selector.filter === void 0 ? void 0 : TermSetSelectorFromFrontToApi(selector.filter)
32314
- };
32315
- case "as_of":
32316
- return {
32317
- type: "as_of",
32318
- at: selector.at,
32319
- filter: selector.filter === void 0 ? void 0 : TermSetSelectorFromFrontToApi(selector.filter)
32320
- };
32321
- }
32322
- }
32323
32744
  function TemporalSeriesSpecFromFrontToApi(spec) {
32324
32745
  const time = spec.time.kind === "date_time_feature" ? { kind: "date_time_feature", name: spec.time.name } : { kind: "epoch_feature", name: spec.time.name, unit: spec.time.unit };
32325
32746
  const value = spec.value.kind === "feature" ? { kind: "feature", name: spec.value.name } : { kind: "count" };
@@ -32356,7 +32777,7 @@ function TemporalSeriesRequestFromFrontToApi(model) {
32356
32777
  };
32357
32778
  }
32358
32779
  function TemporalSeriesPointFromApiToFront(value) {
32359
- if (!isRecord3(value)) {
32780
+ if (!isRecord4(value)) {
32360
32781
  return void 0;
32361
32782
  }
32362
32783
  const bucketStart = asNumber(value["bucket_start"]);
@@ -32374,7 +32795,7 @@ function TemporalSeriesPointFromApiToFront(value) {
32374
32795
  };
32375
32796
  }
32376
32797
  function TemporalTrendSummaryFromApiToFront(value) {
32377
- if (!isRecord3(value)) {
32798
+ if (!isRecord4(value)) {
32378
32799
  return void 0;
32379
32800
  }
32380
32801
  const slopePerMs = asNumber(value["slope_per_ms"]);
@@ -32389,7 +32810,7 @@ function TemporalTrendSummaryFromApiToFront(value) {
32389
32810
  return { slopePerMs, intercept, first, last, delta, n };
32390
32811
  }
32391
32812
  function TemporalSeriesFromApiToFront(value) {
32392
- if (!isRecord3(value)) {
32813
+ if (!isRecord4(value)) {
32393
32814
  return void 0;
32394
32815
  }
32395
32816
  const rawPoints = value["points"];
@@ -32536,7 +32957,7 @@ var TemporalClient = class {
32536
32957
  };
32537
32958
 
32538
32959
  // src/normalizers/forecast.ts
32539
- function isRecord4(value) {
32960
+ function isRecord5(value) {
32540
32961
  return typeof value === "object" && value !== null && !Array.isArray(value);
32541
32962
  }
32542
32963
  function asNumber2(value) {
@@ -32589,7 +33010,7 @@ function ForecastRequestFromFrontToApi(model) {
32589
33010
  };
32590
33011
  }
32591
33012
  function CompetitorForecastFromApiToFront(value) {
32592
- if (!isRecord4(value)) {
33013
+ if (!isRecord5(value)) {
32593
33014
  return void 0;
32594
33015
  }
32595
33016
  const id = asString(value["id"]);
@@ -32601,7 +33022,7 @@ function CompetitorForecastFromApiToFront(value) {
32601
33022
  return { id, pWin, pTopK };
32602
33023
  }
32603
33024
  function OrderedComboFromApiToFront(value) {
32604
- if (!isRecord4(value)) {
33025
+ if (!isRecord5(value)) {
32605
33026
  return void 0;
32606
33027
  }
32607
33028
  const members = asStringArray(value["members"]);
@@ -32612,7 +33033,7 @@ function OrderedComboFromApiToFront(value) {
32612
33033
  return { members, probability };
32613
33034
  }
32614
33035
  function ForecastCoveringSetFromApiToFront(value) {
32615
- if (!isRecord4(value)) {
33036
+ if (!isRecord5(value)) {
32616
33037
  return void 0;
32617
33038
  }
32618
33039
  const members = asStringArray(value["members"]);
@@ -32625,7 +33046,7 @@ function ForecastCoveringSetFromApiToFront(value) {
32625
33046
  return { members, alpha, slice, sliceFallback };
32626
33047
  }
32627
33048
  function RankedInstrumentFromApiToFront(value) {
32628
- if (!isRecord4(value)) {
33049
+ if (!isRecord5(value)) {
32629
33050
  return void 0;
32630
33051
  }
32631
33052
  const id = asString(value["id"]);
@@ -32645,7 +33066,7 @@ function RankedInstrumentFromApiToFront(value) {
32645
33066
  return { id, score, rank, interval };
32646
33067
  }
32647
33068
  function ForecastBodyFromApiToFront(value) {
32648
- if (!isRecord4(value)) {
33069
+ if (!isRecord5(value)) {
32649
33070
  return void 0;
32650
33071
  }
32651
33072
  const shape = value["shape"];
@@ -32699,7 +33120,7 @@ function ForecastBodyFromApiToFront(value) {
32699
33120
  return void 0;
32700
33121
  }
32701
33122
  function ForecastCertificateFromApiToFront(value) {
32702
- if (!isRecord4(value)) {
33123
+ if (!isRecord5(value)) {
32703
33124
  return void 0;
32704
33125
  }
32705
33126
  const modelFingerprint = asString(value["model_fingerprint"]);
@@ -32718,7 +33139,7 @@ function ForecastCertificateFromApiToFront(value) {
32718
33139
  };
32719
33140
  }
32720
33141
  function CertifiedForecastFromApiToFront(value) {
32721
- if (!isRecord4(value)) {
33142
+ if (!isRecord5(value)) {
32722
33143
  return void 0;
32723
33144
  }
32724
33145
  const outcome = value["outcome"];
@@ -32995,7 +33416,9 @@ var DlClient = class {
32995
33416
  * ```
32996
33417
  */
32997
33418
  async satisfiable(request) {
32998
- const response = await this.api.satisfiable(DlSatisfiableRequestFromFrontToApi(request));
33419
+ const response = await this.api.satisfiable(DlSatisfiableRequestFromFrontToApi(request), {
33420
+ headers: { [RAW_BODY_HEADER]: "1" }
33421
+ });
32999
33422
  return DlSatisfiableResponseFromApiToFront(response.data);
33000
33423
  }
33001
33424
  /**
@@ -33031,7 +33454,9 @@ var DlClient = class {
33031
33454
  * ```
33032
33455
  */
33033
33456
  async subsumes(request) {
33034
- const response = await this.api.subsumes(DlSubsumesRequestFromFrontToApi(request));
33457
+ const response = await this.api.subsumes(DlSubsumesRequestFromFrontToApi(request), {
33458
+ headers: { [RAW_BODY_HEADER]: "1" }
33459
+ });
33035
33460
  return DlSubsumesResponseFromApiToFront(response.data);
33036
33461
  }
33037
33462
  };
@@ -33788,21 +34213,50 @@ var OntologyExportClient = class {
33788
34213
  constructor(api) {
33789
34214
  this.api = api;
33790
34215
  }
34216
+ /**
34217
+ * Issue a content-negotiated export request and project the response.
34218
+ *
34219
+ * @internal
34220
+ * @remarks
34221
+ * Goes through the transport directly rather than through the generated route
34222
+ * methods: `root` is repeatable server-side (`?root=a&root=b`), but utoipa
34223
+ * cannot express a repeated query parameter, so the generated routes type it as
34224
+ * a lone `root?: string` — narrower than the endpoint each route's own
34225
+ * "(repeatable)" doc comment describes. The transport's query serializer
34226
+ * already branches on `Array.isArray` and emits the repeats correctly.
34227
+ */
34228
+ async requestExport(path, options) {
34229
+ const response = await this.api.http.request({
34230
+ path,
34231
+ method: "GET",
34232
+ query: OntologyExportQueryFromFrontToApi(options),
34233
+ secure: true,
34234
+ headers: { Accept: OntologyExportAcceptFromFrontToApi(options?.format) }
34235
+ });
34236
+ const document = await response.text();
34237
+ return OntologyExportDocumentFromApiToFront(
34238
+ response.headers.get("content-type"),
34239
+ document
34240
+ );
34241
+ }
33791
34242
  /**
33792
34243
  * Export the tenant's sort lattice (or a sub-lattice) as an OWL ontology.
33793
34244
  *
33794
34245
  * @param options - Export options: the base IRI for synthesized IRIs, the root
33795
- * sort to restrict the export to, and the serialization to negotiate on.
34246
+ * sort (or sorts) to restrict the export to, and the serialization to
34247
+ * negotiate on.
33796
34248
  * @returns The exported document, verbatim, with the media type the server
33797
34249
  * answered with.
33798
34250
  * @throws {BadRequestError} If the base IRI is invalid or the query is malformed.
33799
- * @throws {NotFoundError} If the requested root sort does not exist.
34251
+ * @throws {NotFoundError} If a requested root sort does not exist.
33800
34252
  * @throws {ApiError} If the request otherwise fails.
33801
34253
  *
33802
34254
  * @remarks
33803
34255
  * Omit `root` to export the whole tenant schema. Omit `base` to let the backend
33804
34256
  * synthesize IRIs under `urn:osfkb:tenant:{tenant_id}`.
33805
34257
  *
34258
+ * `root` is repeatable: pass an array to export several sub-lattices at once.
34259
+ *
33806
34260
  * `format` selects the `Accept` header: an RDF serialization yields an RDF
33807
34261
  * document, and the default (`'json'`) yields the backend's JSON rendering as
33808
34262
  * JSON text — parse it with `JSON.parse` when you need the object.
@@ -33815,36 +34269,35 @@ var OntologyExportClient = class {
33815
34269
  * format: 'turtle',
33816
34270
  * });
33817
34271
  *
33818
- * console.log(owl.contentType); // 'text/turtle'
34272
+ * console.log(owl.contentType); // 'text/turtle; charset=utf-8'
33819
34273
  * console.log(owl.document); // '@prefix : <https://example.org/ontology#> ...'
34274
+ *
34275
+ * // Several sub-lattices in one export -> ?root=clinical_entity&root=administrative_entity
34276
+ * const both = await client.ontologyExport.exportOwl({
34277
+ * root: ['clinical_entity', 'administrative_entity'],
34278
+ * });
33820
34279
  * ```
33821
34280
  */
33822
34281
  async exportOwl(options) {
33823
- const response = await this.api.exportOntologyOwl(
33824
- OntologyExportQueryFromFrontToApi(options),
33825
- { headers: { Accept: OntologyExportAcceptFromFrontToApi(options?.format) } }
33826
- );
33827
- const document = await response.text();
33828
- return OntologyExportDocumentFromApiToFront(
33829
- response.headers.get("content-type"),
33830
- document
33831
- );
34282
+ return this.requestExport("/api/v1/ontology/export/owl", options);
33832
34283
  }
33833
34284
  /**
33834
34285
  * Export the tenant's schema constraints (or those of a sub-lattice) as SHACL
33835
34286
  * shapes.
33836
34287
  *
33837
34288
  * @param options - Export options: the base IRI for synthesized IRIs, the root
33838
- * sort to restrict the export to, and the serialization to negotiate on.
34289
+ * sort (or sorts) to restrict the export to, and the serialization to
34290
+ * negotiate on.
33839
34291
  * @returns The exported document, verbatim, with the media type the server
33840
34292
  * answered with.
33841
34293
  * @throws {BadRequestError} If the base IRI is invalid or the query is malformed.
33842
- * @throws {NotFoundError} If the requested root sort does not exist.
34294
+ * @throws {NotFoundError} If a requested root sort does not exist.
33843
34295
  * @throws {ApiError} If the request otherwise fails.
33844
34296
  *
33845
34297
  * @remarks
33846
34298
  * Each exported shape targets one sort and constrains its features. Omit `root`
33847
- * to export the whole tenant schema.
34299
+ * to export the whole tenant schema; pass an array to export the shapes of
34300
+ * several sub-lattices at once.
33848
34301
  *
33849
34302
  * `format` selects the `Accept` header: an RDF serialization yields an RDF
33850
34303
  * document, and the default (`'json'`) yields the backend's JSON rendering of
@@ -33854,20 +34307,12 @@ var OntologyExportClient = class {
33854
34307
  * ```typescript
33855
34308
  * const shacl = await client.ontologyExport.exportShacl({ format: 'turtle' });
33856
34309
  *
33857
- * console.log(shacl.contentType); // 'text/turtle'
34310
+ * console.log(shacl.contentType); // 'text/turtle; charset=utf-8'
33858
34311
  * console.log(shacl.document); // '... sh:NodeShape ...'
33859
34312
  * ```
33860
34313
  */
33861
34314
  async exportShacl(options) {
33862
- const response = await this.api.exportOntologyShacl(
33863
- OntologyExportQueryFromFrontToApi(options),
33864
- { headers: { Accept: OntologyExportAcceptFromFrontToApi(options?.format) } }
33865
- );
33866
- const document = await response.text();
33867
- return OntologyExportDocumentFromApiToFront(
33868
- response.headers.get("content-type"),
33869
- document
33870
- );
34315
+ return this.requestExport("/api/v1/ontology/export/shacl", options);
33871
34316
  }
33872
34317
  };
33873
34318