segmind 0.2.2 → 0.2.4
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 +13 -3
- package/dist/index.cjs +70 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -5
- package/dist/index.d.ts +31 -5
- package/dist/index.js +70 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -147,6 +147,12 @@ interface UploadOptions {
|
|
|
147
147
|
filename?: string;
|
|
148
148
|
/** The file's type, when neither the name nor the bytes tell. */
|
|
149
149
|
mimeType?: string;
|
|
150
|
+
/**
|
|
151
|
+
* Keep the file in your Segmind asset library and return a URL that does not
|
|
152
|
+
* expire, as the Python SDK's upload does. By default the file is a temporary
|
|
153
|
+
* model input, kept for at least two days.
|
|
154
|
+
*/
|
|
155
|
+
persist?: boolean;
|
|
150
156
|
signal?: AbortSignal;
|
|
151
157
|
}
|
|
152
158
|
interface UploadedFile {
|
|
@@ -154,11 +160,13 @@ interface UploadedFile {
|
|
|
154
160
|
url: string;
|
|
155
161
|
filename: string;
|
|
156
162
|
size: number;
|
|
163
|
+
/** True when the file is in your asset library and the URL does not expire. */
|
|
164
|
+
persistent: boolean;
|
|
157
165
|
}
|
|
158
166
|
/**
|
|
159
167
|
* Uploads files to pass as model inputs. Each file goes straight to storage on
|
|
160
168
|
* a presigned URL, so large videos never travel as base64 JSON. The URLs are
|
|
161
|
-
* public
|
|
169
|
+
* public. They are temporary unless you pass `persist: true`.
|
|
162
170
|
*/
|
|
163
171
|
declare class Files {
|
|
164
172
|
private readonly client;
|
|
@@ -168,6 +176,12 @@ declare class Files {
|
|
|
168
176
|
/** Uploads several files, in order. */
|
|
169
177
|
upload(files: FileInput[], options?: Omit<UploadOptions, 'filename'>): Promise<UploadedFile[]>;
|
|
170
178
|
private uploadOne;
|
|
179
|
+
/** A temporary model input on the inference API's input bucket. */
|
|
180
|
+
private stage;
|
|
181
|
+
/** A file in the caller's asset library: presign, PUT, then confirm to register it. */
|
|
182
|
+
private persist;
|
|
183
|
+
/** A PUT to the same key is idempotent, so it retries. `bare` keeps the API key off the storage host. */
|
|
184
|
+
private put;
|
|
171
185
|
}
|
|
172
186
|
|
|
173
187
|
/** One page of a paginated list. */
|
|
@@ -391,11 +405,20 @@ declare class Webhooks {
|
|
|
391
405
|
add(webhookUrl: string, eventTypes: WebhookEventType[], options?: {
|
|
392
406
|
signal?: AbortSignal;
|
|
393
407
|
}): Promise<Webhook>;
|
|
394
|
-
/**
|
|
395
|
-
|
|
408
|
+
/**
|
|
409
|
+
* Points an active registration at a new URL. The event types stay as
|
|
410
|
+
* registered: to change them, `delete` the registration and `add` a new one.
|
|
411
|
+
*
|
|
412
|
+
* @param _eventTypes Ignored. Kept so 0.2 calls still compile; the API never
|
|
413
|
+
* changed event types in place.
|
|
414
|
+
*/
|
|
415
|
+
update(webhookId: string, webhookUrl: string, _eventTypes?: WebhookEventType[], options?: {
|
|
396
416
|
signal?: AbortSignal;
|
|
397
417
|
}): Promise<Record<string, unknown>>;
|
|
398
|
-
/**
|
|
418
|
+
/**
|
|
419
|
+
* Deactivates a registration. Not retried: a second attempt after a lost
|
|
420
|
+
* response would report the registration as already deactivated.
|
|
421
|
+
*/
|
|
399
422
|
delete(webhookId: string, options?: {
|
|
400
423
|
signal?: AbortSignal;
|
|
401
424
|
}): Promise<Record<string, unknown>>;
|
|
@@ -418,6 +441,8 @@ interface ClientOptions {
|
|
|
418
441
|
spotURL?: string;
|
|
419
442
|
/** The account API. Default https://cloud.segmind.com/api. */
|
|
420
443
|
consoleURL?: string;
|
|
444
|
+
/** The asset library API, for persistent uploads. Default https://platform-api.segmind.com. */
|
|
445
|
+
assetsURL?: string;
|
|
421
446
|
/** Milliseconds per HTTP request. Default 600 000. */
|
|
422
447
|
timeout?: number;
|
|
423
448
|
/** Retries for requests that cannot bill twice. Default 2. */
|
|
@@ -445,6 +470,7 @@ declare class Segmind {
|
|
|
445
470
|
readonly baseURL: string;
|
|
446
471
|
readonly spotURL: string;
|
|
447
472
|
readonly consoleURL: string;
|
|
473
|
+
readonly assetsURL: string;
|
|
448
474
|
readonly models: Models;
|
|
449
475
|
readonly accounts: Accounts;
|
|
450
476
|
/** Upload files to pass as model inputs. */
|
|
@@ -581,7 +607,7 @@ declare class InferenceTimeout extends SegmindError {
|
|
|
581
607
|
constructor(requestId: string, elapsedMs: number);
|
|
582
608
|
}
|
|
583
609
|
|
|
584
|
-
declare const VERSION = "0.2.
|
|
610
|
+
declare const VERSION = "0.2.4";
|
|
585
611
|
|
|
586
612
|
/** `new Segmind().run(...)` with the key from `SEGMIND_API_KEY`. */
|
|
587
613
|
declare const run: (slug: string, params?: Params, options?: RunOptions) => Promise<RunResult>;
|
package/dist/index.js
CHANGED
|
@@ -423,12 +423,16 @@ var Files = class {
|
|
|
423
423
|
}
|
|
424
424
|
async uploadOne(input, options) {
|
|
425
425
|
const file = await readFileInput(input, { ...options, caller: "files.upload" });
|
|
426
|
-
const
|
|
427
|
-
|
|
426
|
+
const url = options.persist ? await this.persist(file, options.signal) : await this.stage(file, options.signal);
|
|
427
|
+
return { url, filename: file.filename, size: file.bytes.byteLength, persistent: options.persist === true };
|
|
428
|
+
}
|
|
429
|
+
/** A temporary model input on the inference API's input bucket. */
|
|
430
|
+
async stage(file, signal) {
|
|
431
|
+
const ticket = await this.client.http.json({
|
|
428
432
|
method: "POST",
|
|
429
433
|
url: `${this.client.spotURL}/inference-request/input-presign`,
|
|
430
434
|
body: { filename: file.filename, size: file.bytes.byteLength },
|
|
431
|
-
signal
|
|
435
|
+
signal,
|
|
432
436
|
retry: true
|
|
433
437
|
});
|
|
434
438
|
if (!ticket.upload_url || !ticket.url) {
|
|
@@ -437,16 +441,41 @@ var Files = class {
|
|
|
437
441
|
const headers = { ...ticket.required_headers };
|
|
438
442
|
delete headers["Content-Length"];
|
|
439
443
|
delete headers["content-length"];
|
|
440
|
-
await
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
444
|
+
await this.put(ticket.upload_url, file, headers, signal);
|
|
445
|
+
return ticket.url;
|
|
446
|
+
}
|
|
447
|
+
/** A file in the caller's asset library: presign, PUT, then confirm to register it. */
|
|
448
|
+
async persist(file, signal) {
|
|
449
|
+
const contentType = file.mimeType;
|
|
450
|
+
if (!contentType) {
|
|
451
|
+
throw new SegmindError(`files.upload: cannot tell the type of ${file.filename}; pass { mimeType } to persist it`);
|
|
452
|
+
}
|
|
453
|
+
const { http, assetsURL } = this.client;
|
|
454
|
+
const ticket = await http.json({
|
|
455
|
+
method: "POST",
|
|
456
|
+
url: `${assetsURL}/upload-asset/presign`,
|
|
457
|
+
body: { filename: file.filename, contentType, size: file.bytes.byteLength },
|
|
458
|
+
signal,
|
|
447
459
|
retry: true
|
|
448
460
|
});
|
|
449
|
-
|
|
461
|
+
if (!ticket.presignedUrl || !ticket.s3Key || !ticket.publicUrl) {
|
|
462
|
+
throw new SegmindError("files.upload: the asset presign response had no presignedUrl, s3Key or publicUrl", {
|
|
463
|
+
body: ticket
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
await this.put(ticket.presignedUrl, file, { "Content-Type": contentType }, signal);
|
|
467
|
+
const confirmed = await http.json({
|
|
468
|
+
method: "POST",
|
|
469
|
+
url: `${assetsURL}/upload-asset/confirm`,
|
|
470
|
+
body: { s3Key: ticket.s3Key, publicUrl: ticket.publicUrl, contentType, filename: file.filename },
|
|
471
|
+
signal,
|
|
472
|
+
retry: true
|
|
473
|
+
});
|
|
474
|
+
return confirmed.asset?.url ?? ticket.publicUrl;
|
|
475
|
+
}
|
|
476
|
+
/** A PUT to the same key is idempotent, so it retries. `bare` keeps the API key off the storage host. */
|
|
477
|
+
async put(url, file, headers, signal) {
|
|
478
|
+
await this.client.http.request({ method: "PUT", url, rawBody: file.bytes, headers, bare: true, signal, retry: true });
|
|
450
479
|
}
|
|
451
480
|
};
|
|
452
481
|
|
|
@@ -684,7 +713,7 @@ function failureDetail(body) {
|
|
|
684
713
|
}
|
|
685
714
|
|
|
686
715
|
// src/version.ts
|
|
687
|
-
var VERSION = "0.2.
|
|
716
|
+
var VERSION = "0.2.4";
|
|
688
717
|
|
|
689
718
|
// src/webhooks.ts
|
|
690
719
|
var Webhooks = class {
|
|
@@ -703,16 +732,26 @@ var Webhooks = class {
|
|
|
703
732
|
signal: options.signal
|
|
704
733
|
});
|
|
705
734
|
}
|
|
706
|
-
/**
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
735
|
+
/**
|
|
736
|
+
* Points an active registration at a new URL. The event types stay as
|
|
737
|
+
* registered: to change them, `delete` the registration and `add` a new one.
|
|
738
|
+
*
|
|
739
|
+
* @param _eventTypes Ignored. Kept so 0.2 calls still compile; the API never
|
|
740
|
+
* changed event types in place.
|
|
741
|
+
*/
|
|
742
|
+
async update(webhookId, webhookUrl, _eventTypes, options = {}) {
|
|
743
|
+
return this.call("PUT", "/update", {
|
|
744
|
+
body: { webhook_id: webhookId, webhook_url: webhookUrl },
|
|
745
|
+
signal: options.signal,
|
|
746
|
+
retry: true
|
|
711
747
|
});
|
|
712
748
|
}
|
|
713
|
-
/**
|
|
749
|
+
/**
|
|
750
|
+
* Deactivates a registration. Not retried: a second attempt after a lost
|
|
751
|
+
* response would report the registration as already deactivated.
|
|
752
|
+
*/
|
|
714
753
|
async delete(webhookId, options = {}) {
|
|
715
|
-
return this.call("
|
|
754
|
+
return this.call("DELETE", "/inactive", { query: { webhook_id: webhookId }, signal: options.signal });
|
|
716
755
|
}
|
|
717
756
|
/** Delivery history for one registration. */
|
|
718
757
|
async logs(webhookId, options = {}) {
|
|
@@ -733,10 +772,12 @@ function requireTypes(eventTypes) {
|
|
|
733
772
|
var DEFAULT_BASE_URL = "https://api.segmind.com";
|
|
734
773
|
var DEFAULT_SPOT_URL = "https://api.spotprod.segmind.com";
|
|
735
774
|
var DEFAULT_CONSOLE_URL = "https://cloud.segmind.com/api";
|
|
775
|
+
var DEFAULT_ASSETS_URL = "https://platform-api.segmind.com";
|
|
736
776
|
var Segmind = class {
|
|
737
777
|
baseURL;
|
|
738
778
|
spotURL;
|
|
739
779
|
consoleURL;
|
|
780
|
+
assetsURL;
|
|
740
781
|
models;
|
|
741
782
|
accounts;
|
|
742
783
|
/** Upload files to pass as model inputs. */
|
|
@@ -765,6 +806,7 @@ var Segmind = class {
|
|
|
765
806
|
this.baseURL = trimBase(options.baseURL ?? readEnv("SEGMIND_BASE_URL") ?? DEFAULT_BASE_URL);
|
|
766
807
|
this.spotURL = trimSlash(options.spotURL ?? DEFAULT_SPOT_URL);
|
|
767
808
|
this.consoleURL = trimSlash(options.consoleURL ?? DEFAULT_CONSOLE_URL);
|
|
809
|
+
this.assetsURL = trimSlash(options.assetsURL ?? DEFAULT_ASSETS_URL);
|
|
768
810
|
const headers = { "X-Initiator": "SDK-JS", ...options.defaultHeaders };
|
|
769
811
|
const node = nodeVersion();
|
|
770
812
|
if (runtime === "node" && node) headers["User-Agent"] = `segmind-js/${VERSION} node/${node}`;
|
|
@@ -857,7 +899,7 @@ var Segmind = class {
|
|
|
857
899
|
body
|
|
858
900
|
});
|
|
859
901
|
}
|
|
860
|
-
return new Job(this.http, validateSubmit(body, response.status), transform);
|
|
902
|
+
return new Job(this.http, onBase(validateSubmit(body, response.status), this.baseURL), transform);
|
|
861
903
|
}
|
|
862
904
|
if (canRetry && response.status === 503) {
|
|
863
905
|
await response.body?.cancel().catch(() => void 0);
|
|
@@ -918,6 +960,14 @@ function path(slug) {
|
|
|
918
960
|
if (!clean) throw new SegmindError("A model slug is required.");
|
|
919
961
|
return clean;
|
|
920
962
|
}
|
|
963
|
+
function onBase(body, baseURL) {
|
|
964
|
+
const origin = new URL(baseURL).origin;
|
|
965
|
+
const pin = (url) => {
|
|
966
|
+
const target = new URL(url, `${baseURL}/`);
|
|
967
|
+
return target.origin === origin ? target.href : `${baseURL}${target.pathname}${target.search}`;
|
|
968
|
+
};
|
|
969
|
+
return { ...body, status_url: pin(body.status_url), response_url: pin(body.response_url) };
|
|
970
|
+
}
|
|
921
971
|
function trimSlash(url) {
|
|
922
972
|
return url.replace(/\/+$/, "");
|
|
923
973
|
}
|