agl 22.0.4 → 24.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 +21 -0
- package/dist_serve/bundle.js +2418 -2408
- package/dist_serve/bundle.js.map +1 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.authstore.js +2 -2
- package/dist_ts/classes.browserresourcehost.d.ts +1 -0
- package/dist_ts/classes.browserresourcehost.js +7 -1
- package/dist_ts/classes.controller.d.ts +37 -5
- package/dist_ts/classes.controller.js +1491 -249
- package/dist_ts/classes.flexservice.d.ts +5 -0
- package/dist_ts/classes.flexservice.js +131 -4
- package/dist_ts/classes.opencodeclient.d.ts +2 -0
- package/dist_ts/classes.opencodeclient.js +23 -1
- package/dist_ts/classes.validation.d.ts +9 -1
- package/dist_ts/classes.validation.js +62 -7
- package/dist_ts/interfaces.flexipc.d.ts +18 -1
- package/dist_ts/interfaces.flexipc.js +42 -8
- package/dist_ts_interfaces/browsertransport.d.ts +72 -0
- package/dist_ts_interfaces/browsertransport.js +47 -0
- package/dist_ts_interfaces/index.d.ts +1 -0
- package/dist_ts_interfaces/index.js +2 -1
- package/dist_ts_interfaces/interfaces.d.ts +42 -7
- package/dist_ts_interfaces/interfaces.js +5 -3
- package/dist_ts_interfaces/requests.d.ts +20 -21
- package/package.json +7 -7
- package/readme.md +12 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.authstore.ts +1 -1
- package/ts/classes.browserresourcehost.ts +7 -0
- package/ts/classes.controller.ts +1960 -305
- package/ts/classes.flexservice.ts +132 -2
- package/ts/classes.opencodeclient.ts +19 -0
- package/ts/classes.validation.ts +77 -6
- package/ts/interfaces.flexipc.ts +65 -7
- package/ts_interfaces/browsertransport.ts +126 -0
- package/ts_interfaces/index.ts +1 -0
- package/ts_interfaces/interfaces.ts +46 -11
- package/ts_interfaces/requests.ts +23 -30
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/classes.browserviewtransport.ts +532 -0
- package/ts_web/classes.controllersocketclient.ts +119 -29
- package/ts_web/elements.harnesscontrollerapp.ts +1727 -287
- package/ts_web/index.ts +1 -0
- package/ts_web/plugins.ts +2 -0
|
@@ -3,6 +3,7 @@ import * as interfaces from '../ts_interfaces/index.js';
|
|
|
3
3
|
|
|
4
4
|
const controllerEventTypes: ReadonlySet<string> = new Set(interfaces.controllerEventTypes);
|
|
5
5
|
const controllerRequestTimeoutMs = 35_000;
|
|
6
|
+
const textEncoder = new TextEncoder();
|
|
6
7
|
|
|
7
8
|
const isQualifiedRuntimeId = (
|
|
8
9
|
valueArg: unknown,
|
|
@@ -16,7 +17,7 @@ const isQualifiedRuntimeId = (
|
|
|
16
17
|
&& allowedHarnessIdsArg.has(candidate.harnessId as interfaces.TControllerHarnessId)
|
|
17
18
|
&& typeof candidate.nativeId === 'string'
|
|
18
19
|
&& candidate.nativeId.length > 0
|
|
19
|
-
&&
|
|
20
|
+
&& textEncoder.encode(candidate.nativeId).byteLength <= 512
|
|
20
21
|
);
|
|
21
22
|
};
|
|
22
23
|
|
|
@@ -36,6 +37,14 @@ const textUpdateKeys = new Set([
|
|
|
36
37
|
'sessionId', 'messageId', 'partId', 'text', 'status', 'order',
|
|
37
38
|
'sourceUpdatedAt', 'revision', 'streamEpoch',
|
|
38
39
|
]);
|
|
40
|
+
const messageDeltaKeys = new Set([
|
|
41
|
+
'sessionId', 'messageId', 'partId', 'delta', 'baseTextUtf8Bytes', 'textUtf8Bytes',
|
|
42
|
+
'order', 'sourceUpdatedAt', 'revision', 'streamEpoch',
|
|
43
|
+
]);
|
|
44
|
+
const messageDeltaRequiredKeys = [
|
|
45
|
+
'sessionId', 'messageId', 'partId', 'delta', 'baseTextUtf8Bytes', 'textUtf8Bytes',
|
|
46
|
+
'sourceUpdatedAt', 'revision', 'streamEpoch',
|
|
47
|
+
] as const;
|
|
39
48
|
|
|
40
49
|
const isOptionalFiniteNumber = (valueArg: unknown): boolean => (
|
|
41
50
|
valueArg === undefined || (typeof valueArg === 'number' && Number.isFinite(valueArg))
|
|
@@ -53,12 +62,26 @@ const isTranscriptOrder = (valueArg: unknown): boolean => {
|
|
|
53
62
|
|
|
54
63
|
const serializedBytesWithin = (valueArg: unknown, byteLimitArg: number): boolean => {
|
|
55
64
|
try {
|
|
56
|
-
return
|
|
65
|
+
return textEncoder.encode(JSON.stringify(valueArg)).byteLength <= byteLimitArg;
|
|
57
66
|
} catch {
|
|
58
67
|
return false;
|
|
59
68
|
}
|
|
60
69
|
};
|
|
61
70
|
|
|
71
|
+
const hasExactDeltaUtf8Coordinates = (
|
|
72
|
+
deltaArg: string,
|
|
73
|
+
baseTextUtf8BytesArg: number,
|
|
74
|
+
textUtf8BytesArg: number,
|
|
75
|
+
): boolean => {
|
|
76
|
+
const encodedDeltaBytes = textEncoder.encode(deltaArg).byteLength;
|
|
77
|
+
const increment = textUtf8BytesArg - baseTextUtf8BytesArg;
|
|
78
|
+
if (increment === encodedDeltaBytes) return true;
|
|
79
|
+
const firstCodeUnit = deltaArg.charCodeAt(0);
|
|
80
|
+
return firstCodeUnit >= 0xDC00
|
|
81
|
+
&& firstCodeUnit <= 0xDFFF
|
|
82
|
+
&& increment === encodedDeltaBytes - 2;
|
|
83
|
+
};
|
|
84
|
+
|
|
62
85
|
const isDraftAttachment = (valueArg: unknown): valueArg is interfaces.IControllerDraftAttachment => {
|
|
63
86
|
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) return false;
|
|
64
87
|
const candidate = valueArg as Partial<interfaces.IControllerDraftAttachment>;
|
|
@@ -68,13 +91,13 @@ const isDraftAttachment = (valueArg: unknown): valueArg is interfaces.IControlle
|
|
|
68
91
|
))
|
|
69
92
|
|| typeof candidate.id !== 'string'
|
|
70
93
|
|| candidate.id.length === 0
|
|
71
|
-
||
|
|
94
|
+
|| textEncoder.encode(candidate.id).byteLength > 512
|
|
72
95
|
|| typeof candidate.name !== 'string'
|
|
73
96
|
|| candidate.name.length === 0
|
|
74
|
-
||
|
|
97
|
+
|| textEncoder.encode(candidate.name).byteLength > 255
|
|
75
98
|
|| typeof candidate.mediaType !== 'string'
|
|
76
99
|
|| candidate.mediaType.length === 0
|
|
77
|
-
||
|
|
100
|
+
|| textEncoder.encode(candidate.mediaType).byteLength > 129
|
|
78
101
|
|| !Number.isSafeInteger(candidate.size)
|
|
79
102
|
|| (candidate.size ?? -1) < 0
|
|
80
103
|
|| (candidate.size ?? 0) > interfaces.controllerMaxDraftAttachmentBytes
|
|
@@ -101,7 +124,7 @@ const isSessionDraftUpdate = (
|
|
|
101
124
|
|| (candidate.text === undefined && candidate.attachments === undefined)
|
|
102
125
|
|| (candidate.text !== undefined && (
|
|
103
126
|
typeof candidate.text !== 'string'
|
|
104
|
-
||
|
|
127
|
+
|| textEncoder.encode(candidate.text).byteLength > interfaces.controllerMaxDraftTextBytes
|
|
105
128
|
))
|
|
106
129
|
|| (candidate.attachments !== undefined && (
|
|
107
130
|
!Array.isArray(candidate.attachments)
|
|
@@ -130,7 +153,7 @@ const isControllerToolExecution = (
|
|
|
130
153
|
&& isQualifiedRuntimeId(candidate.callId, executionHarnessIds)
|
|
131
154
|
&& typeof candidate.toolName === 'string'
|
|
132
155
|
&& candidate.toolName.length > 0
|
|
133
|
-
&&
|
|
156
|
+
&& textEncoder.encode(candidate.toolName).byteLength <= 2048
|
|
134
157
|
&& ['pending', 'running', 'completed', 'error'].includes(candidate.status ?? '')
|
|
135
158
|
&& (candidate.exitCode === undefined
|
|
136
159
|
|| (Number.isSafeInteger(candidate.exitCode) && candidate.exitCode >= 0))
|
|
@@ -166,7 +189,7 @@ const isControllerReasoningUpdate = (
|
|
|
166
189
|
&& isQualifiedRuntimeId(candidate.messageId, harnessIds)
|
|
167
190
|
&& isQualifiedRuntimeId(candidate.partId, harnessIds)
|
|
168
191
|
&& typeof candidate.text === 'string'
|
|
169
|
-
&&
|
|
192
|
+
&& textEncoder.encode(candidate.text).byteLength
|
|
170
193
|
<= interfaces.controllerMaxLiveMessageEventBytes
|
|
171
194
|
&& ['running', 'completed', 'cancelled'].includes(candidate.status ?? '')
|
|
172
195
|
&& (candidate.order === undefined || isTranscriptOrder(candidate.order))
|
|
@@ -193,7 +216,7 @@ const isControllerTextUpdate = (
|
|
|
193
216
|
&& isQualifiedRuntimeId(candidate.messageId, harnessIds)
|
|
194
217
|
&& isQualifiedRuntimeId(candidate.partId, harnessIds)
|
|
195
218
|
&& typeof candidate.text === 'string'
|
|
196
|
-
&&
|
|
219
|
+
&& textEncoder.encode(candidate.text).byteLength
|
|
197
220
|
<= interfaces.controllerMaxLiveMessageEventBytes
|
|
198
221
|
&& ['running', 'completed'].includes(candidate.status ?? '')
|
|
199
222
|
&& (candidate.order === undefined || isTranscriptOrder(candidate.order))
|
|
@@ -207,6 +230,48 @@ const isControllerTextUpdate = (
|
|
|
207
230
|
&& (candidate.streamEpoch ?? -1) >= 0;
|
|
208
231
|
};
|
|
209
232
|
|
|
233
|
+
const isControllerMessageDelta = (
|
|
234
|
+
valueArg: unknown,
|
|
235
|
+
): valueArg is interfaces.IControllerReasoningDelta | interfaces.IControllerTextDelta => {
|
|
236
|
+
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) return false;
|
|
237
|
+
const candidate = valueArg as Partial<interfaces.IControllerReasoningDelta>;
|
|
238
|
+
if (!isQualifiedRuntimeId(candidate.sessionId, sessionHarnessIds)) return false;
|
|
239
|
+
const harnessIds: ReadonlySet<interfaces.TControllerHarnessId> = new Set([
|
|
240
|
+
candidate.sessionId.harnessId,
|
|
241
|
+
]);
|
|
242
|
+
const keys = Object.keys(candidate);
|
|
243
|
+
const hasOrder = Object.prototype.hasOwnProperty.call(candidate, 'order');
|
|
244
|
+
return keys.length === messageDeltaRequiredKeys.length + (hasOrder ? 1 : 0)
|
|
245
|
+
&& keys.every((key) => messageDeltaKeys.has(key))
|
|
246
|
+
&& messageDeltaRequiredKeys.every((key) => (
|
|
247
|
+
Object.prototype.hasOwnProperty.call(candidate, key)
|
|
248
|
+
))
|
|
249
|
+
&& isQualifiedRuntimeId(candidate.messageId, harnessIds)
|
|
250
|
+
&& isQualifiedRuntimeId(candidate.partId, harnessIds)
|
|
251
|
+
&& typeof candidate.delta === 'string'
|
|
252
|
+
&& candidate.delta.length > 0
|
|
253
|
+
&& textEncoder.encode(candidate.delta).byteLength
|
|
254
|
+
<= interfaces.controllerMaxLiveMessageEventBytes
|
|
255
|
+
&& Number.isSafeInteger(candidate.baseTextUtf8Bytes)
|
|
256
|
+
&& (candidate.baseTextUtf8Bytes ?? -1) >= 0
|
|
257
|
+
&& Number.isSafeInteger(candidate.textUtf8Bytes)
|
|
258
|
+
&& (candidate.textUtf8Bytes ?? -1) > (candidate.baseTextUtf8Bytes ?? -1)
|
|
259
|
+
&& hasExactDeltaUtf8Coordinates(
|
|
260
|
+
candidate.delta,
|
|
261
|
+
candidate.baseTextUtf8Bytes!,
|
|
262
|
+
candidate.textUtf8Bytes!,
|
|
263
|
+
)
|
|
264
|
+
&& (!hasOrder || isTranscriptOrder(candidate.order))
|
|
265
|
+
&& (candidate.sessionId.harnessId !== 'flex' || hasOrder)
|
|
266
|
+
&& (candidate.sessionId.harnessId !== 'opencode' || !hasOrder)
|
|
267
|
+
&& typeof candidate.sourceUpdatedAt === 'number'
|
|
268
|
+
&& Number.isFinite(candidate.sourceUpdatedAt)
|
|
269
|
+
&& Number.isSafeInteger(candidate.revision)
|
|
270
|
+
&& (candidate.revision ?? -1) >= 0
|
|
271
|
+
&& Number.isSafeInteger(candidate.streamEpoch)
|
|
272
|
+
&& (candidate.streamEpoch ?? -1) >= 0;
|
|
273
|
+
};
|
|
274
|
+
|
|
210
275
|
export interface IControllerSocketClientOptions {
|
|
211
276
|
onStatus: (status: plugins.typedsocket.TConnectionStatus) => void;
|
|
212
277
|
onControllerEvent: (event: interfaces.IControllerEvent) => void | Promise<void>;
|
|
@@ -214,18 +279,11 @@ export interface IControllerSocketClientOptions {
|
|
|
214
279
|
onTerminalOutput?: (
|
|
215
280
|
output: interfaces.IReq_ControllerTerminalOutput['request'],
|
|
216
281
|
) => void | Promise<void>;
|
|
217
|
-
onBrowserViewEvent?: (
|
|
218
|
-
event: TControllerBrowserViewEventMessage,
|
|
219
|
-
) => void | Promise<void>;
|
|
220
282
|
/** Fires when the transport fail-closes the connection (e.g. frame limits). */
|
|
221
283
|
onTransportClose?: (closeCode: number, reason: string) => void;
|
|
284
|
+
onReconnectExhausted?: (attempts: number, endpoint: string) => void;
|
|
222
285
|
}
|
|
223
286
|
|
|
224
|
-
export type TControllerBrowserViewEventMessage =
|
|
225
|
-
plugins.typedrequest.TReverseVirtualStreamDirections<
|
|
226
|
-
interfaces.IReq_ControllerBrowserViewEvent['request']
|
|
227
|
-
>;
|
|
228
|
-
|
|
229
287
|
export interface IControllerSocketRequestOptions
|
|
230
288
|
extends plugins.typedrequest.ITypedRequestFireOptions {
|
|
231
289
|
abortSignal?: AbortSignal;
|
|
@@ -240,9 +298,18 @@ export const isControllerEvent = (valueArg: unknown): valueArg is interfaces.ICo
|
|
|
240
298
|
const hasSessionMarker = candidate.sessionStatus !== undefined || candidate.sessionError !== undefined;
|
|
241
299
|
const hasToolExecution = candidate.toolExecution !== undefined;
|
|
242
300
|
const hasReasoningUpdate = candidate.reasoningUpdate !== undefined;
|
|
301
|
+
const hasReasoningDelta = candidate.reasoningDelta !== undefined;
|
|
243
302
|
const hasTextUpdate = candidate.textUpdate !== undefined;
|
|
303
|
+
const hasTextDelta = candidate.textDelta !== undefined;
|
|
244
304
|
const hasDraftUpdate = candidate.sessionDraftUpdate !== undefined;
|
|
245
305
|
const hasUpgrade = candidate.upgrade !== undefined;
|
|
306
|
+
const livePayloadCount = [
|
|
307
|
+
hasToolExecution,
|
|
308
|
+
hasReasoningUpdate,
|
|
309
|
+
hasReasoningDelta,
|
|
310
|
+
hasTextUpdate,
|
|
311
|
+
hasTextDelta,
|
|
312
|
+
].filter(Boolean).length;
|
|
246
313
|
return (
|
|
247
314
|
typeof candidate.type === 'string'
|
|
248
315
|
&& controllerEventTypes.has(candidate.type as interfaces.TControllerEventType)
|
|
@@ -269,14 +336,19 @@ export const isControllerEvent = (valueArg: unknown): valueArg is interfaces.ICo
|
|
|
269
336
|
&& (candidate.toolExecution === undefined || isControllerToolExecution(candidate.toolExecution))
|
|
270
337
|
&& (candidate.reasoningUpdate === undefined
|
|
271
338
|
|| isControllerReasoningUpdate(candidate.reasoningUpdate))
|
|
339
|
+
&& (candidate.reasoningDelta === undefined
|
|
340
|
+
|| isControllerMessageDelta(candidate.reasoningDelta))
|
|
272
341
|
&& (candidate.textUpdate === undefined || isControllerTextUpdate(candidate.textUpdate))
|
|
342
|
+
&& (candidate.textDelta === undefined || isControllerMessageDelta(candidate.textDelta))
|
|
273
343
|
&& (candidate.sessionDraftUpdate === undefined
|
|
274
344
|
|| isSessionDraftUpdate(candidate.sessionDraftUpdate))
|
|
345
|
+
&& livePayloadCount <= 1
|
|
275
346
|
&& (!hasToolExecution || serializedBytesWithin(
|
|
276
347
|
candidate,
|
|
277
348
|
interfaces.controllerMaxToolEventBytes,
|
|
278
349
|
))
|
|
279
|
-
&& (!(hasReasoningUpdate || hasTextUpdate
|
|
350
|
+
&& (!(hasReasoningUpdate || hasReasoningDelta || hasTextUpdate || hasTextDelta)
|
|
351
|
+
|| serializedBytesWithin(
|
|
280
352
|
candidate,
|
|
281
353
|
interfaces.controllerMaxLiveMessageEventBytes,
|
|
282
354
|
))
|
|
@@ -312,6 +384,16 @@ export const isControllerEvent = (valueArg: unknown): valueArg is interfaces.ICo
|
|
|
312
384
|
=== interfaces.controllerRuntimeIdKey(candidate.reasoningUpdate!.sessionId)
|
|
313
385
|
))
|
|
314
386
|
&& (hasReasoningUpdate || candidate.type !== 'session.reasoning.updated')
|
|
387
|
+
&& (!hasReasoningDelta || (
|
|
388
|
+
candidate.type === 'session.reasoning.delta'
|
|
389
|
+
&& (candidate.harnessId === 'opencode' || candidate.harnessId === 'flex')
|
|
390
|
+
&& typeof candidate.projectId === 'string'
|
|
391
|
+
&& isQualifiedRuntimeId(candidate.sessionId, sessionHarnessIds)
|
|
392
|
+
&& candidate.harnessId === candidate.reasoningDelta!.sessionId.harnessId
|
|
393
|
+
&& interfaces.controllerRuntimeIdKey(candidate.sessionId)
|
|
394
|
+
=== interfaces.controllerRuntimeIdKey(candidate.reasoningDelta!.sessionId)
|
|
395
|
+
))
|
|
396
|
+
&& (hasReasoningDelta || candidate.type !== 'session.reasoning.delta')
|
|
315
397
|
&& (!hasTextUpdate || (
|
|
316
398
|
candidate.type === 'session.text.updated'
|
|
317
399
|
&& (candidate.harnessId === 'opencode' || candidate.harnessId === 'flex')
|
|
@@ -322,6 +404,16 @@ export const isControllerEvent = (valueArg: unknown): valueArg is interfaces.ICo
|
|
|
322
404
|
=== interfaces.controllerRuntimeIdKey(candidate.textUpdate!.sessionId)
|
|
323
405
|
))
|
|
324
406
|
&& (hasTextUpdate || candidate.type !== 'session.text.updated')
|
|
407
|
+
&& (!hasTextDelta || (
|
|
408
|
+
candidate.type === 'session.text.delta'
|
|
409
|
+
&& (candidate.harnessId === 'opencode' || candidate.harnessId === 'flex')
|
|
410
|
+
&& typeof candidate.projectId === 'string'
|
|
411
|
+
&& isQualifiedRuntimeId(candidate.sessionId, sessionHarnessIds)
|
|
412
|
+
&& candidate.harnessId === candidate.textDelta!.sessionId.harnessId
|
|
413
|
+
&& interfaces.controllerRuntimeIdKey(candidate.sessionId)
|
|
414
|
+
=== interfaces.controllerRuntimeIdKey(candidate.textDelta!.sessionId)
|
|
415
|
+
))
|
|
416
|
+
&& (hasTextDelta || candidate.type !== 'session.text.delta')
|
|
325
417
|
&& (!hasDraftUpdate || (
|
|
326
418
|
candidate.type === 'session.draft.changed'
|
|
327
419
|
&& typeof candidate.projectId === 'string'
|
|
@@ -337,7 +429,9 @@ export const isControllerEvent = (valueArg: unknown): valueArg is interfaces.ICo
|
|
|
337
429
|
candidate.type === 'harness.changed'
|
|
338
430
|
&& (candidate.harnessId === 'opencode' || candidate.harnessId === 'flex')
|
|
339
431
|
&& !hasReasoningUpdate
|
|
432
|
+
&& !hasReasoningDelta
|
|
340
433
|
&& !hasTextUpdate
|
|
434
|
+
&& !hasTextDelta
|
|
341
435
|
))
|
|
342
436
|
&& (candidate.upgrade === undefined || (
|
|
343
437
|
typeof candidate.upgrade === 'object'
|
|
@@ -345,10 +439,10 @@ export const isControllerEvent = (valueArg: unknown): valueArg is interfaces.ICo
|
|
|
345
439
|
&& Object.keys(candidate.upgrade).length === 3
|
|
346
440
|
&& typeof candidate.upgrade.fromVersion === 'string'
|
|
347
441
|
&& candidate.upgrade.fromVersion.length > 0
|
|
348
|
-
&&
|
|
442
|
+
&& textEncoder.encode(candidate.upgrade.fromVersion).byteLength <= 128
|
|
349
443
|
&& typeof candidate.upgrade.toVersion === 'string'
|
|
350
444
|
&& candidate.upgrade.toVersion.length > 0
|
|
351
|
-
&&
|
|
445
|
+
&& textEncoder.encode(candidate.upgrade.toVersion).byteLength <= 128
|
|
352
446
|
&& ['preparing', 'pausing', 'installing', 'restarting', 'continuing', 'completed', 'failed']
|
|
353
447
|
.includes(candidate.upgrade.phase)
|
|
354
448
|
))
|
|
@@ -401,15 +495,6 @@ export class ControllerSocketClient {
|
|
|
401
495
|
},
|
|
402
496
|
),
|
|
403
497
|
);
|
|
404
|
-
this.typedRouter.addTypedHandler(
|
|
405
|
-
new plugins.typedrequest.TypedHandler<interfaces.IReq_ControllerBrowserViewEvent>(
|
|
406
|
-
'controller.browser.view.event',
|
|
407
|
-
async (eventArg) => {
|
|
408
|
-
await this.options.onBrowserViewEvent?.(eventArg);
|
|
409
|
-
return {};
|
|
410
|
-
},
|
|
411
|
-
),
|
|
412
|
-
);
|
|
413
498
|
}
|
|
414
499
|
|
|
415
500
|
public get status(): plugins.typedsocket.TConnectionStatus {
|
|
@@ -507,6 +592,11 @@ export class ControllerSocketClient {
|
|
|
507
592
|
diagnosticArg.closeCode,
|
|
508
593
|
typeof diagnosticArg.reason === 'string' ? diagnosticArg.reason : '',
|
|
509
594
|
);
|
|
595
|
+
} else if (diagnosticArg.kind === 'reconnectExhausted') {
|
|
596
|
+
this.options.onReconnectExhausted?.(
|
|
597
|
+
diagnosticArg.attempts,
|
|
598
|
+
diagnosticArg.endpoint,
|
|
599
|
+
);
|
|
510
600
|
}
|
|
511
601
|
});
|
|
512
602
|
|