@kybernesis/buzz 0.9.4 → 0.9.5

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/dist/turn.d.ts CHANGED
@@ -64,6 +64,21 @@ export declare function composeMessage(text: string, attachments: MediaRef[], fe
64
64
  /** Continue a channel's existing conversation, replacing it only when it is explicitly stale. */
65
65
  export declare function answerTurn(client: Client, sessions: SessionStore, channel: string, message: TurnMessage, community: string, log?: (message: string) => void, agentSilenceTimeoutMs?: number): Promise<TurnOutcome>;
66
66
  /** What the room is told when eve refuses the turn itself. */
67
+ /**
68
+ * The two answers from eve that mean the stored session cannot carry another
69
+ * turn: an unknown session id (404), and a session that ended (409 with
70
+ * `session_not_active`, "The session is no longer active."). A session ends
71
+ * when one of its turns fails hard, for instance a model call that 404s at
72
+ * the gateway; the channel must then start a fresh one.
73
+ *
74
+ * Only these replace the mapping. A 400 about the message, a timeout, or a
75
+ * transport failure says nothing about whether the session is alive, and
76
+ * discarding it on those is how conversations were lost (KYB-502). The 409
77
+ * was missed when the timeout work narrowed the rule to 404 alone, and a
78
+ * channel then failed every message with "The session is no longer active."
79
+ * until someone edited the store by hand.
80
+ */
81
+ export declare function isSessionGone(error: unknown): boolean;
67
82
  export declare function rejectedTurnReply(error: unknown): string | null;
68
83
  /** Give the originating channel one accurate recovery message for bridge-owned silence. */
69
84
  export declare function agentSilenceReply(error: unknown): string | null;
package/dist/turn.js CHANGED
@@ -268,7 +268,7 @@ export async function answerTurn(client, sessions, channel, message, community,
268
268
  catch (error) {
269
269
  // Transport uncertainty, request rejection, and our own timeout do not
270
270
  // prove the durable server conversation is stale. Preserve its mapping.
271
- if (!(error instanceof ClientError) || error.status !== 404)
271
+ if (!isSessionGone(error))
272
272
  throw error;
273
273
  log(`session for ${channel.slice(0, 8)} could not continue (${error.message}); starting a new one`);
274
274
  sessions.delete(community, channel);
@@ -305,6 +305,28 @@ export async function answerTurn(client, sessions, channel, message, community,
305
305
  }
306
306
  }
307
307
  /** What the room is told when eve refuses the turn itself. */
308
+ /**
309
+ * The two answers from eve that mean the stored session cannot carry another
310
+ * turn: an unknown session id (404), and a session that ended (409 with
311
+ * `session_not_active`, "The session is no longer active."). A session ends
312
+ * when one of its turns fails hard, for instance a model call that 404s at
313
+ * the gateway; the channel must then start a fresh one.
314
+ *
315
+ * Only these replace the mapping. A 400 about the message, a timeout, or a
316
+ * transport failure says nothing about whether the session is alive, and
317
+ * discarding it on those is how conversations were lost (KYB-502). The 409
318
+ * was missed when the timeout work narrowed the rule to 404 alone, and a
319
+ * channel then failed every message with "The session is no longer active."
320
+ * until someone edited the store by hand.
321
+ */
322
+ export function isSessionGone(error) {
323
+ if (!(error instanceof ClientError))
324
+ return false;
325
+ if (error.status === 404)
326
+ return true;
327
+ return (error.status === 409 &&
328
+ (error.code === "session_not_active" || /no longer active/i.test(String(error.message ?? ""))));
329
+ }
308
330
  export function rejectedTurnReply(error) {
309
331
  if (!(error instanceof ClientError) || error.status !== 400)
310
332
  return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kybernesis/buzz",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
4
4
  "description": "Put an eve agent in a Buzz workspace as a member: per-speaker verified identity resolved through the control plane, self-service identity linking, presence, typing and seen signals.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",