segmind 0.2.4 → 0.3.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/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/core/errors.ts
2
- var SegmindError = class _SegmindError extends Error {
2
+ var SegmindError = class extends Error {
3
3
  /** HTTP status, when the error came from a response. */
4
4
  status;
5
5
  /** The server's error text (`error` in the response body), when it sent one. */
@@ -17,20 +17,21 @@ var SegmindError = class _SegmindError extends Error {
17
17
  this.body = options.body;
18
18
  }
19
19
  /** Reads the response body and builds the error. Consumes the body. */
20
- static async fromResponse(response, requestId) {
21
- const text = await response.text().catch(() => "");
22
- let body = text;
23
- try {
24
- body = text ? JSON.parse(text) : void 0;
25
- } catch {
26
- }
27
- const detail = errorDetail(body) ?? (typeof body === "string" && body ? body.slice(0, 500) : void 0);
28
- const message = detail ? `${response.status} ${detail}` : `${response.status} ${response.statusText || "request failed"}`;
29
- return new _SegmindError(message, { status: response.status, detail, requestId, body });
20
+ static fromResponse(response, requestId) {
21
+ return errorFromResponse(response, requestId);
30
22
  }
31
23
  };
32
24
  var APIConnectionError = class extends SegmindError {
33
25
  };
26
+ var InsufficientCredits = class extends SegmindError {
27
+ };
28
+ var RateLimited = class extends SegmindError {
29
+ retryAfterMs;
30
+ constructor(message, options = {}) {
31
+ super(message, options);
32
+ this.retryAfterMs = options.retryAfterMs;
33
+ }
34
+ };
34
35
  var InferenceFailed = class extends SegmindError {
35
36
  /** The status body that reported the failure. */
36
37
  statusBody;
@@ -51,6 +52,43 @@ var InferenceTimeout = class extends SegmindError {
51
52
  this.elapsedMs = elapsedMs;
52
53
  }
53
54
  };
55
+ async function errorFromResponse(response, requestId) {
56
+ const text = await response.text().catch(() => "");
57
+ let body = text;
58
+ try {
59
+ body = text ? JSON.parse(text) : void 0;
60
+ } catch {
61
+ }
62
+ const detail = errorDetail(body) ?? plainText(body);
63
+ const message = detail ? `${response.status} ${detail}` : `${response.status} ${response.statusText || "request failed"}`;
64
+ const options = { status: response.status, detail, requestId, body };
65
+ if (response.status === 429) {
66
+ return new RateLimited(message, { ...options, retryAfterMs: parseRetryAfter(response.headers.get("retry-after")) });
67
+ }
68
+ if (response.status === 402 || isOutOfCredits(detail)) return new InsufficientCredits(message, options);
69
+ return new SegmindError(message, options);
70
+ }
71
+ function requestFailure(requestId, statusBody, detail) {
72
+ detail ??= typeof statusBody.error === "string" ? statusBody.error : void 0;
73
+ if (isOutOfCredits(detail)) {
74
+ return new InsufficientCredits(`request ${requestId} failed: ${detail}`, { detail, requestId, body: statusBody });
75
+ }
76
+ return new InferenceFailed(requestId, statusBody, detail);
77
+ }
78
+ function parseRetryAfter(value, now = Date.now()) {
79
+ if (!value) return void 0;
80
+ const seconds = Number(value);
81
+ if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
82
+ const date = Date.parse(value);
83
+ return Number.isNaN(date) ? void 0 : Math.max(date - now, 0);
84
+ }
85
+ function isOutOfCredits(detail) {
86
+ return detail?.startsWith("Insufficient credits.") ?? false;
87
+ }
88
+ function plainText(body) {
89
+ if (typeof body !== "string" || !body || body.trimStart().startsWith("<")) return void 0;
90
+ return body.slice(0, 500);
91
+ }
54
92
  function errorDetail(body) {
55
93
  if (!body || typeof body !== "object") return void 0;
56
94
  const record2 = body;
@@ -168,6 +206,12 @@ function detectRuntime() {
168
206
  if (g.process?.versions?.node) return "node";
169
207
  return "other";
170
208
  }
209
+ function initiatorHeaders(options) {
210
+ return {
211
+ ...options.initiator ? { "X-Initiator": options.initiator } : {},
212
+ ...options.initiatorId ? { "X-Initiator-ID": options.initiatorId } : {}
213
+ };
214
+ }
171
215
  function readEnv(name) {
172
216
  try {
173
217
  const value = g.process?.env?.[name];
@@ -200,15 +244,15 @@ function toBase64(bytes) {
200
244
  var RETRYABLE_STATUS = /* @__PURE__ */ new Set([408, 429, 502, 503, 504]);
201
245
  var MAX_RETRY_DELAY_MS = 6e4;
202
246
  function retryDelay(attempt, retryAfter, now = Date.now()) {
203
- if (retryAfter) {
204
- const seconds = Number(retryAfter);
205
- if (Number.isFinite(seconds) && seconds >= 0) return Math.min(seconds * 1e3, MAX_RETRY_DELAY_MS);
206
- const date = Date.parse(retryAfter);
207
- if (!Number.isNaN(date)) return Math.min(Math.max(date - now, 0), MAX_RETRY_DELAY_MS);
208
- }
247
+ const asked = parseRetryAfter(retryAfter, now);
248
+ if (asked !== void 0) return Math.min(asked, MAX_RETRY_DELAY_MS);
209
249
  const base = Math.min(500 * 2 ** attempt, 8e3);
210
250
  return base * (0.75 + Math.random() * 0.25);
211
251
  }
252
+ function pollDelay(interval, elapsedMs, fallback) {
253
+ const delay = typeof interval === "function" ? interval(elapsedMs) : interval ?? fallback;
254
+ return Number.isFinite(delay) && delay >= 0 ? delay : fallback;
255
+ }
212
256
  function sleep(ms, signal) {
213
257
  return new Promise((resolve, reject) => {
214
258
  if (signal?.aborted) return reject(signal.reason);
@@ -228,23 +272,35 @@ var HttpClient = class {
228
272
  this.config = config;
229
273
  }
230
274
  config;
275
+ /** The hook call in flight, so that requests failing together share one refresh. */
276
+ unauthorized;
231
277
  /** The response whatever its status, after retries when `retry` is set. */
232
278
  async fetchRaw(req) {
233
- for (let attempt = 0; ; attempt++) {
279
+ let attempt = 0;
280
+ let reauthenticated = false;
281
+ for (; ; ) {
234
282
  const canRetry = req.retry === true && attempt < this.config.maxRetries;
283
+ const token = await this.sessionToken(req);
235
284
  let response;
236
285
  try {
237
- response = await this.attempt(req);
286
+ response = await this.attempt(req, token);
238
287
  } catch (err) {
239
288
  if (canRetry && err instanceof APIConnectionError) {
240
289
  await sleep(retryDelay(attempt, null), req.signal);
290
+ attempt++;
241
291
  continue;
242
292
  }
243
293
  throw err;
244
294
  }
295
+ if (response.status === 401 && !reauthenticated && await this.reauthenticate(req, token)) {
296
+ reauthenticated = true;
297
+ await response.body?.cancel().catch(() => void 0);
298
+ continue;
299
+ }
245
300
  if (canRetry && RETRYABLE_STATUS.has(response.status)) {
246
301
  await response.body?.cancel().catch(() => void 0);
247
302
  await sleep(retryDelay(attempt, response.headers.get("retry-after")), req.signal);
303
+ attempt++;
248
304
  continue;
249
305
  }
250
306
  return response;
@@ -260,7 +316,31 @@ var HttpClient = class {
260
316
  async json(req) {
261
317
  return readJson(await this.request(req));
262
318
  }
263
- async attempt(req) {
319
+ async sessionToken(req) {
320
+ if (!this.config.tokenProvider || req.bare) return void 0;
321
+ try {
322
+ return await this.config.tokenProvider() ?? void 0;
323
+ } catch (err) {
324
+ throw new SegmindError(`tokenProvider failed: ${describe(err)}`, { cause: err });
325
+ }
326
+ }
327
+ /** Tells the app its token was refused. True when it now has a different one to try. */
328
+ async reauthenticate(req, refused) {
329
+ if (!this.config.tokenProvider || req.bare) return false;
330
+ try {
331
+ if (this.config.onUnauthorized) {
332
+ this.unauthorized ??= Promise.resolve(this.config.onUnauthorized()).finally(() => {
333
+ this.unauthorized = void 0;
334
+ });
335
+ await this.unauthorized;
336
+ }
337
+ const next = await this.config.tokenProvider();
338
+ return Boolean(next) && next !== refused;
339
+ } catch {
340
+ return false;
341
+ }
342
+ }
343
+ async attempt(req, token) {
264
344
  const { signal } = req;
265
345
  if (signal?.aborted) throw signal.reason;
266
346
  const timeout = req.timeout ?? this.config.timeout;
@@ -274,6 +354,7 @@ var HttpClient = class {
274
354
  signal?.addEventListener("abort", onAbort, { once: true });
275
355
  const headers = req.bare ? { ...req.headers } : { ...this.config.headers, ...req.headers };
276
356
  if (this.config.apiKey && !req.bare) headers["x-api-key"] = this.config.apiKey;
357
+ if (token) headers.Authorization = `Bearer ${token}`;
277
358
  if (req.body !== void 0) headers["content-type"] = "application/json";
278
359
  const body = req.rawBody ?? (req.body === void 0 ? void 0 : JSON.stringify(req.body));
279
360
  try {
@@ -368,7 +449,12 @@ async function readFileInput(input, options) {
368
449
  if (detectRuntime() !== "node") {
369
450
  throw new SegmindError(`${options.caller}: file paths work in Node only; pass a Blob or bytes`);
370
451
  }
371
- const { readFile } = await import("node:fs/promises");
452
+ const { readFile } = await import(
453
+ /* webpackIgnore: true */
454
+ /* turbopackIgnore: true */
455
+ /* @vite-ignore */
456
+ "node:fs/promises"
457
+ );
372
458
  try {
373
459
  bytes = new Uint8Array(await readFile(input));
374
460
  } catch (err) {
@@ -551,12 +637,12 @@ var Job = class {
551
637
  return await this.read(this.statusUrl, options.signal);
552
638
  }
553
639
  /**
554
- * The finished result. Throws `InferenceFailed` when the request failed, and
555
- * a `SegmindError` when it has not finished yet (use `wait()` for that).
640
+ * The finished result. Throws `InferenceFailed` when the request failed
641
+ * (`InsufficientCredits` when that was for lack of credits), and a `SegmindError` when it has not finished yet (use `wait()` for that).
556
642
  */
557
643
  async result(options = {}) {
558
644
  const body = await this.read(this.responseUrl, options.signal);
559
- if (body.status === "FAILED") throw new InferenceFailed(this.requestId, body);
645
+ if (body.status === "FAILED") throw requestFailure(this.requestId, body);
560
646
  if (body.status !== void 0 && body.status !== "COMPLETED") {
561
647
  throw new SegmindError(`request ${this.requestId} is still ${String(body.status)}; use wait()`, {
562
648
  requestId: this.requestId,
@@ -568,15 +654,16 @@ var Job = class {
568
654
  /** Polls until the request finishes, then returns its result. */
569
655
  async wait(options = {}) {
570
656
  const timeout = options.timeout ?? DEFAULT_WAIT_TIMEOUT_MS;
571
- const interval = options.interval ?? DEFAULT_WAIT_INTERVAL_MS;
572
657
  const started = Date.now();
573
658
  for (; ; ) {
574
659
  const status = await this.status({ signal: options.signal });
660
+ options.onStatus?.(status);
575
661
  if (status.status === "COMPLETED") return this.result({ signal: options.signal });
576
- if (status.status === "FAILED") throw new InferenceFailed(this.requestId, status);
662
+ if (status.status === "FAILED") throw requestFailure(this.requestId, status);
577
663
  const elapsed = Date.now() - started;
578
664
  if (elapsed >= timeout) throw new InferenceTimeout(this.requestId, elapsed);
579
- await sleep(Math.min(interval, timeout - elapsed), options.signal);
665
+ const delay = pollDelay(options.interval, elapsed, DEFAULT_WAIT_INTERVAL_MS);
666
+ await sleep(Math.min(delay, timeout - elapsed), options.signal);
580
667
  }
581
668
  }
582
669
  /**
@@ -608,8 +695,8 @@ var PixelFlows = class {
608
695
  client;
609
696
  /** Runs a workflow and waits for its outputs. */
610
697
  async run(slug, inputs = {}, options = {}) {
611
- const job = await this.submit(slug, inputs, options);
612
- return job.wait(options);
698
+ const job2 = await this.submit(slug, inputs, options);
699
+ return job2.wait(options);
613
700
  }
614
701
  /** Starts a workflow and returns a job to wait on. Never retried: a run bills. */
615
702
  async submit(slug, inputs = {}, options = {}) {
@@ -620,6 +707,7 @@ var PixelFlows = class {
620
707
  method: "POST",
621
708
  url: `${this.client.baseURL}${route}${clean}`,
622
709
  body: inputs,
710
+ headers: initiatorHeaders(options),
623
711
  signal: options.signal
624
712
  });
625
713
  const requestId = body.request_id;
@@ -655,20 +743,21 @@ var PixelflowJob = class {
655
743
  }
656
744
  /**
657
745
  * Polls until the run finishes. Throws `InferenceFailed` (its `detail` names
658
- * the failing node) or `InferenceTimeout`; the run may still finish after a
746
+ * the failing node), `InsufficientCredits` or `InferenceTimeout`; the run may still finish after a
659
747
  * timeout, so `wait()` can be called again.
660
748
  */
661
749
  async wait(options = {}) {
662
750
  const timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
663
- const interval = options.interval ?? DEFAULT_INTERVAL_MS;
664
751
  const started = Date.now();
665
752
  for (; ; ) {
666
753
  const state = await this.status({ signal: options.signal });
754
+ options.onStatus?.(state);
667
755
  if (DONE.has(state.status)) return state;
668
- if (FAILED.has(state.status)) throw new InferenceFailed(this.requestId, state.raw, failureDetail(state.raw));
756
+ if (FAILED.has(state.status)) throw requestFailure(this.requestId, state.raw, failureDetail(state.raw));
669
757
  const elapsed = Date.now() - started;
670
- if (elapsed + interval > timeout) throw new InferenceTimeout(this.requestId, elapsed);
671
- await sleep(interval, options.signal);
758
+ const delay = pollDelay(options.interval, elapsed, DEFAULT_INTERVAL_MS);
759
+ if (elapsed + delay > timeout) throw new InferenceTimeout(this.requestId, elapsed);
760
+ await sleep(delay, options.signal);
672
761
  }
673
762
  }
674
763
  };
@@ -713,7 +802,7 @@ function failureDetail(body) {
713
802
  }
714
803
 
715
804
  // src/version.ts
716
- var VERSION = "0.2.4";
805
+ var VERSION = "0.3.0";
717
806
 
718
807
  // src/webhooks.ts
719
808
  var Webhooks = class {
@@ -791,14 +880,17 @@ var Segmind = class {
791
880
  /** @internal */
792
881
  http;
793
882
  constructor(options = {}) {
794
- const apiKey = options.apiKey ?? readEnv("SEGMIND_API_KEY");
883
+ if (options.apiKey && options.tokenProvider) {
884
+ throw new SegmindError("Pass either apiKey or tokenProvider, not both.");
885
+ }
886
+ const apiKey = options.apiKey ?? (options.tokenProvider ? void 0 : readEnv("SEGMIND_API_KEY"));
795
887
  const runtime = detectRuntime();
796
888
  if (apiKey && (runtime === "browser" || runtime === "react-native") && !options.dangerouslyAllowBrowser) {
797
889
  throw new SegmindError(
798
890
  "An API key in a browser or mobile app exposes it to every user. Call Segmind from your backend instead, or pass dangerouslyAllowBrowser: true if you accept that risk."
799
891
  );
800
892
  }
801
- if (!apiKey) {
893
+ if (!apiKey && !options.tokenProvider) {
802
894
  throw new SegmindError("Missing API key: pass { apiKey } or set the SEGMIND_API_KEY environment variable.");
803
895
  }
804
896
  const fetchImpl = options.fetch ?? globalThis.fetch?.bind(globalThis);
@@ -807,11 +899,17 @@ var Segmind = class {
807
899
  this.spotURL = trimSlash(options.spotURL ?? DEFAULT_SPOT_URL);
808
900
  this.consoleURL = trimSlash(options.consoleURL ?? DEFAULT_CONSOLE_URL);
809
901
  this.assetsURL = trimSlash(options.assetsURL ?? DEFAULT_ASSETS_URL);
810
- const headers = { "X-Initiator": "SDK-JS", ...options.defaultHeaders };
902
+ const headers = {
903
+ "X-Initiator": "SDK-JS",
904
+ ...initiatorHeaders(options),
905
+ ...options.defaultHeaders
906
+ };
811
907
  const node = nodeVersion();
812
908
  if (runtime === "node" && node) headers["User-Agent"] = `segmind-js/${VERSION} node/${node}`;
813
909
  this.http = new HttpClient({
814
910
  apiKey,
911
+ tokenProvider: options.tokenProvider,
912
+ onUnauthorized: options.onUnauthorized,
815
913
  fetch: fetchImpl,
816
914
  timeout: options.timeout ?? 6e5,
817
915
  maxRetries: options.maxRetries ?? 2,
@@ -829,8 +927,8 @@ var Segmind = class {
829
927
  * until it finishes. `params` go to the model unchanged.
830
928
  */
831
929
  async run(slug, params = {}, options = {}) {
832
- const job = await this.submit(slug, params, options);
833
- return job.wait(options);
930
+ const job2 = await this.submit(slug, params, options);
931
+ return job2.wait(options);
834
932
  }
835
933
  /**
836
934
  * One blocking `POST /v1/{slug}`. Returns the fetch `Response`: call
@@ -842,6 +940,7 @@ var Segmind = class {
842
940
  method: "POST",
843
941
  url: `${this.baseURL}/v1/${path(slug)}`,
844
942
  body: params,
943
+ headers: initiatorHeaders(options),
845
944
  signal: options.signal,
846
945
  timeout: options.timeout
847
946
  });
@@ -854,10 +953,27 @@ var Segmind = class {
854
953
  async submit(slug, params = {}, options = {}) {
855
954
  return this.submitJob(slug, params, options, (body) => body);
856
955
  }
956
+ /**
957
+ * A job submitted earlier, from its id alone, for picking one up after a
958
+ * reload or in another process. Makes no request. The result is kept for about
959
+ * an hour, and only for the user who submitted it: anything else reads as a
960
+ * `SegmindError` with status 404.
961
+ */
962
+ job(requestId) {
963
+ const clean = requestId.trim();
964
+ if (!clean) throw new SegmindError("A request id is required.");
965
+ const url = `${this.baseURL}/v2/requests/${encodeURIComponent(clean)}`;
966
+ return new Job(this.http, {
967
+ request_id: clean,
968
+ status: "UNKNOWN",
969
+ status_url: `${url}/status`,
970
+ response_url: url
971
+ });
972
+ }
857
973
  /** Chat with an LLM through the v2 queue. Returns a provider-neutral reply. */
858
974
  async chat(slug, params, options = {}) {
859
- const job = await this.submitChat(slug, params, options);
860
- return job.wait(options);
975
+ const job2 = await this.submitChat(slug, params, options);
976
+ return job2.wait(options);
861
977
  }
862
978
  /** Chat with one blocking `POST /v1/{slug}`. */
863
979
  async chatSync(slug, params, options = {}) {
@@ -880,7 +996,7 @@ var Segmind = class {
880
996
  method: "POST",
881
997
  url,
882
998
  body: params,
883
- headers: { "X-Request-ID": requestId },
999
+ headers: { "X-Request-ID": requestId, ...initiatorHeaders(options) },
884
1000
  signal: options.signal
885
1001
  });
886
1002
  } catch (err) {
@@ -916,21 +1032,62 @@ var Segmind = class {
916
1032
  }
917
1033
  }
918
1034
  };
1035
+ var MODELS_PAGE_LIMIT = 100;
919
1036
  var Models = class {
920
1037
  constructor(client2) {
921
1038
  this.client = client2;
922
1039
  }
923
1040
  client;
924
- /** Every model in the catalog, under the key `Inference Model Information List`. */
925
- async list(options = {}) {
1041
+ /** One page of the catalog. Pass `offset` from the previous page while `has_more` is true. */
1042
+ async list(params = {}, options = {}) {
926
1043
  return this.client.http.json({
927
1044
  method: "GET",
928
- url: `${this.client.spotURL}/inference-model-information/list`,
1045
+ url: `${this.client.baseURL}/models`,
1046
+ query: modelsQuery(params),
929
1047
  signal: options.signal,
930
1048
  retry: true
931
1049
  });
932
1050
  }
1051
+ /** Every model matching `params`, reading page after page. */
1052
+ async listAll(params = {}, options = {}) {
1053
+ const models2 = [];
1054
+ for (let offset = 0; ; ) {
1055
+ const page = await this.list({ ...params, limit: MODELS_PAGE_LIMIT, offset }, options);
1056
+ models2.push(...page.models);
1057
+ offset += page.models.length;
1058
+ if (!page.has_more || !page.models.length || offset >= page.total) return models2;
1059
+ }
1060
+ }
933
1061
  };
1062
+ function modelsQuery(p) {
1063
+ return {
1064
+ q: p.q,
1065
+ sort: p.sort,
1066
+ category: p.category,
1067
+ modality: p.modality,
1068
+ input: joinList(p.input),
1069
+ output: joinList(p.output),
1070
+ provider: p.provider,
1071
+ slugs: joinList(p.slugs),
1072
+ operations: joinList(p.operations),
1073
+ features: joinList(p.features),
1074
+ min_popularity: p.minPopularity,
1075
+ min_category_percentile: p.minCategoryPercentile,
1076
+ min_cost: p.minCost,
1077
+ max_cost: p.maxCost,
1078
+ max_latency: p.maxLatency,
1079
+ is_new: p.isNew,
1080
+ created_after: p.createdAfter,
1081
+ include_coming_soon: p.includeComingSoon,
1082
+ facets: p.facets,
1083
+ limit: p.limit,
1084
+ offset: p.offset
1085
+ };
1086
+ }
1087
+ function joinList(value) {
1088
+ if (value === void 0) return void 0;
1089
+ return Array.isArray(value) ? value.join(",") : value;
1090
+ }
934
1091
  var Accounts = class {
935
1092
  constructor(client2) {
936
1093
  this.client = client2;
@@ -945,6 +1102,16 @@ var Accounts = class {
945
1102
  retry: true
946
1103
  });
947
1104
  }
1105
+ /** The current credit balance. */
1106
+ async credits(options = {}) {
1107
+ const { "free-credits": freeCredits, ...rest } = await this.client.http.json({
1108
+ method: "GET",
1109
+ url: `${this.client.baseURL}/v1/get-user-credits`,
1110
+ signal: options.signal,
1111
+ retry: true
1112
+ });
1113
+ return { ...rest, credits: Number(rest.credits), freeCredits: Number(freeCredits) };
1114
+ }
948
1115
  };
949
1116
  function validateSubmit(body, status) {
950
1117
  if (!body.request_id || !body.status_url || !body.response_url) {
@@ -993,14 +1160,17 @@ function client() {
993
1160
  var run = (slug, params, options) => client().run(slug, params, options);
994
1161
  var runSync = (slug, params, options) => client().runSync(slug, params, options);
995
1162
  var submit = (slug, params, options) => client().submit(slug, params, options);
1163
+ var job = (requestId) => client().job(requestId);
996
1164
  var chat = (slug, params, options) => client().chat(slug, params, options);
997
1165
  var chatSync = (slug, params, options) => client().chatSync(slug, params, options);
998
1166
  var submitChat = (slug, params, options) => client().submitChat(slug, params, options);
999
1167
  var models = {
1000
- list: (options) => client().models.list(options)
1168
+ list: (params, options) => client().models.list(params, options),
1169
+ listAll: (params, options) => client().models.listAll(params, options)
1001
1170
  };
1002
1171
  var accounts = {
1003
- current: (options) => client().accounts.current(options)
1172
+ current: (options) => client().accounts.current(options),
1173
+ credits: (options) => client().accounts.credits(options)
1004
1174
  };
1005
1175
  var files = {
1006
1176
  upload: ((input, options) => client().files.upload(input, options))
@@ -1037,10 +1207,12 @@ export {
1037
1207
  Generations,
1038
1208
  InferenceFailed,
1039
1209
  InferenceTimeout,
1210
+ InsufficientCredits,
1040
1211
  Job,
1041
1212
  Models,
1042
1213
  PixelFlows,
1043
1214
  PixelflowJob,
1215
+ RateLimited,
1044
1216
  Segmind,
1045
1217
  SegmindError,
1046
1218
  VERSION,
@@ -1051,6 +1223,7 @@ export {
1051
1223
  files,
1052
1224
  generations,
1053
1225
  imageUrl,
1226
+ job,
1054
1227
  models,
1055
1228
  pixelflows,
1056
1229
  run,