@kortexya/reasoninglayer 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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 = "5.0.0";
10
+ var SDK_VERSION = "5.1.0";
11
11
  function resolveConfig(config) {
12
12
  if (!config.baseUrl) {
13
13
  throw new Error("ClientConfig.baseUrl is required");
@@ -952,6 +952,8 @@ function toSnakeCase(input) {
952
952
 
953
953
  // src/http.ts
954
954
  var RAW_BODY_HEADER = "X-RL-Raw-Body";
955
+ var BINARY_BODY_HEADER = "X-RL-Binary-Body";
956
+ var BINARY_BODY_PART = "body";
955
957
 
956
958
  // src/utils/audit-headers.ts
957
959
  var AUDIT_CAUSAL_REQUEST_HEADERS = {
@@ -1180,6 +1182,18 @@ function buildAuthHeaders(config) {
1180
1182
  }
1181
1183
  function transformRequestInit(init) {
1182
1184
  if (!init) return init;
1185
+ const binaryType = findHeader(init.headers, BINARY_BODY_HEADER_LOWER);
1186
+ if (binaryType !== void 0) {
1187
+ return {
1188
+ ...init,
1189
+ headers: withHeader(
1190
+ withoutHeader(init.headers, BINARY_BODY_HEADER_LOWER),
1191
+ "Content-Type",
1192
+ binaryType
1193
+ ),
1194
+ body: binaryBody(init.body)
1195
+ };
1196
+ }
1183
1197
  if (hasRawBodyHeader(init.headers)) {
1184
1198
  return { ...init, headers: withoutRawBodyHeader(init.headers) };
1185
1199
  }
@@ -1192,6 +1206,31 @@ function transformRequestInit(init) {
1192
1206
  return init;
1193
1207
  }
1194
1208
  }
1209
+ var BINARY_BODY_HEADER_LOWER = BINARY_BODY_HEADER.toLowerCase();
1210
+ function binaryBody(body) {
1211
+ if (body instanceof FormData) {
1212
+ const parts = [];
1213
+ body.forEach((value, name) => parts.push([name, value]));
1214
+ const only = parts[0];
1215
+ if (parts.length === 1 && only !== void 0 && only[0] === BINARY_BODY_PART) {
1216
+ const value = only[1];
1217
+ if (value instanceof Blob) return value;
1218
+ }
1219
+ }
1220
+ throw new ValidationError(
1221
+ `A ${BINARY_BODY_HEADER} request must carry exactly one Blob part named "${BINARY_BODY_PART}"`
1222
+ );
1223
+ }
1224
+ function withHeader(headers, name, value) {
1225
+ const lowerName = name.toLowerCase();
1226
+ const rest = withoutHeader(headers, lowerName);
1227
+ if (rest instanceof Headers) {
1228
+ rest.set(name, value);
1229
+ return rest;
1230
+ }
1231
+ if (Array.isArray(rest)) return [...rest, [name, value]];
1232
+ return { ...rest, [name]: value };
1233
+ }
1195
1234
  var REQUEST_BUDGET_HEADER_LOWER = REQUEST_BUDGET_HEADER.toLowerCase();
1196
1235
  function readRequestBudget(headers) {
1197
1236
  const raw = findHeader(headers, REQUEST_BUDGET_HEADER_LOWER);
@@ -9356,11 +9395,11 @@ var Analysis = class {
9356
9395
  ...params
9357
9396
  });
9358
9397
  /**
9359
- * @description The exploration must be complete (no more questions) before calling this. Creates appropriateness sorts in the hierarchy from the Duquenne-Guigues basis.
9398
+ * @description The exploration must be complete (no more questions) before calling this. Registration happens before the terminal commit and ignores existing names, so a retry after a lost commit is safe. The committed receipt is retained: completing again returns it unchanged. `rules_created` counts those sort registrations; no inference rule is installed.
9360
9399
  *
9361
9400
  * @tags analysis
9362
9401
  * @name CompleteExploration
9363
- * @summary Complete the exploration and create sort rules from confirmed implications.
9402
+ * @summary Complete the exploration and register appropriateness sorts for its basis.
9364
9403
  * @request POST:/api/v1/analysis/attribute-exploration/{session_id}/complete
9365
9404
  */
9366
9405
  completeExploration = (sessionId, params = {}) => this.http.request({
@@ -9370,7 +9409,7 @@ var Analysis = class {
9370
9409
  ...params
9371
9410
  });
9372
9411
  /**
9373
- * @description The body names the question being confirmed. The check and the mutation run under one session write lock, so an answer is applied at most once.
9412
+ * @description The body names the question being confirmed. The answer commits only on top of the session version it was checked against, so across every server sharing the repository an answer is applied at most once.
9374
9413
  *
9375
9414
  * @tags analysis
9376
9415
  * @name ConfirmImplication
@@ -40000,6 +40039,51 @@ function IngestAudioResponseFromApiToFront(dto) {
40000
40039
  translatedLang: dto.translated_lang ?? void 0
40001
40040
  };
40002
40041
  }
40042
+ function CreateRdfUploadRequestFromFrontToApi(request) {
40043
+ return {
40044
+ name: request.name,
40045
+ size: request.size,
40046
+ ...request.datasetScope !== void 0 && { dataset_scope: request.datasetScope }
40047
+ };
40048
+ }
40049
+ function RdfUploadFromApiToFront(dto) {
40050
+ return {
40051
+ id: dto.id,
40052
+ name: dto.name,
40053
+ size: dto.size,
40054
+ uploadedBytes: dto.uploaded_bytes,
40055
+ chunkBytes: dto.chunk_bytes,
40056
+ chunkSha256: dto.chunk_sha256,
40057
+ sha256: dto.sha256,
40058
+ engineBinarySha256: dto.engine_binary_sha256,
40059
+ format: dto.format,
40060
+ gzip: dto.gzip,
40061
+ status: dto.status,
40062
+ ownerId: dto.owner_id,
40063
+ sessionId: dto.session_id,
40064
+ documentId: dto.document_id,
40065
+ datasetScope: dto.dataset_scope,
40066
+ prefixBindings: definedRecord(dto.prefix_bindings ?? {}),
40067
+ quadsCommitted: dto.quads_committed,
40068
+ batchesCommitted: dto.batches_committed,
40069
+ resourcesCreated: dto.resources_created,
40070
+ sortsCreated: dto.sorts_created,
40071
+ error: dto.error,
40072
+ updatedAt: dto.updated_at
40073
+ };
40074
+ }
40075
+ function RdfUploadChunkReceiptFromApiToFront(dto) {
40076
+ return {
40077
+ uploadedBytes: dto.uploaded_bytes,
40078
+ sha256: dto.sha256
40079
+ };
40080
+ }
40081
+ function RdfUploadPauseReceiptFromApiToFront(dto) {
40082
+ return {
40083
+ id: dto.id,
40084
+ status: dto.status
40085
+ };
40086
+ }
40003
40087
 
40004
40088
  // src/resources/ingestion-session.ts
40005
40089
  var IngestionFailedError = class extends ReasoningLayerError {
@@ -41285,6 +41369,208 @@ var IngestionClient = class {
41285
41369
  const response = await this.api.resumeAudioJob(jobId, toRequestParams(requestOptions));
41286
41370
  return decodeResponse(response, IngestAudioResponseFromApiToFront);
41287
41371
  }
41372
+ /**
41373
+ * Open a resumable upload of one original RDF file —
41374
+ * `POST /api/v1/ingest/rdf/uploads`.
41375
+ *
41376
+ * @param request - The file name (its extension selects the format), its
41377
+ * exact size, and an optional shared N-Triples/N-Quads dataset scope.
41378
+ * @param requestOptions - Per-call request options.
41379
+ * @returns The new upload (HTTP 201), with `status: 'uploading'`,
41380
+ * `uploadedBytes: 0` and the `chunkBytes` every chunk must respect.
41381
+ * @throws {BadRequestError} 400 when the name is empty, longer than 255
41382
+ * bytes or holds `/`, `\` or NUL; when the size is 0 or above 32 GiB; when
41383
+ * the extension names no RDF format; or when a dataset scope accompanies a
41384
+ * format other than N-Triples or N-Quads.
41385
+ *
41386
+ * @remarks
41387
+ * Body is snake_case on the wire (`dataset_scope`). The engine keeps the
41388
+ * uploaded bytes verbatim and parses them only when
41389
+ * {@link IngestionClient.completeRdfUpload} starts the import. Send the
41390
+ * bytes with {@link IngestionClient.uploadRdfChunk}.
41391
+ *
41392
+ * @example
41393
+ * ```typescript
41394
+ * const upload = await client.ingestion.createRdfUpload({
41395
+ * name: file.name,
41396
+ * size: file.size,
41397
+ * });
41398
+ * for (let offset = 0; offset < file.size; offset += upload.chunkBytes) {
41399
+ * await client.ingestion.uploadRdfChunk(
41400
+ * upload.id,
41401
+ * offset,
41402
+ * file.slice(offset, offset + upload.chunkBytes),
41403
+ * );
41404
+ * }
41405
+ * await client.ingestion.completeRdfUpload(upload.id);
41406
+ * ```
41407
+ */
41408
+ async createRdfUpload(request, requestOptions) {
41409
+ const response = await this.api.create(
41410
+ CreateRdfUploadRequestFromFrontToApi(request),
41411
+ toRequestParams(requestOptions)
41412
+ );
41413
+ return decodeResponse(response, RdfUploadFromApiToFront);
41414
+ }
41415
+ /**
41416
+ * List the tenant's original RDF uploads — `GET /api/v1/ingest/rdf/uploads`.
41417
+ *
41418
+ * @param requestOptions - Per-call request options.
41419
+ * @returns Every RDF upload of the tenant, the most recently updated first.
41420
+ * Each `chunkSha256` is empty in this listing; read one upload with
41421
+ * {@link IngestionClient.getRdfUpload} for its chunk digests.
41422
+ * @throws {ApiError} If the request fails.
41423
+ *
41424
+ * @remarks
41425
+ * Response is snake_case on the wire. An import that reads `queued` or
41426
+ * `processing` without a live worker is reported as `interrupted`.
41427
+ *
41428
+ * @example
41429
+ * ```typescript
41430
+ * const uploads = await client.ingestion.listRdfUploads();
41431
+ * const interrupted = uploads.filter((u) => u.status === 'interrupted');
41432
+ * ```
41433
+ */
41434
+ async listRdfUploads(requestOptions) {
41435
+ const response = await this.api.list(toRequestParams(requestOptions));
41436
+ return decodeResponse(response, (dto) => dto.map(RdfUploadFromApiToFront));
41437
+ }
41438
+ /**
41439
+ * Read one RDF upload: its upload extent and its durable ingestion
41440
+ * checkpoint — `GET /api/v1/ingest/rdf/uploads/{id}`.
41441
+ *
41442
+ * @param id - The upload id ({@link RdfUpload.id}).
41443
+ * @param requestOptions - Per-call request options.
41444
+ * @returns The upload, with the SHA-256 of every stored chunk.
41445
+ * @throws {NotFoundError} 404 when the tenant has no RDF upload with this id.
41446
+ *
41447
+ * @remarks
41448
+ * Response is snake_case on the wire. Use `uploadedBytes` to resume an
41449
+ * interrupted upload at the right offset, and `status` to follow the
41450
+ * import; `interrupted` means no worker runs it, and
41451
+ * {@link IngestionClient.completeRdfUpload} resumes it.
41452
+ *
41453
+ * @example
41454
+ * ```typescript
41455
+ * const upload = await client.ingestion.getRdfUpload(id);
41456
+ * const nextOffset = upload.uploadedBytes;
41457
+ * ```
41458
+ */
41459
+ async getRdfUpload(id, requestOptions) {
41460
+ const response = await this.api.get(id, toRequestParams(requestOptions));
41461
+ return decodeResponse(response, RdfUploadFromApiToFront);
41462
+ }
41463
+ /**
41464
+ * Store one chunk of an RDF upload durably —
41465
+ * `PUT /api/v1/ingest/rdf/uploads/{id}?offset=…`.
41466
+ *
41467
+ * @param id - The upload id ({@link RdfUpload.id}).
41468
+ * @param offset - The byte offset of the chunk in the file: a multiple of
41469
+ * {@link RdfUpload.chunkBytes}, equal to `uploadedBytes` for a new chunk.
41470
+ * @param chunk - The chunk's bytes: exactly `chunkBytes` of them, except for
41471
+ * the last chunk of the file. A `File` slice (`file.slice(start, end)`) is
41472
+ * a `Blob`; wrap other bytes as `new Blob([bytes])`.
41473
+ * @param requestOptions - Per-call request options.
41474
+ * @returns The bytes stored so far and the SHA-256 of this chunk.
41475
+ * @throws {BadRequestError} 400 when the upload no longer accepts bytes, when
41476
+ * the offset or chunk size breaks the rules above, when the offset skips
41477
+ * or precedes the stored extent, or when a resent chunk differs from the
41478
+ * bytes stored at that offset.
41479
+ * @throws {ForbiddenError} 403 when the caller did not open the upload.
41480
+ * @throws {NotFoundError} 404 when the tenant has no RDF upload with this id.
41481
+ *
41482
+ * @remarks
41483
+ * The body is the raw bytes, sent as `application/octet-stream`; the
41484
+ * response is snake_case on the wire. Resending a chunk the engine already
41485
+ * stored, with the same bytes, answers the same receipt, so a retry after a
41486
+ * lost response is safe.
41487
+ *
41488
+ * @example
41489
+ * ```typescript
41490
+ * const upload = await client.ingestion.getRdfUpload(id);
41491
+ * const start = upload.uploadedBytes;
41492
+ * const receipt = await client.ingestion.uploadRdfChunk(
41493
+ * id,
41494
+ * start,
41495
+ * file.slice(start, start + upload.chunkBytes),
41496
+ * );
41497
+ * console.log(receipt.uploadedBytes, receipt.sha256);
41498
+ * ```
41499
+ */
41500
+ async uploadRdfChunk(id, offset, chunk, requestOptions) {
41501
+ const body = new FormData();
41502
+ body.append(BINARY_BODY_PART, chunk);
41503
+ const response = await this.api.http.request({
41504
+ ...mergeRequestParams(
41505
+ { headers: { [BINARY_BODY_HEADER]: "application/octet-stream" } },
41506
+ requestOptions
41507
+ ),
41508
+ path: `/api/v1/ingest/rdf/uploads/${encodeURIComponent(id)}`,
41509
+ method: "PUT",
41510
+ query: { offset },
41511
+ body,
41512
+ type: "multipart/form-data",
41513
+ format: "json"
41514
+ });
41515
+ return decodeResponse(response, RdfUploadChunkReceiptFromApiToFront);
41516
+ }
41517
+ /**
41518
+ * Start, or resume, the import of a fully uploaded RDF file —
41519
+ * `POST /api/v1/ingest/rdf/uploads/{id}/complete`.
41520
+ *
41521
+ * @param id - The upload id ({@link RdfUpload.id}).
41522
+ * @param requestOptions - Per-call request options.
41523
+ * @returns The upload: queued or resumed (HTTP 202), or unchanged (HTTP 200)
41524
+ * when the import is already complete or already has a live worker.
41525
+ * @throws {BadRequestError} 400 when bytes are still missing.
41526
+ * @throws {ForbiddenError} 403 when the caller did not open the upload.
41527
+ * @throws {NotFoundError} 404 when the tenant has no RDF upload with this id.
41528
+ * @throws {ConstraintViolationError} 409 while a paused worker is still
41529
+ * finishing its pause; retry the call.
41530
+ *
41531
+ * @remarks
41532
+ * The import runs in the background and commits in durable batches; a
41533
+ * resumed import continues from the last committed batch. Follow it with
41534
+ * {@link IngestionClient.getRdfUpload}. Response is snake_case on the wire.
41535
+ *
41536
+ * @example
41537
+ * ```typescript
41538
+ * const started = await client.ingestion.completeRdfUpload(id);
41539
+ * console.log(started.status); // 'queued'
41540
+ * ```
41541
+ */
41542
+ async completeRdfUpload(id, requestOptions) {
41543
+ const response = await this.api.complete(id, toRequestParams(requestOptions));
41544
+ return decodeResponse(response, RdfUploadFromApiToFront);
41545
+ }
41546
+ /**
41547
+ * Pause a running RDF import at its next durable checkpoint —
41548
+ * `POST /api/v1/ingest/rdf/uploads/{id}/pause`.
41549
+ *
41550
+ * @param id - The upload id ({@link RdfUpload.id}).
41551
+ * @param requestOptions - Per-call request options.
41552
+ * @returns The receipt, with `status: 'pausing'`.
41553
+ * @throws {BadRequestError} 400 when the import is not `queued` or
41554
+ * `processing`.
41555
+ * @throws {ForbiddenError} 403 when the caller did not open the upload.
41556
+ * @throws {NotFoundError} 404 when the tenant has no RDF upload with this id.
41557
+ *
41558
+ * @remarks
41559
+ * The import stops after its current batch commits; the upload then reads
41560
+ * `paused`. {@link IngestionClient.completeRdfUpload} resumes it. Response
41561
+ * is snake_case on the wire.
41562
+ *
41563
+ * @example
41564
+ * ```typescript
41565
+ * await client.ingestion.pauseRdfUpload(id);
41566
+ * // later
41567
+ * await client.ingestion.completeRdfUpload(id);
41568
+ * ```
41569
+ */
41570
+ async pauseRdfUpload(id, requestOptions) {
41571
+ const response = await this.api.pause(id, toRequestParams(requestOptions));
41572
+ return decodeResponse(response, RdfUploadPauseReceiptFromApiToFront);
41573
+ }
41288
41574
  };
41289
41575
 
41290
41576
  // src/normalizers/reviews.ts
@@ -53853,6 +54139,20 @@ function OsfqlFailureFromApiToFront(body) {
53853
54139
  }
53854
54140
  return failure;
53855
54141
  }
54142
+ function OsfqlTokenFromApiToFront(dto) {
54143
+ return {
54144
+ line: dto.line,
54145
+ startChar: dto.start_char,
54146
+ length: dto.length,
54147
+ kind: dto.kind
54148
+ };
54149
+ }
54150
+ function OsfqlTokensResponseFromApiToFront(dto) {
54151
+ return {
54152
+ encoding: dto.encoding,
54153
+ tokens: dto.tokens.map(OsfqlTokenFromApiToFront)
54154
+ };
54155
+ }
53856
54156
 
53857
54157
  // src/resources/osfql.ts
53858
54158
  var OsfqlClient = class {
@@ -54196,6 +54496,38 @@ var OsfqlClient = class {
54196
54496
  });
54197
54497
  return decodeResponse(response, (dto) => dto.map(OsfqlCatalogEntryFromApiToFront));
54198
54498
  }
54499
+ /**
54500
+ * Highlight OSFQL source with the engine's own classifier — the one the
54501
+ * OSFQL language server uses.
54502
+ *
54503
+ * @param query - The source as authored, incomplete statements included. At
54504
+ * most 256 KiB of UTF-8.
54505
+ * @param requestOptions - Per-call transport options (timeout, signal, headers).
54506
+ * @returns The editor tokens, sorted by position, in UTF-16 coordinates.
54507
+ * @throws {BadRequestError} 400 when the source exceeds 256 KiB.
54508
+ *
54509
+ * @remarks
54510
+ * Sent to `POST /api/v1/osfql/tokens` as `{ "query": … }`; the response is
54511
+ * mapped from snake_case (`start_char`) at the boundary. The engine parser
54512
+ * classifies sorts, features, literals and required fields, with a lexical
54513
+ * fallback for an incomplete document. Nothing runs and the knowledge base
54514
+ * is not read. This is presentation data, not validation: a source with
54515
+ * errors still receives tokens. Use {@link OsfqlClient.diagnose} for errors.
54516
+ *
54517
+ * @example
54518
+ * ```typescript
54519
+ * const source = 'MATCH person(name: ?N);';
54520
+ * const { tokens } = await client.osfql.tokens(source);
54521
+ * for (const t of tokens) {
54522
+ * const text = source.split('\n')[t.line]?.slice(t.startChar, t.startChar + t.length);
54523
+ * console.log(t.kind, text); // "keyword MATCH", "sort person", …
54524
+ * }
54525
+ * ```
54526
+ */
54527
+ async tokens(query, requestOptions) {
54528
+ const response = await this.api.osfqlTokens({ query }, toRequestParams(requestOptions));
54529
+ return decodeResponse(response, OsfqlTokensResponseFromApiToFront);
54530
+ }
54199
54531
  };
54200
54532
  function rethrowOsfqlFailure(error) {
54201
54533
  if (error instanceof ApiError) {