@band-ai/band-sdk-core 0.4.1 → 0.6.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 +70 -1
- package/band_sdk_core.js +549 -0
- package/band_sdk_core_bg.wasm +0 -0
- package/index.d.ts +152 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ exception class.
|
|
|
54
54
|
|
|
55
55
|
### Delivery-state runtime classes
|
|
56
56
|
|
|
57
|
-
`ClaimRegistry`, `RetryTracker`, and `
|
|
57
|
+
`ClaimRegistry`, `RetryTracker`, `ParticipantRoster`, and `SubscriptionTracker` are the
|
|
58
58
|
inbound-delivery runtime state classes — lifecycle and design decisions:
|
|
59
59
|
[`runtime-state-policy.md`](https://github.com/band-ai/band-sdk-core/blob/main/crates/core/docs/runtime-state-policy.md).
|
|
60
60
|
|
|
@@ -68,6 +68,75 @@ snapshot names the same `id` twice. `RetryTracker`'s `maxTracked` must be
|
|
|
68
68
|
at least `1`; `0` throws. `ClaimRegistry`'s `maxCompleted` must be at
|
|
69
69
|
least `1` too — `0` also throws.
|
|
70
70
|
|
|
71
|
+
`SubscriptionTracker` provides synchronous, transport-independent decisions for
|
|
72
|
+
agent-topic joins and the two-topic room subscription transaction. Its opaque
|
|
73
|
+
tickets are JavaScript `bigint` values and must be supplied when recording a
|
|
74
|
+
completion. Failed rollbacks and failed or unknown leaves require explicit
|
|
75
|
+
reconciliation before a fresh claim is allowed.
|
|
76
|
+
|
|
77
|
+
### `SubscriptionTracker` lifecycle
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { SubscriptionTracker } from "@band-ai/band-sdk-core";
|
|
81
|
+
|
|
82
|
+
const tracker = new SubscriptionTracker();
|
|
83
|
+
const ticket = tracker.beginRoomSubscribe("room-1");
|
|
84
|
+
if (ticket === undefined) throw new Error("room is not claimable");
|
|
85
|
+
|
|
86
|
+
switch (tracker.recordRoomParticipantsJoinFailed("room-1", ticket, false)) {
|
|
87
|
+
case "rollback_failed":
|
|
88
|
+
if (tracker.roomStatus("room-1") !== "needs_reconciliation") {
|
|
89
|
+
throw new Error("rollback state was not retained");
|
|
90
|
+
}
|
|
91
|
+
tracker.acknowledgeRoomReconciled("room-1");
|
|
92
|
+
const retryTicket = tracker.beginRoomSubscribe("room-1");
|
|
93
|
+
if (retryTicket === undefined) throw new Error("reconciled room is not claimable");
|
|
94
|
+
if (tracker.recordBothRoomTopicsJoined("room-1", retryTicket) !== "subscribed") {
|
|
95
|
+
throw new Error("room did not subscribe");
|
|
96
|
+
}
|
|
97
|
+
const leaveTicket = tracker.unsubscribeRoom("room-1");
|
|
98
|
+
if (leaveTicket === undefined || !tracker.markRoomLeaveComplete("room-1", leaveTicket, "left")) {
|
|
99
|
+
throw new Error("room did not leave");
|
|
100
|
+
}
|
|
101
|
+
break;
|
|
102
|
+
case "subscribed":
|
|
103
|
+
case "join_failed":
|
|
104
|
+
case "rolled_back":
|
|
105
|
+
case "stale":
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
```
|
|
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
|
+
|
|
71
140
|
### `validateMemoryTypeForSystem(system, type, traceContext?)`
|
|
72
141
|
|
|
73
142
|
Validates the canonical memory taxonomy — design decisions:
|
package/band_sdk_core.js
CHANGED
|
@@ -348,6 +348,533 @@ class RetryTracker {
|
|
|
348
348
|
if (Symbol.dispose) RetryTracker.prototype[Symbol.dispose] = RetryTracker.prototype.free;
|
|
349
349
|
exports.RetryTracker = RetryTracker;
|
|
350
350
|
|
|
351
|
+
/**
|
|
352
|
+
* One WebSocket session's state machine. Behavior contract:
|
|
353
|
+
* `docs/runtime-state-policy.md`'s `## Session` section.
|
|
354
|
+
*/
|
|
355
|
+
class Session {
|
|
356
|
+
__destroy_into_raw() {
|
|
357
|
+
const ptr = this.__wbg_ptr;
|
|
358
|
+
this.__wbg_ptr = 0;
|
|
359
|
+
SessionFinalization.unregister(this);
|
|
360
|
+
return ptr;
|
|
361
|
+
}
|
|
362
|
+
free() {
|
|
363
|
+
const ptr = this.__destroy_into_raw();
|
|
364
|
+
wasm.__wbg_session_free(ptr, 0);
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* @param {number} nowS
|
|
368
|
+
* @returns {bigint | undefined}
|
|
369
|
+
*/
|
|
370
|
+
beginAttempt(nowS) {
|
|
371
|
+
const ret = wasm.session_beginAttempt(this.__wbg_ptr, nowS);
|
|
372
|
+
if (ret[3]) {
|
|
373
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
374
|
+
}
|
|
375
|
+
return ret[0] === 0 ? undefined : BigInt.asUintN(64, ret[1]);
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* @returns {string}
|
|
379
|
+
*/
|
|
380
|
+
end() {
|
|
381
|
+
let deferred1_0;
|
|
382
|
+
let deferred1_1;
|
|
383
|
+
try {
|
|
384
|
+
const ret = wasm.session_end(this.__wbg_ptr);
|
|
385
|
+
deferred1_0 = ret[0];
|
|
386
|
+
deferred1_1 = ret[1];
|
|
387
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
388
|
+
} finally {
|
|
389
|
+
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* @param {SessionPolicy} policy
|
|
394
|
+
*/
|
|
395
|
+
constructor(policy) {
|
|
396
|
+
_assertClass(policy, SessionPolicy);
|
|
397
|
+
const ret = wasm.session_new(policy.__wbg_ptr);
|
|
398
|
+
this.__wbg_ptr = ret;
|
|
399
|
+
SessionFinalization.register(this, this.__wbg_ptr, this);
|
|
400
|
+
return this;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* @param {bigint} epoch
|
|
404
|
+
* @param {number} nowS
|
|
405
|
+
* @returns {SessionOutcome}
|
|
406
|
+
*/
|
|
407
|
+
onConnected(epoch, nowS) {
|
|
408
|
+
const ret = wasm.session_onConnected(this.__wbg_ptr, epoch, nowS);
|
|
409
|
+
if (ret[2]) {
|
|
410
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
411
|
+
}
|
|
412
|
+
return SessionOutcome.__wrap(ret[0]);
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* @param {bigint} epoch
|
|
416
|
+
* @param {number} nowS
|
|
417
|
+
* @param {number | null | undefined} closeCode
|
|
418
|
+
* @param {number} jitterSample
|
|
419
|
+
* @returns {SessionOutcome}
|
|
420
|
+
*/
|
|
421
|
+
onSocketClose(epoch, nowS, closeCode, jitterSample) {
|
|
422
|
+
const ret = wasm.session_onSocketClose(this.__wbg_ptr, epoch, nowS, !isLikeNone(closeCode), isLikeNone(closeCode) ? 0 : closeCode, jitterSample);
|
|
423
|
+
if (ret[2]) {
|
|
424
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
425
|
+
}
|
|
426
|
+
return SessionOutcome.__wrap(ret[0]);
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* @param {number} nowS
|
|
430
|
+
* @param {boolean} retryable
|
|
431
|
+
* @param {number | null | undefined} retryAfterS
|
|
432
|
+
* @param {number} jitterSample
|
|
433
|
+
* @returns {SessionOutcome}
|
|
434
|
+
*/
|
|
435
|
+
onSupersede(nowS, retryable, retryAfterS, jitterSample) {
|
|
436
|
+
const ret = wasm.session_onSupersede(this.__wbg_ptr, nowS, retryable, !isLikeNone(retryAfterS), isLikeNone(retryAfterS) ? 0 : retryAfterS, jitterSample);
|
|
437
|
+
if (ret[2]) {
|
|
438
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
439
|
+
}
|
|
440
|
+
return SessionOutcome.__wrap(ret[0]);
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* @param {bigint} epoch
|
|
444
|
+
* @param {number} nowS
|
|
445
|
+
* @param {number} status
|
|
446
|
+
* @param {number | null | undefined} retryAfterS
|
|
447
|
+
* @param {number} jitterSample
|
|
448
|
+
* @returns {SessionOutcome}
|
|
449
|
+
*/
|
|
450
|
+
onUpgradeRejected(epoch, nowS, status, retryAfterS, jitterSample) {
|
|
451
|
+
const ret = wasm.session_onUpgradeRejected(this.__wbg_ptr, epoch, nowS, status, !isLikeNone(retryAfterS), isLikeNone(retryAfterS) ? 0 : retryAfterS, jitterSample);
|
|
452
|
+
if (ret[2]) {
|
|
453
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
454
|
+
}
|
|
455
|
+
return SessionOutcome.__wrap(ret[0]);
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* @returns {string}
|
|
459
|
+
*/
|
|
460
|
+
get state() {
|
|
461
|
+
let deferred1_0;
|
|
462
|
+
let deferred1_1;
|
|
463
|
+
try {
|
|
464
|
+
const ret = wasm.session_state(this.__wbg_ptr);
|
|
465
|
+
deferred1_0 = ret[0];
|
|
466
|
+
deferred1_1 = ret[1];
|
|
467
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
468
|
+
} finally {
|
|
469
|
+
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
if (Symbol.dispose) Session.prototype[Symbol.dispose] = Session.prototype.free;
|
|
474
|
+
exports.Session = Session;
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* The settled outcome of one `Session` call.
|
|
478
|
+
*/
|
|
479
|
+
class SessionOutcome {
|
|
480
|
+
static __wrap(ptr) {
|
|
481
|
+
const obj = Object.create(SessionOutcome.prototype);
|
|
482
|
+
obj.__wbg_ptr = ptr;
|
|
483
|
+
SessionOutcomeFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
484
|
+
return obj;
|
|
485
|
+
}
|
|
486
|
+
__destroy_into_raw() {
|
|
487
|
+
const ptr = this.__wbg_ptr;
|
|
488
|
+
this.__wbg_ptr = 0;
|
|
489
|
+
SessionOutcomeFinalization.unregister(this);
|
|
490
|
+
return ptr;
|
|
491
|
+
}
|
|
492
|
+
free() {
|
|
493
|
+
const ptr = this.__destroy_into_raw();
|
|
494
|
+
wasm.__wbg_sessionoutcome_free(ptr, 0);
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* @returns {string | undefined}
|
|
498
|
+
*/
|
|
499
|
+
get deadReason() {
|
|
500
|
+
const ret = wasm.sessionoutcome_deadReason(this.__wbg_ptr);
|
|
501
|
+
let v1;
|
|
502
|
+
if (ret[0] !== 0) {
|
|
503
|
+
v1 = getStringFromWasm0(ret[0], ret[1]);
|
|
504
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
505
|
+
}
|
|
506
|
+
return v1;
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* @returns {number | undefined}
|
|
510
|
+
*/
|
|
511
|
+
get retryAfterS() {
|
|
512
|
+
const ret = wasm.sessionoutcome_retryAfterS(this.__wbg_ptr);
|
|
513
|
+
return ret[0] === 0 ? undefined : ret[1];
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* @returns {boolean}
|
|
517
|
+
*/
|
|
518
|
+
get stale() {
|
|
519
|
+
const ret = wasm.sessionoutcome_stale(this.__wbg_ptr);
|
|
520
|
+
return ret !== 0;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* @returns {string}
|
|
524
|
+
*/
|
|
525
|
+
get state() {
|
|
526
|
+
let deferred1_0;
|
|
527
|
+
let deferred1_1;
|
|
528
|
+
try {
|
|
529
|
+
const ret = wasm.sessionoutcome_state(this.__wbg_ptr);
|
|
530
|
+
deferred1_0 = ret[0];
|
|
531
|
+
deferred1_1 = ret[1];
|
|
532
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
533
|
+
} finally {
|
|
534
|
+
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
if (Symbol.dispose) SessionOutcome.prototype[Symbol.dispose] = SessionOutcome.prototype.free;
|
|
539
|
+
exports.SessionOutcome = SessionOutcome;
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Reconnect backoff/jitter policy, plus the graduated rapid-disconnect
|
|
543
|
+
* cooldown ladder. Behavior contract: `docs/runtime-state-policy.md`'s
|
|
544
|
+
* `## Session` section.
|
|
545
|
+
*/
|
|
546
|
+
class SessionPolicy {
|
|
547
|
+
static __wrap(ptr) {
|
|
548
|
+
const obj = Object.create(SessionPolicy.prototype);
|
|
549
|
+
obj.__wbg_ptr = ptr;
|
|
550
|
+
SessionPolicyFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
551
|
+
return obj;
|
|
552
|
+
}
|
|
553
|
+
__destroy_into_raw() {
|
|
554
|
+
const ptr = this.__wbg_ptr;
|
|
555
|
+
this.__wbg_ptr = 0;
|
|
556
|
+
SessionPolicyFinalization.unregister(this);
|
|
557
|
+
return ptr;
|
|
558
|
+
}
|
|
559
|
+
free() {
|
|
560
|
+
const ptr = this.__destroy_into_raw();
|
|
561
|
+
wasm.__wbg_sessionpolicy_free(ptr, 0);
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* A recommended, not final, default.
|
|
565
|
+
* @returns {SessionPolicy}
|
|
566
|
+
*/
|
|
567
|
+
static default() {
|
|
568
|
+
const ret = wasm.sessionpolicy_default();
|
|
569
|
+
return SessionPolicy.__wrap(ret);
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* `config` is any plain object with the fields declared in
|
|
573
|
+
* `index.d.ts`'s `SessionPolicyConfig`; grouped into one value rather
|
|
574
|
+
* than a flat, many-argument constructor.
|
|
575
|
+
* @param {any} config
|
|
576
|
+
* @param {any} traceContext
|
|
577
|
+
*/
|
|
578
|
+
constructor(config, traceContext) {
|
|
579
|
+
const ret = wasm.sessionpolicy_new(config, traceContext);
|
|
580
|
+
if (ret[2]) {
|
|
581
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
582
|
+
}
|
|
583
|
+
this.__wbg_ptr = ret[0];
|
|
584
|
+
SessionPolicyFinalization.register(this, this.__wbg_ptr, this);
|
|
585
|
+
return this;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
if (Symbol.dispose) SessionPolicy.prototype[Symbol.dispose] = SessionPolicy.prototype.free;
|
|
589
|
+
exports.SessionPolicy = SessionPolicy;
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Transport-independent subscription decisions for one agent session.
|
|
593
|
+
*/
|
|
594
|
+
class SubscriptionTracker {
|
|
595
|
+
__destroy_into_raw() {
|
|
596
|
+
const ptr = this.__wbg_ptr;
|
|
597
|
+
this.__wbg_ptr = 0;
|
|
598
|
+
SubscriptionTrackerFinalization.unregister(this);
|
|
599
|
+
return ptr;
|
|
600
|
+
}
|
|
601
|
+
free() {
|
|
602
|
+
const ptr = this.__destroy_into_raw();
|
|
603
|
+
wasm.__wbg_subscriptiontracker_free(ptr, 0);
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* @param {any} topic
|
|
607
|
+
* @returns {boolean}
|
|
608
|
+
*/
|
|
609
|
+
acknowledgeAgentTopicReconciled(topic) {
|
|
610
|
+
const ret = wasm.subscriptiontracker_acknowledgeAgentTopicReconciled(this.__wbg_ptr, topic);
|
|
611
|
+
if (ret[2]) {
|
|
612
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
613
|
+
}
|
|
614
|
+
return ret[0] !== 0;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* @param {any} room_id
|
|
618
|
+
* @returns {boolean}
|
|
619
|
+
*/
|
|
620
|
+
acknowledgeRoomReconciled(room_id) {
|
|
621
|
+
const ret = wasm.subscriptiontracker_acknowledgeRoomReconciled(this.__wbg_ptr, room_id);
|
|
622
|
+
if (ret[2]) {
|
|
623
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
624
|
+
}
|
|
625
|
+
return ret[0] !== 0;
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* @param {any} topic
|
|
629
|
+
* @returns {string}
|
|
630
|
+
*/
|
|
631
|
+
agentTopicStatus(topic) {
|
|
632
|
+
const ret = wasm.subscriptiontracker_agentTopicStatus(this.__wbg_ptr, topic);
|
|
633
|
+
if (ret[3]) {
|
|
634
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
635
|
+
}
|
|
636
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* @param {any} topic
|
|
640
|
+
* @returns {bigint | undefined}
|
|
641
|
+
*/
|
|
642
|
+
beginAgentTopicJoin(topic) {
|
|
643
|
+
const ret = wasm.subscriptiontracker_beginAgentTopicJoin(this.__wbg_ptr, topic);
|
|
644
|
+
if (ret[3]) {
|
|
645
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
646
|
+
}
|
|
647
|
+
return ret[0] === 0 ? undefined : BigInt.asUintN(64, ret[1]);
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* @param {any} room_id
|
|
651
|
+
* @returns {bigint | undefined}
|
|
652
|
+
*/
|
|
653
|
+
beginRoomSubscribe(room_id) {
|
|
654
|
+
const ret = wasm.subscriptiontracker_beginRoomSubscribe(this.__wbg_ptr, room_id);
|
|
655
|
+
if (ret[3]) {
|
|
656
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
657
|
+
}
|
|
658
|
+
return ret[0] === 0 ? undefined : BigInt.asUintN(64, ret[1]);
|
|
659
|
+
}
|
|
660
|
+
endSession() {
|
|
661
|
+
wasm.subscriptiontracker_endSession(this.__wbg_ptr);
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* @param {any} topic
|
|
665
|
+
* @param {bigint} ticket
|
|
666
|
+
* @returns {boolean}
|
|
667
|
+
*/
|
|
668
|
+
isAgentTopicClaimCurrent(topic, ticket) {
|
|
669
|
+
const ret = wasm.subscriptiontracker_isAgentTopicClaimCurrent(this.__wbg_ptr, topic, ticket);
|
|
670
|
+
if (ret[2]) {
|
|
671
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
672
|
+
}
|
|
673
|
+
return ret[0] !== 0;
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* @param {any} topic
|
|
677
|
+
* @returns {boolean}
|
|
678
|
+
*/
|
|
679
|
+
isAgentTopicJoined(topic) {
|
|
680
|
+
const ret = wasm.subscriptiontracker_isAgentTopicJoined(this.__wbg_ptr, topic);
|
|
681
|
+
if (ret[2]) {
|
|
682
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
683
|
+
}
|
|
684
|
+
return ret[0] !== 0;
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* @param {any} room_id
|
|
688
|
+
* @param {bigint} ticket
|
|
689
|
+
* @returns {boolean}
|
|
690
|
+
*/
|
|
691
|
+
isRoomClaimCurrent(room_id, ticket) {
|
|
692
|
+
const ret = wasm.subscriptiontracker_isRoomClaimCurrent(this.__wbg_ptr, room_id, ticket);
|
|
693
|
+
if (ret[2]) {
|
|
694
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
695
|
+
}
|
|
696
|
+
return ret[0] !== 0;
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* @param {any} room_id
|
|
700
|
+
* @returns {boolean}
|
|
701
|
+
*/
|
|
702
|
+
isRoomSubscribed(room_id) {
|
|
703
|
+
const ret = wasm.subscriptiontracker_isRoomSubscribed(this.__wbg_ptr, room_id);
|
|
704
|
+
if (ret[2]) {
|
|
705
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
706
|
+
}
|
|
707
|
+
return ret[0] !== 0;
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* @returns {string[]}
|
|
711
|
+
*/
|
|
712
|
+
joinedAgentTopics() {
|
|
713
|
+
const ret = wasm.subscriptiontracker_joinedAgentTopics(this.__wbg_ptr);
|
|
714
|
+
var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]);
|
|
715
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
716
|
+
return v1;
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* @param {any} topic
|
|
720
|
+
* @returns {bigint | undefined}
|
|
721
|
+
*/
|
|
722
|
+
leaveAgentTopic(topic) {
|
|
723
|
+
const ret = wasm.subscriptiontracker_leaveAgentTopic(this.__wbg_ptr, topic);
|
|
724
|
+
if (ret[3]) {
|
|
725
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
726
|
+
}
|
|
727
|
+
return ret[0] === 0 ? undefined : BigInt.asUintN(64, ret[1]);
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* @param {any} topic
|
|
731
|
+
* @param {bigint} ticket
|
|
732
|
+
* @param {any} outcome
|
|
733
|
+
* @returns {boolean}
|
|
734
|
+
*/
|
|
735
|
+
markAgentTopicLeaveComplete(topic, ticket, outcome) {
|
|
736
|
+
const ret = wasm.subscriptiontracker_markAgentTopicLeaveComplete(this.__wbg_ptr, topic, ticket, outcome);
|
|
737
|
+
if (ret[2]) {
|
|
738
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
739
|
+
}
|
|
740
|
+
return ret[0] !== 0;
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* @param {any} room_id
|
|
744
|
+
* @param {bigint} ticket
|
|
745
|
+
* @param {any} outcome
|
|
746
|
+
* @returns {boolean}
|
|
747
|
+
*/
|
|
748
|
+
markRoomLeaveComplete(room_id, ticket, outcome) {
|
|
749
|
+
const ret = wasm.subscriptiontracker_markRoomLeaveComplete(this.__wbg_ptr, room_id, ticket, outcome);
|
|
750
|
+
if (ret[2]) {
|
|
751
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
752
|
+
}
|
|
753
|
+
return ret[0] !== 0;
|
|
754
|
+
}
|
|
755
|
+
constructor() {
|
|
756
|
+
const ret = wasm.subscriptiontracker_new();
|
|
757
|
+
this.__wbg_ptr = ret;
|
|
758
|
+
SubscriptionTrackerFinalization.register(this, this.__wbg_ptr, this);
|
|
759
|
+
return this;
|
|
760
|
+
}
|
|
761
|
+
onReconnected() {
|
|
762
|
+
wasm.subscriptiontracker_onReconnected(this.__wbg_ptr);
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* @param {any} topic
|
|
766
|
+
* @param {bigint} ticket
|
|
767
|
+
* @param {boolean} joined
|
|
768
|
+
* @returns {boolean}
|
|
769
|
+
*/
|
|
770
|
+
recordAgentTopicJoin(topic, ticket, joined) {
|
|
771
|
+
const ret = wasm.subscriptiontracker_recordAgentTopicJoin(this.__wbg_ptr, topic, ticket, joined);
|
|
772
|
+
if (ret[2]) {
|
|
773
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
774
|
+
}
|
|
775
|
+
return ret[0] !== 0;
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* @param {any} room_id
|
|
779
|
+
* @param {bigint} ticket
|
|
780
|
+
* @returns {string}
|
|
781
|
+
*/
|
|
782
|
+
recordBothRoomTopicsJoined(room_id, ticket) {
|
|
783
|
+
const ret = wasm.subscriptiontracker_recordBothRoomTopicsJoined(this.__wbg_ptr, room_id, ticket);
|
|
784
|
+
if (ret[3]) {
|
|
785
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
786
|
+
}
|
|
787
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* @param {any} room_id
|
|
791
|
+
* @param {bigint} ticket
|
|
792
|
+
* @returns {string}
|
|
793
|
+
*/
|
|
794
|
+
recordChatRoomJoinFailed(room_id, ticket) {
|
|
795
|
+
const ret = wasm.subscriptiontracker_recordChatRoomJoinFailed(this.__wbg_ptr, room_id, ticket);
|
|
796
|
+
if (ret[3]) {
|
|
797
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
798
|
+
}
|
|
799
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* @param {any} room_id
|
|
803
|
+
* @param {bigint} ticket
|
|
804
|
+
* @param {boolean} chatRoomLeft
|
|
805
|
+
* @returns {string}
|
|
806
|
+
*/
|
|
807
|
+
recordRoomParticipantsJoinFailed(room_id, ticket, chatRoomLeft) {
|
|
808
|
+
const ret = wasm.subscriptiontracker_recordRoomParticipantsJoinFailed(this.__wbg_ptr, room_id, ticket, chatRoomLeft);
|
|
809
|
+
if (ret[3]) {
|
|
810
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
811
|
+
}
|
|
812
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* @param {any} room_id
|
|
816
|
+
* @returns {string}
|
|
817
|
+
*/
|
|
818
|
+
roomStatus(room_id) {
|
|
819
|
+
const ret = wasm.subscriptiontracker_roomStatus(this.__wbg_ptr, room_id);
|
|
820
|
+
if (ret[3]) {
|
|
821
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
822
|
+
}
|
|
823
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* @returns {string[]}
|
|
827
|
+
*/
|
|
828
|
+
subscribedRoomIds() {
|
|
829
|
+
const ret = wasm.subscriptiontracker_subscribedRoomIds(this.__wbg_ptr);
|
|
830
|
+
var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]);
|
|
831
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
832
|
+
return v1;
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* @param {any} room_id
|
|
836
|
+
* @returns {bigint | undefined}
|
|
837
|
+
*/
|
|
838
|
+
unsubscribeRoom(room_id) {
|
|
839
|
+
const ret = wasm.subscriptiontracker_unsubscribeRoom(this.__wbg_ptr, room_id);
|
|
840
|
+
if (ret[3]) {
|
|
841
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
842
|
+
}
|
|
843
|
+
return ret[0] === 0 ? undefined : BigInt.asUintN(64, ret[1]);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
if (Symbol.dispose) SubscriptionTracker.prototype[Symbol.dispose] = SubscriptionTracker.prototype.free;
|
|
847
|
+
exports.SubscriptionTracker = SubscriptionTracker;
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* Classify a WebSocket close code. Returns `[terminal, delayRange]`.
|
|
851
|
+
* @param {number | null} [closeCode]
|
|
852
|
+
* @returns {Array<any>}
|
|
853
|
+
*/
|
|
854
|
+
function classifyClose(closeCode) {
|
|
855
|
+
const ret = wasm.classifyClose(!isLikeNone(closeCode), isLikeNone(closeCode) ? 0 : closeCode);
|
|
856
|
+
if (ret[2]) {
|
|
857
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
858
|
+
}
|
|
859
|
+
return takeFromExternrefTable0(ret[0]);
|
|
860
|
+
}
|
|
861
|
+
exports.classifyClose = classifyClose;
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Classify an HTTP upgrade-rejection status code. Returns
|
|
865
|
+
* `[terminal, delayRange]`.
|
|
866
|
+
* @param {number} status
|
|
867
|
+
* @returns {Array<any>}
|
|
868
|
+
*/
|
|
869
|
+
function classifyUpgrade(status) {
|
|
870
|
+
const ret = wasm.classifyUpgrade(status);
|
|
871
|
+
if (ret[2]) {
|
|
872
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
873
|
+
}
|
|
874
|
+
return takeFromExternrefTable0(ret[0]);
|
|
875
|
+
}
|
|
876
|
+
exports.classifyUpgrade = classifyUpgrade;
|
|
877
|
+
|
|
351
878
|
/**
|
|
352
879
|
* Validate and normalize an inbound platform event payload.
|
|
353
880
|
*
|
|
@@ -486,6 +1013,10 @@ function __wbg_get_imports() {
|
|
|
486
1013
|
const ret = Object.entries(arg0);
|
|
487
1014
|
return ret;
|
|
488
1015
|
},
|
|
1016
|
+
__wbg_get_971a0c45d172643f: function() { return handleError(function (arg0, arg1) {
|
|
1017
|
+
const ret = Reflect.get(arg0, arg1);
|
|
1018
|
+
return ret;
|
|
1019
|
+
}, arguments); },
|
|
489
1020
|
__wbg_get_c0c8f8d7da0c03dd: function(arg0, arg1) {
|
|
490
1021
|
const ret = arg0[arg1 >>> 0];
|
|
491
1022
|
return ret;
|
|
@@ -650,6 +1181,18 @@ const ParticipantRosterFinalization = (typeof FinalizationRegistry === 'undefine
|
|
|
650
1181
|
const RetryTrackerFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
651
1182
|
? { register: () => {}, unregister: () => {} }
|
|
652
1183
|
: new FinalizationRegistry(ptr => wasm.__wbg_retrytracker_free(ptr, 1));
|
|
1184
|
+
const SessionFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
1185
|
+
? { register: () => {}, unregister: () => {} }
|
|
1186
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_session_free(ptr, 1));
|
|
1187
|
+
const SessionOutcomeFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
1188
|
+
? { register: () => {}, unregister: () => {} }
|
|
1189
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_sessionoutcome_free(ptr, 1));
|
|
1190
|
+
const SessionPolicyFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
1191
|
+
? { register: () => {}, unregister: () => {} }
|
|
1192
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_sessionpolicy_free(ptr, 1));
|
|
1193
|
+
const SubscriptionTrackerFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
1194
|
+
? { register: () => {}, unregister: () => {} }
|
|
1195
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_subscriptiontracker_free(ptr, 1));
|
|
653
1196
|
|
|
654
1197
|
function addToExternrefTable0(obj) {
|
|
655
1198
|
const idx = wasm.__externref_table_alloc();
|
|
@@ -657,6 +1200,12 @@ function addToExternrefTable0(obj) {
|
|
|
657
1200
|
return idx;
|
|
658
1201
|
}
|
|
659
1202
|
|
|
1203
|
+
function _assertClass(instance, klass) {
|
|
1204
|
+
if (!(instance instanceof klass)) {
|
|
1205
|
+
throw new Error(`expected instance of ${klass.name}`);
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
|
|
660
1209
|
function debugString(val) {
|
|
661
1210
|
// primitive types
|
|
662
1211
|
const type = typeof val;
|
package/band_sdk_core_bg.wasm
CHANGED
|
Binary file
|
package/index.d.ts
CHANGED
|
@@ -145,3 +145,155 @@ export class ParticipantRoster {
|
|
|
145
145
|
changed(): boolean;
|
|
146
146
|
markSent(): void;
|
|
147
147
|
}
|
|
148
|
+
|
|
149
|
+
export type RoomSubscribeResult =
|
|
150
|
+
| "subscribed"
|
|
151
|
+
| "join_failed"
|
|
152
|
+
| "rolled_back"
|
|
153
|
+
| "rollback_failed"
|
|
154
|
+
| "stale";
|
|
155
|
+
|
|
156
|
+
export type RoomStatus =
|
|
157
|
+
| "absent"
|
|
158
|
+
| "pending"
|
|
159
|
+
| "subscribed"
|
|
160
|
+
| "leaving"
|
|
161
|
+
| "needs_reconciliation";
|
|
162
|
+
|
|
163
|
+
export type AgentTopicStatus =
|
|
164
|
+
| "absent"
|
|
165
|
+
| "pending"
|
|
166
|
+
| "joined"
|
|
167
|
+
| "leaving"
|
|
168
|
+
| "needs_reconciliation";
|
|
169
|
+
|
|
170
|
+
export type LeaveOutcome = "left" | "failed" | "unknown";
|
|
171
|
+
|
|
172
|
+
export type SessionState = "connecting" | "up" | "reconnecting" | "dead";
|
|
173
|
+
|
|
174
|
+
export type DeadReason = "classified" | "rapid_disconnect";
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Classify a WebSocket close code. Returns `[terminal, delayRange]`.
|
|
178
|
+
* Throws a plain `Error` if `closeCode` is not an integer in `0..=65535`
|
|
179
|
+
* (or `undefined`).
|
|
180
|
+
*/
|
|
181
|
+
export function classifyClose(
|
|
182
|
+
closeCode: number | undefined,
|
|
183
|
+
): [boolean, [number, number] | undefined];
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Classify an HTTP upgrade-rejection status code. Returns
|
|
187
|
+
* `[terminal, delayRange]`. Throws a plain `Error` if `status` is not an
|
|
188
|
+
* integer in `0..=65535`.
|
|
189
|
+
*/
|
|
190
|
+
export function classifyUpgrade(
|
|
191
|
+
status: number,
|
|
192
|
+
): [boolean, [number, number] | undefined];
|
|
193
|
+
|
|
194
|
+
/** The settled outcome of one {@link Session} call. */
|
|
195
|
+
export class SessionOutcome {
|
|
196
|
+
private constructor();
|
|
197
|
+
readonly state: SessionState;
|
|
198
|
+
readonly retryAfterS: number | undefined;
|
|
199
|
+
readonly deadReason: DeadReason | undefined;
|
|
200
|
+
readonly stale: boolean;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** {@link SessionPolicy}'s constructor fields. */
|
|
204
|
+
export interface SessionPolicyConfig {
|
|
205
|
+
baseDelayS: number;
|
|
206
|
+
factor: number;
|
|
207
|
+
maxDelayS: number;
|
|
208
|
+
stableResetS: number;
|
|
209
|
+
rapidDisconnectUptimeS: number;
|
|
210
|
+
rapidWindowS: number;
|
|
211
|
+
rapidFirstMinDelayS: number;
|
|
212
|
+
rapidSecondMinDelayS: number;
|
|
213
|
+
rapidCooldownBaseS: number;
|
|
214
|
+
rapidCooldownStepS: number;
|
|
215
|
+
rapidCooldownMaxS: number;
|
|
216
|
+
rapidThreshold: number;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Reconnect backoff/jitter policy, plus the graduated rapid-disconnect
|
|
221
|
+
* cooldown ladder. A recommended, not final, starting design -- see
|
|
222
|
+
* `docs/runtime-state-policy.md`'s `## Session` section.
|
|
223
|
+
*
|
|
224
|
+
* Throws a native `Error` with `.issues`/`.traceContext` if `factor < 1.0`
|
|
225
|
+
* or `baseDelayS > maxDelayS`. Throws a plain `Error` if `config` is
|
|
226
|
+
* missing a field or a field is not a finite, non-negative number
|
|
227
|
+
* (`rapidThreshold` must also be an integer).
|
|
228
|
+
*/
|
|
229
|
+
export class SessionPolicy {
|
|
230
|
+
constructor(config: SessionPolicyConfig, traceContext?: string | null);
|
|
231
|
+
/** A recommended, not final, default. */
|
|
232
|
+
static default(): SessionPolicy;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* One WebSocket session's state machine: which epoch (connection attempt)
|
|
237
|
+
* is live, the current lifecycle state, and the reconnect/rapid-disconnect
|
|
238
|
+
* bookkeeping. Single-writer -- exactly one owner drives a given `Session`
|
|
239
|
+
* at a time.
|
|
240
|
+
*
|
|
241
|
+
* `nowS`/`retryAfterS` each throw a plain `Error` if not a finite,
|
|
242
|
+
* non-negative number; `jitterSample` throws unless it's a finite number
|
|
243
|
+
* in `[0.0, 1.0]` (a fraction, not an open-ended time value);
|
|
244
|
+
* `closeCode`/`status` throw if not an integer in `0..=65535` (or
|
|
245
|
+
* `undefined` for `closeCode`).
|
|
246
|
+
*/
|
|
247
|
+
export class Session {
|
|
248
|
+
constructor(policy: SessionPolicy);
|
|
249
|
+
readonly state: SessionState;
|
|
250
|
+
beginAttempt(nowS: number): bigint | undefined;
|
|
251
|
+
onConnected(epoch: bigint, nowS: number): SessionOutcome;
|
|
252
|
+
onSocketClose(
|
|
253
|
+
epoch: bigint,
|
|
254
|
+
nowS: number,
|
|
255
|
+
closeCode: number | undefined,
|
|
256
|
+
jitterSample: number,
|
|
257
|
+
): SessionOutcome;
|
|
258
|
+
onUpgradeRejected(
|
|
259
|
+
epoch: bigint,
|
|
260
|
+
nowS: number,
|
|
261
|
+
status: number,
|
|
262
|
+
retryAfterS: number | undefined,
|
|
263
|
+
jitterSample: number,
|
|
264
|
+
): SessionOutcome;
|
|
265
|
+
onSupersede(
|
|
266
|
+
nowS: number,
|
|
267
|
+
retryable: boolean,
|
|
268
|
+
retryAfterS: number | undefined,
|
|
269
|
+
jitterSample: number,
|
|
270
|
+
): SessionOutcome;
|
|
271
|
+
end(): SessionState;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** Transport-independent subscription decisions for one agent session. */
|
|
275
|
+
export class SubscriptionTracker {
|
|
276
|
+
constructor();
|
|
277
|
+
beginRoomSubscribe(roomId: string): bigint | undefined;
|
|
278
|
+
recordChatRoomJoinFailed(roomId: string, ticket: bigint): RoomSubscribeResult;
|
|
279
|
+
recordBothRoomTopicsJoined(roomId: string, ticket: bigint): RoomSubscribeResult;
|
|
280
|
+
recordRoomParticipantsJoinFailed(roomId: string, ticket: bigint, chatRoomLeft: boolean): RoomSubscribeResult;
|
|
281
|
+
isRoomSubscribed(roomId: string): boolean;
|
|
282
|
+
isRoomClaimCurrent(roomId: string, ticket: bigint): boolean;
|
|
283
|
+
roomStatus(roomId: string): RoomStatus;
|
|
284
|
+
unsubscribeRoom(roomId: string): bigint | undefined;
|
|
285
|
+
markRoomLeaveComplete(roomId: string, ticket: bigint, outcome: LeaveOutcome): boolean;
|
|
286
|
+
acknowledgeRoomReconciled(roomId: string): boolean;
|
|
287
|
+
subscribedRoomIds(): string[];
|
|
288
|
+
onReconnected(): void;
|
|
289
|
+
endSession(): void;
|
|
290
|
+
beginAgentTopicJoin(topic: string): bigint | undefined;
|
|
291
|
+
recordAgentTopicJoin(topic: string, ticket: bigint, joined: boolean): boolean;
|
|
292
|
+
isAgentTopicJoined(topic: string): boolean;
|
|
293
|
+
isAgentTopicClaimCurrent(topic: string, ticket: bigint): boolean;
|
|
294
|
+
agentTopicStatus(topic: string): AgentTopicStatus;
|
|
295
|
+
leaveAgentTopic(topic: string): bigint | undefined;
|
|
296
|
+
markAgentTopicLeaveComplete(topic: string, ticket: bigint, outcome: LeaveOutcome): boolean;
|
|
297
|
+
acknowledgeAgentTopicReconciled(topic: string): boolean;
|
|
298
|
+
joinedAgentTopics(): string[];
|
|
299
|
+
}
|