@spooled/sdk 1.2.1 → 1.4.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.
@@ -1,10 +1,124 @@
1
1
  import * as grpc from '@grpc/grpc-js';
2
2
 
3
+ /**
4
+ * Circuit Breaker Utility
5
+ *
6
+ * Implements the circuit breaker pattern to prevent cascading failures.
7
+ * States: CLOSED (normal) -> OPEN (failing) -> HALF_OPEN (testing) -> CLOSED
8
+ */
9
+
10
+ /** Circuit breaker states */
11
+ declare enum CircuitState {
12
+ /** Normal operation - requests flow through */
13
+ CLOSED = "CLOSED",
14
+ /** Circuit is open - requests are rejected immediately */
15
+ OPEN = "OPEN",
16
+ /** Testing state - limited requests allowed to test recovery */
17
+ HALF_OPEN = "HALF_OPEN"
18
+ }
19
+ /** Circuit breaker state change event */
20
+ interface CircuitStateChange {
21
+ from: CircuitState;
22
+ to: CircuitState;
23
+ timestamp: Date;
24
+ failureCount: number;
25
+ }
26
+ /** Circuit breaker options */
27
+ interface CircuitBreakerOptions extends CircuitBreakerConfig {
28
+ /** Callback when state changes */
29
+ onStateChange?: (event: CircuitStateChange) => void;
30
+ /**
31
+ * Custom function to determine if an error should count as a failure.
32
+ * Defaults to {@link isCircuitBreakerFailure}.
33
+ */
34
+ isFailure?: (error: Error) => boolean;
35
+ }
36
+ /**
37
+ * Default circuit breaker failure predicate.
38
+ *
39
+ * Counts the errors that say the API or the network is unhealthy: the
40
+ * retryable ones (network errors, timeouts, 5xx, 408). A 429 never counts. A
41
+ * rate-limit 429 is the API working as designed and telling this client to
42
+ * slow down for `Retry-After` seconds; counting it let a burst above the plan
43
+ * limit open the breaker and fail every call on the client for the breaker
44
+ * timeout (30 s by default), including the retries that `Retry-After` had
45
+ * already scheduled. The retry layer handles rate limiting on its own. A quota
46
+ * 429 (`RateLimitError.isQuota`) was already excluded.
47
+ */
48
+ declare function isCircuitBreakerFailure(error: Error): boolean;
49
+ /**
50
+ * Circuit Breaker implementation
51
+ *
52
+ * Tracks failures and prevents requests when the failure threshold is reached.
53
+ */
54
+ declare class CircuitBreaker {
55
+ private state;
56
+ private failureCount;
57
+ private successCount;
58
+ private lastFailureTime;
59
+ private readonly config;
60
+ constructor(config: CircuitBreakerOptions);
61
+ /**
62
+ * Get current circuit state
63
+ */
64
+ getState(): CircuitState;
65
+ /**
66
+ * Check if circuit breaker is enabled
67
+ */
68
+ isEnabled(): boolean;
69
+ /**
70
+ * Check if requests are currently allowed
71
+ */
72
+ isAllowed(): boolean;
73
+ /**
74
+ * Record a successful request
75
+ */
76
+ recordSuccess(): void;
77
+ /**
78
+ * Record a failed request
79
+ */
80
+ recordFailure(error: Error): void;
81
+ /**
82
+ * Transition to a new state
83
+ */
84
+ private transitionTo;
85
+ /**
86
+ * Reset the circuit breaker to closed state
87
+ */
88
+ reset(): void;
89
+ /**
90
+ * Execute a function with circuit breaker protection
91
+ *
92
+ * @param fn - Async function to execute
93
+ * @returns Promise resolving to the function result
94
+ * @throws CircuitBreakerOpenError if circuit is open
95
+ */
96
+ execute<T>(fn: () => Promise<T>): Promise<T>;
97
+ /**
98
+ * Get circuit breaker statistics
99
+ */
100
+ getStats(): {
101
+ state: CircuitState;
102
+ failureCount: number;
103
+ successCount: number;
104
+ lastFailureTime: Date | null;
105
+ config: CircuitBreakerConfig;
106
+ };
107
+ }
108
+ /**
109
+ * Create a circuit breaker instance from configuration.
110
+ *
111
+ * Unless the config carries its own `isFailure`, rate-limit 429s do not count
112
+ * as failures (the constructor defaults to {@link isCircuitBreakerFailure}).
113
+ */
114
+ declare function createCircuitBreaker(config: CircuitBreakerOptions): CircuitBreaker;
115
+
3
116
  /**
4
117
  * SDK Configuration
5
118
  *
6
119
  * Defines configuration types and defaults for the Spooled SDK.
7
120
  */
121
+
8
122
  /** Retry configuration options */
9
123
  interface RetryConfig {
10
124
  /** Maximum number of retry attempts (default: 3) */
@@ -57,8 +171,11 @@ interface SpooledClientConfig {
57
171
  retryDelay?: number;
58
172
  /** Full retry configuration */
59
173
  retry?: Partial<RetryConfig>;
60
- /** Circuit breaker configuration */
61
- circuitBreaker?: Partial<CircuitBreakerConfig>;
174
+ /**
175
+ * Circuit breaker configuration. Besides the thresholds it takes
176
+ * `isFailure` (which errors count as failures) and `onStateChange`.
177
+ */
178
+ circuitBreaker?: Partial<CircuitBreakerOptions>;
62
179
  /** Additional headers to include in all requests */
63
180
  headers?: Record<string, string>;
64
181
  /** Custom fetch implementation (for testing or special runtimes) */
@@ -81,7 +198,7 @@ interface ResolvedConfig {
81
198
  grpcAddress: string;
82
199
  timeout: number;
83
200
  retry: RetryConfig;
84
- circuitBreaker: CircuitBreakerConfig;
201
+ circuitBreaker: CircuitBreakerOptions;
85
202
  headers: Record<string, string>;
86
203
  fetch: typeof fetch;
87
204
  userAgent: string;
@@ -107,11 +224,11 @@ declare const DEFAULT_CONFIG: {
107
224
  successThreshold: number;
108
225
  timeout: number;
109
226
  };
110
- readonly userAgent: "@spooled/sdk-nodejs/1.2.1";
227
+ readonly userAgent: "@spooled/sdk-nodejs/1.4.0";
111
228
  readonly autoRefreshToken: true;
112
229
  };
113
230
  /** SDK version */
114
- declare const SDK_VERSION = "1.2.1";
231
+ declare const SDK_VERSION = "1.4.0";
115
232
  /** API version prefix */
116
233
  declare const API_VERSION = "v1";
117
234
  /**
@@ -125,98 +242,206 @@ declare function resolveConfig(options: SpooledClientConfig): ResolvedConfig;
125
242
  declare function validateConfig(config: ResolvedConfig): void;
126
243
 
127
244
  /**
128
- * Circuit Breaker Utility
245
+ * Custom Error Classes
129
246
  *
130
- * Implements the circuit breaker pattern to prevent cascading failures.
131
- * States: CLOSED (normal) -> OPEN (failing) -> HALF_OPEN (testing) -> CLOSED
247
+ * Provides a hierarchy of error types for the Spooled SDK.
132
248
  */
133
-
134
- /** Circuit breaker states */
135
- declare enum CircuitState {
136
- /** Normal operation - requests flow through */
137
- CLOSED = "CLOSED",
138
- /** Circuit is open - requests are rejected immediately */
139
- OPEN = "OPEN",
140
- /** Testing state - limited requests allowed to test recovery */
141
- HALF_OPEN = "HALF_OPEN"
142
- }
143
- /** Circuit breaker state change event */
144
- interface CircuitStateChange {
145
- from: CircuitState;
146
- to: CircuitState;
147
- timestamp: Date;
148
- failureCount: number;
149
- }
150
- /** Circuit breaker options */
151
- interface CircuitBreakerOptions extends CircuitBreakerConfig {
152
- /** Callback when state changes */
153
- onStateChange?: (event: CircuitStateChange) => void;
154
- /** Custom function to determine if an error should count as a failure */
155
- isFailure?: (error: Error) => boolean;
249
+ /** Error response body from the API */
250
+ interface ApiErrorBody {
251
+ code: string;
252
+ message: string;
253
+ details?: Record<string, unknown>;
156
254
  }
157
255
  /**
158
- * Circuit Breaker implementation
256
+ * Rate limit information parsed from headers.
159
257
  *
160
- * Tracks failures and prevents requests when the failure threshold is reached.
258
+ * Authenticated responses that went through the plan rate limiter carry
259
+ * `X-RateLimit-Limit`, `-Remaining`, `-Reset` and `-Scope` (API 0.1.122+); a
260
+ * 429 adds `Retry-After`. Every field is optional: the headers are left out
261
+ * when no rate-limit check ran (public and admin routes, a server without
262
+ * Redis, older servers).
161
263
  */
162
- declare class CircuitBreaker {
163
- private state;
164
- private failureCount;
165
- private successCount;
166
- private lastFailureTime;
167
- private readonly config;
168
- constructor(config: CircuitBreakerOptions);
169
- /**
170
- * Get current circuit state
171
- */
172
- getState(): CircuitState;
173
- /**
174
- * Check if circuit breaker is enabled
175
- */
176
- isEnabled(): boolean;
264
+ interface RateLimitInfo {
177
265
  /**
178
- * Check if requests are currently allowed
179
- */
180
- isAllowed(): boolean;
181
- /**
182
- * Record a successful request
266
+ * The limit the other fields describe: the plan burst (organization token
267
+ * bucket) or an API key's own requests per minute.
183
268
  */
184
- recordSuccess(): void;
185
- /**
186
- * Record a failed request
187
- */
188
- recordFailure(error: Error): void;
269
+ limit?: number;
270
+ /** Whole requests left after this one */
271
+ remaining?: number;
189
272
  /**
190
- * Transition to a new state
273
+ * When `remaining` next goes up (`X-RateLimit-Reset`, a Unix time in
274
+ * seconds; the current time while the bucket is full).
191
275
  */
192
- private transitionTo;
276
+ reset?: Date;
277
+ /** Seconds to wait before retrying (`Retry-After`, on a 429) */
278
+ retryAfter?: number;
193
279
  /**
194
- * Reset the circuit breaker to closed state
280
+ * Which limit the headers describe (`X-RateLimit-Scope`): `organization`
281
+ * (the plan's token bucket) or `api_key` (the key's `rateLimit`).
195
282
  */
196
- reset(): void;
197
- /**
198
- * Execute a function with circuit breaker protection
283
+ scope?: "organization" | "api_key" | (string & {});
284
+ }
285
+ /**
286
+ * Base error class for all Spooled SDK errors
287
+ */
288
+ declare class SpooledError extends Error {
289
+ /** HTTP status code (if applicable) */
290
+ readonly statusCode: number;
291
+ /** Error code from API response */
292
+ readonly code: string;
293
+ /** Additional error details */
294
+ readonly details?: Record<string, unknown>;
295
+ /** Request ID for debugging */
296
+ readonly requestId?: string;
297
+ /** Original cause of the error */
298
+ readonly cause?: Error;
299
+ constructor(message: string, statusCode?: number, code?: string, details?: Record<string, unknown>, requestId?: string, cause?: Error);
300
+ /**
301
+ * Whether this error is retryable.
199
302
  *
200
- * @param fn - Async function to execute
201
- * @returns Promise resolving to the function result
202
- * @throws CircuitBreakerOpenError if circuit is open
303
+ * Only 408 (Request Timeout) is retryable among the plain 4xx statuses: the
304
+ * server gave up waiting for the request, so it never ran. Subclasses
305
+ * override this (5xx, network, timeout, rate limit).
203
306
  */
204
- execute<T>(fn: () => Promise<T>): Promise<T>;
307
+ isRetryable(): boolean;
308
+ /** Convert to plain object for logging */
309
+ toJSON(): Record<string, unknown>;
310
+ }
311
+ /**
312
+ * Authentication error (401)
313
+ * Thrown when authentication fails (invalid/expired token or API key)
314
+ */
315
+ declare class AuthenticationError extends SpooledError {
316
+ constructor(message?: string, code?: string, details?: Record<string, unknown>, requestId?: string);
317
+ }
318
+ /**
319
+ * Authorization error (403)
320
+ * Thrown when the authenticated user lacks permission
321
+ */
322
+ declare class AuthorizationError extends SpooledError {
323
+ constructor(message?: string, code?: string, details?: Record<string, unknown>, requestId?: string);
324
+ }
325
+ /**
326
+ * Not found error (404)
327
+ * Thrown when a requested resource doesn't exist
328
+ */
329
+ declare class NotFoundError extends SpooledError {
330
+ constructor(message?: string, code?: string, details?: Record<string, unknown>, requestId?: string);
331
+ }
332
+ /**
333
+ * Conflict error (409)
334
+ * Thrown when there's a conflict (e.g., duplicate resource)
335
+ */
336
+ declare class ConflictError extends SpooledError {
337
+ constructor(message?: string, code?: string, details?: Record<string, unknown>, requestId?: string);
338
+ }
339
+ /**
340
+ * Validation error (400 or 422)
341
+ * Thrown when request validation fails.
342
+ *
343
+ * The API answers a field-rule failure (length, range) with 400 but a missing
344
+ * or mistyped JSON field with 422; both are the caller's request being invalid,
345
+ * so both surface as this class. `statusCode` tells them apart.
346
+ */
347
+ declare class ValidationError extends SpooledError {
348
+ constructor(message?: string, code?: string, details?: Record<string, unknown>, requestId?: string, statusCode?: 400 | 422);
349
+ }
350
+ /**
351
+ * Payload too large error (413)
352
+ * Thrown when request body exceeds size limit
353
+ */
354
+ declare class PayloadTooLargeError extends SpooledError {
355
+ constructor(message?: string, code?: string, details?: Record<string, unknown>, requestId?: string);
356
+ }
357
+ /**
358
+ * Rate limit error (429)
359
+ * Thrown when rate limit is exceeded, or a plan quota is (see `isQuota`)
360
+ */
361
+ declare class RateLimitError extends SpooledError {
362
+ /** Rate limit information */
363
+ readonly rateLimitInfo: RateLimitInfo;
364
+ constructor(message?: string, code?: string, rateLimitInfo?: RateLimitInfo, details?: Record<string, unknown>, requestId?: string);
205
365
  /**
206
- * Get circuit breaker statistics
366
+ * True when this 429 is a plan quota or limit (daily job cap, active jobs,
367
+ * queue/worker/webhook caps) rather than per-second rate limiting.
368
+ *
369
+ * A quota does not clear for minutes or hours, so retrying it only blocks the
370
+ * caller for the whole backoff and, via the circuit breaker, takes every
371
+ * other call on the client down with it. It is never retried and never
372
+ * counted as a circuit breaker failure.
373
+ *
374
+ * Detection: the `QUOTA_EXCEEDED` code, or, for older plan-limit paths that
375
+ * answer with plain text wrapped as `RATE_LIMIT_EXCEEDED`, a "... limit
376
+ * reached" message that carries no `Retry-After`.
207
377
  */
208
- getStats(): {
209
- state: CircuitState;
210
- failureCount: number;
211
- successCount: number;
212
- lastFailureTime: Date | null;
213
- config: CircuitBreakerConfig;
214
- };
378
+ get isQuota(): boolean;
379
+ isRetryable(): boolean;
380
+ /** Get the number of seconds to wait before retrying */
381
+ getRetryAfter(): number;
382
+ toJSON(): Record<string, unknown>;
383
+ }
384
+ /**
385
+ * Server error (5xx)
386
+ * Thrown when the server encounters an error
387
+ */
388
+ declare class ServerError extends SpooledError {
389
+ constructor(message?: string, statusCode?: number, code?: string, details?: Record<string, unknown>, requestId?: string);
390
+ isRetryable(): boolean;
391
+ }
392
+ /**
393
+ * Network error
394
+ * Thrown when a network request fails (no response received)
395
+ */
396
+ declare class NetworkError extends SpooledError {
397
+ constructor(message?: string, cause?: Error);
398
+ isRetryable(): boolean;
399
+ }
400
+ /**
401
+ * Timeout error
402
+ * Thrown when a request times out
403
+ */
404
+ declare class TimeoutError extends SpooledError {
405
+ /** Timeout duration in milliseconds */
406
+ readonly timeoutMs: number;
407
+ constructor(message?: string, timeoutMs?: number);
408
+ isRetryable(): boolean;
409
+ }
410
+ /**
411
+ * Circuit breaker open error
412
+ * Thrown when the circuit breaker is open and rejecting requests
413
+ */
414
+ declare class CircuitBreakerOpenError extends SpooledError {
415
+ constructor(message?: string);
416
+ isRetryable(): boolean;
417
+ }
418
+ /**
419
+ * Unsupported operation error
420
+ * Thrown by SDK methods whose route the Spooled API does not provide (or
421
+ * always rejects). It is raised before any network call, so code that still
422
+ * calls such a method fails loudly with an explanation instead of a 404.
423
+ */
424
+ declare class UnsupportedOperationError extends SpooledError {
425
+ /** The SDK method that is not supported, e.g. `ingest.github` */
426
+ readonly operation: string;
427
+ constructor(operation: string, reason: string);
215
428
  }
216
429
  /**
217
- * Create a circuit breaker instance from configuration
430
+ * Parse rate limit headers from a Response
431
+ */
432
+ declare function parseRateLimitHeaders(headers: Headers): RateLimitInfo;
433
+ /**
434
+ * Create an appropriate error from an HTTP response
435
+ */
436
+ declare function createErrorFromResponse(response: Response): Promise<SpooledError>;
437
+ /**
438
+ * Check if an error is a SpooledError instance
439
+ */
440
+ declare function isSpooledError(error: unknown): error is SpooledError;
441
+ /**
442
+ * Check if an error is retryable
218
443
  */
219
- declare function createCircuitBreaker(config: CircuitBreakerConfig): CircuitBreaker;
444
+ declare function isRetryableError(error: unknown): boolean;
220
445
 
221
446
  /**
222
447
  * HTTP Client Utility
@@ -262,6 +487,20 @@ interface HttpRequestOptions {
262
487
  skipResponseConversion?: boolean;
263
488
  /** Whether to skip retry logic */
264
489
  skipRetry?: boolean;
490
+ /**
491
+ * The request is safe to replay even though it is a POST/PATCH, so network
492
+ * errors, timeouts, 5xx and 408 are retried like they are for a GET.
493
+ *
494
+ * Use it only for calls the server makes idempotent: lease-fenced job and
495
+ * worker acks (complete/fail/heartbeat answer a replay with 409) and job
496
+ * creation with an idempotency key (the server returns the existing job).
497
+ */
498
+ idempotent?: boolean;
499
+ /**
500
+ * Never try to refresh the access token when this request gets a 401.
501
+ * Set on the auth calls that the refresh itself makes.
502
+ */
503
+ skipAuthRefresh?: boolean;
265
504
  /** Optional abort signal */
266
505
  signal?: AbortSignal;
267
506
  }
@@ -287,13 +526,25 @@ declare class HttpClient {
287
526
  private authToken;
288
527
  /** Optional function to mint a fresh access token (set when auto-refresh is enabled) */
289
528
  private refreshTokenFn;
290
- /** Guard to prevent a refresh request from recursively triggering another refresh */
291
- private isRefreshing;
529
+ /**
530
+ * The refresh currently in flight, shared by every request that gets a 401
531
+ * meanwhile. A boolean guard here made the second concurrent 401 skip the
532
+ * refresh and fail even though the token was about to be replaced.
533
+ */
534
+ private refreshInFlight;
535
+ /** Rate-limit headers of the most recent response that carried them */
536
+ private lastRateLimit;
292
537
  constructor(config: ResolvedConfig, circuitBreaker: CircuitBreaker);
293
538
  /**
294
539
  * Set the authentication token
295
540
  */
296
541
  setAuthToken(token: string): void;
542
+ /**
543
+ * The `X-RateLimit-*` (and `Retry-After`) values of the most recent
544
+ * response that carried them, successful or not. `undefined` until such a
545
+ * response arrives. With concurrent requests it is the last one to finish.
546
+ */
547
+ getLastRateLimitInfo(): RateLimitInfo | undefined;
297
548
  /**
298
549
  * Set the token refresh function.
299
550
  *
@@ -301,6 +552,13 @@ declare class HttpClient {
301
552
  * refresh + retry of the original request with the new token.
302
553
  */
303
554
  setRefreshTokenFn(fn: () => Promise<string>): void;
555
+ /**
556
+ * Refresh the access token once for all callers.
557
+ *
558
+ * Resolves true when a new token is installed, false when the refresh failed
559
+ * (the caller then surfaces its original 401).
560
+ */
561
+ private refreshAuthToken;
304
562
  /**
305
563
  * Build full URL with query parameters
306
564
  */
@@ -317,6 +575,8 @@ declare class HttpClient {
317
575
  * Execute a single HTTP request (no retry)
318
576
  */
319
577
  private executeRequest;
578
+ /** Remember the rate-limit headers of a response that has them. */
579
+ private recordRateLimit;
320
580
  /**
321
581
  * Make an HTTP request with retry and circuit breaker
322
582
  */
@@ -329,12 +589,13 @@ declare class HttpClient {
329
589
  /**
330
590
  * Resolve the retry configuration for a request.
331
591
  *
332
- * Idempotent methods (GET/PUT/DELETE) and any request carrying an
333
- * idempotency key retry normally. Non-idempotent methods (POST/PATCH)
334
- * without an idempotency key must NOT be retried on ambiguous failures
592
+ * Idempotent methods (GET/PUT/DELETE), any request carrying an idempotency
593
+ * key and any request marked `idempotent` retry normally. Non-idempotent
594
+ * methods (POST/PATCH) otherwise must NOT be retried on ambiguous failures
335
595
  * (network/timeout/5xx) — doing so risks duplicate jobs, double claims,
336
- * etc. They are still retried on 429, which is rejected before the
337
- * server processes the request and is therefore side-effect-free.
596
+ * etc. They are still retried on a rate-limit 429, which is rejected before
597
+ * the server processes the request and is therefore side-effect-free. A
598
+ * quota 429 is never retried: it does not clear for hours.
338
599
  */
339
600
  private resolveRetryConfig;
340
601
  /**
@@ -509,8 +770,32 @@ type PlanTier = "free" | "starter" | "pro" | "enterprise";
509
770
  type ScheduleRunStatus = "pending" | "running" | "completed" | "failed";
510
771
  /** Webhook delivery status */
511
772
  type WebhookDeliveryStatus = "pending" | "success" | "failed";
512
- /** Webhook event types */
513
- type WebhookEventType = "job.created" | "job.started" | "job.completed" | "job.failed" | "job.cancelled" | "queue.paused" | "queue.resumed" | "worker.registered" | "worker.deregistered" | "schedule.triggered";
773
+ /**
774
+ * Webhook event types.
775
+ *
776
+ * `job.deadlettered`, `job.retried`, `workflow.completed` and
777
+ * `workflow.failed` need API 0.1.122 or later. The SDK does not check event
778
+ * names in responses: a name newer than this list is passed through as a
779
+ * string, so give a `switch` over it a `default` branch.
780
+ */
781
+ type WebhookEventType = "job.created" | "job.started" | "job.completed" | "job.failed" | "job.cancelled" | "queue.paused" | "queue.resumed" | "worker.registered" | "worker.deregistered" | "schedule.triggered"
782
+ /** Sent next to every `job.failed` whose `data.status` is `deadletter`. */
783
+ | "job.deadlettered"
784
+ /** A manual retry (job, DLQ or workflow retry) put the job back to pending. */
785
+ | "job.retried"
786
+ /** A workflow finished; announced at most once, up to ~10 s late. */
787
+ | "workflow.completed"
788
+ /** A workflow failed; announced at most once, up to ~10 s late. */
789
+ | "workflow.failed";
790
+ /**
791
+ * Body format of an outgoing webhook (API 0.1.122+).
792
+ *
793
+ * `json` (the default) is the signed JSON envelope. `slack`, `discord` and
794
+ * `teams` send one short chat message built from the event, so a chat
795
+ * service's incoming-webhook URL can be used as it is (`teams` is the legacy
796
+ * Office 365 connector `MessageCard`; Teams Workflows URLs reject it).
797
+ */
798
+ type WebhookFormat = "json" | "slack" | "discord" | "teams";
514
799
  /** Dependency mode for workflows */
515
800
  type DependencyMode = "all" | "any";
516
801
  /** Pagination parameters */
@@ -540,6 +825,22 @@ interface PaginatedResponse<T> {
540
825
  /** Whether there are more results */
541
826
  hasMore: boolean;
542
827
  }
828
+ /**
829
+ * One page of a list endpoint that reports `X-Has-More` (API 0.1.122+):
830
+ * `GET /jobs`, `GET /jobs/dlq` and `GET /jobs/{id}/history`.
831
+ *
832
+ * The response body stays a bare array; `hasMore` comes from the header.
833
+ */
834
+ interface ListPage<T> {
835
+ /** Items of this page, in the server's order */
836
+ data: T[];
837
+ /**
838
+ * `true` when another page follows: ask again with
839
+ * `offset + data.length`. From the `X-Has-More` header; an older server
840
+ * without it gets a guess from the page size (a full page means "maybe").
841
+ */
842
+ hasMore: boolean;
843
+ }
543
844
  /**
544
845
  * Helper to create a paginated response from an array
545
846
  */
@@ -624,18 +925,44 @@ interface CreateJobParams {
624
925
  parentJobId?: string;
625
926
  /** Webhook URL for completion notification */
626
927
  completionWebhook?: string;
928
+ /** HMAC secret used to sign the `completionWebhook` request (never returned by the API) */
929
+ completionWebhookSecret?: string;
627
930
  }
628
931
  /** Result of creating a job */
629
932
  interface CreateJobResult {
630
933
  id: string;
631
934
  created: boolean;
632
935
  }
936
+ /**
937
+ * Server-side job search filters (API 0.1.122+), shared by `GET /jobs` and
938
+ * `GET /jobs/dlq`. All filters combine with AND. An invalid value is a 400
939
+ * `ValidationError`; an older server ignores them.
940
+ */
941
+ interface JobSearchParams {
942
+ /**
943
+ * Search text, case-insensitive: matches a job whose id starts with it, or
944
+ * whose queue name or `payload.job_type` contains it (at most 255 bytes).
945
+ */
946
+ q?: string;
947
+ /** Exact `payload.job_type` (at most 255 bytes) */
948
+ jobType?: string;
949
+ /**
950
+ * Only jobs created at or after this instant. A `Date` is sent as an
951
+ * ISO 8601 UTC string; a string must be RFC 3339.
952
+ */
953
+ createdAfter?: Date | string;
954
+ /** Only jobs created before this instant (exclusive); see `createdAfter` */
955
+ createdBefore?: Date | string;
956
+ }
633
957
  /** Parameters for listing jobs */
634
- interface ListJobsParams extends ListParams {
958
+ interface ListJobsParams extends ListParams, JobSearchParams {
635
959
  /** Filter by queue name */
636
960
  queueName?: string;
637
- /** Filter by status */
638
- status?: JobStatus;
961
+ /**
962
+ * Filter by status: one status, or several (sent as the comma list
963
+ * `status=failed,deadletter`, which needs API 0.1.122+).
964
+ */
965
+ status?: JobStatus | readonly JobStatus[];
639
966
  /** Filter by a single tag (matches Postgres `tags ? tag` semantics) */
640
967
  tag?: string;
641
968
  }
@@ -669,10 +996,9 @@ interface ClaimedJob {
669
996
  timeoutSeconds: number;
670
997
  leaseExpiresAt?: string;
671
998
  /**
672
- * Lease fencing token for this claim. Echo it back on
673
- * complete/fail/heartbeat so the operation applies only to the lease this
674
- * worker actually holds (backend rejects stale leases with 409
675
- * LEASE_EXPIRED). Omitted = legacy behavior.
999
+ * Lease fencing token for this claim. Send it back on
1000
+ * complete/fail/heartbeat: the API requires it (a call without it is a 422
1001
+ * `ValidationError`, since 2026-07) and rejects a stale lease with 409.
676
1002
  */
677
1003
  leaseId?: string | null;
678
1004
  }
@@ -697,7 +1023,10 @@ interface CompleteJobParams {
697
1023
  workerId: string;
698
1024
  /** Optional result payload (any JSON) */
699
1025
  result?: JsonValue;
700
- /** Lease fencing token from the claimed job (rejects stale leases when set) */
1026
+ /**
1027
+ * Lease fencing token from the claimed job (`ClaimedJob.leaseId`). The API
1028
+ * requires it: without it the call is a 422 `ValidationError`.
1029
+ */
701
1030
  leaseId?: string;
702
1031
  }
703
1032
  /** Parameters for failing a job */
@@ -706,7 +1035,10 @@ interface FailJobParams {
706
1035
  workerId: string;
707
1036
  /** Error message (1-2048 chars) */
708
1037
  error: string;
709
- /** Lease fencing token from the claimed job (rejects stale leases when set) */
1038
+ /**
1039
+ * Lease fencing token from the claimed job (`ClaimedJob.leaseId`). The API
1040
+ * requires it: without it the call is a 422 `ValidationError`.
1041
+ */
710
1042
  leaseId?: string;
711
1043
  }
712
1044
  /** Parameters for job heartbeat */
@@ -715,7 +1047,10 @@ interface HeartbeatJobParams {
715
1047
  workerId: string;
716
1048
  /** Lease duration in seconds (5-3600) */
717
1049
  leaseDurationSecs: number;
718
- /** Lease fencing token from the claimed job (rejects stale leases when set) */
1050
+ /**
1051
+ * Lease fencing token from the claimed job (`ClaimedJob.leaseId`). The API
1052
+ * requires it: without it the call is a 422 `ValidationError`.
1053
+ */
719
1054
  leaseId?: string;
720
1055
  }
721
1056
  /** Response for priority boost */
@@ -760,10 +1095,37 @@ interface BulkEnqueueResponse {
760
1095
  failureCount: number;
761
1096
  }
762
1097
  /** Parameters for listing DLQ */
763
- interface ListDlqParams extends ListParams {
1098
+ interface ListDlqParams extends ListParams, JobSearchParams {
764
1099
  /** Filter by queue name */
765
1100
  queueName?: string;
766
1101
  }
1102
+ /**
1103
+ * Event types of `GET /jobs/{id}/history`. The server records `processing`
1104
+ * (REST claim), `completed` (REST complete), `retry_scheduled` and
1105
+ * `deadlettered` (REST fail, scheduler sweeps); `created` is defined but not
1106
+ * written today, and jobs settled over gRPC have sparse history. Any other
1107
+ * string the server sends is passed through.
1108
+ */
1109
+ type JobHistoryEventType = "created" | "processing" | "completed" | "retry_scheduled" | "deadlettered" | (string & {});
1110
+ /** One recorded lifecycle event of a job (`GET /jobs/{id}/history`) */
1111
+ interface JobHistoryEvent {
1112
+ id: string;
1113
+ jobId: string;
1114
+ eventType: JobHistoryEventType;
1115
+ /** The worker that caused the event, when known */
1116
+ workerId?: string | null;
1117
+ /**
1118
+ * Event details as stored (any JSON, keys left in snake_case as the server
1119
+ * wrote them).
1120
+ */
1121
+ details: JsonValue;
1122
+ createdAt: string;
1123
+ }
1124
+ /** Parameters for `jobs.history()` (API 0.1.122+) */
1125
+ interface JobHistoryParams extends PaginationParams {
1126
+ /** `asc` (default, oldest first) or `desc` (newest first) */
1127
+ order?: "asc" | "desc";
1128
+ }
767
1129
  /** Parameters for retrying DLQ jobs */
768
1130
  interface RetryDlqParams {
769
1131
  /** Specific job IDs to retry */
@@ -802,6 +1164,11 @@ interface PurgeDlqResponse {
802
1164
  interface DlqOperations {
803
1165
  /** List jobs in dead-letter queue */
804
1166
  list(params?: ListDlqParams): Promise<JobSummary[]>;
1167
+ /**
1168
+ * List one page of the dead-letter queue with `hasMore` from the
1169
+ * `X-Has-More` header (API 0.1.122+).
1170
+ */
1171
+ listPage(params?: ListDlqParams): Promise<ListPage<JobSummary>>;
805
1172
  /** Retry jobs from DLQ */
806
1173
  retry(params: RetryDlqParams): Promise<RetryDlqResponse>;
807
1174
  /** Purge jobs from DLQ */
@@ -822,8 +1189,33 @@ declare class JobsResource {
822
1189
  createAndGet(params: CreateJobParams): Promise<Job>;
823
1190
  /**
824
1191
  * List jobs with optional filtering
1192
+ *
1193
+ * `status` takes one status or several, and `q`, `jobType`, `createdAfter`
1194
+ * and `createdBefore` filter on the server (API 0.1.122+). Use
1195
+ * {@link JobsResource.listPage} to also learn whether another page follows.
825
1196
  */
826
1197
  list(params?: ListJobsParams): Promise<JobSummary[]>;
1198
+ /**
1199
+ * List one page of jobs with `hasMore` from the `X-Has-More` header
1200
+ * (API 0.1.122+). Takes the same filters as {@link JobsResource.list}.
1201
+ *
1202
+ * @example
1203
+ * ```typescript
1204
+ * let offset = 0;
1205
+ * for (;;) {
1206
+ * const page = await client.jobs.listPage({
1207
+ * status: ["failed", "deadletter"],
1208
+ * createdAfter: new Date(Date.now() - 86_400_000),
1209
+ * limit: 100,
1210
+ * offset,
1211
+ * });
1212
+ * handle(page.data);
1213
+ * if (!page.hasMore) break;
1214
+ * offset += page.data.length;
1215
+ * }
1216
+ * ```
1217
+ */
1218
+ listPage(params?: ListJobsParams): Promise<ListPage<JobSummary>>;
827
1219
  /**
828
1220
  * Get a job by ID
829
1221
  */
@@ -840,6 +1232,21 @@ declare class JobsResource {
840
1232
  * Boost job priority
841
1233
  */
842
1234
  boostPriority(id: string, priority: number): Promise<BoostPriorityResponse>;
1235
+ /**
1236
+ * Get the recorded lifecycle events of a job (`GET /jobs/{id}/history`,
1237
+ * API 0.1.122+), oldest first unless `order: "desc"`.
1238
+ *
1239
+ * The history is sparse: the server records REST claims (`processing`),
1240
+ * completions (`completed`) and failures (`retry_scheduled`,
1241
+ * `deadlettered`) and the scheduler's dead-letter sweeps, so a job settled
1242
+ * over gRPC may have few or no events. An unknown job is a `NotFoundError`.
1243
+ */
1244
+ history(id: string, params?: JobHistoryParams): Promise<JobHistoryEvent[]>;
1245
+ /**
1246
+ * One page of {@link JobsResource.history} with `hasMore` from the
1247
+ * `X-Has-More` header. `limit` defaults to 100 (at most 500).
1248
+ */
1249
+ historyPage(id: string, params?: JobHistoryParams): Promise<ListPage<JobHistoryEvent>>;
843
1250
  /**
844
1251
  * Get job statistics
845
1252
  */
@@ -858,12 +1265,20 @@ declare class JobsResource {
858
1265
  claim(params: ClaimJobsParams): Promise<ClaimJobsResult>;
859
1266
  /**
860
1267
  * Complete a job (worker ack)
1268
+ *
1269
+ * Lease-fenced and idempotent on the server, so a network error, timeout or
1270
+ * 5xx is retried: a lost ack would otherwise re-run a finished job.
861
1271
  */
862
1272
  complete(id: string, params: CompleteJobParams): Promise<{
863
1273
  success: boolean;
864
1274
  }>;
865
1275
  /**
866
1276
  * Fail a job (worker nack)
1277
+ *
1278
+ * `params.error` is made acceptable first: empty text becomes "Job failed"
1279
+ * and text over 2048 characters is truncated, because the API rejects both
1280
+ * with a 400 that would leave the job processing until its lease expires.
1281
+ * Retried like {@link JobsResource.complete}.
867
1282
  */
868
1283
  fail(id: string, params: FailJobParams): Promise<{
869
1284
  success: boolean;
@@ -871,11 +1286,16 @@ declare class JobsResource {
871
1286
  }>;
872
1287
  /**
873
1288
  * Extend job lease (heartbeat)
1289
+ *
1290
+ * Retried like {@link JobsResource.complete}: with the default 30 s lease and
1291
+ * 15 s heartbeat, one lost heartbeat leaves no slack.
874
1292
  */
875
1293
  heartbeat(id: string, params: HeartbeatJobParams): Promise<{
876
1294
  success: boolean;
877
1295
  }>;
878
1296
  private listDlq;
1297
+ private listDlqPage;
1298
+ private listSummaries;
879
1299
  private retryDlq;
880
1300
  private purgeDlq;
881
1301
  }
@@ -946,6 +1366,14 @@ interface ResumeQueueResponse {
946
1366
  resumed: boolean;
947
1367
  pausedDurationSecs: number;
948
1368
  }
1369
+ /** Options for deleting a queue */
1370
+ interface DeleteQueueOptions {
1371
+ /**
1372
+ * Also delete every job (and dead-letter row) of the queue. Required to
1373
+ * delete a queue with pending/processing jobs or one without a stored config.
1374
+ */
1375
+ deleteJobs?: boolean;
1376
+ }
949
1377
 
950
1378
  /**
951
1379
  * Queues Resource
@@ -982,8 +1410,14 @@ declare class QueuesResource {
982
1410
  resume(name: string): Promise<ResumeQueueResponse>;
983
1411
  /**
984
1412
  * Delete a queue configuration
1413
+ *
1414
+ * Without `deleteJobs` the API only deletes an explicit queue config of an
1415
+ * idle queue, and answers 409 otherwise: a queue that exists only because
1416
+ * jobs were posted to it has no config to delete, and a queue with pending
1417
+ * or processing jobs is not idle. Pass `{ deleteJobs: true }` to delete the
1418
+ * queue's jobs (and DLQ rows) along with it.
985
1419
  */
986
- delete(name: string): Promise<void>;
1420
+ delete(name: string, options?: DeleteQueueOptions): Promise<void>;
987
1421
  }
988
1422
 
989
1423
  /**
@@ -1012,6 +1446,17 @@ interface Worker {
1012
1446
  registeredAt: string;
1013
1447
  /** Last row update (detail response). */
1014
1448
  updatedAt?: string;
1449
+ /**
1450
+ * Jobs this worker completed while it held the lease (API 0.1.122+; counts
1451
+ * start at 0 with that release).
1452
+ */
1453
+ jobsProcessed?: number;
1454
+ /**
1455
+ * Failed attempts this worker reported while it held the lease: a fail
1456
+ * that was retried or dead-lettered (API 0.1.122+). Lease-expiry recovery
1457
+ * does not count.
1458
+ */
1459
+ jobsFailed?: number;
1015
1460
  }
1016
1461
  /** Worker summary for list responses */
1017
1462
  interface WorkerSummary {
@@ -1022,6 +1467,10 @@ interface WorkerSummary {
1022
1467
  currentJobs: number;
1023
1468
  maxConcurrency: number;
1024
1469
  lastHeartbeat: string;
1470
+ /** See {@link Worker.jobsProcessed} (API 0.1.122+). */
1471
+ jobsProcessed?: number;
1472
+ /** See {@link Worker.jobsFailed} (API 0.1.122+). */
1473
+ jobsFailed?: number;
1025
1474
  }
1026
1475
  /** Parameters for registering a worker */
1027
1476
  interface RegisterWorkerParams {
@@ -1090,6 +1539,8 @@ declare class WorkersResource {
1090
1539
  register(params: RegisterWorkerParams): Promise<RegisterWorkerResponse>;
1091
1540
  /**
1092
1541
  * Send worker heartbeat
1542
+ *
1543
+ * Idempotent on the server, so network errors, timeouts and 5xx are retried.
1093
1544
  */
1094
1545
  heartbeat(id: string, params: WorkerHeartbeatParams): Promise<void>;
1095
1546
  /**
@@ -1359,8 +1810,12 @@ interface WorkflowJob {
1359
1810
  id: string;
1360
1811
  /** Workflow ID this job belongs to */
1361
1812
  workflowId: string;
1362
- /** Job key within the workflow */
1363
- key: string;
1813
+ /**
1814
+ * Job key within the workflow. The API does not return it (a job stores only
1815
+ * its workflow step), so this is undefined today; take the key to job ID
1816
+ * mapping from the `jobIds` of `workflows.create()`.
1817
+ */
1818
+ key?: string;
1364
1819
  /** Queue name */
1365
1820
  queueName: string;
1366
1821
  /** Current job status */
@@ -1392,8 +1847,8 @@ interface WorkflowJob {
1392
1847
  interface WorkflowJobStatus {
1393
1848
  /** Job ID */
1394
1849
  jobId: string;
1395
- /** Job key within the workflow */
1396
- key: string;
1850
+ /** Job key within the workflow; undefined, see {@link WorkflowJob.key} */
1851
+ key?: string;
1397
1852
  /** Current status */
1398
1853
  status: string;
1399
1854
  /** Progress percentage (0-100) */
@@ -1415,7 +1870,7 @@ interface WorkflowJobOperations {
1415
1870
  * @example
1416
1871
  * ```typescript
1417
1872
  * const jobs = await client.workflows.jobs.list('wf_123');
1418
- * console.log('Jobs:', jobs.map(j => j.key));
1873
+ * console.log('Jobs:', jobs.map(j => j.id));
1419
1874
  * ```
1420
1875
  */
1421
1876
  list(workflowId: string): Promise<WorkflowJob[]>;
@@ -1434,14 +1889,16 @@ interface WorkflowJobOperations {
1434
1889
  /**
1435
1890
  * Get the status of all jobs in a workflow.
1436
1891
  *
1437
- * Returns a summary of each job's status and progress.
1892
+ * Returns a summary of each job's status. The API does not store or return
1893
+ * the `key` a job was created with, so `key` is undefined; map keys to job
1894
+ * IDs from the `jobIds` array that `workflows.create()` returns.
1438
1895
  *
1439
1896
  * @param workflowId - The workflow ID
1440
1897
  * @example
1441
1898
  * ```typescript
1442
1899
  * const statuses = await client.workflows.jobs.getStatus('wf_123');
1443
1900
  * for (const s of statuses) {
1444
- * console.log(`${s.key}: ${s.status}`);
1901
+ * console.log(`${s.jobId}: ${s.status}`);
1445
1902
  * }
1446
1903
  * ```
1447
1904
  */
@@ -1538,6 +1995,12 @@ interface OutgoingWebhook {
1538
1995
  * it is re-enabled with `update(id, { enabled: true })`.
1539
1996
  */
1540
1997
  lastStatus?: "success" | "failed" | "auto_disabled";
1998
+ /**
1999
+ * Body format of the deliveries (API 0.1.122+; absent from older servers,
2000
+ * which only send `json`). A format newer than this SDK is passed through
2001
+ * as a string.
2002
+ */
2003
+ format?: WebhookFormat | (string & {});
1541
2004
  createdAt: string;
1542
2005
  updatedAt: string;
1543
2006
  }
@@ -1553,6 +2016,11 @@ interface CreateOutgoingWebhookParams {
1553
2016
  secret?: string;
1554
2017
  /** Whether enabled (default: true) */
1555
2018
  enabled?: boolean;
2019
+ /**
2020
+ * Body format (default `json`; API 0.1.122+). `slack`, `discord` and
2021
+ * `teams` post a chat message to that service's incoming-webhook URL.
2022
+ */
2023
+ format?: WebhookFormat;
1556
2024
  }
1557
2025
  /**
1558
2026
  * Parameters for updating an outgoing webhook.
@@ -1583,6 +2051,8 @@ interface UpdateOutgoingWebhookParams {
1583
2051
  * `QUOTA_EXCEEDED` even though no webhook is being created.
1584
2052
  */
1585
2053
  enabled?: boolean;
2054
+ /** New body format; omit it to keep the current one (API 0.1.122+). */
2055
+ format?: WebhookFormat;
1586
2056
  }
1587
2057
  /** Response for webhook test */
1588
2058
  interface TestWebhookResponse {
@@ -1951,14 +2421,12 @@ declare class OrganizationsResource {
1951
2421
  /**
1952
2422
  * Clear/delete the webhook token for the current organization.
1953
2423
  *
1954
- * POST /organizations/webhook-token/clear requires `{ confirm: true }`.
1955
- * An empty body 422s. The API currently rejects the operation and tells
1956
- * callers to use regenerateWebhookToken() instead.
1957
- *
1958
- * @example
1959
- * ```typescript
1960
- * await client.organizations.clearWebhookToken();
1961
- * ```
2424
+ * @deprecated The API refuses this operation on purpose (an org without a
2425
+ * webhook token would have an open public ingestion endpoint) and always
2426
+ * answers with an error. This method now throws
2427
+ * {@link UnsupportedOperationError} without a network call; rotate the token
2428
+ * with {@link OrganizationsResource.regenerateWebhookToken} instead. It will
2429
+ * be removed in the next major release.
1962
2430
  */
1963
2431
  clearWebhookToken(): Promise<void>;
1964
2432
  }
@@ -2271,8 +2739,9 @@ declare class AdminResource {
2271
2739
  /**
2272
2740
  * Webhook Ingestion Types
2273
2741
  *
2274
- * These endpoints are primarily intended to be called by external webhook providers (GitHub/Stripe)
2275
- * and are authenticated via signatures (not API keys).
2742
+ * The custom endpoint is called by external webhook providers and is
2743
+ * authenticated by the org webhook token (not an API key). The GitHub and
2744
+ * Stripe option types are kept only so existing code still compiles.
2276
2745
  */
2277
2746
 
2278
2747
  interface IngestCustomWebhookParams {
@@ -2288,6 +2757,39 @@ interface IngestCustomWebhookResponse {
2288
2757
  queueName?: string;
2289
2758
  status?: string;
2290
2759
  }
2760
+ /** `status` of an inbound webhook log entry */
2761
+ type InboundDeliveryStatus = "created" | "duplicate";
2762
+ /** Parameters for `ingest.listDeliveries()` (`GET /webhooks/deliveries`) */
2763
+ interface ListInboundDeliveriesParams extends PaginationParams {
2764
+ /** `created` (a new job) or `duplicate` (an idempotent replay) */
2765
+ status?: InboundDeliveryStatus;
2766
+ /**
2767
+ * Only entries received at or after this instant. A `Date` is sent as an
2768
+ * ISO 8601 UTC string; a string must be RFC 3339.
2769
+ */
2770
+ since?: Date | string;
2771
+ /** Only entries whose job went to this queue (exact match) */
2772
+ queueName?: string;
2773
+ }
2774
+ /**
2775
+ * One accepted request to `POST /webhooks/{org_id}/custom`, from the inbound
2776
+ * webhook log (API 0.1.122+). The log never holds the payload or a signature.
2777
+ */
2778
+ interface InboundWebhookDelivery {
2779
+ id: string;
2780
+ /** `custom` today */
2781
+ provider: string;
2782
+ /** The request's event type, `custom` when it had none */
2783
+ eventType: string;
2784
+ /** Queue of the job the request resolved to */
2785
+ matchedQueue: string | null;
2786
+ /** Job the request created or matched (`null` for entries before 0.1.122) */
2787
+ jobId: string | null;
2788
+ /** `created` or `duplicate` (`null` for entries before 0.1.122) */
2789
+ status: InboundDeliveryStatus | (string & {}) | null;
2790
+ createdAt: string;
2791
+ }
2792
+ /** @deprecated The API has no GitHub webhook route; `ingest.github` throws. */
2291
2793
  interface IngestGitHubWebhookOptions {
2292
2794
  /** Value for X-GitHub-Event header (e.g. "pull_request") */
2293
2795
  githubEvent: string;
@@ -2300,6 +2802,7 @@ interface IngestGitHubWebhookOptions {
2300
2802
  /** If provided, the SDK will compute the signature for you */
2301
2803
  secret?: string;
2302
2804
  }
2805
+ /** @deprecated The API has no Stripe webhook route; `ingest.stripe` throws. */
2303
2806
  interface IngestStripeWebhookOptions {
2304
2807
  /** Optional org-scoped webhook token (X-Webhook-Token) */
2305
2808
  webhookToken?: string;
@@ -2316,8 +2819,9 @@ interface IngestStripeWebhookOptions {
2316
2819
  /**
2317
2820
  * Webhook Ingestion Resource
2318
2821
  *
2319
- * These endpoints are intended for webhook providers (GitHub/Stripe/custom) to enqueue jobs.
2320
- * They are authenticated via signatures (not API keys).
2822
+ * The Spooled API ingests webhooks on one route:
2823
+ * `POST /api/v1/webhooks/{org_id}/custom`, authenticated by the org's webhook
2824
+ * token. The GitHub and Stripe routes were removed from the API.
2321
2825
  */
2322
2826
 
2323
2827
  declare class WebhookIngestionResource {
@@ -2326,15 +2830,23 @@ declare class WebhookIngestionResource {
2326
2830
  /**
2327
2831
  * Ingest a GitHub webhook.
2328
2832
  *
2329
- * POST /api/v1/webhooks/{org_id}/github
2833
+ * @deprecated The API has no `/webhooks/{org_id}/github` route (it always
2834
+ * answered 404). This method now throws {@link UnsupportedOperationError}
2835
+ * without a network call; point the GitHub webhook at `ingest.custom` /
2836
+ * `POST /api/v1/webhooks/{org_id}/custom` instead. It will be removed in the
2837
+ * next major release.
2330
2838
  */
2331
- github(orgId: string, body: string | Uint8Array | ArrayBuffer, options: IngestGitHubWebhookOptions): Promise<void>;
2839
+ github(_orgId: string, _body: string | Uint8Array | ArrayBuffer, _options: IngestGitHubWebhookOptions): Promise<void>;
2332
2840
  /**
2333
2841
  * Ingest a Stripe webhook.
2334
2842
  *
2335
- * POST /api/v1/webhooks/{org_id}/stripe
2843
+ * @deprecated The API has no `/webhooks/{org_id}/stripe` route (it always
2844
+ * answered 404). This method now throws {@link UnsupportedOperationError}
2845
+ * without a network call; point the Stripe webhook at `ingest.custom` /
2846
+ * `POST /api/v1/webhooks/{org_id}/custom` instead. It will be removed in the
2847
+ * next major release.
2336
2848
  */
2337
- stripe(orgId: string, body: string | Uint8Array | ArrayBuffer, options?: IngestStripeWebhookOptions): Promise<void>;
2849
+ stripe(_orgId: string, _body: string | Uint8Array | ArrayBuffer, _options?: IngestStripeWebhookOptions): Promise<void>;
2338
2850
  /**
2339
2851
  * Ingest a custom webhook.
2340
2852
  *
@@ -2345,6 +2857,17 @@ declare class WebhookIngestionResource {
2345
2857
  webhookToken?: string;
2346
2858
  forwardedProto?: string;
2347
2859
  }): Promise<IngestCustomWebhookResponse>;
2860
+ /**
2861
+ * The inbound webhook log: accepted requests to
2862
+ * `POST /webhooks/{org_id}/custom`, newest first
2863
+ * (`GET /webhooks/deliveries`, API 0.1.122+).
2864
+ *
2865
+ * Needs an API key without a queue restriction (a queue-scoped key gets a
2866
+ * 403 `AuthorizationError`). Entries carry no payload and no signature;
2867
+ * requests that were rejected are not logged. `limit` defaults to 50 (at
2868
+ * most 100); an invalid filter is a 400 `ValidationError`.
2869
+ */
2870
+ listDeliveries(params?: ListInboundDeliveriesParams): Promise<InboundWebhookDelivery[]>;
2348
2871
  }
2349
2872
 
2350
2873
  /**
@@ -2758,8 +3281,11 @@ interface GrpcCompleteRequest {
2758
3281
  workerId: string;
2759
3282
  /** Result as object (will be converted to google.protobuf.Struct) */
2760
3283
  result?: Record<string, unknown>;
2761
- /** Lease fencing token from the dequeued job (proto `lease_id`) */
2762
- leaseId?: string;
3284
+ /**
3285
+ * Lease fencing token from the dequeued job (proto `lease_id`). Required: the
3286
+ * server rejects a settlement without it with INVALID_ARGUMENT.
3287
+ */
3288
+ leaseId: string;
2763
3289
  }
2764
3290
  /** Complete response */
2765
3291
  interface GrpcCompleteResponse {
@@ -2770,9 +3296,20 @@ interface GrpcFailRequest {
2770
3296
  jobId: string;
2771
3297
  workerId: string;
2772
3298
  error: string;
3299
+ /**
3300
+ * Retry the job (until its `maxRetries` run out) instead of dead-lettering it
3301
+ * at once. Defaults to `true`, which the SDK sends explicitly, so servers
3302
+ * from before proto field 4 became `optional bool` (where an absent field
3303
+ * read as `false` and dead-lettered the job on its first failure) behave the
3304
+ * same. Pass `false` to dead-letter the job now, whatever `maxRetries` says:
3305
+ * the SDK puts `retry = false` on the wire with field presence.
3306
+ */
2773
3307
  retry?: boolean;
2774
- /** Lease fencing token from the dequeued job (proto `lease_id`) */
2775
- leaseId?: string;
3308
+ /**
3309
+ * Lease fencing token from the dequeued job (proto `lease_id`). Required: the
3310
+ * server rejects a settlement without it with INVALID_ARGUMENT.
3311
+ */
3312
+ leaseId: string;
2776
3313
  }
2777
3314
  /** Fail response */
2778
3315
  interface GrpcFailResponse {
@@ -2785,8 +3322,11 @@ interface GrpcRenewLeaseRequest {
2785
3322
  jobId: string;
2786
3323
  workerId: string;
2787
3324
  extensionSecs: number;
2788
- /** Lease fencing token from the dequeued job (proto `lease_id`) */
2789
- leaseId?: string;
3325
+ /**
3326
+ * Lease fencing token from the dequeued job (proto `lease_id`). Required: the
3327
+ * server rejects a renewal without it with INVALID_ARGUMENT.
3328
+ */
3329
+ leaseId: string;
2790
3330
  }
2791
3331
  /** Renew lease response */
2792
3332
  interface GrpcRenewLeaseResponse {
@@ -2851,6 +3391,17 @@ interface GrpcRegisterWorkerRequest {
2851
3391
  maxConcurrency?: number;
2852
3392
  version?: string;
2853
3393
  metadata?: Record<string, string>;
3394
+ /**
3395
+ * Stable worker id (proto `optional string worker_id = 7`): 1-128
3396
+ * characters, letters, digits, `-`, `_` and `.`.
3397
+ *
3398
+ * Send the same id after a restart and the server updates that worker
3399
+ * instead of adding one, so a restarting worker does not count twice against
3400
+ * the plan's worker limit. Omitted or empty: the server assigns a new id. An
3401
+ * id that another organization already uses fails with ALREADY_EXISTS
3402
+ * (`ConflictError`). Servers older than API 0.1.119 ignore the field.
3403
+ */
3404
+ workerId?: string;
2854
3405
  }
2855
3406
  /** Register worker response */
2856
3407
  interface GrpcRegisterWorkerResponse {
@@ -3319,6 +3870,13 @@ declare class SpooledClient {
3319
3870
  /**
3320
3871
  * Exchange the API key for a JWT via /auth/login and cache the result.
3321
3872
  *
3873
+ * The JWT belongs to the realtime transport only. It must NOT replace the
3874
+ * REST bearer: an API-key client has no refresh token wired into its HTTP
3875
+ * layer, so after the JWT's 24 h lifetime every REST call (claim, complete,
3876
+ * heartbeat, create) would have failed with 401 for good. REST keeps using
3877
+ * the API key; realtime re-mints its own JWT near expiry (see
3878
+ * `getJwtToken`).
3879
+ *
3322
3880
  * Concurrent callers share a single in-flight login so a burst of reconnects
3323
3881
  * (e.g. WebSocket and SSE at once) issues just one request.
3324
3882
  */
@@ -3339,6 +3897,15 @@ declare class SpooledClient {
3339
3897
  * Get current configuration (read-only)
3340
3898
  */
3341
3899
  getConfig(): Readonly<ResolvedConfig>;
3900
+ /**
3901
+ * Rate-limit state from the most recent response that carried
3902
+ * `X-RateLimit-*` headers (API 0.1.122+): `limit`, `remaining`, `reset`
3903
+ * (from the Unix-seconds header), `scope` and, after a 429, `retryAfter`.
3904
+ * `undefined` until such a response arrives, and for servers or routes that
3905
+ * do not send the headers. A 429 also carries the same values on
3906
+ * `RateLimitError.rateLimitInfo`.
3907
+ */
3908
+ getRateLimitInfo(): RateLimitInfo | undefined;
3342
3909
  /**
3343
3910
  * Get circuit breaker statistics
3344
3911
  */
@@ -3416,7 +3983,10 @@ interface SpooledWorkerOptions {
3416
3983
  version?: string;
3417
3984
  /** Additional worker metadata */
3418
3985
  metadata?: JsonObject;
3419
- /** Graceful shutdown timeout in ms (default: 30000) */
3986
+ /**
3987
+ * Graceful shutdown timeout in ms (default: 30000): how long `stop()` lets
3988
+ * running handlers finish before aborting and failing them.
3989
+ */
3420
3990
  shutdownTimeout?: number;
3421
3991
  }
3422
3992
  /** Worker state */
@@ -3433,7 +4003,12 @@ interface JobContext {
3433
4003
  retryCount: number;
3434
4004
  /** Maximum retries */
3435
4005
  maxRetries: number;
3436
- /** Abort signal for graceful shutdown */
4006
+ /**
4007
+ * Abort signal. Aborted when the job exceeds its `timeoutSeconds` or when a
4008
+ * stop outlives `shutdownTimeout`; NOT aborted merely because a stop was
4009
+ * requested (the handler gets the grace period to finish and be acked).
4010
+ * `signal.reason` carries the cause.
4011
+ */
3437
4012
  signal: AbortSignal;
3438
4013
  /** Log local job progress (0-100); backend progress persistence is not yet available. */
3439
4014
  progress: (percent: number, message?: string) => Promise<void>;
@@ -3493,7 +4068,16 @@ interface ActiveJob {
3493
4068
  job: ClaimedJob;
3494
4069
  startedAt: Date;
3495
4070
  heartbeatTimer?: ReturnType<typeof setInterval>;
4071
+ /** Fires when the job exceeds its `timeoutSeconds` */
4072
+ timeoutTimer?: ReturnType<typeof setTimeout>;
3496
4073
  abortController: AbortController;
4074
+ /**
4075
+ * The outcome of this execution is decided (acked, or about to be): nothing
4076
+ * else may ack it. Set when the handler settles or the shutdown fails it.
4077
+ */
4078
+ settled?: boolean;
4079
+ /** The complete/fail request for this execution, once started. */
4080
+ ack?: Promise<void>;
3497
4081
  }
3498
4082
 
3499
4083
  /**
@@ -3542,6 +4126,10 @@ declare class SpooledWorker {
3542
4126
  private pollTimer;
3543
4127
  private workerHeartbeatTimer;
3544
4128
  private shutdownPromise;
4129
+ /** The claim request currently on the wire, so a stop can wait for its jobs. */
4130
+ private pollInFlight;
4131
+ /** Wakes the shutdown drain when the last active job has been acked. */
4132
+ private drainWaiter;
3545
4133
  private eventHandlers;
3546
4134
  constructor(client: SpooledClient, options: SpooledWorkerOptions);
3547
4135
  /**
@@ -3565,7 +4153,15 @@ declare class SpooledWorker {
3565
4153
  */
3566
4154
  start(): Promise<void>;
3567
4155
  /**
3568
- * Stop the worker gracefully
4156
+ * Stop the worker gracefully.
4157
+ *
4158
+ * Drains: the worker stops claiming, then lets running handlers finish for
4159
+ * up to `shutdownTimeout`. A handler that returns completes its job and one
4160
+ * that throws fails it, even though a stop was requested meanwhile; its
4161
+ * `signal` is NOT aborted during the grace period. Only handlers still
4162
+ * running when the timeout ends are aborted and failed with "Worker shutdown
4163
+ * timeout". The worker deregisters last, because deregistering returns every
4164
+ * job the worker still holds to the queue.
3569
4165
  */
3570
4166
  stop(): Promise<void>;
3571
4167
  private doStop;
@@ -3582,13 +4178,24 @@ declare class SpooledWorker {
3582
4178
  private poll;
3583
4179
  private processJob;
3584
4180
  private executeHandler;
4181
+ /**
4182
+ * Run the handler, racing it against the job's `timeoutSeconds`.
4183
+ * Never rejects: a throw (sync or async) is reported as an outcome.
4184
+ */
4185
+ private runHandler;
4186
+ /** Abort a handler that outlived the shutdown grace period and fail its job. */
4187
+ private abandonJob;
3585
4188
  private completeJob;
3586
4189
  private failJob;
4190
+ private clearTimeoutTimer;
3587
4191
  private cleanupJob;
3588
4192
  private sendJobHeartbeat;
3589
4193
  private sendWorkerHeartbeat;
3590
- private waitForActiveJobs;
3591
- private sleep;
4194
+ /**
4195
+ * Resolve once no job is active, or after `timeoutMs`. The timer is always
4196
+ * cleared, so a clean stop leaves nothing that keeps the process alive.
4197
+ */
4198
+ private waitForDrain;
3592
4199
  }
3593
4200
 
3594
- export { type CreateWorkflowParams as $, API_VERSION as A, type BatchJobStatus as B, type ConnectionState as C, type BulkEnqueueResponse as D, type BulkJobItem as E, type CheckEmailResponse as F, type CheckSlugResponse as G, CircuitBreaker as H, type CircuitBreakerConfig as I, CircuitState as J, type ClaimJobsParams as K, type ClaimJobsResult as L, type ClaimedJob as M, type CompleteJobParams as N, type CreateApiKeyParams as O, type CreateApiKeyResponse as P, type CreateBillingPortalParams as Q, type RealtimeConnectionOptions as R, type SubscriptionFilter as S, type CreateBillingPortalResponse as T, type CreateJobParams as U, type CreateJobResult as V, type CreateOrganizationParams as W, type CreateOrganizationResponse as X, type CreateOutgoingWebhookParams as Y, type CreateScheduleParams as Z, type CreateScheduleResponse as _, type RealtimeEventType as a, type IngestGitHubWebhookOptions as a$, type CreateWorkflowResponse as a0, type CurrentUserResponse as a1, DEFAULT_CONFIG as a2, type DashboardData as a3, DashboardResource as a4, type DashboardWorkerSummary as a5, type DebugFn as a6, type DependencyInfo as a7, type DependencyMode as a8, type FailJobParams as a9, type GrpcHeartbeatRequest as aA, type GrpcHeartbeatResponse as aB, type GrpcHeartbeatResponse_Legacy as aC, type GrpcJob as aD, GrpcJobStatus as aE, GrpcJobStatusNumber as aF, type GrpcProcessRequest as aG, type GrpcProcessResponse as aH, GrpcQueueOperations as aI, type GrpcRegisterWorkerParams as aJ, type GrpcRegisterWorkerRequest as aK, type GrpcRegisterWorkerResponse as aL, type GrpcRegisterWorkerResponse_Legacy as aM, type GrpcRenewLeaseParams as aN, type GrpcRenewLeaseRequest as aO, type GrpcRenewLeaseResponse as aP, type GrpcRenewLeaseResponse_Legacy as aQ, type GrpcStreamJobsRequest as aR, type GrpcTimestamp as aS, GrpcWorkerOperations as aT, HealthResource as aU, type HealthResponse as aV, type HeartbeatEvent as aW, type HeartbeatJobParams as aX, HttpClient as aY, type IngestCustomWebhookParams as aZ, type IngestCustomWebhookResponse as a_, type GrpcClientOptions as aa, type GrpcCompleteJobParams as ab, type GrpcCompleteJobResponse as ac, type GrpcCompleteRequest as ad, type GrpcCompleteResponse as ae, type GrpcDequeueJobParams as af, type GrpcDequeueJobResponse as ag, type GrpcDequeueRequest as ah, type GrpcDequeueResponse as ai, type GrpcDeregisterRequest as aj, type GrpcDeregisterResponse as ak, type GrpcEnqueueJobParams as al, type GrpcEnqueueJobResponse as am, type GrpcEnqueueRequest as an, type GrpcEnqueueResponse as ao, type GrpcErrorResponse as ap, type GrpcFailJobParams as aq, type GrpcFailJobResponse as ar, type GrpcFailRequest as as, type GrpcFailResponse as at, type GrpcGetJobRequest as au, type GrpcGetJobResponse as av, type GrpcGetQueueStatsRequest as aw, type GrpcGetQueueStatsResponse as ax, type GrpcGetQueueStatsResponse_Legacy as ay, type GrpcHeartbeatParams as az, type RealtimeEvent as b, type RetryDlqParams as b$, type IngestStripeWebhookOptions as b0, type InitialApiKey as b1, type Job as b2, type JobCompletedEvent as b3, type JobContext as b4, type JobCreatedEvent as b5, type JobFailedEvent as b6, type JobHandler as b7, type JobProgressEvent as b8, type JobResult as b9, type OutgoingWebhook as bA, type OutgoingWebhookDelivery as bB, type PaginatedResponse as bC, type PaginationParams as bD, type PauseQueueResponse as bE, type PlanCount as bF, type PlanLimits as bG, type PlanTier as bH, type ProcessJobsStream as bI, type PurgeDlqParams as bJ, type PurgeDlqResponse as bK, type QueueConfig as bL, type QueueConfigSummary as bM, type QueuePausedEvent as bN, type QueueResumedEvent as bO, type QueueStats as bP, type QueueSummary as bQ, QueuesResource as bR, type RealtimeEventData as bS, type RecentActivity as bT, type RefreshTokenParams as bU, type RefreshTokenResponse as bV, type RegisterWorkerParams as bW, type RegisterWorkerResponse as bX, type ResolvedConfig as bY, type ResourceUsage as bZ, type ResumeQueueResponse as b_, type JobStartedEvent as ba, type JobStats as bb, type JobStatus as bc, type JobStatusChangedEvent as bd, type JobStream as be, type JobSummary as bf, type JobSummaryStats as bg, type JobWithDependencies as bh, JobsResource as bi, type JsonArray as bj, type JsonObject as bk, type JsonPrimitive as bl, type JsonValue as bm, type ListDlqParams as bn, type ListJobsParams as bo, type ListParams as bp, type ListSchedulesParams as bq, type ListWorkflowsParams as br, type LoginParams as bs, type LoginResponse as bt, MetricsResource as bu, type Organization as bv, type OrganizationMember as bw, type OrganizationSummary as bx, type OrganizationUsage as by, OrganizationsResource as bz, type RetryConfig as c, type RetryDlqResponse as c0, SDK_VERSION as c1, type Schedule as c2, type ScheduleRun as c3, type ScheduleRunStatus as c4, type ScheduleTriggeredEvent as c5, SchedulesResource as c6, SpooledClient as c7, type SpooledClientConfig as c8, SpooledGrpcClient as c9, type WorkerEvent as cA, type WorkerEventData as cB, type WorkerHeartbeatParams as cC, type WorkerRegisteredEvent as cD, type WorkerState as cE, type WorkerStatus as cF, type WorkerSummary as cG, WorkersResource as cH, type Workflow as cI, type WorkflowJob as cJ, type WorkflowJobDefinition as cK, type WorkflowJobStatus as cL, type WorkflowResponse as cM, type WorkflowStatus as cN, WorkflowsResource as cO, asyncIterableFromStream as cP, createCircuitBreaker as cQ, createClient as cR, createHttpClient as cS, createJobStream as cT, createPaginatedResponse as cU, createProcessJobsStream as cV, dateToTimestamp as cW, resolveConfig as cX, timestampToDate as cY, validateConfig as cZ, type ActiveJob as c_, SpooledRealtime as ca, type SpooledRealtimeOptions as cb, SpooledWorker as cc, type SpooledWorkerOptions as cd, type StartEmailLoginResponse as ce, type StreamOptions as cf, type SystemInfo as cg, type TestWebhookResponse as ch, type TokenClaims as ci, type TriggerScheduleResponse as cj, type UpdateApiKeyParams as ck, type UpdateOrganizationParams as cl, type UpdateOutgoingWebhookParams as cm, type UpdateQueueConfigParams as cn, type UpdateScheduleParams as co, type UsageItem as cp, type UsageWarning as cq, type ValidateTokenParams as cr, type ValidateTokenResponse as cs, type WebhookDeliveryStatus as ct, type WebhookEventType as cu, WebhookIngestionResource as cv, type WebhookTokenResponse as cw, WebhooksResource as cx, type Worker as cy, type WorkerDeregisteredEvent as cz, type AddDependenciesParams as d, type AddDependenciesResponse as e, type AdminApiKeyResponse as f, type AdminCreateApiKeyParams as g, type AdminCreateOrganizationParams as h, type AdminCreateOrganizationResponse as i, type AdminDeleteOrganizationParams as j, type AdminListOrganizationsParams as k, type AdminOrganizationDetail as l, type AdminOrganizationList as m, type AdminOrganizationSummary as n, type AdminPlanLimits as o, type AdminPlatformStats as p, AdminResource as q, type AdminUpdateOrganizationParams as r, type AdminUsageStats as s, type ApiKeySummary as t, ApiKeysResource as u, AuthResource as v, BillingResource as w, type BillingStatus as x, type BoostPriorityResponse as y, type BulkEnqueueParams as z };
4201
+ export { type CreateJobParams as $, API_VERSION as A, type BatchJobStatus as B, type ConnectionState as C, type BillingStatus as D, type BoostPriorityResponse as E, type BulkEnqueueParams as F, type BulkEnqueueResponse as G, type BulkJobItem as H, type CheckEmailResponse as I, type CheckSlugResponse as J, CircuitBreaker as K, type CircuitBreakerConfig as L, CircuitBreakerOpenError as M, type CircuitBreakerOptions as N, CircuitState as O, type CircuitStateChange as P, type ClaimJobsParams as Q, type RealtimeConnectionOptions as R, type SubscriptionFilter as S, type ClaimJobsResult as T, type ClaimedJob as U, type CompleteJobParams as V, ConflictError as W, type CreateApiKeyParams as X, type CreateApiKeyResponse as Y, type CreateBillingPortalParams as Z, type CreateBillingPortalResponse as _, type RealtimeEventType as a, GrpcWorkerOperations as a$, type CreateJobResult as a0, type CreateOrganizationParams as a1, type CreateOrganizationResponse as a2, type CreateOutgoingWebhookParams as a3, type CreateScheduleParams as a4, type CreateScheduleResponse as a5, type CreateWorkflowParams as a6, type CreateWorkflowResponse as a7, type CurrentUserResponse as a8, DEFAULT_CONFIG as a9, type GrpcFailRequest as aA, type GrpcFailResponse as aB, type GrpcGetJobRequest as aC, type GrpcGetJobResponse as aD, type GrpcGetQueueStatsRequest as aE, type GrpcGetQueueStatsResponse as aF, type GrpcGetQueueStatsResponse_Legacy as aG, type GrpcHeartbeatParams as aH, type GrpcHeartbeatRequest as aI, type GrpcHeartbeatResponse as aJ, type GrpcHeartbeatResponse_Legacy as aK, type GrpcJob as aL, GrpcJobStatus as aM, GrpcJobStatusNumber as aN, type GrpcProcessRequest as aO, type GrpcProcessResponse as aP, GrpcQueueOperations as aQ, type GrpcRegisterWorkerParams as aR, type GrpcRegisterWorkerRequest as aS, type GrpcRegisterWorkerResponse as aT, type GrpcRegisterWorkerResponse_Legacy as aU, type GrpcRenewLeaseParams as aV, type GrpcRenewLeaseRequest as aW, type GrpcRenewLeaseResponse as aX, type GrpcRenewLeaseResponse_Legacy as aY, type GrpcStreamJobsRequest as aZ, type GrpcTimestamp as a_, type DashboardData as aa, DashboardResource as ab, type DashboardWorkerSummary as ac, type DebugFn as ad, type DeleteQueueOptions as ae, type DependencyInfo as af, type DependencyMode as ag, type FailJobParams as ah, type GrpcClientOptions as ai, type GrpcCompleteJobParams as aj, type GrpcCompleteJobResponse as ak, type GrpcCompleteRequest as al, type GrpcCompleteResponse as am, type GrpcDequeueJobParams as an, type GrpcDequeueJobResponse as ao, type GrpcDequeueRequest as ap, type GrpcDequeueResponse as aq, type GrpcDeregisterRequest as ar, type GrpcDeregisterResponse as as, type GrpcEnqueueJobParams as at, type GrpcEnqueueJobResponse as au, type GrpcEnqueueRequest as av, type GrpcEnqueueResponse as aw, type GrpcErrorResponse as ax, type GrpcFailJobParams as ay, type GrpcFailJobResponse as az, type RealtimeEvent as b, type ProcessJobsStream as b$, HealthResource as b0, type HealthResponse as b1, type HeartbeatEvent as b2, type HeartbeatJobParams as b3, HttpClient as b4, type InboundDeliveryStatus as b5, type InboundWebhookDelivery as b6, type IngestCustomWebhookParams as b7, type IngestCustomWebhookResponse as b8, type IngestGitHubWebhookOptions as b9, type JsonValue as bA, type ListDlqParams as bB, type ListInboundDeliveriesParams as bC, type ListJobsParams as bD, type ListPage as bE, type ListParams as bF, type ListSchedulesParams as bG, type ListWorkflowsParams as bH, type LoginParams as bI, type LoginResponse as bJ, MetricsResource as bK, NetworkError as bL, NotFoundError as bM, type Organization as bN, type OrganizationMember as bO, type OrganizationSummary as bP, type OrganizationUsage as bQ, OrganizationsResource as bR, type OutgoingWebhook as bS, type OutgoingWebhookDelivery as bT, type PaginatedResponse as bU, type PaginationParams as bV, type PauseQueueResponse as bW, PayloadTooLargeError as bX, type PlanCount as bY, type PlanLimits as bZ, type PlanTier as b_, type IngestStripeWebhookOptions as ba, type InitialApiKey as bb, type Job as bc, type JobCompletedEvent as bd, type JobContext as be, type JobCreatedEvent as bf, type JobFailedEvent as bg, type JobHandler as bh, type JobHistoryEvent as bi, type JobHistoryEventType as bj, type JobHistoryParams as bk, type JobProgressEvent as bl, type JobResult as bm, type JobSearchParams as bn, type JobStartedEvent as bo, type JobStats as bp, type JobStatus as bq, type JobStatusChangedEvent as br, type JobStream as bs, type JobSummary as bt, type JobSummaryStats as bu, type JobWithDependencies as bv, JobsResource as bw, type JsonArray as bx, type JsonObject as by, type JsonPrimitive as bz, type RetryConfig as c, type WorkerEvent as c$, type PurgeDlqParams as c0, type PurgeDlqResponse as c1, type QueueConfig as c2, type QueueConfigSummary as c3, type QueuePausedEvent as c4, type QueueResumedEvent as c5, type QueueStats as c6, type QueueSummary as c7, QueuesResource as c8, RateLimitError as c9, type SpooledWorkerOptions as cA, type StartEmailLoginResponse as cB, type StreamOptions as cC, type SystemInfo as cD, type TestWebhookResponse as cE, TimeoutError as cF, type TokenClaims as cG, type TriggerScheduleResponse as cH, UnsupportedOperationError as cI, type UpdateApiKeyParams as cJ, type UpdateOrganizationParams as cK, type UpdateOutgoingWebhookParams as cL, type UpdateQueueConfigParams as cM, type UpdateScheduleParams as cN, type UsageItem as cO, type UsageWarning as cP, type ValidateTokenParams as cQ, type ValidateTokenResponse as cR, ValidationError as cS, type WebhookDeliveryStatus as cT, type WebhookEventType as cU, type WebhookFormat as cV, WebhookIngestionResource as cW, type WebhookTokenResponse as cX, WebhooksResource as cY, type Worker as cZ, type WorkerDeregisteredEvent as c_, type RateLimitInfo as ca, type RealtimeEventData as cb, type RecentActivity as cc, type RefreshTokenParams as cd, type RefreshTokenResponse as ce, type RegisterWorkerParams as cf, type RegisterWorkerResponse as cg, type ResolvedConfig as ch, type ResourceUsage as ci, type ResumeQueueResponse as cj, type RetryDlqParams as ck, type RetryDlqResponse as cl, SDK_VERSION as cm, type Schedule as cn, type ScheduleRun as co, type ScheduleRunStatus as cp, type ScheduleTriggeredEvent as cq, SchedulesResource as cr, ServerError as cs, SpooledClient as ct, type SpooledClientConfig as cu, SpooledError as cv, SpooledGrpcClient as cw, SpooledRealtime as cx, type SpooledRealtimeOptions as cy, SpooledWorker as cz, type AddDependenciesParams as d, type WorkerEventData as d0, type WorkerHeartbeatParams as d1, type WorkerRegisteredEvent as d2, type WorkerState as d3, type WorkerStatus as d4, type WorkerSummary as d5, WorkersResource as d6, type Workflow as d7, type WorkflowJob as d8, type WorkflowJobDefinition as d9, type WorkflowJobStatus as da, type WorkflowResponse as db, type WorkflowStatus as dc, WorkflowsResource as dd, asyncIterableFromStream as de, createCircuitBreaker as df, createClient as dg, createErrorFromResponse as dh, createHttpClient as di, createJobStream as dj, createPaginatedResponse as dk, createProcessJobsStream as dl, dateToTimestamp as dm, isCircuitBreakerFailure as dn, isRetryableError as dp, isSpooledError as dq, parseRateLimitHeaders as dr, resolveConfig as ds, timestampToDate as dt, validateConfig as du, type ActiveJob as dv, type AddDependenciesResponse as e, type AdminApiKeyResponse as f, type AdminCreateApiKeyParams as g, type AdminCreateOrganizationParams as h, type AdminCreateOrganizationResponse as i, type AdminDeleteOrganizationParams as j, type AdminListOrganizationsParams as k, type AdminOrganizationDetail as l, type AdminOrganizationList as m, type AdminOrganizationSummary as n, type AdminPlanLimits as o, type AdminPlatformStats as p, AdminResource as q, type AdminUpdateOrganizationParams as r, type AdminUsageStats as s, type ApiErrorBody as t, type ApiKeySummary as u, ApiKeysResource as v, AuthResource as w, AuthenticationError as x, AuthorizationError as y, BillingResource as z };