@pellux/goodvibes-errors 0.30.3 → 0.33.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/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @pellux/goodvibes-errors
2
2
 
3
- Internal workspace package backing `@pellux/goodvibes-sdk/errors`.
3
+ Public GoodVibes error package for structured SDK, transport, and daemon failures.
4
4
 
5
- Consumers should install `@pellux/goodvibes-sdk` and import this surface from the umbrella package.
5
+ Most applications should install `@pellux/goodvibes-sdk` and import `@pellux/goodvibes-sdk/errors`. Install this package directly when you only need the shared error model.
6
6
 
7
7
  Consumer import:
8
8
 
@@ -19,18 +19,18 @@ export declare const DaemonErrorCategory: {
19
19
  export type DaemonErrorSource = 'provider' | 'tool' | 'transport' | 'config' | 'permission' | 'runtime' | 'render' | 'acp' | 'unknown';
20
20
  export interface StructuredDaemonErrorBody {
21
21
  readonly error: string;
22
- readonly hint?: string;
23
- readonly code?: string;
24
- readonly category?: DaemonErrorCategory;
25
- readonly source?: DaemonErrorSource;
26
- readonly recoverable?: boolean;
27
- readonly status?: number;
28
- readonly provider?: string;
29
- readonly operation?: string;
30
- readonly phase?: string;
31
- readonly requestId?: string;
32
- readonly providerCode?: string;
33
- readonly providerType?: string;
34
- readonly retryAfterMs?: number;
22
+ readonly hint?: string | undefined;
23
+ readonly code?: string | undefined;
24
+ readonly category?: DaemonErrorCategory | undefined;
25
+ readonly source?: DaemonErrorSource | undefined;
26
+ readonly recoverable?: boolean | undefined;
27
+ readonly status?: number | undefined;
28
+ readonly provider?: string | undefined;
29
+ readonly operation?: string | undefined;
30
+ readonly phase?: string | undefined;
31
+ readonly requestId?: string | undefined;
32
+ readonly providerCode?: string | undefined;
33
+ readonly providerType?: string | undefined;
34
+ readonly retryAfterMs?: number | undefined;
35
35
  }
36
36
  //# sourceMappingURL=daemon-error-contract.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"daemon-error-contract.d.ts","sourceRoot":"","sources":["../src/daemon-error-contract.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAC3B,gBAAgB,GAChB,eAAe,GACf,SAAS,GACT,YAAY,GACZ,SAAS,GACT,SAAS,GACT,aAAa,GACb,WAAW,GACX,YAAY,GACZ,MAAM,GACN,QAAQ,GACR,UAAU,GACV,SAAS,GACT,UAAU,GACV,SAAS,CAAC;AAEd,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;CAgBwB,CAAC;AAEzD,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,MAAM,GACN,WAAW,GACX,QAAQ,GACR,YAAY,GACZ,SAAS,GACT,QAAQ,GACR,KAAK,GACL,SAAS,CAAC;AAEd,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC"}
1
+ {"version":3,"file":"daemon-error-contract.d.ts","sourceRoot":"","sources":["../src/daemon-error-contract.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAC3B,gBAAgB,GAChB,eAAe,GACf,SAAS,GACT,YAAY,GACZ,SAAS,GACT,SAAS,GACT,aAAa,GACb,WAAW,GACX,YAAY,GACZ,MAAM,GACN,QAAQ,GACR,UAAU,GACV,SAAS,GACT,UAAU,GACV,SAAS,CAAC;AAEd,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;CAgBwB,CAAC;AAEzD,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,MAAM,GACN,WAAW,GACX,QAAQ,GACR,YAAY,GACZ,SAAS,GACT,QAAQ,GACR,KAAK,GACL,SAAS,CAAC;AAEd,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAChD,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5C"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,13 @@
1
1
  import type { DaemonErrorCategory, DaemonErrorSource, StructuredDaemonErrorBody } from './daemon-error-contract.js';
2
2
  export type { DaemonErrorSource, StructuredDaemonErrorBody, } from './daemon-error-contract.js';
3
3
  export { DaemonErrorCategory } from './daemon-error-contract.js';
4
+ /**
5
+ * `'contract'` is an SDK-internal category used when the daemon returns
6
+ * a response that violates the expected contract schema. It is NOT part of the
7
+ * daemon wire schema (`DaemonErrorCategory`) and MUST NOT be marshalled over
8
+ * the wire — doing so will cause the daemon to schema-reject the error envelope.
9
+ * Treat `'contract'` as a local SDK sentinel only.
10
+ */
4
11
  export type ErrorCategory = DaemonErrorCategory | 'contract';
5
12
  export type ErrorSource = DaemonErrorSource | 'contract';
6
13
  /**
@@ -18,23 +25,23 @@ export type ErrorSource = DaemonErrorSource | 'contract';
18
25
  */
19
26
  export type SDKErrorKind = 'auth' | 'config' | 'contract' | 'network' | 'not-found' | 'protocol' | 'rate-limit' | 'service' | 'internal' | 'tool' | 'validation' | 'unknown';
20
27
  export interface GoodVibesSdkErrorOptions {
21
- readonly code?: string;
22
- readonly category?: ErrorCategory;
23
- readonly source?: ErrorSource;
24
- readonly recoverable?: boolean;
25
- readonly status?: number;
26
- readonly url?: string;
27
- readonly method?: string;
28
- readonly body?: unknown;
29
- readonly hint?: string;
30
- readonly provider?: string;
31
- readonly operation?: string;
32
- readonly phase?: string;
33
- readonly requestId?: string;
34
- readonly providerCode?: string;
35
- readonly providerType?: string;
36
- readonly retryAfterMs?: number;
37
- readonly cause?: unknown;
28
+ readonly code?: string | undefined;
29
+ readonly category?: ErrorCategory | undefined;
30
+ readonly source?: ErrorSource | undefined;
31
+ readonly recoverable?: boolean | undefined;
32
+ readonly status?: number | undefined;
33
+ readonly url?: string | undefined;
34
+ readonly method?: string | undefined;
35
+ readonly body?: unknown | undefined;
36
+ readonly hint?: string | undefined;
37
+ readonly provider?: string | undefined;
38
+ readonly operation?: string | undefined;
39
+ readonly phase?: string | undefined;
40
+ readonly requestId?: string | undefined;
41
+ readonly providerCode?: string | undefined;
42
+ readonly providerType?: string | undefined;
43
+ readonly retryAfterMs?: number | undefined;
44
+ readonly cause?: unknown | undefined;
38
45
  }
39
46
  export declare const RETRYABLE_STATUS_CODES: readonly number[];
40
47
  /**
@@ -45,7 +52,7 @@ export declare const RETRYABLE_STATUS_CODES: readonly number[];
45
52
  *
46
53
  * ### Narrowing pattern
47
54
  * ```ts
48
- * import { GoodVibesSdkError, HttpStatusError, ConfigurationError } from '@pellux/goodvibes-sdk';
55
+ * import { GoodVibesSdkError, HttpStatusError, ConfigurationError } from '@pellux/goodvibes-errors';
49
56
  *
50
57
  * try {
51
58
  * await sdk.operator.agents.list();
@@ -62,23 +69,23 @@ export declare const RETRYABLE_STATUS_CODES: readonly number[];
62
69
  */
63
70
  export declare class GoodVibesSdkError extends Error {
64
71
  readonly kind: SDKErrorKind;
65
- readonly code?: string;
72
+ readonly code?: string | undefined;
66
73
  readonly category: ErrorCategory;
67
74
  readonly source: ErrorSource;
68
75
  readonly recoverable: boolean;
69
- readonly status?: number;
70
- readonly url?: string;
71
- readonly method?: string;
72
- readonly body?: unknown;
73
- readonly hint?: string;
74
- readonly provider?: string;
75
- readonly operation?: string;
76
- readonly phase?: string;
77
- readonly requestId?: string;
78
- readonly providerCode?: string;
79
- readonly providerType?: string;
80
- readonly retryAfterMs?: number;
81
- readonly cause?: unknown;
76
+ readonly status?: number | undefined;
77
+ readonly url?: string | undefined;
78
+ readonly method?: string | undefined;
79
+ readonly body?: unknown | undefined;
80
+ readonly hint?: string | undefined;
81
+ readonly provider?: string | undefined;
82
+ readonly operation?: string | undefined;
83
+ readonly phase?: string | undefined;
84
+ readonly requestId?: string | undefined;
85
+ readonly providerCode?: string | undefined;
86
+ readonly providerType?: string | undefined;
87
+ readonly retryAfterMs?: number | undefined;
88
+ readonly cause?: unknown | undefined;
82
89
  static [Symbol.hasInstance](value: unknown): boolean;
83
90
  constructor(message: string, options?: GoodVibesSdkErrorOptions);
84
91
  toJSON(): Record<string, unknown>;
@@ -91,7 +98,7 @@ export declare class GoodVibesSdkError extends Error {
91
98
  * Category: `'config'`. Kind: `'config'`.
92
99
  *
93
100
  * @example
94
- * import { ConfigurationError } from '@pellux/goodvibes-sdk';
101
+ * import { ConfigurationError } from '@pellux/goodvibes-errors';
95
102
  *
96
103
  * try {
97
104
  * await sdk.auth.setToken('x');
@@ -102,6 +109,13 @@ export declare class GoodVibesSdkError extends Error {
102
109
  * }
103
110
  */
104
111
  export declare class ConfigurationError extends GoodVibesSdkError {
112
+ /**
113
+ * Brand contract — `code` is the source of truth, not the prototype chain.
114
+ * A `GoodVibesSdkError` constructed directly with `code: 'SDK_CONFIGURATION_ERROR'`
115
+ * will pass `instanceof ConfigurationError` even if its prototype is only
116
+ * `GoodVibesSdkError`. Callers that need strict prototype checking should use
117
+ * `Object.getPrototypeOf(err) === ConfigurationError.prototype` instead.
118
+ */
105
119
  static [Symbol.hasInstance](value: unknown): boolean;
106
120
  constructor(message: string, options?: GoodVibesSdkErrorOptions);
107
121
  }
@@ -113,7 +127,7 @@ export declare class ConfigurationError extends GoodVibesSdkError {
113
127
  * Category: `'contract'`. Kind: `'contract'`.
114
128
  *
115
129
  * @example
116
- * import { ContractError } from '@pellux/goodvibes-sdk';
130
+ * import { ContractError } from '@pellux/goodvibes-errors';
117
131
  *
118
132
  * try {
119
133
  * const result = await sdk.operator.agents.get({ id: agentId });
@@ -125,6 +139,13 @@ export declare class ConfigurationError extends GoodVibesSdkError {
125
139
  * }
126
140
  */
127
141
  export declare class ContractError extends GoodVibesSdkError {
142
+ /**
143
+ * Brand contract — `code` is the source of truth, not the prototype chain.
144
+ * A `GoodVibesSdkError` constructed directly with `code: 'SDK_CONTRACT_ERROR'`
145
+ * will pass `instanceof ContractError` even if its prototype is only
146
+ * `GoodVibesSdkError`. Callers that need strict prototype checking should use
147
+ * `Object.getPrototypeOf(err) === ContractError.prototype` instead.
148
+ */
128
149
  static [Symbol.hasInstance](value: unknown): boolean;
129
150
  constructor(message: string, options?: GoodVibesSdkErrorOptions);
130
151
  }
@@ -135,12 +156,20 @@ export declare class ContractError extends GoodVibesSdkError {
135
156
  * - `401` → `'authentication'` `402` → `'billing'` `403` → `'authorization'`
136
157
  * - `404` → `'not_found'` `408` → `'timeout'` `429` → `'rate_limit'`
137
158
  * - `5xx` → `'service'`
159
+ * - Any other status (or when constructed without a `status`) → `'unknown'`
160
+ *
161
+ * When constructed without a `status` argument (e.g. as a typed
162
+ * wrapper around a structured daemon error that provides its own `category`),
163
+ * the category defaults to `'unknown'`. Callers relying on category-based
164
+ * routing should always prefer the structured-body factory
165
+ * (`createHttpStatusError`) or check `err.category` directly rather than
166
+ * assuming a specific category from constructor arguments alone.
138
167
  *
139
168
  * Use `recoverable` to decide whether to retry, and `retryAfterMs` for
140
169
  * the backoff hint on rate-limit responses.
141
170
  *
142
171
  * @example
143
- * import { HttpStatusError } from '@pellux/goodvibes-sdk';
172
+ * import { HttpStatusError } from '@pellux/goodvibes-errors';
144
173
  *
145
174
  * try {
146
175
  * await sdk.operator.agents.list();
@@ -155,6 +184,13 @@ export declare class ContractError extends GoodVibesSdkError {
155
184
  * }
156
185
  */
157
186
  export declare class HttpStatusError extends GoodVibesSdkError {
187
+ /**
188
+ * Brand contract — `code` is the source of truth, not the prototype chain.
189
+ * A `GoodVibesSdkError` constructed directly with `code: 'SDK_HTTP_STATUS_ERROR'`
190
+ * will pass `instanceof HttpStatusError` even if its prototype is only
191
+ * `GoodVibesSdkError`. Callers that need strict prototype checking should use
192
+ * `Object.getPrototypeOf(err) === HttpStatusError.prototype` instead.
193
+ */
158
194
  static [Symbol.hasInstance](value: unknown): boolean;
159
195
  constructor(message: string, options?: GoodVibesSdkErrorOptions);
160
196
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -76,7 +76,10 @@ function readErrorCategory(value) {
76
76
  ? value
77
77
  : undefined;
78
78
  }
79
- function inferCategoryFromCause(cause, seen = new Set()) {
79
+ const MAX_ERROR_CAUSE_DEPTH = 32;
80
+ function inferCategoryFromCause(cause, seen = new Set(), depth = 0) {
81
+ if (depth >= MAX_ERROR_CAUSE_DEPTH)
82
+ return undefined;
80
83
  if (!cause || typeof cause !== 'object')
81
84
  return undefined;
82
85
  const objectCause = cause;
@@ -87,9 +90,9 @@ function inferCategoryFromCause(cause, seen = new Set()) {
87
90
  const category = readErrorCategory(record.category);
88
91
  if (category && category !== 'unknown')
89
92
  return category;
90
- return inferCategoryFromCause(record.cause, seen)
91
- ?? inferCategoryFromCause(record.originalError, seen)
92
- ?? inferCategoryFromCause(record.error, seen);
93
+ return inferCategoryFromCause(record.cause, seen, depth + 1)
94
+ ?? inferCategoryFromCause(record.originalError, seen, depth + 1)
95
+ ?? inferCategoryFromCause(record.error, seen, depth + 1);
93
96
  }
94
97
  /**
95
98
  * Base error class for all errors thrown by the GoodVibes SDK.
@@ -99,7 +102,7 @@ function inferCategoryFromCause(cause, seen = new Set()) {
99
102
  *
100
103
  * ### Narrowing pattern
101
104
  * ```ts
102
- * import { GoodVibesSdkError, HttpStatusError, ConfigurationError } from '@pellux/goodvibes-sdk';
105
+ * import { GoodVibesSdkError, HttpStatusError, ConfigurationError } from '@pellux/goodvibes-errors';
103
106
  *
104
107
  * try {
105
108
  * await sdk.operator.agents.list();
@@ -142,12 +145,7 @@ export class GoodVibesSdkError extends Error {
142
145
  if (typeof value !== 'object' || value === null)
143
146
  return false;
144
147
  const record = value;
145
- return record[GOODVIBES_SDK_ERROR_BRAND] === true
146
- || (value instanceof Error
147
- && typeof record.kind === 'string'
148
- && typeof record.category === 'string'
149
- && typeof record.source === 'string'
150
- && typeof record.recoverable === 'boolean');
148
+ return record[GOODVIBES_SDK_ERROR_BRAND] === true;
151
149
  }
152
150
  constructor(message, options = {}) {
153
151
  const category = options.category
@@ -204,14 +202,31 @@ export class GoodVibesSdkError extends Error {
204
202
  });
205
203
  }
206
204
  }
207
- function serializeCause(cause) {
205
+ function serializeCause(cause, seen = new Set(), depth = 0) {
208
206
  if (cause === undefined)
209
207
  return undefined;
208
+ if (depth >= MAX_ERROR_CAUSE_DEPTH)
209
+ return undefined;
210
210
  if (cause instanceof Error) {
211
- return omitUndefined({
212
- name: cause.name,
213
- message: cause.message,
214
- });
211
+ const record = { name: cause.name, message: cause.message };
212
+ // Walk .cause, .originalError, .error chains symmetrically with inferCategoryFromCause.
213
+ const causeRecord = cause;
214
+ const nestedCause = causeRecord.cause ?? causeRecord.originalError ?? causeRecord.error;
215
+ if (nestedCause !== undefined) {
216
+ const objectKey = causeRecord.cause !== undefined ? 'cause' : causeRecord.originalError !== undefined ? 'originalError' : 'error';
217
+ const serialized = typeof nestedCause === 'object' && nestedCause !== null
218
+ ? (seen.has(nestedCause) ? '[Circular]' : serializeCause(nestedCause, new Set([...seen, nestedCause]), depth + 1))
219
+ : serializeCause(nestedCause, seen, depth + 1);
220
+ if (serialized !== undefined)
221
+ record[objectKey] = serialized;
222
+ }
223
+ return omitUndefined(record);
224
+ }
225
+ if (typeof cause === 'object' && cause !== null) {
226
+ if (seen.has(cause))
227
+ return '[Circular]';
228
+ // Serialize plain-object causes (e.g. from transport error payloads) as-is.
229
+ return cause;
215
230
  }
216
231
  return cause;
217
232
  }
@@ -226,7 +241,7 @@ function omitUndefined(record) {
226
241
  * Category: `'config'`. Kind: `'config'`.
227
242
  *
228
243
  * @example
229
- * import { ConfigurationError } from '@pellux/goodvibes-sdk';
244
+ * import { ConfigurationError } from '@pellux/goodvibes-errors';
230
245
  *
231
246
  * try {
232
247
  * await sdk.auth.setToken('x');
@@ -237,14 +252,22 @@ function omitUndefined(record) {
237
252
  * }
238
253
  */
239
254
  export class ConfigurationError extends GoodVibesSdkError {
255
+ /**
256
+ * Brand contract — `code` is the source of truth, not the prototype chain.
257
+ * A `GoodVibesSdkError` constructed directly with `code: 'SDK_CONFIGURATION_ERROR'`
258
+ * will pass `instanceof ConfigurationError` even if its prototype is only
259
+ * `GoodVibesSdkError`. Callers that need strict prototype checking should use
260
+ * `Object.getPrototypeOf(err) === ConfigurationError.prototype` instead.
261
+ */
240
262
  static [Symbol.hasInstance](value) {
241
263
  if (this !== ConfigurationError) {
242
264
  return typeof value === 'object'
243
265
  && value !== null
244
266
  && this.prototype.isPrototypeOf(value);
245
267
  }
246
- return typeof value === 'object'
247
- && value !== null
268
+ // Require both the brand (real SDK error instance) and matching code
269
+ // to prevent plain objects like { code: 'SDK_CONFIGURATION_ERROR' } from passing.
270
+ return GoodVibesSdkError[Symbol.hasInstance](value)
248
271
  && value.code === 'SDK_CONFIGURATION_ERROR';
249
272
  }
250
273
  constructor(message, options = {}) {
@@ -265,7 +288,7 @@ export class ConfigurationError extends GoodVibesSdkError {
265
288
  * Category: `'contract'`. Kind: `'contract'`.
266
289
  *
267
290
  * @example
268
- * import { ContractError } from '@pellux/goodvibes-sdk';
291
+ * import { ContractError } from '@pellux/goodvibes-errors';
269
292
  *
270
293
  * try {
271
294
  * const result = await sdk.operator.agents.get({ id: agentId });
@@ -277,14 +300,22 @@ export class ConfigurationError extends GoodVibesSdkError {
277
300
  * }
278
301
  */
279
302
  export class ContractError extends GoodVibesSdkError {
303
+ /**
304
+ * Brand contract — `code` is the source of truth, not the prototype chain.
305
+ * A `GoodVibesSdkError` constructed directly with `code: 'SDK_CONTRACT_ERROR'`
306
+ * will pass `instanceof ContractError` even if its prototype is only
307
+ * `GoodVibesSdkError`. Callers that need strict prototype checking should use
308
+ * `Object.getPrototypeOf(err) === ContractError.prototype` instead.
309
+ */
280
310
  static [Symbol.hasInstance](value) {
281
311
  if (this !== ContractError) {
282
312
  return typeof value === 'object'
283
313
  && value !== null
284
314
  && this.prototype.isPrototypeOf(value);
285
315
  }
286
- return typeof value === 'object'
287
- && value !== null
316
+ // Require both the brand (real SDK error instance) and matching code
317
+ // to prevent plain objects like { code: 'SDK_CONTRACT_ERROR' } from passing.
318
+ return GoodVibesSdkError[Symbol.hasInstance](value)
288
319
  && value.code === 'SDK_CONTRACT_ERROR';
289
320
  }
290
321
  constructor(message, options = {}) {
@@ -304,12 +335,20 @@ export class ContractError extends GoodVibesSdkError {
304
335
  * - `401` → `'authentication'` `402` → `'billing'` `403` → `'authorization'`
305
336
  * - `404` → `'not_found'` `408` → `'timeout'` `429` → `'rate_limit'`
306
337
  * - `5xx` → `'service'`
338
+ * - Any other status (or when constructed without a `status`) → `'unknown'`
339
+ *
340
+ * When constructed without a `status` argument (e.g. as a typed
341
+ * wrapper around a structured daemon error that provides its own `category`),
342
+ * the category defaults to `'unknown'`. Callers relying on category-based
343
+ * routing should always prefer the structured-body factory
344
+ * (`createHttpStatusError`) or check `err.category` directly rather than
345
+ * assuming a specific category from constructor arguments alone.
307
346
  *
308
347
  * Use `recoverable` to decide whether to retry, and `retryAfterMs` for
309
348
  * the backoff hint on rate-limit responses.
310
349
  *
311
350
  * @example
312
- * import { HttpStatusError } from '@pellux/goodvibes-sdk';
351
+ * import { HttpStatusError } from '@pellux/goodvibes-errors';
313
352
  *
314
353
  * try {
315
354
  * await sdk.operator.agents.list();
@@ -324,16 +363,23 @@ export class ContractError extends GoodVibesSdkError {
324
363
  * }
325
364
  */
326
365
  export class HttpStatusError extends GoodVibesSdkError {
366
+ /**
367
+ * Brand contract — `code` is the source of truth, not the prototype chain.
368
+ * A `GoodVibesSdkError` constructed directly with `code: 'SDK_HTTP_STATUS_ERROR'`
369
+ * will pass `instanceof HttpStatusError` even if its prototype is only
370
+ * `GoodVibesSdkError`. Callers that need strict prototype checking should use
371
+ * `Object.getPrototypeOf(err) === HttpStatusError.prototype` instead.
372
+ */
327
373
  static [Symbol.hasInstance](value) {
328
374
  if (this !== HttpStatusError) {
329
375
  return typeof value === 'object'
330
376
  && value !== null
331
377
  && this.prototype.isPrototypeOf(value);
332
378
  }
333
- if (typeof value !== 'object' || value === null)
334
- return false;
335
- const record = value;
336
- return record.code === 'SDK_HTTP_STATUS_ERROR';
379
+ // Require both the brand (real SDK error instance) and matching code
380
+ // to prevent plain objects like { code: 'SDK_HTTP_STATUS_ERROR' } from passing.
381
+ return GoodVibesSdkError[Symbol.hasInstance](value)
382
+ && value.code === 'SDK_HTTP_STATUS_ERROR';
337
383
  }
338
384
  constructor(message, options = {}) {
339
385
  super(message, {
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@pellux/goodvibes-errors",
3
- "version": "0.30.3",
3
+ "version": "0.33.0",
4
4
  "engines": {
5
- "node": ">=20.0.0"
5
+ "bun": "1.3.10",
6
+ "node": ">=22.0.0"
6
7
  },
7
8
  "description": "Structured SDK, transport, and daemon error types for GoodVibes integrations.",
8
9
  "type": "module",