@sogni-ai/sogni-client 4.2.0-alpha.2 → 4.2.0-alpha.21
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 +148 -0
- package/CLAUDE.md +25 -3
- package/README.md +411 -136
- package/dist/Account/index.d.ts +4 -2
- package/dist/Account/index.js +27 -23
- package/dist/Account/index.js.map +1 -1
- package/dist/Account/types.d.ts +7 -0
- package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.d.ts +3 -1
- package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js +26 -2
- package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js.map +1 -1
- package/dist/ApiClient/WebSocketClient/eventSubscriptions.d.ts +33 -0
- package/dist/ApiClient/WebSocketClient/eventSubscriptions.js +39 -0
- package/dist/ApiClient/WebSocketClient/eventSubscriptions.js.map +1 -0
- package/dist/ApiClient/WebSocketClient/events.d.ts +24 -7
- package/dist/ApiClient/WebSocketClient/index.d.ts +5 -1
- package/dist/ApiClient/WebSocketClient/index.js +24 -1
- package/dist/ApiClient/WebSocketClient/index.js.map +1 -1
- package/dist/ApiClient/WebSocketClient/messages.d.ts +2 -0
- package/dist/ApiClient/WebSocketClient/types.d.ts +2 -0
- package/dist/ApiClient/index.d.ts +6 -1
- package/dist/ApiClient/index.js +7 -3
- package/dist/ApiClient/index.js.map +1 -1
- package/dist/Chat/ChatTools.d.ts +5 -49
- package/dist/Chat/ChatTools.js +311 -88
- package/dist/Chat/ChatTools.js.map +1 -1
- package/dist/Chat/index.d.ts +11 -2
- package/dist/Chat/index.js +78 -4
- package/dist/Chat/index.js.map +1 -1
- package/dist/Chat/modelRouting.d.ts +100 -0
- package/dist/Chat/modelRouting.js +441 -0
- package/dist/Chat/modelRouting.js.map +1 -0
- package/dist/Chat/sogniHostedTools.generated.json +529 -0
- package/dist/Chat/tools.d.ts +9 -55
- package/dist/Chat/tools.js +72 -228
- package/dist/Chat/tools.js.map +1 -1
- package/dist/Chat/types.d.ts +91 -2
- package/dist/CreativeWorkflows/index.d.ts +23 -0
- package/dist/CreativeWorkflows/index.js +274 -0
- package/dist/CreativeWorkflows/index.js.map +1 -0
- package/dist/CreativeWorkflows/types.d.ts +106 -0
- package/dist/CreativeWorkflows/types.js +3 -0
- package/dist/CreativeWorkflows/types.js.map +1 -0
- package/dist/Projects/Job.d.ts +6 -0
- package/dist/Projects/Job.js +60 -5
- package/dist/Projects/Job.js.map +1 -1
- package/dist/Projects/Project.js +15 -3
- package/dist/Projects/Project.js.map +1 -1
- package/dist/Projects/createJobRequestMessage.js +140 -6
- package/dist/Projects/createJobRequestMessage.js.map +1 -1
- package/dist/Projects/index.d.ts +10 -1
- package/dist/Projects/index.js +197 -58
- package/dist/Projects/index.js.map +1 -1
- package/dist/Projects/types/ModelOptions.d.ts +3 -3
- package/dist/Projects/types/ModelOptions.js +12 -5
- package/dist/Projects/types/ModelOptions.js.map +1 -1
- package/dist/Projects/types/ModelTiersRaw.d.ts +7 -7
- package/dist/Projects/types/RawProject.d.ts +2 -0
- package/dist/Projects/types/events.d.ts +5 -4
- package/dist/Projects/types/index.d.ts +77 -7
- package/dist/Projects/types/index.js.map +1 -1
- package/dist/Projects/utils/index.d.ts +8 -1
- package/dist/Projects/utils/index.js +22 -8
- package/dist/Projects/utils/index.js.map +1 -1
- package/dist/index.d.ts +28 -3
- package/dist/index.js +19 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/RestClient.d.ts +4 -1
- package/dist/lib/RestClient.js +17 -9
- package/dist/lib/RestClient.js.map +1 -1
- package/dist/lib/mediaValidation.d.ts +16 -0
- package/dist/lib/mediaValidation.js +280 -0
- package/dist/lib/mediaValidation.js.map +1 -0
- package/dist/lib/validation.d.ts +6 -1
- package/dist/lib/validation.js +28 -2
- package/dist/lib/validation.js.map +1 -1
- package/llms-full.txt +372 -133
- package/llms.txt +197 -86
- package/package.json +13 -4
- package/src/Account/index.ts +22 -2
- package/src/Account/types.ts +7 -0
- package/src/ApiClient/WebSocketClient/BrowserWebSocketClient/index.ts +47 -3
- package/src/ApiClient/WebSocketClient/eventSubscriptions.ts +92 -0
- package/src/ApiClient/WebSocketClient/events.ts +25 -7
- package/src/ApiClient/WebSocketClient/index.ts +33 -1
- package/src/ApiClient/WebSocketClient/messages.ts +2 -0
- package/src/ApiClient/WebSocketClient/types.ts +2 -0
- package/src/ApiClient/index.ts +32 -2
- package/src/Chat/ChatTools.ts +395 -95
- package/src/Chat/index.ts +149 -5
- package/src/Chat/modelRouting.ts +602 -0
- package/src/Chat/sogniHostedTools.generated.json +529 -0
- package/src/Chat/tools.ts +98 -245
- package/src/Chat/types.ts +100 -2
- package/src/CreativeWorkflows/index.ts +290 -0
- package/src/CreativeWorkflows/types.ts +134 -0
- package/src/Projects/Job.ts +76 -5
- package/src/Projects/Project.ts +13 -3
- package/src/Projects/createJobRequestMessage.ts +152 -13
- package/src/Projects/index.ts +230 -52
- package/src/Projects/types/ModelOptions.ts +15 -8
- package/src/Projects/types/ModelTiersRaw.ts +7 -7
- package/src/Projects/types/RawProject.ts +2 -0
- package/src/Projects/types/events.ts +5 -4
- package/src/Projects/types/index.ts +86 -6
- package/src/Projects/utils/index.ts +24 -8
- package/src/index.ts +93 -0
- package/src/lib/RestClient.ts +15 -5
- package/src/lib/mediaValidation.ts +367 -0
- package/src/lib/validation.ts +38 -2
package/src/Account/index.ts
CHANGED
|
@@ -133,7 +133,15 @@ class AccountApi extends ApiGroup {
|
|
|
133
133
|
* @internal
|
|
134
134
|
*/
|
|
135
135
|
async create(
|
|
136
|
-
{
|
|
136
|
+
{
|
|
137
|
+
username,
|
|
138
|
+
email,
|
|
139
|
+
password,
|
|
140
|
+
subscribe,
|
|
141
|
+
turnstileToken,
|
|
142
|
+
referralCode,
|
|
143
|
+
appSource
|
|
144
|
+
}: AccountCreateParams,
|
|
137
145
|
rememberMe = false
|
|
138
146
|
): Promise<AccountCreateData> {
|
|
139
147
|
const wallet = this.getWallet(username, password);
|
|
@@ -146,9 +154,11 @@ class AccountApi extends ApiGroup {
|
|
|
146
154
|
walletAddress: wallet.address,
|
|
147
155
|
turnstileToken
|
|
148
156
|
};
|
|
157
|
+
const resolvedAppSource = appSource?.trim() || this.client.appSource;
|
|
149
158
|
const signature = await this.eip712.signTypedData(wallet, 'signup', { ...payload, nonce });
|
|
150
159
|
const res = await this.client.rest.post<ApiResponse<AccountCreateData>>('/v1/account/create', {
|
|
151
160
|
...payload,
|
|
161
|
+
...(resolvedAppSource ? { appSource: resolvedAppSource } : {}),
|
|
152
162
|
referralCode,
|
|
153
163
|
signature,
|
|
154
164
|
rememberMe
|
|
@@ -175,17 +185,26 @@ class AccountApi extends ApiGroup {
|
|
|
175
185
|
* @param password
|
|
176
186
|
* @param rememberMe - Whether to establish a long-lived session. Default is false. Only
|
|
177
187
|
* applicable for cookie-based authentication.
|
|
188
|
+
* @param appSource - Optional client app/source label for login attribution. Defaults to the
|
|
189
|
+
* SogniClient connection appSource when configured.
|
|
178
190
|
*/
|
|
179
|
-
async login(
|
|
191
|
+
async login(
|
|
192
|
+
username: string,
|
|
193
|
+
password: string,
|
|
194
|
+
rememberMe = false,
|
|
195
|
+
appSource?: string
|
|
196
|
+
): Promise<LoginData> {
|
|
180
197
|
const wallet = this.getWallet(username, password);
|
|
181
198
|
const nonce = await this.getNonce(wallet.address);
|
|
182
199
|
const signature = await this.eip712.signTypedData(wallet, 'authentication', {
|
|
183
200
|
walletAddress: wallet.address,
|
|
184
201
|
nonce
|
|
185
202
|
});
|
|
203
|
+
const resolvedAppSource = appSource?.trim() || this.client.appSource;
|
|
186
204
|
const res = await this.client.rest.post<ApiResponse<LoginData>>('/v1/account/login', {
|
|
187
205
|
walletAddress: wallet.address,
|
|
188
206
|
signature,
|
|
207
|
+
...(resolvedAppSource ? { appSource: resolvedAppSource } : {}),
|
|
189
208
|
rememberMe
|
|
190
209
|
});
|
|
191
210
|
const auth = this.client.auth;
|
|
@@ -414,6 +433,7 @@ class AccountApi extends ApiGroup {
|
|
|
414
433
|
tokenType: raw.tokenType,
|
|
415
434
|
claimed: !!raw.claimed,
|
|
416
435
|
canClaim: !!raw.canClaim,
|
|
436
|
+
cantClaimReason: raw.cantClaimReason ?? null,
|
|
417
437
|
lastClaim: new Date(raw.lastClaimTimestamp * 1000),
|
|
418
438
|
provider: query.provider || 'base',
|
|
419
439
|
nextClaim:
|
package/src/Account/types.ts
CHANGED
|
@@ -11,6 +11,11 @@ export interface AccountCreateParams {
|
|
|
11
11
|
subscribe: boolean;
|
|
12
12
|
turnstileToken: string;
|
|
13
13
|
referralCode?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Optional client app/source label for signup attribution. Defaults to the
|
|
16
|
+
* SogniClient connection appSource when configured.
|
|
17
|
+
*/
|
|
18
|
+
appSource?: string;
|
|
14
19
|
}
|
|
15
20
|
|
|
16
21
|
export interface AccountCreateData {
|
|
@@ -126,6 +131,7 @@ export interface RewardRaw {
|
|
|
126
131
|
tokenType: TokenType;
|
|
127
132
|
claimed: number;
|
|
128
133
|
canClaim: number;
|
|
134
|
+
cantClaimReason?: 'already_claimed' | 'over_free_cap' | null;
|
|
129
135
|
lastClaimTimestamp: number;
|
|
130
136
|
claimResetFrequencySec: number;
|
|
131
137
|
}
|
|
@@ -143,6 +149,7 @@ export interface Reward {
|
|
|
143
149
|
tokenType: TokenType;
|
|
144
150
|
claimed: boolean;
|
|
145
151
|
canClaim: boolean;
|
|
152
|
+
cantClaimReason?: 'already_claimed' | 'over_free_cap' | null;
|
|
146
153
|
lastClaim: Date;
|
|
147
154
|
nextClaim: Date | null;
|
|
148
155
|
provider?: string;
|
|
@@ -6,6 +6,7 @@ import RestClient from '../../../lib/RestClient';
|
|
|
6
6
|
import { SocketEventMap } from '../events';
|
|
7
7
|
import { MessageType, SocketMessageMap } from '../messages';
|
|
8
8
|
import ChannelCoordinator from './ChannelCoordinator';
|
|
9
|
+
import type { SocketEventSubscriptionInput, SocketEventSubscriptions } from '../eventSubscriptions';
|
|
9
10
|
|
|
10
11
|
interface SocketSend<T extends MessageType = MessageType> {
|
|
11
12
|
type: 'socket-send';
|
|
@@ -25,7 +26,17 @@ interface SwitchNetwork {
|
|
|
25
26
|
payload: SupernetType;
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
interface SetSocketEventSubscriptions {
|
|
30
|
+
type: 'setSocketEventSubscriptions';
|
|
31
|
+
payload: SocketEventSubscriptionInput;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type Message =
|
|
35
|
+
| SocketConnect
|
|
36
|
+
| SocketDisconnect
|
|
37
|
+
| SocketSend
|
|
38
|
+
| SwitchNetwork
|
|
39
|
+
| SetSocketEventSubscriptions;
|
|
29
40
|
|
|
30
41
|
interface EventNotification<T extends keyof SocketEventMap = keyof SocketEventMap> {
|
|
31
42
|
type: 'socket-event';
|
|
@@ -70,9 +81,19 @@ class BrowserWebSocketClient extends RestClient<SocketEventMap> implements IWebS
|
|
|
70
81
|
auth: AuthManager,
|
|
71
82
|
appId: string,
|
|
72
83
|
supernetType: SupernetType,
|
|
73
|
-
logger: Logger
|
|
84
|
+
logger: Logger,
|
|
85
|
+
appSource?: string,
|
|
86
|
+
socketEventSubscriptions?: SocketEventSubscriptions
|
|
74
87
|
) {
|
|
75
|
-
const socketClient = new WrappedClient(
|
|
88
|
+
const socketClient = new WrappedClient(
|
|
89
|
+
baseUrl,
|
|
90
|
+
auth,
|
|
91
|
+
appId,
|
|
92
|
+
supernetType,
|
|
93
|
+
logger,
|
|
94
|
+
appSource,
|
|
95
|
+
socketEventSubscriptions
|
|
96
|
+
);
|
|
76
97
|
super(socketClient.baseUrl, auth, logger);
|
|
77
98
|
this.socketClient = socketClient;
|
|
78
99
|
this.appId = appId;
|
|
@@ -88,6 +109,14 @@ class BrowserWebSocketClient extends RestClient<SocketEventMap> implements IWebS
|
|
|
88
109
|
});
|
|
89
110
|
this.auth.on('updated', this.handleAuthUpdated.bind(this));
|
|
90
111
|
this.socketClient.intercept(this.handleSocketEvent.bind(this));
|
|
112
|
+
// Keep this tab's WrappedClient subscription state in sync with the server's authoritative
|
|
113
|
+
// snapshot, even when this tab is currently a secondary. If we get promoted to primary, the
|
|
114
|
+
// next `connect()` will serialize the up-to-date state into the URL query string.
|
|
115
|
+
this.on('socketEventSubscriptionsUpdated', (payload) => {
|
|
116
|
+
if (payload && payload.socketEventSubscriptions) {
|
|
117
|
+
this.socketClient.socketEventSubscriptions = { ...payload.socketEventSubscriptions };
|
|
118
|
+
}
|
|
119
|
+
});
|
|
91
120
|
}
|
|
92
121
|
|
|
93
122
|
get isConnected() {
|
|
@@ -133,6 +162,17 @@ class BrowserWebSocketClient extends RestClient<SocketEventMap> implements IWebS
|
|
|
133
162
|
return supernetType;
|
|
134
163
|
}
|
|
135
164
|
|
|
165
|
+
async setSocketEventSubscriptions(update: SocketEventSubscriptionInput): Promise<void> {
|
|
166
|
+
await this.coordinator.isReady();
|
|
167
|
+
if (this.coordinator.isPrimary) {
|
|
168
|
+
return this.socketClient.setSocketEventSubscriptions(update);
|
|
169
|
+
}
|
|
170
|
+
return this.coordinator.sendMessage({
|
|
171
|
+
type: 'setSocketEventSubscriptions',
|
|
172
|
+
payload: update
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
136
176
|
async send<T extends MessageType>(messageType: T, data: SocketMessageMap[T]): Promise<void> {
|
|
137
177
|
await this.coordinator.isReady();
|
|
138
178
|
if (this.coordinator.isPrimary) {
|
|
@@ -172,6 +212,10 @@ class BrowserWebSocketClient extends RestClient<SocketEventMap> implements IWebS
|
|
|
172
212
|
await this.switchNetwork(message.payload);
|
|
173
213
|
return;
|
|
174
214
|
}
|
|
215
|
+
case 'setSocketEventSubscriptions': {
|
|
216
|
+
await this.socketClient.setSocketEventSubscriptions(message.payload);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
175
219
|
default: {
|
|
176
220
|
this._logger.error('Received unknown message type:', message);
|
|
177
221
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { SocketEventName } from './events';
|
|
2
|
+
|
|
3
|
+
export type SocketEventSubscriptionGroup = 'modelAvailability';
|
|
4
|
+
|
|
5
|
+
export type SocketEventSubscriptionName =
|
|
6
|
+
| SocketEventName
|
|
7
|
+
| SocketEventSubscriptionGroup
|
|
8
|
+
| (string & {});
|
|
9
|
+
|
|
10
|
+
export type SocketEventSubscriptions = Partial<
|
|
11
|
+
Record<SocketEventName | SocketEventSubscriptionGroup, boolean>
|
|
12
|
+
> &
|
|
13
|
+
Record<string, boolean | undefined>;
|
|
14
|
+
|
|
15
|
+
export interface SocketEventSubscriptionUpdate {
|
|
16
|
+
/**
|
|
17
|
+
* Replace or merge explicit event subscription flags.
|
|
18
|
+
*/
|
|
19
|
+
subscriptions?: SocketEventSubscriptions;
|
|
20
|
+
/**
|
|
21
|
+
* Subscribe to one or more socket events or event groups.
|
|
22
|
+
*/
|
|
23
|
+
subscribe?: SocketEventSubscriptionName | SocketEventSubscriptionName[];
|
|
24
|
+
/**
|
|
25
|
+
* Unsubscribe from one or more socket events or event groups.
|
|
26
|
+
*/
|
|
27
|
+
unsubscribe?: SocketEventSubscriptionName | SocketEventSubscriptionName[];
|
|
28
|
+
/**
|
|
29
|
+
* Clear existing server-side subscription overrides before applying this update.
|
|
30
|
+
*/
|
|
31
|
+
reset?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Single-event update shorthand.
|
|
34
|
+
*/
|
|
35
|
+
event?: SocketEventSubscriptionName;
|
|
36
|
+
/**
|
|
37
|
+
* Boolean value for the single-event update shorthand.
|
|
38
|
+
*/
|
|
39
|
+
enabled?: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type SocketEventSubscriptionInput = SocketEventSubscriptions | SocketEventSubscriptionUpdate;
|
|
43
|
+
|
|
44
|
+
const UPDATE_KEYS = new Set([
|
|
45
|
+
'subscriptions',
|
|
46
|
+
'subscribe',
|
|
47
|
+
'unsubscribe',
|
|
48
|
+
'reset',
|
|
49
|
+
'event',
|
|
50
|
+
'enabled'
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
function hasUpdateShape(input: Record<string, unknown>): boolean {
|
|
54
|
+
return Object.keys(input).some((key) => UPDATE_KEYS.has(key));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function normalizeSubscriptions(
|
|
58
|
+
subscriptions?: SocketEventSubscriptions
|
|
59
|
+
): SocketEventSubscriptions | undefined {
|
|
60
|
+
if (!subscriptions || typeof subscriptions !== 'object') {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const normalized: SocketEventSubscriptions = {};
|
|
65
|
+
for (const [eventName, enabled] of Object.entries(subscriptions)) {
|
|
66
|
+
if (typeof enabled === 'boolean') {
|
|
67
|
+
normalized[eventName] = enabled;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return Object.keys(normalized).length ? normalized : undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function normalizeSocketEventSubscriptionUpdate(
|
|
74
|
+
input: SocketEventSubscriptionInput
|
|
75
|
+
): SocketEventSubscriptionUpdate {
|
|
76
|
+
const raw = input && typeof input === 'object' ? input : {};
|
|
77
|
+
const update = hasUpdateShape(raw as Record<string, unknown>)
|
|
78
|
+
? (raw as SocketEventSubscriptionUpdate)
|
|
79
|
+
: { subscriptions: raw as SocketEventSubscriptions };
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
...update,
|
|
83
|
+
subscriptions: normalizeSubscriptions(update.subscriptions)
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function serializeSocketEventSubscriptions(
|
|
88
|
+
subscriptions?: SocketEventSubscriptions
|
|
89
|
+
): string | undefined {
|
|
90
|
+
const normalized = normalizeSubscriptions(subscriptions);
|
|
91
|
+
return normalized ? JSON.stringify(normalized) : undefined;
|
|
92
|
+
}
|
|
@@ -44,9 +44,10 @@ export type JobErrorData = {
|
|
|
44
44
|
export type JobProgressData = {
|
|
45
45
|
jobID: string;
|
|
46
46
|
imgID: string;
|
|
47
|
-
hasImage
|
|
48
|
-
step
|
|
49
|
-
stepCount
|
|
47
|
+
hasImage?: boolean;
|
|
48
|
+
step?: number;
|
|
49
|
+
stepCount?: number;
|
|
50
|
+
progress?: number;
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
export type JobETAData = {
|
|
@@ -58,11 +59,20 @@ export type JobETAData = {
|
|
|
58
59
|
export type JobResultData = {
|
|
59
60
|
jobID: string;
|
|
60
61
|
imgID: string;
|
|
61
|
-
performedStepCount
|
|
62
|
-
lastSeed
|
|
63
|
-
userCanceled
|
|
64
|
-
triggeredNSFWFilter
|
|
62
|
+
performedStepCount?: number;
|
|
63
|
+
lastSeed?: string;
|
|
64
|
+
userCanceled?: boolean;
|
|
65
|
+
triggeredNSFWFilter?: boolean;
|
|
65
66
|
resultUrl?: string;
|
|
67
|
+
resultKey?: string;
|
|
68
|
+
/**
|
|
69
|
+
* @deprecated Use `resultUrl`. Kept for older video worker/socket payload compatibility.
|
|
70
|
+
*/
|
|
71
|
+
videoUrl?: string;
|
|
72
|
+
/**
|
|
73
|
+
* @deprecated Use `resultUrl`. Kept for older video worker/socket payload compatibility.
|
|
74
|
+
*/
|
|
75
|
+
videoFile?: string;
|
|
66
76
|
};
|
|
67
77
|
|
|
68
78
|
export type JobStateData =
|
|
@@ -148,6 +158,10 @@ export type LLMJobErrorData = {
|
|
|
148
158
|
workerName?: string;
|
|
149
159
|
};
|
|
150
160
|
|
|
161
|
+
export type SocketEventSubscriptionsUpdatedData = {
|
|
162
|
+
socketEventSubscriptions: Record<string, boolean | undefined>;
|
|
163
|
+
};
|
|
164
|
+
|
|
151
165
|
export type SocketEventMap = {
|
|
152
166
|
/**
|
|
153
167
|
* @event WebSocketClient#authenticated - Received after successful connection to the WebSocket server
|
|
@@ -204,6 +218,10 @@ export type SocketEventMap = {
|
|
|
204
218
|
* @event WebSocketClient#swarmLLMModels - Available LLM models with worker counts
|
|
205
219
|
*/
|
|
206
220
|
swarmLLMModels: Record<string, number | LLMModelInfo>;
|
|
221
|
+
/**
|
|
222
|
+
* @event WebSocketClient#socketEventSubscriptionsUpdated - Current socket event subscriptions changed
|
|
223
|
+
*/
|
|
224
|
+
socketEventSubscriptionsUpdated: SocketEventSubscriptionsUpdatedData;
|
|
207
225
|
/**
|
|
208
226
|
* @event WebSocketClient#connected - WebSocket connection opened
|
|
209
227
|
*/
|
|
@@ -8,6 +8,11 @@ import isNodejs from '../../lib/isNodejs';
|
|
|
8
8
|
import { LIB_VERSION } from '../../version';
|
|
9
9
|
import { Logger } from '../../lib/DefaultLogger';
|
|
10
10
|
import { AuthManager } from '../../lib/AuthManager';
|
|
11
|
+
import {
|
|
12
|
+
normalizeSocketEventSubscriptionUpdate,
|
|
13
|
+
serializeSocketEventSubscriptions
|
|
14
|
+
} from './eventSubscriptions';
|
|
15
|
+
import type { SocketEventSubscriptionInput, SocketEventSubscriptions } from './eventSubscriptions';
|
|
11
16
|
|
|
12
17
|
const PROTOCOL_VERSION = '3.0.0';
|
|
13
18
|
|
|
@@ -15,7 +20,9 @@ const PING_INTERVAL = 15000;
|
|
|
15
20
|
|
|
16
21
|
class WebSocketClient extends RestClient<SocketEventMap> implements IWebSocketClient {
|
|
17
22
|
appId: string;
|
|
23
|
+
appSource?: string;
|
|
18
24
|
baseUrl: string;
|
|
25
|
+
socketEventSubscriptions?: SocketEventSubscriptions;
|
|
19
26
|
private socket: WebSocket | null = null;
|
|
20
27
|
private _supernetType: SupernetType;
|
|
21
28
|
private _pingInterval: NodeJS.Timeout | null = null;
|
|
@@ -25,7 +32,9 @@ class WebSocketClient extends RestClient<SocketEventMap> implements IWebSocketCl
|
|
|
25
32
|
auth: AuthManager,
|
|
26
33
|
appId: string,
|
|
27
34
|
supernetType: SupernetType,
|
|
28
|
-
logger: Logger
|
|
35
|
+
logger: Logger,
|
|
36
|
+
appSource?: string,
|
|
37
|
+
socketEventSubscriptions?: SocketEventSubscriptions
|
|
29
38
|
) {
|
|
30
39
|
const _baseUrl = new URL(baseUrl);
|
|
31
40
|
switch (_baseUrl.protocol) {
|
|
@@ -42,8 +51,17 @@ class WebSocketClient extends RestClient<SocketEventMap> implements IWebSocketCl
|
|
|
42
51
|
}
|
|
43
52
|
super(_baseUrl.toString(), auth, logger);
|
|
44
53
|
this.appId = appId;
|
|
54
|
+
this.appSource = appSource?.trim() || undefined;
|
|
55
|
+
this.socketEventSubscriptions = socketEventSubscriptions;
|
|
45
56
|
this.baseUrl = _baseUrl.toString();
|
|
46
57
|
this._supernetType = supernetType;
|
|
58
|
+
// Mirror the server's authoritative subscriptions snapshot so reconnects keep any
|
|
59
|
+
// runtime updates applied via `setSocketEventSubscriptions` after the initial connect.
|
|
60
|
+
this.on('socketEventSubscriptionsUpdated', (payload) => {
|
|
61
|
+
if (payload && payload.socketEventSubscriptions) {
|
|
62
|
+
this.socketEventSubscriptions = { ...payload.socketEventSubscriptions };
|
|
63
|
+
}
|
|
64
|
+
});
|
|
47
65
|
}
|
|
48
66
|
|
|
49
67
|
get supernetType(): SupernetType {
|
|
@@ -63,6 +81,15 @@ class WebSocketClient extends RestClient<SocketEventMap> implements IWebSocketCl
|
|
|
63
81
|
const isNotSecure = url.protocol === 'http:' || url.protocol === 'ws:';
|
|
64
82
|
url.protocol = isNotSecure ? 'ws:' : 'wss:';
|
|
65
83
|
url.searchParams.set('appId', this.appId);
|
|
84
|
+
if (this.appSource) {
|
|
85
|
+
url.searchParams.set('appSource', this.appSource);
|
|
86
|
+
}
|
|
87
|
+
const socketEventSubscriptions = serializeSocketEventSubscriptions(
|
|
88
|
+
this.socketEventSubscriptions
|
|
89
|
+
);
|
|
90
|
+
if (socketEventSubscriptions) {
|
|
91
|
+
url.searchParams.set('socketEventSubscriptions', socketEventSubscriptions);
|
|
92
|
+
}
|
|
66
93
|
url.searchParams.set('clientName', userAgent);
|
|
67
94
|
url.searchParams.set('clientType', 'artist');
|
|
68
95
|
//At this point 'relaxed' does not work as expected, so we use 'fast' or empty
|
|
@@ -115,6 +142,11 @@ class WebSocketClient extends RestClient<SocketEventMap> implements IWebSocketCl
|
|
|
115
142
|
});
|
|
116
143
|
}
|
|
117
144
|
|
|
145
|
+
async setSocketEventSubscriptions(update: SocketEventSubscriptionInput): Promise<void> {
|
|
146
|
+
const normalizedUpdate = normalizeSocketEventSubscriptionUpdate(update);
|
|
147
|
+
await this.send('setSocketEventSubscriptions', normalizedUpdate);
|
|
148
|
+
}
|
|
149
|
+
|
|
118
150
|
/**
|
|
119
151
|
* Ensure the WebSocket connection is open, waiting if necessary and throwing an error if it fails
|
|
120
152
|
* @private
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { JobRequestRaw } from '../../Projects/createJobRequestMessage';
|
|
2
2
|
import { SupernetType } from './types';
|
|
3
3
|
import { ChatRequestMessage } from '../../Chat/types';
|
|
4
|
+
import type { SocketEventSubscriptionUpdate } from './eventSubscriptions';
|
|
4
5
|
|
|
5
6
|
export interface JobErrorMessage {
|
|
6
7
|
jobID: string;
|
|
@@ -14,6 +15,7 @@ export interface SocketMessageMap {
|
|
|
14
15
|
jobError: JobErrorMessage;
|
|
15
16
|
changeNetwork: SupernetType;
|
|
16
17
|
llmJobRequest: ChatRequestMessage;
|
|
18
|
+
setSocketEventSubscriptions: SocketEventSubscriptionUpdate;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
export type MessageType = keyof SocketMessageMap;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MessageType, SocketMessageMap } from './messages';
|
|
2
2
|
import RestClient from '../../lib/RestClient';
|
|
3
3
|
import { SocketEventMap } from './events';
|
|
4
|
+
import type { SocketEventSubscriptionInput } from './eventSubscriptions';
|
|
4
5
|
|
|
5
6
|
export type SupernetType = 'relaxed' | 'fast';
|
|
6
7
|
|
|
@@ -13,5 +14,6 @@ export interface IWebSocketClient extends RestClient<SocketEventMap> {
|
|
|
13
14
|
connect(): Promise<void>;
|
|
14
15
|
disconnect(): void;
|
|
15
16
|
send<T extends MessageType>(messageType: T, data: SocketMessageMap[T]): Promise<void>;
|
|
17
|
+
setSocketEventSubscriptions(update: SocketEventSubscriptionInput): Promise<void>;
|
|
16
18
|
switchNetwork(supernetType: SupernetType): Promise<SupernetType>;
|
|
17
19
|
}
|
package/src/ApiClient/index.ts
CHANGED
|
@@ -6,6 +6,10 @@ import { ServerConnectData, ServerDisconnectData } from './WebSocketClient/event
|
|
|
6
6
|
import { ErrorCode, isNotRecoverable } from './WebSocketClient/ErrorCode';
|
|
7
7
|
import { JSONValue } from '../types/json';
|
|
8
8
|
import { IWebSocketClient, SupernetType } from './WebSocketClient/types';
|
|
9
|
+
import type {
|
|
10
|
+
SocketEventSubscriptionInput,
|
|
11
|
+
SocketEventSubscriptions
|
|
12
|
+
} from './WebSocketClient/eventSubscriptions';
|
|
9
13
|
import { Logger } from '../lib/DefaultLogger';
|
|
10
14
|
import ApiKeyAuthManager from '../lib/AuthManager/ApiKeyAuthManager';
|
|
11
15
|
import CookieAuthManager from '../lib/AuthManager/CookieAuthManager';
|
|
@@ -41,6 +45,8 @@ export interface ApiClientOptions {
|
|
|
41
45
|
baseUrl: string;
|
|
42
46
|
socketUrl: string;
|
|
43
47
|
appId: string;
|
|
48
|
+
appSource?: string;
|
|
49
|
+
socketEventSubscriptions?: SocketEventSubscriptions;
|
|
44
50
|
networkType: SupernetType;
|
|
45
51
|
logger: Logger;
|
|
46
52
|
authType: 'token' | 'cookies' | 'apiKey';
|
|
@@ -50,6 +56,7 @@ export interface ApiClientOptions {
|
|
|
50
56
|
|
|
51
57
|
class ApiClient extends TypedEventEmitter<ApiClientEvents> {
|
|
52
58
|
readonly appId: string;
|
|
59
|
+
readonly appSource?: string;
|
|
53
60
|
readonly logger: Logger;
|
|
54
61
|
private _rest: RestClient;
|
|
55
62
|
private _socket: IWebSocketClient;
|
|
@@ -61,6 +68,8 @@ class ApiClient extends TypedEventEmitter<ApiClientEvents> {
|
|
|
61
68
|
baseUrl,
|
|
62
69
|
socketUrl,
|
|
63
70
|
appId,
|
|
71
|
+
appSource,
|
|
72
|
+
socketEventSubscriptions,
|
|
64
73
|
networkType,
|
|
65
74
|
authType,
|
|
66
75
|
logger,
|
|
@@ -69,6 +78,7 @@ class ApiClient extends TypedEventEmitter<ApiClientEvents> {
|
|
|
69
78
|
}: ApiClientOptions) {
|
|
70
79
|
super();
|
|
71
80
|
this.appId = appId;
|
|
81
|
+
this.appSource = appSource?.trim() || undefined;
|
|
72
82
|
this.logger = logger;
|
|
73
83
|
if (authType === 'apiKey') {
|
|
74
84
|
this._auth = new ApiKeyAuthManager(logger);
|
|
@@ -81,9 +91,25 @@ class ApiClient extends TypedEventEmitter<ApiClientEvents> {
|
|
|
81
91
|
const supportMultiInstance = !isNodejs && this._auth instanceof CookieAuthManager;
|
|
82
92
|
if (supportMultiInstance && multiInstance) {
|
|
83
93
|
// Use coordinated WebSocket client to share single connection between tabs
|
|
84
|
-
this._socket = new BrowserWebSocketClient(
|
|
94
|
+
this._socket = new BrowserWebSocketClient(
|
|
95
|
+
socketUrl,
|
|
96
|
+
this._auth,
|
|
97
|
+
appId,
|
|
98
|
+
networkType,
|
|
99
|
+
logger,
|
|
100
|
+
this.appSource,
|
|
101
|
+
socketEventSubscriptions
|
|
102
|
+
);
|
|
85
103
|
} else {
|
|
86
|
-
this._socket = new WebSocketClient(
|
|
104
|
+
this._socket = new WebSocketClient(
|
|
105
|
+
socketUrl,
|
|
106
|
+
this._auth,
|
|
107
|
+
appId,
|
|
108
|
+
networkType,
|
|
109
|
+
logger,
|
|
110
|
+
this.appSource,
|
|
111
|
+
socketEventSubscriptions
|
|
112
|
+
);
|
|
87
113
|
}
|
|
88
114
|
this._disableSocket = disableSocket;
|
|
89
115
|
this._auth.on('updated', this.handleAuthUpdated.bind(this));
|
|
@@ -111,6 +137,10 @@ class ApiClient extends TypedEventEmitter<ApiClientEvents> {
|
|
|
111
137
|
return !this._disableSocket;
|
|
112
138
|
}
|
|
113
139
|
|
|
140
|
+
setSocketEventSubscriptions(update: SocketEventSubscriptionInput): Promise<void> {
|
|
141
|
+
return this.socket.setSocketEventSubscriptions(update);
|
|
142
|
+
}
|
|
143
|
+
|
|
114
144
|
handleSocketConnect({ network }: ServerConnectData) {
|
|
115
145
|
this._reconnectAttempts = WS_RECONNECT_ATTEMPTS;
|
|
116
146
|
this.emit('connected', { network });
|