@band-ai/band-sdk-core 2.8.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
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;
@@ -1791,6 +1846,18 @@ function noReplyTool() {
1791
1846
  }
1792
1847
  exports.noReplyTool = noReplyTool;
1793
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
+
1794
1861
  /**
1795
1862
  * This platform's Phoenix Channels topic for a room's `room_participants`
1796
1863
  * channel.
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@band-ai/band-sdk-core",
3
- "version": "2.8.0",
3
+ "version": "2.9.0",
4
4
  "description": "Shared Band event-payload validation",
5
5
  "license": "MIT",
6
6
  "repository": {