@kortexya/reasoninglayer 4.0.0 → 4.2.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.js CHANGED
@@ -5,7 +5,7 @@ var __export = (target, all) => {
5
5
  };
6
6
 
7
7
  // src/config.ts
8
- var SDK_VERSION = "4.0.0";
8
+ var SDK_VERSION = "4.2.0";
9
9
  function resolveConfig(config) {
10
10
  if (!config.baseUrl) {
11
11
  throw new Error("ClientConfig.baseUrl is required");
@@ -2530,7 +2530,7 @@ var Inference = class {
2530
2530
  ...params
2531
2531
  });
2532
2532
  /**
2533
- * @description # The disposition is the caller's `?derivations=refuse` (the default) refuses while the rule still supports materialized conclusions and says how many; `?derivations=retract` withdraws them with it and reports the counts. A delete that silently drops derivations is as wrong as one that silently keeps them, so neither is the unnamed default. # Authorization Requires `X-Tenant-Id`. Runs the same delete guard as `DELETE /api/v1/terms/{id}` — a rule is a policy-relevant object, and withdrawing one changes what the engine will conclude. Honours `If-Match` against the conclusion's content ETag, and requires it under `OSFKB_REQUIRE_IF_MATCH=1`. Every request is captured by the audit middleware.
2533
+ * @description # The disposition is the caller's `?derivations=refuse` (the default) refuses while the rule still supports materialized conclusions and says how many; `?derivations=retract` withdraws them with it and reports the counts. A delete that silently drops derivations is as wrong as one that silently keeps them, so neither is the unnamed default. # Authorization Requires `X-Tenant-Id`. Runs the same delete guard as `DELETE /api/v1/terms/{id}` — a rule is a policy-relevant object, and withdrawing one changes what the engine will conclude. Honours `If-Match` against the conclusion's content ETag — the tag [`rule_content_tag`] publishes on the rule routes (#473) — and requires it under `OSFKB_REQUIRE_IF_MATCH=1`. Every request is captured by the audit middleware.
2534
2534
  *
2535
2535
  * @tags inference
2536
2536
  * @name DeleteRule
@@ -11005,7 +11005,7 @@ var Ui = class {
11005
11005
  ...params
11006
11006
  });
11007
11007
  /**
11008
- * @description Events: - `layout_ready` — LayoutSurface JSON - `component_ready` — {slot_id, descriptor} JSON - `data_chunk` — {slot_id, data} JSON (if data was loaded) - `complete` — {} POST /api/v1/ui/describe/stream
11008
+ * @description Events: - `layout_ready` — LayoutSurface JSON - `component_ready` — {slot_id, descriptor} JSON - `data_chunk` — {slot_id, data} JSON (if data was loaded) - `data_load_error` — {slot_id, error} JSON (if the data load failed; the error carries the typed `code`, `message` and `query`, #475) - `complete` — {} POST /api/v1/ui/describe/stream
11009
11009
  *
11010
11010
  * @tags ui
11011
11011
  * @name DescribeUiStream
@@ -17784,6 +17784,7 @@ var RESPONSE_COMPONENTS = {
17784
17784
  injection: [2, "InjectionSummaryDto"],
17785
17785
  intent: [1, 0],
17786
17786
  matched_templates: [2, { array: "QueryTemplateDto" }],
17787
+ notices: [1, { array: 0 }],
17787
17788
  produced_term_ids: [1, { array: 0 }],
17788
17789
  prompt_trace: [2, "PromptTraceDto"],
17789
17790
  proof_trace: [2, "ProofTraceNodeDto"],
@@ -17967,6 +17968,7 @@ var RESPONSE_COMPONENTS = {
17967
17968
  explanation: [1, 0]
17968
17969
  }
17969
17970
  },
17971
+ DataLoadErrorDto: { object: { code: [1, 0], message: [1, 0], query: [1, 0] } },
17970
17972
  DataMixingStatsDto: {
17971
17973
  object: {
17972
17974
  negative_count: [1, 0],
@@ -18436,6 +18438,7 @@ var RESPONSE_COMPONENTS = {
18436
18438
  chunks_processed: [1, 0],
18437
18439
  document_id: [1, 0],
18438
18440
  entities_extracted: [1, 0],
18441
+ entities_refused: [1, { array: "RefusedEntityDto" }],
18439
18442
  processing_time_ms: [1, 0],
18440
18443
  relations_extracted: [1, 0],
18441
18444
  relations_integrated: [1, 0],
@@ -21267,9 +21270,11 @@ var RESPONSE_COMPONENTS = {
21267
21270
  }
21268
21271
  },
21269
21272
  PromptTraceDto: { object: { llm_context: [1, "LlmContextTraceDto"], system_prompt: [1, 0] } },
21273
+ ProofConclusionDto: { object: { features: [1, { object: {} }], sort_id: [1, 0] } },
21270
21274
  ProofDto: {
21271
21275
  object: {
21272
21276
  certainty: [1, 0],
21277
+ conclusion: [0, "ProofConclusionDto"],
21273
21278
  kind: [1, 0],
21274
21279
  subproofs: [0, { array: "ProofDto" }],
21275
21280
  substitution: [1, "HomoiconicSubstitutionDto"]
@@ -22338,6 +22343,7 @@ var RESPONSE_COMPONENTS = {
22338
22343
  SolutionDto: {
22339
22344
  object: {
22340
22345
  certainty: [1, 0],
22346
+ conclusion: [2, "ProofConclusionDto"],
22341
22347
  matched_sorts: [0, { array: 0 }],
22342
22348
  proof: [2, "ProofDto"],
22343
22349
  residuated_sorts: [0, { array: 0 }],
@@ -23060,6 +23066,7 @@ var RESPONSE_COMPONENTS = {
23060
23066
  UIAssemblyStatsDto: {
23061
23067
  object: {
23062
23068
  component_count: [1, 0],
23069
+ data_load_error: [2, "DataLoadErrorDto"],
23063
23070
  included_features: [1, 0],
23064
23071
  sort_name: [1, 0],
23065
23072
  total_features: [1, 0],
@@ -23098,6 +23105,7 @@ var RESPONSE_COMPONENTS = {
23098
23105
  UIGenerateResponse: {
23099
23106
  object: {
23100
23107
  data: [2, "DataPayloadDto"],
23108
+ data_load_errors: [0, { array: "DataLoadErrorDto" }],
23101
23109
  data_sources: [0, { array: "DataSourcePayloadDto" }],
23102
23110
  descriptor: [2, "UIDescriptorDto"],
23103
23111
  diagnostics: [0, { array: 0 }],
@@ -24786,6 +24794,11 @@ var RESPONSE_OPERATIONS = {
24786
24794
  path: "/api/v1/constraint-sessions/{session_id}",
24787
24795
  responses: { 200: "ConstraintSessionStatusResponse" }
24788
24796
  },
24797
+ getConversation: {
24798
+ method: "GET",
24799
+ path: "/api/v1/conversation/{id}",
24800
+ responses: { 200: "ConversationSummaryDto" }
24801
+ },
24789
24802
  getConversationEntries: {
24790
24803
  method: "GET",
24791
24804
  path: "/api/v1/audit/entries/{conversation_id}",
@@ -28614,10 +28627,11 @@ var TermsClient = class {
28614
28627
  * `etag` is optional in every case, not only for `asOf`. A historical read
28615
28628
  * carries none (a past state is not a representation `If-Match` can guard,
28616
28629
  * and a client that could capture one could overwrite the present with the
28617
- * past), and neither does a rule's conclusion or a term answered straight
28618
- * from durable storage. A rule's id is its conclusion term's id, so
28619
- * `getTerm(ruleId).etag` is the tag {@link InferenceClient.deleteRule} and
28620
- * {@link InferenceClient.replaceRule} take as `ifMatch`.
28630
+ * past), and neither does a term answered straight from durable storage.
28631
+ * A rule's id answers 404 here; read the tag
28632
+ * {@link InferenceClient.deleteRule} and {@link InferenceClient.replaceRule}
28633
+ * take as `ifMatch` from the rule routes ({@link AddRuleResponse.etag},
28634
+ * {@link RuleEntryDto.etag}).
28621
28635
  *
28622
28636
  * @example
28623
28637
  * ```typescript
@@ -29293,6 +29307,14 @@ function HomoiconicSubstitutionDtoFromApiToFront(dto) {
29293
29307
  bindings: dto.bindings.map(BindingDtoFromApiToFront)
29294
29308
  };
29295
29309
  }
29310
+ function ProofConclusionDtoFromApiToFront(dto) {
29311
+ return {
29312
+ features: featuresFromApiToFront(dto.features),
29313
+ sortId: dto.sort_id,
29314
+ sortName: dto.sort_name ?? void 0,
29315
+ termId: dto.term_id ?? void 0
29316
+ };
29317
+ }
29296
29318
  function ProofDtoFromApiToFront(dto) {
29297
29319
  return {
29298
29320
  kind: dto.kind,
@@ -29300,6 +29322,7 @@ function ProofDtoFromApiToFront(dto) {
29300
29322
  ruleTermId: dto.rule_term_id,
29301
29323
  ruleHeadTermId: dto.rule_head_term_id,
29302
29324
  goalDisplay: dto.goal_display,
29325
+ conclusion: dto.conclusion ? ProofConclusionDtoFromApiToFront(dto.conclusion) : void 0,
29303
29326
  ruleLabel: dto.rule_label,
29304
29327
  substitution: HomoiconicSubstitutionDtoFromApiToFront(dto.substitution),
29305
29328
  subproofs: dto.subproofs?.map(ProofDtoFromApiToFront),
@@ -29353,6 +29376,7 @@ function SolutionDtoFromApiToFront(dto) {
29353
29376
  const solution = {
29354
29377
  substitution: HomoiconicSubstitutionDtoFromApiToFront(dto.substitution),
29355
29378
  proof: dto.proof ? ProofDtoFromApiToFront(dto.proof) : void 0,
29379
+ conclusion: dto.conclusion ? ProofConclusionDtoFromApiToFront(dto.conclusion) : void 0,
29356
29380
  certainty: dto.certainty,
29357
29381
  evidenceMatched: dto.evidence_matched ?? void 0,
29358
29382
  evidenceRatio: dto.evidence_ratio ?? void 0,
@@ -29599,6 +29623,7 @@ function RuleEntryDtoFromApiToFront(dto) {
29599
29623
  if (dto.aggregator !== void 0 && dto.aggregator !== null) {
29600
29624
  entry.aggregator = RuleAggregatorDtoFromApiToFront(dto.aggregator);
29601
29625
  }
29626
+ if (dto.etag !== void 0 && dto.etag !== null) entry.etag = dto.etag;
29602
29627
  if (dto.osfql !== void 0 && dto.osfql !== null) entry.osfql = dto.osfql;
29603
29628
  return entry;
29604
29629
  }
@@ -30050,7 +30075,10 @@ var InferenceClient = class {
30050
30075
  *
30051
30076
  * @param request - Rule definition using TermInputDto. Set `aggregator` to declare an
30052
30077
  * engine-side head aggregator (see {@link RuleAggregatorDto}).
30053
- * @returns The created rule wrapped in an AddRuleResponse.
30078
+ * @returns The created rule wrapped in an AddRuleResponse, with its
30079
+ * {@link AddRuleResponse.etag} when the engine sends the `ETag` header.
30080
+ * @throws {@link ValidationError} before the request is sent, when `antecedents` is
30081
+ * not an array (a request built from untyped data) — `field` is `antecedents`.
30054
30082
  * @throws {ApiError} If the rule is rejected or the request fails — 422 when
30055
30083
  * it is unusable as written: a head or body antecedent naming a sort or
30056
30084
  * term that does not exist (the message names it and its position — `the
@@ -30060,9 +30088,8 @@ var InferenceClient = class {
30060
30088
  * cycle the program already had is not blamed on it), or a rule with no
30061
30089
  * antecedents (`rule rejected: a rule needs at least one antecedent; a
30062
30090
  * term with no antecedents is a fact — write it through POST
30063
- * /api/v1/terms` — write a fact with `client.terms.createTerm`). A body
30064
- * with no `antecedents` key at all is refused by the body decoder with a
30065
- * plain-text 422. The refusal is a
30091
+ * /api/v1/terms` — write a fact with `client.terms.createTerm`). The
30092
+ * refusal is a
30066
30093
  * plain {@link ApiError} with `status` 422 — not a `BadRequestError`
30067
30094
  * (earlier engines answered an unknown head sort with 400), and not a
30068
30095
  * `NamedConstraintViolationError`, which is reserved for a feature
@@ -30073,6 +30100,9 @@ var InferenceClient = class {
30073
30100
  *
30074
30101
  * Ask {@link InferenceClient.validateRule} first to learn every reason the
30075
30102
  * write would refuse, without writing.
30103
+ * The `ETag` response header is the rule's content tag, folded into
30104
+ * `etag`: the `ifMatch` for {@link InferenceClient.deleteRule} and
30105
+ * {@link InferenceClient.replaceRule}.
30076
30106
  * A `{ termId }` reference to a term that is durable but not yet loaded
30077
30107
  * into the engine process resolves: the route loads the terms the request
30078
30108
  * names before it converts them.
@@ -30089,7 +30119,7 @@ var InferenceClient = class {
30089
30119
  async addRule(request, requestOptions) {
30090
30120
  const wireRequest = {
30091
30121
  term: convertTermArg(request.term),
30092
- antecedents: request.antecedents.map(convertTermArg),
30122
+ antecedents: convertAntecedents(request.antecedents, "antecedents"),
30093
30123
  certainty: request.certainty,
30094
30124
  aggregator: request.aggregator
30095
30125
  };
@@ -30097,7 +30127,7 @@ var InferenceClient = class {
30097
30127
  AddRuleRequestFromFrontToApi(wireRequest),
30098
30128
  toRequestParams(requestOptions)
30099
30129
  );
30100
- return decodeResponse(response, AddRuleResponseFromApiToFront);
30130
+ return withRuleEtag(decodeResponse(response, AddRuleResponseFromApiToFront), response.headers);
30101
30131
  }
30102
30132
  /**
30103
30133
  * Run every check {@link InferenceClient.addRule} runs — without writing.
@@ -30106,6 +30136,8 @@ var InferenceClient = class {
30106
30136
  * @returns Whether the write would accept it (`ok`), every refusal with the
30107
30137
  * status the write would answer, the NAF-safety warnings, and the rule as
30108
30138
  * the write would build it.
30139
+ * @throws {@link ValidationError} before the request is sent, when `antecedents` is
30140
+ * not an array (a request built from untyped data) — `field` is `antecedents`.
30109
30141
  * @throws {ApiError} If the request itself fails.
30110
30142
  *
30111
30143
  * @remarks
@@ -30130,7 +30162,7 @@ var InferenceClient = class {
30130
30162
  async validateRule(request, requestOptions) {
30131
30163
  const wireRequest = {
30132
30164
  term: convertTermArg(request.term),
30133
- antecedents: request.antecedents.map(convertTermArg),
30165
+ antecedents: convertAntecedents(request.antecedents, "antecedents"),
30134
30166
  certainty: request.certainty,
30135
30167
  aggregator: request.aggregator
30136
30168
  };
@@ -30175,10 +30207,11 @@ var InferenceClient = class {
30175
30207
  * @param requestOptions - Per-call request options.
30176
30208
  * @returns What was written, and what was refused: `ruleTermIds` and
30177
30209
  * `rulesAdded` for the accepted rules, `rejected` naming each refused one.
30178
- * @throws {@link ApiError} 422 when the body is malformed (for example a row
30179
- * with no `antecedents` key) — a 422 never means a refused row.
30210
+ * @throws {@link ApiError} 422 when the body is malformed — a 422 never
30211
+ * means a refused row.
30180
30212
  * @throws {@link ValidationError} before the request is sent, when a rule's
30181
- * term cannot be encoded — `field` names it as `rules[k].term` or
30213
+ * term cannot be encoded, or a row has no `antecedents` array — `field`
30214
+ * names it as `rules[k].term`, `rules[k].antecedents` or
30182
30215
  * `rules[k].antecedents[i]`.
30183
30216
  *
30184
30217
  * @remarks
@@ -30193,7 +30226,8 @@ var InferenceClient = class {
30193
30226
  * number submitted. A row with an empty `antecedents` list is refused per
30194
30227
  * row this way (`rule rejected: a rule needs at least one antecedent; …`)
30195
30228
  * and is not counted in `rulesAdded` or `ruleTermIds`; a row with no
30196
- * `antecedents` key fails the whole batch with a 422. A rule that closes a
30229
+ * `antecedents` array is refused before the request is sent, with a
30230
+ * `ValidationError` whose `field` is `rules[k].antecedents`. A rule that closes a
30197
30231
  * NEW cycle through negation is refused the same way (the reason names the
30198
30232
  * cycle's sorts), decided for every row before any row is written.
30199
30233
  *
@@ -30207,9 +30241,9 @@ var InferenceClient = class {
30207
30241
  */
30208
30242
  async bulkAddRules(request, requestOptions) {
30209
30243
  const wireRequest = {
30210
- rules: request.rules.map((r) => ({
30244
+ rules: request.rules.map((r, k) => ({
30211
30245
  term: convertTermArg(r.term),
30212
- antecedents: r.antecedents.map(convertTermArg),
30246
+ antecedents: convertAntecedents(r.antecedents, `rules[${k}].antecedents`),
30213
30247
  certainty: r.certainty,
30214
30248
  aggregator: r.aggregator
30215
30249
  }))
@@ -30319,8 +30353,8 @@ var InferenceClient = class {
30319
30353
  * @param ruleId - Term id of the rule (its conclusion), as returned by
30320
30354
  * {@link InferenceClient.addRule} or {@link InferenceClient.getRules}.
30321
30355
  * @param options - `derivations` decides what happens to the conclusions the
30322
- * rule derived (defaults to `'refuse'`); `ifMatch` is the ETag of the
30323
- * rule's term, sent as the `If-Match` header.
30356
+ * rule derived (defaults to `'refuse'`); `ifMatch` is the rule's content
30357
+ * tag, sent as the `If-Match` header.
30324
30358
  * @param requestOptions - Per-call request options.
30325
30359
  * @returns What the withdrawal removed, tier by tier.
30326
30360
  * @throws {@link ApiError} 400 if the id names a fact rather than a rule, or
@@ -30349,14 +30383,16 @@ var InferenceClient = class {
30349
30383
  * conclusions are resident is refused too; `'retract'` removes them and
30350
30384
  * {@link RuleWithdrawalReport.consequencesInvalidated} counts them.
30351
30385
  *
30352
- * **Optimistic concurrency.** The rule routes send no ETag of their own.
30353
- * A rule's id is its conclusion term's id, so read the tag with
30354
- * `client.terms.getTerm(ruleId)` and pass its `etag` as `ifMatch`; a rule
30355
- * edited since answers 412.
30386
+ * **Optimistic concurrency.** Read the rule's tag from
30387
+ * {@link AddRuleResponse.etag}, {@link ReplaceRuleResponse.etag} or the
30388
+ * listing's {@link RuleEntryDto.etag} ({@link InferenceClient.getRules}),
30389
+ * and pass it as `ifMatch`; a rule edited since answers 412. The term route
30390
+ * does not serve it: `client.terms.getTerm(ruleId)` answers 404 for a rule.
30356
30391
  *
30357
30392
  * @example
30358
30393
  * ```typescript
30359
- * const { etag } = await client.terms.getTerm(ruleId);
30394
+ * const { rules } = await client.inference.getRules();
30395
+ * const etag = rules.find((rule) => rule.ruleId === ruleId)?.etag;
30360
30396
  * const report = await client.inference.deleteRule(ruleId, {
30361
30397
  * derivations: 'retract',
30362
30398
  * ifMatch: etag,
@@ -30377,11 +30413,12 @@ var InferenceClient = class {
30377
30413
  *
30378
30414
  * @param ruleId - Term id of the rule (its conclusion) to replace.
30379
30415
  * @param request - The replacement rule, in the same shape
30380
- * {@link InferenceClient.addRule} takes, plus `ifMatch`: the ETag of the
30381
- * outgoing rule's term, sent as the `If-Match` header and never in the body.
30416
+ * {@link InferenceClient.addRule} takes, plus `ifMatch`: the content tag
30417
+ * of the outgoing rule, sent as the `If-Match` header and never in the body.
30382
30418
  * @param requestOptions - Per-call request options.
30383
30419
  * @returns The replacement, the id it replaced, what the withdrawal removed,
30384
- * and how the rule base's guarantees moved.
30420
+ * and how the rule base's guarantees moved; `etag` is the replacement's
30421
+ * content tag when the engine sends the `ETag` header.
30385
30422
  * @throws {@link ApiError} 422 if the replacement is rejected by the
30386
30423
  * authoring guards — in which case the original rule is left live. An
30387
30424
  * empty `antecedents` list is one such refusal (`rule rejected: a rule
@@ -30392,7 +30429,8 @@ var InferenceClient = class {
30392
30429
  * @throws {@link PreconditionRequiredError} 428 when `ifMatch` is omitted
30393
30430
  * and the engine runs with `OSFKB_REQUIRE_IF_MATCH=1`.
30394
30431
  * @throws {@link ValidationError} before the request is sent, when a term
30395
- * cannot be encoded — `field` names it (`term`, `antecedents[i]`).
30432
+ * cannot be encoded, or `antecedents` is not an array — `field` names it
30433
+ * (`term`, `antecedents`, `antecedents[i]`).
30396
30434
  *
30397
30435
  * @remarks
30398
30436
  * A rule's id IS its conclusion term id, so an edit changes it by
@@ -30404,16 +30442,23 @@ var InferenceClient = class {
30404
30442
  * addresses a single clause.
30405
30443
  *
30406
30444
  * `ifMatch` guards the edit exactly as it guards
30407
- * {@link InferenceClient.deleteRule}: read the tag with
30408
- * `client.terms.getTerm(ruleId)`.
30445
+ * {@link InferenceClient.deleteRule}: read the tag from
30446
+ * {@link AddRuleResponse.etag}, a previous {@link ReplaceRuleResponse.etag}
30447
+ * or the listing's {@link RuleEntryDto.etag}. The response's own `etag` is
30448
+ * the REPLACEMENT's tag, the `ifMatch` for the next edit.
30409
30449
  *
30410
30450
  * **Serialization format**: untagged `TermInputDto` / `FeatureInputValueDto`.
30411
30451
  *
30412
30452
  * @example
30413
30453
  * ```typescript
30414
- * const result = await client.inference.replaceRule(ruleId, {
30454
+ * const created = await client.inference.addRule({
30455
+ * term: psi('senior', { name: Var('N') }),
30456
+ * antecedents: [psi('person', { name: Var('N') })],
30457
+ * });
30458
+ * const result = await client.inference.replaceRule(created.term.termId, {
30415
30459
  * term: psi('retiree', { name: Var('N') }),
30416
30460
  * antecedents: [psi('person', { name: Var('N') })],
30461
+ * ifMatch: created.etag,
30417
30462
  * });
30418
30463
  * console.log(result.previousRuleId, '->', result.term.termId);
30419
30464
  * if (result.certification.regressed) {
@@ -30424,7 +30469,7 @@ var InferenceClient = class {
30424
30469
  async replaceRule(ruleId, request, requestOptions) {
30425
30470
  const wireRequest = {
30426
30471
  term: convertTermArg(request.term),
30427
- antecedents: request.antecedents.map(convertTermArg),
30472
+ antecedents: convertAntecedents(request.antecedents, "antecedents"),
30428
30473
  certainty: request.certainty,
30429
30474
  aggregator: request.aggregator
30430
30475
  };
@@ -30433,7 +30478,10 @@ var InferenceClient = class {
30433
30478
  AddRuleRequestFromFrontToApi(wireRequest),
30434
30479
  ifMatchParams(request.ifMatch, requestOptions)
30435
30480
  );
30436
- return decodeResponse(response, ReplaceRuleResponseFromApiToFront);
30481
+ return withRuleEtag(
30482
+ decodeResponse(response, ReplaceRuleResponseFromApiToFront),
30483
+ response.headers
30484
+ );
30437
30485
  }
30438
30486
  /**
30439
30487
  * Query for matching data by searching rules and facts backwards from a goal pattern.
@@ -30931,6 +30979,16 @@ var InferenceClient = class {
30931
30979
  function convertTermArg(input) {
30932
30980
  return isPsiTermInput(input) ? toTermInputDto(input) : input;
30933
30981
  }
30982
+ function convertAntecedents(antecedents, field) {
30983
+ if (!Array.isArray(antecedents)) {
30984
+ throw new ValidationError(`${field} must be an array of terms`, field);
30985
+ }
30986
+ return antecedents.map(convertTermArg);
30987
+ }
30988
+ function withRuleEtag(body, headers) {
30989
+ const etag = headers.get("etag");
30990
+ return etag === null ? body : { ...body, etag };
30991
+ }
30934
30992
 
30935
30993
  // src/normalizers/query.ts
30936
30994
  function TermPatternDtoFromFrontToApi(model) {
@@ -37215,6 +37273,7 @@ function DocumentReceiptFromApiToFront(dto) {
37215
37273
  function SessionDocumentFromApiToFront(dto) {
37216
37274
  const out = { documentId: dto.document_id, status: dto.status };
37217
37275
  if (dto.error != null) out.error = dto.error;
37276
+ if (dto.error_code != null) out.errorCode = dto.error_code;
37218
37277
  if (dto.receipt != null) out.receipt = DocumentReceiptFromApiToFront(dto.receipt);
37219
37278
  return out;
37220
37279
  }
@@ -37328,6 +37387,7 @@ function DocumentStatsDtoFromApiToFront(dto) {
37328
37387
  documentId: dto.document_id,
37329
37388
  documentTermId: dto.document_term_id ?? void 0,
37330
37389
  entitiesExtracted: dto.entities_extracted,
37390
+ entitiesRefused: dto.entities_refused.map(RefusedEntityDtoFromApiToFront),
37331
37391
  processingTimeMs: dto.processing_time_ms,
37332
37392
  relationsExtracted: dto.relations_extracted,
37333
37393
  relationsIntegrated: dto.relations_integrated,
@@ -43046,8 +43106,8 @@ function MaterializeScenarioRequestFromFrontToApi(model) {
43046
43106
  return {
43047
43107
  // The prefix keys are data (`''`, `myOnt`), copied verbatim.
43048
43108
  prefixes: model.prefixes === void 0 ? void 0 : { ...model.prefixes },
43049
- // Accepted: the scenario is opaque user data sent verbatim (RAW_BODY_HEADER,
43050
- // #39); the engine validates its shape, so the SDK does not re-type it.
43109
+ // The scenario is user data sent verbatim (RAW_BODY_HEADER, #39): every
43110
+ // key reaches the engine under the spelling the caller wrote.
43051
43111
  scenario: model.scenario
43052
43112
  };
43053
43113
  }
@@ -51177,10 +51237,14 @@ function LayoutSurfaceDtoFromApiToFront(dto) {
51177
51237
  slots: dto.slots
51178
51238
  };
51179
51239
  }
51240
+ function DataLoadErrorFromApiToFront(dto) {
51241
+ return { code: dto.code, message: dto.message, query: dto.query };
51242
+ }
51180
51243
  function UIAssemblyStatsDtoFromApiToFront(dto) {
51181
51244
  return {
51182
51245
  componentCount: dto.component_count,
51183
51246
  dataRows: dto.data_rows ?? void 0,
51247
+ dataLoadError: dto.data_load_error ? DataLoadErrorFromApiToFront(dto.data_load_error) : void 0,
51184
51248
  includedFeatures: dto.included_features,
51185
51249
  osfqlExecuted: dto.osfql_executed ?? void 0,
51186
51250
  sortName: dto.sort_name,
@@ -51329,6 +51393,9 @@ function UIGenerateResponseFromApiToFront(dto) {
51329
51393
  if (dto.data_sources !== void 0) {
51330
51394
  result.dataSources = dto.data_sources.map(UIDataSourcePayloadFromApiToFront);
51331
51395
  }
51396
+ if (dto.data_load_errors !== void 0) {
51397
+ result.dataLoadErrors = dto.data_load_errors.map(DataLoadErrorFromApiToFront);
51398
+ }
51332
51399
  if (dto.intents !== void 0) result.intents = dto.intents.map(UIGenerateIntentFromApiToFront);
51333
51400
  if (dto.trace != null) result.trace = dto.trace.map(UIPipelineStageTraceFromApiToFront);
51334
51401
  return result;
@@ -51576,6 +51643,34 @@ function ReasoningTraceDtoFromApiToFront(dto) {
51576
51643
  llmCalls: dto.llm_calls
51577
51644
  };
51578
51645
  }
51646
+ function ConversationNoticeFromApiToFront(dto) {
51647
+ switch (dto.kind) {
51648
+ case "pruned_features":
51649
+ return {
51650
+ kind: dto.kind,
51651
+ message: dto.message,
51652
+ skipped: dto.skipped.map((s) => ({ feature: s.feature, sort: s.sort }))
51653
+ };
51654
+ case "value_grounding":
51655
+ return {
51656
+ kind: dto.kind,
51657
+ message: dto.message,
51658
+ substitutions: dto.substitutions.map((s) => ({
51659
+ feature: s.feature,
51660
+ from: s.from,
51661
+ sort: s.sort,
51662
+ to: s.to
51663
+ }))
51664
+ };
51665
+ case "retrieval_rescue":
51666
+ return {
51667
+ kind: dto.kind,
51668
+ message: dto.message,
51669
+ recordCount: dto.record_count,
51670
+ sorts: [...dto.sorts]
51671
+ };
51672
+ }
51673
+ }
51579
51674
  function ConversationMessageResponseFromApiToFront(dto) {
51580
51675
  return {
51581
51676
  assistantMessage: dto.assistant_message,
@@ -51589,6 +51684,7 @@ function ConversationMessageResponseFromApiToFront(dto) {
51589
51684
  producedTermIds: dto.produced_term_ids,
51590
51685
  uiSortId: dto.ui_sort_id ?? void 0,
51591
51686
  suggestions: dto.suggestions,
51687
+ notices: dto.notices.map(ConversationNoticeFromApiToFront),
51592
51688
  claimAnnotations: dto.claim_annotations?.map(ClaimAnnotationDtoFromApiToFront) ?? void 0,
51593
51689
  proofTrace: dto.proof_trace ? ProofTraceNodeDtoFromApiToFront(dto.proof_trace) : void 0,
51594
51690
  uiCustomizations: dto.ui_customizations?.map(UICustomizationDtoFromApiToFront) ?? void 0,
@@ -51611,7 +51707,7 @@ function isJsonObject2(value) {
51611
51707
  }
51612
51708
  function isConversationMessageResponseDto(value) {
51613
51709
  if (!isJsonObject2(value)) return false;
51614
- return typeof Reflect.get(value, "assistant_message") === "string" && typeof Reflect.get(value, "conversation_id") === "string" && typeof Reflect.get(value, "intent") === "string" && typeof Reflect.get(value, "turn_id") === "string" && Array.isArray(Reflect.get(value, "produced_term_ids")) && Array.isArray(Reflect.get(value, "suggestions"));
51710
+ return typeof Reflect.get(value, "assistant_message") === "string" && typeof Reflect.get(value, "conversation_id") === "string" && typeof Reflect.get(value, "intent") === "string" && typeof Reflect.get(value, "turn_id") === "string" && Array.isArray(Reflect.get(value, "produced_term_ids")) && Array.isArray(Reflect.get(value, "suggestions")) && Array.isArray(Reflect.get(value, "notices"));
51615
51711
  }
51616
51712
  function decodeConversationMessage(payload) {
51617
51713
  return isConversationMessageResponseDto(payload) ? ConversationMessageResponseFromApiToFront(payload) : null;
@@ -51964,6 +52060,37 @@ var ConversationClient = class {
51964
52060
  });
51965
52061
  return decodeResponse(response, ListConversationsResponseFromApiToFront);
51966
52062
  }
52063
+ /**
52064
+ * Read one conversation's summary: the row {@link listConversations}
52065
+ * returns for it.
52066
+ *
52067
+ * @param conversationId - The conversation ID.
52068
+ * @param requestOptions - Per-call transport overrides.
52069
+ * @returns The summary, with its `kind` and `title`.
52070
+ * @throws {BadRequestError} `400` if the ID is malformed.
52071
+ * @throws {NotFoundError} `404` if the conversation is not the caller's.
52072
+ * @throws {ApiError} If the request fails.
52073
+ *
52074
+ * @remarks
52075
+ * Uses GET `/api/v1/conversation/{id}`. A caller that resumes a conversation
52076
+ * by ID learns its `kind` and `title` here without reading the whole listing.
52077
+ *
52078
+ * @example
52079
+ * ```typescript
52080
+ * const summary = await client.conversation.getConversation('conv-uuid');
52081
+ * console.log(`${summary.kind}: ${summary.title ?? '(untitled)'}`);
52082
+ * ```
52083
+ */
52084
+ async getConversation(conversationId, requestOptions) {
52085
+ const response = await this.http.request({
52086
+ ...toRequestParams(requestOptions),
52087
+ path: `/api/v1/conversation/${encodeURIComponent(conversationId)}`,
52088
+ method: "GET",
52089
+ secure: true,
52090
+ format: "json"
52091
+ });
52092
+ return decodeResponse(response, ConversationSummaryDtoFromApiToFront);
52093
+ }
51967
52094
  /**
51968
52095
  * List the registered comparison models so the UI can populate a
51969
52096
  * selector / compare panel.
@@ -53511,10 +53638,12 @@ var UiClient = class {
53511
53638
  * keys inside them — `params`, `props_override`, a `component`'s `props`
53512
53639
  * (`dataKey`) and `initial_values` — reach the engine exactly as written.
53513
53640
  *
53514
- * The data load runs read-only OSFQL. A query that writes the store is
53515
- * refused without an exception: the answer's `stats.osfqlExecuted` starts
53516
- * with `FAILED:` (`FAILED: <query> — a data load runs read-only OSFQL, and this query writes the store; run it through POST /api/v1/ui/action or POST /api/v1/osfql`) and no rows load. Read a `FAILED:` value as a refused
53517
- * load, not as an empty result.
53641
+ * The data load runs read-only OSFQL. A load that fails, including a query
53642
+ * that writes the store, does not throw: the view renders without rows,
53643
+ * `stats.dataLoadError` carries the typed `code`, the `message` and the
53644
+ * `query`, and `stats.osfqlExecuted` is absent. Branch on `code`
53645
+ * (`data_load_writes`, `osfql_parse_error`, `osfql_compile_error`,
53646
+ * `osfql_execution_failed`), not on the message.
53518
53647
  *
53519
53648
  * A data view (table, graph, chart, map, timeline, matrix) names in
53520
53649
  * `props.rowKey` the column in which each loaded row carries its term's id.
@@ -53554,8 +53683,8 @@ var UiClient = class {
53554
53683
  * `delete_record` template, is not a UUID; if a `"sort_ref"` field's sort
53555
53684
  * declares no entity range; if `sortName` names no sort of the tenant or
53556
53685
  * contains a backtick; if `values` names a feature the sort does not
53557
- * declare; if an `update_form`'s term is held under another sort than
53558
- * `sortName`; or if the request is malformed otherwise.
53686
+ * declare; if an `update_form` names a term the tenant does not hold, or a
53687
+ * term whose own sort `sortName` does not subsume; or if the request is malformed otherwise.
53559
53688
  * @throws {ApiError} If the request fails otherwise.
53560
53689
  *
53561
53690
  * @remarks
@@ -53625,8 +53754,8 @@ var UiClient = class {
53625
53754
  * endpoint abstains with live-schema suggestions. Data rows always come from OSFQL
53626
53755
  * execution after certification — never from the model. The data source runs
53627
53756
  * read-only OSFQL: a load query that writes the store is refused without an
53628
- * exception, and the load reports `FAILED: <query> — a data load runs read-only
53629
- * OSFQL, …` instead of rows.
53757
+ * exception, and the failure is a `dataLoadErrors` entry (typed `code`,
53758
+ * `message`, `query`) instead of rows.
53630
53759
  *
53631
53760
  * A certified single-pattern data query is bound to its rows' term ids: the
53632
53761
  * engine adds the identity binding to its root pattern (a note in
@@ -60774,8 +60903,9 @@ var AguiClient = class {
60774
60903
  *
60775
60904
  * A data load the run performs executes read-only OSFQL. A load query that
60776
60905
  * writes the store is refused without an exception or a `RUN_ERROR`: the
60777
- * load reports `FAILED: <query> — a data load runs read-only OSFQL, …` in
60778
- * place of rows.
60906
+ * run emits a `CUSTOM` event named `osfkb.data_load_error` whose `value` is
60907
+ * `{ code, message, query }`, and the `STATE_SNAPSHOT` carries the same
60908
+ * object at `osfkb.dataLoadError`; branch on `code`. No rows are loaded.
60779
60909
  *
60780
60910
  * @example
60781
60911
  * ```typescript