@band-ai/sdk 0.1.4 → 0.1.10

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 (73) hide show
  1. package/README.md +372 -0
  2. package/dist/{ClaudeSDKAdapter-CRq4R-WB.d.cts → ClaudeSDKAdapter-DfjaI5ke.d.cts} +9 -7
  3. package/dist/{ClaudeSDKAdapter-BHOkjN3X.d.ts → ClaudeSDKAdapter-DonPGJ43.d.ts} +9 -7
  4. package/dist/{acp-server-BdRz9_UN.d.cts → acp-server-CUBXIiG6.d.cts} +2 -2
  5. package/dist/{acp-server-B1Da7L6u.d.ts → acp-server-NZAeg-WO.d.ts} +2 -2
  6. package/dist/adapters.cjs +494 -106
  7. package/dist/adapters.d.cts +12 -12
  8. package/dist/adapters.d.ts +12 -12
  9. package/dist/adapters.js +7 -7
  10. package/dist/{backends-SVMT-7l4.d.cts → backends-DYtEhCZG.d.cts} +7 -2
  11. package/dist/{backends-CzDbiQar.d.ts → backends-oYAb7EU-.d.ts} +7 -2
  12. package/dist/{chunk-MSL6CWHY.js → chunk-2BHHR6YW.js} +17 -16
  13. package/dist/{chunk-EDPKUUJL.js → chunk-6RXWL6TC.js} +9 -1
  14. package/dist/{chunk-SFVKOEQH.js → chunk-DNPVCR3S.js} +92 -14
  15. package/dist/{chunk-I5EZG52P.js → chunk-FP237EAG.js} +424 -136
  16. package/dist/{chunk-RHVH2GZR.js → chunk-J3M3PFFY.js} +81 -31
  17. package/dist/{chunk-GVEQ3RAH.js → chunk-MLROFDKR.js} +132 -23
  18. package/dist/{chunk-INA6YZTZ.js → chunk-RDM4TE4B.js} +32 -30
  19. package/dist/chunk-US226AS4.js +130 -0
  20. package/dist/{chunk-W5NDZSYE.js → chunk-XA4N2JPH.js} +1 -1
  21. package/dist/converters.cjs +469 -13
  22. package/dist/converters.d.cts +5 -5
  23. package/dist/converters.d.ts +5 -5
  24. package/dist/converters.js +3 -2
  25. package/dist/core.cjs +45 -2
  26. package/dist/core.d.cts +4 -3
  27. package/dist/core.d.ts +4 -3
  28. package/dist/core.js +5 -1
  29. package/dist/disconnectReason-IuADl6TH.d.cts +34 -0
  30. package/dist/disconnectReason-IuADl6TH.d.ts +34 -0
  31. package/dist/{dtos-DUpbIu8k.d.cts → dtos-Dd_fTfLn.d.cts} +26 -6
  32. package/dist/{dtos-DUpbIu8k.d.ts → dtos-Dd_fTfLn.d.ts} +26 -6
  33. package/dist/index.cjs +1089 -269
  34. package/dist/index.d.cts +16 -15
  35. package/dist/index.d.ts +16 -15
  36. package/dist/index.js +14 -8
  37. package/dist/linear.cjs +985 -53
  38. package/dist/linear.d.cts +137 -7
  39. package/dist/linear.d.ts +137 -7
  40. package/dist/linear.js +974 -53
  41. package/dist/mcp-claude.cjs +303 -32
  42. package/dist/mcp-claude.d.cts +3 -3
  43. package/dist/mcp-claude.d.ts +3 -3
  44. package/dist/mcp-claude.js +210 -12
  45. package/dist/mcp.cjs +313 -45
  46. package/dist/mcp.d.cts +5 -5
  47. package/dist/mcp.d.ts +5 -5
  48. package/dist/mcp.js +3 -3
  49. package/dist/{opencode-BBcDchcN.d.cts → opencode--iA5-KYk.d.cts} +2 -2
  50. package/dist/{opencode-DthQQUsZ.d.ts → opencode-YNacv-eJ.d.ts} +2 -2
  51. package/dist/{pagination-CcDkVFxK.d.ts → pagination-BBLsYLhT.d.ts} +2 -2
  52. package/dist/{pagination-BPiys10t.d.cts → pagination-CqidD-L_.d.cts} +2 -2
  53. package/dist/{protocols-DrhzOH6K.d.ts → protocols-BF6jamIl.d.ts} +1 -1
  54. package/dist/{protocols-CInhtFpA.d.cts → protocols-D2bTrQ_t.d.cts} +1 -1
  55. package/dist/rest.d.cts +5 -5
  56. package/dist/rest.d.ts +5 -5
  57. package/dist/runtime.cjs +721 -172
  58. package/dist/runtime.d.cts +15 -10
  59. package/dist/runtime.d.ts +15 -10
  60. package/dist/runtime.js +11 -8
  61. package/dist/{schemas-vos1AaBc.d.ts → schemas-B1Fd3oUM.d.ts} +17 -8
  62. package/dist/{schemas-BpEBkq5V.d.cts → schemas-CI0qgcp_.d.cts} +17 -8
  63. package/dist/{sdk-CcnQ5OUC.d.ts → sdk-CyqN1W5g.d.ts} +32 -2
  64. package/dist/{sdk-CwTAxhwI.d.cts → sdk-D2rTDU_o.d.cts} +32 -2
  65. package/dist/{simpleAdapter-DqhvjsGr.d.cts → simpleAdapter-C_f-01Cu.d.cts} +1 -1
  66. package/dist/{simpleAdapter-9OE_p6QW.d.ts → simpleAdapter-qQt-tSz4.d.ts} +1 -1
  67. package/dist/testing.d.cts +3 -3
  68. package/dist/testing.d.ts +3 -3
  69. package/dist/{types-CovcHpYf.d.cts → types-CKqrhGB1.d.cts} +2 -2
  70. package/dist/{types-CxII3XkA.d.ts → types-D3AsUnd0.d.ts} +1 -1
  71. package/dist/{types-7jVzOeOP.d.ts → types-DNySTI_8.d.ts} +2 -2
  72. package/dist/{types-CSHFipIc.d.cts → types-DtMms5Fi.d.cts} +1 -1
  73. package/package.json +22 -21
package/dist/adapters.cjs CHANGED
@@ -30,32 +30,81 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  ));
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
- // src/contracts/protocols.ts
34
- function isToolExecutorError(value) {
35
- if (!value || typeof value !== "object") {
36
- return false;
37
- }
38
- const candidate = value;
39
- return candidate.ok === false && typeof candidate.errorType === "string" && TOOL_EXECUTOR_ERROR_TYPES.includes(candidate.errorType) && typeof candidate.toolName === "string" && typeof candidate.message === "string" && typeof candidate.legacyMessage === "string";
33
+ // src/contracts/memory.ts
34
+ function namedValues(values) {
35
+ return Object.fromEntries(values.map((value) => [value, value]));
40
36
  }
41
- function toLegacyToolExecutorErrorMessage(value) {
42
- if (typeof value === "string") {
43
- return value;
44
- }
45
- if (!isToolExecutorError(value)) {
46
- return null;
47
- }
48
- return value.legacyMessage;
49
- }
50
- var TOOL_EXECUTOR_ERROR_TYPES;
51
- var init_protocols = __esm({
52
- "src/contracts/protocols.ts"() {
37
+ var SENSORY_MEMORY_TYPES, COGNITIVE_MEMORY_TYPES, MEMORY_SYSTEM_TYPES, MEMORY_SYSTEMS, MEMORY_TYPES, MEMORY_SEGMENTS, MEMORY_STORE_SCOPES, MEMORY_LIST_SCOPES, MEMORY_STATUSES, MEMORY_SYSTEM, MEMORY_TYPE, MEMORY_SEGMENT, MEMORY_STORE_SCOPE;
38
+ var init_memory = __esm({
39
+ "src/contracts/memory.ts"() {
53
40
  "use strict";
54
- TOOL_EXECUTOR_ERROR_TYPES = [
55
- "ToolArgumentsValidationError",
56
- "ToolNotFoundError",
57
- "ToolExecutionError"
41
+ SENSORY_MEMORY_TYPES = [
42
+ "iconic",
43
+ // Visual input
44
+ "echoic",
45
+ // Auditory input
46
+ "haptic"
47
+ // Tactile input
58
48
  ];
49
+ COGNITIVE_MEMORY_TYPES = [
50
+ "episodic",
51
+ // Events that occurred
52
+ "semantic",
53
+ // Facts, preferences, learned knowledge
54
+ "procedural"
55
+ // How to perform tasks
56
+ ];
57
+ MEMORY_SYSTEM_TYPES = {
58
+ sensory: SENSORY_MEMORY_TYPES,
59
+ // Brief sensory inputs
60
+ working: COGNITIVE_MEMORY_TYPES,
61
+ // Short-term session context
62
+ long_term: COGNITIVE_MEMORY_TYPES
63
+ // Persistent cross-conversation memory
64
+ };
65
+ MEMORY_SYSTEMS = Object.keys(MEMORY_SYSTEM_TYPES);
66
+ MEMORY_TYPES = [
67
+ ...SENSORY_MEMORY_TYPES,
68
+ ...COGNITIVE_MEMORY_TYPES
69
+ ];
70
+ MEMORY_SEGMENTS = [
71
+ "user",
72
+ // User preferences or profile info
73
+ "agent",
74
+ // Facts or events about agents/entities
75
+ "tool",
76
+ // Tool usage or task procedures
77
+ "guideline"
78
+ // Behavioral rules or policies
79
+ ];
80
+ MEMORY_STORE_SCOPES = [
81
+ "subject",
82
+ // About one person/agent; requires subject_id
83
+ "organization"
84
+ // Shared org-wide
85
+ ];
86
+ MEMORY_LIST_SCOPES = [
87
+ "subject",
88
+ // Subject-scoped memories only
89
+ "organization",
90
+ // Organization-scoped memories only
91
+ "all"
92
+ // Both scopes (no scope filter)
93
+ ];
94
+ MEMORY_STATUSES = [
95
+ "active",
96
+ // Normal, visible memories
97
+ "superseded",
98
+ // Outdated; soft-deleted via thenvoi_supersede_memory
99
+ "archived",
100
+ // Hidden but preserved via thenvoi_archive_memory
101
+ "all"
102
+ // Any status (no filter)
103
+ ];
104
+ MEMORY_SYSTEM = namedValues(MEMORY_SYSTEMS);
105
+ MEMORY_TYPE = namedValues(MEMORY_TYPES);
106
+ MEMORY_SEGMENT = namedValues(MEMORY_SEGMENTS);
107
+ MEMORY_STORE_SCOPE = namedValues(MEMORY_STORE_SCOPES);
59
108
  }
60
109
  });
61
110
 
@@ -115,6 +164,7 @@ var init_schemas = __esm({
115
164
  "src/runtime/tools/schemas.ts"() {
116
165
  "use strict";
117
166
  init_chatEvents();
167
+ init_memory();
118
168
  TOOL_MODELS = {
119
169
  thenvoi_send_message: {
120
170
  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.",
@@ -301,29 +351,22 @@ var init_schemas = __esm({
301
351
  },
302
352
  scope: {
303
353
  type: "string",
304
- enum: ["subject", "organization", "all"],
354
+ enum: [...MEMORY_LIST_SCOPES],
305
355
  description: "Filter by scope."
306
356
  },
307
357
  system: {
308
358
  type: "string",
309
- enum: ["sensory", "working", "long_term"],
359
+ enum: [...MEMORY_SYSTEMS],
310
360
  description: "Filter by memory system."
311
361
  },
312
362
  type: {
313
363
  type: "string",
314
- enum: [
315
- "iconic",
316
- "echoic",
317
- "haptic",
318
- "episodic",
319
- "semantic",
320
- "procedural"
321
- ],
364
+ enum: [...MEMORY_TYPES],
322
365
  description: "Filter by memory type."
323
366
  },
324
367
  segment: {
325
368
  type: "string",
326
- enum: ["user", "agent", "tool", "guideline"],
369
+ enum: [...MEMORY_SEGMENTS],
327
370
  description: "Filter by segment."
328
371
  },
329
372
  content_query: {
@@ -338,7 +381,7 @@ var init_schemas = __esm({
338
381
  },
339
382
  status: {
340
383
  type: "string",
341
- enum: ["active", "superseded", "archived", "all"],
384
+ enum: [...MEMORY_STATUSES],
342
385
  description: "Filter by status."
343
386
  }
344
387
  },
@@ -353,24 +396,17 @@ var init_schemas = __esm({
353
396
  },
354
397
  system: {
355
398
  type: "string",
356
- enum: ["sensory", "working", "long_term"],
399
+ enum: [...MEMORY_SYSTEMS],
357
400
  description: "Memory system tier."
358
401
  },
359
402
  type: {
360
403
  type: "string",
361
- enum: [
362
- "iconic",
363
- "echoic",
364
- "haptic",
365
- "episodic",
366
- "semantic",
367
- "procedural"
368
- ],
404
+ enum: [...MEMORY_TYPES],
369
405
  description: "Memory type (must be valid for selected system)."
370
406
  },
371
407
  segment: {
372
408
  type: "string",
373
- enum: ["user", "agent", "tool", "guideline"],
409
+ enum: [...MEMORY_SEGMENTS],
374
410
  description: "Logical segment."
375
411
  },
376
412
  thought: {
@@ -379,7 +415,7 @@ var init_schemas = __esm({
379
415
  },
380
416
  scope: {
381
417
  type: "string",
382
- enum: ["subject", "organization"],
418
+ enum: [...MEMORY_STORE_SCOPES],
383
419
  description: "Visibility scope."
384
420
  },
385
421
  subject_id: {
@@ -449,6 +485,35 @@ var init_schemas = __esm({
449
485
  }
450
486
  });
451
487
 
488
+ // src/contracts/protocols.ts
489
+ function isToolExecutorError(value) {
490
+ if (!value || typeof value !== "object") {
491
+ return false;
492
+ }
493
+ const candidate = value;
494
+ return candidate.ok === false && typeof candidate.errorType === "string" && TOOL_EXECUTOR_ERROR_TYPES.includes(candidate.errorType) && typeof candidate.toolName === "string" && typeof candidate.message === "string" && typeof candidate.legacyMessage === "string";
495
+ }
496
+ function toLegacyToolExecutorErrorMessage(value) {
497
+ if (typeof value === "string") {
498
+ return value;
499
+ }
500
+ if (!isToolExecutorError(value)) {
501
+ return null;
502
+ }
503
+ return value.legacyMessage;
504
+ }
505
+ var TOOL_EXECUTOR_ERROR_TYPES;
506
+ var init_protocols = __esm({
507
+ "src/contracts/protocols.ts"() {
508
+ "use strict";
509
+ TOOL_EXECUTOR_ERROR_TYPES = [
510
+ "ToolArgumentsValidationError",
511
+ "ToolNotFoundError",
512
+ "ToolExecutionError"
513
+ ];
514
+ }
515
+ });
516
+
452
517
  // src/mcp/registrations.ts
453
518
  function buildRoomScopedRegistrations(resolver, options = {}) {
454
519
  const toolNames = resolveToolNames(options);
@@ -567,6 +632,13 @@ function serializeValue(value) {
567
632
  return String(value);
568
633
  }
569
634
  }
635
+ function resolveSingleRoomTools(getToolsForRoom) {
636
+ const tools = getToolsForRoom("");
637
+ if (!tools) {
638
+ throw new Error('Single-room mode requires getToolsForRoom("") to return a tools instance');
639
+ }
640
+ return tools;
641
+ }
570
642
  var init_registrations = __esm({
571
643
  "src/mcp/registrations.ts"() {
572
644
  "use strict";
@@ -625,16 +697,16 @@ __export(sdk_exports, {
625
697
  createThenvoiSdkMcpServer: () => createThenvoiSdkMcpServer
626
698
  });
627
699
  function createThenvoiSdkMcpServer(options) {
628
- const registrations = buildRoomScopedRegistrations(
629
- options.getToolsForRoom,
630
- {
631
- enableMemoryTools: options.enableMemoryTools,
632
- enableContactTools: true,
633
- additionalTools: options.additionalTools
634
- }
635
- );
700
+ const registrationOptions = {
701
+ enableMemoryTools: options.enableMemoryTools,
702
+ enableContactTools: true,
703
+ additionalTools: options.additionalTools
704
+ };
705
+ const registrations = options.multiRoom === false ? buildSingleContextRegistrations(resolveSingleRoomTools(options.getToolsForRoom), registrationOptions) : buildRoomScopedRegistrations(options.getToolsForRoom, registrationOptions);
636
706
  const toolDefinitions = registrations.map(toSdkToolDefinition);
637
707
  const toolNames = new Set(registrations.map((r) => r.name));
708
+ const contextCache = /* @__PURE__ */ new Map();
709
+ const MAX_CONTEXT_CACHE_ENTRIES = 100;
638
710
  const serverConfig = (0, import_claude_agent_sdk.createSdkMcpServer)({
639
711
  name: "thenvoi",
640
712
  tools: toolDefinitions
@@ -642,9 +714,205 @@ function createThenvoiSdkMcpServer(options) {
642
714
  return {
643
715
  serverConfig,
644
716
  allowedTools: mcpToolNames(toolNames),
645
- toolDefinitions
717
+ toolDefinitions,
718
+ getSystemPromptContext: async (roomId, contextOptions) => {
719
+ const context = await getOrBuildSystemPromptContext(
720
+ roomId,
721
+ contextOptions,
722
+ options.getToolsForRoom,
723
+ contextCache,
724
+ MAX_CONTEXT_CACHE_ENTRIES
725
+ );
726
+ return context.markdown;
727
+ },
728
+ getSystemPromptContextData: (roomId, contextOptions) => {
729
+ return getOrBuildSystemPromptContext(
730
+ roomId,
731
+ contextOptions,
732
+ options.getToolsForRoom,
733
+ contextCache,
734
+ MAX_CONTEXT_CACHE_ENTRIES
735
+ );
736
+ }
737
+ };
738
+ }
739
+ async function getOrBuildSystemPromptContext(roomId, contextOptions, getToolsForRoom, contextCache, maxEntries) {
740
+ const ttlMs = contextOptions?.ttlMs ?? 3e4;
741
+ const now = Date.now();
742
+ const cached = contextCache.get(roomId);
743
+ if (cached && cached.expiresAt > now) {
744
+ cached.lastAccessedAt = now;
745
+ return cached.value;
746
+ }
747
+ if (cached) {
748
+ contextCache.delete(roomId);
749
+ }
750
+ const tools = getToolsForRoom(roomId);
751
+ if (!tools) {
752
+ return buildUnavailableSystemPromptContext(roomId);
753
+ }
754
+ const context = await buildSystemPromptContext(roomId, tools);
755
+ contextCache.set(roomId, {
756
+ value: context,
757
+ expiresAt: now + ttlMs,
758
+ lastAccessedAt: now
759
+ });
760
+ evictLeastRecentlyUsedContext(contextCache, maxEntries);
761
+ return context;
762
+ }
763
+ async function buildSystemPromptContext(roomId, tools) {
764
+ const participants = await tools.getParticipants();
765
+ const warnings = [];
766
+ const agentResolution = await resolveAgentIdentity(tools);
767
+ if (agentResolution.warning) {
768
+ warnings.push(agentResolution.warning);
769
+ }
770
+ const roomResolution = await resolveRoomTitle(tools, roomId);
771
+ if (roomResolution.warning) {
772
+ warnings.push(roomResolution.warning);
773
+ }
774
+ const agentIdentity = agentResolution.value;
775
+ const roomTitle = roomResolution.value;
776
+ const normalizedParticipants = participants.map((participant) => ({
777
+ id: String(participant.id),
778
+ name: String(participant.name ?? "Unknown"),
779
+ type: String(participant.type ?? "Unknown"),
780
+ handle: normalizeHandle(participant.handle),
781
+ isSelf: participant.id === agentIdentity?.id
782
+ }));
783
+ const selfHandle = normalizeHandle(agentIdentity?.handle);
784
+ const selfName = agentIdentity?.name ?? "Agent";
785
+ const mentionHandles = normalizedParticipants.filter((participant) => !participant.isSelf).map((participant) => participant.handle).filter((handle) => Boolean(handle));
786
+ const mentionFormat = mentionHandles.length > 0 ? mentionHandles.join(", ") : "No participant handles available";
787
+ const roomLabel = roomTitle ? `"${roomTitle}"` : "this room";
788
+ const agentLabel = selfHandle ? `${selfName} (${selfHandle})` : selfName;
789
+ const participantLines = normalizedParticipants.length > 0 ? normalizedParticipants.map((participant) => {
790
+ const suffix = participant.isSelf ? " (you)" : "";
791
+ const handle = participant.handle ? ` (${participant.handle})` : "";
792
+ return `- **${participant.name}**${handle} -- ${participant.type}${suffix}`;
793
+ }).join("\n") : "- No participants found";
794
+ const markdown = [
795
+ "## Room Context",
796
+ "",
797
+ `You are **${agentLabel}** in room ${roomLabel} (id: ${roomId}).`,
798
+ "",
799
+ "### Participants",
800
+ participantLines,
801
+ "",
802
+ "### Mention Format",
803
+ `To address someone, use their exact handle: ${mentionFormat}`,
804
+ ...warnings.length > 0 ? ["", "### Warnings", ...warnings.map((warning) => `- ${warning}`)] : []
805
+ ].join("\n");
806
+ return {
807
+ roomId,
808
+ roomTitle,
809
+ agent: {
810
+ id: agentIdentity?.id ?? "unknown-agent",
811
+ name: selfName,
812
+ handle: selfHandle,
813
+ description: agentIdentity?.description ?? null
814
+ },
815
+ participants: normalizedParticipants,
816
+ mentionFormat,
817
+ warnings,
818
+ markdown
646
819
  };
647
820
  }
821
+ async function resolveAgentIdentity(tools) {
822
+ const maybeTools = tools;
823
+ try {
824
+ if (maybeTools.getAgentIdentity) {
825
+ return { value: await maybeTools.getAgentIdentity(), warning: null };
826
+ }
827
+ if (maybeTools.rest?.getAgentMe) {
828
+ return { value: await maybeTools.rest.getAgentMe(), warning: null };
829
+ }
830
+ } catch (error) {
831
+ return {
832
+ value: null,
833
+ warning: `Unable to resolve agent identity: ${error instanceof Error ? error.message : String(error)}`
834
+ };
835
+ }
836
+ return { value: null, warning: null };
837
+ }
838
+ async function resolveRoomTitle(tools, roomId) {
839
+ const maybeTools = tools;
840
+ const rest = maybeTools.rest;
841
+ if (!rest?.listChats) {
842
+ return { value: null, warning: null };
843
+ }
844
+ try {
845
+ let page = 1;
846
+ const pageSize = 100;
847
+ while (true) {
848
+ const response = await rest.listChats({ page, pageSize });
849
+ const room = response?.data?.find((entry) => entry.id === roomId);
850
+ if (typeof room?.title === "string" && room.title.length > 0) {
851
+ return { value: room.title, warning: null };
852
+ }
853
+ const totalPages = response?.metadata?.totalPages ?? page;
854
+ if (page >= totalPages) {
855
+ return { value: null, warning: null };
856
+ }
857
+ page += 1;
858
+ }
859
+ } catch (error) {
860
+ return {
861
+ value: null,
862
+ warning: `Unable to resolve room title: ${error instanceof Error ? error.message : String(error)}`
863
+ };
864
+ }
865
+ }
866
+ function buildUnavailableSystemPromptContext(roomId) {
867
+ const warnings = [`No tool context found for room_id ${roomId}`];
868
+ const markdown = [
869
+ "## Room Context",
870
+ "",
871
+ `You are **Agent** in this room (id: ${roomId}).`,
872
+ "",
873
+ "### Participants",
874
+ "- No participants found",
875
+ "",
876
+ "### Mention Format",
877
+ "No participant handles available",
878
+ "",
879
+ "### Warnings",
880
+ ...warnings.map((warning) => `- ${warning}`)
881
+ ].join("\n");
882
+ return {
883
+ roomId,
884
+ roomTitle: null,
885
+ agent: {
886
+ id: "unknown-agent",
887
+ name: "Agent",
888
+ handle: null,
889
+ description: null
890
+ },
891
+ participants: [],
892
+ mentionFormat: "No participant handles available",
893
+ warnings,
894
+ markdown
895
+ };
896
+ }
897
+ function evictLeastRecentlyUsedContext(contextCache, maxEntries) {
898
+ if (contextCache.size <= maxEntries) {
899
+ return;
900
+ }
901
+ let oldestKey = null;
902
+ let oldestAccessedAt = Number.POSITIVE_INFINITY;
903
+ for (const [key, entry] of contextCache.entries()) {
904
+ if (entry.lastAccessedAt < oldestAccessedAt) {
905
+ oldestAccessedAt = entry.lastAccessedAt;
906
+ oldestKey = key;
907
+ }
908
+ }
909
+ if (oldestKey) {
910
+ contextCache.delete(oldestKey);
911
+ }
912
+ }
913
+ function normalizeHandle(handle) {
914
+ return typeof handle === "string" && handle.trim().length > 0 ? handle.trim() : null;
915
+ }
648
916
  function toSdkToolDefinition(registration) {
649
917
  const shape = buildZodShape(
650
918
  import_zod5.z,
@@ -795,16 +1063,15 @@ var ACPClientHistoryConverter = class {
795
1063
  }
796
1064
  };
797
1065
 
798
- // src/runtime/prompts.ts
799
- var BASE_INSTRUCTIONS = `
1066
+ // src/runtime/prompts/base.ts
1067
+ var ENVIRONMENT_SECTION = `
800
1068
  ## Environment
801
1069
 
802
1070
  Multi-participant chat. Messages show sender: [Name]: content.
803
1071
  Messages prefixed with [System]: are platform updates (participant changes, contact updates, etc.) \u2014 not messages from users.
804
1072
  Use \`thenvoi_send_message(content, mentions)\` to respond. Plain text output is not delivered.
805
- Mentions use handles: @<username> for users, @<username>/<agent-name> for agents.
806
-
807
- ## CRITICAL: Delegate When You Cannot Help Directly
1073
+ Mentions use handles: @<username> for users, @<username>/<agent-name> for agents.`;
1074
+ var MULTI_AGENT_RULES_SECTION = `## CRITICAL: Delegate When You Cannot Help Directly
808
1075
 
809
1076
  You have NO internet access and NO real-time data. When asked about weather, news, stock prices,
810
1077
  or any current information you cannot answer directly:
@@ -830,14 +1097,12 @@ Only remove agents if the user explicitly requests it.
830
1097
  When someone asks you to get information from another agent:
831
1098
  1. Ask the other agent for the information
832
1099
  2. When you receive the response, IMMEDIATELY relay it back to the ORIGINAL REQUESTER
833
- 3. Do NOT just thank the helper agent - the requester is waiting for their answer!
834
-
835
- ## IMPORTANT: Always Share Your Thinking
1100
+ 3. Do NOT just thank the helper agent - the requester is waiting for their answer!`;
1101
+ var THINKING_SECTION = `## IMPORTANT: Always Share Your Thinking
836
1102
 
837
1103
  You MUST call \`thenvoi_send_event(content, message_type="thought")\` BEFORE every action.
838
- This is required so users can see your reasoning process.
839
-
840
- ## Examples
1104
+ This is required so users can see your reasoning process.`;
1105
+ var EXAMPLES_SECTION = `## Examples
841
1106
 
842
1107
  ### Simple question - answer directly
843
1108
  [John Doe]: What's 2+2?
@@ -870,8 +1135,75 @@ This is required so users can see your reasoning process.
870
1135
 
871
1136
  [Weather Agent]: London is 8\xB0C and rainy.
872
1137
  -> thenvoi_send_event("Got London weather. Relaying to John Doe.", message_type="thought")
873
- -> thenvoi_send_message("London is 8\xB0C and rainy.", mentions=["@john"])
874
- `;
1138
+ -> thenvoi_send_message("London is 8\xB0C and rainy.", mentions=["@john"])`;
1139
+ var BASE_INSTRUCTIONS = [
1140
+ ENVIRONMENT_SECTION,
1141
+ MULTI_AGENT_RULES_SECTION,
1142
+ THINKING_SECTION,
1143
+ EXAMPLES_SECTION
1144
+ ].join("\n\n") + "\n";
1145
+
1146
+ // src/runtime/prompts/memory.ts
1147
+ init_memory();
1148
+ init_schemas();
1149
+ var MEMORY_INTRO = `## Memory Tools
1150
+
1151
+ You have access to memory tools for storing and retrieving information
1152
+ across conversations. Use \`thenvoi_store_memory\` to persist important
1153
+ information and \`thenvoi_list_memories\` / \`thenvoi_get_memory\` to recall it.
1154
+ Use \`thenvoi_supersede_memory\` to mark outdated memories and
1155
+ \`thenvoi_archive_memory\` to hide memories that should be preserved.`;
1156
+ function longTermPattern(label, type, segment, scope) {
1157
+ return {
1158
+ label,
1159
+ system: MEMORY_SYSTEM.long_term,
1160
+ type,
1161
+ segment,
1162
+ scope
1163
+ };
1164
+ }
1165
+ var COMMON_MEMORY_PATTERNS = [
1166
+ longTermPattern("Facts learned about a specific agent/entity", MEMORY_TYPE.semantic, MEMORY_SEGMENT.agent, MEMORY_STORE_SCOPE.subject),
1167
+ longTermPattern("Events involving a specific person/agent", MEMORY_TYPE.episodic, MEMORY_SEGMENT.agent, MEMORY_STORE_SCOPE.subject),
1168
+ longTermPattern("A user's preferences or profile info", MEMORY_TYPE.semantic, MEMORY_SEGMENT.user, MEMORY_STORE_SCOPE.subject),
1169
+ longTermPattern("Org-wide knowledge or how to perform a task", MEMORY_TYPE.procedural, MEMORY_SEGMENT.tool, MEMORY_STORE_SCOPE.organization)
1170
+ ];
1171
+ function renderMemoryPattern(pattern) {
1172
+ return `- ${pattern.label}: \`system="${pattern.system}"\`, \`type="${pattern.type}"\`, \`segment="${pattern.segment}"\`, \`scope="${pattern.scope}"\``;
1173
+ }
1174
+ var MEMORY_COMMON_PATTERNS = [
1175
+ "Common patterns:",
1176
+ ...COMMON_MEMORY_PATTERNS.map(renderMemoryPattern)
1177
+ ].join("\n");
1178
+ var MEMORY_SCOPE_GUIDANCE = `Prefer \`scope="${MEMORY_STORE_SCOPE.subject}"\` whenever the memory is about a specific person or agent, so it
1179
+ stays attached to that subject rather than leaking org-wide. Storing with \`scope="${MEMORY_STORE_SCOPE.subject}"\` requires a
1180
+ real \`subject_id\` UUID, so resolve it first via \`thenvoi_lookup_peers\` or the participant list.
1181
+ Reserve \`scope="${MEMORY_STORE_SCOPE.organization}"\` for knowledge that is genuinely shared across the whole organization and
1182
+ is not about any one subject.`;
1183
+ function quoteChoices(values) {
1184
+ return values.map((value) => `\`"${value}"\``).join(" | ");
1185
+ }
1186
+ function memoryTypeLines() {
1187
+ return Object.entries(MEMORY_SYSTEM_TYPES).map(([system, types]) => ` - ${system}: ${quoteChoices(types)}`).join("\n");
1188
+ }
1189
+ function buildMemorySection() {
1190
+ const storeMemoryProps = TOOL_MODELS.thenvoi_store_memory.properties;
1191
+ const systems = storeMemoryProps.system.enum;
1192
+ const segments = storeMemoryProps.segment.enum;
1193
+ const scopes = storeMemoryProps.scope.enum;
1194
+ const fieldRules = `When calling \`thenvoi_store_memory\`, the \`system\`, \`type\`, \`segment\`, and \`scope\` fields
1195
+ must use these exact values (case-sensitive):
1196
+
1197
+ - **system**: ${quoteChoices(systems)}
1198
+ - **type** (must match the chosen system):
1199
+ ${memoryTypeLines()}
1200
+ - **segment**: ${quoteChoices(segments)}
1201
+ - **scope**: ${quoteChoices(scopes)}`;
1202
+ return [MEMORY_INTRO, fieldRules, MEMORY_COMMON_PATTERNS, MEMORY_SCOPE_GUIDANCE].join("\n\n");
1203
+ }
1204
+ var MEMORY_SECTION = buildMemorySection();
1205
+
1206
+ // src/runtime/prompts/templates.ts
875
1207
  var TEMPLATES = {
876
1208
  default: `You are {agent_name}, {agent_description}.
877
1209
 
@@ -890,7 +1222,13 @@ ${customSection}`.trim();
890
1222
  }
891
1223
  const template = options?.template ?? "default";
892
1224
  const templateString = TEMPLATES[template] ?? TEMPLATES.default;
893
- return templateString.replaceAll("{agent_name}", agentName).replaceAll("{agent_description}", agentDescription).replaceAll("{custom_section}", customSection);
1225
+ const parts = [
1226
+ templateString.replaceAll("{agent_name}", agentName).replaceAll("{agent_description}", agentDescription).replaceAll("{custom_section}", customSection)
1227
+ ];
1228
+ if (options?.capabilities?.memory) {
1229
+ parts.push(MEMORY_SECTION);
1230
+ }
1231
+ return parts.join("\n\n");
894
1232
  }
895
1233
 
896
1234
  // src/mcp/server.ts
@@ -2971,7 +3309,7 @@ function replaceUuidMentions(content, participants) {
2971
3309
  const participantId = participant.id;
2972
3310
  const handle = participant.handle;
2973
3311
  if (typeof participantId === "string" && typeof handle === "string") {
2974
- next = next.replaceAll(`@[[${participantId}]]`, `@${handle}`);
3312
+ next = next.replaceAll(`@[[${participantId}]]`, ensureHandlePrefix(handle) ?? "");
2975
3313
  }
2976
3314
  }
2977
3315
  return next;
@@ -4390,7 +4728,8 @@ var GoogleADKAdapter = class extends SimpleAdapter {
4390
4728
  this.systemPrompt = this.systemPromptOverride ?? renderSystemPrompt({
4391
4729
  agentName,
4392
4730
  agentDescription,
4393
- customSection: this.customSection
4731
+ customSection: this.customSection,
4732
+ capabilities: { memory: this.enableMemoryTools }
4394
4733
  });
4395
4734
  }
4396
4735
  async onMessage(message, tools, history, participantsMessage, contactsMessage, context) {
@@ -4630,7 +4969,8 @@ var LangGraphAdapter = class extends SimpleAdapter {
4630
4969
  this.renderedSystemPrompt = this.systemPromptOverride ?? renderSystemPrompt({
4631
4970
  agentName,
4632
4971
  agentDescription,
4633
- customSection: this.customSection
4972
+ customSection: this.customSection,
4973
+ capabilities: { memory: this.includeMemoryTools }
4634
4974
  });
4635
4975
  }
4636
4976
  async onMessage(message, tools, history, participantsMessage, contactsMessage, context) {
@@ -4649,14 +4989,17 @@ var LangGraphAdapter = class extends SimpleAdapter {
4649
4989
  ];
4650
4990
  }
4651
4991
  const graph = await this.resolveGraph(sdk, langGraphTools);
4652
- const messages = this.buildMessages(
4653
- history,
4654
- message,
4655
- participantsMessage,
4656
- contactsMessage,
4657
- context.isSessionBootstrap,
4658
- context.roomId
4659
- );
4992
+ const usesCheckpointer = Boolean(this.checkpointer);
4993
+ const isFirstBootstrap = context.isSessionBootstrap && !this.bootstrappedRooms.has(context.roomId);
4994
+ const replayHistory = !usesCheckpointer || isFirstBootstrap;
4995
+ const includeSystemPrompt = this.usesCustomGraph && (!usesCheckpointer || isFirstBootstrap);
4996
+ if (context.isSessionBootstrap) {
4997
+ this.bootstrappedRooms.add(context.roomId);
4998
+ }
4999
+ const messages = this.buildMessages(history, message, participantsMessage, contactsMessage, {
5000
+ replayHistory,
5001
+ includeSystemPrompt
5002
+ });
4660
5003
  const input = { messages };
4661
5004
  const graphConfig = {
4662
5005
  configurable: {
@@ -4683,6 +5026,10 @@ var LangGraphAdapter = class extends SimpleAdapter {
4683
5026
  async onCleanup(roomId) {
4684
5027
  this.bootstrappedRooms.delete(roomId);
4685
5028
  }
5029
+ /** A caller-supplied graph rather than the built-in createReactAgent. */
5030
+ get usesCustomGraph() {
5031
+ return Boolean(this.graph || this.graphFactory);
5032
+ }
4686
5033
  resolveGraph(sdk, langGraphTools) {
4687
5034
  if (this.graphFactory) {
4688
5035
  return Promise.resolve(this.graphFactory(langGraphTools));
@@ -4703,14 +5050,13 @@ var LangGraphAdapter = class extends SimpleAdapter {
4703
5050
  prompt: this.renderedSystemPrompt
4704
5051
  }));
4705
5052
  }
4706
- buildMessages(history, message, participantsMessage, contactsMessage, isSessionBootstrap, roomId) {
5053
+ buildMessages(history, message, participantsMessage, contactsMessage, options) {
4707
5054
  const messages = [];
4708
- if (isSessionBootstrap && !this.bootstrappedRooms.has(roomId)) {
5055
+ if (options.includeSystemPrompt) {
4709
5056
  messages.push(["system", this.renderedSystemPrompt]);
4710
- this.bootstrappedRooms.add(roomId);
4711
5057
  }
4712
- if (isSessionBootstrap && history.length > 0) {
4713
- const historical = history.raw.slice(-this.maxHistoryMessages);
5058
+ if (options.replayHistory && history.length > 0) {
5059
+ const historical = history.raw.filter((item) => item.id !== message.id).slice(-this.maxHistoryMessages);
4714
5060
  for (const item of historical) {
4715
5061
  const role = String(item.sender_type ?? "") === "Agent" ? "assistant" : "user";
4716
5062
  const content = String(item.content ?? "");
@@ -4729,7 +5075,7 @@ var LangGraphAdapter = class extends SimpleAdapter {
4729
5075
  return messages;
4730
5076
  }
4731
5077
  async forwardStreamEvents(graph, input, config, tools) {
4732
- const stream = graph.streamEvents?.(input, config, { version: "v2" });
5078
+ const stream = graph.streamEvents?.(input, { ...config, version: "v2" });
4733
5079
  if (!stream) {
4734
5080
  return null;
4735
5081
  }
@@ -4756,6 +5102,10 @@ var LangGraphAdapter = class extends SimpleAdapter {
4756
5102
  );
4757
5103
  }
4758
5104
  if (eventType === "on_chain_end") {
5105
+ const chainName = String(data.name ?? "");
5106
+ if (!this.usesCustomGraph && chainName !== "LangGraph" && chainName !== "agent") {
5107
+ continue;
5108
+ }
4759
5109
  const output = asOptionalRecord(data.data) ?? {};
4760
5110
  const text = extractAssistantText(output.output);
4761
5111
  if (text) {
@@ -4817,18 +5167,25 @@ function stringifyToolResult2(value, logger, toolName) {
4817
5167
  });
4818
5168
  }
4819
5169
  function extractAssistantText(result) {
4820
- if (typeof result === "string" && result.trim().length > 0) {
4821
- return result.trim();
5170
+ if (typeof result === "string") {
5171
+ const trimmed = result.trim();
5172
+ return trimmed.length > 0 && !isInternalLangGraphMarker(trimmed) ? trimmed : null;
4822
5173
  }
4823
5174
  const record = asOptionalRecord(result) ?? {};
5175
+ if (isLangChainAssistantMessage(record)) {
5176
+ const text = asLangChainMessageContent(record);
5177
+ if (text && !isInternalLangGraphMarker(text)) {
5178
+ return text;
5179
+ }
5180
+ }
4824
5181
  const directContent = asMessageContent(record.content);
4825
- if (directContent) {
5182
+ if (directContent && !isInternalLangGraphMarker(directContent)) {
4826
5183
  return directContent;
4827
5184
  }
4828
5185
  const messages = Array.isArray(record.messages) ? record.messages : [];
4829
5186
  for (let index = messages.length - 1; index >= 0; index -= 1) {
4830
5187
  const text = asMessageText(messages[index]);
4831
- if (text) {
5188
+ if (text && !isInternalLangGraphMarker(text)) {
4832
5189
  return text;
4833
5190
  }
4834
5191
  }
@@ -4845,12 +5202,40 @@ function asMessageText(value) {
4845
5202
  if (!record) {
4846
5203
  return null;
4847
5204
  }
5205
+ if (isLangChainAssistantMessage(record)) {
5206
+ return asLangChainMessageContent(record);
5207
+ }
4848
5208
  const role = String(record.role ?? "");
4849
5209
  if (role !== "assistant") {
4850
5210
  return null;
4851
5211
  }
4852
5212
  return asMessageContent(record.content);
4853
5213
  }
5214
+ function isLangChainAssistantMessage(record) {
5215
+ const id = record.id;
5216
+ if (Array.isArray(id)) {
5217
+ const typeName = String(id[id.length - 1] ?? "");
5218
+ if (typeName === "AIMessage" || typeName === "AIMessageChunk") {
5219
+ return true;
5220
+ }
5221
+ }
5222
+ const getType = record.getType;
5223
+ if (typeof getType === "function") {
5224
+ try {
5225
+ return getType.call(record) === "ai";
5226
+ } catch {
5227
+ return false;
5228
+ }
5229
+ }
5230
+ return false;
5231
+ }
5232
+ function asLangChainMessageContent(record) {
5233
+ const kwargs = asOptionalRecord(record.kwargs);
5234
+ return asMessageContent(kwargs?.content ?? record.content);
5235
+ }
5236
+ function isInternalLangGraphMarker(text) {
5237
+ return text === "__end__" || text === "__start__";
5238
+ }
4854
5239
  function asMessageContent(value) {
4855
5240
  if (typeof value === "string" && value.trim().length > 0) {
4856
5241
  return value.trim();
@@ -7804,20 +8189,17 @@ function registerTools3(mcpServer, z4, registrations) {
7804
8189
 
7805
8190
  // src/mcp/backends.ts
7806
8191
  async function createThenvoiMcpBackend(options) {
7807
- const registrations = buildRoomScopedRegistrations(
7808
- options.getToolsForRoom,
7809
- {
7810
- enableMemoryTools: options.enableMemoryTools,
7811
- enableContactTools: true,
7812
- additionalTools: options.additionalTools
7813
- }
7814
- );
7815
- const allowedTools = mcpToolNames(new Set(registrations.map((registration) => registration.name)));
8192
+ const registrationOptions = {
8193
+ enableMemoryTools: options.enableMemoryTools,
8194
+ enableContactTools: true,
8195
+ additionalTools: options.additionalTools
8196
+ };
7816
8197
  if (options.kind === "sdk") {
7817
8198
  const { createThenvoiSdkMcpServer: createThenvoiSdkMcpServer2 } = await Promise.resolve().then(() => (init_sdk(), sdk_exports));
7818
8199
  const server2 = createThenvoiSdkMcpServer2({
7819
- enableMemoryTools: options.enableMemoryTools,
7820
8200
  getToolsForRoom: options.getToolsForRoom,
8201
+ multiRoom: options.multiRoom,
8202
+ enableMemoryTools: options.enableMemoryTools,
7821
8203
  additionalTools: options.additionalTools
7822
8204
  });
7823
8205
  return {
@@ -7827,9 +8209,12 @@ async function createThenvoiMcpBackend(options) {
7827
8209
  stop: async () => void 0
7828
8210
  };
7829
8211
  }
8212
+ const resolvedTools = options.multiRoom === false ? resolveSingleRoomTools(options.getToolsForRoom) : options.getToolsForRoom;
8213
+ const registrations = options.multiRoom === false ? buildSingleContextRegistrations(resolvedTools, registrationOptions) : buildRoomScopedRegistrations(resolvedTools, registrationOptions);
8214
+ const allowedTools = mcpToolNames(new Set(registrations.map((registration) => registration.name)));
7830
8215
  if (options.kind === "stdio") {
7831
8216
  const server2 = new ThenvoiMcpStdioServer({
7832
- tools: options.getToolsForRoom,
8217
+ tools: resolvedTools,
7833
8218
  enableMemoryTools: options.enableMemoryTools,
7834
8219
  enableContactTools: true,
7835
8220
  additionalTools: options.additionalTools
@@ -7846,7 +8231,7 @@ async function createThenvoiMcpBackend(options) {
7846
8231
  }
7847
8232
  if (options.kind === "sse") {
7848
8233
  const server2 = new ThenvoiMcpSseServer({
7849
- tools: options.getToolsForRoom,
8234
+ tools: resolvedTools,
7850
8235
  enableMemoryTools: options.enableMemoryTools,
7851
8236
  enableContactTools: true,
7852
8237
  additionalTools: options.additionalTools
@@ -7862,7 +8247,7 @@ async function createThenvoiMcpBackend(options) {
7862
8247
  };
7863
8248
  }
7864
8249
  const server = new ThenvoiMcpServer({
7865
- tools: options.getToolsForRoom,
8250
+ tools: resolvedTools,
7866
8251
  enableMemoryTools: options.enableMemoryTools,
7867
8252
  enableContactTools: true,
7868
8253
  additionalTools: options.additionalTools
@@ -8302,7 +8687,8 @@ var OpencodeAdapter = class extends SimpleAdapter {
8302
8687
  agentName,
8303
8688
  agentDescription,
8304
8689
  customSection: this.config.customSection,
8305
- includeBaseInstructions: this.config.includeBaseInstructions
8690
+ includeBaseInstructions: this.config.includeBaseInstructions,
8691
+ capabilities: { memory: this.config.enableMemoryTools }
8306
8692
  }).trim();
8307
8693
  this.systemPrompt = `${systemPrompt}
8308
8694
 
@@ -9169,7 +9555,8 @@ var ClaudeSDKAdapter = class extends SimpleAdapter {
9169
9555
  agentName,
9170
9556
  agentDescription,
9171
9557
  customSection: this.customSection,
9172
- includeBaseInstructions: this.includeBaseInstructions
9558
+ includeBaseInstructions: this.includeBaseInstructions,
9559
+ capabilities: { memory: this.enableMemoryTools }
9173
9560
  });
9174
9561
  if (this.enableMcpTools) {
9175
9562
  const createThenvoiMcpBridge = await thenvoiMcpBridgeFactory.get();
@@ -9889,7 +10276,8 @@ var CodexAdapter = class extends SimpleAdapter {
9889
10276
  agentName: this.agentName,
9890
10277
  agentDescription: this.agentDescription,
9891
10278
  customSection,
9892
- includeBaseInstructions: this.baseConfig.includeBaseInstructions ?? true
10279
+ includeBaseInstructions: this.baseConfig.includeBaseInstructions ?? true,
10280
+ capabilities: { memory: this.includeMemoryTools }
9893
10281
  }).trim();
9894
10282
  this.systemPrompt = prompt.length > 0 ? prompt : null;
9895
10283
  }