@xemahq/llm-registry-api-client 0.8.12 → 0.8.13

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.
@@ -97,6 +97,7 @@ export declare class ClientError extends Error {
97
97
  readonly url: string;
98
98
  readonly body: unknown;
99
99
  constructor(status: number, url: string, body: unknown);
100
+ static [Symbol.hasInstance](candidate: unknown): boolean;
100
101
  }
101
102
  export declare function configureClient(config: ClientConfig): void;
102
103
  export declare function getClientConfig(): ClientConfig;
@@ -19,6 +19,50 @@ Object.defineProperty(exports, "__esModule", { value: true });
19
19
  exports.customFetch = exports.ClientError = void 0;
20
20
  exports.configureClient = configureClient;
21
21
  exports.getClientConfig = getClientConfig;
22
+ /**
23
+ * Cross-package identity for `ClientError`.
24
+ *
25
+ * ── THE OUTAGE THIS IS FOR ────────────────────────────────────────────────
26
+ *
27
+ * PRODUCTION, 2026-09-22. A session launch aborted on
28
+ * `HTTP 503 from http://skill-registry-api…/skills`. A 503 is the archetypal
29
+ * TRANSIENT — agent-session's launch taxonomy already listed it as retryable —
30
+ * but it was classified PERMANENT and the launch was abandoned.
31
+ *
32
+ * The cause was this file. Every generated client package gets its OWN copy of
33
+ * `ClientError`, so there are as many classes as there are clients (81 at the
34
+ * time of writing), all byte-identical and all DIFFERENT OBJECTS. A consumer
35
+ * naturally writes `err instanceof ClientError` against the one client it
36
+ * imported — which reads as obviously correct and is silently package-local. An
37
+ * error from any OTHER client fails it, falls past every status check, and lands
38
+ * on whatever the default is.
39
+ *
40
+ * That was not the first time: biome-host had already switched to structural
41
+ * detection for the same reason, and canopy imports TWO `ClientError` classes
42
+ * and tests both. Three more call sites elsewhere carry the same shape.
43
+ *
44
+ * ── WHY A BRAND AND NOT A SHARED PACKAGE ─────────────────────────────────
45
+ *
46
+ * The obvious fix is one shared runtime class every client imports. It was
47
+ * rejected on measurement: the 81 generated clients are DEPENDENCY-FREE by
48
+ * design (exactly one has any dependency at all), and a shared class would have
49
+ * to be a PEER dependency to be safe — a normal dependency can be installed
50
+ * twice under version skew, which reinstates this identical bug in a form that
51
+ * is HARDER to see, because the classes then look like they ought to match.
52
+ *
53
+ * `Symbol.for` is a process-wide registry keyed by STRING, so every copy of
54
+ * this template resolves the same symbol without importing anything. The brand
55
+ * costs no dependency, cannot skew, and needs no new package.
56
+ *
57
+ * `Symbol.hasInstance` then makes plain `instanceof` mean the right thing
58
+ * fleet-wide: an error from ANY generated client satisfies `instanceof
59
+ * ClientError` in ANY other. A helper would have made the safe pattern
60
+ * available; this makes the dangerous pattern impossible.
61
+ *
62
+ * Narrow on purpose — the brand is set only by this constructor, so an unrelated
63
+ * error carrying a `status` is not admitted.
64
+ */
65
+ const CLIENT_ERROR_BRAND = Symbol.for('xema.generatedClientError');
22
66
  class ClientError extends Error {
23
67
  status;
24
68
  url;
@@ -29,6 +73,14 @@ class ClientError extends Error {
29
73
  this.url = url;
30
74
  this.body = body;
31
75
  this.name = 'ClientError';
76
+ // Non-enumerable: it must not appear in JSON, logs or snapshots — it is an
77
+ // identity marker, not payload.
78
+ Object.defineProperty(this, CLIENT_ERROR_BRAND, { value: true });
79
+ }
80
+ static [Symbol.hasInstance](candidate) {
81
+ return (typeof candidate === 'object' &&
82
+ candidate !== null &&
83
+ CLIENT_ERROR_BRAND in candidate);
32
84
  }
33
85
  }
34
86
  exports.ClientError = ClientError;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xemahq/llm-registry-api-client",
3
- "version": "0.8.12",
3
+ "version": "0.8.13",
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.21.0",
22
+ "generator": "@xemahq/api-client-generator@1.1.2",
23
23
  "source": "openapi.public.json"
24
24
  },
25
25
  "license": "LicenseRef-Xema-BSL-1.1",