@xemahq/llm-registry-api-client 0.8.7 → 0.8.9

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.
@@ -223,14 +223,66 @@ const customFetch = async (url, options) => {
223
223
  }
224
224
  };
225
225
  exports.customFetch = customFetch;
226
- async function parseBody(response) {
227
- const contentType = response.headers.get('content-type');
228
- if (contentType?.includes('application/json')) {
229
- return response.json();
226
+ /**
227
+ * Does this media type carry JSON?
228
+ *
229
+ * ── THE OUTAGE THIS FIXES ────────────────────────────────────────────────
230
+ *
231
+ * This used to be `contentType?.includes('application/json')`, and EVERY error
232
+ * this fleet returns failed that test. The platform's `GlobalExceptionFilter`
233
+ * emits RFC 9457 problem documents and sets the media type explicitly —
234
+ * `.type(PROBLEM_DETAILS_CONTENT_TYPE)` before `.json()`, so it cannot be
235
+ * overridden — and that constant is `application/problem+json`, which does NOT
236
+ * contain the substring `application/json`: after `application/` comes
237
+ * `problem+json`.
238
+ *
239
+ * So every non-2xx body fell through to `response.text()` and reached the
240
+ * caller as an UNPARSED STRING. `ClientError.body` is typed `unknown`, so
241
+ * nothing complained; every consumer that reads a machine-readable code off an
242
+ * error — `error.body.code`, `error.body.details.code` — silently read
243
+ * `undefined` instead, for every error, in every service.
244
+ *
245
+ * Measured in production on 2026-09-15: skill-registry-api's
246
+ * `resolveOrNull()` absorbs `RELEASE_CHANNEL_NOT_FOUND` into `null` by exactly
247
+ * that read. With the code unreadable the absorb never fired, a routine "no
248
+ * pointer on this channel" 404 became a 500 on `GET /skills` and
249
+ * `GET /describe-objects`, and agent-session-api's `apply_control_bundle` step
250
+ * aborted EVERY session launch in the organisation — 7,871 failed resolutions
251
+ * an hour. A fix written for that exact page months earlier was present in the
252
+ * running image and could not help, because the classifier it repaired was
253
+ * being handed a string.
254
+ *
255
+ * ── WHY THE STRUCTURED SUFFIX, NOT A SECOND SUBSTRING ────────────────────
256
+ *
257
+ * Adding `|| includes('application/problem+json')` would fix this one media
258
+ * type and leave the next one — `application/vnd.api+json`, and anything else
259
+ * a service legitimately emits. RFC 6839 defines `+json` as the structured
260
+ * syntax suffix meaning "this is JSON"; that is the actual rule, so it is the
261
+ * rule implemented. Parameters are stripped first, because
262
+ * `application/problem+json; charset=utf-8` is the same media type.
263
+ */
264
+ function isJsonMediaType(contentType) {
265
+ if (contentType === null) {
266
+ return false;
230
267
  }
268
+ const essence = contentType.split(';')[0]?.trim().toLowerCase() ?? '';
269
+ return essence === 'application/json' || essence.endsWith('+json');
270
+ }
271
+ async function parseBody(response) {
272
+ // 204 FIRST, and deliberately — this ORDER is carried from `develop`, which
273
+ // fixed the same defect independently and got this half right where `main`
274
+ // did not. A 204 carries no body, so `response.json()` on one throws
275
+ // SyntaxError; and a 204 whose headers STILL declare a JSON content type is
276
+ // ordinary, because the framework sets the header before the handler returns
277
+ // nothing. With the JSON branch first, a documented `undefined` becomes a
278
+ // thrown parse error. Pinned by a case in `transport-problem-json.test.cjs`.
231
279
  if (response.status === 204) {
232
280
  return undefined;
233
281
  }
282
+ const contentType = response.headers.get('content-type');
283
+ if (isJsonMediaType(contentType)) {
284
+ return response.json();
285
+ }
234
286
  return response.text();
235
287
  }
236
288
  function parseRetryAfter(value) {
@@ -3,7 +3,7 @@
3
3
  * LLM Registry API
4
4
  * OpenAPI spec version: 0.1.3
5
5
  */
6
- import type { BindModelStrategyDto, CreateModelStrategyDto, ModelStrategyControllerGetProjectBinding200, ModelStrategyResponseDtoDataArrayEnvelope, ModelStrategyResponseDtoDataEnvelope, OrgDefaultStrategyStatusResponseDtoDataEnvelope, ProjectModelStrategyBindingResponseDtoDataEnvelope, StrategyTemplateResponseDtoDataArrayEnvelope, UpdateModelStrategyDto, UpsertModelStrategyEntriesDto } from '../../models';
6
+ import type { BindModelStrategyDto, CreateModelStrategyDto, ModelStrategyControllerGetProjectBinding200, ModelStrategyResponseDtoDataArrayEnvelope, ModelStrategyResponseDtoDataEnvelope, OrgDefaultStrategyStatusResponseDtoDataEnvelope, ProjectModelStrategyBindingResponseDtoDataEnvelope, StrategyDeletionImpactResponseDtoDataEnvelope, StrategyTemplateResponseDtoDataArrayEnvelope, UpdateModelStrategyDto, UpsertModelStrategyEntriesDto } from '../../models';
7
7
  export declare const getModelStrategyControllerCreateStrategyUrl: () => string;
8
8
  /**
9
9
  * @summary Create a model strategy
@@ -44,6 +44,11 @@ export declare const getModelStrategyControllerDeleteStrategyUrl: (id: string) =
44
44
  * @summary Delete a model strategy
45
45
  */
46
46
  export declare const modelStrategyControllerDeleteStrategy: (id: string, options?: RequestInit) => Promise<unknown>;
47
+ export declare const getModelStrategyControllerGetStrategyDeletionImpactUrl: (id: string) => string;
48
+ /**
49
+ * @summary What deleting this model strategy would change for projects bound to it
50
+ */
51
+ export declare const modelStrategyControllerGetStrategyDeletionImpact: (id: string, options?: RequestInit) => Promise<StrategyDeletionImpactResponseDtoDataEnvelope>;
47
52
  export declare const getModelStrategyControllerUpsertEntriesUrl: (id: string) => string;
48
53
  /**
49
54
  * @summary Replace all strategy entries
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.modelStrategyControllerUnbindStrategy = exports.getModelStrategyControllerUnbindStrategyUrl = exports.modelStrategyControllerGetProjectBinding = exports.getModelStrategyControllerGetProjectBindingUrl = exports.modelStrategyControllerBindStrategy = exports.getModelStrategyControllerBindStrategyUrl = exports.modelStrategyControllerUpsertEntries = exports.getModelStrategyControllerUpsertEntriesUrl = exports.modelStrategyControllerDeleteStrategy = exports.getModelStrategyControllerDeleteStrategyUrl = exports.modelStrategyControllerUpdateStrategy = exports.getModelStrategyControllerUpdateStrategyUrl = exports.modelStrategyControllerGetStrategy = exports.getModelStrategyControllerGetStrategyUrl = exports.modelStrategyControllerAdoptTemplate = exports.getModelStrategyControllerAdoptTemplateUrl = exports.modelStrategyControllerListTemplates = exports.getModelStrategyControllerListTemplatesUrl = exports.modelStrategyControllerGetOrgDefaultStatus = exports.getModelStrategyControllerGetOrgDefaultStatusUrl = exports.modelStrategyControllerListStrategies = exports.getModelStrategyControllerListStrategiesUrl = exports.modelStrategyControllerCreateStrategy = exports.getModelStrategyControllerCreateStrategyUrl = void 0;
3
+ exports.modelStrategyControllerUnbindStrategy = exports.getModelStrategyControllerUnbindStrategyUrl = exports.modelStrategyControllerGetProjectBinding = exports.getModelStrategyControllerGetProjectBindingUrl = exports.modelStrategyControllerBindStrategy = exports.getModelStrategyControllerBindStrategyUrl = exports.modelStrategyControllerUpsertEntries = exports.getModelStrategyControllerUpsertEntriesUrl = exports.modelStrategyControllerGetStrategyDeletionImpact = exports.getModelStrategyControllerGetStrategyDeletionImpactUrl = exports.modelStrategyControllerDeleteStrategy = exports.getModelStrategyControllerDeleteStrategyUrl = exports.modelStrategyControllerUpdateStrategy = exports.getModelStrategyControllerUpdateStrategyUrl = exports.modelStrategyControllerGetStrategy = exports.getModelStrategyControllerGetStrategyUrl = exports.modelStrategyControllerAdoptTemplate = exports.getModelStrategyControllerAdoptTemplateUrl = exports.modelStrategyControllerListTemplates = exports.getModelStrategyControllerListTemplatesUrl = exports.modelStrategyControllerGetOrgDefaultStatus = exports.getModelStrategyControllerGetOrgDefaultStatusUrl = exports.modelStrategyControllerListStrategies = exports.getModelStrategyControllerListStrategiesUrl = exports.modelStrategyControllerCreateStrategy = exports.getModelStrategyControllerCreateStrategyUrl = void 0;
4
4
  const custom_fetch_1 = require("../../custom-fetch");
5
5
  const getModelStrategyControllerCreateStrategyUrl = () => {
6
6
  return `/model-strategies`;
@@ -118,6 +118,20 @@ const modelStrategyControllerDeleteStrategy = async (id, options) => {
118
118
  });
119
119
  };
120
120
  exports.modelStrategyControllerDeleteStrategy = modelStrategyControllerDeleteStrategy;
121
+ const getModelStrategyControllerGetStrategyDeletionImpactUrl = (id) => {
122
+ return `/model-strategies/${id}/deletion-impact`;
123
+ };
124
+ exports.getModelStrategyControllerGetStrategyDeletionImpactUrl = getModelStrategyControllerGetStrategyDeletionImpactUrl;
125
+ /**
126
+ * @summary What deleting this model strategy would change for projects bound to it
127
+ */
128
+ const modelStrategyControllerGetStrategyDeletionImpact = async (id, options) => {
129
+ return (0, custom_fetch_1.customFetch)((0, exports.getModelStrategyControllerGetStrategyDeletionImpactUrl)(id), {
130
+ ...options,
131
+ method: 'GET'
132
+ });
133
+ };
134
+ exports.modelStrategyControllerGetStrategyDeletionImpact = modelStrategyControllerGetStrategyDeletionImpact;
121
135
  const getModelStrategyControllerUpsertEntriesUrl = (id) => {
122
136
  return `/model-strategies/${id}/entries`;
123
137
  };
@@ -8,4 +8,5 @@ export declare const AgentCapabilityApertureDtoKind: {
8
8
  readonly unrestricted: "unrestricted";
9
9
  readonly armed: "armed";
10
10
  readonly scoped: "scoped";
11
+ readonly representative: "representative";
11
12
  };
@@ -10,4 +10,5 @@ exports.AgentCapabilityApertureDtoKind = {
10
10
  unrestricted: 'unrestricted',
11
11
  armed: 'armed',
12
12
  scoped: 'scoped',
13
+ representative: 'representative',
13
14
  };
@@ -309,6 +309,9 @@ export * from './rollbackAgentRevisionDto';
309
309
  export * from './scopeSource';
310
310
  export * from './standingSessionRefDto';
311
311
  export * from './startEmbeddingMigrationDto';
312
+ export * from './strategyDeletionAffectedProjectDto';
313
+ export * from './strategyDeletionImpactResponseDto';
314
+ export * from './strategyDeletionImpactResponseDtoDataEnvelope';
312
315
  export * from './strategyTemplateAvailabilityDto';
313
316
  export * from './strategyTemplateAvailabilityDtoReasonsItem';
314
317
  export * from './strategyTemplateEntryDto';
@@ -326,6 +326,9 @@ __exportStar(require("./rollbackAgentRevisionDto"), exports);
326
326
  __exportStar(require("./scopeSource"), exports);
327
327
  __exportStar(require("./standingSessionRefDto"), exports);
328
328
  __exportStar(require("./startEmbeddingMigrationDto"), exports);
329
+ __exportStar(require("./strategyDeletionAffectedProjectDto"), exports);
330
+ __exportStar(require("./strategyDeletionImpactResponseDto"), exports);
331
+ __exportStar(require("./strategyDeletionImpactResponseDtoDataEnvelope"), exports);
329
332
  __exportStar(require("./strategyTemplateAvailabilityDto"), exports);
330
333
  __exportStar(require("./strategyTemplateAvailabilityDtoReasonsItem"), exports);
331
334
  __exportStar(require("./strategyTemplateEntryDto"), exports);
@@ -4,6 +4,9 @@
4
4
  * OpenAPI spec version: 0.1.3
5
5
  */
6
6
  import type { ProblemFieldIssueDto } from './problemFieldIssueDto.js';
7
+ /**
8
+ * RFC 9457 problem document. The declared members are the reserved core; extension members are TOP-LEVEL and OPEN, owned by the refusing plane.
9
+ */
7
10
  export interface ProblemDetailsDto {
8
11
  /** Absolute URI identifying the refusal TYPE. Derived one-to-one from `code`, so a caller may branch on either and can never be told two different things. Never `about:blank`. */
9
12
  type: string;
@@ -21,4 +24,5 @@ export interface ProblemDetailsDto {
21
24
  traceId?: string;
22
25
  /** Field-level issues, when the refusal is about the request body. */
23
26
  errors?: ProblemFieldIssueDto[];
27
+ [key: string]: unknown;
24
28
  }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Generated by @xemahq/api-client-generator — do not edit manually.
3
+ * LLM Registry API
4
+ * OpenAPI spec version: 0.1.3
5
+ */
6
+ export interface StrategyDeletionAffectedProjectDto {
7
+ /** Project whose binding cascade-deletes. */
8
+ projectId: string;
9
+ }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * Generated by @xemahq/api-client-generator — do not edit manually.
4
+ * LLM Registry API
5
+ * OpenAPI spec version: 0.1.3
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Generated by @xemahq/api-client-generator — do not edit manually.
3
+ * LLM Registry API
4
+ * OpenAPI spec version: 0.1.3
5
+ */
6
+ import type { StrategyDeletionAffectedProjectDto } from './strategyDeletionAffectedProjectDto.js';
7
+ export interface StrategyDeletionImpactResponseDto {
8
+ strategyId: string;
9
+ displayName: string;
10
+ /** Whether this strategy is the organisation default. When true, deleting it leaves bound projects with no fallback — there is no platform-level default beneath it. */
11
+ isOrgDefault: boolean;
12
+ /** Projects explicitly bound to this strategy. Their bindings cascade-delete. */
13
+ boundProjectCount: number;
14
+ affectedProjects: StrategyDeletionAffectedProjectDto[];
15
+ /**
16
+ * The strategy those projects resolve to after deletion, or null when the organisation would be left with no default at all.
17
+ * @nullable
18
+ */
19
+ fallsBackToStrategyId: string | null;
20
+ /**
21
+ * Display name of `fallsBackToStrategyId`.
22
+ * @nullable
23
+ */
24
+ fallsBackToDisplayName: string | null;
25
+ /** True when at least one project would have NO resolvable strategy after this deletion. The caller should treat this as destructive. */
26
+ leavesProjectsUnresolved: boolean;
27
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Generated by @xemahq/api-client-generator — do not edit manually.
3
+ * LLM Registry API
4
+ * OpenAPI spec version: 0.1.3
5
+ */
6
+ import type { StrategyDeletionImpactResponseDto } from './strategyDeletionImpactResponseDto.js';
7
+ export interface StrategyDeletionImpactResponseDtoDataEnvelope {
8
+ data: StrategyDeletionImpactResponseDto;
9
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xemahq/llm-registry-api-client",
3
- "version": "0.8.7",
3
+ "version": "0.8.9",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
@@ -19,7 +19,7 @@
19
19
  "service": "llm-registry-api",
20
20
  "biome": "agent-runtime",
21
21
  "target": "server",
22
- "generator": "@xemahq/api-client-generator@0.19.0",
22
+ "generator": "@xemahq/api-client-generator@0.21.0",
23
23
  "source": "openapi.public.json"
24
24
  },
25
25
  "license": "LicenseRef-Xema-BSL-1.1",