segmind 0.2.3 → 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.3";
805
+ var VERSION = "0.3.0";
717
806
 
718
807
  // src/webhooks.ts
719
808
  var Webhooks = class {
@@ -732,16 +821,26 @@ var Webhooks = class {
732
821
  signal: options.signal
733
822
  });
734
823
  }
735
- /** Changes a registration's URL and event types. */
736
- async update(webhookId, webhookUrl, eventTypes, options = {}) {
737
- return this.call("POST", "/update", {
738
- body: { webhook_id: webhookId, webhook_url: webhookUrl, event: { types: requireTypes(eventTypes) } },
739
- signal: options.signal
824
+ /**
825
+ * Points an active registration at a new URL. The event types stay as
826
+ * registered: to change them, `delete` the registration and `add` a new one.
827
+ *
828
+ * @param _eventTypes Ignored. Kept so 0.2 calls still compile; the API never
829
+ * changed event types in place.
830
+ */
831
+ async update(webhookId, webhookUrl, _eventTypes, options = {}) {
832
+ return this.call("PUT", "/update", {
833
+ body: { webhook_id: webhookId, webhook_url: webhookUrl },
834
+ signal: options.signal,
835
+ retry: true
740
836
  });
741
837
  }
742
- /** Deactivates a registration. */
838
+ /**
839
+ * Deactivates a registration. Not retried: a second attempt after a lost
840
+ * response would report the registration as already deactivated.
841
+ */
743
842
  async delete(webhookId, options = {}) {
744
- return this.call("GET", "/inactive", { query: { webhook_id: webhookId }, signal: options.signal, retry: true });
843
+ return this.call("DELETE", "/inactive", { query: { webhook_id: webhookId }, signal: options.signal });
745
844
  }
746
845
  /** Delivery history for one registration. */
747
846
  async logs(webhookId, options = {}) {
@@ -781,14 +880,17 @@ var Segmind = class {
781
880
  /** @internal */
782
881
  http;
783
882
  constructor(options = {}) {
784
- 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"));
785
887
  const runtime = detectRuntime();
786
888
  if (apiKey && (runtime === "browser" || runtime === "react-native") && !options.dangerouslyAllowBrowser) {
787
889
  throw new SegmindError(
788
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."
789
891
  );
790
892
  }
791
- if (!apiKey) {
893
+ if (!apiKey && !options.tokenProvider) {
792
894
  throw new SegmindError("Missing API key: pass { apiKey } or set the SEGMIND_API_KEY environment variable.");
793
895
  }
794
896
  const fetchImpl = options.fetch ?? globalThis.fetch?.bind(globalThis);
@@ -797,11 +899,17 @@ var Segmind = class {
797
899
  this.spotURL = trimSlash(options.spotURL ?? DEFAULT_SPOT_URL);
798
900
  this.consoleURL = trimSlash(options.consoleURL ?? DEFAULT_CONSOLE_URL);
799
901
  this.assetsURL = trimSlash(options.assetsURL ?? DEFAULT_ASSETS_URL);
800
- const headers = { "X-Initiator": "SDK-JS", ...options.defaultHeaders };
902
+ const headers = {
903
+ "X-Initiator": "SDK-JS",
904
+ ...initiatorHeaders(options),
905
+ ...options.defaultHeaders
906
+ };
801
907
  const node = nodeVersion();
802
908
  if (runtime === "node" && node) headers["User-Agent"] = `segmind-js/${VERSION} node/${node}`;
803
909
  this.http = new HttpClient({
804
910
  apiKey,
911
+ tokenProvider: options.tokenProvider,
912
+ onUnauthorized: options.onUnauthorized,
805
913
  fetch: fetchImpl,
806
914
  timeout: options.timeout ?? 6e5,
807
915
  maxRetries: options.maxRetries ?? 2,
@@ -819,8 +927,8 @@ var Segmind = class {
819
927
  * until it finishes. `params` go to the model unchanged.
820
928
  */
821
929
  async run(slug, params = {}, options = {}) {
822
- const job = await this.submit(slug, params, options);
823
- return job.wait(options);
930
+ const job2 = await this.submit(slug, params, options);
931
+ return job2.wait(options);
824
932
  }
825
933
  /**
826
934
  * One blocking `POST /v1/{slug}`. Returns the fetch `Response`: call
@@ -832,6 +940,7 @@ var Segmind = class {
832
940
  method: "POST",
833
941
  url: `${this.baseURL}/v1/${path(slug)}`,
834
942
  body: params,
943
+ headers: initiatorHeaders(options),
835
944
  signal: options.signal,
836
945
  timeout: options.timeout
837
946
  });
@@ -844,10 +953,27 @@ var Segmind = class {
844
953
  async submit(slug, params = {}, options = {}) {
845
954
  return this.submitJob(slug, params, options, (body) => body);
846
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
+ }
847
973
  /** Chat with an LLM through the v2 queue. Returns a provider-neutral reply. */
848
974
  async chat(slug, params, options = {}) {
849
- const job = await this.submitChat(slug, params, options);
850
- return job.wait(options);
975
+ const job2 = await this.submitChat(slug, params, options);
976
+ return job2.wait(options);
851
977
  }
852
978
  /** Chat with one blocking `POST /v1/{slug}`. */
853
979
  async chatSync(slug, params, options = {}) {
@@ -870,7 +996,7 @@ var Segmind = class {
870
996
  method: "POST",
871
997
  url,
872
998
  body: params,
873
- headers: { "X-Request-ID": requestId },
999
+ headers: { "X-Request-ID": requestId, ...initiatorHeaders(options) },
874
1000
  signal: options.signal
875
1001
  });
876
1002
  } catch (err) {
@@ -889,7 +1015,7 @@ var Segmind = class {
889
1015
  body
890
1016
  });
891
1017
  }
892
- return new Job(this.http, validateSubmit(body, response.status), transform);
1018
+ return new Job(this.http, onBase(validateSubmit(body, response.status), this.baseURL), transform);
893
1019
  }
894
1020
  if (canRetry && response.status === 503) {
895
1021
  await response.body?.cancel().catch(() => void 0);
@@ -906,21 +1032,62 @@ var Segmind = class {
906
1032
  }
907
1033
  }
908
1034
  };
1035
+ var MODELS_PAGE_LIMIT = 100;
909
1036
  var Models = class {
910
1037
  constructor(client2) {
911
1038
  this.client = client2;
912
1039
  }
913
1040
  client;
914
- /** Every model in the catalog, under the key `Inference Model Information List`. */
915
- 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 = {}) {
916
1043
  return this.client.http.json({
917
1044
  method: "GET",
918
- url: `${this.client.spotURL}/inference-model-information/list`,
1045
+ url: `${this.client.baseURL}/models`,
1046
+ query: modelsQuery(params),
919
1047
  signal: options.signal,
920
1048
  retry: true
921
1049
  });
922
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
+ }
923
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
+ }
924
1091
  var Accounts = class {
925
1092
  constructor(client2) {
926
1093
  this.client = client2;
@@ -935,6 +1102,16 @@ var Accounts = class {
935
1102
  retry: true
936
1103
  });
937
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
+ }
938
1115
  };
939
1116
  function validateSubmit(body, status) {
940
1117
  if (!body.request_id || !body.status_url || !body.response_url) {
@@ -950,6 +1127,14 @@ function path(slug) {
950
1127
  if (!clean) throw new SegmindError("A model slug is required.");
951
1128
  return clean;
952
1129
  }
1130
+ function onBase(body, baseURL) {
1131
+ const origin = new URL(baseURL).origin;
1132
+ const pin = (url) => {
1133
+ const target = new URL(url, `${baseURL}/`);
1134
+ return target.origin === origin ? target.href : `${baseURL}${target.pathname}${target.search}`;
1135
+ };
1136
+ return { ...body, status_url: pin(body.status_url), response_url: pin(body.response_url) };
1137
+ }
953
1138
  function trimSlash(url) {
954
1139
  return url.replace(/\/+$/, "");
955
1140
  }
@@ -975,14 +1160,17 @@ function client() {
975
1160
  var run = (slug, params, options) => client().run(slug, params, options);
976
1161
  var runSync = (slug, params, options) => client().runSync(slug, params, options);
977
1162
  var submit = (slug, params, options) => client().submit(slug, params, options);
1163
+ var job = (requestId) => client().job(requestId);
978
1164
  var chat = (slug, params, options) => client().chat(slug, params, options);
979
1165
  var chatSync = (slug, params, options) => client().chatSync(slug, params, options);
980
1166
  var submitChat = (slug, params, options) => client().submitChat(slug, params, options);
981
1167
  var models = {
982
- list: (options) => client().models.list(options)
1168
+ list: (params, options) => client().models.list(params, options),
1169
+ listAll: (params, options) => client().models.listAll(params, options)
983
1170
  };
984
1171
  var accounts = {
985
- current: (options) => client().accounts.current(options)
1172
+ current: (options) => client().accounts.current(options),
1173
+ credits: (options) => client().accounts.credits(options)
986
1174
  };
987
1175
  var files = {
988
1176
  upload: ((input, options) => client().files.upload(input, options))
@@ -1019,10 +1207,12 @@ export {
1019
1207
  Generations,
1020
1208
  InferenceFailed,
1021
1209
  InferenceTimeout,
1210
+ InsufficientCredits,
1022
1211
  Job,
1023
1212
  Models,
1024
1213
  PixelFlows,
1025
1214
  PixelflowJob,
1215
+ RateLimited,
1026
1216
  Segmind,
1027
1217
  SegmindError,
1028
1218
  VERSION,
@@ -1033,6 +1223,7 @@ export {
1033
1223
  files,
1034
1224
  generations,
1035
1225
  imageUrl,
1226
+ job,
1036
1227
  models,
1037
1228
  pixelflows,
1038
1229
  run,