@band-ai/sdk 0.1.10 → 0.2.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.
Files changed (81) hide show
  1. package/README.md +54 -54
  2. package/dist/{ClaudeSDKAdapter-DfjaI5ke.d.cts → ClaudeSDKAdapter-BY4zEbCl.d.cts} +12 -10
  3. package/dist/{ClaudeSDKAdapter-DonPGJ43.d.ts → ClaudeSDKAdapter-Cna5P1dR.d.ts} +12 -10
  4. package/dist/{acp-server-NZAeg-WO.d.ts → acp-server-CiUqN3G3.d.ts} +2 -2
  5. package/dist/{acp-server-CUBXIiG6.d.cts → acp-server-Dlj7D563.d.cts} +2 -2
  6. package/dist/adapters.cjs +250 -183
  7. package/dist/adapters.d.cts +21 -19
  8. package/dist/adapters.d.ts +21 -19
  9. package/dist/adapters.js +65 -44
  10. package/dist/backends-D-dBdDm-.d.ts +27 -0
  11. package/dist/backends-ZLxmQrTZ.d.cts +27 -0
  12. package/dist/{chunk-2BHHR6YW.js → chunk-4IAXZBXX.js} +62 -23
  13. package/dist/{chunk-SG4WLD2H.js → chunk-EAI2M3WM.js} +38 -94
  14. package/dist/{chunk-YR3BOQNW.js → chunk-JY75VSQK.js} +7 -7
  15. package/dist/{chunk-RDM4TE4B.js → chunk-LBWKISBS.js} +19 -1
  16. package/dist/{chunk-FP237EAG.js → chunk-N2QTUMGO.js} +112 -195
  17. package/dist/{chunk-J3M3PFFY.js → chunk-NMZLX7TP.js} +35 -31
  18. package/dist/{chunk-6RXWL6TC.js → chunk-NT7TBFX2.js} +1 -1
  19. package/dist/{chunk-MLROFDKR.js → chunk-RV76SKFT.js} +39 -33
  20. package/dist/{chunk-XA4N2JPH.js → chunk-TLBCKDQO.js} +23 -23
  21. package/dist/{chunk-IZPV6QS6.js → chunk-WL2HNJZ6.js} +38 -11
  22. package/dist/{chunk-DNPVCR3S.js → chunk-WLCM2OXG.js} +31 -31
  23. package/dist/config.cjs +40 -13
  24. package/dist/config.d.cts +7 -1
  25. package/dist/config.d.ts +7 -1
  26. package/dist/config.js +2 -2
  27. package/dist/converters.cjs +61 -61
  28. package/dist/converters.d.cts +5 -5
  29. package/dist/converters.d.ts +5 -5
  30. package/dist/converters.js +4 -4
  31. package/dist/core.cjs +8 -8
  32. package/dist/core.d.cts +9 -9
  33. package/dist/core.d.ts +9 -9
  34. package/dist/core.js +3 -3
  35. package/dist/{dtos-Dd_fTfLn.d.cts → dtos-B8KU_q4d.d.cts} +2 -2
  36. package/dist/{dtos-Dd_fTfLn.d.ts → dtos-B8KU_q4d.d.ts} +2 -2
  37. package/dist/index.cjs +459 -504
  38. package/dist/index.d.cts +16 -15
  39. package/dist/index.d.ts +16 -15
  40. package/dist/index.js +15 -13
  41. package/dist/linear.cjs +74 -74
  42. package/dist/linear.d.cts +14 -14
  43. package/dist/linear.d.ts +14 -14
  44. package/dist/linear.js +72 -72
  45. package/dist/mcp-claude.cjs +37 -36
  46. package/dist/mcp-claude.d.cts +3 -3
  47. package/dist/mcp-claude.d.ts +3 -3
  48. package/dist/mcp-claude.js +7 -6
  49. package/dist/mcp.cjs +103 -62
  50. package/dist/mcp.d.cts +29 -16
  51. package/dist/mcp.d.ts +29 -16
  52. package/dist/mcp.js +14 -14
  53. package/dist/{opencode--iA5-KYk.d.cts → opencode-2YdscIc1.d.cts} +5 -5
  54. package/dist/{opencode-YNacv-eJ.d.ts → opencode-Bld62x5t.d.ts} +5 -5
  55. package/dist/{pagination-BBLsYLhT.d.ts → pagination-BgEx-HeL.d.ts} +2 -2
  56. package/dist/{pagination-CqidD-L_.d.cts → pagination-DqdkQArT.d.cts} +2 -2
  57. package/dist/{protocols-BF6jamIl.d.ts → protocols-Bwwcql0h.d.ts} +1 -1
  58. package/dist/{protocols-D2bTrQ_t.d.cts → protocols-Bz1rxcUg.d.cts} +1 -1
  59. package/dist/rest.cjs +41 -97
  60. package/dist/rest.d.cts +7 -7
  61. package/dist/rest.d.ts +7 -7
  62. package/dist/rest.js +2 -2
  63. package/dist/runtime.cjs +293 -464
  64. package/dist/runtime.d.cts +16 -28
  65. package/dist/runtime.d.ts +16 -28
  66. package/dist/runtime.js +12 -63
  67. package/dist/{schemas-CI0qgcp_.d.cts → schemas-BotL3ZLH.d.cts} +40 -54
  68. package/dist/{schemas-B1Fd3oUM.d.ts → schemas-DBsC4J1g.d.ts} +40 -54
  69. package/dist/{sdk-D2rTDU_o.d.cts → sdk-BTciSLRQ.d.cts} +5 -5
  70. package/dist/{sdk-CyqN1W5g.d.ts → sdk-qKJtMma_.d.ts} +5 -5
  71. package/dist/{simpleAdapter-qQt-tSz4.d.ts → simpleAdapter--wznuoOw.d.ts} +1 -1
  72. package/dist/{simpleAdapter-C_f-01Cu.d.cts → simpleAdapter-BpT4XbZC.d.cts} +1 -1
  73. package/dist/testing.d.cts +3 -3
  74. package/dist/testing.d.ts +3 -3
  75. package/dist/{types-DNySTI_8.d.ts → types-BTN_ZETM.d.ts} +2 -2
  76. package/dist/{types-D3AsUnd0.d.ts → types-BgYFd_Yw.d.cts} +5 -5
  77. package/dist/{types-DtMms5Fi.d.cts → types-BivGO7I9.d.ts} +5 -5
  78. package/dist/{types-CKqrhGB1.d.cts → types-D958TC71.d.cts} +2 -2
  79. package/package.json +6 -5
  80. package/dist/backends-DYtEhCZG.d.cts +0 -25
  81. package/dist/backends-oYAb7EU-.d.ts +0 -25
package/dist/runtime.cjs CHANGED
@@ -37,12 +37,13 @@ __export(runtime_exports, {
37
37
  GracefulShutdown: () => GracefulShutdown,
38
38
  HUB_ROOM_SYSTEM_PROMPT: () => HUB_ROOM_SYSTEM_PROMPT,
39
39
  HistoryProvider: () => HistoryProvider,
40
+ MCP_SERVER_NAME: () => MCP_SERVER_NAME,
40
41
  MCP_TOOL_PREFIX: () => MCP_TOOL_PREFIX,
41
42
  MEMORY_SECTION: () => MEMORY_SECTION,
42
43
  MEMORY_TOOL_NAMES: () => MEMORY_TOOL_NAMES,
43
- MessageRetryTracker: () => MessageRetryTracker,
44
- ParticipantTracker: () => ParticipantTracker,
44
+ ParticipantRoster: () => import_band_sdk_core3.ParticipantRoster,
45
45
  PlatformRuntime: () => PlatformRuntime,
46
+ RetryTracker: () => import_band_sdk_core3.RetryTracker,
46
47
  RoomPresence: () => RoomPresence,
47
48
  SYNTHETIC_CONTACT_EVENTS_SENDER_ID: () => SYNTHETIC_CONTACT_EVENTS_SENDER_ID,
48
49
  SYNTHETIC_CONTACT_EVENTS_SENDER_NAME: () => SYNTHETIC_CONTACT_EVENTS_SENDER_NAME,
@@ -99,39 +100,112 @@ var NoopLogger = class {
99
100
  var DEFAULT_REQUEST_OPTIONS = {
100
101
  maxRetries: 3
101
102
  };
103
+ var MESSAGE_SEND_MAX_RETRIES = 2;
102
104
 
103
105
  // src/core/errors.ts
104
- var ThenvoiSdkError = class extends Error {
106
+ var BandSdkError = class extends Error {
105
107
  constructor(message, cause) {
106
108
  super(message, cause !== void 0 ? { cause } : void 0);
107
- this.name = "ThenvoiSdkError";
109
+ this.name = "BandSdkError";
108
110
  }
109
111
  };
110
- var UnsupportedFeatureError = class extends ThenvoiSdkError {
112
+ var UnsupportedFeatureError = class extends BandSdkError {
111
113
  constructor(message) {
112
114
  super(message);
113
115
  this.name = "UnsupportedFeatureError";
114
116
  }
115
117
  };
116
- var ValidationError = class extends ThenvoiSdkError {
118
+ var ValidationError = class extends BandSdkError {
117
119
  constructor(message, cause) {
118
120
  super(message, cause);
119
121
  this.name = "ValidationError";
120
122
  }
121
123
  };
122
- var TransportError = class extends ThenvoiSdkError {
124
+ var TransportError = class extends BandSdkError {
123
125
  constructor(message, cause) {
124
126
  super(message, cause);
125
127
  this.name = "TransportError";
126
128
  }
127
129
  };
128
- var RuntimeStateError = class extends ThenvoiSdkError {
130
+ var RuntimeStateError = class extends BandSdkError {
129
131
  constructor(message) {
130
132
  super(message);
131
133
  this.name = "RuntimeStateError";
132
134
  }
133
135
  };
134
136
 
137
+ // src/runtime/formatters.ts
138
+ function isMetadataMap(value) {
139
+ return value !== null && typeof value === "object" && !Array.isArray(value);
140
+ }
141
+ function replaceUuidMentions(content, participants) {
142
+ if (!content || participants.length === 0) {
143
+ return content;
144
+ }
145
+ let next = content;
146
+ for (const participant of participants) {
147
+ const participantId = participant.id;
148
+ const handle = participant.handle;
149
+ if (typeof participantId === "string" && typeof handle === "string") {
150
+ next = next.replaceAll(`@[[${participantId}]]`, ensureHandlePrefix(handle) ?? "");
151
+ }
152
+ }
153
+ return next;
154
+ }
155
+ function formatMessageForLlm(message, participants) {
156
+ const senderType = String(message.sender_type ?? "");
157
+ const senderName = String(message.sender_name ?? message.name ?? senderType);
158
+ const content = participants ? replaceUuidMentions(String(message.content ?? ""), participants) : String(message.content ?? "");
159
+ return {
160
+ role: senderType === "Agent" ? "assistant" : "user",
161
+ content,
162
+ sender_name: senderName,
163
+ sender_type: senderType,
164
+ message_type: String(message.message_type ?? "text"),
165
+ metadata: isMetadataMap(message.metadata) ? message.metadata : {}
166
+ };
167
+ }
168
+ function formatHistoryForLlm(messages, options) {
169
+ const excludeId = options?.excludeId;
170
+ const participants = options?.participants;
171
+ return messages.filter((message) => String(message.id ?? "") !== excludeId).map((message) => formatMessageForLlm(message, participants));
172
+ }
173
+ function toParticipantRecord(fields) {
174
+ return {
175
+ id: fields.id,
176
+ name: fields.name ?? "unknown",
177
+ type: fields.type ?? "unknown",
178
+ handle: fields.handle ?? null
179
+ };
180
+ }
181
+ function toParticipantRecordFromRest(participant) {
182
+ return {
183
+ id: participant.id,
184
+ name: participant.name,
185
+ type: participant.type,
186
+ handle: participant.handle ?? null
187
+ };
188
+ }
189
+ function buildParticipantsMessage(participants) {
190
+ if (participants.length === 0) {
191
+ return "## Current Participants\nNo other participants in this room.";
192
+ }
193
+ const lines = ["## Current Participants"];
194
+ for (const participant of participants) {
195
+ const participantType = String(participant.type ?? "Unknown");
196
+ const participantName = String(participant.name ?? "Unknown");
197
+ const participantHandle = String(participant.handle ?? "Unknown");
198
+ lines.push(
199
+ `- ${ensureHandlePrefix(participantHandle) ?? ""} \u2014 ${participantName} (${participantType})`
200
+ );
201
+ }
202
+ lines.push("");
203
+ lines.push(
204
+ "IMPORTANT: In band_send_message mentions, always use the exact handle shown above (e.g. '@john' for users, '@john/weather-agent' for agents), NOT the display name. Handles are lowercase with no spaces."
205
+ );
206
+ return lines.join("\n");
207
+ }
208
+
135
209
  // src/runtime/tools/ContactToolsImpl.ts
136
210
  var ContactToolsImpl = class {
137
211
  rest;
@@ -228,14 +302,6 @@ var ContactToolsImpl = class {
228
302
  };
229
303
 
230
304
  // src/runtime/tools/ContactCallbackTools.ts
231
- function toParticipantRecord(participant) {
232
- return {
233
- id: participant.id,
234
- name: participant.name,
235
- type: participant.type,
236
- handle: participant.handle ?? null
237
- };
238
- }
239
305
  function normalizePage(value, fallback) {
240
306
  return Number.isInteger(value) && value && value > 0 ? value : fallback;
241
307
  }
@@ -279,8 +345,7 @@ var ContactCallbackTools = class {
279
345
  {
280
346
  content,
281
347
  ...normalizedMentions ? { mentions: normalizedMentions } : {}
282
- },
283
- DEFAULT_REQUEST_OPTIONS
348
+ }
284
349
  );
285
350
  }
286
351
  async sendEvent(content, messageType, metadata) {
@@ -294,8 +359,7 @@ var ContactCallbackTools = class {
294
359
  content,
295
360
  messageType,
296
361
  ...metadata ? { metadata } : {}
297
- },
298
- DEFAULT_REQUEST_OPTIONS
362
+ }
299
363
  );
300
364
  }
301
365
  async addParticipant() {
@@ -309,7 +373,7 @@ var ContactCallbackTools = class {
309
373
  if (!this.rest.listChatParticipants) {
310
374
  throw new UnsupportedFeatureError("Participant listing is not available in current REST adapter");
311
375
  }
312
- return (await this.rest.listChatParticipants(roomId, DEFAULT_REQUEST_OPTIONS)).map(toParticipantRecord);
376
+ return (await this.rest.listChatParticipants(roomId, DEFAULT_REQUEST_OPTIONS)).map(toParticipantRecordFromRest);
313
377
  }
314
378
  async createChatroom(taskId) {
315
379
  const chat = await this.rest.createChat(taskId, DEFAULT_REQUEST_OPTIONS);
@@ -399,48 +463,48 @@ var ContactCallbackTools = class {
399
463
  }
400
464
  async executeToolCall(toolName, toolArgs) {
401
465
  switch (toolName) {
402
- case "thenvoi_send_message":
466
+ case "band_send_message":
403
467
  return this.sendMessage(
404
468
  String(toolArgs.content ?? ""),
405
469
  toolArgs.mentions
406
470
  );
407
- case "thenvoi_send_event":
471
+ case "band_send_event":
408
472
  return this.sendEvent(
409
473
  String(toolArgs.content ?? ""),
410
474
  String(toolArgs.message_type ?? "task"),
411
475
  toolArgs.metadata
412
476
  );
413
- case "thenvoi_get_participants":
477
+ case "band_get_participants":
414
478
  return this.getParticipants();
415
- case "thenvoi_create_chatroom":
479
+ case "band_create_chatroom":
416
480
  return this.createChatroom(typeof toolArgs.task_id === "string" ? toolArgs.task_id : void 0);
417
- case "thenvoi_lookup_peers":
481
+ case "band_lookup_peers":
418
482
  return this.lookupPeers(
419
483
  typeof toolArgs.page === "number" ? toolArgs.page : void 0,
420
484
  typeof toolArgs.page_size === "number" ? toolArgs.page_size : void 0
421
485
  );
422
- case "thenvoi_list_contacts":
486
+ case "band_list_contacts":
423
487
  return this.listContacts({
424
488
  page: typeof toolArgs.page === "number" ? toolArgs.page : void 0,
425
489
  pageSize: typeof toolArgs.page_size === "number" ? toolArgs.page_size : void 0
426
490
  });
427
- case "thenvoi_add_contact":
491
+ case "band_add_contact":
428
492
  return this.addContact({
429
493
  handle: String(toolArgs.handle ?? ""),
430
494
  ...typeof toolArgs.message === "string" ? { message: toolArgs.message } : {}
431
495
  });
432
- case "thenvoi_remove_contact":
496
+ case "band_remove_contact":
433
497
  if (typeof toolArgs.contact_id === "string") {
434
498
  return this.removeContact({ target: "contactId", contactId: toolArgs.contact_id });
435
499
  }
436
500
  return this.removeContact({ target: "handle", handle: String(toolArgs.handle ?? "") });
437
- case "thenvoi_list_contact_requests":
501
+ case "band_list_contact_requests":
438
502
  return this.listContactRequests({
439
503
  page: typeof toolArgs.page === "number" ? toolArgs.page : void 0,
440
504
  pageSize: typeof toolArgs.page_size === "number" ? toolArgs.page_size : void 0,
441
505
  sentStatus: typeof toolArgs.sent_status === "string" ? toolArgs.sent_status : void 0
442
506
  });
443
- case "thenvoi_respond_contact_request":
507
+ case "band_respond_contact_request":
444
508
  if (typeof toolArgs.request_id === "string") {
445
509
  return this.respondContactRequest({
446
510
  action: String(toolArgs.action ?? "approve"),
@@ -453,15 +517,15 @@ var ContactCallbackTools = class {
453
517
  target: "handle",
454
518
  handle: String(toolArgs.handle ?? "")
455
519
  });
456
- case "thenvoi_list_memories":
520
+ case "band_list_memories":
457
521
  return this.listMemories(toolArgs);
458
- case "thenvoi_store_memory":
522
+ case "band_store_memory":
459
523
  return this.storeMemory(toolArgs);
460
- case "thenvoi_get_memory":
524
+ case "band_get_memory":
461
525
  return this.getMemory(String(toolArgs.memory_id ?? ""));
462
- case "thenvoi_supersede_memory":
526
+ case "band_supersede_memory":
463
527
  return this.supersedeMemory(String(toolArgs.memory_id ?? ""));
464
- case "thenvoi_archive_memory":
528
+ case "band_archive_memory":
465
529
  return this.archiveMemory(String(toolArgs.memory_id ?? ""));
466
530
  default:
467
531
  throw new UnsupportedFeatureError(`Unsupported tool call for contact callback: ${toolName}`);
@@ -475,14 +539,14 @@ var HUB_ROOM_SYSTEM_PROMPT = `## OVERRIDE: Contact Management Mode
475
539
 
476
540
  This is your CONTACTS HUB - a dedicated room for managing contact requests.
477
541
 
478
- **IMPORTANT: Do NOT delegate or add participants here.** You handle contact events DIRECTLY using the contact tools below. Do NOT call thenvoi_lookup_peers() or thenvoi_add_participant() in this room.
542
+ **IMPORTANT: Do NOT delegate or add participants here.** You handle contact events DIRECTLY using the contact tools below. Do NOT call band_lookup_peers() or band_add_participant() in this room.
479
543
 
480
544
  ## Your Role
481
545
 
482
546
  1. **Review incoming contact requests** - When you see a [Contact Request] message, evaluate it
483
547
  2. **Take action** - Use the contact tools to respond:
484
- - \`thenvoi_respond_contact_request(action="approve", request_id="...")\` to accept
485
- - \`thenvoi_respond_contact_request(action="reject", request_id="...")\` to decline
548
+ - \`band_respond_contact_request(action="approve", request_id="...")\` to accept
549
+ - \`band_respond_contact_request(action="reject", request_id="...")\` to decline
486
550
  3. **Report your decision** - Send a thought event explaining what you did
487
551
 
488
552
  ## Example
@@ -491,14 +555,14 @@ This is your CONTACTS HUB - a dedicated room for managing contact requests.
491
555
  Request ID: abc-123
492
556
 
493
557
  Your response:
494
- 1. thenvoi_send_event("Received contact request from Alice. Approving.", message_type="thought")
495
- 2. thenvoi_respond_contact_request(action="approve", request_id="abc-123")
496
- 3. thenvoi_send_event("Approved contact request from Alice (@alice)", message_type="thought")
558
+ 1. band_send_event("Received contact request from Alice. Approving.", message_type="thought")
559
+ 2. band_respond_contact_request(action="approve", request_id="abc-123")
560
+ 3. band_send_event("Approved contact request from Alice (@alice)", message_type="thought")
497
561
 
498
562
  ## Contact Tools (use these, NOT participant tools)
499
- - \`thenvoi_respond_contact_request(action, request_id)\` - Approve/reject requests
500
- - \`thenvoi_list_contact_requests()\` - List pending requests
501
- - \`thenvoi_list_contacts()\` - List current contacts`;
563
+ - \`band_respond_contact_request(action, request_id)\` - Approve/reject requests
564
+ - \`band_list_contact_requests()\` - List pending requests
565
+ - \`band_list_contacts()\` - List current contacts`;
502
566
  var ContactEventHandlerError = class extends Error {
503
567
  retryable;
504
568
  stage;
@@ -1118,6 +1182,9 @@ var Execution = class {
1118
1182
  }
1119
1183
  };
1120
1184
 
1185
+ // src/runtime/tools/AgentTools.ts
1186
+ var import_band_sdk_core = require("@band-ai/band-sdk-core");
1187
+
1121
1188
  // src/contracts/capabilities.ts
1122
1189
  var CAPABILITY_LABELS = {
1123
1190
  peers: "Peer lookup",
@@ -1234,9 +1301,9 @@ var MEMORY_STATUSES = [
1234
1301
  "active",
1235
1302
  // Normal, visible memories
1236
1303
  "superseded",
1237
- // Outdated; soft-deleted via thenvoi_supersede_memory
1304
+ // Outdated; soft-deleted via band_supersede_memory
1238
1305
  "archived",
1239
- // Hidden but preserved via thenvoi_archive_memory
1306
+ // Hidden but preserved via band_archive_memory
1240
1307
  "all"
1241
1308
  // Any status (no filter)
1242
1309
  ];
@@ -1277,7 +1344,7 @@ function memoryTypeForSystemError(system) {
1277
1344
 
1278
1345
  // src/runtime/tools/schemas.ts
1279
1346
  var TOOL_MODELS = {
1280
- thenvoi_send_message: {
1347
+ band_send_message: {
1281
1348
  description: "Send a message to the chat room. Use this to respond to users or other agents. Messages require at least one @mention in the mentions array. You MUST use this tool to communicate \u2014 plain text responses won't reach users. When delegating, send the full task context in this message instead of assuming hidden state.",
1282
1349
  properties: {
1283
1350
  content: {
@@ -1293,7 +1360,7 @@ var TOOL_MODELS = {
1293
1360
  },
1294
1361
  required: ["content", "mentions"]
1295
1362
  },
1296
- thenvoi_send_event: {
1363
+ band_send_event: {
1297
1364
  description: "Send an event to the chat room. No mentions required. 'thought': Share your reasoning or plan BEFORE taking actions. Explain what you're about to do and why. 'error': Report an error or problem that occurred. 'task': Report task progress or completion status. Always send a thought before complex actions to keep users informed.",
1298
1365
  properties: {
1299
1366
  content: {
@@ -1312,12 +1379,12 @@ var TOOL_MODELS = {
1312
1379
  },
1313
1380
  required: ["content", "message_type"]
1314
1381
  },
1315
- thenvoi_add_participant: {
1316
- description: "Add a participant (agent or user) to the chat room by name. IMPORTANT: Use thenvoi_lookup_peers() first to find available agents. Pass the exact peer name from thenvoi_lookup_peers, not the handle. For normal delegation, omit role or use 'member'.",
1382
+ band_add_participant: {
1383
+ description: "Add a participant (agent or user) to the chat room by name. IMPORTANT: Use band_lookup_peers() first to find available agents. Pass the exact peer name from band_lookup_peers, not the handle. For normal delegation, omit role or use 'member'.",
1317
1384
  properties: {
1318
1385
  name: {
1319
1386
  type: "string",
1320
- description: "Name of participant to add (must match a name from thenvoi_lookup_peers)."
1387
+ description: "Name of participant to add (must match a name from band_lookup_peers)."
1321
1388
  },
1322
1389
  role: {
1323
1390
  type: "string",
@@ -1327,7 +1394,7 @@ var TOOL_MODELS = {
1327
1394
  },
1328
1395
  required: ["name"]
1329
1396
  },
1330
- thenvoi_remove_participant: {
1397
+ band_remove_participant: {
1331
1398
  description: "Remove a participant from the chat room by name.",
1332
1399
  properties: {
1333
1400
  name: {
@@ -1337,12 +1404,12 @@ var TOOL_MODELS = {
1337
1404
  },
1338
1405
  required: ["name"]
1339
1406
  },
1340
- thenvoi_get_participants: {
1407
+ band_get_participants: {
1341
1408
  description: "Get a list of all participants in the current chat room.",
1342
1409
  properties: {},
1343
1410
  required: []
1344
1411
  },
1345
- thenvoi_lookup_peers: {
1412
+ band_lookup_peers: {
1346
1413
  description: "List available peers (agents and users) that can be added to this room. Automatically excludes peers already in the room. Returns dict with 'peers' list and 'metadata' (page, page_size, total_count, total_pages). Use this to find specialized agents (e.g., Weather Agent) when you cannot answer a question directly.",
1347
1414
  properties: {
1348
1415
  page: {
@@ -1357,7 +1424,7 @@ var TOOL_MODELS = {
1357
1424
  },
1358
1425
  required: []
1359
1426
  },
1360
- thenvoi_create_chatroom: {
1427
+ band_create_chatroom: {
1361
1428
  description: "Create a new chat room for a specific task or conversation.",
1362
1429
  properties: {
1363
1430
  task_id: {
@@ -1367,7 +1434,7 @@ var TOOL_MODELS = {
1367
1434
  },
1368
1435
  required: []
1369
1436
  },
1370
- thenvoi_list_contacts: {
1437
+ band_list_contacts: {
1371
1438
  description: "List agent's contacts with pagination.",
1372
1439
  properties: {
1373
1440
  page: {
@@ -1384,7 +1451,7 @@ var TOOL_MODELS = {
1384
1451
  },
1385
1452
  required: []
1386
1453
  },
1387
- thenvoi_add_contact: {
1454
+ band_add_contact: {
1388
1455
  description: "Send a contact request to add someone as a contact. Returns 'pending' when request is created. Returns 'approved' when inverse request existed and was auto-accepted.",
1389
1456
  properties: {
1390
1457
  handle: {
@@ -1398,7 +1465,7 @@ var TOOL_MODELS = {
1398
1465
  },
1399
1466
  required: ["handle"]
1400
1467
  },
1401
- thenvoi_remove_contact: {
1468
+ band_remove_contact: {
1402
1469
  description: "Remove an existing contact by handle or ID.",
1403
1470
  properties: {
1404
1471
  handle: {
@@ -1412,7 +1479,7 @@ var TOOL_MODELS = {
1412
1479
  },
1413
1480
  required: []
1414
1481
  },
1415
- thenvoi_list_contact_requests: {
1482
+ band_list_contact_requests: {
1416
1483
  description: "List both received and sent contact requests. Received requests are always filtered to pending status. Sent requests can be filtered by status.",
1417
1484
  properties: {
1418
1485
  page: {
@@ -1434,7 +1501,7 @@ var TOOL_MODELS = {
1434
1501
  },
1435
1502
  required: []
1436
1503
  },
1437
- thenvoi_respond_contact_request: {
1504
+ band_respond_contact_request: {
1438
1505
  description: "Respond to a contact request. 'approve'/'reject': For requests you RECEIVED (handle = requester's handle). 'cancel': For requests you SENT (handle = recipient's handle).",
1439
1506
  properties: {
1440
1507
  action: {
@@ -1453,7 +1520,7 @@ var TOOL_MODELS = {
1453
1520
  },
1454
1521
  required: ["action"]
1455
1522
  },
1456
- thenvoi_list_memories: {
1523
+ band_list_memories: {
1457
1524
  description: "List memories accessible to the agent. Returns memories about the specified subject (cross-agent sharing) and organization-wide shared memories.",
1458
1525
  properties: {
1459
1526
  subject_id: {
@@ -1498,7 +1565,7 @@ var TOOL_MODELS = {
1498
1565
  },
1499
1566
  required: []
1500
1567
  },
1501
- thenvoi_store_memory: {
1568
+ band_store_memory: {
1502
1569
  description: "Store a new memory entry. The memory will be associated with the authenticated agent as the source. For subject-scoped memories, provide a subject_id. For organization-scoped memories, omit subject_id.",
1503
1570
  properties: {
1504
1571
  content: {
@@ -1540,7 +1607,7 @@ var TOOL_MODELS = {
1540
1607
  },
1541
1608
  required: ["content", "system", "type", "segment", "thought"]
1542
1609
  },
1543
- thenvoi_get_memory: {
1610
+ band_get_memory: {
1544
1611
  description: "Retrieve a specific memory by ID.",
1545
1612
  properties: {
1546
1613
  memory_id: {
@@ -1550,7 +1617,7 @@ var TOOL_MODELS = {
1550
1617
  },
1551
1618
  required: ["memory_id"]
1552
1619
  },
1553
- thenvoi_supersede_memory: {
1620
+ band_supersede_memory: {
1554
1621
  description: "Mark a memory as superseded (soft delete). Use when information is outdated or incorrect. The memory remains for audit trail but won't appear in normal queries. Only the source agent can supersede.",
1555
1622
  properties: {
1556
1623
  memory_id: {
@@ -1560,7 +1627,7 @@ var TOOL_MODELS = {
1560
1627
  },
1561
1628
  required: ["memory_id"]
1562
1629
  },
1563
- thenvoi_archive_memory: {
1630
+ band_archive_memory: {
1564
1631
  description: "Archive a memory (hide but preserve). Use when memory is valid but not currently needed. Archived memories can be restored later by humans. Only the source agent can archive.",
1565
1632
  properties: {
1566
1633
  memory_id: {
@@ -1573,18 +1640,18 @@ var TOOL_MODELS = {
1573
1640
  };
1574
1641
  var ALL_TOOL_NAMES = new Set(Object.keys(TOOL_MODELS));
1575
1642
  var MEMORY_TOOL_NAMES = /* @__PURE__ */ new Set([
1576
- "thenvoi_list_memories",
1577
- "thenvoi_store_memory",
1578
- "thenvoi_get_memory",
1579
- "thenvoi_supersede_memory",
1580
- "thenvoi_archive_memory"
1643
+ "band_list_memories",
1644
+ "band_store_memory",
1645
+ "band_get_memory",
1646
+ "band_supersede_memory",
1647
+ "band_archive_memory"
1581
1648
  ]);
1582
1649
  var CONTACT_TOOL_NAMES = /* @__PURE__ */ new Set([
1583
- "thenvoi_list_contacts",
1584
- "thenvoi_add_contact",
1585
- "thenvoi_remove_contact",
1586
- "thenvoi_list_contact_requests",
1587
- "thenvoi_respond_contact_request"
1650
+ "band_list_contacts",
1651
+ "band_add_contact",
1652
+ "band_remove_contact",
1653
+ "band_list_contact_requests",
1654
+ "band_respond_contact_request"
1588
1655
  ]);
1589
1656
  var BASE_TOOL_NAMES = new Set(
1590
1657
  [...ALL_TOOL_NAMES].filter((name) => !MEMORY_TOOL_NAMES.has(name))
@@ -1592,7 +1659,8 @@ var BASE_TOOL_NAMES = new Set(
1592
1659
  var CHAT_TOOL_NAMES = new Set(
1593
1660
  [...BASE_TOOL_NAMES].filter((name) => !CONTACT_TOOL_NAMES.has(name))
1594
1661
  );
1595
- var MCP_TOOL_PREFIX = "mcp__thenvoi__";
1662
+ var MCP_TOOL_PREFIX = "mcp__band__";
1663
+ var MCP_SERVER_NAME = "band";
1596
1664
  function mcpToolNames(names) {
1597
1665
  return [...names].sort((a, b) => a.localeCompare(b)).map((name) => `${MCP_TOOL_PREFIX}${name}`);
1598
1666
  }
@@ -1640,13 +1708,13 @@ var AgentTools = class {
1640
1708
  roomId;
1641
1709
  capabilities;
1642
1710
  rest;
1643
- participants;
1711
+ roster;
1644
1712
  adapterTools;
1645
1713
  toolHandlers;
1646
1714
  constructor(options) {
1647
1715
  this.roomId = options.roomId;
1648
1716
  this.rest = options.rest;
1649
- this.participants = options.participants ?? [];
1717
+ this.roster = options.roster ?? new import_band_sdk_core.ParticipantRoster();
1650
1718
  this.capabilities = {
1651
1719
  ...DEFAULT_AGENT_TOOLS_CAPABILITIES,
1652
1720
  ...options.capabilities
@@ -1658,17 +1726,20 @@ var AgentTools = class {
1658
1726
  return this.adapterTools;
1659
1727
  }
1660
1728
  async sendMessage(content, mentions = []) {
1661
- if (mentions.length > 0 && typeof mentions[0] === "string" && this.participants.length === 0) {
1662
- await this.syncParticipants();
1729
+ let participants;
1730
+ if (mentions.length > 0 && typeof mentions[0] === "string") {
1731
+ participants = this.roster.list();
1732
+ if (participants.length === 0) {
1733
+ participants = await this.syncParticipants();
1734
+ }
1663
1735
  }
1664
- const resolvedMentions = this.resolveMentions(mentions);
1736
+ const resolvedMentions = this.resolveMentions(mentions, participants);
1665
1737
  return this.rest.createChatMessage(
1666
1738
  this.roomId,
1667
1739
  {
1668
1740
  content,
1669
1741
  mentions: resolvedMentions
1670
- },
1671
- DEFAULT_REQUEST_OPTIONS
1742
+ }
1672
1743
  );
1673
1744
  }
1674
1745
  async sendEvent(content, messageType, metadata) {
@@ -1679,8 +1750,7 @@ var AgentTools = class {
1679
1750
  content,
1680
1751
  messageType,
1681
1752
  metadata
1682
- },
1683
- DEFAULT_REQUEST_OPTIONS
1753
+ }
1684
1754
  );
1685
1755
  }
1686
1756
  async createChatroom(taskId) {
@@ -1719,7 +1789,7 @@ var AgentTools = class {
1719
1789
  type: String(peer.type ?? "Agent"),
1720
1790
  handle: typeof peer.handle === "string" ? peer.handle : null
1721
1791
  };
1722
- this.participants.push(participantRecord);
1792
+ this.roster.add(participantRecord);
1723
1793
  return {
1724
1794
  ...participantRecord,
1725
1795
  status: "added"
@@ -1734,7 +1804,7 @@ var AgentTools = class {
1734
1804
  throw new ValidationError(`Participant '${name}' not found in room`);
1735
1805
  }
1736
1806
  await this.rest.removeChatParticipant(this.roomId, String(participant.id), DEFAULT_REQUEST_OPTIONS);
1737
- this.replaceParticipants(this.participants.filter((entry) => entry.id !== participant.id));
1807
+ this.roster.remove(participant.id);
1738
1808
  return {
1739
1809
  id: participant.id,
1740
1810
  name,
@@ -1762,17 +1832,12 @@ var AgentTools = class {
1762
1832
  }
1763
1833
  async fetchParticipants() {
1764
1834
  const participants = await this.rest.listChatParticipants(this.roomId, DEFAULT_REQUEST_OPTIONS);
1765
- return participants.map((participant) => ({
1766
- id: participant.id,
1767
- name: participant.name,
1768
- type: participant.type,
1769
- handle: participant.handle ?? null
1770
- }));
1835
+ return participants.map(toParticipantRecordFromRest);
1771
1836
  }
1772
1837
  async syncParticipants() {
1773
1838
  const participants = await this.fetchParticipants();
1774
- this.replaceParticipants(participants);
1775
- return [...this.participants];
1839
+ this.roster.setAll(participants);
1840
+ return this.roster.list().map(toParticipantRecord);
1776
1841
  }
1777
1842
  async executeToolCall(toolName, arguments_) {
1778
1843
  const validationError = validateToolArgs(toolName, arguments_);
@@ -1820,7 +1885,7 @@ var AgentTools = class {
1820
1885
  if (!CHAT_TOOL_NAMES.has(name) && !this.capabilities.contacts) {
1821
1886
  return false;
1822
1887
  }
1823
- if (name === "thenvoi_lookup_peers" && !this.capabilities.peers) {
1888
+ if (name === "band_lookup_peers" && !this.capabilities.peers) {
1824
1889
  return false;
1825
1890
  }
1826
1891
  return true;
@@ -2015,7 +2080,7 @@ var AgentTools = class {
2015
2080
  }
2016
2081
  return this.rest.archiveMemory(normalizedMemoryId, DEFAULT_REQUEST_OPTIONS);
2017
2082
  }
2018
- resolveMentions(mentions) {
2083
+ resolveMentions(mentions, participants) {
2019
2084
  if (mentions.length === 0) {
2020
2085
  return [];
2021
2086
  }
@@ -2028,7 +2093,7 @@ var AgentTools = class {
2028
2093
  const participantsByHandle = /* @__PURE__ */ new Map();
2029
2094
  const participantsById = /* @__PURE__ */ new Map();
2030
2095
  const participantsByName = /* @__PURE__ */ new Map();
2031
- for (const participant of this.participants) {
2096
+ for (const participant of participants ?? []) {
2032
2097
  const ref = {
2033
2098
  id: String(participant.id),
2034
2099
  handle: typeof participant.handle === "string" ? participant.handle : void 0
@@ -2084,9 +2149,6 @@ var AgentTools = class {
2084
2149
  normalizeMentionHandle(handle) {
2085
2150
  return handle.trim().replace(/^@+/, "").toLowerCase();
2086
2151
  }
2087
- replaceParticipants(participants) {
2088
- this.participants.splice(0, this.participants.length, ...participants);
2089
- }
2090
2152
  buildAdapterTools() {
2091
2153
  const tools = {
2092
2154
  capabilities: this.capabilities
@@ -2117,51 +2179,51 @@ var AgentTools = class {
2117
2179
  }
2118
2180
  buildMessagingToolHandlers() {
2119
2181
  return {
2120
- thenvoi_send_message: async (arguments_) => this.sendMessage(
2182
+ band_send_message: async (arguments_) => this.sendMessage(
2121
2183
  String(arguments_.content ?? ""),
2122
2184
  this.normalizeMentionInput(arguments_.mentions)
2123
2185
  ),
2124
- thenvoi_send_event: async (arguments_) => this.sendEvent(
2186
+ band_send_event: async (arguments_) => this.sendEvent(
2125
2187
  String(arguments_.content ?? ""),
2126
2188
  String(arguments_.message_type ?? "task"),
2127
2189
  this.normalizeOptionalMetadata(arguments_.metadata)
2128
2190
  ),
2129
- thenvoi_add_participant: async (arguments_) => this.addParticipant(String(arguments_.name ?? ""), String(arguments_.role ?? "member")),
2130
- thenvoi_remove_participant: async (arguments_) => this.removeParticipant(String(arguments_.name ?? "")),
2131
- thenvoi_lookup_peers: async (arguments_) => this.lookupPeers(
2191
+ band_add_participant: async (arguments_) => this.addParticipant(String(arguments_.name ?? ""), String(arguments_.role ?? "member")),
2192
+ band_remove_participant: async (arguments_) => this.removeParticipant(String(arguments_.name ?? "")),
2193
+ band_lookup_peers: async (arguments_) => this.lookupPeers(
2132
2194
  coercePositiveInt(arguments_.page, 1),
2133
2195
  coercePositiveInt(arguments_.page_size, 50)
2134
2196
  ),
2135
- thenvoi_get_participants: async () => this.getParticipants(),
2136
- thenvoi_create_chatroom: async (arguments_) => this.createChatroom(this.normalizeOptionalString(arguments_.task_id))
2197
+ band_get_participants: async () => this.getParticipants(),
2198
+ band_create_chatroom: async (arguments_) => this.createChatroom(this.normalizeOptionalString(arguments_.task_id))
2137
2199
  };
2138
2200
  }
2139
2201
  buildContactToolHandlers() {
2140
2202
  return {
2141
- thenvoi_list_contacts: async (arguments_) => this.listContacts({
2203
+ band_list_contacts: async (arguments_) => this.listContacts({
2142
2204
  page: coercePositiveInt(arguments_.page, 1),
2143
2205
  pageSize: coercePositiveInt(arguments_.page_size, 50)
2144
2206
  }),
2145
- thenvoi_add_contact: async (arguments_) => this.addContact({
2207
+ band_add_contact: async (arguments_) => this.addContact({
2146
2208
  handle: String(arguments_.handle ?? ""),
2147
2209
  ...typeof arguments_.message === "string" ? { message: arguments_.message } : {}
2148
2210
  }),
2149
- thenvoi_remove_contact: async (arguments_) => this.removeContact(this.toRemoveContactArgs(arguments_)),
2150
- thenvoi_list_contact_requests: async (arguments_) => this.listContactRequests({
2211
+ band_remove_contact: async (arguments_) => this.removeContact(this.toRemoveContactArgs(arguments_)),
2212
+ band_list_contact_requests: async (arguments_) => this.listContactRequests({
2151
2213
  page: coercePositiveInt(arguments_.page, 1),
2152
2214
  pageSize: coercePositiveInt(arguments_.page_size, 50),
2153
2215
  sentStatus: String(arguments_.sent_status ?? "pending")
2154
2216
  }),
2155
- thenvoi_respond_contact_request: async (arguments_) => this.respondContactRequest(this.toRespondContactRequestArgs(arguments_))
2217
+ band_respond_contact_request: async (arguments_) => this.respondContactRequest(this.toRespondContactRequestArgs(arguments_))
2156
2218
  };
2157
2219
  }
2158
2220
  buildMemoryToolHandlers() {
2159
2221
  return {
2160
- thenvoi_list_memories: async (arguments_) => this.listMemories(this.toListMemoriesArgs(arguments_)),
2161
- thenvoi_store_memory: async (arguments_) => this.storeMemory(this.toStoreMemoryArgs(arguments_)),
2162
- thenvoi_get_memory: async (arguments_) => this.getMemory(String(arguments_.memory_id ?? "")),
2163
- thenvoi_supersede_memory: async (arguments_) => this.supersedeMemory(String(arguments_.memory_id ?? "")),
2164
- thenvoi_archive_memory: async (arguments_) => this.archiveMemory(String(arguments_.memory_id ?? ""))
2222
+ band_list_memories: async (arguments_) => this.listMemories(this.toListMemoriesArgs(arguments_)),
2223
+ band_store_memory: async (arguments_) => this.storeMemory(this.toStoreMemoryArgs(arguments_)),
2224
+ band_get_memory: async (arguments_) => this.getMemory(String(arguments_.memory_id ?? "")),
2225
+ band_supersede_memory: async (arguments_) => this.supersedeMemory(String(arguments_.memory_id ?? "")),
2226
+ band_archive_memory: async (arguments_) => this.archiveMemory(String(arguments_.memory_id ?? ""))
2165
2227
  };
2166
2228
  }
2167
2229
  toRemoveContactArgs(arguments_) {
@@ -2405,13 +2467,13 @@ function validateToolArgs(toolName, args) {
2405
2467
  errors.push(`${field}: Field required`);
2406
2468
  }
2407
2469
  }
2408
- if (toolName === "thenvoi_send_message") {
2470
+ if (toolName === "band_send_message") {
2409
2471
  const mentions = args.mentions;
2410
2472
  if (Array.isArray(mentions) && mentions.length === 0) {
2411
2473
  errors.push("mentions: At least one mention is required");
2412
2474
  }
2413
2475
  }
2414
- if (toolName === "thenvoi_send_event") {
2476
+ if (toolName === "band_send_event") {
2415
2477
  const messageType = args.message_type;
2416
2478
  if (typeof messageType === "string" && !CHAT_EVENT_TYPES.includes(messageType)) {
2417
2479
  errors.push(
@@ -2419,7 +2481,7 @@ function validateToolArgs(toolName, args) {
2419
2481
  );
2420
2482
  }
2421
2483
  }
2422
- if (toolName === "thenvoi_respond_contact_request") {
2484
+ if (toolName === "band_respond_contact_request") {
2423
2485
  const action = args.action;
2424
2486
  const validActions = ["approve", "reject", "cancel"];
2425
2487
  if (typeof action === "string" && !validActions.includes(action)) {
@@ -2428,7 +2490,7 @@ function validateToolArgs(toolName, args) {
2428
2490
  );
2429
2491
  }
2430
2492
  }
2431
- if (toolName === "thenvoi_store_memory") {
2493
+ if (toolName === "band_store_memory") {
2432
2494
  if (typeof args.system === "string" && !isMemorySystem(args.system)) {
2433
2495
  errors.push(`system: Invalid value '${args.system}'. Expected one of: ${expectedList(MEMORY_SYSTEMS)}`);
2434
2496
  }
@@ -2457,114 +2519,8 @@ function validateToolArgs(toolName, args) {
2457
2519
  return null;
2458
2520
  }
2459
2521
 
2460
- // src/runtime/retryTracker.ts
2461
- var DEFAULT_MAX_TRACKED = 1e4;
2462
- var MessageRetryTracker = class {
2463
- maxRetriesValue;
2464
- maxTracked;
2465
- attempts = /* @__PURE__ */ new Map();
2466
- failed = /* @__PURE__ */ new Set();
2467
- constructor(maxRetries = 1, maxTracked = DEFAULT_MAX_TRACKED) {
2468
- this.maxRetriesValue = maxRetries;
2469
- this.maxTracked = maxTracked;
2470
- }
2471
- get maxRetries() {
2472
- return this.maxRetriesValue;
2473
- }
2474
- isPermanentlyFailed(messageId) {
2475
- return this.failed.has(messageId);
2476
- }
2477
- recordAttempt(messageId) {
2478
- const attempts = (this.attempts.get(messageId) ?? 0) + 1;
2479
- this.attempts.set(messageId, attempts);
2480
- const exceeded = attempts > this.maxRetriesValue;
2481
- if (exceeded) {
2482
- this.evictSetIfNeeded(this.failed);
2483
- this.failed.add(messageId);
2484
- }
2485
- this.evictMapIfNeeded(this.attempts);
2486
- return [attempts, exceeded];
2487
- }
2488
- markSuccess(messageId) {
2489
- this.attempts.delete(messageId);
2490
- }
2491
- markPermanentlyFailed(messageId) {
2492
- this.evictSetIfNeeded(this.failed);
2493
- this.failed.add(messageId);
2494
- }
2495
- evictMapIfNeeded(map) {
2496
- while (map.size >= this.maxTracked) {
2497
- const first = map.keys().next();
2498
- if (first.done) break;
2499
- map.delete(first.value);
2500
- }
2501
- }
2502
- evictSetIfNeeded(set) {
2503
- while (set.size >= this.maxTracked) {
2504
- const first = set.values().next();
2505
- if (first.done) break;
2506
- set.delete(first.value);
2507
- }
2508
- }
2509
- };
2510
-
2511
- // src/runtime/formatters.ts
2512
- function isMetadataMap(value) {
2513
- return value !== null && typeof value === "object" && !Array.isArray(value);
2514
- }
2515
- function replaceUuidMentions(content, participants) {
2516
- if (!content || participants.length === 0) {
2517
- return content;
2518
- }
2519
- let next = content;
2520
- for (const participant of participants) {
2521
- const participantId = participant.id;
2522
- const handle = participant.handle;
2523
- if (typeof participantId === "string" && typeof handle === "string") {
2524
- next = next.replaceAll(`@[[${participantId}]]`, ensureHandlePrefix(handle) ?? "");
2525
- }
2526
- }
2527
- return next;
2528
- }
2529
- function formatMessageForLlm(message, participants) {
2530
- const senderType = String(message.sender_type ?? "");
2531
- const senderName = String(message.sender_name ?? message.name ?? senderType);
2532
- const content = participants ? replaceUuidMentions(String(message.content ?? ""), participants) : String(message.content ?? "");
2533
- return {
2534
- role: senderType === "Agent" ? "assistant" : "user",
2535
- content,
2536
- sender_name: senderName,
2537
- sender_type: senderType,
2538
- message_type: String(message.message_type ?? "text"),
2539
- metadata: isMetadataMap(message.metadata) ? message.metadata : {}
2540
- };
2541
- }
2542
- function formatHistoryForLlm(messages, options) {
2543
- const excludeId = options?.excludeId;
2544
- const participants = options?.participants;
2545
- return messages.filter((message) => String(message.id ?? "") !== excludeId).map((message) => formatMessageForLlm(message, participants));
2546
- }
2547
- function buildParticipantsMessage(participants) {
2548
- if (participants.length === 0) {
2549
- return "## Current Participants\nNo other participants in this room.";
2550
- }
2551
- const lines = ["## Current Participants"];
2552
- for (const participant of participants) {
2553
- const participantType = String(participant.type ?? "Unknown");
2554
- const participantName = String(participant.name ?? "Unknown");
2555
- const participantHandle = String(participant.handle ?? "Unknown");
2556
- lines.push(
2557
- `- ${ensureHandlePrefix(participantHandle) ?? ""} \u2014 ${participantName} (${participantType})`
2558
- );
2559
- }
2560
- lines.push("");
2561
- lines.push(
2562
- "IMPORTANT: In thenvoi_send_message mentions, always use the exact handle shown above (e.g. '@john' for users, '@john/weather-agent' for agents), NOT the display name. Handles are lowercase with no spaces."
2563
- );
2564
- return lines.join("\n");
2565
- }
2566
-
2567
2522
  // src/runtime/ExecutionContext.ts
2523
+ var import_band_sdk_core2 = require("@band-ai/band-sdk-core");
2568
2524
  var DEDUP_CACHE_MAX = 500;
2569
2525
  var ExecutionContext = class {
2570
2526
  roomId;
@@ -2576,11 +2532,10 @@ var ExecutionContext = class {
2576
2532
  history = [];
2577
2533
  messageIds = /* @__PURE__ */ new Set();
2578
2534
  dedupCache = /* @__PURE__ */ new Map();
2579
- participants = [];
2535
+ roster = new import_band_sdk_core2.ParticipantRoster();
2580
2536
  tools;
2581
2537
  adapterTools;
2582
2538
  participantsMessage = null;
2583
- lastSentParticipantIds = null;
2584
2539
  contactsMessage = null;
2585
2540
  contextCache = null;
2586
2541
  contextCacheExpiresAt = 0;
@@ -2595,11 +2550,11 @@ var ExecutionContext = class {
2595
2550
  this.enableContextCache = options.enableContextCache ?? true;
2596
2551
  this.contextCacheTtlMs = Math.max(0, (options.contextCacheTtlSeconds ?? 300) * 1e3);
2597
2552
  this.enableContextHydration = options.enableContextHydration ?? true;
2598
- this.retryTrackerInstance = new MessageRetryTracker(options.maxMessageRetries ?? 1);
2553
+ this.retryTrackerInstance = new import_band_sdk_core2.RetryTracker(options.maxMessageRetries ?? 1);
2599
2554
  this.tools = new AgentTools({
2600
2555
  roomId: this.roomId,
2601
2556
  rest: this.link.rest,
2602
- participants: this.participants,
2557
+ roster: this.roster,
2603
2558
  capabilities: this.link.capabilities
2604
2559
  });
2605
2560
  this.adapterTools = this.tools.getAdapterTools();
@@ -2667,23 +2622,20 @@ var ExecutionContext = class {
2667
2622
  }));
2668
2623
  }
2669
2624
  setParticipants(participants) {
2670
- this.replaceParticipants(participants);
2625
+ this.roster.setAll(participants);
2671
2626
  this.updateCachedParticipants();
2672
2627
  }
2673
2628
  addParticipant(participant) {
2674
- const existingIndex = this.participants.findIndex((entry) => entry.id === participant.id);
2675
- if (existingIndex >= 0) {
2676
- this.participants.splice(existingIndex, 1);
2629
+ const isNew = this.roster.add(participant);
2630
+ if (isNew) {
2631
+ const name = String(participant.name ?? "unknown");
2632
+ this.participantsMessage = `${name} joined the room.`;
2677
2633
  }
2678
- this.participants.push(participant);
2679
- const name = String(participant.name ?? "unknown");
2680
- this.participantsMessage = `${name} joined the room.`;
2681
2634
  this.updateCachedParticipants();
2682
2635
  }
2683
2636
  removeParticipant(participantId) {
2684
- const removed = this.participants.find((entry) => String(entry.id) === participantId);
2685
- const next = this.participants.filter((entry) => String(entry.id) !== participantId);
2686
- this.replaceParticipants(next);
2637
+ const removed = this.roster.list().find((entry) => entry.id === participantId);
2638
+ this.roster.remove(participantId);
2687
2639
  if (removed) {
2688
2640
  this.participantsMessage = `${String(removed.name ?? participantId)} left the room.`;
2689
2641
  }
@@ -2693,16 +2645,7 @@ var ExecutionContext = class {
2693
2645
  this.contactsMessage = message;
2694
2646
  }
2695
2647
  consumeParticipantsMessage() {
2696
- const currentIds = new Set(this.participants.map((p) => String(p.id)));
2697
- let changed = !this.lastSentParticipantIds || currentIds.size !== this.lastSentParticipantIds.size;
2698
- if (!changed) {
2699
- for (const id of currentIds) {
2700
- if (!this.lastSentParticipantIds.has(id)) {
2701
- changed = true;
2702
- break;
2703
- }
2704
- }
2705
- }
2648
+ const changed = this.roster.changed();
2706
2649
  if (!changed && !this.participantsMessage) {
2707
2650
  return null;
2708
2651
  }
@@ -2712,15 +2655,9 @@ var ExecutionContext = class {
2712
2655
  this.participantsMessage = null;
2713
2656
  }
2714
2657
  if (changed) {
2715
- const asRecords = this.participants.map((p) => ({
2716
- id: p.id,
2717
- name: p.name,
2718
- type: p.type,
2719
- handle: p.handle ?? null
2720
- }));
2721
- parts.push(buildParticipantsMessage(asRecords));
2722
- }
2723
- this.lastSentParticipantIds = currentIds;
2658
+ parts.push(buildParticipantsMessage(this.roster.list().map((p) => ({ ...toParticipantRecord(p) }))));
2659
+ }
2660
+ this.roster.markSent();
2724
2661
  return parts.length > 0 ? parts.join("\n") : null;
2725
2662
  }
2726
2663
  consumeContactsMessage() {
@@ -2771,27 +2708,19 @@ var ExecutionContext = class {
2771
2708
  return fallback;
2772
2709
  }
2773
2710
  }
2774
- replaceParticipants(participants) {
2775
- this.participants.splice(0, this.participants.length, ...participants);
2776
- }
2777
2711
  buildLocalContext() {
2778
2712
  return {
2779
2713
  roomId: this.roomId,
2780
2714
  messages: this.getRawHistory(),
2781
- participants: [...this.participants],
2715
+ participants: this.roster.list().map(toParticipantRecord),
2782
2716
  hydratedAt: /* @__PURE__ */ new Date()
2783
2717
  };
2784
2718
  }
2785
2719
  async loadParticipants() {
2786
2720
  const participants = await this.link.rest.listChatParticipants(this.roomId, DEFAULT_REQUEST_OPTIONS);
2787
- const normalized = participants.map((participant) => ({
2788
- id: participant.id,
2789
- name: participant.name,
2790
- type: participant.type,
2791
- handle: participant.handle ?? null
2792
- }));
2793
- this.replaceParticipants(normalized);
2794
- return [...this.participants];
2721
+ const normalized = participants.map(toParticipantRecordFromRest);
2722
+ this.roster.setAll(normalized);
2723
+ return this.roster.list().map(toParticipantRecord);
2795
2724
  }
2796
2725
  async loadHydratedMessages() {
2797
2726
  const messages = [];
@@ -2833,7 +2762,7 @@ var ExecutionContext = class {
2833
2762
  if (!this.contextCache) {
2834
2763
  return;
2835
2764
  }
2836
- this.contextCache.participants = [...this.participants];
2765
+ this.contextCache.participants = this.roster.list().map(toParticipantRecord);
2837
2766
  this.contextCache.hydratedAt = /* @__PURE__ */ new Date();
2838
2767
  this.contextCacheExpiresAt = this.nextCacheExpiry();
2839
2768
  }
@@ -3545,54 +3474,16 @@ function normalizeContactRequestsResult(result) {
3545
3474
  }
3546
3475
 
3547
3476
  // src/client/rest/FernRestAdapter.ts
3548
- function mergeOptions(options) {
3477
+ function mergeOptions(options, maxRetries) {
3549
3478
  return {
3550
3479
  ...DEFAULT_REQUEST_OPTIONS,
3480
+ ...maxRetries !== void 0 ? { maxRetries } : {},
3551
3481
  ...options
3552
3482
  };
3553
3483
  }
3554
- var AGENT_ME_RETRY_LIMIT = 4;
3555
- var AGENT_ME_RETRY_BASE_DELAY_MS = 2e3;
3556
- var MESSAGE_SEND_RETRY_LIMIT = 3;
3557
- var MESSAGE_SEND_RETRY_BASE_DELAY_MS = 500;
3558
3484
  function asMetadataMap2(value) {
3559
3485
  return asOptionalRecord(value);
3560
3486
  }
3561
- function extractHttpStatus(error) {
3562
- const record = asOptionalRecord(error);
3563
- if (!record) {
3564
- return void 0;
3565
- }
3566
- const response = asOptionalRecord(record.response);
3567
- const status = record.statusCode ?? record.status ?? response?.statusCode ?? response?.status;
3568
- return typeof status === "number" ? status : void 0;
3569
- }
3570
- function isFernRateLimitError(error) {
3571
- return extractHttpStatus(error) === 429;
3572
- }
3573
- async function sleep(ms) {
3574
- await new Promise((resolveDelay) => setTimeout(resolveDelay, ms));
3575
- }
3576
- function computeRetryDelayMs(baseDelayMs, attempt) {
3577
- const backoff = baseDelayMs * 2 ** (attempt - 1);
3578
- const jitter = Math.floor(Math.random() * Math.max(1, Math.floor(backoff / 4)));
3579
- return backoff + jitter;
3580
- }
3581
- async function withRateLimitRetry(operation, options) {
3582
- let lastError;
3583
- for (let attempt = 1; attempt <= options.retryLimit; attempt += 1) {
3584
- try {
3585
- return await operation();
3586
- } catch (error) {
3587
- lastError = error;
3588
- if (!isFernRateLimitError(error) || attempt === options.retryLimit) {
3589
- throw error;
3590
- }
3591
- await sleep(computeRetryDelayMs(options.baseDelayMs, attempt));
3592
- }
3593
- }
3594
- throw lastError instanceof Error ? lastError : new Error("Rate-limit retry exhausted without a terminal error.");
3595
- }
3596
3487
  function requireNonEmptyStringField(value, field, source) {
3597
3488
  if (typeof value !== "string" || value.trim().length === 0) {
3598
3489
  throw new Error(`Invalid ${source} response: expected non-empty string AgentIdentity.${field}`);
@@ -3800,28 +3691,21 @@ var FernRestAdapter = class {
3800
3691
  this.client = client;
3801
3692
  }
3802
3693
  async getAgentMe(options) {
3803
- return withRateLimitRetry(
3804
- async () => {
3805
- if (this.client.agentApiIdentity?.getAgentMe) {
3806
- const response = await this.client.agentApiIdentity.getAgentMe(mergeOptions(options));
3807
- return normalizeAgentIdentityEnvelope(response, "agentApiIdentity.getAgentMe");
3808
- }
3809
- const profileClient = this.client.myProfile ?? this.client.humanApiProfile;
3810
- if (!profileClient?.getMyProfile) {
3811
- throw new UnsupportedFeatureError(
3812
- "Fern client missing agentApiIdentity.getAgentMe or humanApiProfile.getMyProfile"
3813
- );
3814
- }
3815
- const profile = await profileClient.getMyProfile(mergeOptions(options));
3816
- return normalizeLegacyProfileIdentity(
3817
- normalizeLegacyProfileEnvelope(profile),
3818
- "profile.getMyProfile"
3819
- );
3820
- },
3821
- {
3822
- retryLimit: AGENT_ME_RETRY_LIMIT,
3823
- baseDelayMs: AGENT_ME_RETRY_BASE_DELAY_MS
3824
- }
3694
+ const requestOptions = mergeOptions(options);
3695
+ if (this.client.agentApiIdentity?.getAgentMe) {
3696
+ const response = await this.client.agentApiIdentity.getAgentMe(requestOptions);
3697
+ return normalizeAgentIdentityEnvelope(response, "agentApiIdentity.getAgentMe");
3698
+ }
3699
+ const profileClient = this.client.myProfile ?? this.client.humanApiProfile;
3700
+ if (!profileClient?.getMyProfile) {
3701
+ throw new UnsupportedFeatureError(
3702
+ "Fern client missing agentApiIdentity.getAgentMe or humanApiProfile.getMyProfile"
3703
+ );
3704
+ }
3705
+ const profile = await profileClient.getMyProfile(requestOptions);
3706
+ return normalizeLegacyProfileIdentity(
3707
+ normalizeLegacyProfileEnvelope(profile),
3708
+ "profile.getMyProfile"
3825
3709
  );
3826
3710
  }
3827
3711
  async createChatMessage(chatId, message, options) {
@@ -3829,45 +3713,33 @@ var FernRestAdapter = class {
3829
3713
  if (!api) {
3830
3714
  throw new UnsupportedFeatureError("Fern client missing chat message creation endpoint");
3831
3715
  }
3832
- const response = await withRateLimitRetry(
3833
- async () => await api(
3834
- chatId,
3835
- {
3836
- message: {
3837
- content: message.content,
3838
- message_type: message.messageType,
3839
- metadata: message.metadata,
3840
- mentions: message.mentions
3841
- }
3842
- },
3843
- mergeOptions(options)
3844
- ),
3716
+ const response = await api(
3717
+ chatId,
3845
3718
  {
3846
- retryLimit: MESSAGE_SEND_RETRY_LIMIT,
3847
- baseDelayMs: MESSAGE_SEND_RETRY_BASE_DELAY_MS
3848
- }
3719
+ message: {
3720
+ content: message.content,
3721
+ message_type: message.messageType,
3722
+ metadata: message.metadata,
3723
+ mentions: message.mentions
3724
+ }
3725
+ },
3726
+ mergeOptions(options, MESSAGE_SEND_MAX_RETRIES)
3849
3727
  );
3850
3728
  return normalizeToolOperationResult(response);
3851
3729
  }
3852
3730
  async createChatEvent(chatId, event, options) {
3853
3731
  const createAgentChatEvent = this.client.agentApiEvents?.createAgentChatEvent?.bind(this.client.agentApiEvents);
3854
3732
  if (createAgentChatEvent) {
3855
- const response = await withRateLimitRetry(
3856
- async () => await createAgentChatEvent(
3857
- chatId,
3858
- {
3859
- event: {
3860
- content: event.content,
3861
- message_type: event.messageType,
3862
- metadata: event.metadata
3863
- }
3864
- },
3865
- mergeOptions(options)
3866
- ),
3733
+ const response = await createAgentChatEvent(
3734
+ chatId,
3867
3735
  {
3868
- retryLimit: MESSAGE_SEND_RETRY_LIMIT,
3869
- baseDelayMs: MESSAGE_SEND_RETRY_BASE_DELAY_MS
3870
- }
3736
+ event: {
3737
+ content: event.content,
3738
+ message_type: event.messageType,
3739
+ metadata: event.metadata
3740
+ }
3741
+ },
3742
+ mergeOptions(options, MESSAGE_SEND_MAX_RETRIES)
3871
3743
  );
3872
3744
  return normalizeToolOperationResult(response);
3873
3745
  }
@@ -4390,7 +4262,7 @@ function retryAfterFromHeaders(headers) {
4390
4262
  var import_ws = require("ws");
4391
4263
  function createNodeWebSocketFactory(headers) {
4392
4264
  const Constructor = import_ws.WebSocket;
4393
- class ThenvoiNodeWebSocket {
4265
+ class BandNodeWebSocket {
4394
4266
  constructor(address, protocols) {
4395
4267
  const socket = new Constructor(address, protocols, headers ? { headers } : void 0);
4396
4268
  socket.once("unexpected-response", (request, response) => {
@@ -4399,7 +4271,7 @@ function createNodeWebSocketFactory(headers) {
4399
4271
  return socket;
4400
4272
  }
4401
4273
  }
4402
- return ThenvoiNodeWebSocket;
4274
+ return BandNodeWebSocket;
4403
4275
  }
4404
4276
  async function emitUpgradeError(websocket, request, response) {
4405
4277
  const body = await readResponseBody(response);
@@ -4787,9 +4659,9 @@ function getSocketChannelCount(socket) {
4787
4659
  return candidate.channels.length;
4788
4660
  }
4789
4661
 
4790
- // src/platform/ThenvoiLink.ts
4791
- var import_rest_client = require("@thenvoi/rest-client");
4792
- var DEFAULT_WS_URL = "wss://app.thenvoi.com/api/v1/socket";
4662
+ // src/platform/BandLink.ts
4663
+ var import_rest_client = require("@band-ai/rest-client");
4664
+ var DEFAULT_WS_URL = "wss://app.band.ai/api/v1/socket";
4793
4665
  function deriveDefaultRestUrl(wsUrl) {
4794
4666
  const parsed = new URL(wsUrl);
4795
4667
  const protocol = parsed.protocol === "ws:" ? "http:" : "https:";
@@ -4814,7 +4686,7 @@ function toPlatformMessage(roomId, message) {
4814
4686
  createdAt: new Date(message.inserted_at)
4815
4687
  };
4816
4688
  }
4817
- var ThenvoiLink = class {
4689
+ var BandLink = class {
4818
4690
  agentId;
4819
4691
  apiKey;
4820
4692
  wsUrl;
@@ -4840,7 +4712,7 @@ var ThenvoiLink = class {
4840
4712
  ...options.capabilities
4841
4713
  };
4842
4714
  const restApi = options.restApi ?? new FernRestAdapter(
4843
- new import_rest_client.ThenvoiClient({
4715
+ new import_rest_client.BandClient({
4844
4716
  apiKey: this.apiKey,
4845
4717
  baseUrl: this.restUrl
4846
4718
  })
@@ -5213,6 +5085,8 @@ var DefaultPreprocessor = class {
5213
5085
  };
5214
5086
 
5215
5087
  // src/runtime/PlatformRuntime.ts
5088
+ var MAX_MESSAGE_RETRIES = 4294967295;
5089
+ var isValidRetryCount = (value) => Number.isInteger(value) && value >= 0 && value <= MAX_MESSAGE_RETRIES;
5216
5090
  var PlatformRuntime = class {
5217
5091
  _agentId;
5218
5092
  _apiKey;
@@ -5249,6 +5123,12 @@ var PlatformRuntime = class {
5249
5123
  "apiKey is required and must be a non-empty string. Use loadAgentConfig() to load credentials from agent_config.yaml."
5250
5124
  );
5251
5125
  }
5126
+ const maxMessageRetries = options.sessionConfig?.maxMessageRetries;
5127
+ if (maxMessageRetries !== void 0 && !isValidRetryCount(maxMessageRetries)) {
5128
+ throw new ValidationError(
5129
+ `sessionConfig.maxMessageRetries must be an integer between 0 and ${MAX_MESSAGE_RETRIES}, got ${maxMessageRetries}.`
5130
+ );
5131
+ }
5252
5132
  this._agentId = options.agentId;
5253
5133
  this._apiKey = options.apiKey;
5254
5134
  this._wsUrl = options.wsUrl;
@@ -5301,7 +5181,7 @@ var PlatformRuntime = class {
5301
5181
  }
5302
5182
  async doInitialize() {
5303
5183
  if (!this.linkInstance) {
5304
- this.linkInstance = new ThenvoiLink({
5184
+ this.linkInstance = new BandLink({
5305
5185
  ...this.linkOptions,
5306
5186
  agentId: this._agentId,
5307
5187
  apiKey: this._apiKey,
@@ -5584,25 +5464,28 @@ var RoomPresence = class {
5584
5464
  }
5585
5465
  };
5586
5466
 
5467
+ // src/runtime/index.ts
5468
+ var import_band_sdk_core3 = require("@band-ai/band-sdk-core");
5469
+
5587
5470
  // src/runtime/prompts/base.ts
5588
5471
  var ENVIRONMENT_SECTION = `
5589
5472
  ## Environment
5590
5473
 
5591
5474
  Multi-participant chat. Messages show sender: [Name]: content.
5592
5475
  Messages prefixed with [System]: are platform updates (participant changes, contact updates, etc.) \u2014 not messages from users.
5593
- Use \`thenvoi_send_message(content, mentions)\` to respond. Plain text output is not delivered.
5476
+ Use \`band_send_message(content, mentions)\` to respond. Plain text output is not delivered.
5594
5477
  Mentions use handles: @<username> for users, @<username>/<agent-name> for agents.`;
5595
5478
  var MULTI_AGENT_RULES_SECTION = `## CRITICAL: Delegate When You Cannot Help Directly
5596
5479
 
5597
5480
  You have NO internet access and NO real-time data. When asked about weather, news, stock prices,
5598
5481
  or any current information you cannot answer directly:
5599
5482
 
5600
- 1. Call \`thenvoi_lookup_peers()\` to find available specialized agents
5601
- 2. If a relevant agent exists, call \`thenvoi_add_participant(name)\` to add them
5602
- 3. Ask that agent using \`thenvoi_send_message(question, mentions=[agent_handle])\`
5483
+ 1. Call \`band_lookup_peers()\` to find available specialized agents
5484
+ 2. If a relevant agent exists, call \`band_add_participant(name)\` to add them
5485
+ 3. Ask that agent using \`band_send_message(question, mentions=[agent_handle])\`
5603
5486
  4. Wait for their response and relay it back to the user
5604
5487
 
5605
- NEVER say "I can't do that" without first checking if another agent can help via \`thenvoi_lookup_peers()\`.
5488
+ NEVER say "I can't do that" without first checking if another agent can help via \`band_lookup_peers()\`.
5606
5489
 
5607
5490
  ## CRITICAL: Do NOT Remove Agents Automatically
5608
5491
 
@@ -5621,42 +5504,42 @@ When someone asks you to get information from another agent:
5621
5504
  3. Do NOT just thank the helper agent - the requester is waiting for their answer!`;
5622
5505
  var THINKING_SECTION = `## IMPORTANT: Always Share Your Thinking
5623
5506
 
5624
- You MUST call \`thenvoi_send_event(content, message_type="thought")\` BEFORE every action.
5507
+ You MUST call \`band_send_event(content, message_type="thought")\` BEFORE every action.
5625
5508
  This is required so users can see your reasoning process.`;
5626
5509
  var EXAMPLES_SECTION = `## Examples
5627
5510
 
5628
5511
  ### Simple question - answer directly
5629
5512
  [John Doe]: What's 2+2?
5630
- -> thenvoi_send_event("Simple arithmetic, answering directly.", message_type="thought")
5631
- -> thenvoi_send_message("4", mentions=["@john"])
5513
+ -> band_send_event("Simple arithmetic, answering directly.", message_type="thought")
5514
+ -> band_send_message("4", mentions=["@john"])
5632
5515
 
5633
5516
  ### User asks about weather (you cannot answer directly)
5634
5517
  [John Doe]: What's the weather in Tokyo?
5635
- -> thenvoi_send_event("I can't check weather directly. Looking for a Weather Agent.", message_type="thought")
5636
- -> thenvoi_lookup_peers()
5637
- -> thenvoi_send_event("Found Weather Agent. Adding to room.", message_type="thought")
5638
- -> thenvoi_add_participant("Weather Agent")
5639
- -> thenvoi_send_message("What's the weather in Tokyo?", mentions=["@john/weather-agent"])
5518
+ -> band_send_event("I can't check weather directly. Looking for a Weather Agent.", message_type="thought")
5519
+ -> band_lookup_peers()
5520
+ -> band_send_event("Found Weather Agent. Adding to room.", message_type="thought")
5521
+ -> band_add_participant("Weather Agent")
5522
+ -> band_send_message("What's the weather in Tokyo?", mentions=["@john/weather-agent"])
5640
5523
 
5641
5524
  [Weather Agent]: Tokyo is 15\xB0C and cloudy.
5642
- -> thenvoi_send_event("Got weather response. Relaying back to John Doe.", message_type="thought")
5643
- -> thenvoi_send_message("The weather in Tokyo is 15\xB0C and cloudy.", mentions=["@john"])
5525
+ -> band_send_event("Got weather response. Relaying back to John Doe.", message_type="thought")
5526
+ -> band_send_message("The weather in Tokyo is 15\xB0C and cloudy.", mentions=["@john"])
5644
5527
 
5645
5528
  ### No suitable agent available
5646
5529
  [John Doe]: What's the stock price of AAPL?
5647
- -> thenvoi_send_event("I can't check stock prices. Looking for a Stock Agent.", message_type="thought")
5648
- -> thenvoi_lookup_peers()
5649
- -> thenvoi_send_event("No stock agent available. Must inform user.", message_type="thought")
5650
- -> thenvoi_send_message("I don't have access to stock prices, and there's no specialized agent available to help with that.", mentions=["@john"])
5530
+ -> band_send_event("I can't check stock prices. Looking for a Stock Agent.", message_type="thought")
5531
+ -> band_lookup_peers()
5532
+ -> band_send_event("No stock agent available. Must inform user.", message_type="thought")
5533
+ -> band_send_message("I don't have access to stock prices, and there's no specialized agent available to help with that.", mentions=["@john"])
5651
5534
 
5652
5535
  ### Follow-up question in same conversation
5653
5536
  [John Doe]: What about London?
5654
- -> thenvoi_send_event("Follow-up weather question. Asking Weather Agent.", message_type="thought")
5655
- -> thenvoi_send_message("What's the weather in London?", mentions=["@john/weather-agent"])
5537
+ -> band_send_event("Follow-up weather question. Asking Weather Agent.", message_type="thought")
5538
+ -> band_send_message("What's the weather in London?", mentions=["@john/weather-agent"])
5656
5539
 
5657
5540
  [Weather Agent]: London is 8\xB0C and rainy.
5658
- -> thenvoi_send_event("Got London weather. Relaying to John Doe.", message_type="thought")
5659
- -> thenvoi_send_message("London is 8\xB0C and rainy.", mentions=["@john"])`;
5541
+ -> band_send_event("Got London weather. Relaying to John Doe.", message_type="thought")
5542
+ -> band_send_message("London is 8\xB0C and rainy.", mentions=["@john"])`;
5660
5543
  var BASE_INSTRUCTIONS = [
5661
5544
  ENVIRONMENT_SECTION,
5662
5545
  MULTI_AGENT_RULES_SECTION,
@@ -5668,10 +5551,10 @@ var BASE_INSTRUCTIONS = [
5668
5551
  var MEMORY_INTRO = `## Memory Tools
5669
5552
 
5670
5553
  You have access to memory tools for storing and retrieving information
5671
- across conversations. Use \`thenvoi_store_memory\` to persist important
5672
- information and \`thenvoi_list_memories\` / \`thenvoi_get_memory\` to recall it.
5673
- Use \`thenvoi_supersede_memory\` to mark outdated memories and
5674
- \`thenvoi_archive_memory\` to hide memories that should be preserved.`;
5554
+ across conversations. Use \`band_store_memory\` to persist important
5555
+ information and \`band_list_memories\` / \`band_get_memory\` to recall it.
5556
+ Use \`band_supersede_memory\` to mark outdated memories and
5557
+ \`band_archive_memory\` to hide memories that should be preserved.`;
5675
5558
  function longTermPattern(label, type, segment, scope) {
5676
5559
  return {
5677
5560
  label,
@@ -5696,7 +5579,7 @@ var MEMORY_COMMON_PATTERNS = [
5696
5579
  ].join("\n");
5697
5580
  var MEMORY_SCOPE_GUIDANCE = `Prefer \`scope="${MEMORY_STORE_SCOPE.subject}"\` whenever the memory is about a specific person or agent, so it
5698
5581
  stays attached to that subject rather than leaking org-wide. Storing with \`scope="${MEMORY_STORE_SCOPE.subject}"\` requires a
5699
- real \`subject_id\` UUID, so resolve it first via \`thenvoi_lookup_peers\` or the participant list.
5582
+ real \`subject_id\` UUID, so resolve it first via \`band_lookup_peers\` or the participant list.
5700
5583
  Reserve \`scope="${MEMORY_STORE_SCOPE.organization}"\` for knowledge that is genuinely shared across the whole organization and
5701
5584
  is not about any one subject.`;
5702
5585
  function quoteChoices(values) {
@@ -5706,11 +5589,11 @@ function memoryTypeLines() {
5706
5589
  return Object.entries(MEMORY_SYSTEM_TYPES).map(([system, types]) => ` - ${system}: ${quoteChoices(types)}`).join("\n");
5707
5590
  }
5708
5591
  function buildMemorySection() {
5709
- const storeMemoryProps = TOOL_MODELS.thenvoi_store_memory.properties;
5592
+ const storeMemoryProps = TOOL_MODELS.band_store_memory.properties;
5710
5593
  const systems = storeMemoryProps.system.enum;
5711
5594
  const segments = storeMemoryProps.segment.enum;
5712
5595
  const scopes = storeMemoryProps.scope.enum;
5713
- const fieldRules = `When calling \`thenvoi_store_memory\`, the \`system\`, \`type\`, \`segment\`, and \`scope\` fields
5596
+ const fieldRules = `When calling \`band_store_memory\`, the \`system\`, \`type\`, \`segment\`, and \`scope\` fields
5714
5597
  must use these exact values (case-sensitive):
5715
5598
 
5716
5599
  - **system**: ${quoteChoices(systems)}
@@ -5750,61 +5633,6 @@ ${customSection}`.trim();
5750
5633
  return parts.join("\n\n");
5751
5634
  }
5752
5635
 
5753
- // src/runtime/participantTracker.ts
5754
- var ParticipantTracker = class {
5755
- participantsList = [];
5756
- lastSent = null;
5757
- loaded = false;
5758
- get participants() {
5759
- return [...this.participantsList];
5760
- }
5761
- get isLoaded() {
5762
- return this.loaded;
5763
- }
5764
- setLoaded(participants) {
5765
- this.participantsList = participants.map((participant) => ({ ...participant }));
5766
- this.loaded = true;
5767
- }
5768
- add(participant) {
5769
- if (this.participantsList.some((entry) => entry.id === participant.id)) {
5770
- return false;
5771
- }
5772
- this.participantsList.push({
5773
- id: participant.id,
5774
- name: participant.name,
5775
- type: participant.type,
5776
- handle: participant.handle
5777
- });
5778
- return true;
5779
- }
5780
- remove(participantId) {
5781
- const before = this.participantsList.length;
5782
- this.participantsList = this.participantsList.filter(
5783
- (participant) => participant.id !== participantId
5784
- );
5785
- return this.participantsList.length < before;
5786
- }
5787
- changed() {
5788
- if (!this.lastSent) {
5789
- return true;
5790
- }
5791
- const oldIds = new Set(this.lastSent.map((participant) => participant.id));
5792
- const newIds = new Set(this.participantsList.map((participant) => participant.id));
5793
- if (oldIds.size !== newIds.size) {
5794
- return true;
5795
- }
5796
- for (const id of oldIds) {
5797
- if (!newIds.has(id)) {
5798
- return true;
5799
- }
5800
- }
5801
- return false;
5802
- }
5803
- markSent() {
5804
- this.lastSent = this.participantsList.map((participant) => ({ ...participant }));
5805
- }
5806
- };
5807
-
5808
5636
  // src/runtime/shutdown.ts
5809
5637
  var DEFAULT_SHUTDOWN_TIMEOUT_MS = 3e4;
5810
5638
  var GracefulShutdown = class {
@@ -5883,12 +5711,13 @@ async function runWithGracefulShutdown(agent, options) {
5883
5711
  GracefulShutdown,
5884
5712
  HUB_ROOM_SYSTEM_PROMPT,
5885
5713
  HistoryProvider,
5714
+ MCP_SERVER_NAME,
5886
5715
  MCP_TOOL_PREFIX,
5887
5716
  MEMORY_SECTION,
5888
5717
  MEMORY_TOOL_NAMES,
5889
- MessageRetryTracker,
5890
- ParticipantTracker,
5718
+ ParticipantRoster,
5891
5719
  PlatformRuntime,
5720
+ RetryTracker,
5892
5721
  RoomPresence,
5893
5722
  SYNTHETIC_CONTACT_EVENTS_SENDER_ID,
5894
5723
  SYNTHETIC_CONTACT_EVENTS_SENDER_NAME,