@sogni-ai/sogni-client 4.0.0-alpha.5 → 4.0.0-alpha.51
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/CHANGELOG.md +357 -0
- package/README.md +295 -58
- package/dist/Account/index.d.ts +18 -16
- package/dist/Account/index.js +42 -21
- package/dist/Account/index.js.map +1 -1
- package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/ChannelCoordinator.d.ts +66 -0
- package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/ChannelCoordinator.js +332 -0
- package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/ChannelCoordinator.js.map +1 -0
- package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.d.ts +28 -0
- package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js +203 -0
- package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js.map +1 -0
- package/dist/ApiClient/WebSocketClient/events.d.ts +12 -0
- package/dist/ApiClient/WebSocketClient/index.d.ts +2 -2
- package/dist/ApiClient/WebSocketClient/index.js +13 -3
- package/dist/ApiClient/WebSocketClient/index.js.map +1 -1
- package/dist/ApiClient/WebSocketClient/types.d.ts +13 -0
- package/dist/ApiClient/index.d.ts +4 -4
- package/dist/ApiClient/index.js +23 -4
- package/dist/ApiClient/index.js.map +1 -1
- package/dist/Projects/Job.d.ts +44 -4
- package/dist/Projects/Job.js +83 -16
- package/dist/Projects/Job.js.map +1 -1
- package/dist/Projects/Project.d.ts +18 -0
- package/dist/Projects/Project.js +38 -10
- package/dist/Projects/Project.js.map +1 -1
- package/dist/Projects/createJobRequestMessage.d.ts +2 -1
- package/dist/Projects/createJobRequestMessage.js +173 -14
- package/dist/Projects/createJobRequestMessage.js.map +1 -1
- package/dist/Projects/index.d.ts +114 -11
- package/dist/Projects/index.js +504 -47
- package/dist/Projects/index.js.map +1 -1
- package/dist/Projects/types/ComfySamplerParams.d.ts +0 -0
- package/dist/Projects/types/ComfySamplerParams.js +2 -0
- package/dist/Projects/types/ComfySamplerParams.js.map +1 -0
- package/dist/Projects/types/EstimationResponse.d.ts +2 -0
- package/dist/Projects/types/ModelOptions.d.ts +31 -0
- package/dist/Projects/types/ModelOptions.js +56 -0
- package/dist/Projects/types/ModelOptions.js.map +1 -0
- package/dist/Projects/types/ModelTiersRaw.d.ts +67 -0
- package/dist/Projects/types/ModelTiersRaw.js +15 -0
- package/dist/Projects/types/ModelTiersRaw.js.map +1 -0
- package/dist/Projects/types/events.d.ts +5 -1
- package/dist/Projects/types/index.d.ts +219 -42
- package/dist/Projects/types/index.js +8 -0
- package/dist/Projects/types/index.js.map +1 -1
- package/dist/Projects/utils/index.d.ts +20 -0
- package/dist/Projects/utils/index.js +91 -0
- package/dist/Projects/utils/index.js.map +1 -0
- package/dist/Projects/utils/samplers.d.ts +6 -0
- package/dist/Projects/utils/samplers.js +39 -0
- package/dist/Projects/utils/samplers.js.map +1 -0
- package/dist/Projects/utils/scheduler.d.ts +6 -0
- package/dist/Projects/utils/scheduler.js +30 -0
- package/dist/Projects/utils/scheduler.js.map +1 -0
- package/dist/index.d.ts +11 -3
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/AuthManager/TokenAuthManager.js +0 -2
- package/dist/lib/AuthManager/TokenAuthManager.js.map +1 -1
- package/dist/lib/DataEntity.js +4 -2
- package/dist/lib/DataEntity.js.map +1 -1
- package/dist/lib/RestClient.js +15 -2
- package/dist/lib/RestClient.js.map +1 -1
- package/dist/lib/{utils.js → utils/index.js} +1 -1
- package/dist/lib/utils/index.js.map +1 -0
- package/dist/lib/validation.d.ts +31 -2
- package/dist/lib/validation.js +80 -13
- package/dist/lib/validation.js.map +1 -1
- package/package.json +4 -4
- package/src/Account/index.ts +39 -20
- package/src/ApiClient/WebSocketClient/BrowserWebSocketClient/ChannelCoordinator.ts +426 -0
- package/src/ApiClient/WebSocketClient/BrowserWebSocketClient/index.ts +237 -0
- package/src/ApiClient/WebSocketClient/events.ts +14 -0
- package/src/ApiClient/WebSocketClient/index.ts +15 -5
- package/src/ApiClient/WebSocketClient/types.ts +16 -0
- package/src/ApiClient/index.ts +30 -8
- package/src/Projects/Job.ts +97 -16
- package/src/Projects/Project.ts +46 -13
- package/src/Projects/createJobRequestMessage.ts +239 -34
- package/src/Projects/index.ts +533 -51
- package/src/Projects/types/ComfySamplerParams.ts +0 -0
- package/src/Projects/types/EstimationResponse.ts +2 -0
- package/src/Projects/types/ModelOptions.ts +92 -0
- package/src/Projects/types/ModelTiersRaw.ts +86 -0
- package/src/Projects/types/events.ts +6 -0
- package/src/Projects/types/index.ts +253 -45
- package/src/Projects/utils/index.ts +90 -0
- package/src/Projects/utils/samplers.ts +36 -0
- package/src/Projects/utils/scheduler.ts +27 -0
- package/src/index.ts +36 -9
- package/src/lib/AuthManager/TokenAuthManager.ts +0 -2
- package/src/lib/DataEntity.ts +4 -2
- package/src/lib/RestClient.ts +16 -2
- package/src/lib/validation.ts +90 -17
- package/dist/Projects/types/SamplerParams.d.ts +0 -15
- package/dist/Projects/types/SamplerParams.js +0 -21
- package/dist/Projects/types/SamplerParams.js.map +0 -1
- package/dist/Projects/types/SchedulerParams.d.ts +0 -13
- package/dist/Projects/types/SchedulerParams.js +0 -19
- package/dist/Projects/types/SchedulerParams.js.map +0 -1
- package/dist/Projects/utils.d.ts +0 -2
- package/dist/Projects/utils.js +0 -14
- package/dist/Projects/utils.js.map +0 -1
- package/dist/lib/utils.js.map +0 -1
- package/src/Projects/types/SamplerParams.ts +0 -19
- package/src/Projects/types/SchedulerParams.ts +0 -17
- package/src/Projects/utils.ts +0 -12
- /package/dist/lib/{utils.d.ts → utils/index.d.ts} +0 -0
- /package/src/lib/{utils.ts → utils/index.ts} +0 -0
package/dist/Projects/index.js
CHANGED
|
@@ -20,9 +20,39 @@ const getUUID_1 = __importDefault(require("../lib/getUUID"));
|
|
|
20
20
|
const Cache_1 = __importDefault(require("../lib/Cache"));
|
|
21
21
|
const Job_1 = require("./Job");
|
|
22
22
|
const utils_1 = require("./utils");
|
|
23
|
+
const validation_1 = require("../lib/validation");
|
|
24
|
+
const ModelTiersRaw_1 = require("./types/ModelTiersRaw");
|
|
25
|
+
const ModelOptions_1 = require("./types/ModelOptions");
|
|
23
26
|
const sizePresetCache = new Cache_1.default(10 * 60 * 1000);
|
|
24
27
|
const GARBAGE_COLLECT_TIMEOUT = 30000;
|
|
25
28
|
const MODELS_REFRESH_INTERVAL = 1000 * 60 * 60 * 24; // 24 hours
|
|
29
|
+
/**
|
|
30
|
+
* Detect content type from a file object.
|
|
31
|
+
* For File objects in browser, uses the type property.
|
|
32
|
+
* Returns undefined if content type cannot be detected.
|
|
33
|
+
*/
|
|
34
|
+
function getFileContentType(file) {
|
|
35
|
+
if (file instanceof Blob && 'type' in file && file.type) {
|
|
36
|
+
return file.type;
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Convert file to a format compatible with fetch body.
|
|
42
|
+
* Converts Node.js Buffer to Blob for cross-platform compatibility.
|
|
43
|
+
*/
|
|
44
|
+
function toFetchBody(file) {
|
|
45
|
+
// Node.js Buffer is not supported in browsers, so we can skip this conversion
|
|
46
|
+
if (typeof Buffer === 'undefined') {
|
|
47
|
+
return file;
|
|
48
|
+
}
|
|
49
|
+
if (Buffer.isBuffer(file)) {
|
|
50
|
+
// Copy Buffer data to a new ArrayBuffer to ensure type compatibility
|
|
51
|
+
const arrayBuffer = file.buffer.slice(file.byteOffset, file.byteOffset + file.byteLength);
|
|
52
|
+
return new Blob([arrayBuffer]);
|
|
53
|
+
}
|
|
54
|
+
return file;
|
|
55
|
+
}
|
|
26
56
|
function mapErrorCodes(code) {
|
|
27
57
|
switch (code) {
|
|
28
58
|
case 'serverRestarting':
|
|
@@ -43,6 +73,20 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
43
73
|
get availableModels() {
|
|
44
74
|
return this._availableModels;
|
|
45
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Check if a model produces video output using the cached models list.
|
|
78
|
+
* Uses the `media` property from the models API when available,
|
|
79
|
+
* falls back to model ID prefix check if models aren't loaded yet.
|
|
80
|
+
*/
|
|
81
|
+
isVideoModelId(modelId) {
|
|
82
|
+
var _a;
|
|
83
|
+
const model = (_a = this._supportedModels.data) === null || _a === void 0 ? void 0 : _a.find((m) => m.id === modelId);
|
|
84
|
+
if (model) {
|
|
85
|
+
return model.media === 'video';
|
|
86
|
+
}
|
|
87
|
+
// Fallback to prefix check if models not loaded
|
|
88
|
+
return (0, utils_1.isVideoModel)(modelId);
|
|
89
|
+
}
|
|
46
90
|
constructor(config) {
|
|
47
91
|
super(config);
|
|
48
92
|
this._availableModels = [];
|
|
@@ -51,19 +95,38 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
51
95
|
data: null,
|
|
52
96
|
updatedAt: new Date(0)
|
|
53
97
|
};
|
|
98
|
+
this._modelTiers = {
|
|
99
|
+
data: {},
|
|
100
|
+
updatedAt: new Date(0)
|
|
101
|
+
};
|
|
54
102
|
// Listen to server events and emit them as project and job events
|
|
55
103
|
this.client.socket.on('changeNetwork', this.handleChangeNetwork.bind(this));
|
|
56
104
|
this.client.socket.on('swarmModels', this.handleSwarmModels.bind(this));
|
|
57
105
|
this.client.socket.on('jobState', this.handleJobState.bind(this));
|
|
58
106
|
this.client.socket.on('jobProgress', this.handleJobProgress.bind(this));
|
|
107
|
+
this.client.socket.on('jobETA', this.handleJobETA.bind(this));
|
|
59
108
|
this.client.socket.on('jobError', this.handleJobError.bind(this));
|
|
60
|
-
this.client.socket.on('jobResult',
|
|
109
|
+
this.client.socket.on('jobResult', (data) => {
|
|
110
|
+
this.handleJobResult(data).catch((err) => {
|
|
111
|
+
this.client.logger.error('Error in handleJobResult:', err);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
61
114
|
// Listen to the server disconnect event
|
|
62
115
|
this.client.on('disconnected', this.handleServerDisconnected.bind(this));
|
|
63
116
|
// Listen to project and job events and update project and job instances
|
|
64
117
|
this.on('project', this.handleProjectEvent.bind(this));
|
|
65
118
|
this.on('job', this.handleJobEvent.bind(this));
|
|
66
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Retrieves a list of projects created and tracked by this SogniClient instance.
|
|
122
|
+
*
|
|
123
|
+
* Note: When a project is finished, it will be removed from this list after 30 seconds
|
|
124
|
+
*
|
|
125
|
+
* @return {Array} A copy of the array containing the tracked projects.
|
|
126
|
+
*/
|
|
127
|
+
get trackedProjects() {
|
|
128
|
+
return this.projects.slice(0);
|
|
129
|
+
}
|
|
67
130
|
handleChangeNetwork() {
|
|
68
131
|
this._availableModels = [];
|
|
69
132
|
this.emit('availableModels', this._availableModels);
|
|
@@ -82,11 +145,12 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
82
145
|
return acc;
|
|
83
146
|
}, {});
|
|
84
147
|
this._availableModels = Object.entries(data).map(([id, workerCount]) => {
|
|
85
|
-
var _a;
|
|
148
|
+
var _a, _b;
|
|
86
149
|
return ({
|
|
87
150
|
id,
|
|
88
151
|
name: ((_a = modelIndex[id]) === null || _a === void 0 ? void 0 : _a.name) || id.replace(/-/g, ' '),
|
|
89
|
-
workerCount
|
|
152
|
+
workerCount,
|
|
153
|
+
media: ((_b = modelIndex[id]) === null || _b === void 0 ? void 0 : _b.media) || 'image'
|
|
90
154
|
});
|
|
91
155
|
});
|
|
92
156
|
this.emit('availableModels', this._availableModels);
|
|
@@ -154,20 +218,61 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
154
218
|
}
|
|
155
219
|
});
|
|
156
220
|
}
|
|
221
|
+
handleJobETA(data) {
|
|
222
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
223
|
+
this.emit('job', {
|
|
224
|
+
type: 'jobETA',
|
|
225
|
+
projectId: data.jobID,
|
|
226
|
+
jobId: data.imgID || '',
|
|
227
|
+
etaSeconds: data.etaSeconds
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
}
|
|
157
231
|
handleJobResult(data) {
|
|
158
232
|
return __awaiter(this, void 0, void 0, function* () {
|
|
159
233
|
const project = this.projects.find((p) => p.id === data.jobID);
|
|
160
234
|
const passNSFWCheck = !data.triggeredNSFWFilter || !project || project.params.disableNSFWFilter;
|
|
161
|
-
let downloadUrl = null;
|
|
162
|
-
// If
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
235
|
+
let downloadUrl = data.resultUrl || null; // Use resultUrl from event if provided
|
|
236
|
+
// If no resultUrl provided and NSFW check passes, generate download URL
|
|
237
|
+
if (!downloadUrl && passNSFWCheck && !data.userCanceled) {
|
|
238
|
+
// Use media endpoint for video models, image endpoint for image models
|
|
239
|
+
const isVideo = project && this.isVideoModelId(project.params.modelId);
|
|
240
|
+
try {
|
|
241
|
+
if (isVideo) {
|
|
242
|
+
downloadUrl = yield this.mediaDownloadUrl({
|
|
243
|
+
jobId: data.jobID,
|
|
244
|
+
id: data.imgID,
|
|
245
|
+
type: 'complete'
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
downloadUrl = yield this.downloadUrl({
|
|
250
|
+
jobId: data.jobID,
|
|
251
|
+
imageId: data.imgID,
|
|
252
|
+
type: 'complete'
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
this.client.logger.error('Failed to generate download URL for job result');
|
|
258
|
+
this.client.logger.error(error);
|
|
259
|
+
}
|
|
170
260
|
}
|
|
261
|
+
// Update the job directly with the result URL to prevent duplicate API calls
|
|
262
|
+
if (project) {
|
|
263
|
+
const job = project.job(data.imgID);
|
|
264
|
+
if (job) {
|
|
265
|
+
job._update({
|
|
266
|
+
status: data.userCanceled ? 'canceled' : 'completed',
|
|
267
|
+
step: data.performedStepCount,
|
|
268
|
+
seed: Number(data.lastSeed),
|
|
269
|
+
resultUrl: downloadUrl,
|
|
270
|
+
isNSFW: data.triggeredNSFWFilter,
|
|
271
|
+
userCanceled: data.userCanceled
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// Emit job completion event with the generated download URL
|
|
171
276
|
this.emit('job', {
|
|
172
277
|
type: 'completed',
|
|
173
278
|
projectId: data.jobID,
|
|
@@ -238,7 +343,11 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
238
343
|
if (project.finished) {
|
|
239
344
|
// Sync project data with the server and remove it from the list after some time
|
|
240
345
|
project._syncToServer().catch((e) => {
|
|
241
|
-
|
|
346
|
+
// 404 errors are expected when project is still initializing
|
|
347
|
+
// Only log non-404 errors to avoid confusing users
|
|
348
|
+
if (e.status !== 404) {
|
|
349
|
+
this.client.logger.error(e);
|
|
350
|
+
}
|
|
242
351
|
});
|
|
243
352
|
setTimeout(() => {
|
|
244
353
|
this.projects = this.projects.filter((p) => !p.finished);
|
|
@@ -246,6 +355,7 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
246
355
|
}
|
|
247
356
|
}
|
|
248
357
|
handleJobEvent(event) {
|
|
358
|
+
var _a, _b, _c;
|
|
249
359
|
let project = this.projects.find((p) => p.id === event.projectId);
|
|
250
360
|
if (!project) {
|
|
251
361
|
return;
|
|
@@ -257,7 +367,7 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
257
367
|
projectId: event.projectId,
|
|
258
368
|
status: 'pending',
|
|
259
369
|
step: 0,
|
|
260
|
-
stepCount: project.params.steps
|
|
370
|
+
stepCount: (_a = project.params.steps) !== null && _a !== void 0 ? _a : 0
|
|
261
371
|
});
|
|
262
372
|
}
|
|
263
373
|
switch (event.type) {
|
|
@@ -284,7 +394,7 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
284
394
|
case 'progress':
|
|
285
395
|
job._update({
|
|
286
396
|
status: 'processing',
|
|
287
|
-
//
|
|
397
|
+
// Just in case event comes out of order
|
|
288
398
|
step: Math.max(event.step, job.step),
|
|
289
399
|
stepCount: event.stepCount
|
|
290
400
|
});
|
|
@@ -292,6 +402,23 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
292
402
|
project._update({ status: 'processing' });
|
|
293
403
|
}
|
|
294
404
|
break;
|
|
405
|
+
case 'jobETA': {
|
|
406
|
+
// ETA updates keep the project alive (refreshes lastUpdated) and store the ETA value.
|
|
407
|
+
// This is critical for long-running jobs like video generation that can take several
|
|
408
|
+
// minutes and may not send frequent progress updates.
|
|
409
|
+
// We always call _keepAlive() to ensure lastUpdated is refreshed, preventing premature timeouts.
|
|
410
|
+
project._keepAlive();
|
|
411
|
+
const newEta = new Date(Date.now() + event.etaSeconds * 1000);
|
|
412
|
+
if (((_b = job.eta) === null || _b === void 0 ? void 0 : _b.getTime()) !== (newEta === null || newEta === void 0 ? void 0 : newEta.getTime())) {
|
|
413
|
+
job._update({ eta: newEta });
|
|
414
|
+
const maxEta = project.jobs.reduce((max, j) => { var _a; return Math.max(max, ((_a = j.eta) === null || _a === void 0 ? void 0 : _a.getTime()) || 0); }, 0);
|
|
415
|
+
const projectETA = maxEta ? new Date(maxEta) : undefined;
|
|
416
|
+
if (((_c = project.eta) === null || _c === void 0 ? void 0 : _c.getTime()) !== (projectETA === null || projectETA === void 0 ? void 0 : projectETA.getTime())) {
|
|
417
|
+
project._update({ eta: projectETA });
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
break;
|
|
421
|
+
}
|
|
295
422
|
case 'preview':
|
|
296
423
|
job._update({ previewUrl: event.url });
|
|
297
424
|
break;
|
|
@@ -308,6 +435,17 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
308
435
|
}
|
|
309
436
|
case 'error':
|
|
310
437
|
job._update({ status: 'failed', error: event.error });
|
|
438
|
+
// Check if project should also fail when a job fails
|
|
439
|
+
// For video jobs (single image) or when all jobs have failed, propagate to project
|
|
440
|
+
const allJobsStarted = project.jobs.length >= project.params.numberOfMedia;
|
|
441
|
+
const allJobsFailed = allJobsStarted && project.jobs.every((j) => j.status === 'failed');
|
|
442
|
+
const isSingleJobProject = project.params.numberOfMedia === 1;
|
|
443
|
+
if (isSingleJobProject || allJobsFailed) {
|
|
444
|
+
project._update({
|
|
445
|
+
status: 'failed',
|
|
446
|
+
error: event.error
|
|
447
|
+
});
|
|
448
|
+
}
|
|
311
449
|
break;
|
|
312
450
|
}
|
|
313
451
|
}
|
|
@@ -328,41 +466,69 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
328
466
|
return Promise.resolve(this._availableModels);
|
|
329
467
|
}
|
|
330
468
|
return new Promise((resolve, reject) => {
|
|
469
|
+
let settled = false;
|
|
331
470
|
const timeoutId = setTimeout(() => {
|
|
332
|
-
|
|
471
|
+
if (!settled) {
|
|
472
|
+
settled = true;
|
|
473
|
+
this.off('availableModels', handler);
|
|
474
|
+
reject(new Error('Timeout waiting for models'));
|
|
475
|
+
}
|
|
333
476
|
}, timeout);
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
477
|
+
const handler = (models) => {
|
|
478
|
+
// Only resolve when we get a non-empty models list
|
|
479
|
+
// Empty arrays may be emitted during disconnects/reconnects
|
|
480
|
+
if (models.length && !settled) {
|
|
481
|
+
settled = true;
|
|
482
|
+
clearTimeout(timeoutId);
|
|
483
|
+
this.off('availableModels', handler);
|
|
337
484
|
resolve(models);
|
|
338
485
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
}
|
|
342
|
-
});
|
|
486
|
+
};
|
|
487
|
+
this.on('availableModels', handler);
|
|
343
488
|
});
|
|
344
489
|
}
|
|
345
490
|
/**
|
|
346
491
|
* Send new project request to the network. Returns project instance which can be used to track
|
|
347
|
-
* progress and get resulting images.
|
|
492
|
+
* progress and get resulting images or videos.
|
|
348
493
|
* @param data
|
|
349
494
|
*/
|
|
350
495
|
create(data) {
|
|
351
496
|
return __awaiter(this, void 0, void 0, function* () {
|
|
352
|
-
var _a, _b;
|
|
353
497
|
const project = new Project_1.default(Object.assign({}, data), { api: this, logger: this.client.logger });
|
|
498
|
+
const modelOptions = yield this.getModelOptions(data.modelId);
|
|
499
|
+
const request = (0, createJobRequestMessage_1.default)(project.id, data, modelOptions);
|
|
500
|
+
switch (data.type) {
|
|
501
|
+
case 'image':
|
|
502
|
+
yield this._processImageAssets(project, data);
|
|
503
|
+
break;
|
|
504
|
+
case 'video':
|
|
505
|
+
yield this._processVideoAssets(project, data);
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
yield this.client.socket.send('jobRequest', request);
|
|
509
|
+
this.projects.push(project);
|
|
510
|
+
return project;
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
_processImageAssets(project, data) {
|
|
514
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
515
|
+
var _a, _b;
|
|
516
|
+
//Guide image
|
|
354
517
|
if (data.startingImage && data.startingImage !== true) {
|
|
355
518
|
yield this.uploadGuideImage(project.id, data.startingImage);
|
|
356
519
|
}
|
|
520
|
+
// ControlNet image
|
|
357
521
|
if (((_a = data.controlNet) === null || _a === void 0 ? void 0 : _a.image) && data.controlNet.image !== true) {
|
|
358
522
|
yield this.uploadCNImage(project.id, data.controlNet.image);
|
|
359
523
|
}
|
|
524
|
+
// Context images (Flux.2 Dev supports up to 6; Qwen Image Edit Plus supports up to 3; Flux Kontext supports up to 2)
|
|
360
525
|
if ((_b = data.contextImages) === null || _b === void 0 ? void 0 : _b.length) {
|
|
361
|
-
|
|
526
|
+
const maxContextImages = (0, validation_1.getMaxContextImages)(data.modelId);
|
|
527
|
+
if (data.contextImages.length > maxContextImages) {
|
|
362
528
|
throw new ApiClient_1.ApiError(500, {
|
|
363
529
|
status: 'error',
|
|
364
530
|
errorCode: 0,
|
|
365
|
-
message: `Up to
|
|
531
|
+
message: `Up to ${maxContextImages} context images are supported for this model`
|
|
366
532
|
});
|
|
367
533
|
}
|
|
368
534
|
yield Promise.all(data.contextImages.map((image, index) => {
|
|
@@ -371,10 +537,22 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
371
537
|
}
|
|
372
538
|
}));
|
|
373
539
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
_processVideoAssets(project, data) {
|
|
543
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
544
|
+
if ((data === null || data === void 0 ? void 0 : data.referenceImage) && data.referenceImage !== true) {
|
|
545
|
+
yield this.uploadReferenceImage(project.id, data.referenceImage);
|
|
546
|
+
}
|
|
547
|
+
if ((data === null || data === void 0 ? void 0 : data.referenceImageEnd) && data.referenceImageEnd !== true) {
|
|
548
|
+
yield this.uploadReferenceImageEnd(project.id, data.referenceImageEnd);
|
|
549
|
+
}
|
|
550
|
+
if ((data === null || data === void 0 ? void 0 : data.referenceAudio) && data.referenceAudio !== true) {
|
|
551
|
+
yield this.uploadReferenceAudio(project.id, data.referenceAudio);
|
|
552
|
+
}
|
|
553
|
+
if ((data === null || data === void 0 ? void 0 : data.referenceVideo) && data.referenceVideo !== true) {
|
|
554
|
+
yield this.uploadReferenceVideo(project.id, data.referenceVideo);
|
|
555
|
+
}
|
|
378
556
|
});
|
|
379
557
|
}
|
|
380
558
|
/**
|
|
@@ -425,13 +603,13 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
425
603
|
return __awaiter(this, void 0, void 0, function* () {
|
|
426
604
|
const imageId = (0, getUUID_1.default)();
|
|
427
605
|
const presignedUrl = yield this.uploadUrl({
|
|
428
|
-
imageId
|
|
606
|
+
imageId,
|
|
429
607
|
jobId: projectId,
|
|
430
608
|
type: 'startingImage'
|
|
431
609
|
});
|
|
432
610
|
const res = yield fetch(presignedUrl, {
|
|
433
611
|
method: 'PUT',
|
|
434
|
-
body: file
|
|
612
|
+
body: toFetchBody(file)
|
|
435
613
|
});
|
|
436
614
|
if (!res.ok) {
|
|
437
615
|
throw new ApiClient_1.ApiError(res.status, {
|
|
@@ -447,13 +625,13 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
447
625
|
return __awaiter(this, void 0, void 0, function* () {
|
|
448
626
|
const imageId = (0, getUUID_1.default)();
|
|
449
627
|
const presignedUrl = yield this.uploadUrl({
|
|
450
|
-
imageId
|
|
628
|
+
imageId,
|
|
451
629
|
jobId: projectId,
|
|
452
630
|
type: 'cnImage'
|
|
453
631
|
});
|
|
454
632
|
const res = yield fetch(presignedUrl, {
|
|
455
633
|
method: 'PUT',
|
|
456
|
-
body: file
|
|
634
|
+
body: toFetchBody(file)
|
|
457
635
|
});
|
|
458
636
|
if (!res.ok) {
|
|
459
637
|
throw new ApiClient_1.ApiError(res.status, {
|
|
@@ -474,9 +652,10 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
474
652
|
jobId: projectId,
|
|
475
653
|
type: `contextImage${imageIndex}`
|
|
476
654
|
});
|
|
655
|
+
const body = toFetchBody(file);
|
|
477
656
|
const res = yield fetch(presignedUrl, {
|
|
478
657
|
method: 'PUT',
|
|
479
|
-
body
|
|
658
|
+
body
|
|
480
659
|
});
|
|
481
660
|
if (!res.ok) {
|
|
482
661
|
throw new ApiClient_1.ApiError(res.status, {
|
|
@@ -488,14 +667,133 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
488
667
|
return imageId;
|
|
489
668
|
});
|
|
490
669
|
}
|
|
670
|
+
// ============================================
|
|
671
|
+
// VIDEO WORKFLOW UPLOADS (WAN 2.2)
|
|
672
|
+
// ============================================
|
|
491
673
|
/**
|
|
492
|
-
*
|
|
674
|
+
* Upload reference image for WAN video workflows
|
|
675
|
+
* @internal
|
|
676
|
+
*/
|
|
677
|
+
uploadReferenceImage(projectId, file) {
|
|
678
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
679
|
+
const imageId = (0, getUUID_1.default)();
|
|
680
|
+
const presignedUrl = yield this.uploadUrl({
|
|
681
|
+
imageId,
|
|
682
|
+
jobId: projectId,
|
|
683
|
+
type: 'referenceImage'
|
|
684
|
+
});
|
|
685
|
+
const res = yield fetch(presignedUrl, {
|
|
686
|
+
method: 'PUT',
|
|
687
|
+
body: toFetchBody(file)
|
|
688
|
+
});
|
|
689
|
+
if (!res.ok) {
|
|
690
|
+
throw new ApiClient_1.ApiError(res.status, {
|
|
691
|
+
status: 'error',
|
|
692
|
+
errorCode: 0,
|
|
693
|
+
message: 'Failed to upload reference image'
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
return imageId;
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Upload reference image end for i2v interpolation
|
|
701
|
+
* @internal
|
|
702
|
+
*/
|
|
703
|
+
uploadReferenceImageEnd(projectId, file) {
|
|
704
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
705
|
+
const imageId = (0, getUUID_1.default)();
|
|
706
|
+
const presignedUrl = yield this.uploadUrl({
|
|
707
|
+
imageId,
|
|
708
|
+
jobId: projectId,
|
|
709
|
+
type: 'referenceImageEnd'
|
|
710
|
+
});
|
|
711
|
+
const res = yield fetch(presignedUrl, {
|
|
712
|
+
method: 'PUT',
|
|
713
|
+
body: toFetchBody(file)
|
|
714
|
+
});
|
|
715
|
+
if (!res.ok) {
|
|
716
|
+
throw new ApiClient_1.ApiError(res.status, {
|
|
717
|
+
status: 'error',
|
|
718
|
+
errorCode: 0,
|
|
719
|
+
message: 'Failed to upload reference image end'
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
return imageId;
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Upload reference audio for s2v workflows
|
|
727
|
+
* Supported formats: mp3, m4a, wav
|
|
728
|
+
* @internal
|
|
729
|
+
*/
|
|
730
|
+
uploadReferenceAudio(projectId, file) {
|
|
731
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
732
|
+
const contentType = getFileContentType(file);
|
|
733
|
+
const presignedUrl = yield this.mediaUploadUrl({
|
|
734
|
+
jobId: projectId,
|
|
735
|
+
type: 'referenceAudio'
|
|
736
|
+
});
|
|
737
|
+
const headers = {};
|
|
738
|
+
if (contentType) {
|
|
739
|
+
headers['Content-Type'] = contentType;
|
|
740
|
+
}
|
|
741
|
+
const res = yield fetch(presignedUrl, {
|
|
742
|
+
method: 'PUT',
|
|
743
|
+
body: toFetchBody(file),
|
|
744
|
+
headers
|
|
745
|
+
});
|
|
746
|
+
if (!res.ok) {
|
|
747
|
+
throw new ApiClient_1.ApiError(res.status, {
|
|
748
|
+
status: 'error',
|
|
749
|
+
errorCode: 0,
|
|
750
|
+
message: 'Failed to upload reference audio'
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* Upload reference video for animate workflows
|
|
757
|
+
* Supported formats: mp4, mov
|
|
758
|
+
* @internal
|
|
759
|
+
*/
|
|
760
|
+
uploadReferenceVideo(projectId, file) {
|
|
761
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
762
|
+
const contentType = getFileContentType(file);
|
|
763
|
+
const presignedUrl = yield this.mediaUploadUrl({
|
|
764
|
+
jobId: projectId,
|
|
765
|
+
type: 'referenceVideo'
|
|
766
|
+
});
|
|
767
|
+
const headers = {};
|
|
768
|
+
if (contentType) {
|
|
769
|
+
headers['Content-Type'] = contentType;
|
|
770
|
+
}
|
|
771
|
+
const res = yield fetch(presignedUrl, {
|
|
772
|
+
method: 'PUT',
|
|
773
|
+
body: toFetchBody(file),
|
|
774
|
+
headers
|
|
775
|
+
});
|
|
776
|
+
if (!res.ok) {
|
|
777
|
+
throw new ApiClient_1.ApiError(res.status, {
|
|
778
|
+
status: 'error',
|
|
779
|
+
errorCode: 0,
|
|
780
|
+
message: 'Failed to upload reference video'
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
// ============================================
|
|
786
|
+
// COST ESTIMATION
|
|
787
|
+
// ============================================
|
|
788
|
+
/**
|
|
789
|
+
* Estimate image project cost
|
|
493
790
|
*/
|
|
494
791
|
estimateCost(_a) {
|
|
495
|
-
return __awaiter(this, arguments, void 0, function* ({ network, tokenType, model, imageCount, stepCount, previewCount, cnEnabled, startingImageStrength, width, height, sizePreset, guidance,
|
|
792
|
+
return __awaiter(this, arguments, void 0, function* ({ network, tokenType, model, imageCount, stepCount, previewCount, cnEnabled, startingImageStrength, width, height, sizePreset, guidance, sampler, contextImages }) {
|
|
496
793
|
let apiVersion = 2;
|
|
794
|
+
const modelOptions = yield this.getModelOptions(model);
|
|
497
795
|
const pathParams = [
|
|
498
|
-
tokenType || '
|
|
796
|
+
tokenType || 'spark',
|
|
499
797
|
network,
|
|
500
798
|
model,
|
|
501
799
|
imageCount,
|
|
@@ -518,21 +816,28 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
518
816
|
else {
|
|
519
817
|
pathParams.push(0, 0);
|
|
520
818
|
}
|
|
521
|
-
if (
|
|
819
|
+
if (sampler) {
|
|
522
820
|
apiVersion = 3;
|
|
523
821
|
pathParams.push(guidance || 0);
|
|
524
|
-
pathParams.push(
|
|
822
|
+
pathParams.push((0, validation_1.validateSampler)(sampler, modelOptions));
|
|
525
823
|
pathParams.push(contextImages || 0);
|
|
526
824
|
}
|
|
527
825
|
const r = yield this.client.socket.get(`/api/v${apiVersion}/job/estimate/${pathParams.join('/')}`);
|
|
528
826
|
return {
|
|
529
827
|
token: r.quote.project.costInToken,
|
|
530
|
-
usd: r.quote.project.costInUSD
|
|
828
|
+
usd: r.quote.project.costInUSD,
|
|
829
|
+
spark: r.quote.project.costInSpark,
|
|
830
|
+
sogni: r.quote.project.costInSogni
|
|
531
831
|
};
|
|
532
832
|
});
|
|
533
833
|
}
|
|
834
|
+
/**
|
|
835
|
+
* Estimate image enhancement cost
|
|
836
|
+
* @param strength
|
|
837
|
+
* @param tokenType
|
|
838
|
+
*/
|
|
534
839
|
estimateEnhancementCost(strength_1) {
|
|
535
|
-
return __awaiter(this, arguments, void 0, function* (strength, tokenType = '
|
|
840
|
+
return __awaiter(this, arguments, void 0, function* (strength, tokenType = 'spark') {
|
|
536
841
|
return this.estimateCost({
|
|
537
842
|
network: Job_1.enhancementDefaults.network,
|
|
538
843
|
tokenType,
|
|
@@ -545,10 +850,51 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
545
850
|
});
|
|
546
851
|
});
|
|
547
852
|
}
|
|
853
|
+
/**
|
|
854
|
+
* Estimates the cost of generating a video based on the provided parameters.
|
|
855
|
+
*
|
|
856
|
+
* @param {VideoEstimateRequest} params - The parameters required for video cost estimation. This includes:
|
|
857
|
+
* - tokenType: The type of token to be used for generation.
|
|
858
|
+
* - model: The model to be used for video generation.
|
|
859
|
+
* - width: The width of the video in pixels.
|
|
860
|
+
* - height: The height of the video in pixels.
|
|
861
|
+
* - frames: The total number of frames in the video.
|
|
862
|
+
* - fps: The frames per second for the video.
|
|
863
|
+
* - steps: Number of steps.
|
|
864
|
+
* @return {Promise<Object>} Returns an object containing the estimated costs for the video in different units:
|
|
865
|
+
* - token: Cost in tokens.
|
|
866
|
+
* - usd: Cost in USD.
|
|
867
|
+
* - spark: Cost in Spark.
|
|
868
|
+
* - sogni: Cost in Sogni.
|
|
869
|
+
*/
|
|
870
|
+
estimateVideoCost(params) {
|
|
871
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
872
|
+
const pathParams = [
|
|
873
|
+
params.tokenType,
|
|
874
|
+
params.model,
|
|
875
|
+
params.width,
|
|
876
|
+
params.height,
|
|
877
|
+
params.frames ? params.frames : params.duration * 16 + 1,
|
|
878
|
+
params.fps,
|
|
879
|
+
params.steps,
|
|
880
|
+
params.numberOfMedia
|
|
881
|
+
];
|
|
882
|
+
const path = pathParams.map((p) => encodeURIComponent(p)).join('/');
|
|
883
|
+
const r = yield this.client.socket.get(`/api/v1/job-video/estimate/${path}`);
|
|
884
|
+
return {
|
|
885
|
+
token: r.quote.project.costInToken,
|
|
886
|
+
usd: r.quote.project.costInUSD,
|
|
887
|
+
spark: r.quote.project.costInSpark,
|
|
888
|
+
sogni: r.quote.project.costInSogni
|
|
889
|
+
};
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
// ============================================
|
|
893
|
+
// URL HELPERS
|
|
894
|
+
// ============================================
|
|
548
895
|
/**
|
|
549
896
|
* Get upload URL for image
|
|
550
897
|
* @internal
|
|
551
|
-
* @param params
|
|
552
898
|
*/
|
|
553
899
|
uploadUrl(params) {
|
|
554
900
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -559,14 +905,44 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
559
905
|
/**
|
|
560
906
|
* Get download URL for image
|
|
561
907
|
* @internal
|
|
562
|
-
* @param params
|
|
563
908
|
*/
|
|
564
909
|
downloadUrl(params) {
|
|
565
910
|
return __awaiter(this, void 0, void 0, function* () {
|
|
911
|
+
var _a;
|
|
566
912
|
const r = yield this.client.rest.get(`/v1/image/downloadUrl`, params);
|
|
913
|
+
if (!((_a = r === null || r === void 0 ? void 0 : r.data) === null || _a === void 0 ? void 0 : _a.downloadUrl)) {
|
|
914
|
+
throw new Error(`API returned no downloadUrl: ${JSON.stringify(r)}`);
|
|
915
|
+
}
|
|
916
|
+
return r.data.downloadUrl;
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Get upload URL for media (video/audio)
|
|
921
|
+
* @internal
|
|
922
|
+
*/
|
|
923
|
+
mediaUploadUrl(params) {
|
|
924
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
925
|
+
const r = yield this.client.rest.get(`/v1/media/uploadUrl`, params);
|
|
926
|
+
return r.data.uploadUrl;
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* Get download URL for media (video/audio)
|
|
931
|
+
* @internal
|
|
932
|
+
*/
|
|
933
|
+
mediaDownloadUrl(params) {
|
|
934
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
935
|
+
var _a;
|
|
936
|
+
const r = yield this.client.rest.get(`/v1/media/downloadUrl`, params);
|
|
937
|
+
if (!((_a = r === null || r === void 0 ? void 0 : r.data) === null || _a === void 0 ? void 0 : _a.downloadUrl)) {
|
|
938
|
+
throw new Error(`API returned no downloadUrl: ${JSON.stringify(r)}`);
|
|
939
|
+
}
|
|
567
940
|
return r.data.downloadUrl;
|
|
568
941
|
});
|
|
569
942
|
}
|
|
943
|
+
// ============================================
|
|
944
|
+
// MODEL/PRESET HELPERS
|
|
945
|
+
// ============================================
|
|
570
946
|
getSupportedModels() {
|
|
571
947
|
return __awaiter(this, arguments, void 0, function* (forceRefresh = false) {
|
|
572
948
|
if (this._supportedModels.data &&
|
|
@@ -579,12 +955,24 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
579
955
|
return models;
|
|
580
956
|
});
|
|
581
957
|
}
|
|
958
|
+
_getModelTiers() {
|
|
959
|
+
return __awaiter(this, arguments, void 0, function* (forceRefresh = false) {
|
|
960
|
+
if (this._modelTiers.data &&
|
|
961
|
+
!forceRefresh &&
|
|
962
|
+
Date.now() - this._modelTiers.updatedAt.getTime() < MODELS_REFRESH_INTERVAL) {
|
|
963
|
+
return this._modelTiers.data;
|
|
964
|
+
}
|
|
965
|
+
const tiers = yield this.client.socket.get(`/api/v2/models/tiers`);
|
|
966
|
+
this._modelTiers = { data: tiers, updatedAt: new Date() };
|
|
967
|
+
return tiers;
|
|
968
|
+
});
|
|
969
|
+
}
|
|
582
970
|
/**
|
|
583
971
|
* Get supported size presets for the model and network. Size presets are cached for 10 minutes.
|
|
584
972
|
*
|
|
585
973
|
* @example
|
|
586
974
|
* ```ts
|
|
587
|
-
* const presets = await
|
|
975
|
+
* const presets = await sogni.projects.getSizePresets('fast', 'flux1-schnell-fp8');
|
|
588
976
|
* console.log(presets);
|
|
589
977
|
* ```
|
|
590
978
|
*
|
|
@@ -612,6 +1000,50 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
612
1000
|
return data;
|
|
613
1001
|
});
|
|
614
1002
|
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Retrieves the video asset configuration for a given video model identifier.
|
|
1005
|
+
* Validates whether the provided model ID corresponds to a video model. If it does,
|
|
1006
|
+
* returns the appropriate video asset configuration based on the workflow type.
|
|
1007
|
+
*
|
|
1008
|
+
* @example Returned object for a model that implements image to video workflow:
|
|
1009
|
+
* ```json
|
|
1010
|
+
* {
|
|
1011
|
+
* "workflowType": "i2v",
|
|
1012
|
+
* "assets": {
|
|
1013
|
+
* "referenceImage": "required",
|
|
1014
|
+
* "referenceImageEnd": "optional",
|
|
1015
|
+
* "referenceAudio": "forbidden",
|
|
1016
|
+
* "referenceVideo": "forbidden"
|
|
1017
|
+
* }
|
|
1018
|
+
* }
|
|
1019
|
+
* ```
|
|
1020
|
+
*
|
|
1021
|
+
* @param {string} modelId - The identifier of the video model to retrieve the configuration for.
|
|
1022
|
+
* @return {Object} The video asset configuration object where key is asset field and value is
|
|
1023
|
+
* either `required`, `forbidden` or `optional`. Returns `null` if no rules defined for the model.
|
|
1024
|
+
* @throws {ApiError} Throws an error if the provided model ID is not a video model.
|
|
1025
|
+
*/
|
|
1026
|
+
getVideoAssetConfig(modelId) {
|
|
1027
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1028
|
+
if (!this.isVideoModelId(modelId)) {
|
|
1029
|
+
throw new ApiClient_1.ApiError(400, {
|
|
1030
|
+
status: 'error',
|
|
1031
|
+
errorCode: 0,
|
|
1032
|
+
message: `Model ${modelId} is not a video model`
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
const workflow = (0, utils_1.getVideoWorkflowType)(modelId);
|
|
1036
|
+
if (!workflow) {
|
|
1037
|
+
return {
|
|
1038
|
+
workflowType: null
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
return {
|
|
1042
|
+
workflowType: workflow,
|
|
1043
|
+
assets: utils_1.VIDEO_WORKFLOW_ASSETS[workflow]
|
|
1044
|
+
};
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
615
1047
|
/**
|
|
616
1048
|
* Get available models and their worker counts. Normally, you would get list once you connect
|
|
617
1049
|
* to the server, but you can also call this method to get the list of available models manually.
|
|
@@ -627,11 +1059,36 @@ class ProjectsApi extends ApiGroup_1.default {
|
|
|
627
1059
|
return {
|
|
628
1060
|
id: (model === null || model === void 0 ? void 0 : model.id) || sid,
|
|
629
1061
|
name: (model === null || model === void 0 ? void 0 : model.name) || sid.replace(/-/g, ' '),
|
|
630
|
-
workerCount
|
|
1062
|
+
workerCount,
|
|
1063
|
+
media: (model === null || model === void 0 ? void 0 : model.media) || 'image'
|
|
631
1064
|
};
|
|
632
1065
|
});
|
|
633
1066
|
});
|
|
634
1067
|
}
|
|
1068
|
+
getModelOptions(modelId) {
|
|
1069
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1070
|
+
const models = yield this.getSupportedModels();
|
|
1071
|
+
const tiers = yield this._getModelTiers();
|
|
1072
|
+
const model = models.find((m) => m.id === modelId);
|
|
1073
|
+
if (!model) {
|
|
1074
|
+
throw new Error(`Model ${modelId} not supported`);
|
|
1075
|
+
}
|
|
1076
|
+
const tier = tiers[model.tier];
|
|
1077
|
+
if (!tier) {
|
|
1078
|
+
throw new Error(`Unable to find model tier "${model.tier}" please contact support`);
|
|
1079
|
+
}
|
|
1080
|
+
if ((0, ModelTiersRaw_1.isImageTier)(tier)) {
|
|
1081
|
+
return (0, ModelOptions_1.mapImageTier)(tier);
|
|
1082
|
+
}
|
|
1083
|
+
if ((0, ModelTiersRaw_1.isVideoTier)(tier)) {
|
|
1084
|
+
return (0, ModelOptions_1.mapVideoTier)(tier);
|
|
1085
|
+
}
|
|
1086
|
+
if ((0, ModelTiersRaw_1.isComfyImageTier)(tier)) {
|
|
1087
|
+
return (0, ModelOptions_1.mapComfyImageTier)(tier);
|
|
1088
|
+
}
|
|
1089
|
+
throw new Error(`Unsupported model tier "${model.tier}"`);
|
|
1090
|
+
});
|
|
1091
|
+
}
|
|
635
1092
|
}
|
|
636
1093
|
exports.default = ProjectsApi;
|
|
637
1094
|
//# sourceMappingURL=index.js.map
|