@loomcycle/client 1.105.0 → 1.107.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/errors.d.ts CHANGED
@@ -20,9 +20,16 @@
20
20
  export declare class LoomcycleError extends Error {
21
21
  readonly status?: number;
22
22
  readonly bodyText?: string;
23
+ /** The machine-readable `code` of a JSON error body (`model_not_allowed`,
24
+ * `token_limit_exceeded`, `per_user_quota_exhausted`, …), on whichever
25
+ * class the status maps to. Undefined when the body is not JSON or carries
26
+ * no string `code`. Read from the whole body, so it survives where
27
+ * `bodyText` is cut at 1 KiB. Branch on this, not on the message. */
28
+ readonly code?: string;
23
29
  constructor(message: string, opts?: {
24
30
  status?: number;
25
31
  bodyText?: string;
32
+ code?: string;
26
33
  });
27
34
  }
28
35
  /** Base class for every HTTP 404 the client surfaces. Lets callers
@@ -34,36 +41,91 @@ export declare class NotFoundError extends LoomcycleError {
34
41
  constructor(message: string, opts?: {
35
42
  status?: number;
36
43
  bodyText?: string;
44
+ code?: string;
37
45
  });
38
46
  }
39
47
  export declare class AgentNotFoundError extends NotFoundError {
40
48
  constructor(message: string, opts?: {
41
49
  status?: number;
42
50
  bodyText?: string;
51
+ code?: string;
43
52
  });
44
53
  }
45
54
  export declare class SessionNotFoundError extends NotFoundError {
46
55
  constructor(message: string, opts?: {
47
56
  status?: number;
48
57
  bodyText?: string;
58
+ code?: string;
49
59
  });
50
60
  }
51
61
  export declare class SessionBusyError extends LoomcycleError {
52
62
  constructor(message: string, opts?: {
53
63
  status?: number;
54
64
  bodyText?: string;
65
+ code?: string;
55
66
  });
56
67
  }
57
68
  export declare class AgentIDInUseError extends LoomcycleError {
58
69
  constructor(message: string, opts?: {
59
70
  status?: number;
60
71
  bodyText?: string;
72
+ code?: string;
61
73
  });
62
74
  }
75
+ /** Every HTTP 429 that is not a per-user quota. A plain BackpressureError is
76
+ * the transient case (the server is busy; back off and retry). It has one
77
+ * subclass that is NOT transient, TokenLimitExceededError — check for that
78
+ * first when deciding whether to retry. */
63
79
  export declare class BackpressureError extends LoomcycleError {
64
80
  constructor(message: string, opts?: {
65
81
  status?: number;
66
82
  bodyText?: string;
83
+ code?: string;
84
+ });
85
+ }
86
+ /**
87
+ * TokenLimitExceededError signals that the caller is at a hard token budget:
88
+ * HTTP 429 with body code `token_limit_exceeded`, from run creation and from
89
+ * `decide()`.
90
+ *
91
+ * Do not retry it the way you retry backpressure. The budget is a calendar
92
+ * month's tokens for an operator, tenant or user; the same call is refused
93
+ * until an operator raises the budget or the window rolls over.
94
+ *
95
+ * It extends BackpressureError only so that code written before this class
96
+ * existed, which caught this refusal with `instanceof BackpressureError`,
97
+ * keeps catching it. Test for this class BEFORE BackpressureError:
98
+ *
99
+ * if (e instanceof TokenLimitExceededError) {
100
+ * // not retryable now: report e.scope / e.used / e.limit
101
+ * } else if (e instanceof BackpressureError) {
102
+ * // transient: back off and retry
103
+ * }
104
+ *
105
+ * The fields come from the response body and are null when the server did
106
+ * not send them.
107
+ */
108
+ export declare class TokenLimitExceededError extends BackpressureError {
109
+ /** Whose budget was hit: "operator", "tenant" or "user". */
110
+ readonly scope: string | null;
111
+ /** The id of that scope: the tenant id or the user subject. Null for the
112
+ * operator-wide budget, and where the server withholds it. */
113
+ readonly scopeId: string | null;
114
+ /** Tokens the scope has used in the current window. */
115
+ readonly used: number | null;
116
+ /** The hard ceiling that was reached, in tokens. */
117
+ readonly limit: number | null;
118
+ /** The budget window, e.g. "month" (a calendar month, UTC). */
119
+ readonly window: string | null;
120
+ constructor(message: string, opts?: {
121
+ status?: number;
122
+ bodyText?: string;
123
+ code?: string;
124
+ scope?: string;
125
+ scopeId?: string;
126
+ used?: number;
127
+ limit?: number;
128
+ window?: string;
67
129
  });
68
130
  }
69
131
  /**
@@ -111,6 +173,7 @@ export declare class PerUserQuotaExhaustedError extends LoomcycleError {
111
173
  constructor(message: string, opts?: {
112
174
  status?: number;
113
175
  bodyText?: string;
176
+ code?: string;
114
177
  userId?: string;
115
178
  cap?: number;
116
179
  retryAfterMs?: number;
@@ -120,18 +183,21 @@ export declare class AuthError extends LoomcycleError {
120
183
  constructor(message: string, opts?: {
121
184
  status?: number;
122
185
  bodyText?: string;
186
+ code?: string;
123
187
  });
124
188
  }
125
189
  export declare class UnavailableError extends LoomcycleError {
126
190
  constructor(message: string, opts?: {
127
191
  status?: number;
128
192
  bodyText?: string;
193
+ code?: string;
129
194
  });
130
195
  }
131
196
  export declare class InvalidArgumentError extends LoomcycleError {
132
197
  constructor(message: string, opts?: {
133
198
  status?: number;
134
199
  bodyText?: string;
200
+ code?: string;
135
201
  });
136
202
  }
137
203
  /** Subclasses UnavailableError for back-compat: code that broadly
@@ -141,36 +207,76 @@ export declare class PauseNotConfiguredError extends UnavailableError {
141
207
  constructor(message: string, opts?: {
142
208
  status?: number;
143
209
  bodyText?: string;
210
+ code?: string;
144
211
  });
145
212
  }
146
213
  export declare class AlreadyPausingError extends LoomcycleError {
147
214
  constructor(message: string, opts?: {
148
215
  status?: number;
149
216
  bodyText?: string;
217
+ code?: string;
150
218
  });
151
219
  }
152
220
  export declare class NotPausedError extends LoomcycleError {
153
221
  constructor(message: string, opts?: {
154
222
  status?: number;
155
223
  bodyText?: string;
224
+ code?: string;
156
225
  });
157
226
  }
158
227
  export declare class SnapshotNotFoundError extends NotFoundError {
159
228
  constructor(message: string, opts?: {
160
229
  status?: number;
161
230
  bodyText?: string;
231
+ code?: string;
162
232
  });
163
233
  }
234
+ /** A snapshot envelope over the size cap (HTTP 413, body code
235
+ * `snapshot_too_large`).
236
+ *
237
+ * For compatibility it is ALSO the base class of every other 413: until
238
+ * RequestTooLargeError and PromptTooLargeError existed, the client raised
239
+ * this class for any 413, so `instanceof SnapshotTooLargeError` is true for
240
+ * all of them and stays true. To single out a snapshot that is too large,
241
+ * test `e.code === "snapshot_too_large"`. */
164
242
  export declare class SnapshotTooLargeError extends LoomcycleError {
165
243
  constructor(message: string, opts?: {
166
244
  status?: number;
167
245
  bodyText?: string;
246
+ code?: string;
247
+ });
248
+ }
249
+ /** An HTTP 413 that is not about a snapshot: a request body over the server's
250
+ * size limit (`request_too_large`, or a plain-text 413 with no code), a
251
+ * memory value or quota (`memory_value_too_large`, `memory_quota_exceeded`),
252
+ * a channel payload (`payload_too_large`). `e.code` says which.
253
+ *
254
+ * It extends SnapshotTooLargeError only because that is the class these
255
+ * responses were raised as before this one existed; the relation keeps an
256
+ * existing `instanceof SnapshotTooLargeError` matching and says nothing about
257
+ * snapshots. */
258
+ export declare class RequestTooLargeError extends SnapshotTooLargeError {
259
+ constructor(message: string, opts?: {
260
+ status?: number;
261
+ bodyText?: string;
262
+ code?: string;
263
+ });
264
+ }
265
+ /** A `decide()` request that does not fit the decision model's context (HTTP
266
+ * 413, body code `prompt_too_large`). The server never shortens it for you:
267
+ * shorten `state` or ask fewer questions, then send it again. */
268
+ export declare class PromptTooLargeError extends RequestTooLargeError {
269
+ constructor(message: string, opts?: {
270
+ status?: number;
271
+ bodyText?: string;
272
+ code?: string;
168
273
  });
169
274
  }
170
275
  export declare class SnapshotVersionError extends LoomcycleError {
171
276
  constructor(message: string, opts?: {
172
277
  status?: number;
173
278
  bodyText?: string;
279
+ code?: string;
174
280
  });
175
281
  }
176
282
  /** ChannelCursorRegressionError — raised by `client.ackChannel()`
@@ -187,6 +293,7 @@ export declare class ChannelCursorRegressionError extends LoomcycleError {
187
293
  constructor(message: string, opts?: {
188
294
  status?: number;
189
295
  bodyText?: string;
296
+ code?: string;
190
297
  });
191
298
  }
192
299
  /** SubstrateToolRefusedError — raised by `client.agentDef()` /
@@ -205,6 +312,7 @@ export declare class SubstrateToolRefusedError extends LoomcycleError {
205
312
  constructor(message: string, opts?: {
206
313
  status?: number;
207
314
  bodyText?: string;
315
+ code?: string;
208
316
  tool?: string;
209
317
  });
210
318
  }
package/dist/errors.js CHANGED
@@ -20,11 +20,18 @@
20
20
  export class LoomcycleError extends Error {
21
21
  status;
22
22
  bodyText;
23
+ /** The machine-readable `code` of a JSON error body (`model_not_allowed`,
24
+ * `token_limit_exceeded`, `per_user_quota_exhausted`, …), on whichever
25
+ * class the status maps to. Undefined when the body is not JSON or carries
26
+ * no string `code`. Read from the whole body, so it survives where
27
+ * `bodyText` is cut at 1 KiB. Branch on this, not on the message. */
28
+ code;
23
29
  constructor(message, opts) {
24
30
  super(message);
25
31
  this.name = "LoomcycleError";
26
32
  this.status = opts?.status;
27
33
  this.bodyText = opts?.bodyText;
34
+ this.code = opts?.code;
28
35
  }
29
36
  }
30
37
  /** Base class for every HTTP 404 the client surfaces. Lets callers
@@ -62,12 +69,60 @@ export class AgentIDInUseError extends LoomcycleError {
62
69
  this.name = "AgentIDInUseError";
63
70
  }
64
71
  }
72
+ /** Every HTTP 429 that is not a per-user quota. A plain BackpressureError is
73
+ * the transient case (the server is busy; back off and retry). It has one
74
+ * subclass that is NOT transient, TokenLimitExceededError — check for that
75
+ * first when deciding whether to retry. */
65
76
  export class BackpressureError extends LoomcycleError {
66
77
  constructor(message, opts) {
67
78
  super(message, opts);
68
79
  this.name = "BackpressureError";
69
80
  }
70
81
  }
82
+ /**
83
+ * TokenLimitExceededError signals that the caller is at a hard token budget:
84
+ * HTTP 429 with body code `token_limit_exceeded`, from run creation and from
85
+ * `decide()`.
86
+ *
87
+ * Do not retry it the way you retry backpressure. The budget is a calendar
88
+ * month's tokens for an operator, tenant or user; the same call is refused
89
+ * until an operator raises the budget or the window rolls over.
90
+ *
91
+ * It extends BackpressureError only so that code written before this class
92
+ * existed, which caught this refusal with `instanceof BackpressureError`,
93
+ * keeps catching it. Test for this class BEFORE BackpressureError:
94
+ *
95
+ * if (e instanceof TokenLimitExceededError) {
96
+ * // not retryable now: report e.scope / e.used / e.limit
97
+ * } else if (e instanceof BackpressureError) {
98
+ * // transient: back off and retry
99
+ * }
100
+ *
101
+ * The fields come from the response body and are null when the server did
102
+ * not send them.
103
+ */
104
+ export class TokenLimitExceededError extends BackpressureError {
105
+ /** Whose budget was hit: "operator", "tenant" or "user". */
106
+ scope;
107
+ /** The id of that scope: the tenant id or the user subject. Null for the
108
+ * operator-wide budget, and where the server withholds it. */
109
+ scopeId;
110
+ /** Tokens the scope has used in the current window. */
111
+ used;
112
+ /** The hard ceiling that was reached, in tokens. */
113
+ limit;
114
+ /** The budget window, e.g. "month" (a calendar month, UTC). */
115
+ window;
116
+ constructor(message, opts) {
117
+ super(message, opts);
118
+ this.name = "TokenLimitExceededError";
119
+ this.scope = opts?.scope ?? null;
120
+ this.scopeId = opts?.scopeId ?? null;
121
+ this.used = opts?.used ?? null;
122
+ this.limit = opts?.limit ?? null;
123
+ this.window = opts?.window ?? null;
124
+ }
125
+ }
71
126
  /**
72
127
  * PerUserQuotaExhaustedError signals that the caller has hit their
73
128
  * per-user cap on in-flight (active+queued) runs. Distinct from
@@ -164,12 +219,44 @@ export class SnapshotNotFoundError extends NotFoundError {
164
219
  this.name = "SnapshotNotFoundError";
165
220
  }
166
221
  }
222
+ /** A snapshot envelope over the size cap (HTTP 413, body code
223
+ * `snapshot_too_large`).
224
+ *
225
+ * For compatibility it is ALSO the base class of every other 413: until
226
+ * RequestTooLargeError and PromptTooLargeError existed, the client raised
227
+ * this class for any 413, so `instanceof SnapshotTooLargeError` is true for
228
+ * all of them and stays true. To single out a snapshot that is too large,
229
+ * test `e.code === "snapshot_too_large"`. */
167
230
  export class SnapshotTooLargeError extends LoomcycleError {
168
231
  constructor(message, opts) {
169
232
  super(message, opts);
170
233
  this.name = "SnapshotTooLargeError";
171
234
  }
172
235
  }
236
+ /** An HTTP 413 that is not about a snapshot: a request body over the server's
237
+ * size limit (`request_too_large`, or a plain-text 413 with no code), a
238
+ * memory value or quota (`memory_value_too_large`, `memory_quota_exceeded`),
239
+ * a channel payload (`payload_too_large`). `e.code` says which.
240
+ *
241
+ * It extends SnapshotTooLargeError only because that is the class these
242
+ * responses were raised as before this one existed; the relation keeps an
243
+ * existing `instanceof SnapshotTooLargeError` matching and says nothing about
244
+ * snapshots. */
245
+ export class RequestTooLargeError extends SnapshotTooLargeError {
246
+ constructor(message, opts) {
247
+ super(message, opts);
248
+ this.name = "RequestTooLargeError";
249
+ }
250
+ }
251
+ /** A `decide()` request that does not fit the decision model's context (HTTP
252
+ * 413, body code `prompt_too_large`). The server never shortens it for you:
253
+ * shorten `state` or ask fewer questions, then send it again. */
254
+ export class PromptTooLargeError extends RequestTooLargeError {
255
+ constructor(message, opts) {
256
+ super(message, opts);
257
+ this.name = "PromptTooLargeError";
258
+ }
259
+ }
173
260
  export class SnapshotVersionError extends LoomcycleError {
174
261
  constructor(message, opts) {
175
262
  super(message, opts);
@@ -88,15 +88,23 @@ export declare function deleteJSON<T>(ctx: _FetchContext, path: string, opts?: {
88
88
  * 409 + "session" → SessionBusyError
89
89
  * 409 + "agent_id" → AgentIDInUseError
90
90
  * 409 + (other) → LoomcycleError (base)
91
- * 413 → SnapshotTooLargeError
91
+ * 413 + code "snapshot_too_large" → SnapshotTooLargeError ──┐ all are
92
+ * 413 + code "prompt_too_large" → PromptTooLargeError │ instanceof
93
+ * 413 (other) → RequestTooLargeError ───┘ SnapshotTooLargeError
92
94
  * 422 → SnapshotVersionError (snapshot-version-too-new/unknown)
93
- * 429 → BackpressureError
95
+ * 429 + code "per_user_quota_exhausted" → PerUserQuotaExhaustedError
96
+ * 429 + code "token_limit_exceeded" → TokenLimitExceededError
97
+ * (subclass of BackpressureError)
98
+ * 429 (other) → BackpressureError
94
99
  * 503 + "pause manager not configured" → PauseNotConfiguredError
95
100
  * (subclass of UnavailableError)
96
101
  * 503 + (other) → UnavailableError
97
102
  * 500-599 (other) → LoomcycleError (base)
98
103
  * default → LoomcycleError (base)
99
104
  *
105
+ * Whatever class the status maps to, a JSON body's string `code` is on the
106
+ * error as `code` (see bodyCode).
107
+ *
100
108
  * Priority within a status group is most-specific-first; an unknown
101
109
  * 409 falls through to base LoomcycleError so callers see a
102
110
  * meaningful message + status. For 404, the catch-all is NotFoundError
@@ -9,7 +9,7 @@
9
9
  * Method-level code in client.ts stays focused on URL + body shape;
10
10
  * the boring fetch + error-translation machinery lives here.
11
11
  */
12
- import { AgentIDInUseError, AgentNotFoundError, AlreadyPausingError, AuthError, BackpressureError, ChannelCursorRegressionError, InvalidArgumentError, LoomcycleError, NotFoundError, NotPausedError, PauseNotConfiguredError, PerUserQuotaExhaustedError, SessionBusyError, SessionNotFoundError, SnapshotNotFoundError, SnapshotTooLargeError, SnapshotVersionError, SubstrateToolRefusedError, UnavailableError, } from "./errors.js";
12
+ import { AgentIDInUseError, AgentNotFoundError, AlreadyPausingError, AuthError, BackpressureError, ChannelCursorRegressionError, InvalidArgumentError, LoomcycleError, NotFoundError, NotPausedError, PauseNotConfiguredError, PerUserQuotaExhaustedError, PromptTooLargeError, RequestTooLargeError, SessionBusyError, SessionNotFoundError, SnapshotNotFoundError, SnapshotTooLargeError, SnapshotVersionError, SubstrateToolRefusedError, TokenLimitExceededError, UnavailableError, } from "./errors.js";
13
13
  /** authHeaders builds the standard request header set: JSON Accept
14
14
  * + Bearer token when the client was constructed with one. The
15
15
  * caller adds Content-Type when posting a body. */
@@ -168,15 +168,23 @@ export async function deleteJSON(ctx, path, opts) {
168
168
  * 409 + "session" → SessionBusyError
169
169
  * 409 + "agent_id" → AgentIDInUseError
170
170
  * 409 + (other) → LoomcycleError (base)
171
- * 413 → SnapshotTooLargeError
171
+ * 413 + code "snapshot_too_large" → SnapshotTooLargeError ──┐ all are
172
+ * 413 + code "prompt_too_large" → PromptTooLargeError │ instanceof
173
+ * 413 (other) → RequestTooLargeError ───┘ SnapshotTooLargeError
172
174
  * 422 → SnapshotVersionError (snapshot-version-too-new/unknown)
173
- * 429 → BackpressureError
175
+ * 429 + code "per_user_quota_exhausted" → PerUserQuotaExhaustedError
176
+ * 429 + code "token_limit_exceeded" → TokenLimitExceededError
177
+ * (subclass of BackpressureError)
178
+ * 429 (other) → BackpressureError
174
179
  * 503 + "pause manager not configured" → PauseNotConfiguredError
175
180
  * (subclass of UnavailableError)
176
181
  * 503 + (other) → UnavailableError
177
182
  * 500-599 (other) → LoomcycleError (base)
178
183
  * default → LoomcycleError (base)
179
184
  *
185
+ * Whatever class the status maps to, a JSON body's string `code` is on the
186
+ * error as `code` (see bodyCode).
187
+ *
180
188
  * Priority within a status group is most-specific-first; an unknown
181
189
  * 409 falls through to base LoomcycleError so callers see a
182
190
  * meaningful message + status. For 404, the catch-all is NotFoundError
@@ -202,7 +210,7 @@ export async function raiseFromResponse(resp) {
202
210
  // ("401 Unauthorized" not "401 " with a trailing space).
203
211
  const statusPhrase = resp.statusText || stockStatusPhrase(status);
204
212
  const msg = bodyText.trim() ? bodyText.slice(0, 1024) : `${status} ${statusPhrase}`;
205
- const opts = { status, bodyText: bodyText.slice(0, 1024) };
213
+ const opts = { status, bodyText: bodyText.slice(0, 1024), code: bodyCode(bodyText) };
206
214
  switch (status) {
207
215
  case 400:
208
216
  throw new InvalidArgumentError(msg, opts);
@@ -238,7 +246,14 @@ export async function raiseFromResponse(resp) {
238
246
  throw new AgentIDInUseError(msg, opts);
239
247
  throw new LoomcycleError(msg, opts);
240
248
  case 413:
241
- throw new SnapshotTooLargeError(msg, opts);
249
+ // Every 413 used to be a SnapshotTooLargeError, so the two classes
250
+ // below extend it: an existing `instanceof SnapshotTooLargeError`
251
+ // still matches all three.
252
+ if (opts.code === "snapshot_too_large")
253
+ throw new SnapshotTooLargeError(msg, opts);
254
+ if (opts.code === "prompt_too_large")
255
+ throw new PromptTooLargeError(msg, opts);
256
+ throw new RequestTooLargeError(msg, opts);
242
257
  case 422: {
243
258
  // 422 is shared between snapshot version errors (existing)
244
259
  // and v0.8.22 substrate tool refusals. Discriminate by body:
@@ -247,7 +262,7 @@ export async function raiseFromResponse(resp) {
247
262
  try {
248
263
  const parsed = JSON.parse(bodyText);
249
264
  if (parsed.code === "tool_refused") {
250
- throw new SubstrateToolRefusedError(parsed.error ?? msg, { status, bodyText, tool: parsed.tool });
265
+ throw new SubstrateToolRefusedError(parsed.error ?? msg, { status, bodyText, code: parsed.code, tool: parsed.tool });
251
266
  }
252
267
  }
253
268
  catch (e) {
@@ -259,6 +274,20 @@ export async function raiseFromResponse(resp) {
259
274
  throw new SnapshotVersionError(msg, opts);
260
275
  }
261
276
  case 429: {
277
+ // A hard token budget is not transient the way backpressure is, so
278
+ // it gets its own class (a BackpressureError subclass, for callers
279
+ // that already catch that).
280
+ if (opts.code === "token_limit_exceeded") {
281
+ const body = bodyObject(bodyText) ?? {};
282
+ throw new TokenLimitExceededError(msg, {
283
+ ...opts,
284
+ scope: stringField(body.scope),
285
+ scopeId: stringField(body.scope_id),
286
+ used: numberField(body.used),
287
+ limit: numberField(body.limit),
288
+ window: stringField(body.window),
289
+ });
290
+ }
262
291
  // v0.10.1: distinguish per-user quota exhaustion from
263
292
  // operator-wide backpressure. The shapes share the 429 status
264
293
  // but the JSON body's `code` field discriminates. Consumers
@@ -274,6 +303,7 @@ export async function raiseFromResponse(resp) {
274
303
  throw new PerUserQuotaExhaustedError(parsed.error ?? msg, {
275
304
  status,
276
305
  bodyText,
306
+ code: parsed.code,
277
307
  userId: parsed.user_id,
278
308
  cap: parsed.cap,
279
309
  retryAfterMs: Number.isFinite(retryAfterMs) ? retryAfterMs : undefined,
@@ -295,6 +325,36 @@ export async function raiseFromResponse(resp) {
295
325
  throw new LoomcycleError(msg, opts);
296
326
  }
297
327
  }
328
+ /** bodyCode returns the string `code` of a JSON error body, or undefined when
329
+ * the body is not a JSON object or has none. Statuses are shared between
330
+ * unrelated conditions (a 400 is any bad request; a 429 is backpressure, a
331
+ * user quota or a token budget), and the code is what tells them apart. */
332
+ function bodyCode(bodyText) {
333
+ return stringField(bodyObject(bodyText)?.code);
334
+ }
335
+ /** bodyObject returns a JSON error body as an object, or undefined when the
336
+ * body is not JSON or is a JSON array or scalar. */
337
+ function bodyObject(bodyText) {
338
+ try {
339
+ const parsed = JSON.parse(bodyText);
340
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
341
+ return parsed;
342
+ }
343
+ }
344
+ catch {
345
+ // not JSON: a plain-text error body has no fields
346
+ }
347
+ return undefined;
348
+ }
349
+ /** stringField / numberField read one body field, dropping a value of the
350
+ * wrong type: an error's typed fields must not carry whatever a proxy or an
351
+ * older server put under that name. An empty string counts as absent. */
352
+ function stringField(v) {
353
+ return typeof v === "string" && v !== "" ? v : undefined;
354
+ }
355
+ function numberField(v) {
356
+ return typeof v === "number" && Number.isFinite(v) ? v : undefined;
357
+ }
298
358
  /** stockStatusPhrase returns a stock reason phrase for the common
299
359
  * HTTP statuses raiseFromResponse handles. Used as a fallback when
300
360
  * Response.statusText is empty (HTTP/2 strips reason phrases). */
package/dist/index.d.ts CHANGED
@@ -115,7 +115,9 @@
115
115
  * AuthError, UnavailableError, InvalidArgumentError,
116
116
  * PauseNotConfiguredError (subclass of UnavailableError),
117
117
  * AlreadyPausingError, NotPausedError, SnapshotNotFoundError,
118
- * SnapshotTooLargeError, SnapshotVersionError,
118
+ * SnapshotTooLargeError, RequestTooLargeError + PromptTooLargeError
119
+ * (both subclasses of SnapshotTooLargeError), TokenLimitExceededError
120
+ * (subclass of BackpressureError), SnapshotVersionError,
119
121
  * SubstrateToolRefusedError (v0.8.22)
120
122
  *
121
123
  * Transport: HTTP+SSE. Auth: Bearer token via the Authorization
@@ -130,5 +132,5 @@ export { InteractiveSession } from "./interactive.js";
130
132
  export type { InteractiveSessionOps } from "./interactive.js";
131
133
  export { ClientToolHost, clientToolsURL, CLIENT_TOOL_SUBPROTOCOL } from "./client-tools.js";
132
134
  export type { ClientToolSchema, ClientToolInvocation, ConnectClientToolsOptions, WebSocketLike, WebSocketCtor, } from "./client-tools.js";
133
- export type { AgentEvent, ClientOptions, ContinueOptions, EventType, HostWidening, ImageMediaType, ParentContext, PromptContent, PromptSegment, RetryInfo, RunOptions, SamplingOptions, CompactionOptions, ContextOptions, ToolUse, Usage, CallTiming, Agent, AgentStatus, AwaitedState, AgentUsage, RunResult, RunSpec, RunSpecTeam, ConfiguredRun, ConfiguredRunPatch, ToolChoiceOptions, OutputFormatOptions, CancelAgentResult, ListAgentsResponse, WalkRunsPage, RunBatchOptions, RunBatchResult, SpawnRunResult, CompactRunResult, DirectoryBudget, DirectoryInspection, DirectoryTenant, DirectoryUser, ErasureReport, ErasureResidue, ErasureResult, ErasureTier, CancelTurnResult, ReviewRunResult, TranscriptEvent, TranscriptResponse, HealthResponse, ListUsersResponse, UserSummary, UserRecord, CreateUserBody, UpdateUserBody, MintedUserToken, UserTokenMeta, ListUserTokensResponse, RunnableAgent, RunnableAgentsResponse, WhoamiResponse, PauseResult, ResumeResult, RuntimeStateResponse, RuntimeStateStatus, ResolverMatrix, ResolverModelStatus, ResolverProviderAvailability, CreateSnapshotOptions, SnapshotCreateResponse, SnapshotDescriptor, SnapshotEnvelope, SnapshotListResponse, SnapshotRestoreResponse, MemoryEntriesResponse, MemoryEntry, MemoryEntryResponse, MemoryScopeIDsResponse, MemoryScopeIDSummary, MemoryScopeKind, MemoryScopesResponse, MemorySearchInput, MemorySource, MemoryWhen, MemoryTimeFilter, MemorySearchEntry, MemorySearchResponse, MemoryEmbedModelStats, MemoryEmbedStatsResponse, MemoryReembedConfigured, MemoryReembedResponse, MemoryBackfillResponse, MemoryPurgeResponse, InterruptListResponse, InterruptRow, InterruptStatus, ResolveInterruptOptions, ChannelHookCall, ChannelHookResult, HookFailMode, HookPhase, HookToolCall, HookToolResult, PostHookCall, PostHookResult, PreHookCall, PreHookResult, SubstrateToolInput, SubstrateToolResponse, TeamNameSummary, ListTeamsResponse, TeamDiagram, CreatedTeam, PromotedTeam, RetiredTeam, TeamDefDetail, TeamVerification, TeamDraft, TeamDraftVerification, TeamIssue, TeamIssueKind, TeamVersion, TeamVersionList, TeamBreakpoints, TeamRunDetached, TeamRunResult, TeamRunTarget, PathToolInput, PathToolResponse, DocumentToolInput, DocumentToolResponse, HistoryToolInput, HistoryToolResponse, VolumeMode, PersistentVolumeEntry, PersistentVolumesResponse, EphemeralVolumeEntry, EphemeralVolumesResponse, SystemPromptPayload, UserInputPayload, ChannelDescriptor, ListChannelsResponse, RunStateEvent, RunStateStreamClose, RunStateStreamItem, RunStateStreamOpen, StreamUserRunStatesOptions, AckChannelOptions, ChannelAckResult, ChannelMessageItem, ChannelPeekResult, ChannelPublishResult, ChannelPurgeResult, ChannelReleaseResult, ChannelScope, ChannelSubscribeResult, PeekChannelOptions, PublishChannelOptions, SubscribeChannelOptions, AwaitChannelsOptions, BroadcastChannelsOptions, ChannelAwaitEntry, ChannelAwaitMode, ChannelAwaitResult, ChannelBroadcastEntry, ChannelBroadcastResult, CreateChannelOptions, ReleaseChannelOptions, UpdateChannelOptions, SetMemoryEntryOptions, SetMemoryEntryResponse, AgentDefRowResponse, AgentDefVerifyResult, SkillDefVerifyResult, EnsureMcpServerOptions, EnsureMcpServerResult, MCPServerDefRowResponse, MCPServerDefVerifyResult, AgentDefOverlay, HookEvent, InlineWebhook, HookEntry, EventHooks, ToolEntry, ToolHooksByTool, EnsureCodeAgentOptions, EnsureCodeAgentResult, LibraryAgentDefinition, LibraryEntry, LibraryListResponse, LibraryMcpServerDefinition, LibrarySkillDefinition, LLMChatContent, LLMChatMessage, LLMChatOptions, LLMChatResponse, LLMChatStreamDelta, LLMChatStreamItem, LLMChatToolCall, LLMChatUsage, LLMTool, LLMEmbeddingItem, LLMEmbeddingsOptions, LLMEmbeddingsResponse, LLMEmbeddingsUsage, UsageDimension, UsageAggregate, UsageReportResponse, CapabilityInertInfo, LimitInfo, ErrorInfo, CallFormat, CallRef, HookDecisionInfo, EffectiveConfigResponse, EffectiveConfigSource, EffectiveValue, RetuneRunResponse, RunConfigRecord, SubagentHoldInfo, RunConfigResponse, RunPromptResponse, RunPromptSnapshot, PromptBlock, TokenLimit, TokenLimitsResponse, ConfigResponse, ConfigProvider, ConfigModel, ConfigSearch, ConfigInstance, SetTokenLimitRequest, CredentialScope, CredentialMeta, CredentialListResponse, } from "./types.js";
134
- export { AgentIDInUseError, AgentNotFoundError, AlreadyPausingError, AuthError, BackpressureError, NotFoundError, InvalidArgumentError, ChannelCursorRegressionError, LoomcycleError, NotPausedError, PauseNotConfiguredError, PerUserQuotaExhaustedError, SessionBusyError, SessionNotFoundError, SnapshotNotFoundError, SnapshotTooLargeError, SnapshotVersionError, SubstrateToolRefusedError, UnavailableError, } from "./errors.js";
135
+ export type { AgentEvent, ClientOptions, ContinueOptions, EventType, HostWidening, ImageMediaType, ParentContext, PromptContent, PromptSegment, RetryInfo, RunOptions, SamplingOptions, CompactionOptions, ContextOptions, ToolUse, Usage, CallTiming, Agent, AgentStatus, AwaitedState, AgentUsage, RunResult, RunSpec, RunSpecTeam, ConfiguredRun, ConfiguredRunPatch, ToolChoiceOptions, OutputFormatOptions, CancelAgentResult, ListAgentsResponse, WalkRunsPage, RunBatchOptions, RunBatchResult, SpawnRunResult, CompactRunResult, DirectoryBudget, DirectoryInspection, DirectoryTenant, DirectoryUser, ErasureReport, ErasureResidue, ErasureResult, ErasureTier, CancelTurnResult, ReviewRunResult, TranscriptEvent, TranscriptResponse, HealthResponse, ListUsersResponse, UserSummary, UserRecord, CreateUserBody, UpdateUserBody, MintedUserToken, UserTokenMeta, ListUserTokensResponse, RunnableAgent, RunnableAgentsResponse, WhoamiResponse, PauseResult, ResumeResult, RuntimeStateResponse, RuntimeStateStatus, ResolverMatrix, ResolverModelStatus, ResolverProviderAvailability, CreateSnapshotOptions, SnapshotCreateResponse, SnapshotDescriptor, SnapshotEnvelope, SnapshotListResponse, SnapshotRestoreResponse, MemoryEntriesResponse, MemoryEntry, MemoryEntryResponse, MemoryScopeIDsResponse, MemoryScopeIDSummary, MemoryScopeKind, MemoryScopesResponse, MemorySearchInput, MemorySource, MemoryWhen, MemoryTimeFilter, MemorySearchEntry, MemorySearchResponse, MemoryEmbedModelStats, MemoryEmbedStatsResponse, MemoryReembedConfigured, MemoryReembedResponse, MemoryBackfillResponse, MemoryPurgeResponse, InterruptListResponse, InterruptRow, InterruptStatus, ResolveInterruptOptions, ChannelHookCall, ChannelHookResult, HookFailMode, HookPhase, HookToolCall, HookToolResult, PostHookCall, PostHookResult, PreHookCall, PreHookResult, SubstrateToolInput, SubstrateToolResponse, TeamNameSummary, ListTeamsResponse, TeamDiagram, CreatedTeam, PromotedTeam, RetiredTeam, TeamDefDetail, TeamVerification, TeamDraft, TeamDraftVerification, TeamIssue, TeamIssueKind, TeamVersion, TeamVersionList, TeamBreakpoints, TeamRunDetached, TeamRunResult, TeamRunTarget, PathToolInput, PathToolResponse, DocumentToolInput, DocumentToolResponse, HistoryToolInput, HistoryToolResponse, VolumeMode, PersistentVolumeEntry, PersistentVolumesResponse, EphemeralVolumeEntry, EphemeralVolumesResponse, SystemPromptPayload, UserInputPayload, ChannelDescriptor, ListChannelsResponse, RunStateEvent, RunStateStreamClose, RunStateStreamItem, RunStateStreamOpen, StreamUserRunStatesOptions, AckChannelOptions, ChannelAckResult, ChannelMessageItem, ChannelPeekResult, ChannelPublishResult, ChannelPurgeResult, ChannelReleaseResult, ChannelScope, ChannelSubscribeResult, PeekChannelOptions, PublishChannelOptions, SubscribeChannelOptions, AwaitChannelsOptions, BroadcastChannelsOptions, ChannelAwaitEntry, ChannelAwaitMode, ChannelAwaitResult, ChannelBroadcastEntry, ChannelBroadcastResult, CreateChannelOptions, ReleaseChannelOptions, UpdateChannelOptions, SetMemoryEntryOptions, SetMemoryEntryResponse, AgentDefRowResponse, AgentDefVerifyResult, SkillDefVerifyResult, EnsureMcpServerOptions, EnsureMcpServerResult, MCPServerDefRowResponse, MCPServerDefVerifyResult, AgentDefOverlay, HookEvent, InlineWebhook, HookEntry, EventHooks, ToolEntry, ToolHooksByTool, EnsureCodeAgentOptions, EnsureCodeAgentResult, LibraryAgentDefinition, LibraryEntry, LibraryListResponse, LibraryMcpServerDefinition, LibrarySkillDefinition, LLMChatContent, LLMChatMessage, LLMChatOptions, LLMChatResponse, LLMChatStreamDelta, LLMChatStreamItem, LLMChatToolCall, LLMChatUsage, LLMTool, LLMEmbeddingItem, LLMEmbeddingsOptions, LLMEmbeddingsResponse, LLMEmbeddingsUsage, UsageDimension, UsageAggregate, UsageReportResponse, CapabilityInertInfo, LimitInfo, ErrorInfo, CallFormat, CallRef, HookDecisionInfo, EffectiveConfigResponse, EffectiveConfigSource, EffectiveValue, RetuneRunResponse, RunConfigRecord, SubagentHoldInfo, RunConfigResponse, RunPromptResponse, RunPromptSnapshot, PromptBlock, TokenLimit, TokenLimitsResponse, ConfigResponse, ConfigProvider, ConfigModel, ConfigSearch, ConfigInstance, SetTokenLimitRequest, CredentialScope, CredentialMeta, CredentialListResponse, DecideRequest, DecideResponse, DecisionQuestion, DecisionChoiceQuestion, DecisionNoulQuestion, DecisionScoreQuestion, DecisionAnswer, DecisionChoiceAnswer, DecisionNoulAnswer, DecisionScoreAnswer, DecisionModel, DecisionModelsResponse, } from "./types.js";
136
+ export { AgentIDInUseError, AgentNotFoundError, AlreadyPausingError, AuthError, BackpressureError, NotFoundError, InvalidArgumentError, ChannelCursorRegressionError, LoomcycleError, NotPausedError, PauseNotConfiguredError, PerUserQuotaExhaustedError, PromptTooLargeError, RequestTooLargeError, SessionBusyError, SessionNotFoundError, SnapshotNotFoundError, SnapshotTooLargeError, SnapshotVersionError, SubstrateToolRefusedError, TokenLimitExceededError, UnavailableError, } from "./errors.js";
package/dist/index.js CHANGED
@@ -115,7 +115,9 @@
115
115
  * AuthError, UnavailableError, InvalidArgumentError,
116
116
  * PauseNotConfiguredError (subclass of UnavailableError),
117
117
  * AlreadyPausingError, NotPausedError, SnapshotNotFoundError,
118
- * SnapshotTooLargeError, SnapshotVersionError,
118
+ * SnapshotTooLargeError, RequestTooLargeError + PromptTooLargeError
119
+ * (both subclasses of SnapshotTooLargeError), TokenLimitExceededError
120
+ * (subclass of BackpressureError), SnapshotVersionError,
119
121
  * SubstrateToolRefusedError (v0.8.22)
120
122
  *
121
123
  * Transport: HTTP+SSE. Auth: Bearer token via the Authorization
@@ -128,4 +130,4 @@
128
130
  export { LoomcycleClient } from "./client.js";
129
131
  export { InteractiveSession } from "./interactive.js";
130
132
  export { ClientToolHost, clientToolsURL, CLIENT_TOOL_SUBPROTOCOL } from "./client-tools.js";
131
- export { AgentIDInUseError, AgentNotFoundError, AlreadyPausingError, AuthError, BackpressureError, NotFoundError, InvalidArgumentError, ChannelCursorRegressionError, LoomcycleError, NotPausedError, PauseNotConfiguredError, PerUserQuotaExhaustedError, SessionBusyError, SessionNotFoundError, SnapshotNotFoundError, SnapshotTooLargeError, SnapshotVersionError, SubstrateToolRefusedError, UnavailableError, } from "./errors.js";
133
+ export { AgentIDInUseError, AgentNotFoundError, AlreadyPausingError, AuthError, BackpressureError, NotFoundError, InvalidArgumentError, ChannelCursorRegressionError, LoomcycleError, NotPausedError, PauseNotConfiguredError, PerUserQuotaExhaustedError, PromptTooLargeError, RequestTooLargeError, SessionBusyError, SessionNotFoundError, SnapshotNotFoundError, SnapshotTooLargeError, SnapshotVersionError, SubstrateToolRefusedError, TokenLimitExceededError, UnavailableError, } from "./errors.js";