@sogni-ai/sogni-client 4.0.0-alpha.8 → 4.0.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/CHANGELOG.md +275 -0
- package/README.md +263 -31
- package/dist/Account/index.d.ts +18 -16
- package/dist/Account/index.js +31 -20
- 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.js +170 -13
- package/dist/Projects/createJobRequestMessage.js.map +1 -1
- package/dist/Projects/index.d.ts +112 -11
- package/dist/Projects/index.js +473 -45
- package/dist/Projects/index.js.map +1 -1
- package/dist/Projects/types/ComfySamplerParams.d.ts +28 -0
- package/dist/Projects/types/ComfySamplerParams.js +36 -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/EstimationResponse.d.ts +2 -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/events.d.ts +5 -1
- package/dist/Projects/types/index.d.ts +205 -38
- package/dist/Projects/types/index.js +17 -0
- package/dist/Projects/types/index.js.map +1 -1
- package/dist/Projects/utils.d.ts +19 -1
- package/dist/Projects/utils.js +68 -0
- package/dist/Projects/utils.js.map +1 -1
- package/dist/index.d.ts +12 -4
- package/dist/index.js +14 -4
- 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/validation.d.ts +26 -2
- package/dist/lib/validation.js +95 -10
- package/dist/lib/validation.js.map +1 -1
- package/package.json +4 -4
- package/src/Account/index.ts +30 -19
- 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 +222 -35
- package/src/Projects/index.ts +504 -49
- package/src/Projects/types/ComfySamplerParams.ts +34 -0
- package/src/Projects/types/ComfySchedulerParams.ts +21 -0
- package/src/Projects/types/EstimationResponse.ts +2 -0
- package/src/Projects/types/ForgeSamplerParams.ts +37 -0
- package/src/Projects/types/ForgeSchedulerParams.ts +26 -0
- package/src/Projects/types/events.ts +6 -0
- package/src/Projects/types/index.ts +243 -39
- package/src/Projects/utils.ts +66 -1
- package/src/index.ts +60 -8
- 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 +111 -14
- 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/src/Projects/types/SamplerParams.ts +0 -19
- package/src/Projects/types/SchedulerParams.ts +0 -17
|
@@ -1,11 +1,71 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ImageProjectParams,
|
|
3
|
+
isImageParams,
|
|
4
|
+
isVideoParams,
|
|
5
|
+
ProjectParams,
|
|
6
|
+
VideoProjectParams
|
|
7
|
+
} from './types';
|
|
2
8
|
import { ControlNetParams, ControlNetParamsRaw } from './types/ControlNetParams';
|
|
3
9
|
import {
|
|
4
10
|
validateNumber,
|
|
5
11
|
validateCustomImageSize,
|
|
6
|
-
|
|
7
|
-
|
|
12
|
+
validateForgeSampler,
|
|
13
|
+
validateForgeScheduler,
|
|
14
|
+
validateVideoSize,
|
|
15
|
+
validateTeacacheThreshold,
|
|
16
|
+
validateComfySampler,
|
|
17
|
+
validateComfyScheduler,
|
|
18
|
+
isComfyModel,
|
|
19
|
+
validateVideoDuration
|
|
8
20
|
} from '../lib/validation';
|
|
21
|
+
import { getVideoWorkflowType, isVideoModel, VIDEO_WORKFLOW_ASSETS } from './utils';
|
|
22
|
+
import { ApiError } from '../ApiClient';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Validate that the provided assets match the workflow requirements.
|
|
26
|
+
* Throws an error if required assets are missing or forbidden assets are provided.
|
|
27
|
+
*/
|
|
28
|
+
function validateVideoWorkflowAssets(params: VideoProjectParams): void {
|
|
29
|
+
const workflowType = getVideoWorkflowType(params.modelId);
|
|
30
|
+
if (!workflowType) return;
|
|
31
|
+
|
|
32
|
+
const requirements = VIDEO_WORKFLOW_ASSETS[workflowType];
|
|
33
|
+
if (!requirements) return;
|
|
34
|
+
|
|
35
|
+
// Special case for i2v: at least ONE of referenceImage or referenceImageEnd required
|
|
36
|
+
if (workflowType === 'i2v') {
|
|
37
|
+
if (!params.referenceImage && !params.referenceImageEnd) {
|
|
38
|
+
throw new ApiError(400, {
|
|
39
|
+
status: 'error',
|
|
40
|
+
errorCode: 0,
|
|
41
|
+
message:
|
|
42
|
+
'i2v workflow requires at least one of referenceImage or referenceImageEnd. Please provide this asset.'
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Check for missing required assets and forbidden assets
|
|
48
|
+
for (const [asset, requirement] of Object.entries(requirements)) {
|
|
49
|
+
const assetKey = asset as keyof VideoProjectParams;
|
|
50
|
+
const hasAsset = !!params[assetKey];
|
|
51
|
+
|
|
52
|
+
if (requirement === 'required' && !hasAsset) {
|
|
53
|
+
throw new ApiError(400, {
|
|
54
|
+
status: 'error',
|
|
55
|
+
errorCode: 0,
|
|
56
|
+
message: `${workflowType} workflow requires ${assetKey}. Please provide this asset.`
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (requirement === 'forbidden' && hasAsset) {
|
|
61
|
+
throw new ApiError(400, {
|
|
62
|
+
status: 'error',
|
|
63
|
+
errorCode: 0,
|
|
64
|
+
message: `${workflowType} workflow does not support ${assetKey}. Please remove this asset.`
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
9
69
|
|
|
10
70
|
// Mac worker can't process the data if some of the fields are missing, so we need to provide a default template
|
|
11
71
|
function getTemplate() {
|
|
@@ -118,49 +178,176 @@ function getControlNet(params: ControlNetParams): ControlNetParamsRaw[] {
|
|
|
118
178
|
return [cn];
|
|
119
179
|
}
|
|
120
180
|
|
|
181
|
+
function applyImageParams(inputKeyframe: Record<string, any>, params: ImageProjectParams) {
|
|
182
|
+
const keyFrame: Record<string, any> = {
|
|
183
|
+
...inputKeyframe,
|
|
184
|
+
sizePreset: params.sizePreset,
|
|
185
|
+
hasContextImage1: !!params.contextImages?.[0],
|
|
186
|
+
hasContextImage2: !!params.contextImages?.[1],
|
|
187
|
+
hasContextImage3: !!params.contextImages?.[2]
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// Handle sampler/scheduler: ComfyUI models use comfySampler/comfyScheduler,
|
|
191
|
+
// legacy models use sampler/scheduler (mapped to scheduler/timeStepSpacing)
|
|
192
|
+
if (isComfyModel(params.modelId)) {
|
|
193
|
+
if (params.sampler !== undefined) {
|
|
194
|
+
keyFrame.comfySampler = validateComfySampler(params.sampler);
|
|
195
|
+
}
|
|
196
|
+
if (params.scheduler !== undefined) {
|
|
197
|
+
keyFrame.comfyScheduler = validateComfyScheduler(params.scheduler);
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
if (params.sampler !== undefined) {
|
|
201
|
+
keyFrame.scheduler = validateForgeSampler(params.sampler);
|
|
202
|
+
}
|
|
203
|
+
if (params.scheduler !== undefined) {
|
|
204
|
+
keyFrame.timeStepSpacing = validateForgeScheduler(params.scheduler);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (params.startingImage) {
|
|
209
|
+
keyFrame.hasStartingImage = true;
|
|
210
|
+
keyFrame.strengthIsEnabled = true;
|
|
211
|
+
keyFrame.strength = 1 - (Number(params.startingImageStrength) || 0.5);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (params.controlNet) {
|
|
215
|
+
keyFrame.currentControlNetsJob = getControlNet(params.controlNet);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Set sizePreset to 'custom' if width/height are provided but sizePreset is not set
|
|
219
|
+
let effectiveSizePreset = params.sizePreset;
|
|
220
|
+
if (params.width && params.height && !params.sizePreset) {
|
|
221
|
+
effectiveSizePreset = 'custom';
|
|
222
|
+
}
|
|
223
|
+
keyFrame.sizePreset = effectiveSizePreset;
|
|
224
|
+
|
|
225
|
+
if (effectiveSizePreset === 'custom' && params.width && params.height) {
|
|
226
|
+
keyFrame.width = validateCustomImageSize(params.width);
|
|
227
|
+
keyFrame.height = validateCustomImageSize(params.height);
|
|
228
|
+
}
|
|
229
|
+
return keyFrame;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function applyVideoParams(inputKeyframe: Record<string, any>, params: VideoProjectParams) {
|
|
233
|
+
if (!isVideoModel(params.modelId)) {
|
|
234
|
+
throw new ApiError(400, {
|
|
235
|
+
status: 'error',
|
|
236
|
+
errorCode: 0,
|
|
237
|
+
message: 'Video generation is only supported for video models.'
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
validateVideoWorkflowAssets(params);
|
|
241
|
+
const keyFrame: Record<string, any> = { ...inputKeyframe };
|
|
242
|
+
if (params.referenceImage) {
|
|
243
|
+
keyFrame.hasReferenceImage = true;
|
|
244
|
+
}
|
|
245
|
+
if (params.referenceImageEnd) {
|
|
246
|
+
keyFrame.hasReferenceImageEnd = true;
|
|
247
|
+
}
|
|
248
|
+
if (params.referenceAudio) {
|
|
249
|
+
keyFrame.hasReferenceAudio = true;
|
|
250
|
+
}
|
|
251
|
+
if (params.referenceVideo) {
|
|
252
|
+
keyFrame.hasReferenceVideo = true;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Video generation parameters
|
|
256
|
+
if (params.frames !== undefined) {
|
|
257
|
+
keyFrame.frames = params.frames;
|
|
258
|
+
}
|
|
259
|
+
if (params.duration !== undefined) {
|
|
260
|
+
const duration = validateVideoDuration(params.duration);
|
|
261
|
+
keyFrame.frames = duration * 16 + 1;
|
|
262
|
+
}
|
|
263
|
+
if (params.fps !== undefined) {
|
|
264
|
+
keyFrame.fps = params.fps;
|
|
265
|
+
}
|
|
266
|
+
if (params.shift !== undefined) {
|
|
267
|
+
keyFrame.shift = params.shift;
|
|
268
|
+
}
|
|
269
|
+
if (params.teacacheThreshold !== undefined) {
|
|
270
|
+
const validatedThreshold = validateTeacacheThreshold(params.teacacheThreshold);
|
|
271
|
+
if (validatedThreshold !== undefined) {
|
|
272
|
+
keyFrame.teacacheThreshold = validatedThreshold;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// S2V audio parameters
|
|
277
|
+
if (params.audioStart !== undefined) {
|
|
278
|
+
keyFrame.audioStart = params.audioStart;
|
|
279
|
+
}
|
|
280
|
+
if (params.audioDuration !== undefined) {
|
|
281
|
+
keyFrame.audioDuration = params.audioDuration;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Animate video parameters (for animate-move, animate-replace)
|
|
285
|
+
if (params.videoStart !== undefined) {
|
|
286
|
+
keyFrame.videoStart = params.videoStart;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Validate and set video dimensions (minimum 480px for Wan 2.2 models)
|
|
290
|
+
if (params.width && params.height) {
|
|
291
|
+
keyFrame.width = validateVideoSize(params.width, 'width');
|
|
292
|
+
keyFrame.height = validateVideoSize(params.height, 'height');
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Video models are ComfyUI models - only accept comfySampler/comfyScheduler
|
|
296
|
+
// Legacy sampler/scheduler fields are NOT supported for video models
|
|
297
|
+
if (params.sampler !== undefined) {
|
|
298
|
+
keyFrame.comfySampler = validateComfySampler(params.sampler);
|
|
299
|
+
}
|
|
300
|
+
if (params.scheduler !== undefined) {
|
|
301
|
+
keyFrame.comfyScheduler = validateComfyScheduler(params.scheduler);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return keyFrame;
|
|
305
|
+
}
|
|
306
|
+
|
|
121
307
|
function createJobRequestMessage(id: string, params: ProjectParams) {
|
|
122
308
|
const template = getTemplate();
|
|
309
|
+
// Base keyFrame with common params
|
|
310
|
+
let keyFrame: Record<string, any> = {
|
|
311
|
+
...template.keyFrames[0],
|
|
312
|
+
steps: params.steps,
|
|
313
|
+
guidanceScale: params.guidance,
|
|
314
|
+
modelID: params.modelId,
|
|
315
|
+
negativePrompt: params.negativePrompt,
|
|
316
|
+
seed: params.seed,
|
|
317
|
+
positivePrompt: params.positivePrompt,
|
|
318
|
+
stylePrompt: params.stylePrompt
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
switch (params.type) {
|
|
322
|
+
case 'image':
|
|
323
|
+
keyFrame = applyImageParams(keyFrame, params);
|
|
324
|
+
break;
|
|
325
|
+
case 'video':
|
|
326
|
+
keyFrame = applyVideoParams(keyFrame, params);
|
|
327
|
+
break;
|
|
328
|
+
default:
|
|
329
|
+
throw new ApiError(400, {
|
|
330
|
+
status: 'error',
|
|
331
|
+
errorCode: 0,
|
|
332
|
+
message: 'Invalid project type. Must be "image" or "video".'
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
123
336
|
const jobRequest: Record<string, any> = {
|
|
124
337
|
...template,
|
|
125
|
-
keyFrames: [
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
scheduler: validateSampler(params.sampler),
|
|
129
|
-
timeStepSpacing: validateScheduler(params.scheduler),
|
|
130
|
-
steps: params.steps,
|
|
131
|
-
guidanceScale: params.guidance,
|
|
132
|
-
modelID: params.modelId,
|
|
133
|
-
negativePrompt: params.negativePrompt,
|
|
134
|
-
seed: params.seed,
|
|
135
|
-
positivePrompt: params.positivePrompt,
|
|
136
|
-
stylePrompt: params.stylePrompt,
|
|
137
|
-
hasStartingImage: !!params.startingImage,
|
|
138
|
-
hasContextImage1: !!params.contextImages?.[0],
|
|
139
|
-
hasContextImage2: !!params.contextImages?.[1],
|
|
140
|
-
strengthIsEnabled: !!params.startingImage,
|
|
141
|
-
strength: !!params.startingImage
|
|
142
|
-
? 1 - (Number(params.startingImageStrength) || 0.5)
|
|
143
|
-
: undefined,
|
|
144
|
-
sizePreset: params.sizePreset
|
|
145
|
-
}
|
|
146
|
-
],
|
|
147
|
-
previews: params.numberOfPreviews || 0,
|
|
148
|
-
numberOfImages: params.numberOfImages,
|
|
338
|
+
keyFrames: [keyFrame],
|
|
339
|
+
previews: isImageParams(params) ? params.numberOfPreviews || 0 : 0,
|
|
340
|
+
numberOfImages: params.numberOfMedia || 1,
|
|
149
341
|
jobID: id,
|
|
150
342
|
disableSafety: !!params.disableNSFWFilter,
|
|
151
343
|
tokenType: params.tokenType,
|
|
152
|
-
outputFormat: params.outputFormat || 'png'
|
|
344
|
+
outputFormat: params.outputFormat || (isVideoParams(params) ? 'mp4' : 'png')
|
|
153
345
|
};
|
|
346
|
+
|
|
154
347
|
if (params.network) {
|
|
155
348
|
jobRequest.network = params.network;
|
|
156
349
|
}
|
|
157
|
-
|
|
158
|
-
jobRequest.keyFrames[0].currentControlNetsJob = getControlNet(params.controlNet);
|
|
159
|
-
}
|
|
160
|
-
if (params.sizePreset === 'custom') {
|
|
161
|
-
jobRequest.keyFrames[0].width = validateCustomImageSize(params.width);
|
|
162
|
-
jobRequest.keyFrames[0].height = validateCustomImageSize(params.height);
|
|
163
|
-
}
|
|
350
|
+
|
|
164
351
|
return jobRequest;
|
|
165
352
|
}
|
|
166
353
|
|