@sogni-ai/sogni-client 3.0.0-alpha.9 → 3.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 +328 -0
- package/README.md +4 -11
- package/dist/Account/CurrentAccount.d.ts +3 -3
- package/dist/Account/CurrentAccount.js +12 -4
- package/dist/Account/CurrentAccount.js.map +1 -1
- package/dist/Account/index.d.ts +42 -13
- package/dist/Account/index.js +132 -29
- package/dist/Account/index.js.map +1 -1
- package/dist/Account/types.d.ts +21 -0
- package/dist/ApiClient/WebSocketClient/events.d.ts +55 -7
- package/dist/ApiClient/WebSocketClient/index.js +1 -1
- package/dist/ApiClient/index.d.ts +4 -2
- package/dist/ApiClient/index.js +12 -3
- package/dist/ApiClient/index.js.map +1 -1
- package/dist/ApiGroup.d.ts +0 -3
- package/dist/ApiGroup.js +0 -1
- package/dist/ApiGroup.js.map +1 -1
- package/dist/Projects/Job.d.ts +43 -0
- package/dist/Projects/Job.js +76 -0
- package/dist/Projects/Job.js.map +1 -1
- package/dist/Projects/Project.d.ts +1 -1
- package/dist/Projects/Project.js +9 -18
- package/dist/Projects/Project.js.map +1 -1
- package/dist/Projects/createJobRequestMessage.js +1 -1
- package/dist/Projects/createJobRequestMessage.js.map +1 -1
- package/dist/Projects/index.d.ts +7 -2
- package/dist/Projects/index.js +48 -10
- package/dist/Projects/index.js.map +1 -1
- package/dist/Projects/types/ControlNetParams.d.ts +7 -2
- package/dist/Projects/types/events.d.ts +6 -0
- package/dist/Projects/types/index.d.ts +16 -3
- package/dist/Projects/utils.d.ts +2 -0
- package/dist/Projects/utils.js +14 -0
- package/dist/Projects/utils.js.map +1 -0
- package/dist/index.d.ts +10 -6
- package/dist/index.js +6 -15
- package/dist/index.js.map +1 -1
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.js +15 -0
- package/dist/lib/utils.js.map +1 -1
- package/dist/types/token.d.ts +1 -0
- package/dist/types/token.js +3 -0
- package/dist/types/token.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +2 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
- package/src/Account/CurrentAccount.ts +14 -6
- package/src/Account/index.ts +163 -59
- package/src/Account/types.ts +26 -0
- package/src/ApiClient/WebSocketClient/events.ts +59 -7
- package/src/ApiClient/WebSocketClient/index.ts +1 -1
- package/src/ApiClient/index.ts +15 -4
- package/src/ApiGroup.ts +0 -4
- package/src/Projects/Job.ts +98 -0
- package/src/Projects/Project.ts +11 -19
- package/src/Projects/createJobRequestMessage.ts +2 -1
- package/src/Projects/index.ts +53 -13
- package/src/Projects/types/ControlNetParams.ts +8 -2
- package/src/Projects/types/events.ts +6 -0
- package/src/Projects/types/index.ts +17 -3
- package/src/Projects/utils.ts +12 -0
- package/src/Stats/index.ts +2 -2
- package/src/index.ts +23 -19
- package/src/lib/utils.ts +4 -0
- package/src/types/token.ts +1 -0
- package/src/version.ts +2 -1
package/src/Account/types.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { TokenType } from '../types/token';
|
|
2
|
+
|
|
1
3
|
export interface Nonce {
|
|
2
4
|
nonce: string;
|
|
3
5
|
}
|
|
@@ -27,12 +29,22 @@ export interface BalanceData {
|
|
|
27
29
|
credit: string;
|
|
28
30
|
debit: string;
|
|
29
31
|
net: string;
|
|
32
|
+
/**
|
|
33
|
+
* Unclaimed worker earnings amount
|
|
34
|
+
* @experimental Socket messages do not provide this field yet, so it may not be available in all cases.
|
|
35
|
+
*/
|
|
36
|
+
unclaimed?: string;
|
|
30
37
|
}
|
|
31
38
|
|
|
39
|
+
export type Balances = Record<TokenType, BalanceData>;
|
|
40
|
+
|
|
41
|
+
export type FullBalances = Record<TokenType, Required<BalanceData>>;
|
|
42
|
+
|
|
32
43
|
export interface TxHistoryParams {
|
|
33
44
|
status: 'completed';
|
|
34
45
|
address: string;
|
|
35
46
|
limit: number;
|
|
47
|
+
provider?: string;
|
|
36
48
|
offset?: number;
|
|
37
49
|
}
|
|
38
50
|
|
|
@@ -58,6 +70,7 @@ export interface TxRaw {
|
|
|
58
70
|
sourceSID: string;
|
|
59
71
|
endTime: number;
|
|
60
72
|
type: 'debit' | string;
|
|
73
|
+
tokenType: TokenType;
|
|
61
74
|
}
|
|
62
75
|
|
|
63
76
|
export interface TxHistoryEntry {
|
|
@@ -68,6 +81,7 @@ export interface TxHistoryEntry {
|
|
|
68
81
|
status: 'completed';
|
|
69
82
|
role: 'artist' | 'worker';
|
|
70
83
|
amount: number;
|
|
84
|
+
tokenType: TokenType;
|
|
71
85
|
description: string;
|
|
72
86
|
source: 'project' | string;
|
|
73
87
|
endTime: Date;
|
|
@@ -82,20 +96,32 @@ export interface RewardRaw {
|
|
|
82
96
|
title: string;
|
|
83
97
|
description: string;
|
|
84
98
|
amount: string;
|
|
99
|
+
tokenType: TokenType;
|
|
85
100
|
claimed: number;
|
|
86
101
|
canClaim: number;
|
|
87
102
|
lastClaimTimestamp: number;
|
|
88
103
|
claimResetFrequencySec: number;
|
|
89
104
|
}
|
|
90
105
|
|
|
106
|
+
export interface RewardsQuery {
|
|
107
|
+
provider?: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
91
110
|
export interface Reward {
|
|
92
111
|
id: string;
|
|
93
112
|
type: RewardType;
|
|
94
113
|
title: string;
|
|
95
114
|
description: string;
|
|
96
115
|
amount: string;
|
|
116
|
+
tokenType: TokenType;
|
|
97
117
|
claimed: boolean;
|
|
98
118
|
canClaim: boolean;
|
|
99
119
|
lastClaim: Date;
|
|
100
120
|
nextClaim: Date | null;
|
|
121
|
+
provider?: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface ClaimOptions {
|
|
125
|
+
turnstileToken?: string;
|
|
126
|
+
provider?: string;
|
|
101
127
|
}
|
|
@@ -1,11 +1,36 @@
|
|
|
1
1
|
import { SupernetType } from './types';
|
|
2
|
+
import { Balances } from '../../Account/types';
|
|
2
3
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
export interface AuthenticatedData {
|
|
5
|
+
id: string;
|
|
6
|
+
clientType: 'artist' | 'worker';
|
|
7
|
+
username: string;
|
|
8
|
+
address: string;
|
|
9
|
+
SID: number;
|
|
10
|
+
clientSID: number;
|
|
11
|
+
addressSID: number;
|
|
12
|
+
balanceVersion: 2;
|
|
13
|
+
tokens: {
|
|
14
|
+
sogni: {
|
|
15
|
+
settled: string;
|
|
16
|
+
credit: string;
|
|
17
|
+
debit: string;
|
|
18
|
+
net: string;
|
|
19
|
+
};
|
|
20
|
+
spark: {
|
|
21
|
+
settled: string;
|
|
22
|
+
credit: string;
|
|
23
|
+
debit: string;
|
|
24
|
+
net: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
activeProjects: [];
|
|
28
|
+
unclaimedCompletedProjects: [];
|
|
29
|
+
isMainnet: boolean;
|
|
30
|
+
accountWasMigrated: boolean;
|
|
31
|
+
hasUnclaimedAirdrop: boolean;
|
|
32
|
+
firstLoginAfterMigration: boolean;
|
|
33
|
+
}
|
|
9
34
|
|
|
10
35
|
export type JobErrorData = {
|
|
11
36
|
jobID: string;
|
|
@@ -38,6 +63,9 @@ export type JobStateData =
|
|
|
38
63
|
jobID: string;
|
|
39
64
|
imgID: string;
|
|
40
65
|
workerName: string;
|
|
66
|
+
positivePrompt?: string;
|
|
67
|
+
negativePrompt?: string;
|
|
68
|
+
jobIndex?: number;
|
|
41
69
|
}
|
|
42
70
|
| {
|
|
43
71
|
jobID: string;
|
|
@@ -58,11 +86,29 @@ export type ServerDisconnectData = {
|
|
|
58
86
|
reason: string;
|
|
59
87
|
};
|
|
60
88
|
|
|
89
|
+
export type ToastMessage = {
|
|
90
|
+
type: 'info' | 'success' | 'warning' | 'error';
|
|
91
|
+
message: string;
|
|
92
|
+
// Number of milliseconds to show the toast
|
|
93
|
+
autoClose: number;
|
|
94
|
+
stickyID: string;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export type ArtistCancelConfirmation = {
|
|
98
|
+
didCancel: boolean;
|
|
99
|
+
error_message: string;
|
|
100
|
+
jobID: string;
|
|
101
|
+
};
|
|
102
|
+
|
|
61
103
|
export type SocketEventMap = {
|
|
104
|
+
/**
|
|
105
|
+
* @event WebSocketClient#authenticated - Received after successful connection to the WebSocket server
|
|
106
|
+
*/
|
|
107
|
+
authenticated: AuthenticatedData;
|
|
62
108
|
/**
|
|
63
109
|
* @event WebSocketClient#balanceUpdate - Received balance update
|
|
64
110
|
*/
|
|
65
|
-
balanceUpdate:
|
|
111
|
+
balanceUpdate: Balances;
|
|
66
112
|
/**
|
|
67
113
|
* @event WebSocketClient#changeNetwork - Default network changed
|
|
68
114
|
*/
|
|
@@ -95,4 +141,10 @@ export type SocketEventMap = {
|
|
|
95
141
|
* @event WebSocketClient#disconnected - WebSocket connection was closed
|
|
96
142
|
*/
|
|
97
143
|
disconnected: ServerDisconnectData;
|
|
144
|
+
/**
|
|
145
|
+
* @event WebSocketClient#toastMessage - Toast message received
|
|
146
|
+
*/
|
|
147
|
+
toastMessage: ToastMessage;
|
|
148
|
+
|
|
149
|
+
artistCancelConfirmation: ArtistCancelConfirmation;
|
|
98
150
|
};
|
|
@@ -9,7 +9,7 @@ import { LIB_VERSION } from '../../version';
|
|
|
9
9
|
import { Logger } from '../../lib/DefaultLogger';
|
|
10
10
|
import AuthManager from '../../lib/AuthManager';
|
|
11
11
|
|
|
12
|
-
const PROTOCOL_VERSION = '0.
|
|
12
|
+
const PROTOCOL_VERSION = '3.0.0';
|
|
13
13
|
|
|
14
14
|
const PING_INTERVAL = 15000;
|
|
15
15
|
|
package/src/ApiClient/index.ts
CHANGED
|
@@ -11,7 +11,7 @@ import AuthManager, { Tokens } from '../lib/AuthManager';
|
|
|
11
11
|
|
|
12
12
|
const WS_RECONNECT_ATTEMPTS = 5;
|
|
13
13
|
|
|
14
|
-
export interface
|
|
14
|
+
export interface ApiResponse<D = JSONValue> {
|
|
15
15
|
status: 'success';
|
|
16
16
|
data: D;
|
|
17
17
|
}
|
|
@@ -40,13 +40,15 @@ class ApiClient extends TypedEventEmitter<ApiClientEvents> {
|
|
|
40
40
|
private _socket: WebSocketClient;
|
|
41
41
|
private _auth: AuthManager;
|
|
42
42
|
private _reconnectAttempts = WS_RECONNECT_ATTEMPTS;
|
|
43
|
+
private _disableSocket: boolean = false;
|
|
43
44
|
|
|
44
45
|
constructor(
|
|
45
46
|
baseUrl: string,
|
|
46
47
|
socketUrl: string,
|
|
47
48
|
appId: string,
|
|
48
49
|
networkType: SupernetType,
|
|
49
|
-
logger: Logger
|
|
50
|
+
logger: Logger,
|
|
51
|
+
disableSocket: boolean = false
|
|
50
52
|
) {
|
|
51
53
|
super();
|
|
52
54
|
this.appId = appId;
|
|
@@ -54,6 +56,7 @@ class ApiClient extends TypedEventEmitter<ApiClientEvents> {
|
|
|
54
56
|
this._auth = new AuthManager(baseUrl, logger);
|
|
55
57
|
this._rest = new RestClient(baseUrl, this._auth, logger);
|
|
56
58
|
this._socket = new WebSocketClient(socketUrl, this._auth, appId, networkType, logger);
|
|
59
|
+
this._disableSocket = disableSocket;
|
|
57
60
|
|
|
58
61
|
this._auth.on('refreshFailed', this.handleRefreshFailed.bind(this));
|
|
59
62
|
this._socket.on('connected', this.handleSocketConnect.bind(this));
|
|
@@ -76,14 +79,22 @@ class ApiClient extends TypedEventEmitter<ApiClientEvents> {
|
|
|
76
79
|
return this._rest;
|
|
77
80
|
}
|
|
78
81
|
|
|
82
|
+
get socketEnabled(): boolean {
|
|
83
|
+
return !this._disableSocket;
|
|
84
|
+
}
|
|
85
|
+
|
|
79
86
|
async authenticate(tokens: Tokens) {
|
|
80
87
|
await this.auth.setTokens(tokens);
|
|
81
|
-
|
|
88
|
+
if (!this._disableSocket) {
|
|
89
|
+
await this.socket.connect();
|
|
90
|
+
}
|
|
82
91
|
}
|
|
83
92
|
|
|
84
93
|
removeAuth() {
|
|
85
94
|
this.auth.clear();
|
|
86
|
-
this.socket.
|
|
95
|
+
if (this.socket.isConnected) {
|
|
96
|
+
this.socket.disconnect();
|
|
97
|
+
}
|
|
87
98
|
}
|
|
88
99
|
|
|
89
100
|
handleSocketConnect({ network }: ServerConnectData) {
|
package/src/ApiGroup.ts
CHANGED
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
import { AbstractProvider } from 'ethers';
|
|
2
1
|
import ApiClient from './ApiClient';
|
|
3
2
|
import EIP712Helper from './lib/EIP712Helper';
|
|
4
3
|
import TypedEventEmitter, { EventMap } from './lib/TypedEventEmitter';
|
|
5
4
|
|
|
6
5
|
export interface ApiConfig {
|
|
7
6
|
client: ApiClient;
|
|
8
|
-
provider: AbstractProvider;
|
|
9
7
|
eip712: EIP712Helper;
|
|
10
8
|
}
|
|
11
9
|
|
|
12
10
|
abstract class ApiGroup<E extends EventMap = {}> extends TypedEventEmitter<E> {
|
|
13
11
|
protected client: ApiClient;
|
|
14
|
-
protected provider: AbstractProvider;
|
|
15
12
|
protected eip712: EIP712Helper;
|
|
16
13
|
|
|
17
14
|
constructor(config: ApiConfig) {
|
|
18
15
|
super();
|
|
19
16
|
this.client = config.client;
|
|
20
|
-
this.provider = config.provider;
|
|
21
17
|
this.eip712 = config.eip712;
|
|
22
18
|
}
|
|
23
19
|
}
|
package/src/Projects/Job.ts
CHANGED
|
@@ -4,6 +4,24 @@ import { RawJob, RawProject } from './types/RawProject';
|
|
|
4
4
|
import ProjectsApi from './index';
|
|
5
5
|
import { Logger } from '../lib/DefaultLogger';
|
|
6
6
|
import getUUID from '../lib/getUUID';
|
|
7
|
+
import { EnhancementStrength } from './types';
|
|
8
|
+
import Project from './Project';
|
|
9
|
+
import { SupernetType } from '../ApiClient/WebSocketClient/types';
|
|
10
|
+
import { getEnhacementStrength } from './utils';
|
|
11
|
+
import { TokenType } from '../types/token';
|
|
12
|
+
|
|
13
|
+
export const enhancementDefaults = {
|
|
14
|
+
network: 'fast' as SupernetType,
|
|
15
|
+
modelId: 'flux1-schnell-fp8',
|
|
16
|
+
positivePrompt: '',
|
|
17
|
+
negativePrompt: '',
|
|
18
|
+
stylePrompt: '',
|
|
19
|
+
startingImageStrength: 0.5,
|
|
20
|
+
steps: 5,
|
|
21
|
+
guidance: 1,
|
|
22
|
+
numberOfImages: 1,
|
|
23
|
+
numberOfPreviews: 0
|
|
24
|
+
};
|
|
7
25
|
|
|
8
26
|
export type JobStatus =
|
|
9
27
|
| 'pending'
|
|
@@ -40,6 +58,9 @@ export interface JobData {
|
|
|
40
58
|
previewUrl?: string;
|
|
41
59
|
resultUrl?: string | null;
|
|
42
60
|
error?: ErrorData;
|
|
61
|
+
positivePrompt?: string;
|
|
62
|
+
negativePrompt?: string;
|
|
63
|
+
jobIndex?: number;
|
|
43
64
|
}
|
|
44
65
|
|
|
45
66
|
export interface JobEventMap extends EntityEvents {
|
|
@@ -51,6 +72,7 @@ export interface JobEventMap extends EntityEvents {
|
|
|
51
72
|
export interface JobOptions {
|
|
52
73
|
api: ProjectsApi;
|
|
53
74
|
logger: Logger;
|
|
75
|
+
project: Project;
|
|
54
76
|
}
|
|
55
77
|
|
|
56
78
|
class Job extends DataEntity<JobData, JobEventMap> {
|
|
@@ -72,14 +94,18 @@ class Job extends DataEntity<JobData, JobEventMap> {
|
|
|
72
94
|
|
|
73
95
|
private readonly _api: ProjectsApi;
|
|
74
96
|
private readonly _logger: Logger;
|
|
97
|
+
private readonly _project: Project;
|
|
98
|
+
private _enhancementProject: Project | null = null;
|
|
75
99
|
|
|
76
100
|
constructor(data: JobData, options: JobOptions) {
|
|
77
101
|
super(data);
|
|
78
102
|
|
|
79
103
|
this._api = options.api;
|
|
80
104
|
this._logger = options.logger;
|
|
105
|
+
this._project = options.project;
|
|
81
106
|
|
|
82
107
|
this.on('updated', this.handleUpdated.bind(this));
|
|
108
|
+
this.handleEnhancementUpdate = this.handleEnhancementUpdate.bind(this);
|
|
83
109
|
}
|
|
84
110
|
|
|
85
111
|
get id() {
|
|
@@ -152,6 +178,25 @@ class Job extends DataEntity<JobData, JobEventMap> {
|
|
|
152
178
|
return this.data.error;
|
|
153
179
|
}
|
|
154
180
|
|
|
181
|
+
get hasResultImage() {
|
|
182
|
+
return this.status === 'completed' && !this.isNSFW;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
get enhancedImage() {
|
|
186
|
+
if (!this._enhancementProject) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
const project = this._enhancementProject;
|
|
190
|
+
const job = project.jobs[0];
|
|
191
|
+
return {
|
|
192
|
+
status: project.status,
|
|
193
|
+
progress: project.progress,
|
|
194
|
+
result: job?.resultUrl || null,
|
|
195
|
+
error: project.error,
|
|
196
|
+
getResultUrl: () => job?.getResultUrl()
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
155
200
|
/**
|
|
156
201
|
* Get the result URL of the job. This method will make a request to the API to get signed URL.
|
|
157
202
|
* IMPORTANT: URL expires after 30 minutes, so make sure to download the image as soon as possible.
|
|
@@ -225,6 +270,59 @@ class Job extends DataEntity<JobData, JobEventMap> {
|
|
|
225
270
|
this.emit('failed', this.data.error!);
|
|
226
271
|
}
|
|
227
272
|
}
|
|
273
|
+
|
|
274
|
+
private handleEnhancementUpdate() {
|
|
275
|
+
this.emit('updated', ['enhancedImage']);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
async getResultData() {
|
|
279
|
+
if (!this.hasResultImage) {
|
|
280
|
+
throw new Error('No result image available');
|
|
281
|
+
}
|
|
282
|
+
const url = await this.getResultUrl();
|
|
283
|
+
const response = await fetch(url);
|
|
284
|
+
if (!response.ok) {
|
|
285
|
+
throw new Error(`Failed to fetch image: ${response.statusText}`);
|
|
286
|
+
}
|
|
287
|
+
return response.blob();
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Enhance the image using the Flux model. This method will create a new project with the
|
|
292
|
+
* enhancement parameters and use the result image of the current job as the starting image.
|
|
293
|
+
* @param strength - how much freedom the model has to change the image.
|
|
294
|
+
* @param overrides - optional parameters to override original prompt, style or token type.
|
|
295
|
+
*/
|
|
296
|
+
async enhance(
|
|
297
|
+
strength: EnhancementStrength,
|
|
298
|
+
overrides: { positivePrompt?: string; stylePrompt?: string; tokenType?: TokenType } = {}
|
|
299
|
+
) {
|
|
300
|
+
if (this.status !== 'completed') {
|
|
301
|
+
throw new Error('Job is not completed yet');
|
|
302
|
+
}
|
|
303
|
+
if (this.isNSFW) {
|
|
304
|
+
throw new Error('Job did not pass NSFW filter');
|
|
305
|
+
}
|
|
306
|
+
if (this._enhancementProject) {
|
|
307
|
+
this._enhancementProject.off('updated', this.handleEnhancementUpdate);
|
|
308
|
+
this._enhancementProject = null;
|
|
309
|
+
}
|
|
310
|
+
const imageData = await this.getResultData();
|
|
311
|
+
const project = await this._api.create({
|
|
312
|
+
...enhancementDefaults,
|
|
313
|
+
positivePrompt: overrides.positivePrompt || this._project.params.positivePrompt,
|
|
314
|
+
stylePrompt: overrides.stylePrompt || this._project.params.stylePrompt,
|
|
315
|
+
tokenType: overrides.tokenType || this._project.params.tokenType,
|
|
316
|
+
seed: this.seed || this._project.params.seed,
|
|
317
|
+
startingImage: imageData,
|
|
318
|
+
startingImageStrength: 1 - getEnhacementStrength(strength),
|
|
319
|
+
sizePreset: this._project.params.sizePreset
|
|
320
|
+
});
|
|
321
|
+
this._enhancementProject = project;
|
|
322
|
+
this._enhancementProject.on('updated', this.handleEnhancementUpdate);
|
|
323
|
+
const images = await project.waitForCompletion();
|
|
324
|
+
return images[0];
|
|
325
|
+
}
|
|
228
326
|
}
|
|
229
327
|
|
|
230
328
|
export default Job;
|
package/src/Projects/Project.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Job, { JobData
|
|
1
|
+
import Job, { JobData } from './Job';
|
|
2
2
|
import DataEntity, { EntityEvents } from '../lib/DataEntity';
|
|
3
3
|
import { ProjectParams } from './types';
|
|
4
4
|
import cloneDeep from 'lodash/cloneDeep';
|
|
@@ -50,6 +50,7 @@ export interface ProjectEventMap extends EntityEvents {
|
|
|
50
50
|
progress: number;
|
|
51
51
|
completed: string[];
|
|
52
52
|
failed: ErrorData;
|
|
53
|
+
jobStarted: Job;
|
|
53
54
|
jobCompleted: Job;
|
|
54
55
|
jobFailed: Job;
|
|
55
56
|
}
|
|
@@ -209,37 +210,24 @@ class Project extends DataEntity<ProjectData, ProjectEventMap> {
|
|
|
209
210
|
*/
|
|
210
211
|
_addJob(data: JobData | Job) {
|
|
211
212
|
const job =
|
|
212
|
-
data instanceof Job
|
|
213
|
+
data instanceof Job
|
|
214
|
+
? data
|
|
215
|
+
: new Job(data, { api: this._api, logger: this._logger, project: this });
|
|
213
216
|
this._jobs.push(job);
|
|
214
217
|
job.on('updated', () => {
|
|
215
218
|
this.lastUpdated = new Date();
|
|
216
219
|
this.emit('updated', ['jobs']);
|
|
217
220
|
});
|
|
221
|
+
this.emit('jobStarted', job);
|
|
218
222
|
job.on('completed', () => {
|
|
219
223
|
this.emit('jobCompleted', job);
|
|
220
|
-
this._handleJobFinished(job);
|
|
221
224
|
});
|
|
222
225
|
job.on('failed', () => {
|
|
223
226
|
this.emit('jobFailed', job);
|
|
224
|
-
this._handleJobFinished(job);
|
|
225
227
|
});
|
|
226
228
|
return job;
|
|
227
229
|
}
|
|
228
230
|
|
|
229
|
-
private _handleJobFinished(job: Job) {
|
|
230
|
-
const finalStatus: JobStatus[] = ['completed', 'failed', 'canceled'];
|
|
231
|
-
const allJobsDone = this.jobs.every((job) => finalStatus.includes(job.status));
|
|
232
|
-
// If all jobs are done and project is not already failed or completed, update the project status
|
|
233
|
-
if (allJobsDone && this.status !== 'failed' && this.status !== 'completed') {
|
|
234
|
-
const allJobsFailed = this.jobs.every((job) => job.status === 'failed');
|
|
235
|
-
if (allJobsFailed) {
|
|
236
|
-
this._update({ status: 'failed' });
|
|
237
|
-
} else {
|
|
238
|
-
this._update({ status: 'completed' });
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
231
|
private _checkForTimeout() {
|
|
244
232
|
if (this.lastUpdated.getTime() + PROJECT_TIMEOUT < Date.now()) {
|
|
245
233
|
this._syncToServer().catch((error) => {
|
|
@@ -298,7 +286,11 @@ class Project extends DataEntity<ProjectData, ProjectEventMap> {
|
|
|
298
286
|
// If there are any jobs left in jobData, it means they are new jobs that are not in the project yet
|
|
299
287
|
if (Object.keys(jobData).length) {
|
|
300
288
|
for (const job of Object.values(jobData)) {
|
|
301
|
-
const jobInstance = Job.fromRaw(data, job, {
|
|
289
|
+
const jobInstance = Job.fromRaw(data, job, {
|
|
290
|
+
api: this._api,
|
|
291
|
+
logger: this._logger,
|
|
292
|
+
project: this
|
|
293
|
+
});
|
|
302
294
|
this._addJob(jobInstance);
|
|
303
295
|
}
|
|
304
296
|
}
|
|
@@ -139,7 +139,8 @@ function createJobRequestMessage(id: string, params: ProjectParams) {
|
|
|
139
139
|
previews: params.numberOfPreviews || 0,
|
|
140
140
|
numberOfImages: params.numberOfImages,
|
|
141
141
|
jobID: id,
|
|
142
|
-
disableSafety: !!params.disableNSFWFilter
|
|
142
|
+
disableSafety: !!params.disableNSFWFilter,
|
|
143
|
+
tokenType: params.tokenType
|
|
143
144
|
};
|
|
144
145
|
if (params.network) {
|
|
145
146
|
jobRequest.network = params.network;
|
package/src/Projects/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ApiGroup, { ApiConfig } from '../ApiGroup';
|
|
2
2
|
import {
|
|
3
3
|
AvailableModel,
|
|
4
|
+
EnhancementStrength,
|
|
4
5
|
EstimateRequest,
|
|
5
6
|
ImageUrlParams,
|
|
6
7
|
ProjectParams,
|
|
@@ -16,7 +17,7 @@ import {
|
|
|
16
17
|
} from '../ApiClient/WebSocketClient/events';
|
|
17
18
|
import Project from './Project';
|
|
18
19
|
import createJobRequestMessage from './createJobRequestMessage';
|
|
19
|
-
import { ApiError,
|
|
20
|
+
import { ApiError, ApiResponse } from '../ApiClient';
|
|
20
21
|
import { EstimationResponse } from './types/EstimationResponse';
|
|
21
22
|
import { JobEvent, ProjectApiEvents, ProjectEvent } from './types/events';
|
|
22
23
|
import getUUID from '../lib/getUUID';
|
|
@@ -24,6 +25,9 @@ import { RawProject } from './types/RawProject';
|
|
|
24
25
|
import ErrorData from '../types/ErrorData';
|
|
25
26
|
import { SupernetType } from '../ApiClient/WebSocketClient/types';
|
|
26
27
|
import Cache from '../lib/Cache';
|
|
28
|
+
import { enhancementDefaults } from './Job';
|
|
29
|
+
import { getEnhacementStrength } from './utils';
|
|
30
|
+
import { TokenType } from '../types/token';
|
|
27
31
|
|
|
28
32
|
const sizePresetCache = new Cache<SizePreset[]>(10 * 60 * 1000);
|
|
29
33
|
const GARBAGE_COLLECT_TIMEOUT = 30000;
|
|
@@ -67,7 +71,7 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
67
71
|
this.client.socket.on('jobProgress', this.handleJobProgress.bind(this));
|
|
68
72
|
this.client.socket.on('jobError', this.handleJobError.bind(this));
|
|
69
73
|
this.client.socket.on('jobResult', this.handleJobResult.bind(this));
|
|
70
|
-
// Listen to server disconnect event
|
|
74
|
+
// Listen to the server disconnect event
|
|
71
75
|
this.client.on('disconnected', this.handleServerDisconnected.bind(this));
|
|
72
76
|
// Listen to project and job events and update project and job instances
|
|
73
77
|
this.on('project', this.handleProjectEvent.bind(this));
|
|
@@ -115,7 +119,10 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
115
119
|
type: 'initiating',
|
|
116
120
|
projectId: data.jobID,
|
|
117
121
|
jobId: data.imgID,
|
|
118
|
-
workerName: data.workerName
|
|
122
|
+
workerName: data.workerName,
|
|
123
|
+
positivePrompt: data.positivePrompt,
|
|
124
|
+
negativePrompt: data.negativePrompt,
|
|
125
|
+
jobIndex: data.jobIndex
|
|
119
126
|
});
|
|
120
127
|
return;
|
|
121
128
|
case 'jobStarted': {
|
|
@@ -123,7 +130,10 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
123
130
|
type: 'started',
|
|
124
131
|
projectId: data.jobID,
|
|
125
132
|
jobId: data.imgID,
|
|
126
|
-
workerName: data.workerName
|
|
133
|
+
workerName: data.workerName,
|
|
134
|
+
positivePrompt: data.positivePrompt,
|
|
135
|
+
negativePrompt: data.negativePrompt,
|
|
136
|
+
jobIndex: data.jobIndex
|
|
127
137
|
});
|
|
128
138
|
return;
|
|
129
139
|
}
|
|
@@ -263,15 +273,30 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
263
273
|
}
|
|
264
274
|
switch (event.type) {
|
|
265
275
|
case 'initiating':
|
|
266
|
-
|
|
276
|
+
// positivePrompt and negativePrompt are only received if a Dynamic Prompt was used for the project creating a different prompt for each job
|
|
277
|
+
job._update({
|
|
278
|
+
status: 'initiating',
|
|
279
|
+
workerName: event.workerName,
|
|
280
|
+
positivePrompt: event.positivePrompt,
|
|
281
|
+
negativePrompt: event.negativePrompt,
|
|
282
|
+
jobIndex: event.jobIndex
|
|
283
|
+
});
|
|
267
284
|
break;
|
|
268
285
|
case 'started':
|
|
269
|
-
|
|
286
|
+
// positivePrompt and negativePrompt are only received if a Dynamic Prompt was used for the project creating a different prompt for each job
|
|
287
|
+
job._update({
|
|
288
|
+
status: 'processing',
|
|
289
|
+
workerName: event.workerName,
|
|
290
|
+
positivePrompt: event.positivePrompt,
|
|
291
|
+
negativePrompt: event.negativePrompt,
|
|
292
|
+
jobIndex: event.jobIndex
|
|
293
|
+
});
|
|
270
294
|
break;
|
|
271
295
|
case 'progress':
|
|
272
296
|
job._update({
|
|
273
297
|
status: 'processing',
|
|
274
|
-
|
|
298
|
+
// Jus in case event comes out of order
|
|
299
|
+
step: Math.max(event.step, job.step),
|
|
275
300
|
stepCount: event.stepCount
|
|
276
301
|
});
|
|
277
302
|
if (project.status !== 'processing') {
|
|
@@ -337,10 +362,10 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
337
362
|
*/
|
|
338
363
|
async create(data: ProjectParams): Promise<Project> {
|
|
339
364
|
const project = new Project({ ...data }, { api: this, logger: this.client.logger });
|
|
340
|
-
if (data.startingImage) {
|
|
365
|
+
if (data.startingImage && data.startingImage !== true) {
|
|
341
366
|
await this.uploadGuideImage(project.id, data.startingImage);
|
|
342
367
|
}
|
|
343
|
-
if (data.controlNet?.image) {
|
|
368
|
+
if (data.controlNet?.image && data.controlNet.image !== true) {
|
|
344
369
|
await this.uploadCNImage(project.id, data.controlNet.image);
|
|
345
370
|
}
|
|
346
371
|
const request = createJobRequestMessage(project.id, data);
|
|
@@ -356,7 +381,7 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
356
381
|
* @param projectId
|
|
357
382
|
*/
|
|
358
383
|
async get(projectId: string) {
|
|
359
|
-
const { data } = await this.client.rest.get<
|
|
384
|
+
const { data } = await this.client.rest.get<ApiResponse<{ project: RawProject }>>(
|
|
360
385
|
`/v1/projects/${projectId}`
|
|
361
386
|
);
|
|
362
387
|
return data.project;
|
|
@@ -441,6 +466,7 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
441
466
|
*/
|
|
442
467
|
async estimateCost({
|
|
443
468
|
network,
|
|
469
|
+
tokenType,
|
|
444
470
|
model,
|
|
445
471
|
imageCount,
|
|
446
472
|
stepCount,
|
|
@@ -452,6 +478,7 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
452
478
|
sizePreset
|
|
453
479
|
}: EstimateRequest) {
|
|
454
480
|
const pathParams = [
|
|
481
|
+
tokenType || 'sogni',
|
|
455
482
|
network,
|
|
456
483
|
model,
|
|
457
484
|
imageCount,
|
|
@@ -471,7 +498,7 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
471
498
|
pathParams.push(width, height);
|
|
472
499
|
}
|
|
473
500
|
const r = await this.client.socket.get<EstimationResponse>(
|
|
474
|
-
`/api/
|
|
501
|
+
`/api/v2/job/estimate/${pathParams.join('/')}`
|
|
475
502
|
);
|
|
476
503
|
return {
|
|
477
504
|
token: r.quote.project.costInToken,
|
|
@@ -479,13 +506,26 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
479
506
|
};
|
|
480
507
|
}
|
|
481
508
|
|
|
509
|
+
async estimateEnhancementCost(strength: EnhancementStrength, tokenType: TokenType = 'sogni') {
|
|
510
|
+
return this.estimateCost({
|
|
511
|
+
network: enhancementDefaults.network,
|
|
512
|
+
tokenType,
|
|
513
|
+
model: enhancementDefaults.modelId,
|
|
514
|
+
imageCount: 1,
|
|
515
|
+
stepCount: enhancementDefaults.steps,
|
|
516
|
+
previewCount: 0,
|
|
517
|
+
cnEnabled: false,
|
|
518
|
+
startingImageStrength: getEnhacementStrength(strength)
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
|
|
482
522
|
/**
|
|
483
523
|
* Get upload URL for image
|
|
484
524
|
* @internal
|
|
485
525
|
* @param params
|
|
486
526
|
*/
|
|
487
527
|
async uploadUrl(params: ImageUrlParams) {
|
|
488
|
-
const r = await this.client.rest.get<
|
|
528
|
+
const r = await this.client.rest.get<ApiResponse<{ uploadUrl: string }>>(
|
|
489
529
|
`/v1/image/uploadUrl`,
|
|
490
530
|
params
|
|
491
531
|
);
|
|
@@ -498,7 +538,7 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
|
|
|
498
538
|
* @param params
|
|
499
539
|
*/
|
|
500
540
|
async downloadUrl(params: ImageUrlParams) {
|
|
501
|
-
const r = await this.client.rest.get<
|
|
541
|
+
const r = await this.client.rest.get<ApiResponse<{ downloadUrl: string }>>(
|
|
502
542
|
`/v1/image/downloadUrl`,
|
|
503
543
|
params
|
|
504
544
|
);
|
|
@@ -16,7 +16,8 @@ export type ControlNetName =
|
|
|
16
16
|
| 'segmentation'
|
|
17
17
|
| 'shuffle'
|
|
18
18
|
| 'softedge'
|
|
19
|
-
| 'tile'
|
|
19
|
+
| 'tile'
|
|
20
|
+
| 'instantid';
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* Raw ControlNet parameters passed to the API
|
|
@@ -53,8 +54,13 @@ export interface ControlNetParams {
|
|
|
53
54
|
name: ControlNetName;
|
|
54
55
|
/**
|
|
55
56
|
* ControlNet input image
|
|
57
|
+
* Supported types:
|
|
58
|
+
* `File` - file object from input[type=file]
|
|
59
|
+
* `Buffer` - Node.js buffer object with image data
|
|
60
|
+
* `Blob` - blob object with image data
|
|
61
|
+
* `true` - indicates that the image is already uploaded to the server
|
|
56
62
|
*/
|
|
57
|
-
image?: File | Buffer | Blob;
|
|
63
|
+
image?: File | Buffer | Blob | boolean;
|
|
58
64
|
/**
|
|
59
65
|
* ControlNet strength 0 to 1. 0 full control to prompt, 1 full control to ControlNet
|
|
60
66
|
*/
|