@band-ai/band-sdk-core 0.5.0 → 0.7.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/README.md +30 -0
- package/band_sdk_core.js +458 -0
- package/band_sdk_core_bg.wasm +0 -0
- package/index.d.ts +136 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -107,6 +107,36 @@ switch (tracker.recordRoomParticipantsJoinFailed("room-1", ticket, false)) {
|
|
|
107
107
|
}
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
+
### `Session` — WebSocket reconnect state machine
|
|
111
|
+
|
|
112
|
+
`Session`/`SessionPolicy` are a sans-io session state machine plus
|
|
113
|
+
reconnect backoff/jitter policy; `classifyClose`/`classifyUpgrade`
|
|
114
|
+
classify a WebSocket close code or HTTP upgrade-rejection status.
|
|
115
|
+
`Session` never sleeps, connects, or closes a socket itself — the caller
|
|
116
|
+
drives its own transport and reports what happened through `onConnected`/
|
|
117
|
+
`onSocketClose`/`onUpgradeRejected`/`onSupersede`. Its epoch tickets are
|
|
118
|
+
JavaScript `bigint` values, matching `SubscriptionTracker`'s. Confirmed
|
|
119
|
+
decisions:
|
|
120
|
+
[`runtime-state-policy.md`](https://github.com/band-ai/band-sdk-core/blob/main/crates/core/docs/runtime-state-policy.md)'s
|
|
121
|
+
`## Session` section.
|
|
122
|
+
|
|
123
|
+
### `Session` lifecycle
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
import { Session, SessionPolicy } from "@band-ai/band-sdk-core";
|
|
127
|
+
|
|
128
|
+
const session = new Session(SessionPolicy.default());
|
|
129
|
+
const epoch = session.beginAttempt(0.0);
|
|
130
|
+
if (epoch === undefined) throw new Error("fresh session must yield an epoch");
|
|
131
|
+
|
|
132
|
+
const connected = session.onConnected(epoch, 0.0);
|
|
133
|
+
if (connected.state !== "up") throw new Error("expected up");
|
|
134
|
+
|
|
135
|
+
const disconnected = session.onSocketClose(epoch, 5.0, 1006, 0.5);
|
|
136
|
+
if (disconnected.state !== "reconnecting") throw new Error("expected reconnecting");
|
|
137
|
+
if (disconnected.retryAfterS === undefined) throw new Error("expected a retry delay");
|
|
138
|
+
```
|
|
139
|
+
|
|
110
140
|
### `validateMemoryTypeForSystem(system, type, traceContext?)`
|
|
111
141
|
|
|
112
142
|
Validates the canonical memory taxonomy — design decisions:
|
package/band_sdk_core.js
CHANGED
|
@@ -348,6 +348,410 @@ class RetryTracker {
|
|
|
348
348
|
if (Symbol.dispose) RetryTracker.prototype[Symbol.dispose] = RetryTracker.prototype.free;
|
|
349
349
|
exports.RetryTracker = RetryTracker;
|
|
350
350
|
|
|
351
|
+
/**
|
|
352
|
+
* One reconnect's reconciliation against an authoritative room snapshot.
|
|
353
|
+
* `removed` and `admitting` are already applied by the time this is
|
|
354
|
+
* returned.
|
|
355
|
+
*/
|
|
356
|
+
class RoomReconciliation {
|
|
357
|
+
static __wrap(ptr) {
|
|
358
|
+
const obj = Object.create(RoomReconciliation.prototype);
|
|
359
|
+
obj.__wbg_ptr = ptr;
|
|
360
|
+
RoomReconciliationFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
361
|
+
return obj;
|
|
362
|
+
}
|
|
363
|
+
__destroy_into_raw() {
|
|
364
|
+
const ptr = this.__wbg_ptr;
|
|
365
|
+
this.__wbg_ptr = 0;
|
|
366
|
+
RoomReconciliationFinalization.unregister(this);
|
|
367
|
+
return ptr;
|
|
368
|
+
}
|
|
369
|
+
free() {
|
|
370
|
+
const ptr = this.__destroy_into_raw();
|
|
371
|
+
wasm.__wbg_roomreconciliation_free(ptr, 0);
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* @returns {Array<any>}
|
|
375
|
+
*/
|
|
376
|
+
get admitting() {
|
|
377
|
+
const ret = wasm.roomreconciliation_admitting(this.__wbg_ptr);
|
|
378
|
+
return ret;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* @returns {string[]}
|
|
382
|
+
*/
|
|
383
|
+
get removed() {
|
|
384
|
+
const ret = wasm.roomreconciliation_removed(this.__wbg_ptr);
|
|
385
|
+
var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]);
|
|
386
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
387
|
+
return v1;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* @returns {string[]}
|
|
391
|
+
*/
|
|
392
|
+
get resync() {
|
|
393
|
+
const ret = wasm.roomreconciliation_resync(this.__wbg_ptr);
|
|
394
|
+
var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]);
|
|
395
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
396
|
+
return v1;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (Symbol.dispose) RoomReconciliation.prototype[Symbol.dispose] = RoomReconciliation.prototype.free;
|
|
400
|
+
exports.RoomReconciliation = RoomReconciliation;
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Room admission and membership decisions for one agent session, separate
|
|
404
|
+
* from `SubscriptionTracker`'s two-topic transport join.
|
|
405
|
+
*/
|
|
406
|
+
class RoomRoster {
|
|
407
|
+
__destroy_into_raw() {
|
|
408
|
+
const ptr = this.__wbg_ptr;
|
|
409
|
+
this.__wbg_ptr = 0;
|
|
410
|
+
RoomRosterFinalization.unregister(this);
|
|
411
|
+
return ptr;
|
|
412
|
+
}
|
|
413
|
+
free() {
|
|
414
|
+
const ptr = this.__destroy_into_raw();
|
|
415
|
+
wasm.__wbg_roomroster_free(ptr, 0);
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* @param {any} room_id
|
|
419
|
+
* @param {boolean} passesFilter
|
|
420
|
+
* @returns {bigint | undefined}
|
|
421
|
+
*/
|
|
422
|
+
beginRoomAdmission(room_id, passesFilter) {
|
|
423
|
+
const ret = wasm.roomroster_beginRoomAdmission(this.__wbg_ptr, room_id, passesFilter);
|
|
424
|
+
if (ret[3]) {
|
|
425
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
426
|
+
}
|
|
427
|
+
return ret[0] === 0 ? undefined : BigInt.asUintN(64, ret[1]);
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* @returns {string[]}
|
|
431
|
+
*/
|
|
432
|
+
clear() {
|
|
433
|
+
const ret = wasm.roomroster_clear(this.__wbg_ptr);
|
|
434
|
+
var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]);
|
|
435
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
436
|
+
return v1;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* @param {any} room_id
|
|
440
|
+
* @param {bigint} ticket
|
|
441
|
+
* @returns {boolean}
|
|
442
|
+
*/
|
|
443
|
+
isRoomAdmissionCurrent(room_id, ticket) {
|
|
444
|
+
const ret = wasm.roomroster_isRoomAdmissionCurrent(this.__wbg_ptr, room_id, ticket);
|
|
445
|
+
if (ret[2]) {
|
|
446
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
447
|
+
}
|
|
448
|
+
return ret[0] !== 0;
|
|
449
|
+
}
|
|
450
|
+
constructor() {
|
|
451
|
+
const ret = wasm.roomroster_new();
|
|
452
|
+
this.__wbg_ptr = ret;
|
|
453
|
+
RoomRosterFinalization.register(this, this.__wbg_ptr, this);
|
|
454
|
+
return this;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* @param {any} current_room_ids
|
|
458
|
+
* @returns {RoomReconciliation}
|
|
459
|
+
*/
|
|
460
|
+
reconcile(current_room_ids) {
|
|
461
|
+
const ret = wasm.roomroster_reconcile(this.__wbg_ptr, current_room_ids);
|
|
462
|
+
if (ret[2]) {
|
|
463
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
464
|
+
}
|
|
465
|
+
return RoomReconciliation.__wrap(ret[0]);
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* @param {any} room_id
|
|
469
|
+
* @param {bigint} ticket
|
|
470
|
+
* @param {boolean} succeeded
|
|
471
|
+
* @returns {boolean}
|
|
472
|
+
*/
|
|
473
|
+
recordRoomAdmission(room_id, ticket, succeeded) {
|
|
474
|
+
const ret = wasm.roomroster_recordRoomAdmission(this.__wbg_ptr, room_id, ticket, succeeded);
|
|
475
|
+
if (ret[2]) {
|
|
476
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
477
|
+
}
|
|
478
|
+
return ret[0] !== 0;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* @param {any} room_id
|
|
482
|
+
* @returns {boolean}
|
|
483
|
+
*/
|
|
484
|
+
recordRoomRemoved(room_id) {
|
|
485
|
+
const ret = wasm.roomroster_recordRoomRemoved(this.__wbg_ptr, room_id);
|
|
486
|
+
if (ret[2]) {
|
|
487
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
488
|
+
}
|
|
489
|
+
return ret[0] !== 0;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* @param {any} room_id
|
|
493
|
+
* @returns {string}
|
|
494
|
+
*/
|
|
495
|
+
roomMembership(room_id) {
|
|
496
|
+
const ret = wasm.roomroster_roomMembership(this.__wbg_ptr, room_id);
|
|
497
|
+
if (ret[3]) {
|
|
498
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
499
|
+
}
|
|
500
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* @returns {string[]}
|
|
504
|
+
*/
|
|
505
|
+
trackedRoomIds() {
|
|
506
|
+
const ret = wasm.roomroster_trackedRoomIds(this.__wbg_ptr);
|
|
507
|
+
var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]);
|
|
508
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
509
|
+
return v1;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if (Symbol.dispose) RoomRoster.prototype[Symbol.dispose] = RoomRoster.prototype.free;
|
|
513
|
+
exports.RoomRoster = RoomRoster;
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* One WebSocket session's state machine. Behavior contract:
|
|
517
|
+
* `docs/runtime-state-policy.md`'s `## Session` section.
|
|
518
|
+
*/
|
|
519
|
+
class Session {
|
|
520
|
+
__destroy_into_raw() {
|
|
521
|
+
const ptr = this.__wbg_ptr;
|
|
522
|
+
this.__wbg_ptr = 0;
|
|
523
|
+
SessionFinalization.unregister(this);
|
|
524
|
+
return ptr;
|
|
525
|
+
}
|
|
526
|
+
free() {
|
|
527
|
+
const ptr = this.__destroy_into_raw();
|
|
528
|
+
wasm.__wbg_session_free(ptr, 0);
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* @param {number} nowS
|
|
532
|
+
* @returns {bigint | undefined}
|
|
533
|
+
*/
|
|
534
|
+
beginAttempt(nowS) {
|
|
535
|
+
const ret = wasm.session_beginAttempt(this.__wbg_ptr, nowS);
|
|
536
|
+
if (ret[3]) {
|
|
537
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
538
|
+
}
|
|
539
|
+
return ret[0] === 0 ? undefined : BigInt.asUintN(64, ret[1]);
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* @returns {string}
|
|
543
|
+
*/
|
|
544
|
+
end() {
|
|
545
|
+
let deferred1_0;
|
|
546
|
+
let deferred1_1;
|
|
547
|
+
try {
|
|
548
|
+
const ret = wasm.session_end(this.__wbg_ptr);
|
|
549
|
+
deferred1_0 = ret[0];
|
|
550
|
+
deferred1_1 = ret[1];
|
|
551
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
552
|
+
} finally {
|
|
553
|
+
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* @param {SessionPolicy} policy
|
|
558
|
+
*/
|
|
559
|
+
constructor(policy) {
|
|
560
|
+
_assertClass(policy, SessionPolicy);
|
|
561
|
+
const ret = wasm.session_new(policy.__wbg_ptr);
|
|
562
|
+
this.__wbg_ptr = ret;
|
|
563
|
+
SessionFinalization.register(this, this.__wbg_ptr, this);
|
|
564
|
+
return this;
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* @param {bigint} epoch
|
|
568
|
+
* @param {number} nowS
|
|
569
|
+
* @returns {SessionOutcome}
|
|
570
|
+
*/
|
|
571
|
+
onConnected(epoch, nowS) {
|
|
572
|
+
const ret = wasm.session_onConnected(this.__wbg_ptr, epoch, nowS);
|
|
573
|
+
if (ret[2]) {
|
|
574
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
575
|
+
}
|
|
576
|
+
return SessionOutcome.__wrap(ret[0]);
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* @param {bigint} epoch
|
|
580
|
+
* @param {number} nowS
|
|
581
|
+
* @param {number | null | undefined} closeCode
|
|
582
|
+
* @param {number} jitterSample
|
|
583
|
+
* @returns {SessionOutcome}
|
|
584
|
+
*/
|
|
585
|
+
onSocketClose(epoch, nowS, closeCode, jitterSample) {
|
|
586
|
+
const ret = wasm.session_onSocketClose(this.__wbg_ptr, epoch, nowS, !isLikeNone(closeCode), isLikeNone(closeCode) ? 0 : closeCode, jitterSample);
|
|
587
|
+
if (ret[2]) {
|
|
588
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
589
|
+
}
|
|
590
|
+
return SessionOutcome.__wrap(ret[0]);
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* @param {number} nowS
|
|
594
|
+
* @param {boolean} retryable
|
|
595
|
+
* @param {number | null | undefined} retryAfterS
|
|
596
|
+
* @param {number} jitterSample
|
|
597
|
+
* @returns {SessionOutcome}
|
|
598
|
+
*/
|
|
599
|
+
onSupersede(nowS, retryable, retryAfterS, jitterSample) {
|
|
600
|
+
const ret = wasm.session_onSupersede(this.__wbg_ptr, nowS, retryable, !isLikeNone(retryAfterS), isLikeNone(retryAfterS) ? 0 : retryAfterS, jitterSample);
|
|
601
|
+
if (ret[2]) {
|
|
602
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
603
|
+
}
|
|
604
|
+
return SessionOutcome.__wrap(ret[0]);
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* @param {bigint} epoch
|
|
608
|
+
* @param {number} nowS
|
|
609
|
+
* @param {number} status
|
|
610
|
+
* @param {number | null | undefined} retryAfterS
|
|
611
|
+
* @param {number} jitterSample
|
|
612
|
+
* @returns {SessionOutcome}
|
|
613
|
+
*/
|
|
614
|
+
onUpgradeRejected(epoch, nowS, status, retryAfterS, jitterSample) {
|
|
615
|
+
const ret = wasm.session_onUpgradeRejected(this.__wbg_ptr, epoch, nowS, status, !isLikeNone(retryAfterS), isLikeNone(retryAfterS) ? 0 : retryAfterS, jitterSample);
|
|
616
|
+
if (ret[2]) {
|
|
617
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
618
|
+
}
|
|
619
|
+
return SessionOutcome.__wrap(ret[0]);
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* @returns {string}
|
|
623
|
+
*/
|
|
624
|
+
get state() {
|
|
625
|
+
let deferred1_0;
|
|
626
|
+
let deferred1_1;
|
|
627
|
+
try {
|
|
628
|
+
const ret = wasm.session_state(this.__wbg_ptr);
|
|
629
|
+
deferred1_0 = ret[0];
|
|
630
|
+
deferred1_1 = ret[1];
|
|
631
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
632
|
+
} finally {
|
|
633
|
+
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
if (Symbol.dispose) Session.prototype[Symbol.dispose] = Session.prototype.free;
|
|
638
|
+
exports.Session = Session;
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* The settled outcome of one `Session` call.
|
|
642
|
+
*/
|
|
643
|
+
class SessionOutcome {
|
|
644
|
+
static __wrap(ptr) {
|
|
645
|
+
const obj = Object.create(SessionOutcome.prototype);
|
|
646
|
+
obj.__wbg_ptr = ptr;
|
|
647
|
+
SessionOutcomeFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
648
|
+
return obj;
|
|
649
|
+
}
|
|
650
|
+
__destroy_into_raw() {
|
|
651
|
+
const ptr = this.__wbg_ptr;
|
|
652
|
+
this.__wbg_ptr = 0;
|
|
653
|
+
SessionOutcomeFinalization.unregister(this);
|
|
654
|
+
return ptr;
|
|
655
|
+
}
|
|
656
|
+
free() {
|
|
657
|
+
const ptr = this.__destroy_into_raw();
|
|
658
|
+
wasm.__wbg_sessionoutcome_free(ptr, 0);
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* @returns {string | undefined}
|
|
662
|
+
*/
|
|
663
|
+
get deadReason() {
|
|
664
|
+
const ret = wasm.sessionoutcome_deadReason(this.__wbg_ptr);
|
|
665
|
+
let v1;
|
|
666
|
+
if (ret[0] !== 0) {
|
|
667
|
+
v1 = getStringFromWasm0(ret[0], ret[1]);
|
|
668
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
669
|
+
}
|
|
670
|
+
return v1;
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* @returns {number | undefined}
|
|
674
|
+
*/
|
|
675
|
+
get retryAfterS() {
|
|
676
|
+
const ret = wasm.sessionoutcome_retryAfterS(this.__wbg_ptr);
|
|
677
|
+
return ret[0] === 0 ? undefined : ret[1];
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* @returns {boolean}
|
|
681
|
+
*/
|
|
682
|
+
get stale() {
|
|
683
|
+
const ret = wasm.sessionoutcome_stale(this.__wbg_ptr);
|
|
684
|
+
return ret !== 0;
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* @returns {string}
|
|
688
|
+
*/
|
|
689
|
+
get state() {
|
|
690
|
+
let deferred1_0;
|
|
691
|
+
let deferred1_1;
|
|
692
|
+
try {
|
|
693
|
+
const ret = wasm.sessionoutcome_state(this.__wbg_ptr);
|
|
694
|
+
deferred1_0 = ret[0];
|
|
695
|
+
deferred1_1 = ret[1];
|
|
696
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
697
|
+
} finally {
|
|
698
|
+
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
if (Symbol.dispose) SessionOutcome.prototype[Symbol.dispose] = SessionOutcome.prototype.free;
|
|
703
|
+
exports.SessionOutcome = SessionOutcome;
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* Reconnect backoff/jitter policy, plus the graduated rapid-disconnect
|
|
707
|
+
* cooldown ladder. Behavior contract: `docs/runtime-state-policy.md`'s
|
|
708
|
+
* `## Session` section.
|
|
709
|
+
*/
|
|
710
|
+
class SessionPolicy {
|
|
711
|
+
static __wrap(ptr) {
|
|
712
|
+
const obj = Object.create(SessionPolicy.prototype);
|
|
713
|
+
obj.__wbg_ptr = ptr;
|
|
714
|
+
SessionPolicyFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
715
|
+
return obj;
|
|
716
|
+
}
|
|
717
|
+
__destroy_into_raw() {
|
|
718
|
+
const ptr = this.__wbg_ptr;
|
|
719
|
+
this.__wbg_ptr = 0;
|
|
720
|
+
SessionPolicyFinalization.unregister(this);
|
|
721
|
+
return ptr;
|
|
722
|
+
}
|
|
723
|
+
free() {
|
|
724
|
+
const ptr = this.__destroy_into_raw();
|
|
725
|
+
wasm.__wbg_sessionpolicy_free(ptr, 0);
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* A recommended, not final, default.
|
|
729
|
+
* @returns {SessionPolicy}
|
|
730
|
+
*/
|
|
731
|
+
static default() {
|
|
732
|
+
const ret = wasm.sessionpolicy_default();
|
|
733
|
+
return SessionPolicy.__wrap(ret);
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* `config` is any plain object with the fields declared in
|
|
737
|
+
* `index.d.ts`'s `SessionPolicyConfig`; grouped into one value rather
|
|
738
|
+
* than a flat, many-argument constructor.
|
|
739
|
+
* @param {any} config
|
|
740
|
+
* @param {any} traceContext
|
|
741
|
+
*/
|
|
742
|
+
constructor(config, traceContext) {
|
|
743
|
+
const ret = wasm.sessionpolicy_new(config, traceContext);
|
|
744
|
+
if (ret[2]) {
|
|
745
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
746
|
+
}
|
|
747
|
+
this.__wbg_ptr = ret[0];
|
|
748
|
+
SessionPolicyFinalization.register(this, this.__wbg_ptr, this);
|
|
749
|
+
return this;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
if (Symbol.dispose) SessionPolicy.prototype[Symbol.dispose] = SessionPolicy.prototype.free;
|
|
753
|
+
exports.SessionPolicy = SessionPolicy;
|
|
754
|
+
|
|
351
755
|
/**
|
|
352
756
|
* Transport-independent subscription decisions for one agent session.
|
|
353
757
|
*/
|
|
@@ -606,6 +1010,35 @@ class SubscriptionTracker {
|
|
|
606
1010
|
if (Symbol.dispose) SubscriptionTracker.prototype[Symbol.dispose] = SubscriptionTracker.prototype.free;
|
|
607
1011
|
exports.SubscriptionTracker = SubscriptionTracker;
|
|
608
1012
|
|
|
1013
|
+
/**
|
|
1014
|
+
* Classify a WebSocket close code. Returns `[terminal, delayRange]`.
|
|
1015
|
+
* @param {number | null} [closeCode]
|
|
1016
|
+
* @returns {Array<any>}
|
|
1017
|
+
*/
|
|
1018
|
+
function classifyClose(closeCode) {
|
|
1019
|
+
const ret = wasm.classifyClose(!isLikeNone(closeCode), isLikeNone(closeCode) ? 0 : closeCode);
|
|
1020
|
+
if (ret[2]) {
|
|
1021
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
1022
|
+
}
|
|
1023
|
+
return takeFromExternrefTable0(ret[0]);
|
|
1024
|
+
}
|
|
1025
|
+
exports.classifyClose = classifyClose;
|
|
1026
|
+
|
|
1027
|
+
/**
|
|
1028
|
+
* Classify an HTTP upgrade-rejection status code. Returns
|
|
1029
|
+
* `[terminal, delayRange]`.
|
|
1030
|
+
* @param {number} status
|
|
1031
|
+
* @returns {Array<any>}
|
|
1032
|
+
*/
|
|
1033
|
+
function classifyUpgrade(status) {
|
|
1034
|
+
const ret = wasm.classifyUpgrade(status);
|
|
1035
|
+
if (ret[2]) {
|
|
1036
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
1037
|
+
}
|
|
1038
|
+
return takeFromExternrefTable0(ret[0]);
|
|
1039
|
+
}
|
|
1040
|
+
exports.classifyUpgrade = classifyUpgrade;
|
|
1041
|
+
|
|
609
1042
|
/**
|
|
610
1043
|
* Validate and normalize an inbound platform event payload.
|
|
611
1044
|
*
|
|
@@ -744,6 +1177,10 @@ function __wbg_get_imports() {
|
|
|
744
1177
|
const ret = Object.entries(arg0);
|
|
745
1178
|
return ret;
|
|
746
1179
|
},
|
|
1180
|
+
__wbg_get_971a0c45d172643f: function() { return handleError(function (arg0, arg1) {
|
|
1181
|
+
const ret = Reflect.get(arg0, arg1);
|
|
1182
|
+
return ret;
|
|
1183
|
+
}, arguments); },
|
|
747
1184
|
__wbg_get_c0c8f8d7da0c03dd: function(arg0, arg1) {
|
|
748
1185
|
const ret = arg0[arg1 >>> 0];
|
|
749
1186
|
return ret;
|
|
@@ -908,6 +1345,21 @@ const ParticipantRosterFinalization = (typeof FinalizationRegistry === 'undefine
|
|
|
908
1345
|
const RetryTrackerFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
909
1346
|
? { register: () => {}, unregister: () => {} }
|
|
910
1347
|
: new FinalizationRegistry(ptr => wasm.__wbg_retrytracker_free(ptr, 1));
|
|
1348
|
+
const RoomReconciliationFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
1349
|
+
? { register: () => {}, unregister: () => {} }
|
|
1350
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_roomreconciliation_free(ptr, 1));
|
|
1351
|
+
const RoomRosterFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
1352
|
+
? { register: () => {}, unregister: () => {} }
|
|
1353
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_roomroster_free(ptr, 1));
|
|
1354
|
+
const SessionFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
1355
|
+
? { register: () => {}, unregister: () => {} }
|
|
1356
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_session_free(ptr, 1));
|
|
1357
|
+
const SessionOutcomeFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
1358
|
+
? { register: () => {}, unregister: () => {} }
|
|
1359
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_sessionoutcome_free(ptr, 1));
|
|
1360
|
+
const SessionPolicyFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
1361
|
+
? { register: () => {}, unregister: () => {} }
|
|
1362
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_sessionpolicy_free(ptr, 1));
|
|
911
1363
|
const SubscriptionTrackerFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
912
1364
|
? { register: () => {}, unregister: () => {} }
|
|
913
1365
|
: new FinalizationRegistry(ptr => wasm.__wbg_subscriptiontracker_free(ptr, 1));
|
|
@@ -918,6 +1370,12 @@ function addToExternrefTable0(obj) {
|
|
|
918
1370
|
return idx;
|
|
919
1371
|
}
|
|
920
1372
|
|
|
1373
|
+
function _assertClass(instance, klass) {
|
|
1374
|
+
if (!(instance instanceof klass)) {
|
|
1375
|
+
throw new Error(`expected instance of ${klass.name}`);
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
|
|
921
1379
|
function debugString(val) {
|
|
922
1380
|
// primitive types
|
|
923
1381
|
const type = typeof val;
|
package/band_sdk_core_bg.wasm
CHANGED
|
Binary file
|
package/index.d.ts
CHANGED
|
@@ -169,6 +169,110 @@ export type AgentTopicStatus =
|
|
|
169
169
|
|
|
170
170
|
export type LeaveOutcome = "left" | "failed" | "unknown";
|
|
171
171
|
|
|
172
|
+
export type SessionState = "connecting" | "up" | "reconnecting" | "dead";
|
|
173
|
+
|
|
174
|
+
export type DeadReason = "classified" | "rapid_disconnect";
|
|
175
|
+
|
|
176
|
+
export type RoomMembership = "unadmitted" | "admitting" | "admitted";
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Classify a WebSocket close code. Returns `[terminal, delayRange]`.
|
|
180
|
+
* Throws a plain `Error` if `closeCode` is not an integer in `0..=65535`
|
|
181
|
+
* (or `undefined`).
|
|
182
|
+
*/
|
|
183
|
+
export function classifyClose(
|
|
184
|
+
closeCode: number | undefined,
|
|
185
|
+
): [boolean, [number, number] | undefined];
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Classify an HTTP upgrade-rejection status code. Returns
|
|
189
|
+
* `[terminal, delayRange]`. Throws a plain `Error` if `status` is not an
|
|
190
|
+
* integer in `0..=65535`.
|
|
191
|
+
*/
|
|
192
|
+
export function classifyUpgrade(
|
|
193
|
+
status: number,
|
|
194
|
+
): [boolean, [number, number] | undefined];
|
|
195
|
+
|
|
196
|
+
/** The settled outcome of one {@link Session} call. */
|
|
197
|
+
export class SessionOutcome {
|
|
198
|
+
private constructor();
|
|
199
|
+
readonly state: SessionState;
|
|
200
|
+
readonly retryAfterS: number | undefined;
|
|
201
|
+
readonly deadReason: DeadReason | undefined;
|
|
202
|
+
readonly stale: boolean;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** {@link SessionPolicy}'s constructor fields. */
|
|
206
|
+
export interface SessionPolicyConfig {
|
|
207
|
+
baseDelayS: number;
|
|
208
|
+
factor: number;
|
|
209
|
+
maxDelayS: number;
|
|
210
|
+
stableResetS: number;
|
|
211
|
+
rapidDisconnectUptimeS: number;
|
|
212
|
+
rapidWindowS: number;
|
|
213
|
+
rapidFirstMinDelayS: number;
|
|
214
|
+
rapidSecondMinDelayS: number;
|
|
215
|
+
rapidCooldownBaseS: number;
|
|
216
|
+
rapidCooldownStepS: number;
|
|
217
|
+
rapidCooldownMaxS: number;
|
|
218
|
+
rapidThreshold: number;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Reconnect backoff/jitter policy, plus the graduated rapid-disconnect
|
|
223
|
+
* cooldown ladder. A recommended, not final, starting design -- see
|
|
224
|
+
* `docs/runtime-state-policy.md`'s `## Session` section.
|
|
225
|
+
*
|
|
226
|
+
* Throws a native `Error` with `.issues`/`.traceContext` if `factor < 1.0`
|
|
227
|
+
* or `baseDelayS > maxDelayS`. Throws a plain `Error` if `config` is
|
|
228
|
+
* missing a field or a field is not a finite, non-negative number
|
|
229
|
+
* (`rapidThreshold` must also be an integer).
|
|
230
|
+
*/
|
|
231
|
+
export class SessionPolicy {
|
|
232
|
+
constructor(config: SessionPolicyConfig, traceContext?: string | null);
|
|
233
|
+
/** A recommended, not final, default. */
|
|
234
|
+
static default(): SessionPolicy;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* One WebSocket session's state machine: which epoch (connection attempt)
|
|
239
|
+
* is live, the current lifecycle state, and the reconnect/rapid-disconnect
|
|
240
|
+
* bookkeeping. Single-writer -- exactly one owner drives a given `Session`
|
|
241
|
+
* at a time.
|
|
242
|
+
*
|
|
243
|
+
* `nowS`/`retryAfterS` each throw a plain `Error` if not a finite,
|
|
244
|
+
* non-negative number; `jitterSample` throws unless it's a finite number
|
|
245
|
+
* in `[0.0, 1.0]` (a fraction, not an open-ended time value);
|
|
246
|
+
* `closeCode`/`status` throw if not an integer in `0..=65535` (or
|
|
247
|
+
* `undefined` for `closeCode`).
|
|
248
|
+
*/
|
|
249
|
+
export class Session {
|
|
250
|
+
constructor(policy: SessionPolicy);
|
|
251
|
+
readonly state: SessionState;
|
|
252
|
+
beginAttempt(nowS: number): bigint | undefined;
|
|
253
|
+
onConnected(epoch: bigint, nowS: number): SessionOutcome;
|
|
254
|
+
onSocketClose(
|
|
255
|
+
epoch: bigint,
|
|
256
|
+
nowS: number,
|
|
257
|
+
closeCode: number | undefined,
|
|
258
|
+
jitterSample: number,
|
|
259
|
+
): SessionOutcome;
|
|
260
|
+
onUpgradeRejected(
|
|
261
|
+
epoch: bigint,
|
|
262
|
+
nowS: number,
|
|
263
|
+
status: number,
|
|
264
|
+
retryAfterS: number | undefined,
|
|
265
|
+
jitterSample: number,
|
|
266
|
+
): SessionOutcome;
|
|
267
|
+
onSupersede(
|
|
268
|
+
nowS: number,
|
|
269
|
+
retryable: boolean,
|
|
270
|
+
retryAfterS: number | undefined,
|
|
271
|
+
jitterSample: number,
|
|
272
|
+
): SessionOutcome;
|
|
273
|
+
end(): SessionState;
|
|
274
|
+
}
|
|
275
|
+
|
|
172
276
|
/** Transport-independent subscription decisions for one agent session. */
|
|
173
277
|
export class SubscriptionTracker {
|
|
174
278
|
constructor();
|
|
@@ -195,3 +299,35 @@ export class SubscriptionTracker {
|
|
|
195
299
|
acknowledgeAgentTopicReconciled(topic: string): boolean;
|
|
196
300
|
joinedAgentTopics(): string[];
|
|
197
301
|
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* One reconnect's reconciliation against an authoritative room snapshot.
|
|
305
|
+
* `removed` and `admitting` are already applied by the time this is
|
|
306
|
+
* returned.
|
|
307
|
+
*/
|
|
308
|
+
export class RoomReconciliation {
|
|
309
|
+
private constructor();
|
|
310
|
+
readonly removed: string[];
|
|
311
|
+
readonly admitting: Array<[string, bigint]>;
|
|
312
|
+
readonly resync: string[];
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Room admission and membership decisions for one agent session, separate
|
|
317
|
+
* from {@link SubscriptionTracker}'s two-topic transport join.
|
|
318
|
+
*
|
|
319
|
+
* Every `roomId` argument below throws a plain `Error` if it is not a
|
|
320
|
+
* string. `reconcile` throws a plain `Error` if `currentRoomIds` is not an
|
|
321
|
+
* array of strings.
|
|
322
|
+
*/
|
|
323
|
+
export class RoomRoster {
|
|
324
|
+
constructor();
|
|
325
|
+
roomMembership(roomId: string): RoomMembership;
|
|
326
|
+
beginRoomAdmission(roomId: string, passesFilter: boolean): bigint | undefined;
|
|
327
|
+
recordRoomAdmission(roomId: string, ticket: bigint, succeeded: boolean): boolean;
|
|
328
|
+
isRoomAdmissionCurrent(roomId: string, ticket: bigint): boolean;
|
|
329
|
+
recordRoomRemoved(roomId: string): boolean;
|
|
330
|
+
trackedRoomIds(): string[];
|
|
331
|
+
reconcile(currentRoomIds: string[]): RoomReconciliation;
|
|
332
|
+
clear(): string[];
|
|
333
|
+
}
|