@sogni-ai/sogni-client 4.0.0-alpha.37 → 4.0.0-alpha.38
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 +15 -0
- package/dist/ApiClient/WebSocketClient/events.d.ts +1 -0
- package/dist/Projects/createJobRequestMessage.js +34 -2
- package/dist/Projects/createJobRequestMessage.js.map +1 -1
- package/dist/Projects/index.d.ts +2 -0
- package/dist/Projects/index.js +67 -18
- package/dist/Projects/index.js.map +1 -1
- package/dist/Projects/types/ComfySamplerParams.d.ts +26 -0
- package/dist/Projects/types/ComfySamplerParams.js +33 -0
- package/dist/Projects/types/ComfySamplerParams.js.map +1 -0
- package/dist/Projects/types/ComfySchedulerParams.d.ts +17 -0
- package/dist/Projects/types/ComfySchedulerParams.js +23 -0
- package/dist/Projects/types/ComfySchedulerParams.js.map +1 -0
- package/dist/Projects/types/ForgeSamplerParams.d.ts +27 -0
- package/dist/Projects/types/ForgeSamplerParams.js +39 -0
- package/dist/Projects/types/ForgeSamplerParams.js.map +1 -0
- package/dist/Projects/types/ForgeSchedulerParams.d.ts +17 -0
- package/dist/Projects/types/ForgeSchedulerParams.js +28 -0
- package/dist/Projects/types/ForgeSchedulerParams.js.map +1 -0
- package/dist/Projects/types/index.d.ts +24 -6
- package/dist/Projects/types/index.js +9 -5
- package/dist/Projects/types/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/RestClient.js +15 -2
- package/dist/lib/RestClient.js.map +1 -1
- package/dist/lib/validation.d.ts +15 -2
- package/dist/lib/validation.js +62 -13
- package/dist/lib/validation.js.map +1 -1
- package/package.json +1 -1
- package/src/ApiClient/WebSocketClient/events.ts +1 -0
- package/src/Projects/createJobRequestMessage.ts +41 -5
- package/src/Projects/index.ts +77 -23
- package/src/Projects/types/ComfySamplerParams.ts +31 -0
- package/src/Projects/types/ComfySchedulerParams.ts +21 -0
- package/src/Projects/types/ForgeSamplerParams.ts +37 -0
- package/src/Projects/types/ForgeSchedulerParams.ts +26 -0
- package/src/Projects/types/index.ts +31 -6
- package/src/index.ts +14 -3
- package/src/lib/RestClient.ts +16 -2
- package/src/lib/validation.ts +73 -12
- package/dist/Projects/types/SamplerParams.d.ts +0 -13
- package/dist/Projects/types/SamplerParams.js +0 -26
- package/dist/Projects/types/SamplerParams.js.map +0 -1
- package/dist/Projects/types/SchedulerParams.d.ts +0 -14
- package/dist/Projects/types/SchedulerParams.js +0 -24
- package/dist/Projects/types/SchedulerParams.js.map +0 -1
- package/src/Projects/types/SamplerParams.ts +0 -24
- package/src/Projects/types/SchedulerParams.ts +0 -22
package/src/Projects/index.ts
CHANGED
|
@@ -11,7 +11,15 @@ import {
|
|
|
11
11
|
SupportedModel,
|
|
12
12
|
ImageProjectParams,
|
|
13
13
|
VideoProjectParams,
|
|
14
|
-
VideoEstimateRequest
|
|
14
|
+
VideoEstimateRequest,
|
|
15
|
+
SupportedComfySamplers,
|
|
16
|
+
SupportedForgeSamplers,
|
|
17
|
+
SupportedComfySchedulers,
|
|
18
|
+
SupportedForgeSchedulers,
|
|
19
|
+
ComfyScheduler,
|
|
20
|
+
ForgeScheduler,
|
|
21
|
+
ComfySampler,
|
|
22
|
+
ForgeSampler
|
|
15
23
|
} from './types';
|
|
16
24
|
import {
|
|
17
25
|
JobErrorData,
|
|
@@ -39,7 +47,7 @@ import {
|
|
|
39
47
|
VIDEO_WORKFLOW_ASSETS
|
|
40
48
|
} from './utils';
|
|
41
49
|
import { TokenType } from '../types/token';
|
|
42
|
-
import { validateSampler } from '../lib/validation';
|
|
50
|
+
import { isComfyModel, validateSampler } from '../lib/validation';
|
|
43
51
|
|
|
44
52
|
const sizePresetCache = new Cache<SizePreset[]>(10 * 60 * 1000);
|
|
45
53
|
const GARBAGE_COLLECT_TIMEOUT = 30000;
|
|
@@ -61,17 +69,17 @@ function getFileContentType(file: File | Buffer | Blob): string | undefined {
|
|
|
61
69
|
* Convert file to a format compatible with fetch body.
|
|
62
70
|
* Converts Node.js Buffer to Blob for cross-platform compatibility.
|
|
63
71
|
*/
|
|
64
|
-
function toFetchBody(file: File | Buffer | Blob) {
|
|
72
|
+
function toFetchBody(file: File | Buffer | Blob): BodyInit {
|
|
65
73
|
// Node.js Buffer is not supported in browsers, so we can skip this conversion
|
|
66
74
|
if (typeof Buffer === 'undefined') {
|
|
67
|
-
return file;
|
|
75
|
+
return file as BodyInit;
|
|
68
76
|
}
|
|
69
77
|
if (Buffer.isBuffer(file)) {
|
|
70
78
|
// Copy Buffer data to a new ArrayBuffer to ensure type compatibility
|
|
71
79
|
const arrayBuffer = file.buffer.slice(file.byteOffset, file.byteOffset + file.byteLength);
|
|
72
80
|
return new Blob([arrayBuffer as ArrayBuffer]);
|
|
73
81
|
}
|
|
74
|
-
return file;
|
|
82
|
+
return file as BodyInit;
|
|
75
83
|
}
|
|
76
84
|
|
|
77
85
|
function mapErrorCodes(code: string): number {
|
|
@@ -126,7 +134,11 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
126
134
|
this.client.socket.on('jobProgress', this.handleJobProgress.bind(this));
|
|
127
135
|
this.client.socket.on('jobETA', this.handleJobETA.bind(this));
|
|
128
136
|
this.client.socket.on('jobError', this.handleJobError.bind(this));
|
|
129
|
-
this.client.socket.on('jobResult',
|
|
137
|
+
this.client.socket.on('jobResult', (data: any) => {
|
|
138
|
+
this.handleJobResult(data).catch((err) => {
|
|
139
|
+
this.client.logger.error('Error in handleJobResult:', err);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
130
142
|
// Listen to the server disconnect event
|
|
131
143
|
this.client.on('disconnected', this.handleServerDisconnected.bind(this));
|
|
132
144
|
// Listen to project and job events and update project and job instances
|
|
@@ -245,27 +257,47 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
245
257
|
private async handleJobResult(data: JobResultData) {
|
|
246
258
|
const project = this.projects.find((p) => p.id === data.jobID);
|
|
247
259
|
const passNSFWCheck = !data.triggeredNSFWFilter || !project || project.params.disableNSFWFilter;
|
|
248
|
-
let downloadUrl = null;
|
|
249
|
-
|
|
250
|
-
//
|
|
251
|
-
if (passNSFWCheck && !data.userCanceled) {
|
|
260
|
+
let downloadUrl = data.resultUrl || null; // Use resultUrl from event if provided
|
|
261
|
+
|
|
262
|
+
// If no resultUrl provided and NSFW check passes, generate download URL
|
|
263
|
+
if (!downloadUrl && passNSFWCheck && !data.userCanceled) {
|
|
252
264
|
// Use media endpoint for video models, image endpoint for image models
|
|
253
265
|
const isVideo = project && this.isVideoModelId(project.params.modelId);
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
266
|
+
try {
|
|
267
|
+
if (isVideo) {
|
|
268
|
+
downloadUrl = await this.mediaDownloadUrl({
|
|
269
|
+
jobId: data.jobID,
|
|
270
|
+
id: data.imgID,
|
|
271
|
+
type: 'complete'
|
|
272
|
+
});
|
|
273
|
+
} else {
|
|
274
|
+
downloadUrl = await this.downloadUrl({
|
|
275
|
+
jobId: data.jobID,
|
|
276
|
+
imageId: data.imgID,
|
|
277
|
+
type: 'complete'
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
} catch (error: any) {
|
|
281
|
+
// Continue with null downloadUrl - the event will indicate failure
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Update the job directly with the result URL to prevent duplicate API calls
|
|
286
|
+
if (project) {
|
|
287
|
+
const job = project.job(data.imgID);
|
|
288
|
+
if (job) {
|
|
289
|
+
job._update({
|
|
290
|
+
status: data.userCanceled ? 'canceled' : 'completed',
|
|
291
|
+
step: data.performedStepCount,
|
|
292
|
+
seed: Number(data.lastSeed),
|
|
293
|
+
resultUrl: downloadUrl,
|
|
294
|
+
isNSFW: data.triggeredNSFWFilter,
|
|
295
|
+
userCanceled: data.userCanceled
|
|
265
296
|
});
|
|
266
297
|
}
|
|
267
298
|
}
|
|
268
299
|
|
|
300
|
+
// Emit job completion event with the generated download URL
|
|
269
301
|
this.emit('job', {
|
|
270
302
|
type: 'completed',
|
|
271
303
|
projectId: data.jobID,
|
|
@@ -494,6 +526,7 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
494
526
|
async create(data: ProjectParams): Promise<Project> {
|
|
495
527
|
const project = new Project({ ...data }, { api: this, logger: this.client.logger });
|
|
496
528
|
const request = createJobRequestMessage(project.id, data);
|
|
529
|
+
|
|
497
530
|
switch (data.type) {
|
|
498
531
|
case 'image':
|
|
499
532
|
await this._processImageAssets(project, data);
|
|
@@ -650,9 +683,10 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
650
683
|
jobId: projectId,
|
|
651
684
|
type: `contextImage${imageIndex}`
|
|
652
685
|
});
|
|
686
|
+
const body = toFetchBody(file);
|
|
653
687
|
const res = await fetch(presignedUrl, {
|
|
654
688
|
method: 'PUT',
|
|
655
|
-
body
|
|
689
|
+
body
|
|
656
690
|
});
|
|
657
691
|
if (!res.ok) {
|
|
658
692
|
throw new ApiError(res.status, {
|
|
@@ -825,7 +859,7 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
825
859
|
if (sampler) {
|
|
826
860
|
apiVersion = 3;
|
|
827
861
|
pathParams.push(guidance || 0);
|
|
828
|
-
pathParams.push(validateSampler(sampler)!);
|
|
862
|
+
pathParams.push(validateSampler(model, sampler)!);
|
|
829
863
|
pathParams.push(contextImages || 0);
|
|
830
864
|
}
|
|
831
865
|
const r = await this.client.socket.get<EstimationResponse>(
|
|
@@ -922,6 +956,9 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
922
956
|
`/v1/image/downloadUrl`,
|
|
923
957
|
params
|
|
924
958
|
);
|
|
959
|
+
if (!r?.data?.downloadUrl) {
|
|
960
|
+
throw new Error(`API returned no downloadUrl: ${JSON.stringify(r)}`);
|
|
961
|
+
}
|
|
925
962
|
return r.data.downloadUrl;
|
|
926
963
|
}
|
|
927
964
|
|
|
@@ -946,6 +983,9 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
946
983
|
`/v1/media/downloadUrl`,
|
|
947
984
|
params
|
|
948
985
|
);
|
|
986
|
+
if (!r?.data?.downloadUrl) {
|
|
987
|
+
throw new Error(`API returned no downloadUrl: ${JSON.stringify(r)}`);
|
|
988
|
+
}
|
|
949
989
|
return r.data.downloadUrl;
|
|
950
990
|
}
|
|
951
991
|
|
|
@@ -1064,6 +1104,20 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
1064
1104
|
};
|
|
1065
1105
|
});
|
|
1066
1106
|
}
|
|
1107
|
+
|
|
1108
|
+
async getSamplers(modelId: string) {
|
|
1109
|
+
if (isComfyModel(modelId)) {
|
|
1110
|
+
return Object.keys(SupportedComfySamplers) as ComfySampler[];
|
|
1111
|
+
}
|
|
1112
|
+
return Object.keys(SupportedForgeSamplers) as ForgeSampler[];
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
async getSchedulers(modelId: string) {
|
|
1116
|
+
if (isComfyModel(modelId)) {
|
|
1117
|
+
return Object.keys(SupportedComfySchedulers) as ComfyScheduler[];
|
|
1118
|
+
}
|
|
1119
|
+
return Object.keys(SupportedForgeSchedulers) as ForgeScheduler[];
|
|
1120
|
+
}
|
|
1067
1121
|
}
|
|
1068
1122
|
|
|
1069
1123
|
export default ProjectsApi;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ComfyUI sampler parameters for video models and ComfyUI-based image models.
|
|
3
|
+
* These use lowercase underscore format directly matching ComfyUI's internal names.
|
|
4
|
+
*/
|
|
5
|
+
export const SupportedComfySamplers = {
|
|
6
|
+
euler: 'euler',
|
|
7
|
+
euler_ancestral: 'euler_ancestral',
|
|
8
|
+
heun: 'heun',
|
|
9
|
+
dpmpp_2m: 'dpmpp_2m',
|
|
10
|
+
dpmpp_2m_sde: 'dpmpp_2m_sde',
|
|
11
|
+
dpmpp_sde: 'dpmpp_sde',
|
|
12
|
+
dpmpp_3m_sde: 'dpmpp_3m_sde',
|
|
13
|
+
uni_pc: 'uni_pc',
|
|
14
|
+
lcm: 'lcm',
|
|
15
|
+
// Additional ComfyUI samplers
|
|
16
|
+
lms: 'lms',
|
|
17
|
+
dpm_2: 'dpm_2',
|
|
18
|
+
dpm_2_ancestral: 'dpm_2_ancestral',
|
|
19
|
+
dpm_fast: 'dpm_fast',
|
|
20
|
+
dpm_adaptive: 'dpm_adaptive',
|
|
21
|
+
dpmpp_2s_ancestral: 'dpmpp_2s_ancestral',
|
|
22
|
+
ddpm: 'ddpm',
|
|
23
|
+
ddim: 'ddim',
|
|
24
|
+
uni_pc_bh2: 'uni_pc_bh2'
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function isComfySampler(sampler: string): sampler is ComfySampler {
|
|
28
|
+
return sampler in SupportedComfySamplers;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type ComfySampler = keyof typeof SupportedComfySamplers;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ComfyUI scheduler parameters for video models and ComfyUI-based image models.
|
|
3
|
+
* These use lowercase underscore format directly matching ComfyUI's internal names.
|
|
4
|
+
*/
|
|
5
|
+
export const SupportedComfySchedulers = {
|
|
6
|
+
simple: 'simple',
|
|
7
|
+
normal: 'normal',
|
|
8
|
+
karras: 'karras',
|
|
9
|
+
exponential: 'exponential',
|
|
10
|
+
sgm_uniform: 'sgm_uniform',
|
|
11
|
+
ddim_uniform: 'ddim_uniform',
|
|
12
|
+
beta: 'beta',
|
|
13
|
+
linear_quadratic: 'linear_quadratic',
|
|
14
|
+
kl_optimal: 'kl_optimal'
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function isComfyScheduler(scheduler: string): scheduler is ComfyScheduler {
|
|
18
|
+
return scheduler in SupportedComfySchedulers;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type ComfyScheduler = keyof typeof SupportedComfySchedulers;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export const SupportedForgeSamplers = {
|
|
2
|
+
euler: 'Euler',
|
|
3
|
+
euler_ancestral: 'Euler Ancestral',
|
|
4
|
+
heun: 'Heun',
|
|
5
|
+
dpmpp_2m: 'DPM++ 2M',
|
|
6
|
+
dpmpp_2m_sde: 'DPM++ 2M SDE',
|
|
7
|
+
dpmpp_sde: 'DPM++ SDE',
|
|
8
|
+
dpmpp_3m_sde: 'DPM++ 3M SDE',
|
|
9
|
+
uni_pc: 'UniPC',
|
|
10
|
+
lcm: 'LCM (Latent Consistency Model)',
|
|
11
|
+
// Legacy/other supported samplers
|
|
12
|
+
lms: 'LMS',
|
|
13
|
+
dpm_2: 'DPM 2',
|
|
14
|
+
dpm_2_ancestral: 'DPM 2 Ancestral',
|
|
15
|
+
dpm_fast: 'DPM Fast',
|
|
16
|
+
dpm_adaptive: 'DPM Adaptive',
|
|
17
|
+
dpmpp_2s_ancestral: 'DPM++ 2S Ancestral',
|
|
18
|
+
ddpm: 'DDPM',
|
|
19
|
+
// SDK compatibility aliases
|
|
20
|
+
dfs_sd3: 'Discrete Flow Scheduler (SD3)',
|
|
21
|
+
dpm_pp: 'DPM Solver Multistep (DPM-Solver++)',
|
|
22
|
+
dpm_pp_sde: 'DPM++ SDE',
|
|
23
|
+
dpm_pp_2m: 'DPM++ 2M',
|
|
24
|
+
euler_a: 'Euler a',
|
|
25
|
+
pndm_plms: 'PNDM (Pseudo-linear multi-step)'
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export function isForgeSampler(sampler: string): sampler is ForgeSampler {
|
|
29
|
+
return sampler in SupportedForgeSamplers;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function isRawForgeSampler(sampler: string): boolean {
|
|
33
|
+
const samplers = Object.values(SupportedForgeSamplers);
|
|
34
|
+
return samplers.includes(sampler);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type ForgeSampler = keyof typeof SupportedForgeSamplers;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const SupportedForgeSchedulers = {
|
|
2
|
+
simple: 'Simple',
|
|
3
|
+
normal: 'Normal',
|
|
4
|
+
karras: 'Karras',
|
|
5
|
+
exponential: 'Exponential',
|
|
6
|
+
sgm_uniform: 'SGM Uniform',
|
|
7
|
+
ddim_uniform: 'DDIM Uniform',
|
|
8
|
+
beta: 'Beta',
|
|
9
|
+
linear_quadratic: 'Linear Quadratic',
|
|
10
|
+
kl_optimal: 'KL Optimal',
|
|
11
|
+
// Legacy aliases
|
|
12
|
+
ddim: 'DDIM',
|
|
13
|
+
leading: 'Leading',
|
|
14
|
+
linear: 'Linear'
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function isForgeScheduler(scheduler: string): scheduler is ForgeScheduler {
|
|
18
|
+
return scheduler in SupportedForgeSchedulers;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function isRawForgeScheduler(scheduler: string): boolean {
|
|
22
|
+
const schedulers = Object.values(SupportedForgeSchedulers);
|
|
23
|
+
return schedulers.includes(scheduler);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type ForgeScheduler = keyof typeof SupportedForgeSchedulers;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { SupernetType } from '../../ApiClient/WebSocketClient/types';
|
|
2
2
|
import { ControlNetParams } from './ControlNetParams';
|
|
3
3
|
import { TokenType } from '../../types/token';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { ForgeSampler, SupportedForgeSamplers } from './ForgeSamplerParams';
|
|
5
|
+
import { ForgeScheduler, SupportedForgeSchedulers } from './ForgeSchedulerParams';
|
|
6
|
+
import { ComfySampler, SupportedComfySamplers } from './ComfySamplerParams';
|
|
7
|
+
import { ComfyScheduler, SupportedComfySchedulers } from './ComfySchedulerParams';
|
|
6
8
|
|
|
7
9
|
export interface SupportedModel {
|
|
8
10
|
id: string;
|
|
@@ -33,9 +35,18 @@ export interface SizePreset {
|
|
|
33
35
|
aspect: string;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
export type
|
|
38
|
+
export type Sampler = ForgeSampler | ComfySampler;
|
|
37
39
|
|
|
38
|
-
export
|
|
40
|
+
export type Scheduler = ForgeScheduler | ComfyScheduler;
|
|
41
|
+
|
|
42
|
+
export type { ForgeSampler, ForgeScheduler, ComfySampler, ComfyScheduler };
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
SupportedForgeSamplers,
|
|
46
|
+
SupportedForgeSchedulers,
|
|
47
|
+
SupportedComfySamplers,
|
|
48
|
+
SupportedComfySchedulers
|
|
49
|
+
};
|
|
39
50
|
|
|
40
51
|
export type ImageOutputFormat = 'png' | 'jpg';
|
|
41
52
|
export type VideoOutputFormat = 'mp4';
|
|
@@ -152,6 +163,18 @@ export interface VideoProjectParams extends BaseProjectParams {
|
|
|
152
163
|
* Output video height. Only used if `sizePreset` is "custom"
|
|
153
164
|
*/
|
|
154
165
|
height?: number;
|
|
166
|
+
/**
|
|
167
|
+
* ComfyUI sampler for video generation.
|
|
168
|
+
* Uses ComfyUI's native lowercase format: euler, euler_ancestral, dpmpp_2m, etc.
|
|
169
|
+
* Default: euler (or uni_pc for s2v models)
|
|
170
|
+
*/
|
|
171
|
+
sampler?: ComfySampler;
|
|
172
|
+
/**
|
|
173
|
+
* ComfyUI scheduler for video generation.
|
|
174
|
+
* Uses ComfyUI's native lowercase format: simple, normal, karras, sgm_uniform, etc.
|
|
175
|
+
* Default: simple
|
|
176
|
+
*/
|
|
177
|
+
scheduler?: ComfyScheduler;
|
|
155
178
|
/**
|
|
156
179
|
* Output video format. For now only 'mp4' is supported, defaults to 'mp4'.
|
|
157
180
|
*/
|
|
@@ -184,11 +207,13 @@ export interface ImageProjectParams extends BaseProjectParams {
|
|
|
184
207
|
*/
|
|
185
208
|
contextImages?: InputMedia[];
|
|
186
209
|
/**
|
|
187
|
-
*
|
|
210
|
+
* Legacy sampler for non-ComfyUI models (Automatic1111 workers).
|
|
211
|
+
* Not supported for ComfyUI models - use comfySampler instead.
|
|
188
212
|
*/
|
|
189
213
|
sampler?: Sampler;
|
|
190
214
|
/**
|
|
191
|
-
*
|
|
215
|
+
* Legacy scheduler for non-ComfyUI models (Automatic1111 workers).
|
|
216
|
+
* Not supported for ComfyUI models - use comfyScheduler instead.
|
|
192
217
|
*/
|
|
193
218
|
scheduler?: Scheduler;
|
|
194
219
|
/**
|
package/src/index.ts
CHANGED
|
@@ -19,8 +19,10 @@ import {
|
|
|
19
19
|
ProjectParams,
|
|
20
20
|
Sampler,
|
|
21
21
|
Scheduler,
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
SupportedForgeSamplers,
|
|
23
|
+
SupportedForgeSchedulers,
|
|
24
|
+
SupportedComfySamplers,
|
|
25
|
+
SupportedComfySchedulers,
|
|
24
26
|
VideoProjectParams,
|
|
25
27
|
AudioFormat,
|
|
26
28
|
VideoFormat,
|
|
@@ -56,7 +58,16 @@ export type {
|
|
|
56
58
|
VideoWorkflowType
|
|
57
59
|
};
|
|
58
60
|
|
|
59
|
-
export {
|
|
61
|
+
export {
|
|
62
|
+
ApiError,
|
|
63
|
+
CurrentAccount,
|
|
64
|
+
Job,
|
|
65
|
+
Project,
|
|
66
|
+
SupportedComfySchedulers,
|
|
67
|
+
SupportedComfySamplers,
|
|
68
|
+
SupportedForgeSchedulers,
|
|
69
|
+
SupportedForgeSamplers
|
|
70
|
+
};
|
|
60
71
|
|
|
61
72
|
export interface SogniClientConfig {
|
|
62
73
|
/**
|
package/src/lib/RestClient.ts
CHANGED
|
@@ -30,7 +30,21 @@ class RestClient<E extends EventMap = never> extends TypedEventEmitter<E> {
|
|
|
30
30
|
|
|
31
31
|
private async request<T = JSONValue>(url: string, options: RequestInit = {}): Promise<T> {
|
|
32
32
|
const init = await this.auth.authenticateRequest(options);
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
// Add a timeout to detect hanging requests
|
|
35
|
+
const controller = new AbortController();
|
|
36
|
+
const timeoutId = setTimeout(() => {
|
|
37
|
+
controller.abort();
|
|
38
|
+
}, 30000);
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const response = await fetch(url, { ...init, signal: controller.signal });
|
|
42
|
+
clearTimeout(timeoutId);
|
|
43
|
+
return this.processResponse(response) as T;
|
|
44
|
+
} catch (fetchError: any) {
|
|
45
|
+
clearTimeout(timeoutId);
|
|
46
|
+
throw fetchError;
|
|
47
|
+
}
|
|
34
48
|
}
|
|
35
49
|
|
|
36
50
|
private async processResponse(response: Response): Promise<JSONValue> {
|
|
@@ -52,7 +66,7 @@ class RestClient<E extends EventMap = never> extends TypedEventEmitter<E> {
|
|
|
52
66
|
}
|
|
53
67
|
|
|
54
68
|
get<T = JSONValue>(path: string, query: Record<string, any> = {}): Promise<T> {
|
|
55
|
-
return this.request<T>(this.formatUrl(path, query)
|
|
69
|
+
return this.request<T>(this.formatUrl(path, query));
|
|
56
70
|
}
|
|
57
71
|
|
|
58
72
|
post<T = JSONValue>(path: string, body: Record<string, unknown> = {}): Promise<T> {
|
package/src/lib/validation.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
isRawForgeSampler,
|
|
3
|
+
isForgeSampler,
|
|
4
|
+
SupportedForgeSamplers
|
|
5
|
+
} from '../Projects/types/ForgeSamplerParams';
|
|
6
|
+
import {
|
|
7
|
+
isForgeScheduler,
|
|
8
|
+
isRawForgeScheduler,
|
|
9
|
+
SupportedForgeSchedulers
|
|
10
|
+
} from '../Projects/types/ForgeSchedulerParams';
|
|
11
|
+
import { isComfySampler, SupportedComfySamplers } from '../Projects/types/ComfySamplerParams';
|
|
12
|
+
import { isComfyScheduler, SupportedComfySchedulers } from '../Projects/types/ComfySchedulerParams';
|
|
3
13
|
|
|
4
14
|
export function validateCustomImageSize(value: any): number {
|
|
5
15
|
return validateNumber(value, { min: 256, max: 2048, propertyName: 'Width and height' });
|
|
@@ -54,33 +64,33 @@ export function validateNumber(
|
|
|
54
64
|
return number;
|
|
55
65
|
}
|
|
56
66
|
|
|
57
|
-
export function
|
|
67
|
+
export function validateForgeSampler(value?: string) {
|
|
58
68
|
if (!value) {
|
|
59
69
|
return null;
|
|
60
70
|
}
|
|
61
|
-
if (
|
|
71
|
+
if (isRawForgeSampler(value)) {
|
|
62
72
|
return value;
|
|
63
73
|
}
|
|
64
|
-
if (
|
|
65
|
-
return
|
|
74
|
+
if (isForgeSampler(value)) {
|
|
75
|
+
return SupportedForgeSamplers[value];
|
|
66
76
|
}
|
|
67
77
|
throw new Error(
|
|
68
|
-
`Invalid sampler: ${value}. Supported options: ${Object.keys(
|
|
78
|
+
`Invalid sampler: ${value}. Supported options: ${Object.keys(SupportedForgeSamplers).join(', ')}`
|
|
69
79
|
);
|
|
70
80
|
}
|
|
71
81
|
|
|
72
|
-
export function
|
|
82
|
+
export function validateForgeScheduler(value?: string) {
|
|
73
83
|
if (!value) {
|
|
74
84
|
return null;
|
|
75
85
|
}
|
|
76
|
-
if (
|
|
86
|
+
if (isRawForgeScheduler(value)) {
|
|
77
87
|
return value;
|
|
78
88
|
}
|
|
79
|
-
if (
|
|
80
|
-
return
|
|
89
|
+
if (isForgeScheduler(value)) {
|
|
90
|
+
return SupportedForgeSchedulers[value];
|
|
81
91
|
}
|
|
82
92
|
throw new Error(
|
|
83
|
-
`Invalid scheduler: ${value}. Supported options: ${Object.keys(
|
|
93
|
+
`Invalid scheduler: ${value}. Supported options: ${Object.keys(SupportedForgeSchedulers).join(', ')}`
|
|
84
94
|
);
|
|
85
95
|
}
|
|
86
96
|
|
|
@@ -101,3 +111,54 @@ export function validateTeacacheThreshold(value?: number): number | undefined {
|
|
|
101
111
|
}
|
|
102
112
|
return num;
|
|
103
113
|
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Validate ComfyUI sampler for video models.
|
|
117
|
+
* Returns the sampler string directly (no mapping needed).
|
|
118
|
+
*/
|
|
119
|
+
export function validateComfySampler(value?: string): string | undefined {
|
|
120
|
+
if (!value) {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
if (isComfySampler(value)) {
|
|
124
|
+
return SupportedComfySamplers[value];
|
|
125
|
+
}
|
|
126
|
+
throw new Error(
|
|
127
|
+
`Invalid comfySampler: ${value}. Supported options: ${Object.keys(SupportedComfySamplers).join(', ')}`
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Validate ComfyUI scheduler for video models.
|
|
133
|
+
* Returns the scheduler string directly (no mapping needed).
|
|
134
|
+
*/
|
|
135
|
+
export function validateComfyScheduler(value?: string): string | undefined {
|
|
136
|
+
if (!value) {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
if (isComfyScheduler(value)) {
|
|
140
|
+
return SupportedComfySchedulers[value];
|
|
141
|
+
}
|
|
142
|
+
throw new Error(
|
|
143
|
+
`Invalid comfyScheduler: ${value}. Supported options: ${Object.keys(SupportedComfySchedulers).join(', ')}`
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function isComfyModel(modelId: string): boolean {
|
|
148
|
+
const COMFY_PREFIXES = ['z_image_', 'qwen_image_', 'flux2_', 'wan_'];
|
|
149
|
+
return COMFY_PREFIXES.some((prefix) => modelId.startsWith(prefix));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function validateSampler(modelId: string, sampler: string) {
|
|
153
|
+
if (isComfyModel(modelId)) {
|
|
154
|
+
return validateComfySampler(sampler);
|
|
155
|
+
}
|
|
156
|
+
return validateForgeSampler(sampler);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function validateScheduler(modelId: string, scheduler: string) {
|
|
160
|
+
if (isComfyModel(modelId)) {
|
|
161
|
+
return validateComfyScheduler(scheduler);
|
|
162
|
+
}
|
|
163
|
+
return validateForgeScheduler(scheduler);
|
|
164
|
+
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export declare const SupportedSamplers: {
|
|
2
|
-
dfs_sd3: string;
|
|
3
|
-
dpm_pp: string;
|
|
4
|
-
dpm_pp_sde: string;
|
|
5
|
-
dpm_pp_2m: string;
|
|
6
|
-
euler: string;
|
|
7
|
-
euler_a: string;
|
|
8
|
-
lcm: string;
|
|
9
|
-
pndm_plms: string;
|
|
10
|
-
};
|
|
11
|
-
export declare function isSampler(sampler: string): sampler is Sampler;
|
|
12
|
-
export declare function isRawSampler(sampler: string): boolean;
|
|
13
|
-
export type Sampler = keyof typeof SupportedSamplers;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SupportedSamplers = void 0;
|
|
4
|
-
exports.isSampler = isSampler;
|
|
5
|
-
exports.isRawSampler = isRawSampler;
|
|
6
|
-
exports.SupportedSamplers = {
|
|
7
|
-
dfs_sd3: 'Discrete Flow Scheduler (SD3)',
|
|
8
|
-
dpm_pp: 'DPM Solver Multistep (DPM-Solver++)',
|
|
9
|
-
dpm_pp_sde: 'DPM++ SDE',
|
|
10
|
-
dpm_pp_2m: 'DPM++ 2M',
|
|
11
|
-
//dpm_pp_2m_sde: 'DPM++ 2M SDE',
|
|
12
|
-
euler: 'Euler',
|
|
13
|
-
euler_a: 'Euler a',
|
|
14
|
-
//heun: 'Heun',
|
|
15
|
-
lcm: 'LCM (Latent Consistency Model)',
|
|
16
|
-
pndm_plms: 'PNDM (Pseudo-linear multi-step)'
|
|
17
|
-
//uni_pc: 'UniPC'
|
|
18
|
-
};
|
|
19
|
-
function isSampler(sampler) {
|
|
20
|
-
return sampler in exports.SupportedSamplers;
|
|
21
|
-
}
|
|
22
|
-
function isRawSampler(sampler) {
|
|
23
|
-
const samplers = Object.values(exports.SupportedSamplers);
|
|
24
|
-
return samplers.includes(sampler);
|
|
25
|
-
}
|
|
26
|
-
//# sourceMappingURL=SamplerParams.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SamplerParams.js","sourceRoot":"","sources":["../../../src/Projects/types/SamplerParams.ts"],"names":[],"mappings":";;;AAcA,8BAEC;AAED,oCAGC;AArBY,QAAA,iBAAiB,GAAG;IAC/B,OAAO,EAAE,+BAA+B;IACxC,MAAM,EAAE,qCAAqC;IAC7C,UAAU,EAAE,WAAW;IACvB,SAAS,EAAE,UAAU;IACrB,gCAAgC;IAChC,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,eAAe;IACf,GAAG,EAAE,gCAAgC;IACrC,SAAS,EAAE,iCAAiC;IAC5C,iBAAiB;CAClB,CAAC;AAEF,SAAgB,SAAS,CAAC,OAAe;IACvC,OAAO,OAAO,IAAI,yBAAiB,CAAC;AACtC,CAAC;AAED,SAAgB,YAAY,CAAC,OAAe;IAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,yBAAiB,CAAC,CAAC;IAClD,OAAO,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export declare const SupportedSchedulers: {
|
|
2
|
-
beta: string;
|
|
3
|
-
ddim: string;
|
|
4
|
-
karras: string;
|
|
5
|
-
kl_optimal: string;
|
|
6
|
-
leading: string;
|
|
7
|
-
linear: string;
|
|
8
|
-
normal: string;
|
|
9
|
-
sgm_uniform: string;
|
|
10
|
-
simple: string;
|
|
11
|
-
};
|
|
12
|
-
export declare function isScheduler(scheduler: string): scheduler is Scheduler;
|
|
13
|
-
export declare function isRawScheduler(scheduler: string): boolean;
|
|
14
|
-
export type Scheduler = keyof typeof SupportedSchedulers;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SupportedSchedulers = void 0;
|
|
4
|
-
exports.isScheduler = isScheduler;
|
|
5
|
-
exports.isRawScheduler = isRawScheduler;
|
|
6
|
-
exports.SupportedSchedulers = {
|
|
7
|
-
beta: 'Beta',
|
|
8
|
-
ddim: 'DDIM',
|
|
9
|
-
karras: 'Karras',
|
|
10
|
-
kl_optimal: 'KL Optimal',
|
|
11
|
-
leading: 'Leading',
|
|
12
|
-
linear: 'Linear',
|
|
13
|
-
normal: 'Normal',
|
|
14
|
-
sgm_uniform: 'SGM Uniform',
|
|
15
|
-
simple: 'Simple'
|
|
16
|
-
};
|
|
17
|
-
function isScheduler(scheduler) {
|
|
18
|
-
return scheduler in exports.SupportedSchedulers;
|
|
19
|
-
}
|
|
20
|
-
function isRawScheduler(scheduler) {
|
|
21
|
-
const schedulers = Object.values(exports.SupportedSchedulers);
|
|
22
|
-
return schedulers.includes(scheduler);
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=SchedulerParams.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SchedulerParams.js","sourceRoot":"","sources":["../../../src/Projects/types/SchedulerParams.ts"],"names":[],"mappings":";;;AAYA,kCAEC;AAED,wCAGC;AAnBY,QAAA,mBAAmB,GAAG;IACjC,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE,YAAY;IACxB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,WAAW,EAAE,aAAa;IAC1B,MAAM,EAAE,QAAQ;CACjB,CAAC;AAEF,SAAgB,WAAW,CAAC,SAAiB;IAC3C,OAAO,SAAS,IAAI,2BAAmB,CAAC;AAC1C,CAAC;AAED,SAAgB,cAAc,CAAC,SAAiB;IAC9C,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,2BAAmB,CAAC,CAAC;IACtD,OAAO,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export const SupportedSamplers = {
|
|
2
|
-
dfs_sd3: 'Discrete Flow Scheduler (SD3)',
|
|
3
|
-
dpm_pp: 'DPM Solver Multistep (DPM-Solver++)',
|
|
4
|
-
dpm_pp_sde: 'DPM++ SDE',
|
|
5
|
-
dpm_pp_2m: 'DPM++ 2M',
|
|
6
|
-
//dpm_pp_2m_sde: 'DPM++ 2M SDE',
|
|
7
|
-
euler: 'Euler',
|
|
8
|
-
euler_a: 'Euler a',
|
|
9
|
-
//heun: 'Heun',
|
|
10
|
-
lcm: 'LCM (Latent Consistency Model)',
|
|
11
|
-
pndm_plms: 'PNDM (Pseudo-linear multi-step)'
|
|
12
|
-
//uni_pc: 'UniPC'
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export function isSampler(sampler: string): sampler is Sampler {
|
|
16
|
-
return sampler in SupportedSamplers;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function isRawSampler(sampler: string): boolean {
|
|
20
|
-
const samplers = Object.values(SupportedSamplers);
|
|
21
|
-
return samplers.includes(sampler);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export type Sampler = keyof typeof SupportedSamplers;
|