@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
@@ -3,8 +3,10 @@ import {
3
3
  SYNTHETIC_CONTACT_EVENTS_SENDER_ID,
4
4
  SYNTHETIC_CONTACT_EVENTS_SENDER_NAME,
5
5
  SYNTHETIC_SENDER_TYPE,
6
- buildParticipantsMessage
7
- } from "./chunk-RDM4TE4B.js";
6
+ buildParticipantsMessage,
7
+ toParticipantRecord,
8
+ toParticipantRecordFromRest
9
+ } from "./chunk-LBWKISBS.js";
8
10
  import {
9
11
  CHAT_EVENT_TYPES,
10
12
  CHAT_TOOL_NAMES,
@@ -28,7 +30,7 @@ import {
28
30
  isMemoryType,
29
31
  isMemoryTypeForSystem,
30
32
  memoryTypeForSystemError
31
- } from "./chunk-MLROFDKR.js";
33
+ } from "./chunk-RV76SKFT.js";
32
34
  import {
33
35
  WebSocketDisconnectError,
34
36
  genericCloseReason,
@@ -39,7 +41,7 @@ import {
39
41
  DEFAULT_REQUEST_OPTIONS,
40
42
  FernRestAdapter,
41
43
  fetchPaginated
42
- } from "./chunk-SG4WLD2H.js";
44
+ } from "./chunk-EAI2M3WM.js";
43
45
  import {
44
46
  DEFAULT_AGENT_TOOLS_CAPABILITIES,
45
47
  createToolExecutorError,
@@ -53,7 +55,7 @@ import {
53
55
  TransportError,
54
56
  UnsupportedFeatureError,
55
57
  ValidationError
56
- } from "./chunk-YR3BOQNW.js";
58
+ } from "./chunk-JY75VSQK.js";
57
59
 
58
60
  // src/contracts/capabilities.ts
59
61
  var CAPABILITY_LABELS = {
@@ -170,7 +172,7 @@ import { Socket } from "phoenix";
170
172
  import { WebSocket as NodeWebSocket } from "ws";
171
173
  function createNodeWebSocketFactory(headers) {
172
174
  const Constructor = NodeWebSocket;
173
- class ThenvoiNodeWebSocket {
175
+ class BandNodeWebSocket {
174
176
  constructor(address, protocols) {
175
177
  const socket = new Constructor(address, protocols, headers ? { headers } : void 0);
176
178
  socket.once("unexpected-response", (request, response) => {
@@ -179,7 +181,7 @@ function createNodeWebSocketFactory(headers) {
179
181
  return socket;
180
182
  }
181
183
  }
182
- return ThenvoiNodeWebSocket;
184
+ return BandNodeWebSocket;
183
185
  }
184
186
  async function emitUpgradeError(websocket, request, response) {
185
187
  const body = await readResponseBody(response);
@@ -567,9 +569,9 @@ function getSocketChannelCount(socket) {
567
569
  return candidate.channels.length;
568
570
  }
569
571
 
570
- // src/platform/ThenvoiLink.ts
571
- import { ThenvoiClient } from "@thenvoi/rest-client";
572
- var DEFAULT_WS_URL = "wss://app.thenvoi.com/api/v1/socket";
572
+ // src/platform/BandLink.ts
573
+ import { BandClient } from "@band-ai/rest-client";
574
+ var DEFAULT_WS_URL = "wss://app.band.ai/api/v1/socket";
573
575
  function deriveDefaultRestUrl(wsUrl) {
574
576
  const parsed = new URL(wsUrl);
575
577
  const protocol = parsed.protocol === "ws:" ? "http:" : "https:";
@@ -594,7 +596,7 @@ function toPlatformMessage(roomId, message) {
594
596
  createdAt: new Date(message.inserted_at)
595
597
  };
596
598
  }
597
- var ThenvoiLink = class {
599
+ var BandLink = class {
598
600
  agentId;
599
601
  apiKey;
600
602
  wsUrl;
@@ -620,7 +622,7 @@ var ThenvoiLink = class {
620
622
  ...options.capabilities
621
623
  };
622
624
  const restApi = options.restApi ?? new FernRestAdapter(
623
- new ThenvoiClient({
625
+ new BandClient({
624
626
  apiKey: this.apiKey,
625
627
  baseUrl: this.restUrl
626
628
  })
@@ -1235,6 +1237,7 @@ var Execution = class {
1235
1237
  };
1236
1238
 
1237
1239
  // src/runtime/tools/AgentTools.ts
1240
+ import { ParticipantRoster } from "@band-ai/band-sdk-core";
1238
1241
  var REQUIRED_ADAPTER_TOOL_METHODS = [
1239
1242
  "sendMessage",
1240
1243
  "sendEvent",
@@ -1273,13 +1276,13 @@ var AgentTools = class {
1273
1276
  roomId;
1274
1277
  capabilities;
1275
1278
  rest;
1276
- participants;
1279
+ roster;
1277
1280
  adapterTools;
1278
1281
  toolHandlers;
1279
1282
  constructor(options) {
1280
1283
  this.roomId = options.roomId;
1281
1284
  this.rest = options.rest;
1282
- this.participants = options.participants ?? [];
1285
+ this.roster = options.roster ?? new ParticipantRoster();
1283
1286
  this.capabilities = {
1284
1287
  ...DEFAULT_AGENT_TOOLS_CAPABILITIES,
1285
1288
  ...options.capabilities
@@ -1291,17 +1294,20 @@ var AgentTools = class {
1291
1294
  return this.adapterTools;
1292
1295
  }
1293
1296
  async sendMessage(content, mentions = []) {
1294
- if (mentions.length > 0 && typeof mentions[0] === "string" && this.participants.length === 0) {
1295
- await this.syncParticipants();
1297
+ let participants;
1298
+ if (mentions.length > 0 && typeof mentions[0] === "string") {
1299
+ participants = this.roster.list();
1300
+ if (participants.length === 0) {
1301
+ participants = await this.syncParticipants();
1302
+ }
1296
1303
  }
1297
- const resolvedMentions = this.resolveMentions(mentions);
1304
+ const resolvedMentions = this.resolveMentions(mentions, participants);
1298
1305
  return this.rest.createChatMessage(
1299
1306
  this.roomId,
1300
1307
  {
1301
1308
  content,
1302
1309
  mentions: resolvedMentions
1303
- },
1304
- DEFAULT_REQUEST_OPTIONS
1310
+ }
1305
1311
  );
1306
1312
  }
1307
1313
  async sendEvent(content, messageType, metadata) {
@@ -1312,8 +1318,7 @@ var AgentTools = class {
1312
1318
  content,
1313
1319
  messageType,
1314
1320
  metadata
1315
- },
1316
- DEFAULT_REQUEST_OPTIONS
1321
+ }
1317
1322
  );
1318
1323
  }
1319
1324
  async createChatroom(taskId) {
@@ -1352,7 +1357,7 @@ var AgentTools = class {
1352
1357
  type: String(peer.type ?? "Agent"),
1353
1358
  handle: typeof peer.handle === "string" ? peer.handle : null
1354
1359
  };
1355
- this.participants.push(participantRecord);
1360
+ this.roster.add(participantRecord);
1356
1361
  return {
1357
1362
  ...participantRecord,
1358
1363
  status: "added"
@@ -1367,7 +1372,7 @@ var AgentTools = class {
1367
1372
  throw new ValidationError(`Participant '${name}' not found in room`);
1368
1373
  }
1369
1374
  await this.rest.removeChatParticipant(this.roomId, String(participant.id), DEFAULT_REQUEST_OPTIONS);
1370
- this.replaceParticipants(this.participants.filter((entry) => entry.id !== participant.id));
1375
+ this.roster.remove(participant.id);
1371
1376
  return {
1372
1377
  id: participant.id,
1373
1378
  name,
@@ -1395,17 +1400,12 @@ var AgentTools = class {
1395
1400
  }
1396
1401
  async fetchParticipants() {
1397
1402
  const participants = await this.rest.listChatParticipants(this.roomId, DEFAULT_REQUEST_OPTIONS);
1398
- return participants.map((participant) => ({
1399
- id: participant.id,
1400
- name: participant.name,
1401
- type: participant.type,
1402
- handle: participant.handle ?? null
1403
- }));
1403
+ return participants.map(toParticipantRecordFromRest);
1404
1404
  }
1405
1405
  async syncParticipants() {
1406
1406
  const participants = await this.fetchParticipants();
1407
- this.replaceParticipants(participants);
1408
- return [...this.participants];
1407
+ this.roster.setAll(participants);
1408
+ return this.roster.list().map(toParticipantRecord);
1409
1409
  }
1410
1410
  async executeToolCall(toolName, arguments_) {
1411
1411
  const validationError = validateToolArgs(toolName, arguments_);
@@ -1453,7 +1453,7 @@ var AgentTools = class {
1453
1453
  if (!CHAT_TOOL_NAMES.has(name) && !this.capabilities.contacts) {
1454
1454
  return false;
1455
1455
  }
1456
- if (name === "thenvoi_lookup_peers" && !this.capabilities.peers) {
1456
+ if (name === "band_lookup_peers" && !this.capabilities.peers) {
1457
1457
  return false;
1458
1458
  }
1459
1459
  return true;
@@ -1648,7 +1648,7 @@ var AgentTools = class {
1648
1648
  }
1649
1649
  return this.rest.archiveMemory(normalizedMemoryId, DEFAULT_REQUEST_OPTIONS);
1650
1650
  }
1651
- resolveMentions(mentions) {
1651
+ resolveMentions(mentions, participants) {
1652
1652
  if (mentions.length === 0) {
1653
1653
  return [];
1654
1654
  }
@@ -1661,7 +1661,7 @@ var AgentTools = class {
1661
1661
  const participantsByHandle = /* @__PURE__ */ new Map();
1662
1662
  const participantsById = /* @__PURE__ */ new Map();
1663
1663
  const participantsByName = /* @__PURE__ */ new Map();
1664
- for (const participant of this.participants) {
1664
+ for (const participant of participants ?? []) {
1665
1665
  const ref = {
1666
1666
  id: String(participant.id),
1667
1667
  handle: typeof participant.handle === "string" ? participant.handle : void 0
@@ -1717,9 +1717,6 @@ var AgentTools = class {
1717
1717
  normalizeMentionHandle(handle) {
1718
1718
  return handle.trim().replace(/^@+/, "").toLowerCase();
1719
1719
  }
1720
- replaceParticipants(participants) {
1721
- this.participants.splice(0, this.participants.length, ...participants);
1722
- }
1723
1720
  buildAdapterTools() {
1724
1721
  const tools = {
1725
1722
  capabilities: this.capabilities
@@ -1750,51 +1747,51 @@ var AgentTools = class {
1750
1747
  }
1751
1748
  buildMessagingToolHandlers() {
1752
1749
  return {
1753
- thenvoi_send_message: async (arguments_) => this.sendMessage(
1750
+ band_send_message: async (arguments_) => this.sendMessage(
1754
1751
  String(arguments_.content ?? ""),
1755
1752
  this.normalizeMentionInput(arguments_.mentions)
1756
1753
  ),
1757
- thenvoi_send_event: async (arguments_) => this.sendEvent(
1754
+ band_send_event: async (arguments_) => this.sendEvent(
1758
1755
  String(arguments_.content ?? ""),
1759
1756
  String(arguments_.message_type ?? "task"),
1760
1757
  this.normalizeOptionalMetadata(arguments_.metadata)
1761
1758
  ),
1762
- thenvoi_add_participant: async (arguments_) => this.addParticipant(String(arguments_.name ?? ""), String(arguments_.role ?? "member")),
1763
- thenvoi_remove_participant: async (arguments_) => this.removeParticipant(String(arguments_.name ?? "")),
1764
- thenvoi_lookup_peers: async (arguments_) => this.lookupPeers(
1759
+ band_add_participant: async (arguments_) => this.addParticipant(String(arguments_.name ?? ""), String(arguments_.role ?? "member")),
1760
+ band_remove_participant: async (arguments_) => this.removeParticipant(String(arguments_.name ?? "")),
1761
+ band_lookup_peers: async (arguments_) => this.lookupPeers(
1765
1762
  coercePositiveInt(arguments_.page, 1),
1766
1763
  coercePositiveInt(arguments_.page_size, 50)
1767
1764
  ),
1768
- thenvoi_get_participants: async () => this.getParticipants(),
1769
- thenvoi_create_chatroom: async (arguments_) => this.createChatroom(this.normalizeOptionalString(arguments_.task_id))
1765
+ band_get_participants: async () => this.getParticipants(),
1766
+ band_create_chatroom: async (arguments_) => this.createChatroom(this.normalizeOptionalString(arguments_.task_id))
1770
1767
  };
1771
1768
  }
1772
1769
  buildContactToolHandlers() {
1773
1770
  return {
1774
- thenvoi_list_contacts: async (arguments_) => this.listContacts({
1771
+ band_list_contacts: async (arguments_) => this.listContacts({
1775
1772
  page: coercePositiveInt(arguments_.page, 1),
1776
1773
  pageSize: coercePositiveInt(arguments_.page_size, 50)
1777
1774
  }),
1778
- thenvoi_add_contact: async (arguments_) => this.addContact({
1775
+ band_add_contact: async (arguments_) => this.addContact({
1779
1776
  handle: String(arguments_.handle ?? ""),
1780
1777
  ...typeof arguments_.message === "string" ? { message: arguments_.message } : {}
1781
1778
  }),
1782
- thenvoi_remove_contact: async (arguments_) => this.removeContact(this.toRemoveContactArgs(arguments_)),
1783
- thenvoi_list_contact_requests: async (arguments_) => this.listContactRequests({
1779
+ band_remove_contact: async (arguments_) => this.removeContact(this.toRemoveContactArgs(arguments_)),
1780
+ band_list_contact_requests: async (arguments_) => this.listContactRequests({
1784
1781
  page: coercePositiveInt(arguments_.page, 1),
1785
1782
  pageSize: coercePositiveInt(arguments_.page_size, 50),
1786
1783
  sentStatus: String(arguments_.sent_status ?? "pending")
1787
1784
  }),
1788
- thenvoi_respond_contact_request: async (arguments_) => this.respondContactRequest(this.toRespondContactRequestArgs(arguments_))
1785
+ band_respond_contact_request: async (arguments_) => this.respondContactRequest(this.toRespondContactRequestArgs(arguments_))
1789
1786
  };
1790
1787
  }
1791
1788
  buildMemoryToolHandlers() {
1792
1789
  return {
1793
- thenvoi_list_memories: async (arguments_) => this.listMemories(this.toListMemoriesArgs(arguments_)),
1794
- thenvoi_store_memory: async (arguments_) => this.storeMemory(this.toStoreMemoryArgs(arguments_)),
1795
- thenvoi_get_memory: async (arguments_) => this.getMemory(String(arguments_.memory_id ?? "")),
1796
- thenvoi_supersede_memory: async (arguments_) => this.supersedeMemory(String(arguments_.memory_id ?? "")),
1797
- thenvoi_archive_memory: async (arguments_) => this.archiveMemory(String(arguments_.memory_id ?? ""))
1790
+ band_list_memories: async (arguments_) => this.listMemories(this.toListMemoriesArgs(arguments_)),
1791
+ band_store_memory: async (arguments_) => this.storeMemory(this.toStoreMemoryArgs(arguments_)),
1792
+ band_get_memory: async (arguments_) => this.getMemory(String(arguments_.memory_id ?? "")),
1793
+ band_supersede_memory: async (arguments_) => this.supersedeMemory(String(arguments_.memory_id ?? "")),
1794
+ band_archive_memory: async (arguments_) => this.archiveMemory(String(arguments_.memory_id ?? ""))
1798
1795
  };
1799
1796
  }
1800
1797
  toRemoveContactArgs(arguments_) {
@@ -2038,13 +2035,13 @@ function validateToolArgs(toolName, args) {
2038
2035
  errors.push(`${field}: Field required`);
2039
2036
  }
2040
2037
  }
2041
- if (toolName === "thenvoi_send_message") {
2038
+ if (toolName === "band_send_message") {
2042
2039
  const mentions = args.mentions;
2043
2040
  if (Array.isArray(mentions) && mentions.length === 0) {
2044
2041
  errors.push("mentions: At least one mention is required");
2045
2042
  }
2046
2043
  }
2047
- if (toolName === "thenvoi_send_event") {
2044
+ if (toolName === "band_send_event") {
2048
2045
  const messageType = args.message_type;
2049
2046
  if (typeof messageType === "string" && !CHAT_EVENT_TYPES.includes(messageType)) {
2050
2047
  errors.push(
@@ -2052,7 +2049,7 @@ function validateToolArgs(toolName, args) {
2052
2049
  );
2053
2050
  }
2054
2051
  }
2055
- if (toolName === "thenvoi_respond_contact_request") {
2052
+ if (toolName === "band_respond_contact_request") {
2056
2053
  const action = args.action;
2057
2054
  const validActions = ["approve", "reject", "cancel"];
2058
2055
  if (typeof action === "string" && !validActions.includes(action)) {
@@ -2061,7 +2058,7 @@ function validateToolArgs(toolName, args) {
2061
2058
  );
2062
2059
  }
2063
2060
  }
2064
- if (toolName === "thenvoi_store_memory") {
2061
+ if (toolName === "band_store_memory") {
2065
2062
  if (typeof args.system === "string" && !isMemorySystem(args.system)) {
2066
2063
  errors.push(`system: Invalid value '${args.system}'. Expected one of: ${expectedList(MEMORY_SYSTEMS)}`);
2067
2064
  }
@@ -2090,58 +2087,8 @@ function validateToolArgs(toolName, args) {
2090
2087
  return null;
2091
2088
  }
2092
2089
 
2093
- // src/runtime/retryTracker.ts
2094
- var DEFAULT_MAX_TRACKED = 1e4;
2095
- var MessageRetryTracker = class {
2096
- maxRetriesValue;
2097
- maxTracked;
2098
- attempts = /* @__PURE__ */ new Map();
2099
- failed = /* @__PURE__ */ new Set();
2100
- constructor(maxRetries = 1, maxTracked = DEFAULT_MAX_TRACKED) {
2101
- this.maxRetriesValue = maxRetries;
2102
- this.maxTracked = maxTracked;
2103
- }
2104
- get maxRetries() {
2105
- return this.maxRetriesValue;
2106
- }
2107
- isPermanentlyFailed(messageId) {
2108
- return this.failed.has(messageId);
2109
- }
2110
- recordAttempt(messageId) {
2111
- const attempts = (this.attempts.get(messageId) ?? 0) + 1;
2112
- this.attempts.set(messageId, attempts);
2113
- const exceeded = attempts > this.maxRetriesValue;
2114
- if (exceeded) {
2115
- this.evictSetIfNeeded(this.failed);
2116
- this.failed.add(messageId);
2117
- }
2118
- this.evictMapIfNeeded(this.attempts);
2119
- return [attempts, exceeded];
2120
- }
2121
- markSuccess(messageId) {
2122
- this.attempts.delete(messageId);
2123
- }
2124
- markPermanentlyFailed(messageId) {
2125
- this.evictSetIfNeeded(this.failed);
2126
- this.failed.add(messageId);
2127
- }
2128
- evictMapIfNeeded(map) {
2129
- while (map.size >= this.maxTracked) {
2130
- const first = map.keys().next();
2131
- if (first.done) break;
2132
- map.delete(first.value);
2133
- }
2134
- }
2135
- evictSetIfNeeded(set) {
2136
- while (set.size >= this.maxTracked) {
2137
- const first = set.values().next();
2138
- if (first.done) break;
2139
- set.delete(first.value);
2140
- }
2141
- }
2142
- };
2143
-
2144
2090
  // src/runtime/ExecutionContext.ts
2091
+ import { ParticipantRoster as ParticipantRoster2, RetryTracker } from "@band-ai/band-sdk-core";
2145
2092
  var DEDUP_CACHE_MAX = 500;
2146
2093
  var ExecutionContext = class {
2147
2094
  roomId;
@@ -2153,11 +2100,10 @@ var ExecutionContext = class {
2153
2100
  history = [];
2154
2101
  messageIds = /* @__PURE__ */ new Set();
2155
2102
  dedupCache = /* @__PURE__ */ new Map();
2156
- participants = [];
2103
+ roster = new ParticipantRoster2();
2157
2104
  tools;
2158
2105
  adapterTools;
2159
2106
  participantsMessage = null;
2160
- lastSentParticipantIds = null;
2161
2107
  contactsMessage = null;
2162
2108
  contextCache = null;
2163
2109
  contextCacheExpiresAt = 0;
@@ -2172,11 +2118,11 @@ var ExecutionContext = class {
2172
2118
  this.enableContextCache = options.enableContextCache ?? true;
2173
2119
  this.contextCacheTtlMs = Math.max(0, (options.contextCacheTtlSeconds ?? 300) * 1e3);
2174
2120
  this.enableContextHydration = options.enableContextHydration ?? true;
2175
- this.retryTrackerInstance = new MessageRetryTracker(options.maxMessageRetries ?? 1);
2121
+ this.retryTrackerInstance = new RetryTracker(options.maxMessageRetries ?? 1);
2176
2122
  this.tools = new AgentTools({
2177
2123
  roomId: this.roomId,
2178
2124
  rest: this.link.rest,
2179
- participants: this.participants,
2125
+ roster: this.roster,
2180
2126
  capabilities: this.link.capabilities
2181
2127
  });
2182
2128
  this.adapterTools = this.tools.getAdapterTools();
@@ -2244,23 +2190,20 @@ var ExecutionContext = class {
2244
2190
  }));
2245
2191
  }
2246
2192
  setParticipants(participants) {
2247
- this.replaceParticipants(participants);
2193
+ this.roster.setAll(participants);
2248
2194
  this.updateCachedParticipants();
2249
2195
  }
2250
2196
  addParticipant(participant) {
2251
- const existingIndex = this.participants.findIndex((entry) => entry.id === participant.id);
2252
- if (existingIndex >= 0) {
2253
- this.participants.splice(existingIndex, 1);
2197
+ const isNew = this.roster.add(participant);
2198
+ if (isNew) {
2199
+ const name = String(participant.name ?? "unknown");
2200
+ this.participantsMessage = `${name} joined the room.`;
2254
2201
  }
2255
- this.participants.push(participant);
2256
- const name = String(participant.name ?? "unknown");
2257
- this.participantsMessage = `${name} joined the room.`;
2258
2202
  this.updateCachedParticipants();
2259
2203
  }
2260
2204
  removeParticipant(participantId) {
2261
- const removed = this.participants.find((entry) => String(entry.id) === participantId);
2262
- const next = this.participants.filter((entry) => String(entry.id) !== participantId);
2263
- this.replaceParticipants(next);
2205
+ const removed = this.roster.list().find((entry) => entry.id === participantId);
2206
+ this.roster.remove(participantId);
2264
2207
  if (removed) {
2265
2208
  this.participantsMessage = `${String(removed.name ?? participantId)} left the room.`;
2266
2209
  }
@@ -2270,16 +2213,7 @@ var ExecutionContext = class {
2270
2213
  this.contactsMessage = message;
2271
2214
  }
2272
2215
  consumeParticipantsMessage() {
2273
- const currentIds = new Set(this.participants.map((p) => String(p.id)));
2274
- let changed = !this.lastSentParticipantIds || currentIds.size !== this.lastSentParticipantIds.size;
2275
- if (!changed) {
2276
- for (const id of currentIds) {
2277
- if (!this.lastSentParticipantIds.has(id)) {
2278
- changed = true;
2279
- break;
2280
- }
2281
- }
2282
- }
2216
+ const changed = this.roster.changed();
2283
2217
  if (!changed && !this.participantsMessage) {
2284
2218
  return null;
2285
2219
  }
@@ -2289,15 +2223,9 @@ var ExecutionContext = class {
2289
2223
  this.participantsMessage = null;
2290
2224
  }
2291
2225
  if (changed) {
2292
- const asRecords = this.participants.map((p) => ({
2293
- id: p.id,
2294
- name: p.name,
2295
- type: p.type,
2296
- handle: p.handle ?? null
2297
- }));
2298
- parts.push(buildParticipantsMessage(asRecords));
2299
- }
2300
- this.lastSentParticipantIds = currentIds;
2226
+ parts.push(buildParticipantsMessage(this.roster.list().map((p) => ({ ...toParticipantRecord(p) }))));
2227
+ }
2228
+ this.roster.markSent();
2301
2229
  return parts.length > 0 ? parts.join("\n") : null;
2302
2230
  }
2303
2231
  consumeContactsMessage() {
@@ -2348,27 +2276,19 @@ var ExecutionContext = class {
2348
2276
  return fallback;
2349
2277
  }
2350
2278
  }
2351
- replaceParticipants(participants) {
2352
- this.participants.splice(0, this.participants.length, ...participants);
2353
- }
2354
2279
  buildLocalContext() {
2355
2280
  return {
2356
2281
  roomId: this.roomId,
2357
2282
  messages: this.getRawHistory(),
2358
- participants: [...this.participants],
2283
+ participants: this.roster.list().map(toParticipantRecord),
2359
2284
  hydratedAt: /* @__PURE__ */ new Date()
2360
2285
  };
2361
2286
  }
2362
2287
  async loadParticipants() {
2363
2288
  const participants = await this.link.rest.listChatParticipants(this.roomId, DEFAULT_REQUEST_OPTIONS);
2364
- const normalized = participants.map((participant) => ({
2365
- id: participant.id,
2366
- name: participant.name,
2367
- type: participant.type,
2368
- handle: participant.handle ?? null
2369
- }));
2370
- this.replaceParticipants(normalized);
2371
- return [...this.participants];
2289
+ const normalized = participants.map(toParticipantRecordFromRest);
2290
+ this.roster.setAll(normalized);
2291
+ return this.roster.list().map(toParticipantRecord);
2372
2292
  }
2373
2293
  async loadHydratedMessages() {
2374
2294
  const messages = [];
@@ -2410,7 +2330,7 @@ var ExecutionContext = class {
2410
2330
  if (!this.contextCache) {
2411
2331
  return;
2412
2332
  }
2413
- this.contextCache.participants = [...this.participants];
2333
+ this.contextCache.participants = this.roster.list().map(toParticipantRecord);
2414
2334
  this.contextCache.hydratedAt = /* @__PURE__ */ new Date();
2415
2335
  this.contextCacheExpiresAt = this.nextCacheExpiry();
2416
2336
  }
@@ -3048,14 +2968,6 @@ var ContactToolsImpl = class {
3048
2968
  };
3049
2969
 
3050
2970
  // src/runtime/tools/ContactCallbackTools.ts
3051
- function toParticipantRecord(participant) {
3052
- return {
3053
- id: participant.id,
3054
- name: participant.name,
3055
- type: participant.type,
3056
- handle: participant.handle ?? null
3057
- };
3058
- }
3059
2971
  function normalizePage(value, fallback) {
3060
2972
  return Number.isInteger(value) && value && value > 0 ? value : fallback;
3061
2973
  }
@@ -3099,8 +3011,7 @@ var ContactCallbackTools = class {
3099
3011
  {
3100
3012
  content,
3101
3013
  ...normalizedMentions ? { mentions: normalizedMentions } : {}
3102
- },
3103
- DEFAULT_REQUEST_OPTIONS
3014
+ }
3104
3015
  );
3105
3016
  }
3106
3017
  async sendEvent(content, messageType, metadata) {
@@ -3114,8 +3025,7 @@ var ContactCallbackTools = class {
3114
3025
  content,
3115
3026
  messageType,
3116
3027
  ...metadata ? { metadata } : {}
3117
- },
3118
- DEFAULT_REQUEST_OPTIONS
3028
+ }
3119
3029
  );
3120
3030
  }
3121
3031
  async addParticipant() {
@@ -3129,7 +3039,7 @@ var ContactCallbackTools = class {
3129
3039
  if (!this.rest.listChatParticipants) {
3130
3040
  throw new UnsupportedFeatureError("Participant listing is not available in current REST adapter");
3131
3041
  }
3132
- return (await this.rest.listChatParticipants(roomId, DEFAULT_REQUEST_OPTIONS)).map(toParticipantRecord);
3042
+ return (await this.rest.listChatParticipants(roomId, DEFAULT_REQUEST_OPTIONS)).map(toParticipantRecordFromRest);
3133
3043
  }
3134
3044
  async createChatroom(taskId) {
3135
3045
  const chat = await this.rest.createChat(taskId, DEFAULT_REQUEST_OPTIONS);
@@ -3219,48 +3129,48 @@ var ContactCallbackTools = class {
3219
3129
  }
3220
3130
  async executeToolCall(toolName, toolArgs) {
3221
3131
  switch (toolName) {
3222
- case "thenvoi_send_message":
3132
+ case "band_send_message":
3223
3133
  return this.sendMessage(
3224
3134
  String(toolArgs.content ?? ""),
3225
3135
  toolArgs.mentions
3226
3136
  );
3227
- case "thenvoi_send_event":
3137
+ case "band_send_event":
3228
3138
  return this.sendEvent(
3229
3139
  String(toolArgs.content ?? ""),
3230
3140
  String(toolArgs.message_type ?? "task"),
3231
3141
  toolArgs.metadata
3232
3142
  );
3233
- case "thenvoi_get_participants":
3143
+ case "band_get_participants":
3234
3144
  return this.getParticipants();
3235
- case "thenvoi_create_chatroom":
3145
+ case "band_create_chatroom":
3236
3146
  return this.createChatroom(typeof toolArgs.task_id === "string" ? toolArgs.task_id : void 0);
3237
- case "thenvoi_lookup_peers":
3147
+ case "band_lookup_peers":
3238
3148
  return this.lookupPeers(
3239
3149
  typeof toolArgs.page === "number" ? toolArgs.page : void 0,
3240
3150
  typeof toolArgs.page_size === "number" ? toolArgs.page_size : void 0
3241
3151
  );
3242
- case "thenvoi_list_contacts":
3152
+ case "band_list_contacts":
3243
3153
  return this.listContacts({
3244
3154
  page: typeof toolArgs.page === "number" ? toolArgs.page : void 0,
3245
3155
  pageSize: typeof toolArgs.page_size === "number" ? toolArgs.page_size : void 0
3246
3156
  });
3247
- case "thenvoi_add_contact":
3157
+ case "band_add_contact":
3248
3158
  return this.addContact({
3249
3159
  handle: String(toolArgs.handle ?? ""),
3250
3160
  ...typeof toolArgs.message === "string" ? { message: toolArgs.message } : {}
3251
3161
  });
3252
- case "thenvoi_remove_contact":
3162
+ case "band_remove_contact":
3253
3163
  if (typeof toolArgs.contact_id === "string") {
3254
3164
  return this.removeContact({ target: "contactId", contactId: toolArgs.contact_id });
3255
3165
  }
3256
3166
  return this.removeContact({ target: "handle", handle: String(toolArgs.handle ?? "") });
3257
- case "thenvoi_list_contact_requests":
3167
+ case "band_list_contact_requests":
3258
3168
  return this.listContactRequests({
3259
3169
  page: typeof toolArgs.page === "number" ? toolArgs.page : void 0,
3260
3170
  pageSize: typeof toolArgs.page_size === "number" ? toolArgs.page_size : void 0,
3261
3171
  sentStatus: typeof toolArgs.sent_status === "string" ? toolArgs.sent_status : void 0
3262
3172
  });
3263
- case "thenvoi_respond_contact_request":
3173
+ case "band_respond_contact_request":
3264
3174
  if (typeof toolArgs.request_id === "string") {
3265
3175
  return this.respondContactRequest({
3266
3176
  action: String(toolArgs.action ?? "approve"),
@@ -3273,15 +3183,15 @@ var ContactCallbackTools = class {
3273
3183
  target: "handle",
3274
3184
  handle: String(toolArgs.handle ?? "")
3275
3185
  });
3276
- case "thenvoi_list_memories":
3186
+ case "band_list_memories":
3277
3187
  return this.listMemories(toolArgs);
3278
- case "thenvoi_store_memory":
3188
+ case "band_store_memory":
3279
3189
  return this.storeMemory(toolArgs);
3280
- case "thenvoi_get_memory":
3190
+ case "band_get_memory":
3281
3191
  return this.getMemory(String(toolArgs.memory_id ?? ""));
3282
- case "thenvoi_supersede_memory":
3192
+ case "band_supersede_memory":
3283
3193
  return this.supersedeMemory(String(toolArgs.memory_id ?? ""));
3284
- case "thenvoi_archive_memory":
3194
+ case "band_archive_memory":
3285
3195
  return this.archiveMemory(String(toolArgs.memory_id ?? ""));
3286
3196
  default:
3287
3197
  throw new UnsupportedFeatureError(`Unsupported tool call for contact callback: ${toolName}`);
@@ -3295,14 +3205,14 @@ var HUB_ROOM_SYSTEM_PROMPT = `## OVERRIDE: Contact Management Mode
3295
3205
 
3296
3206
  This is your CONTACTS HUB - a dedicated room for managing contact requests.
3297
3207
 
3298
- **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.
3208
+ **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.
3299
3209
 
3300
3210
  ## Your Role
3301
3211
 
3302
3212
  1. **Review incoming contact requests** - When you see a [Contact Request] message, evaluate it
3303
3213
  2. **Take action** - Use the contact tools to respond:
3304
- - \`thenvoi_respond_contact_request(action="approve", request_id="...")\` to accept
3305
- - \`thenvoi_respond_contact_request(action="reject", request_id="...")\` to decline
3214
+ - \`band_respond_contact_request(action="approve", request_id="...")\` to accept
3215
+ - \`band_respond_contact_request(action="reject", request_id="...")\` to decline
3306
3216
  3. **Report your decision** - Send a thought event explaining what you did
3307
3217
 
3308
3218
  ## Example
@@ -3311,14 +3221,14 @@ This is your CONTACTS HUB - a dedicated room for managing contact requests.
3311
3221
  Request ID: abc-123
3312
3222
 
3313
3223
  Your response:
3314
- 1. thenvoi_send_event("Received contact request from Alice. Approving.", message_type="thought")
3315
- 2. thenvoi_respond_contact_request(action="approve", request_id="abc-123")
3316
- 3. thenvoi_send_event("Approved contact request from Alice (@alice)", message_type="thought")
3224
+ 1. band_send_event("Received contact request from Alice. Approving.", message_type="thought")
3225
+ 2. band_respond_contact_request(action="approve", request_id="abc-123")
3226
+ 3. band_send_event("Approved contact request from Alice (@alice)", message_type="thought")
3317
3227
 
3318
3228
  ## Contact Tools (use these, NOT participant tools)
3319
- - \`thenvoi_respond_contact_request(action, request_id)\` - Approve/reject requests
3320
- - \`thenvoi_list_contact_requests()\` - List pending requests
3321
- - \`thenvoi_list_contacts()\` - List current contacts`;
3229
+ - \`band_respond_contact_request(action, request_id)\` - Approve/reject requests
3230
+ - \`band_list_contact_requests()\` - List pending requests
3231
+ - \`band_list_contacts()\` - List current contacts`;
3322
3232
  var ContactEventHandlerError = class extends Error {
3323
3233
  retryable;
3324
3234
  stage;
@@ -3646,6 +3556,8 @@ function normalizeHandle(handle) {
3646
3556
  }
3647
3557
 
3648
3558
  // src/runtime/PlatformRuntime.ts
3559
+ var MAX_MESSAGE_RETRIES = 4294967295;
3560
+ var isValidRetryCount = (value) => Number.isInteger(value) && value >= 0 && value <= MAX_MESSAGE_RETRIES;
3649
3561
  var PlatformRuntime = class {
3650
3562
  _agentId;
3651
3563
  _apiKey;
@@ -3682,6 +3594,12 @@ var PlatformRuntime = class {
3682
3594
  "apiKey is required and must be a non-empty string. Use loadAgentConfig() to load credentials from agent_config.yaml."
3683
3595
  );
3684
3596
  }
3597
+ const maxMessageRetries = options.sessionConfig?.maxMessageRetries;
3598
+ if (maxMessageRetries !== void 0 && !isValidRetryCount(maxMessageRetries)) {
3599
+ throw new ValidationError(
3600
+ `sessionConfig.maxMessageRetries must be an integer between 0 and ${MAX_MESSAGE_RETRIES}, got ${maxMessageRetries}.`
3601
+ );
3602
+ }
3685
3603
  this._agentId = options.agentId;
3686
3604
  this._apiKey = options.apiKey;
3687
3605
  this._wsUrl = options.wsUrl;
@@ -3734,7 +3652,7 @@ var PlatformRuntime = class {
3734
3652
  }
3735
3653
  async doInitialize() {
3736
3654
  if (!this.linkInstance) {
3737
- this.linkInstance = new ThenvoiLink({
3655
+ this.linkInstance = new BandLink({
3738
3656
  ...this.linkOptions,
3739
3657
  agentId: this._agentId,
3740
3658
  apiKey: this._apiKey,
@@ -3958,10 +3876,9 @@ async function runWithGracefulShutdown(agent, options) {
3958
3876
 
3959
3877
  export {
3960
3878
  deriveDefaultRestUrl,
3961
- ThenvoiLink,
3879
+ BandLink,
3962
3880
  Execution,
3963
3881
  AgentTools,
3964
- MessageRetryTracker,
3965
3882
  ExecutionContext,
3966
3883
  trackRoomJoin,
3967
3884
  trackRoomLeave,