@band-ai/band-sdk-core 2.9.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,54 @@
1
+ Band SDK License Agreement
2
+
3
+ Copyright (c) 2025-2026 THENVOI AI LTD. D/B/A BAND. All rights reserved.
4
+
5
+ By using or redistributing the SDK, you agree to this agreement. If you
6
+ do not agree, do not use or redistribute it.
7
+
8
+ 1. License grant
9
+ Band grants you a non-exclusive, worldwide, royalty-free license to use
10
+ the SDK's compiled binaries to develop and run applications that integrate
11
+ with Band, including commercial applications. You may reproduce and
12
+ redistribute unmodified SDK binaries as dependencies of those applications,
13
+ provided you include this agreement and preserve all copyright, attribution,
14
+ and third-party notices. Recipients receive their SDK rights under this
15
+ agreement. Access to Band services remains subject to their separate terms.
16
+
17
+ 2. Binary-only distribution
18
+ The license covers compiled Python extensions and WebAssembly binaries,
19
+ and the accompanying public interface declarations, generated JavaScript
20
+ loaders, Python package loaders, and documentation supplied by Band. Those
21
+ auxiliary files may be distributed with the binaries under section 1.
22
+ No license to the SDK's Rust implementation source or private repository
23
+ is granted. Repository access does not authorize source redistribution.
24
+
25
+ 3. Restrictions
26
+ Except as expressly permitted above or required by applicable law, you may
27
+ not modify the SDK, distribute it as a standalone competing SDK, disclose
28
+ or distribute its implementation source, or reverse engineer, decompile,
29
+ or disassemble the binaries. No trademark rights are granted. Band retains
30
+ all ownership and all rights not expressly granted by this agreement.
31
+
32
+ 4. Third-party components
33
+ Third-party components remain governed by their own licenses. This
34
+ agreement does not limit rights granted by those licenses. Preserve their
35
+ required notices when redistributing the SDK.
36
+
37
+ 5. No warranty; limitation of liability
38
+ TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SDK IS PROVIDED "AS IS" WITHOUT
39
+ WARRANTIES OF ANY KIND, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR
40
+ PURPOSE, AND NON-INFRINGEMENT. BAND SHALL NOT BE LIABLE FOR INDIRECT,
41
+ INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES, OR LOSS OF DATA,
42
+ PROFITS, OR BUSINESS ARISING FROM USE OF THE SDK. NOTHING IN THIS AGREEMENT
43
+ EXCLUDES LIABILITY THAT CANNOT LAWFULLY BE EXCLUDED.
44
+
45
+ 6. Termination
46
+ Your license terminates if you breach this agreement. On termination, stop
47
+ using and distributing the SDK and delete your copies, except copies you
48
+ must retain by law. Compliant recipients of previously redistributed SDK
49
+ binaries retain their licenses. Sections 2 through 6 survive termination.
50
+
51
+ 7. Scope
52
+ This agreement applies to SDK copies supplied with it. It does not replace
53
+ licenses previously granted for earlier releases. A separately signed
54
+ agreement with Band takes precedence to the extent of a conflict.
package/README.md CHANGED
@@ -5,7 +5,7 @@ runtime state, compiled from Rust to WebAssembly for Node. Every function
5
5
  is synchronous, pure computation — no network, filesystem, or logging.
6
6
 
7
7
  ```
8
- band-sdk-core-core (Rust) --> @band-ai/band-sdk-core (this package, npm) --> band-sdk-typescript
8
+ band-sdk-core (Rust) --> @band-ai/band-sdk-core (this package, npm) --> band-sdk-typescript
9
9
  ```
10
10
 
11
11
  If you're using [`band-sdk-typescript`](https://github.com/band-ai/band-sdk-typescript),
@@ -69,7 +69,7 @@ at least `1`; `0` throws. `ClaimRegistry`'s `maxCompleted` must be at
69
69
  least `1` too — `0` also throws.
70
70
 
71
71
  `ClaimRegistry` keeps one terminal intent per message until
72
- `rememberCompleted`: `rememberAckPending` records a processed write and
72
+ `rememberCompleted` or matching `confirmSettlement`: `rememberAckPending` records a processed write and
73
73
  `rememberFailedAckPending` a failed one carrying its `error`. The first
74
74
  intent wins; a different one throws — leaving the entry unchanged, with
75
75
  `.issues` and `.traceContext` attached — and an identical repeat is a
@@ -301,4 +301,32 @@ just build-wasm # Node package output
301
301
 
302
302
  ## License
303
303
 
304
- MIT — see [LICENSE](https://github.com/band-ai/band-sdk-core/blob/main/LICENSE).
304
+ Proprietary, binary-only Band SDK License Agreement — see the bundled
305
+ [LICENSE](LICENSE). The Rust implementation source is private.
306
+
307
+ ## Fenced delivery settlement
308
+
309
+ `guardedClaim` shares eligibility across discovery paths. Its optional facts
310
+ object accepts boolean `self_echo`, `durably_processed`, `durably_failed`, and
311
+ `allow_failed_retry` fields. Only `allow_failed_retry` defaults to true. Unknown
312
+ fields and non-boolean values throw before ownership changes.
313
+
314
+ Pending originals remain excluded when parked. Record the terminal disposition
315
+ before transport and confirm only after acceptance and a current-execution check.
316
+ Retry confirmation restores charged attempts with the stricter retry ceiling;
317
+ it does not falsely complete the original. Tokens are opaque local strings.
318
+
319
+ ```ts
320
+ import { ClaimRegistry, RetryTracker } from "@band-ai/band-sdk-core";
321
+
322
+ const claims = new ClaimRegistry();
323
+ const previous = new RetryTracker(3);
324
+ if (claims.guardedClaim("room", "message", previous) !== "runnable") throw new Error("not admitted");
325
+ previous.recordAttempt("message");
326
+ const pending = claims.recordFailedSettlement("room", "message", "failure", previous, true);
327
+ claims.release("room", "message");
328
+ const current = new RetryTracker(3);
329
+ if (!claims.confirmSettlement("room", "message", pending.token, current)) throw new Error("not confirmed");
330
+ if (claims.isCompleted("room", "message")) throw new Error("retry falsely completed");
331
+ if (current.recordAttempt("message")[0] !== 2) throw new Error("charge lost");
332
+ ```
package/band_sdk_core.js CHANGED
@@ -145,6 +145,47 @@ class ClaimRegistry {
145
145
  wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
146
146
  return v1;
147
147
  }
148
+ /**
149
+ * @param {any} room_id
150
+ * @param {any} message_id
151
+ * @param {any} token
152
+ * @param {RetryTracker} retry_tracker
153
+ * @returns {boolean}
154
+ */
155
+ confirmSettlement(room_id, message_id, token, retry_tracker) {
156
+ _assertClass(retry_tracker, RetryTracker);
157
+ const ret = wasm.claimregistry_confirmSettlement(this.__wbg_ptr, room_id, message_id, token, retry_tracker.__wbg_ptr);
158
+ if (ret[2]) {
159
+ throw takeFromExternrefTable0(ret[1]);
160
+ }
161
+ return ret[0] !== 0;
162
+ }
163
+ /**
164
+ * @param {any} room_id
165
+ * @param {any} message_id
166
+ * @param {RetryTracker} retry_tracker
167
+ * @param {any} facts
168
+ * @returns {string}
169
+ */
170
+ deliveryEligibility(room_id, message_id, retry_tracker, facts) {
171
+ let deferred2_0;
172
+ let deferred2_1;
173
+ try {
174
+ _assertClass(retry_tracker, RetryTracker);
175
+ const ret = wasm.claimregistry_deliveryEligibility(this.__wbg_ptr, room_id, message_id, retry_tracker.__wbg_ptr, facts);
176
+ var ptr1 = ret[0];
177
+ var len1 = ret[1];
178
+ if (ret[3]) {
179
+ ptr1 = 0; len1 = 0;
180
+ throw takeFromExternrefTable0(ret[2]);
181
+ }
182
+ deferred2_0 = ptr1;
183
+ deferred2_1 = len1;
184
+ return getStringFromWasm0(ptr1, len1);
185
+ } finally {
186
+ wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
187
+ }
188
+ }
148
189
  /**
149
190
  * @param {any} room_id
150
191
  */
@@ -154,6 +195,43 @@ class ClaimRegistry {
154
195
  throw takeFromExternrefTable0(ret[0]);
155
196
  }
156
197
  }
198
+ /**
199
+ * @param {any} room_id
200
+ * @param {any} message_id
201
+ * @param {RetryTracker} retry_tracker
202
+ * @param {any} facts
203
+ * @returns {string}
204
+ */
205
+ guardedClaim(room_id, message_id, retry_tracker, facts) {
206
+ let deferred2_0;
207
+ let deferred2_1;
208
+ try {
209
+ _assertClass(retry_tracker, RetryTracker);
210
+ const ret = wasm.claimregistry_guardedClaim(this.__wbg_ptr, room_id, message_id, retry_tracker.__wbg_ptr, facts);
211
+ var ptr1 = ret[0];
212
+ var len1 = ret[1];
213
+ if (ret[3]) {
214
+ ptr1 = 0; len1 = 0;
215
+ throw takeFromExternrefTable0(ret[2]);
216
+ }
217
+ deferred2_0 = ptr1;
218
+ deferred2_1 = len1;
219
+ return getStringFromWasm0(ptr1, len1);
220
+ } finally {
221
+ wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
222
+ }
223
+ }
224
+ /**
225
+ * @param {any} room_id
226
+ * @returns {boolean}
227
+ */
228
+ hasRetryableSettlement(room_id) {
229
+ const ret = wasm.claimregistry_hasRetryableSettlement(this.__wbg_ptr, room_id);
230
+ if (ret[2]) {
231
+ throw takeFromExternrefTable0(ret[1]);
232
+ }
233
+ return ret[0] !== 0;
234
+ }
157
235
  /**
158
236
  * @param {any} room_id
159
237
  * @returns {string[]}
@@ -225,6 +303,20 @@ class ClaimRegistry {
225
303
  }
226
304
  return ret[0] !== 0;
227
305
  }
306
+ /**
307
+ * @param {any} room_id
308
+ * @param {any} message_id
309
+ * @param {any} token
310
+ * @param {any} reason
311
+ * @returns {boolean}
312
+ */
313
+ parkSettlement(room_id, message_id, token, reason) {
314
+ const ret = wasm.claimregistry_parkSettlement(this.__wbg_ptr, room_id, message_id, token, reason);
315
+ if (ret[2]) {
316
+ throw takeFromExternrefTable0(ret[1]);
317
+ }
318
+ return ret[0] !== 0;
319
+ }
228
320
  /**
229
321
  * @param {any} room_id
230
322
  * @returns {string[]}
@@ -252,6 +344,19 @@ class ClaimRegistry {
252
344
  }
253
345
  return takeFromExternrefTable0(ret[0]);
254
346
  }
347
+ /**
348
+ * @param {any} room_id
349
+ * @param {any} message_id
350
+ * @param {any} trace_context
351
+ * @returns {any}
352
+ */
353
+ pendingSettlement(room_id, message_id, trace_context) {
354
+ const ret = wasm.claimregistry_pendingSettlement(this.__wbg_ptr, room_id, message_id, trace_context);
355
+ if (ret[2]) {
356
+ throw takeFromExternrefTable0(ret[1]);
357
+ }
358
+ return takeFromExternrefTable0(ret[0]);
359
+ }
255
360
  /**
256
361
  * @param {any} room_id
257
362
  * @param {any} message_id
@@ -264,6 +369,36 @@ class ClaimRegistry {
264
369
  }
265
370
  return ret[0] >>> 0;
266
371
  }
372
+ /**
373
+ * @param {any} room_id
374
+ * @param {any} message_id
375
+ * @param {any} error
376
+ * @param {RetryTracker} retry_tracker
377
+ * @param {any} allow_retry
378
+ * @param {any} trace_context
379
+ * @returns {any}
380
+ */
381
+ recordFailedSettlement(room_id, message_id, error, retry_tracker, allow_retry, trace_context) {
382
+ _assertClass(retry_tracker, RetryTracker);
383
+ const ret = wasm.claimregistry_recordFailedSettlement(this.__wbg_ptr, room_id, message_id, error, retry_tracker.__wbg_ptr, allow_retry, trace_context);
384
+ if (ret[2]) {
385
+ throw takeFromExternrefTable0(ret[1]);
386
+ }
387
+ return takeFromExternrefTable0(ret[0]);
388
+ }
389
+ /**
390
+ * @param {any} room_id
391
+ * @param {any} message_id
392
+ * @param {any} trace_context
393
+ * @returns {any}
394
+ */
395
+ recordProcessedSettlement(room_id, message_id, trace_context) {
396
+ const ret = wasm.claimregistry_recordProcessedSettlement(this.__wbg_ptr, room_id, message_id, trace_context);
397
+ if (ret[2]) {
398
+ throw takeFromExternrefTable0(ret[1]);
399
+ }
400
+ return takeFromExternrefTable0(ret[0]);
401
+ }
267
402
  /**
268
403
  * @param {any} room_id
269
404
  * @param {any} message_id
@@ -1951,6 +2086,14 @@ exports.validateMemoryTypeForSystem = validateMemoryTypeForSystem;
1951
2086
  function __wbg_get_imports() {
1952
2087
  const import0 = {
1953
2088
  __proto__: null,
2089
+ __wbg_0_c2e12945caff5360: function(arg0) {
2090
+ const ret = arg0["0"];
2091
+ return ret;
2092
+ },
2093
+ __wbg_1_191c69f1437bcd10: function(arg0) {
2094
+ const ret = arg0["1"];
2095
+ return ret;
2096
+ },
1954
2097
  __wbg_Error_30c8987f7c2ed4e2: function(arg0, arg1) {
1955
2098
  const ret = Error(getStringFromWasm0(arg0, arg1));
1956
2099
  return ret;
@@ -2042,6 +2185,10 @@ function __wbg_get_imports() {
2042
2185
  const ret = arg0.done;
2043
2186
  return ret;
2044
2187
  },
2188
+ __wbg_entries_b6763c9f1557e886: function() { return handleError(function (arg0) {
2189
+ const ret = Object.entries(arg0);
2190
+ return ret;
2191
+ }, arguments); },
2045
2192
  __wbg_entries_fb6397112b1de25f: function(arg0) {
2046
2193
  const ret = Object.entries(arg0);
2047
2194
  return ret;
@@ -2114,6 +2261,10 @@ function __wbg_get_imports() {
2114
2261
  const ret = Array.isArray(arg0);
2115
2262
  return ret;
2116
2263
  },
2264
+ __wbg_isArray_fcec83e4012ff365: function() { return handleError(function (arg0) {
2265
+ const ret = Array.isArray(arg0);
2266
+ return ret;
2267
+ }, arguments); },
2117
2268
  __wbg_isSafeInteger_717808ad6a54bd9e: function(arg0) {
2118
2269
  const ret = Number.isSafeInteger(arg0);
2119
2270
  return ret;
Binary file
package/index.d.ts CHANGED
@@ -143,6 +143,24 @@ export type PendingAck =
143
143
  | { status: "processed"; parked: ParkedReason | null }
144
144
  | { status: "failed"; error: string; parked: ParkedReason | null };
145
145
 
146
+ export type DeliveryEligibility = "self" | "completed" | "pending" | "inflight" | "exhausted" | "failed" | "runnable";
147
+
148
+ export interface DeliveryFacts {
149
+ self_echo?: boolean;
150
+ durably_processed?: boolean;
151
+ durably_failed?: boolean;
152
+ allow_failed_retry?: boolean;
153
+ }
154
+
155
+ export type SettlementContinuation =
156
+ | { kind: "finished" }
157
+ | { kind: "retry"; attempts: number; max_retries: number };
158
+
159
+ export type PendingSettlement = PendingAck & {
160
+ token: string;
161
+ continuation: SettlementContinuation;
162
+ };
163
+
146
164
  /**
147
165
  * Ownership ledger for the inbound message-delivery lifecycle: in-flight,
148
166
  * ack-pending (a stored processed/failed intent, optionally parked), and
@@ -181,6 +199,14 @@ export class ClaimRegistry {
181
199
  unparkAcks(roomId: string): number;
182
200
  pendingAckIds(roomId: string): string[];
183
201
  recordAckRetry(roomId: string, messageId: string): number;
202
+ deliveryEligibility(roomId: string, messageId: string, retryTracker: RetryTracker, facts?: DeliveryFacts): DeliveryEligibility;
203
+ guardedClaim(roomId: string, messageId: string, retryTracker: RetryTracker, facts?: DeliveryFacts): DeliveryEligibility;
204
+ hasRetryableSettlement(roomId: string): boolean;
205
+ pendingSettlement(roomId: string, messageId: string, traceContext?: string | null): PendingSettlement | undefined;
206
+ recordProcessedSettlement(roomId: string, messageId: string, traceContext?: string | null): PendingSettlement;
207
+ recordFailedSettlement(roomId: string, messageId: string, error: string, retryTracker: RetryTracker, allowRetry: boolean, traceContext?: string | null): PendingSettlement;
208
+ confirmSettlement(roomId: string, messageId: string, token: string, retryTracker: RetryTracker): boolean;
209
+ parkSettlement(roomId: string, messageId: string, token: string, reason: ParkedReason): boolean;
184
210
  }
185
211
 
186
212
  /**
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@band-ai/band-sdk-core",
3
- "version": "2.9.0",
3
+ "version": "3.0.0",
4
4
  "description": "Shared Band event-payload validation",
5
- "license": "MIT",
5
+ "license": "SEE LICENSE IN LICENSE",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "https://github.com/band-ai/band-sdk-core"
@@ -11,7 +11,8 @@
11
11
  "band_sdk_core.js",
12
12
  "band_sdk_core_bg.wasm",
13
13
  "index.d.ts",
14
- "README.md"
14
+ "README.md",
15
+ "LICENSE"
15
16
  ],
16
17
  "main": "./band_sdk_core.js",
17
18
  "types": "./index.d.ts",