@band-ai/band-sdk-core 2.7.0 → 2.9.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 CHANGED
@@ -68,6 +68,15 @@ 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
+ `ClaimRegistry` keeps one terminal intent per message until
72
+ `rememberCompleted`: `rememberAckPending` records a processed write and
73
+ `rememberFailedAckPending` a failed one carrying its `error`. The first
74
+ intent wins; a different one throws — leaving the entry unchanged, with
75
+ `.issues` and `.traceContext` attached — and an identical repeat is a
76
+ no-op. `pendingAck` returns `{status, error?, parked}` or `undefined`.
77
+ `parkAck` takes a `ParkedReason` wire name, `parkedReasons()` lists them,
78
+ and any other value throws a plain `Error`.
79
+
71
80
  `SubscriptionTracker` provides synchronous, transport-independent decisions for
72
81
  agent-topic joins and the two-topic room subscription transaction. Its opaque
73
82
  tickets are JavaScript `bigint` values and must be supplied when recording a
@@ -244,6 +253,39 @@ outcome to `"processed"` or `"failed"`.
244
253
  exposed for a host's own call sites that classify a sender without going
245
254
  through either function.
246
255
 
256
+ ### Turn outcome
257
+
258
+ `TurnLedger` judges one agent turn — design decisions live as rustdoc in
259
+ `crates/core/src/turn.rs`. Create one per turn, `record` the `TurnEffect` of
260
+ each successful tool call (a failed call records nothing), and ask for the
261
+ `verdict()` when the model stops: `"complete"` once the turn replied,
262
+ declined, or did real work, else `"missing_reply"` (fail the turn with
263
+ `missingReplyMessage()`). `settle()` marks a turn the SDK answered itself and
264
+ `noteReported()` one whose failure was already reported; both complete it.
265
+ `replySettled()` is `true` once a recorded call posted to the room or
266
+ declined to, so no fallback text is due. `record` throws a plain `Error` for
267
+ anything but a `TurnEffect` wire name.
268
+
269
+ `bandToolEffects()` maps every canonical Band tool name to its `TurnEffect`;
270
+ normalize an alias to its canonical name before the lookup. `noReplyTool()`
271
+ returns `band_no_reply`'s definition as a `ToolSpec` (`name`, `description`,
272
+ `parameters`). `turnEffects()` and `turnVerdicts()` list the wire names.
273
+
274
+ ```ts
275
+ import { TurnLedger, bandToolEffects } from "@band-ai/band-sdk-core";
276
+
277
+ const ledger = new TurnLedger();
278
+ ledger.record(bandToolEffects().band_send_event);
279
+ if (ledger.verdict() !== "missing_reply") {
280
+ throw new Error("an observe-only turn is a missing reply");
281
+ }
282
+
283
+ ledger.record("reply");
284
+ if (ledger.verdict() !== "complete" || !ledger.replySettled()) {
285
+ throw new Error("a reply must complete the turn");
286
+ }
287
+ ```
288
+
247
289
  The public declaration is
248
290
  [`index.d.ts`](https://github.com/band-ai/band-sdk-core/blob/main/crates/wasm/index.d.ts).
249
291
 
package/band_sdk_core.js CHANGED
@@ -118,8 +118,8 @@ exports.AgentFailure = AgentFailure;
118
118
 
119
119
  /**
120
120
  * Ownership ledger for the inbound message-delivery lifecycle: in-flight,
121
- * ack-pending, and completed states, each scoped by `(roomId,
122
- * messageId)`.
121
+ * ack-pending (a stored processed/failed intent, optionally parked), and
122
+ * completed states, each scoped by `(roomId, messageId)`.
123
123
  */
124
124
  class ClaimRegistry {
125
125
  __destroy_into_raw() {
@@ -210,6 +210,21 @@ class ClaimRegistry {
210
210
  ClaimRegistryFinalization.register(this, this.__wbg_ptr, this);
211
211
  return this;
212
212
  }
213
+ /**
214
+ * Mark a pending entry parked for `reason` (`"not_found"` or
215
+ * `"rejected"`); `false` when nothing is pending for the message.
216
+ * @param {any} room_id
217
+ * @param {any} message_id
218
+ * @param {any} reason
219
+ * @returns {boolean}
220
+ */
221
+ parkAck(room_id, message_id, reason) {
222
+ const ret = wasm.claimregistry_parkAck(this.__wbg_ptr, room_id, message_id, reason);
223
+ if (ret[2]) {
224
+ throw takeFromExternrefTable0(ret[1]);
225
+ }
226
+ return ret[0] !== 0;
227
+ }
213
228
  /**
214
229
  * @param {any} room_id
215
230
  * @returns {string[]}
@@ -223,6 +238,20 @@ class ClaimRegistry {
223
238
  wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
224
239
  return v1;
225
240
  }
241
+ /**
242
+ * The pending entry as `{status: "processed" | "failed", error?:
243
+ * string, parked: "not_found" | "rejected" | null}`, or `undefined`.
244
+ * @param {any} room_id
245
+ * @param {any} message_id
246
+ * @returns {any}
247
+ */
248
+ pendingAck(room_id, message_id) {
249
+ const ret = wasm.claimregistry_pendingAck(this.__wbg_ptr, room_id, message_id);
250
+ if (ret[2]) {
251
+ throw takeFromExternrefTable0(ret[1]);
252
+ }
253
+ return takeFromExternrefTable0(ret[0]);
254
+ }
226
255
  /**
227
256
  * @param {any} room_id
228
257
  * @param {any} message_id
@@ -265,6 +294,21 @@ class ClaimRegistry {
265
294
  throw takeFromExternrefTable0(ret[0]);
266
295
  }
267
296
  }
297
+ /**
298
+ * Record a failed turn awaiting a durable failed write carrying
299
+ * `error`. Throws if a different intent is already pending, with
300
+ * `.issues` and `.traceContext`.
301
+ * @param {any} room_id
302
+ * @param {any} message_id
303
+ * @param {any} error
304
+ * @param {any} traceContext
305
+ */
306
+ rememberFailedAckPending(room_id, message_id, error, traceContext) {
307
+ const ret = wasm.claimregistry_rememberFailedAckPending(this.__wbg_ptr, room_id, message_id, error, traceContext);
308
+ if (ret[1]) {
309
+ throw takeFromExternrefTable0(ret[0]);
310
+ }
311
+ }
268
312
  /**
269
313
  * @param {any} room_id
270
314
  * @param {any} message_id
@@ -277,6 +321,17 @@ class ClaimRegistry {
277
321
  }
278
322
  return ret[0] !== 0;
279
323
  }
324
+ /**
325
+ * @param {any} room_id
326
+ * @returns {number}
327
+ */
328
+ unparkAcks(room_id) {
329
+ const ret = wasm.claimregistry_unparkAcks(this.__wbg_ptr, room_id);
330
+ if (ret[2]) {
331
+ throw takeFromExternrefTable0(ret[1]);
332
+ }
333
+ return ret[0] >>> 0;
334
+ }
280
335
  }
281
336
  if (Symbol.dispose) ClaimRegistry.prototype[Symbol.dispose] = ClaimRegistry.prototype.free;
282
337
  exports.ClaimRegistry = ClaimRegistry;
@@ -1369,6 +1424,68 @@ class SubscriptionTracker {
1369
1424
  if (Symbol.dispose) SubscriptionTracker.prototype[Symbol.dispose] = SubscriptionTracker.prototype.free;
1370
1425
  exports.SubscriptionTracker = SubscriptionTracker;
1371
1426
 
1427
+ /**
1428
+ * One agent turn's progress toward a reply. `record` throws a plain
1429
+ * `Error` for anything but a `TurnEffect` wire name.
1430
+ */
1431
+ class TurnLedger {
1432
+ __destroy_into_raw() {
1433
+ const ptr = this.__wbg_ptr;
1434
+ this.__wbg_ptr = 0;
1435
+ TurnLedgerFinalization.unregister(this);
1436
+ return ptr;
1437
+ }
1438
+ free() {
1439
+ const ptr = this.__destroy_into_raw();
1440
+ wasm.__wbg_turnledger_free(ptr, 0);
1441
+ }
1442
+ constructor() {
1443
+ const ret = wasm.turnledger_new();
1444
+ this.__wbg_ptr = ret;
1445
+ TurnLedgerFinalization.register(this, this.__wbg_ptr, this);
1446
+ return this;
1447
+ }
1448
+ noteReported() {
1449
+ wasm.turnledger_noteReported(this.__wbg_ptr);
1450
+ }
1451
+ /**
1452
+ * @param {any} effect
1453
+ */
1454
+ record(effect) {
1455
+ const ret = wasm.turnledger_record(this.__wbg_ptr, effect);
1456
+ if (ret[1]) {
1457
+ throw takeFromExternrefTable0(ret[0]);
1458
+ }
1459
+ }
1460
+ /**
1461
+ * @returns {boolean}
1462
+ */
1463
+ replySettled() {
1464
+ const ret = wasm.turnledger_replySettled(this.__wbg_ptr);
1465
+ return ret !== 0;
1466
+ }
1467
+ settle() {
1468
+ wasm.turnledger_settle(this.__wbg_ptr);
1469
+ }
1470
+ /**
1471
+ * @returns {string}
1472
+ */
1473
+ verdict() {
1474
+ let deferred1_0;
1475
+ let deferred1_1;
1476
+ try {
1477
+ const ret = wasm.turnledger_verdict(this.__wbg_ptr);
1478
+ deferred1_0 = ret[0];
1479
+ deferred1_1 = ret[1];
1480
+ return getStringFromWasm0(ret[0], ret[1]);
1481
+ } finally {
1482
+ wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
1483
+ }
1484
+ }
1485
+ }
1486
+ if (Symbol.dispose) TurnLedger.prototype[Symbol.dispose] = TurnLedger.prototype.free;
1487
+ exports.TurnLedger = TurnLedger;
1488
+
1372
1489
  /**
1373
1490
  * This platform's Phoenix Channels topic for the `agent_contacts` channel.
1374
1491
  * @param {any} agentId
@@ -1444,6 +1561,20 @@ function agentRoomsTopic(agentId) {
1444
1561
  }
1445
1562
  exports.agentRoomsTopic = agentRoomsTopic;
1446
1563
 
1564
+ /**
1565
+ * Every Band tool's canonical name and its `TurnEffect` wire name, as a
1566
+ * plain object in the core table's order.
1567
+ * @returns {any}
1568
+ */
1569
+ function bandToolEffects() {
1570
+ const ret = wasm.bandToolEffects();
1571
+ if (ret[2]) {
1572
+ throw takeFromExternrefTable0(ret[1]);
1573
+ }
1574
+ return takeFromExternrefTable0(ret[0]);
1575
+ }
1576
+ exports.bandToolEffects = bandToolEffects;
1577
+
1447
1578
  /**
1448
1579
  * This platform's Phoenix Channels topic for a room's `chat_room` channel.
1449
1580
  * @param {any} roomId
@@ -1684,6 +1815,49 @@ function memoryTypes() {
1684
1815
  }
1685
1816
  exports.memoryTypes = memoryTypes;
1686
1817
 
1818
+ /**
1819
+ * The text shown to the room on a `"missing_reply"` verdict.
1820
+ * @returns {string}
1821
+ */
1822
+ function missingReplyMessage() {
1823
+ let deferred1_0;
1824
+ let deferred1_1;
1825
+ try {
1826
+ const ret = wasm.missingReplyMessage();
1827
+ deferred1_0 = ret[0];
1828
+ deferred1_1 = ret[1];
1829
+ return getStringFromWasm0(ret[0], ret[1]);
1830
+ } finally {
1831
+ wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
1832
+ }
1833
+ }
1834
+ exports.missingReplyMessage = missingReplyMessage;
1835
+
1836
+ /**
1837
+ * `band_no_reply`'s definition as a plain `ToolSpec` object.
1838
+ * @returns {any}
1839
+ */
1840
+ function noReplyTool() {
1841
+ const ret = wasm.noReplyTool();
1842
+ if (ret[2]) {
1843
+ throw takeFromExternrefTable0(ret[1]);
1844
+ }
1845
+ return takeFromExternrefTable0(ret[0]);
1846
+ }
1847
+ exports.noReplyTool = noReplyTool;
1848
+
1849
+ /**
1850
+ * r" Every `ClaimRegistry.parkAck` reason, in declaration order.
1851
+ * @returns {string[]}
1852
+ */
1853
+ function parkedReasons() {
1854
+ const ret = wasm.parkedReasons();
1855
+ var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]);
1856
+ wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
1857
+ return v1;
1858
+ }
1859
+ exports.parkedReasons = parkedReasons;
1860
+
1687
1861
  /**
1688
1862
  * This platform's Phoenix Channels topic for a room's `room_participants`
1689
1863
  * channel.
@@ -1710,6 +1884,30 @@ function roomParticipantsTopic(roomId) {
1710
1884
  }
1711
1885
  exports.roomParticipantsTopic = roomParticipantsTopic;
1712
1886
 
1887
+ /**
1888
+ * r" Every [`TurnEffect`] wire name, in declaration order.
1889
+ * @returns {string[]}
1890
+ */
1891
+ function turnEffects() {
1892
+ const ret = wasm.turnEffects();
1893
+ var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]);
1894
+ wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
1895
+ return v1;
1896
+ }
1897
+ exports.turnEffects = turnEffects;
1898
+
1899
+ /**
1900
+ * r" Every [`TurnVerdict`] wire name, in declaration order.
1901
+ * @returns {string[]}
1902
+ */
1903
+ function turnVerdicts() {
1904
+ const ret = wasm.turnVerdicts();
1905
+ var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]);
1906
+ wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
1907
+ return v1;
1908
+ }
1909
+ exports.turnVerdicts = turnVerdicts;
1910
+
1713
1911
  /**
1714
1912
  * Validate and normalize an inbound platform event payload.
1715
1913
  *
@@ -1753,7 +1951,7 @@ exports.validateMemoryTypeForSystem = validateMemoryTypeForSystem;
1753
1951
  function __wbg_get_imports() {
1754
1952
  const import0 = {
1755
1953
  __proto__: null,
1756
- __wbg_Error_67e7344beaa85059: function(arg0, arg1) {
1954
+ __wbg_Error_30c8987f7c2ed4e2: function(arg0, arg1) {
1757
1955
  const ret = Error(getStringFromWasm0(arg0, arg1));
1758
1956
  return ret;
1759
1957
  },
@@ -1764,68 +1962,68 @@ function __wbg_get_imports() {
1764
1962
  getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
1765
1963
  getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
1766
1964
  },
1767
- __wbg___wbindgen_bigint_get_as_i64_b482365c149396c8: function(arg0, arg1) {
1965
+ __wbg___wbindgen_bigint_get_as_i64_a2383202b9353e4c: function(arg0, arg1) {
1768
1966
  const v = arg1;
1769
1967
  const ret = typeof(v) === 'bigint' ? v : undefined;
1770
1968
  getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
1771
1969
  getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
1772
1970
  },
1773
- __wbg___wbindgen_boolean_get_7a12af2b3f899c5a: function(arg0) {
1971
+ __wbg___wbindgen_boolean_get_5b446f51afd21013: function(arg0) {
1774
1972
  const v = arg0;
1775
1973
  const ret = typeof(v) === 'boolean' ? v : undefined;
1776
1974
  return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
1777
1975
  },
1778
- __wbg___wbindgen_debug_string_0e68cf47c9cbd9b0: function(arg0, arg1) {
1976
+ __wbg___wbindgen_debug_string_4687d8d8c2017d52: function(arg0, arg1) {
1779
1977
  const ret = debugString(arg1);
1780
1978
  const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1781
1979
  const len1 = WASM_VECTOR_LEN;
1782
1980
  getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
1783
1981
  getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
1784
1982
  },
1785
- __wbg___wbindgen_in_50072d4d6e45c193: function(arg0, arg1) {
1983
+ __wbg___wbindgen_in_92f62ee1427d9e49: function(arg0, arg1) {
1786
1984
  const ret = arg0 in arg1;
1787
1985
  return ret;
1788
1986
  },
1789
- __wbg___wbindgen_is_bigint_60fc0336cb14f5d7: function(arg0) {
1987
+ __wbg___wbindgen_is_bigint_b123553bed3bb382: function(arg0) {
1790
1988
  const ret = typeof(arg0) === 'bigint';
1791
1989
  return ret;
1792
1990
  },
1793
- __wbg___wbindgen_is_function_fcda5e3902d732fe: function(arg0) {
1991
+ __wbg___wbindgen_is_function_1f9d30630b8b1d3d: function(arg0) {
1794
1992
  const ret = typeof(arg0) === 'function';
1795
1993
  return ret;
1796
1994
  },
1797
- __wbg___wbindgen_is_null_5160b3e381865372: function(arg0) {
1995
+ __wbg___wbindgen_is_null_e343b7d08827ba72: function(arg0) {
1798
1996
  const ret = arg0 === null;
1799
1997
  return ret;
1800
1998
  },
1801
- __wbg___wbindgen_is_object_edb6b15aa3afe12e: function(arg0) {
1999
+ __wbg___wbindgen_is_object_3c45d4f2dde4e749: function(arg0) {
1802
2000
  const val = arg0;
1803
2001
  const ret = typeof(val) === 'object' && val !== null;
1804
2002
  return ret;
1805
2003
  },
1806
- __wbg___wbindgen_is_string_c4f7cb494a2a21f1: function(arg0) {
2004
+ __wbg___wbindgen_is_string_90b56bc79aad6f6c: function(arg0) {
1807
2005
  const ret = typeof(arg0) === 'string';
1808
2006
  return ret;
1809
2007
  },
1810
- __wbg___wbindgen_is_undefined_8c687d0b90d5b524: function(arg0) {
2008
+ __wbg___wbindgen_is_undefined_8865fb403f8fe9d8: function(arg0) {
1811
2009
  const ret = arg0 === undefined;
1812
2010
  return ret;
1813
2011
  },
1814
- __wbg___wbindgen_jsval_eq_9fdcd3c0a860dd3b: function(arg0, arg1) {
2012
+ __wbg___wbindgen_jsval_eq_02babf21faa37971: function(arg0, arg1) {
1815
2013
  const ret = arg0 === arg1;
1816
2014
  return ret;
1817
2015
  },
1818
- __wbg___wbindgen_jsval_loose_eq_3c30021c243b64cd: function(arg0, arg1) {
2016
+ __wbg___wbindgen_jsval_loose_eq_677f21e468d6b461: function(arg0, arg1) {
1819
2017
  const ret = arg0 == arg1;
1820
2018
  return ret;
1821
2019
  },
1822
- __wbg___wbindgen_number_get_1dc732b810cb937c: function(arg0, arg1) {
2020
+ __wbg___wbindgen_number_get_2e0e7dee9f701a71: function(arg0, arg1) {
1823
2021
  const obj = arg1;
1824
2022
  const ret = typeof(obj) === 'number' ? obj : undefined;
1825
2023
  getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
1826
2024
  getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
1827
2025
  },
1828
- __wbg___wbindgen_string_get_92ab86bb19cbc12f: function(arg0, arg1) {
2026
+ __wbg___wbindgen_string_get_0380ccaa2f57f0d9: function(arg0, arg1) {
1829
2027
  const obj = arg1;
1830
2028
  const ret = typeof(obj) === 'string' ? obj : undefined;
1831
2029
  var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
@@ -1833,38 +2031,38 @@ function __wbg_get_imports() {
1833
2031
  getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
1834
2032
  getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
1835
2033
  },
1836
- __wbg___wbindgen_throw_5d9e815e6fdf150f: function(arg0, arg1) {
2034
+ __wbg___wbindgen_throw_41e9ee4f547fc59a: function(arg0, arg1) {
1837
2035
  throw new Error(getStringFromWasm0(arg0, arg1));
1838
2036
  },
1839
- __wbg_call_269c5566fbede3eb: function() { return handleError(function (arg0, arg1) {
2037
+ __wbg_call_6137034ef55c9d0f: function() { return handleError(function (arg0, arg1) {
1840
2038
  const ret = arg0.call(arg1);
1841
2039
  return ret;
1842
2040
  }, arguments); },
1843
- __wbg_done_cffed884d87aa22e: function(arg0) {
2041
+ __wbg_done_b41a1d26cdb37fb6: function(arg0) {
1844
2042
  const ret = arg0.done;
1845
2043
  return ret;
1846
2044
  },
1847
- __wbg_entries_972a87586902cf87: function(arg0) {
2045
+ __wbg_entries_fb6397112b1de25f: function(arg0) {
1848
2046
  const ret = Object.entries(arg0);
1849
2047
  return ret;
1850
2048
  },
1851
- __wbg_from_a39669ce566077da: function(arg0) {
2049
+ __wbg_from_296ca31f8d0f1c52: function(arg0) {
1852
2050
  const ret = Array.from(arg0);
1853
2051
  return ret;
1854
2052
  },
1855
- __wbg_get_6cf5a4d4d8ad3c5a: function() { return handleError(function (arg0, arg1) {
2053
+ __wbg_get_31af05bd4842a84f: function() { return handleError(function (arg0, arg1) {
1856
2054
  const ret = Reflect.get(arg0, arg1);
1857
2055
  return ret;
1858
2056
  }, arguments); },
1859
- __wbg_get_989d0a1309644f2b: function() { return handleError(function (arg0, arg1) {
2057
+ __wbg_get_658f6698067d9515: function() { return handleError(function (arg0, arg1) {
1860
2058
  const ret = Reflect.get(arg0, arg1);
1861
2059
  return ret;
1862
2060
  }, arguments); },
1863
- __wbg_get_b1f0ab13c737f856: function(arg0, arg1) {
2061
+ __wbg_get_6c896e0571ddae51: function(arg0, arg1) {
1864
2062
  const ret = arg0[arg1 >>> 0];
1865
2063
  return ret;
1866
2064
  },
1867
- __wbg_get_unchecked_363572bdd397d473: function(arg0, arg1) {
2065
+ __wbg_get_unchecked_288889d017702237: function(arg0, arg1) {
1868
2066
  const ret = arg0[arg1 >>> 0];
1869
2067
  return ret;
1870
2068
  },
@@ -1872,7 +2070,7 @@ function __wbg_get_imports() {
1872
2070
  const ret = arg0[arg1];
1873
2071
  return ret;
1874
2072
  },
1875
- __wbg_instanceof_ArrayBuffer_d4ff01f8247925ae: function(arg0) {
2073
+ __wbg_instanceof_ArrayBuffer_a99f175873e5d9b8: function(arg0) {
1876
2074
  let result;
1877
2075
  try {
1878
2076
  result = arg0 instanceof ArrayBuffer;
@@ -1882,7 +2080,7 @@ function __wbg_get_imports() {
1882
2080
  const ret = result;
1883
2081
  return ret;
1884
2082
  },
1885
- __wbg_instanceof_Map_1ff6a2b54c899f0d: function(arg0) {
2083
+ __wbg_instanceof_Map_b2611749102d7ba3: function(arg0) {
1886
2084
  let result;
1887
2085
  try {
1888
2086
  result = arg0 instanceof Map;
@@ -1892,7 +2090,7 @@ function __wbg_get_imports() {
1892
2090
  const ret = result;
1893
2091
  return ret;
1894
2092
  },
1895
- __wbg_instanceof_Set_daa5e1ad3c6acaeb: function(arg0) {
2093
+ __wbg_instanceof_Set_3b384cb03733893a: function(arg0) {
1896
2094
  let result;
1897
2095
  try {
1898
2096
  result = arg0 instanceof Set;
@@ -1902,7 +2100,7 @@ function __wbg_get_imports() {
1902
2100
  const ret = result;
1903
2101
  return ret;
1904
2102
  },
1905
- __wbg_instanceof_Uint8Array_598adc0fef426aa8: function(arg0) {
2103
+ __wbg_instanceof_Uint8Array_828cef2aaacafc31: function(arg0) {
1906
2104
  let result;
1907
2105
  try {
1908
2106
  result = arg0 instanceof Uint8Array;
@@ -1912,84 +2110,84 @@ function __wbg_get_imports() {
1912
2110
  const ret = result;
1913
2111
  return ret;
1914
2112
  },
1915
- __wbg_isArray_5674713bb7b79043: function(arg0) {
2113
+ __wbg_isArray_e15a2ff68ffdbef2: function(arg0) {
1916
2114
  const ret = Array.isArray(arg0);
1917
2115
  return ret;
1918
2116
  },
1919
- __wbg_isSafeInteger_8f51c743827d1ec5: function(arg0) {
2117
+ __wbg_isSafeInteger_717808ad6a54bd9e: function(arg0) {
1920
2118
  const ret = Number.isSafeInteger(arg0);
1921
2119
  return ret;
1922
2120
  },
1923
- __wbg_iterator_22ddeb808cf55a6f: function() {
2121
+ __wbg_iterator_e3c31c892080e444: function() {
1924
2122
  const ret = Symbol.iterator;
1925
2123
  return ret;
1926
2124
  },
1927
- __wbg_length_31bdaf014f5fbde2: function(arg0) {
2125
+ __wbg_length_7f3c00c40364105e: function(arg0) {
1928
2126
  const ret = arg0.length;
1929
2127
  return ret;
1930
2128
  },
1931
- __wbg_length_4e1adc0d42e23620: function(arg0) {
2129
+ __wbg_length_d4bdea10311bd9cf: function(arg0) {
1932
2130
  const ret = arg0.length;
1933
2131
  return ret;
1934
2132
  },
1935
- __wbg_new_1da3429bc3c4541c: function(arg0) {
2133
+ __wbg_new_1dbf7428bba60a42: function(arg0) {
1936
2134
  const ret = new Uint8Array(arg0);
1937
2135
  return ret;
1938
2136
  },
1939
- __wbg_new_8d36e20aa758e411: function() {
2137
+ __wbg_new_28744009d011f847: function() {
1940
2138
  const ret = new Map();
1941
2139
  return ret;
1942
2140
  },
1943
- __wbg_new_a32a1ab6c6655abe: function(arg0, arg1) {
2141
+ __wbg_new_343a093a3c2ffb4e: function(arg0, arg1) {
1944
2142
  const ret = new Error(getStringFromWasm0(arg0, arg1));
1945
2143
  return ret;
1946
2144
  },
1947
- __wbg_new_bebc3f4757acf305: function() {
2145
+ __wbg_new_617a8cdb8bb1130e: function() {
1948
2146
  const ret = new Object();
1949
2147
  return ret;
1950
2148
  },
1951
- __wbg_new_ffa92086ea89f79c: function() {
2149
+ __wbg_new_ee2291f50781bf1d: function() {
1952
2150
  const ret = new Array();
1953
2151
  return ret;
1954
2152
  },
1955
- __wbg_next_95053e306b1c3aed: function(arg0) {
2153
+ __wbg_next_33784799010f1bbe: function(arg0) {
1956
2154
  const ret = arg0.next;
1957
2155
  return ret;
1958
2156
  },
1959
- __wbg_next_f31ecb8646d2c605: function() { return handleError(function (arg0) {
2157
+ __wbg_next_f4aac29c42af995c: function() { return handleError(function (arg0) {
1960
2158
  const ret = arg0.next();
1961
2159
  return ret;
1962
2160
  }, arguments); },
1963
- __wbg_of_1c173c2ad96e2f7e: function(arg0, arg1) {
2161
+ __wbg_of_20798cb14708764f: function(arg0, arg1) {
1964
2162
  const ret = Array.of(arg0, arg1);
1965
2163
  return ret;
1966
2164
  },
1967
- __wbg_prototypesetcall_ae9f5e7459250748: function(arg0, arg1, arg2) {
2165
+ __wbg_prototypesetcall_bc27214492979395: function(arg0, arg1, arg2) {
1968
2166
  Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
1969
2167
  },
1970
- __wbg_push_bfdf956ba476f65b: function(arg0, arg1) {
2168
+ __wbg_push_2baf45db356cf468: function(arg0, arg1) {
1971
2169
  const ret = arg0.push(arg1);
1972
2170
  return ret;
1973
2171
  },
1974
- __wbg_random_7bce4e9e78e2e0d0: function() {
2172
+ __wbg_random_5a4cafd2f02395ff: function() {
1975
2173
  const ret = Math.random();
1976
2174
  return ret;
1977
2175
  },
1978
- __wbg_set_13d25b81ab403f5e: function(arg0, arg1, arg2) {
1979
- arg0[arg1 >>> 0] = arg2;
1980
- },
1981
- __wbg_set_6be42768c690e380: function(arg0, arg1, arg2) {
1982
- arg0[arg1] = arg2;
1983
- },
1984
- __wbg_set_a377297433dfea63: function() { return handleError(function (arg0, arg1, arg2) {
2176
+ __wbg_set_145a351398b48c65: function() { return handleError(function (arg0, arg1, arg2) {
1985
2177
  const ret = Reflect.set(arg0, arg1, arg2);
1986
2178
  return ret;
1987
2179
  }, arguments); },
1988
- __wbg_set_bf6dde4923b9b059: function(arg0, arg1, arg2) {
2180
+ __wbg_set_6ae97e73113c4f0b: function(arg0, arg1, arg2) {
1989
2181
  const ret = arg0.set(arg1, arg2);
1990
2182
  return ret;
1991
2183
  },
1992
- __wbg_value_c227f843d21da141: function(arg0) {
2184
+ __wbg_set_6be42768c690e380: function(arg0, arg1, arg2) {
2185
+ arg0[arg1] = arg2;
2186
+ },
2187
+ __wbg_set_bea140a88be9b277: function(arg0, arg1, arg2) {
2188
+ arg0[arg1 >>> 0] = arg2;
2189
+ },
2190
+ __wbg_value_f3c585ee8f5ba40c: function(arg0) {
1993
2191
  const ret = arg0.value;
1994
2192
  return ret;
1995
2193
  },
@@ -2062,6 +2260,9 @@ const SessionPolicyFinalization = (typeof FinalizationRegistry === 'undefined')
2062
2260
  const SubscriptionTrackerFinalization = (typeof FinalizationRegistry === 'undefined')
2063
2261
  ? { register: () => {}, unregister: () => {} }
2064
2262
  : new FinalizationRegistry(ptr => wasm.__wbg_subscriptiontracker_free(ptr, 1));
2263
+ const TurnLedgerFinalization = (typeof FinalizationRegistry === 'undefined')
2264
+ ? { register: () => {}, unregister: () => {} }
2265
+ : new FinalizationRegistry(ptr => wasm.__wbg_turnledger_free(ptr, 1));
2065
2266
 
2066
2267
  function addToExternrefTable0(obj) {
2067
2268
  const idx = wasm.__externref_table_alloc();
Binary file
package/index.d.ts CHANGED
@@ -128,9 +128,25 @@ export interface ParticipantFields {
128
128
  description?: string | null;
129
129
  }
130
130
 
131
+ /**
132
+ * Why the platform refused a terminal write that stays pending:
133
+ * `not_found` when the message or room is not visible, `rejected` when it
134
+ * proved no processing attempt exists to settle.
135
+ */
136
+ export type ParkedReason = "not_found" | "rejected";
137
+
138
+ /** Every {@link ParkedReason} wire name, in declaration order. */
139
+ export function parkedReasons(): ParkedReason[];
140
+
141
+ /** A pending entry: its fixed terminal intent plus whether it is parked. */
142
+ export type PendingAck =
143
+ | { status: "processed"; parked: ParkedReason | null }
144
+ | { status: "failed"; error: string; parked: ParkedReason | null };
145
+
131
146
  /**
132
147
  * Ownership ledger for the inbound message-delivery lifecycle: in-flight,
133
- * ack-pending, and completed states, each scoped by `(roomId, messageId)`.
148
+ * ack-pending (a stored processed/failed intent, optionally parked), and
149
+ * completed states, each scoped by `(roomId, messageId)`.
134
150
  *
135
151
  * Throws if `maxCompleted` is not a non-negative integer in range, or is
136
152
  * `0` -- a zero capacity would evict every completed entry the instant it
@@ -149,6 +165,20 @@ export class ClaimRegistry {
149
165
  rememberCompleted(roomId: string, messageId: string): void;
150
166
  isAckPending(roomId: string, messageId: string): boolean;
151
167
  rememberAckPending(roomId: string, messageId: string): void;
168
+ /**
169
+ * Throws if a different terminal intent is already pending, with `.issues`
170
+ * and `.traceContext`.
171
+ */
172
+ rememberFailedAckPending(
173
+ roomId: string,
174
+ messageId: string,
175
+ error: string,
176
+ traceContext?: string | null,
177
+ ): void;
178
+ pendingAck(roomId: string, messageId: string): PendingAck | undefined;
179
+ /** `false` when nothing is pending for the message; throws on an unknown reason. */
180
+ parkAck(roomId: string, messageId: string, reason: ParkedReason): boolean;
181
+ unparkAcks(roomId: string): number;
152
182
  pendingAckIds(roomId: string): string[];
153
183
  recordAckRetry(roomId: string, messageId: string): number;
154
184
  }
@@ -617,3 +647,82 @@ export function evaluateAdapterResult(
617
647
  * `senderId`/`senderType`/`agentId` is not a string.
618
648
  */
619
649
  export function isSelfEcho(senderId: string, senderType: string, agentId: string): boolean;
650
+
651
+ /** What a successful tool call contributes to the turn. */
652
+ export type TurnEffect = "observe" | "act" | "reply" | "decline";
653
+
654
+ /** How the SDK ends a turn, per {@link TurnLedger.verdict}. */
655
+ export type TurnVerdict = "complete" | "missing_reply";
656
+
657
+ /** Every Band tool's canonical name. */
658
+ export type BandToolName =
659
+ | "band_get_participants"
660
+ | "band_lookup_peers"
661
+ | "band_list_contacts"
662
+ | "band_list_contact_requests"
663
+ | "band_list_memories"
664
+ | "band_get_memory"
665
+ | "band_list_room_files"
666
+ | "band_read_room_file"
667
+ | "band_list_tasks"
668
+ | "band_get_task"
669
+ | "band_get_task_history"
670
+ | "band_get_board"
671
+ | "band_send_event"
672
+ | "band_add_participant"
673
+ | "band_remove_participant"
674
+ | "band_create_chatroom"
675
+ | "band_add_contact"
676
+ | "band_remove_contact"
677
+ | "band_respond_contact_request"
678
+ | "band_store_memory"
679
+ | "band_supersede_memory"
680
+ | "band_archive_memory"
681
+ | "band_create_task"
682
+ | "band_update_task"
683
+ | "band_set_board"
684
+ | "band_send_message"
685
+ | "band_send_room_file"
686
+ | "band_no_reply";
687
+
688
+ /** Every {@link TurnEffect} wire name, in declaration order. */
689
+ export function turnEffects(): TurnEffect[];
690
+
691
+ /** Every {@link TurnVerdict} wire name, in declaration order. */
692
+ export function turnVerdicts(): TurnVerdict[];
693
+
694
+ /**
695
+ * One agent turn's progress toward a reply. Record only successful tool
696
+ * calls. `record` throws a plain `Error` for anything but a
697
+ * {@link TurnEffect}.
698
+ */
699
+ export class TurnLedger {
700
+ constructor();
701
+ record(effect: TurnEffect): void;
702
+ settle(): void;
703
+ noteReported(): void;
704
+ replySettled(): boolean;
705
+ verdict(): TurnVerdict;
706
+ }
707
+
708
+ /** Every Band tool's canonical name and its {@link TurnEffect}. */
709
+ export function bandToolEffects(): Record<BandToolName, TurnEffect>;
710
+
711
+ /** One parameter of a {@link ToolSpec}. Each SDK declares its value type. */
712
+ export interface ToolParameterSpec {
713
+ name: string;
714
+ description: string;
715
+ required: boolean;
716
+ }
717
+ /** A tool definition as the model reads it. */
718
+ export interface ToolSpec {
719
+ name: string;
720
+ description: string;
721
+ parameters: ToolParameterSpec[];
722
+ }
723
+
724
+ /** `band_no_reply`'s definition. */
725
+ export function noReplyTool(): ToolSpec;
726
+
727
+ /** The text shown to the room on a `"missing_reply"` verdict. */
728
+ export function missingReplyMessage(): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@band-ai/band-sdk-core",
3
- "version": "2.7.0",
3
+ "version": "2.9.0",
4
4
  "description": "Shared Band event-payload validation",
5
5
  "license": "MIT",
6
6
  "repository": {