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/README.md +50 -2
- package/dist/index.cjs +221 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +226 -80
- package/dist/index.d.ts +226 -80
- package/dist/index.js +221 -48
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/core/errors.ts
|
|
2
|
-
var SegmindError = class
|
|
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
|
|
21
|
-
|
|
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
|
-
|
|
204
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
612
|
-
return
|
|
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
|
|
756
|
+
if (FAILED.has(state.status)) throw requestFailure(this.requestId, state.raw, failureDetail(state.raw));
|
|
669
757
|
const elapsed = Date.now() - started;
|
|
670
|
-
|
|
671
|
-
|
|
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.
|
|
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
|
-
|
|
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 = {
|
|
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
|
|
833
|
-
return
|
|
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
|
|
860
|
-
return
|
|
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
|
-
/**
|
|
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.
|
|
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,
|