@cogitator-ai/swarms 0.4.20 → 0.5.1

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 (134) hide show
  1. package/README.md +245 -897
  2. package/dist/agents.d.ts +13 -0
  3. package/dist/agents.d.ts.map +1 -0
  4. package/dist/agents.js +70 -0
  5. package/dist/agents.js.map +1 -0
  6. package/dist/assessor/assessor.d.ts +9 -2
  7. package/dist/assessor/assessor.d.ts.map +1 -1
  8. package/dist/assessor/assessor.js +71 -52
  9. package/dist/assessor/assessor.js.map +1 -1
  10. package/dist/assessor/role-matcher.d.ts +6 -24
  11. package/dist/assessor/role-matcher.d.ts.map +1 -1
  12. package/dist/assessor/role-matcher.js +9 -37
  13. package/dist/assessor/role-matcher.js.map +1 -1
  14. package/dist/base-coordinator.d.ts +117 -0
  15. package/dist/base-coordinator.d.ts.map +1 -0
  16. package/dist/base-coordinator.js +455 -0
  17. package/dist/base-coordinator.js.map +1 -0
  18. package/dist/communication/blackboard.d.ts +34 -4
  19. package/dist/communication/blackboard.d.ts.map +1 -1
  20. package/dist/communication/blackboard.js +81 -46
  21. package/dist/communication/blackboard.js.map +1 -1
  22. package/dist/communication/event-emitter.d.ts.map +1 -1
  23. package/dist/communication/event-emitter.js +6 -17
  24. package/dist/communication/event-emitter.js.map +1 -1
  25. package/dist/communication/index.d.ts +2 -2
  26. package/dist/communication/index.d.ts.map +1 -1
  27. package/dist/communication/index.js +2 -2
  28. package/dist/communication/index.js.map +1 -1
  29. package/dist/communication/message-bus.d.ts +48 -5
  30. package/dist/communication/message-bus.d.ts.map +1 -1
  31. package/dist/communication/message-bus.js +135 -50
  32. package/dist/communication/message-bus.js.map +1 -1
  33. package/dist/communication/redis-blackboard.d.ts +11 -5
  34. package/dist/communication/redis-blackboard.d.ts.map +1 -1
  35. package/dist/communication/redis-blackboard.js +159 -116
  36. package/dist/communication/redis-blackboard.js.map +1 -1
  37. package/dist/communication/redis-event-emitter.d.ts +12 -0
  38. package/dist/communication/redis-event-emitter.d.ts.map +1 -1
  39. package/dist/communication/redis-event-emitter.js +96 -54
  40. package/dist/communication/redis-event-emitter.js.map +1 -1
  41. package/dist/communication/redis-message-bus.d.ts +11 -6
  42. package/dist/communication/redis-message-bus.d.ts.map +1 -1
  43. package/dist/communication/redis-message-bus.js +88 -77
  44. package/dist/communication/redis-message-bus.js.map +1 -1
  45. package/dist/coordinator.d.ts +7 -41
  46. package/dist/coordinator.d.ts.map +1 -1
  47. package/dist/coordinator.js +17 -340
  48. package/dist/coordinator.js.map +1 -1
  49. package/dist/distributed/distributed-coordinator.d.ts +54 -51
  50. package/dist/distributed/distributed-coordinator.d.ts.map +1 -1
  51. package/dist/distributed/distributed-coordinator.js +166 -284
  52. package/dist/distributed/distributed-coordinator.js.map +1 -1
  53. package/dist/distributed/index.d.ts +1 -1
  54. package/dist/distributed/index.d.ts.map +1 -1
  55. package/dist/distributed/index.js +1 -1
  56. package/dist/distributed/index.js.map +1 -1
  57. package/dist/index.d.ts +4 -3
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +4 -3
  60. package/dist/index.js.map +1 -1
  61. package/dist/resources/circuit-breaker.d.ts.map +1 -1
  62. package/dist/resources/circuit-breaker.js +3 -4
  63. package/dist/resources/circuit-breaker.js.map +1 -1
  64. package/dist/shared/hierarchy.d.ts +21 -0
  65. package/dist/shared/hierarchy.d.ts.map +1 -0
  66. package/dist/shared/hierarchy.js +27 -0
  67. package/dist/shared/hierarchy.js.map +1 -0
  68. package/dist/shared/negotiation.d.ts +27 -0
  69. package/dist/shared/negotiation.d.ts.map +1 -0
  70. package/dist/shared/negotiation.js +55 -0
  71. package/dist/shared/negotiation.js.map +1 -0
  72. package/dist/shared/voting.d.ts +6 -0
  73. package/dist/shared/voting.d.ts.map +1 -0
  74. package/dist/shared/voting.js +13 -0
  75. package/dist/shared/voting.js.map +1 -0
  76. package/dist/strategies/consensus.d.ts +12 -0
  77. package/dist/strategies/consensus.d.ts.map +1 -1
  78. package/dist/strategies/consensus.js +75 -47
  79. package/dist/strategies/consensus.js.map +1 -1
  80. package/dist/strategies/debate.d.ts.map +1 -1
  81. package/dist/strategies/debate.js +18 -8
  82. package/dist/strategies/debate.js.map +1 -1
  83. package/dist/strategies/hierarchical.d.ts.map +1 -1
  84. package/dist/strategies/hierarchical.js +29 -14
  85. package/dist/strategies/hierarchical.js.map +1 -1
  86. package/dist/strategies/negotiation/approval.d.ts.map +1 -1
  87. package/dist/strategies/negotiation/approval.js +22 -19
  88. package/dist/strategies/negotiation/approval.js.map +1 -1
  89. package/dist/strategies/negotiation-strategy.d.ts +24 -2
  90. package/dist/strategies/negotiation-strategy.d.ts.map +1 -1
  91. package/dist/strategies/negotiation-strategy.js +276 -141
  92. package/dist/strategies/negotiation-strategy.js.map +1 -1
  93. package/dist/strategies/pipeline.js +6 -6
  94. package/dist/strategies/pipeline.js.map +1 -1
  95. package/dist/swarm.d.ts +25 -11
  96. package/dist/swarm.d.ts.map +1 -1
  97. package/dist/swarm.js +195 -121
  98. package/dist/swarm.js.map +1 -1
  99. package/dist/tools/blackboard.d.ts +1 -1
  100. package/dist/tools/blackboard.d.ts.map +1 -1
  101. package/dist/tools/blackboard.js +26 -12
  102. package/dist/tools/blackboard.js.map +1 -1
  103. package/dist/tools/delegation.d.ts +17 -4
  104. package/dist/tools/delegation.d.ts.map +1 -1
  105. package/dist/tools/delegation.js +95 -88
  106. package/dist/tools/delegation.js.map +1 -1
  107. package/dist/tools/index.d.ts +3 -1
  108. package/dist/tools/index.d.ts.map +1 -1
  109. package/dist/tools/index.js +9 -4
  110. package/dist/tools/index.js.map +1 -1
  111. package/dist/tools/messaging.d.ts +38 -6
  112. package/dist/tools/messaging.d.ts.map +1 -1
  113. package/dist/tools/messaging.js +118 -41
  114. package/dist/tools/messaging.js.map +1 -1
  115. package/dist/tools/negotiation.d.ts +8 -4
  116. package/dist/tools/negotiation.d.ts.map +1 -1
  117. package/dist/tools/negotiation.js +138 -115
  118. package/dist/tools/negotiation.js.map +1 -1
  119. package/dist/tools/voting.d.ts +3 -0
  120. package/dist/tools/voting.d.ts.map +1 -1
  121. package/dist/tools/voting.js +13 -12
  122. package/dist/tools/voting.js.map +1 -1
  123. package/dist/utils/concurrency.d.ts +10 -0
  124. package/dist/utils/concurrency.d.ts.map +1 -0
  125. package/dist/utils/concurrency.js +28 -0
  126. package/dist/utils/concurrency.js.map +1 -0
  127. package/dist/utils/invoke.d.ts +2 -0
  128. package/dist/utils/invoke.d.ts.map +1 -0
  129. package/dist/utils/invoke.js +19 -0
  130. package/dist/utils/invoke.js.map +1 -0
  131. package/dist/workflow/swarm-node.d.ts.map +1 -1
  132. package/dist/workflow/swarm-node.js +55 -98
  133. package/dist/workflow/swarm-node.js.map +1 -1
  134. package/package.json +6 -6
@@ -1,10 +1,55 @@
1
1
  /**
2
2
  * Blackboard for shared state between agents
3
3
  */
4
+ import { invokeSafely } from '../utils/invoke.js';
5
+ export function isObservableBlackboard(blackboard) {
6
+ return typeof blackboard.onWrite === 'function';
7
+ }
8
+ export class BlackboardListeners {
9
+ label;
10
+ sectionHandlers = new Map();
11
+ writeListeners = new Set();
12
+ constructor(label) {
13
+ this.label = label;
14
+ }
15
+ subscribe(section, handler) {
16
+ let handlers = this.sectionHandlers.get(section);
17
+ if (!handlers) {
18
+ handlers = new Set();
19
+ this.sectionHandlers.set(section, handlers);
20
+ }
21
+ handlers.add(handler);
22
+ return () => {
23
+ const current = this.sectionHandlers.get(section);
24
+ if (!current)
25
+ return;
26
+ current.delete(handler);
27
+ if (current.size === 0) {
28
+ this.sectionHandlers.delete(section);
29
+ }
30
+ };
31
+ }
32
+ onWrite(listener) {
33
+ this.writeListeners.add(listener);
34
+ return () => {
35
+ this.writeListeners.delete(listener);
36
+ };
37
+ }
38
+ notify(write) {
39
+ if (!write.deleted) {
40
+ for (const handler of [...(this.sectionHandlers.get(write.section) ?? [])]) {
41
+ invokeSafely(handler, [write.data, write.agentName], `${this.label} Handler error`);
42
+ }
43
+ }
44
+ for (const listener of [...this.writeListeners]) {
45
+ invokeSafely(listener, [write], `${this.label} Write listener error`);
46
+ }
47
+ }
48
+ }
4
49
  export class InMemoryBlackboard {
5
50
  sections = new Map();
6
51
  history = new Map();
7
- subscriptions = new Map();
52
+ listeners = new BlackboardListeners('[Blackboard]');
8
53
  config;
9
54
  constructor(config) {
10
55
  this.config = config;
@@ -29,9 +74,7 @@ export class InMemoryBlackboard {
29
74
  }
30
75
  }
31
76
  read(section) {
32
- if (!this.config.enabled) {
33
- throw new Error('Blackboard is not enabled');
34
- }
77
+ this.assertEnabled();
35
78
  const sec = this.sections.get(section);
36
79
  if (!sec) {
37
80
  throw new Error(`Blackboard section '${section}' not found`);
@@ -39,34 +82,29 @@ export class InMemoryBlackboard {
39
82
  return sec.data;
40
83
  }
41
84
  write(section, data, agentName) {
42
- if (!this.config.enabled) {
43
- throw new Error('Blackboard is not enabled');
44
- }
85
+ this.assertEnabled();
45
86
  const existing = this.sections.get(section);
46
87
  const version = existing ? existing.version + 1 : 1;
47
88
  const timestamp = Date.now();
48
- const newSection = {
89
+ this.sections.set(section, {
49
90
  name: section,
50
91
  data,
51
92
  lastModified: timestamp,
52
93
  modifiedBy: agentName,
53
94
  version,
54
- };
55
- this.sections.set(section, newSection);
95
+ });
56
96
  if (this.config.trackHistory) {
57
- if (!this.history.has(section)) {
58
- this.history.set(section, []);
97
+ let entries = this.history.get(section);
98
+ if (!entries) {
99
+ entries = [];
100
+ this.history.set(section, entries);
59
101
  }
60
- this.history.get(section).push({
61
- value: data,
62
- writtenBy: agentName,
63
- timestamp,
64
- version,
65
- });
102
+ entries.push({ value: data, writtenBy: agentName, timestamp, version });
66
103
  }
67
- this.notifySubscribers(section, data, agentName);
104
+ this.listeners.notify({ section, data, agentName, version });
68
105
  }
69
106
  append(section, item, agentName) {
107
+ this.assertEnabled();
70
108
  const current = this.sections.get(section);
71
109
  if (!current) {
72
110
  this.write(section, [item], agentName);
@@ -75,31 +113,30 @@ export class InMemoryBlackboard {
75
113
  if (!Array.isArray(current.data)) {
76
114
  throw new Error(`Section '${section}' is not an array, cannot append`);
77
115
  }
78
- const newData = [...current.data, item];
79
- this.write(section, newData, agentName);
116
+ this.write(section, [...current.data, item], agentName);
80
117
  }
81
118
  has(section) {
82
119
  return this.sections.has(section);
83
120
  }
84
121
  delete(section) {
122
+ const existing = this.sections.get(section);
85
123
  this.sections.delete(section);
86
124
  this.history.delete(section);
87
- this.subscriptions.delete(section);
125
+ if (existing) {
126
+ this.listeners.notify({
127
+ section,
128
+ data: undefined,
129
+ agentName: 'system',
130
+ version: existing.version,
131
+ deleted: true,
132
+ });
133
+ }
88
134
  }
89
135
  subscribe(section, handler) {
90
- if (!this.subscriptions.has(section)) {
91
- this.subscriptions.set(section, new Set());
92
- }
93
- this.subscriptions.get(section).add(handler);
94
- return () => {
95
- const handlers = this.subscriptions.get(section);
96
- if (handlers) {
97
- handlers.delete(handler);
98
- if (handlers.size === 0) {
99
- this.subscriptions.delete(section);
100
- }
101
- }
102
- };
136
+ return this.listeners.subscribe(section, handler);
137
+ }
138
+ onWrite(listener) {
139
+ return this.listeners.onWrite(listener);
103
140
  }
104
141
  getSections() {
105
142
  return Array.from(this.sections.keys());
@@ -108,21 +145,19 @@ export class InMemoryBlackboard {
108
145
  return this.sections.get(section);
109
146
  }
110
147
  getHistory(section) {
111
- return this.history.get(section) ?? [];
148
+ return [...(this.history.get(section) ?? [])];
112
149
  }
150
+ /**
151
+ * Remove all sections and history. Subscriptions are preserved so listeners
152
+ * keep working across swarm resets.
153
+ */
113
154
  clear() {
114
155
  this.sections.clear();
115
156
  this.history.clear();
116
- this.subscriptions.clear();
117
- }
118
- notifySubscribers(section, data, agentName) {
119
- const handlers = this.subscriptions.get(section);
120
- if (handlers) {
121
- for (const handler of handlers) {
122
- void Promise.resolve(handler(data, agentName)).catch((error) => {
123
- console.warn('[Blackboard] Handler error:', error);
124
- });
125
- }
157
+ }
158
+ assertEnabled() {
159
+ if (!this.config.enabled) {
160
+ throw new Error('Blackboard is not enabled');
126
161
  }
127
162
  }
128
163
  }
@@ -1 +1 @@
1
- {"version":3,"file":"blackboard.js","sourceRoot":"","sources":["../../src/communication/blackboard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"blackboard.js","sourceRoot":"","sources":["../../src/communication/blackboard.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"event-emitter.d.ts","sourceRoot":"","sources":["../../src/communication/event-emitter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,UAAU,EACV,iBAAiB,EAClB,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,qBAAsB,YAAW,iBAAiB;IAC7D,OAAO,CAAC,QAAQ,CAA2D;IAC3E,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,SAAO;IAI5B,EAAE,CAAC,KAAK,EAAE,cAAc,GAAG,GAAG,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,IAAI;IASvE,IAAI,CAAC,KAAK,EAAE,cAAc,GAAG,GAAG,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,IAAI;IAUzE,IAAI,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAiCrE,GAAG,CAAC,KAAK,EAAE,cAAc,GAAG,GAAG,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAUlE,kBAAkB,CAAC,KAAK,CAAC,EAAE,cAAc,GAAG,IAAI;IAQhD,SAAS,IAAI,UAAU,EAAE;IAIzB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,UAAU,EAAE;IAInD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,EAAE;IAIjD,WAAW,IAAI,IAAI;CAGpB"}
1
+ {"version":3,"file":"event-emitter.d.ts","sourceRoot":"","sources":["../../src/communication/event-emitter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,UAAU,EACV,iBAAiB,EAClB,MAAM,qBAAqB,CAAC;AAG7B,qBAAa,qBAAsB,YAAW,iBAAiB;IAC7D,OAAO,CAAC,QAAQ,CAA2D;IAC3E,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,SAAO;IAI5B,EAAE,CAAC,KAAK,EAAE,cAAc,GAAG,GAAG,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,IAAI;IASvE,IAAI,CAAC,KAAK,EAAE,cAAc,GAAG,GAAG,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,IAAI;IAQzE,IAAI,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAuBrE,GAAG,CAAC,KAAK,EAAE,cAAc,GAAG,GAAG,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAUlE,kBAAkB,CAAC,KAAK,CAAC,EAAE,cAAc,GAAG,IAAI;IAQhD,SAAS,IAAI,UAAU,EAAE;IAIzB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,UAAU,EAAE;IAInD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,EAAE;IAIjD,WAAW,IAAI,IAAI;CAGpB"}
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Event emitter for swarm coordination
3
3
  */
4
+ import { invokeSafely } from '../utils/invoke.js';
4
5
  export class SwarmEventEmitterImpl {
5
6
  handlers = new Map();
6
7
  events = [];
@@ -18,9 +19,7 @@ export class SwarmEventEmitterImpl {
18
19
  once(event, handler) {
19
20
  const wrapper = (e) => {
20
21
  this.off(event, wrapper);
21
- void Promise.resolve(handler(e)).catch((error) => {
22
- console.warn('[SwarmEventEmitter] Once handler error:', error);
23
- });
22
+ invokeSafely(handler, [e], '[SwarmEventEmitter] Once handler error');
24
23
  };
25
24
  return this.on(event, wrapper);
26
25
  }
@@ -35,21 +34,11 @@ export class SwarmEventEmitterImpl {
35
34
  if (this.events.length > this.maxEvents) {
36
35
  this.events = this.events.slice(-this.maxEvents);
37
36
  }
38
- const handlers = this.handlers.get(event);
39
- if (handlers) {
40
- for (const handler of handlers) {
41
- void Promise.resolve(handler(swarmEvent)).catch((error) => {
42
- console.warn('[SwarmEventEmitter] Handler error:', error);
43
- });
44
- }
37
+ for (const handler of [...(this.handlers.get(event) ?? [])]) {
38
+ invokeSafely(handler, [swarmEvent], '[SwarmEventEmitter] Handler error');
45
39
  }
46
- const wildcardHandlers = this.handlers.get('*');
47
- if (wildcardHandlers) {
48
- for (const handler of wildcardHandlers) {
49
- void Promise.resolve(handler(swarmEvent)).catch((error) => {
50
- console.warn('[SwarmEventEmitter] Wildcard handler error:', error);
51
- });
52
- }
40
+ for (const handler of [...(this.handlers.get('*') ?? [])]) {
41
+ invokeSafely(handler, [swarmEvent], '[SwarmEventEmitter] Wildcard handler error');
53
42
  }
54
43
  }
55
44
  off(event, handler) {
@@ -1 +1 @@
1
- {"version":3,"file":"event-emitter.js","sourceRoot":"","sources":["../../src/communication/event-emitter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"event-emitter.js","sourceRoot":"","sources":["../../src/communication/event-emitter.ts"],"names":[],"mappings":"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"}
@@ -2,8 +2,8 @@
2
2
  * Communication primitives for swarm coordination
3
3
  */
4
4
  export { SwarmEventEmitterImpl } from './event-emitter.js';
5
- export { InMemoryMessageBus, createMessageBus } from './message-bus.js';
6
- export { InMemoryBlackboard, createBlackboard } from './blackboard.js';
5
+ export { InMemoryMessageBus, createMessageBus, isReadTrackingMessageBus, type ReadTrackingMessageBus, type MessageListener, } from './message-bus.js';
6
+ export { InMemoryBlackboard, createBlackboard, isObservableBlackboard, type ObservableBlackboard, type BlackboardWrite, type BlackboardWriteListener, type BlackboardSectionHandler, } from './blackboard.js';
7
7
  export { RedisMessageBus, type RedisMessageBusOptions } from './redis-message-bus.js';
8
8
  export { RedisBlackboard, type RedisBlackboardOptions } from './redis-blackboard.js';
9
9
  export { RedisSwarmEventEmitter, type RedisEventEmitterOptions } from './redis-event-emitter.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/communication/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEvE,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACrF,OAAO,EAAE,sBAAsB,EAAE,KAAK,wBAAwB,EAAE,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/communication/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,wBAAwB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,eAAe,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,GAC9B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACrF,OAAO,EAAE,sBAAsB,EAAE,KAAK,wBAAwB,EAAE,MAAM,0BAA0B,CAAC"}
@@ -2,8 +2,8 @@
2
2
  * Communication primitives for swarm coordination
3
3
  */
4
4
  export { SwarmEventEmitterImpl } from './event-emitter.js';
5
- export { InMemoryMessageBus, createMessageBus } from './message-bus.js';
6
- export { InMemoryBlackboard, createBlackboard } from './blackboard.js';
5
+ export { InMemoryMessageBus, createMessageBus, isReadTrackingMessageBus, } from './message-bus.js';
6
+ export { InMemoryBlackboard, createBlackboard, isObservableBlackboard, } from './blackboard.js';
7
7
  export { RedisMessageBus } from './redis-message-bus.js';
8
8
  export { RedisBlackboard } from './redis-blackboard.js';
9
9
  export { RedisSwarmEventEmitter } from './redis-event-emitter.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/communication/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEvE,OAAO,EAAE,eAAe,EAA+B,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAE,eAAe,EAA+B,MAAM,uBAAuB,CAAC;AACrF,OAAO,EAAE,sBAAsB,EAAiC,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/communication/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,wBAAwB,GAGzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,GAKvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,eAAe,EAA+B,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAE,eAAe,EAA+B,MAAM,uBAAuB,CAAC;AACrF,OAAO,EAAE,sBAAsB,EAAiC,MAAM,0BAA0B,CAAC"}
@@ -2,22 +2,65 @@
2
2
  * Message bus for agent-to-agent communication
3
3
  */
4
4
  import type { MessageBus, MessageBusConfig, SwarmMessage } from '@cogitator-ai/types';
5
- export declare class InMemoryMessageBus implements MessageBus {
5
+ export type MessageListener = (msg: SwarmMessage) => void;
6
+ /**
7
+ * Message bus that remembers which messages each agent has already consumed.
8
+ */
9
+ export interface ReadTrackingMessageBus extends MessageBus {
10
+ markAsRead(agentName: string, messageIds: readonly string[]): void;
11
+ resetTurnCounts(agentName?: string): void;
12
+ onMessage(listener: MessageListener): () => void;
13
+ }
14
+ export declare function isReadTrackingMessageBus(bus: MessageBus): bus is ReadTrackingMessageBus;
15
+ export declare function isMessageForAgent(message: SwarmMessage, agentName: string): boolean;
16
+ /**
17
+ * Shared bookkeeping for message bus implementations: per-turn quotas,
18
+ * per-agent read receipts and bus-wide listeners.
19
+ */
20
+ export declare class MessageBusState {
21
+ private readonly label;
22
+ private turnCounts;
23
+ private readReceipts;
24
+ private listeners;
25
+ constructor(label: string);
26
+ consumeTurnQuota(config: MessageBusConfig, from: string): void;
27
+ resetTurnCounts(agentName?: string): void;
28
+ markAsRead(agentName: string, messageIds: readonly string[]): void;
29
+ isRead(agentName: string, messageId: string): boolean;
30
+ forgetMessages(messageIds: readonly string[]): void;
31
+ onMessage(listener: MessageListener): () => void;
32
+ notifyListeners(message: SwarmMessage): void;
33
+ clear(): void;
34
+ }
35
+ export declare function notifyMessageSubscribers(subscriptions: Map<string, Set<MessageListener>>, message: SwarmMessage, label: string): void;
36
+ export declare function addSubscription(subscriptions: Map<string, Set<MessageListener>>, agentName: string, handler: MessageListener): () => void;
37
+ export declare class InMemoryMessageBus implements ReadTrackingMessageBus {
6
38
  private messages;
7
39
  private subscriptions;
8
40
  private config;
9
- private agentMessageCounts;
41
+ private state;
10
42
  constructor(config: MessageBusConfig);
11
43
  send(message: Omit<SwarmMessage, 'id' | 'timestamp'>): Promise<SwarmMessage>;
12
44
  broadcast(from: string, content: string, channel?: string): Promise<void>;
13
- subscribe(agentName: string, handler: (msg: SwarmMessage) => void): () => void;
45
+ subscribe(agentName: string, handler: MessageListener): () => void;
46
+ /**
47
+ * Listen to every message sent through the bus, regardless of recipient.
48
+ */
49
+ onMessage(listener: MessageListener): () => void;
14
50
  getMessages(agentName: string, limit?: number): SwarmMessage[];
15
51
  getConversation(agent1: string, agent2: string): SwarmMessage[];
16
52
  getAllMessages(): SwarmMessage[];
53
+ /**
54
+ * Messages addressed to the agent (directly or via broadcast) that it has not read yet.
55
+ * Use {@link markAsRead} once the messages have been delivered to the agent.
56
+ */
17
57
  getUnreadMessages(agentName: string): SwarmMessage[];
58
+ markAsRead(agentName: string, messageIds: readonly string[]): void;
18
59
  clear(): void;
19
- resetTurnCounts(): void;
20
- private notifySubscribers;
60
+ /**
61
+ * Reset per-turn message quotas for one agent, or for all agents when omitted.
62
+ */
63
+ resetTurnCounts(agentName?: string): void;
21
64
  }
22
65
  export declare function createMessageBus(config?: Partial<MessageBusConfig>): MessageBus;
23
66
  //# sourceMappingURL=message-bus.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"message-bus.d.ts","sourceRoot":"","sources":["../../src/communication/message-bus.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEtF,qBAAa,kBAAmB,YAAW,UAAU;IACnD,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,aAAa,CAAuD;IAC5E,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,kBAAkB,CAA6B;gBAE3C,MAAM,EAAE,gBAAgB;IAI9B,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,WAAW,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC;IAmC5E,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW/E,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI;IAiB9E,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,YAAY,EAAE;IAW9D,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE;IAM/D,cAAc,IAAI,YAAY,EAAE;IAIhC,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,EAAE;IAMpD,KAAK,IAAI,IAAI;IAKb,eAAe,IAAI,IAAI;IAIvB,OAAO,CAAC,iBAAiB;CAsB1B;AAED,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,UAAU,CAM/E"}
1
+ {"version":3,"file":"message-bus.d.ts","sourceRoot":"","sources":["../../src/communication/message-bus.ts"],"names":[],"mappings":"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"}
@@ -2,11 +2,120 @@
2
2
  * Message bus for agent-to-agent communication
3
3
  */
4
4
  import { nanoid } from 'nanoid';
5
+ import { invokeSafely } from '../utils/invoke.js';
6
+ export function isReadTrackingMessageBus(bus) {
7
+ const candidate = bus;
8
+ return (typeof candidate.markAsRead === 'function' &&
9
+ typeof candidate.resetTurnCounts === 'function' &&
10
+ typeof candidate.onMessage === 'function');
11
+ }
12
+ export function isMessageForAgent(message, agentName) {
13
+ return (message.to === agentName || message.to === 'broadcast') && message.from !== agentName;
14
+ }
15
+ /**
16
+ * Shared bookkeeping for message bus implementations: per-turn quotas,
17
+ * per-agent read receipts and bus-wide listeners.
18
+ */
19
+ export class MessageBusState {
20
+ label;
21
+ turnCounts = new Map();
22
+ readReceipts = new Map();
23
+ listeners = new Set();
24
+ constructor(label) {
25
+ this.label = label;
26
+ }
27
+ consumeTurnQuota(config, from) {
28
+ if (!config.maxMessagesPerTurn)
29
+ return;
30
+ const count = this.turnCounts.get(from) ?? 0;
31
+ if (count >= config.maxMessagesPerTurn) {
32
+ throw new Error(`Agent ${from} exceeded max messages per turn (${config.maxMessagesPerTurn})`);
33
+ }
34
+ this.turnCounts.set(from, count + 1);
35
+ }
36
+ resetTurnCounts(agentName) {
37
+ if (agentName === undefined) {
38
+ this.turnCounts.clear();
39
+ }
40
+ else {
41
+ this.turnCounts.delete(agentName);
42
+ }
43
+ }
44
+ markAsRead(agentName, messageIds) {
45
+ let receipts = this.readReceipts.get(agentName);
46
+ if (!receipts) {
47
+ receipts = new Set();
48
+ this.readReceipts.set(agentName, receipts);
49
+ }
50
+ for (const id of messageIds) {
51
+ receipts.add(id);
52
+ }
53
+ }
54
+ isRead(agentName, messageId) {
55
+ return this.readReceipts.get(agentName)?.has(messageId) ?? false;
56
+ }
57
+ forgetMessages(messageIds) {
58
+ if (messageIds.length === 0)
59
+ return;
60
+ for (const receipts of this.readReceipts.values()) {
61
+ for (const id of messageIds) {
62
+ receipts.delete(id);
63
+ }
64
+ }
65
+ }
66
+ onMessage(listener) {
67
+ this.listeners.add(listener);
68
+ return () => {
69
+ this.listeners.delete(listener);
70
+ };
71
+ }
72
+ notifyListeners(message) {
73
+ for (const listener of [...this.listeners]) {
74
+ invokeSafely(listener, [message], `${this.label} Listener error`);
75
+ }
76
+ }
77
+ clear() {
78
+ this.turnCounts.clear();
79
+ this.readReceipts.clear();
80
+ }
81
+ }
82
+ export function notifyMessageSubscribers(subscriptions, message, label) {
83
+ if (message.to !== 'broadcast') {
84
+ for (const handler of [...(subscriptions.get(message.to) ?? [])]) {
85
+ invokeSafely(handler, [message], `${label} Handler error`);
86
+ }
87
+ return;
88
+ }
89
+ for (const [agentName, handlers] of subscriptions) {
90
+ if (agentName === message.from)
91
+ continue;
92
+ for (const handler of [...handlers]) {
93
+ invokeSafely(handler, [message], `${label} Broadcast handler error`);
94
+ }
95
+ }
96
+ }
97
+ export function addSubscription(subscriptions, agentName, handler) {
98
+ let handlers = subscriptions.get(agentName);
99
+ if (!handlers) {
100
+ handlers = new Set();
101
+ subscriptions.set(agentName, handlers);
102
+ }
103
+ handlers.add(handler);
104
+ return () => {
105
+ const current = subscriptions.get(agentName);
106
+ if (!current)
107
+ return;
108
+ current.delete(handler);
109
+ if (current.size === 0) {
110
+ subscriptions.delete(agentName);
111
+ }
112
+ };
113
+ }
5
114
  export class InMemoryMessageBus {
6
115
  messages = [];
7
116
  subscriptions = new Map();
8
117
  config;
9
- agentMessageCounts = new Map();
118
+ state = new MessageBusState('[MessageBus]');
10
119
  constructor(config) {
11
120
  this.config = config;
12
121
  }
@@ -17,23 +126,18 @@ export class InMemoryMessageBus {
17
126
  if (this.config.maxMessageLength && message.content.length > this.config.maxMessageLength) {
18
127
  throw new Error(`Message exceeds max length of ${this.config.maxMessageLength} characters`);
19
128
  }
20
- if (this.config.maxMessagesPerTurn) {
21
- const count = this.agentMessageCounts.get(message.from) ?? 0;
22
- if (count >= this.config.maxMessagesPerTurn) {
23
- throw new Error(`Agent ${message.from} exceeded max messages per turn (${this.config.maxMessagesPerTurn})`);
24
- }
25
- this.agentMessageCounts.set(message.from, count + 1);
26
- }
27
129
  if (this.config.maxTotalMessages && this.messages.length >= this.config.maxTotalMessages) {
28
130
  throw new Error(`Max total messages (${this.config.maxTotalMessages}) reached`);
29
131
  }
132
+ this.state.consumeTurnQuota(this.config, message.from);
30
133
  const fullMessage = {
31
134
  ...message,
32
135
  id: `msg_${nanoid(12)}`,
33
136
  timestamp: Date.now(),
34
137
  };
35
138
  this.messages.push(fullMessage);
36
- this.notifySubscribers(fullMessage);
139
+ notifyMessageSubscribers(this.subscriptions, fullMessage, '[MessageBus]');
140
+ this.state.notifyListeners(fullMessage);
37
141
  return fullMessage;
38
142
  }
39
143
  async broadcast(from, content, channel) {
@@ -47,19 +151,13 @@ export class InMemoryMessageBus {
47
151
  });
48
152
  }
49
153
  subscribe(agentName, handler) {
50
- if (!this.subscriptions.has(agentName)) {
51
- this.subscriptions.set(agentName, new Set());
52
- }
53
- this.subscriptions.get(agentName).add(handler);
54
- return () => {
55
- const handlers = this.subscriptions.get(agentName);
56
- if (handlers) {
57
- handlers.delete(handler);
58
- if (handlers.size === 0) {
59
- this.subscriptions.delete(agentName);
60
- }
61
- }
62
- };
154
+ return addSubscription(this.subscriptions, agentName, handler);
155
+ }
156
+ /**
157
+ * Listen to every message sent through the bus, regardless of recipient.
158
+ */
159
+ onMessage(listener) {
160
+ return this.state.onMessage(listener);
63
161
  }
64
162
  getMessages(agentName, limit) {
65
163
  const relevant = this.messages.filter((m) => m.to === agentName || m.to === 'broadcast' || m.from === agentName);
@@ -74,38 +172,25 @@ export class InMemoryMessageBus {
74
172
  getAllMessages() {
75
173
  return [...this.messages];
76
174
  }
175
+ /**
176
+ * Messages addressed to the agent (directly or via broadcast) that it has not read yet.
177
+ * Use {@link markAsRead} once the messages have been delivered to the agent.
178
+ */
77
179
  getUnreadMessages(agentName) {
78
- return this.messages.filter((m) => (m.to === agentName || m.to === 'broadcast') && m.from !== agentName);
180
+ return this.messages.filter((m) => isMessageForAgent(m, agentName) && !this.state.isRead(agentName, m.id));
181
+ }
182
+ markAsRead(agentName, messageIds) {
183
+ this.state.markAsRead(agentName, messageIds);
79
184
  }
80
185
  clear() {
81
186
  this.messages = [];
82
- this.agentMessageCounts.clear();
83
- }
84
- resetTurnCounts() {
85
- this.agentMessageCounts.clear();
86
- }
87
- notifySubscribers(message) {
88
- if (message.to !== 'broadcast') {
89
- const handlers = this.subscriptions.get(message.to);
90
- if (handlers) {
91
- for (const handler of handlers) {
92
- void Promise.resolve(handler(message)).catch((error) => {
93
- console.warn('[MessageBus] Handler error:', error);
94
- });
95
- }
96
- }
97
- }
98
- else {
99
- for (const [agentName, handlers] of this.subscriptions) {
100
- if (agentName !== message.from) {
101
- for (const handler of handlers) {
102
- void Promise.resolve(handler(message)).catch((error) => {
103
- console.warn('[MessageBus] Broadcast handler error:', error);
104
- });
105
- }
106
- }
107
- }
108
- }
187
+ this.state.clear();
188
+ }
189
+ /**
190
+ * Reset per-turn message quotas for one agent, or for all agents when omitted.
191
+ */
192
+ resetTurnCounts(agentName) {
193
+ this.state.resetTurnCounts(agentName);
109
194
  }
110
195
  }
111
196
  export function createMessageBus(config) {