society-protocol 1.0.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 (271) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/dist/adapters.d.ts +101 -0
  4. package/dist/adapters.d.ts.map +1 -0
  5. package/dist/adapters.js +764 -0
  6. package/dist/adapters.js.map +1 -0
  7. package/dist/agents-md.d.ts +59 -0
  8. package/dist/agents-md.d.ts.map +1 -0
  9. package/dist/agents-md.js +204 -0
  10. package/dist/agents-md.js.map +1 -0
  11. package/dist/autoconfig.d.ts +137 -0
  12. package/dist/autoconfig.d.ts.map +1 -0
  13. package/dist/autoconfig.js +452 -0
  14. package/dist/autoconfig.js.map +1 -0
  15. package/dist/bootstrap.d.ts +68 -0
  16. package/dist/bootstrap.d.ts.map +1 -0
  17. package/dist/bootstrap.js +304 -0
  18. package/dist/bootstrap.js.map +1 -0
  19. package/dist/bridges/a2a-bridge.d.ts +156 -0
  20. package/dist/bridges/a2a-bridge.d.ts.map +1 -0
  21. package/dist/bridges/a2a-bridge.js +337 -0
  22. package/dist/bridges/a2a-bridge.js.map +1 -0
  23. package/dist/bridges/mcp-bridge.d.ts +87 -0
  24. package/dist/bridges/mcp-bridge.d.ts.map +1 -0
  25. package/dist/bridges/mcp-bridge.js +332 -0
  26. package/dist/bridges/mcp-bridge.js.map +1 -0
  27. package/dist/cache.d.ts +130 -0
  28. package/dist/cache.d.ts.map +1 -0
  29. package/dist/cache.js +257 -0
  30. package/dist/cache.js.map +1 -0
  31. package/dist/capsules.d.ts +23 -0
  32. package/dist/capsules.d.ts.map +1 -0
  33. package/dist/capsules.js +75 -0
  34. package/dist/capsules.js.map +1 -0
  35. package/dist/cli/commands.d.ts +8 -0
  36. package/dist/cli/commands.d.ts.map +1 -0
  37. package/dist/cli/commands.js +263 -0
  38. package/dist/cli/commands.js.map +1 -0
  39. package/dist/coc.d.ts +121 -0
  40. package/dist/coc.d.ts.map +1 -0
  41. package/dist/coc.js +629 -0
  42. package/dist/coc.js.map +1 -0
  43. package/dist/coc.test.d.ts +2 -0
  44. package/dist/coc.test.d.ts.map +1 -0
  45. package/dist/coc.test.js +80 -0
  46. package/dist/coc.test.js.map +1 -0
  47. package/dist/compression.d.ts +125 -0
  48. package/dist/compression.d.ts.map +1 -0
  49. package/dist/compression.js +573 -0
  50. package/dist/compression.js.map +1 -0
  51. package/dist/cot-stream.d.ts +220 -0
  52. package/dist/cot-stream.d.ts.map +1 -0
  53. package/dist/cot-stream.js +673 -0
  54. package/dist/cot-stream.js.map +1 -0
  55. package/dist/crypto-wasm.d.ts +100 -0
  56. package/dist/crypto-wasm.d.ts.map +1 -0
  57. package/dist/crypto-wasm.js +229 -0
  58. package/dist/crypto-wasm.js.map +1 -0
  59. package/dist/federation.d.ts +200 -0
  60. package/dist/federation.d.ts.map +1 -0
  61. package/dist/federation.js +691 -0
  62. package/dist/federation.js.map +1 -0
  63. package/dist/federation.test.d.ts +2 -0
  64. package/dist/federation.test.d.ts.map +1 -0
  65. package/dist/federation.test.js +71 -0
  66. package/dist/federation.test.js.map +1 -0
  67. package/dist/gateway/capability-router.d.ts +77 -0
  68. package/dist/gateway/capability-router.d.ts.map +1 -0
  69. package/dist/gateway/capability-router.js +222 -0
  70. package/dist/gateway/capability-router.js.map +1 -0
  71. package/dist/gateway/demand-spawner.d.ts +155 -0
  72. package/dist/gateway/demand-spawner.d.ts.map +1 -0
  73. package/dist/gateway/demand-spawner.js +426 -0
  74. package/dist/gateway/demand-spawner.js.map +1 -0
  75. package/dist/identity.d.ts +46 -0
  76. package/dist/identity.d.ts.map +1 -0
  77. package/dist/identity.js +102 -0
  78. package/dist/identity.js.map +1 -0
  79. package/dist/identity.test.d.ts +2 -0
  80. package/dist/identity.test.d.ts.map +1 -0
  81. package/dist/identity.test.js +45 -0
  82. package/dist/identity.test.js.map +1 -0
  83. package/dist/index.d.ts +36 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +1572 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/integration.d.ts +210 -0
  88. package/dist/integration.d.ts.map +1 -0
  89. package/dist/integration.js +1105 -0
  90. package/dist/integration.js.map +1 -0
  91. package/dist/integration.test.d.ts +2 -0
  92. package/dist/integration.test.d.ts.map +1 -0
  93. package/dist/integration.test.js +155 -0
  94. package/dist/integration.test.js.map +1 -0
  95. package/dist/knowledge.d.ts +219 -0
  96. package/dist/knowledge.d.ts.map +1 -0
  97. package/dist/knowledge.js +543 -0
  98. package/dist/knowledge.js.map +1 -0
  99. package/dist/knowledge.test.d.ts +2 -0
  100. package/dist/knowledge.test.d.ts.map +1 -0
  101. package/dist/knowledge.test.js +72 -0
  102. package/dist/knowledge.test.js.map +1 -0
  103. package/dist/latent-space.d.ts +178 -0
  104. package/dist/latent-space.d.ts.map +1 -0
  105. package/dist/latent-space.js +385 -0
  106. package/dist/latent-space.js.map +1 -0
  107. package/dist/lib.d.ts +30 -0
  108. package/dist/lib.d.ts.map +1 -0
  109. package/dist/lib.js +30 -0
  110. package/dist/lib.js.map +1 -0
  111. package/dist/mcp/server.d.ts +74 -0
  112. package/dist/mcp/server.d.ts.map +1 -0
  113. package/dist/mcp/server.js +1392 -0
  114. package/dist/mcp/server.js.map +1 -0
  115. package/dist/metrics.d.ts +98 -0
  116. package/dist/metrics.d.ts.map +1 -0
  117. package/dist/metrics.js +222 -0
  118. package/dist/metrics.js.map +1 -0
  119. package/dist/p2p.d.ts +87 -0
  120. package/dist/p2p.d.ts.map +1 -0
  121. package/dist/p2p.js +606 -0
  122. package/dist/p2p.js.map +1 -0
  123. package/dist/persona/capabilities.d.ts +17 -0
  124. package/dist/persona/capabilities.d.ts.map +1 -0
  125. package/dist/persona/capabilities.js +224 -0
  126. package/dist/persona/capabilities.js.map +1 -0
  127. package/dist/persona/domains.d.ts +22 -0
  128. package/dist/persona/domains.d.ts.map +1 -0
  129. package/dist/persona/domains.js +176 -0
  130. package/dist/persona/domains.js.map +1 -0
  131. package/dist/persona/embeddings.d.ts +40 -0
  132. package/dist/persona/embeddings.d.ts.map +1 -0
  133. package/dist/persona/embeddings.js +265 -0
  134. package/dist/persona/embeddings.js.map +1 -0
  135. package/dist/persona/engine.d.ts +79 -0
  136. package/dist/persona/engine.d.ts.map +1 -0
  137. package/dist/persona/engine.js +1087 -0
  138. package/dist/persona/engine.js.map +1 -0
  139. package/dist/persona/index.d.ts +11 -0
  140. package/dist/persona/index.d.ts.map +1 -0
  141. package/dist/persona/index.js +11 -0
  142. package/dist/persona/index.js.map +1 -0
  143. package/dist/persona/lifecycle.d.ts +17 -0
  144. package/dist/persona/lifecycle.d.ts.map +1 -0
  145. package/dist/persona/lifecycle.js +36 -0
  146. package/dist/persona/lifecycle.js.map +1 -0
  147. package/dist/persona/retrieval.d.ts +6 -0
  148. package/dist/persona/retrieval.d.ts.map +1 -0
  149. package/dist/persona/retrieval.js +122 -0
  150. package/dist/persona/retrieval.js.map +1 -0
  151. package/dist/persona/sync.d.ts +15 -0
  152. package/dist/persona/sync.d.ts.map +1 -0
  153. package/dist/persona/sync.js +92 -0
  154. package/dist/persona/sync.js.map +1 -0
  155. package/dist/persona/types.d.ts +283 -0
  156. package/dist/persona/types.d.ts.map +1 -0
  157. package/dist/persona/types.js +2 -0
  158. package/dist/persona/types.js.map +1 -0
  159. package/dist/persona/zkp/engine.d.ts +26 -0
  160. package/dist/persona/zkp/engine.d.ts.map +1 -0
  161. package/dist/persona/zkp/engine.js +370 -0
  162. package/dist/persona/zkp/engine.js.map +1 -0
  163. package/dist/persona/zkp/types.d.ts +39 -0
  164. package/dist/persona/zkp/types.d.ts.map +1 -0
  165. package/dist/persona/zkp/types.js +2 -0
  166. package/dist/persona/zkp/types.js.map +1 -0
  167. package/dist/planner.d.ts +114 -0
  168. package/dist/planner.d.ts.map +1 -0
  169. package/dist/planner.js +522 -0
  170. package/dist/planner.js.map +1 -0
  171. package/dist/proactive/checkpoints.d.ts +9 -0
  172. package/dist/proactive/checkpoints.d.ts.map +1 -0
  173. package/dist/proactive/checkpoints.js +20 -0
  174. package/dist/proactive/checkpoints.js.map +1 -0
  175. package/dist/proactive/engine.d.ts +59 -0
  176. package/dist/proactive/engine.d.ts.map +1 -0
  177. package/dist/proactive/engine.js +406 -0
  178. package/dist/proactive/engine.js.map +1 -0
  179. package/dist/proactive/scheduler.d.ts +11 -0
  180. package/dist/proactive/scheduler.d.ts.map +1 -0
  181. package/dist/proactive/scheduler.js +45 -0
  182. package/dist/proactive/scheduler.js.map +1 -0
  183. package/dist/proactive/swarm-controller.d.ts +189 -0
  184. package/dist/proactive/swarm-controller.d.ts.map +1 -0
  185. package/dist/proactive/swarm-controller.js +477 -0
  186. package/dist/proactive/swarm-controller.js.map +1 -0
  187. package/dist/proactive/swarm-registry.d.ts +13 -0
  188. package/dist/proactive/swarm-registry.d.ts.map +1 -0
  189. package/dist/proactive/swarm-registry.js +122 -0
  190. package/dist/proactive/swarm-registry.js.map +1 -0
  191. package/dist/proactive/types.d.ts +145 -0
  192. package/dist/proactive/types.d.ts.map +1 -0
  193. package/dist/proactive/types.js +25 -0
  194. package/dist/proactive/types.js.map +1 -0
  195. package/dist/registry.d.ts +35 -0
  196. package/dist/registry.d.ts.map +1 -0
  197. package/dist/registry.js +88 -0
  198. package/dist/registry.js.map +1 -0
  199. package/dist/reputation.d.ts +123 -0
  200. package/dist/reputation.d.ts.map +1 -0
  201. package/dist/reputation.js +366 -0
  202. package/dist/reputation.js.map +1 -0
  203. package/dist/reputation.test.d.ts +5 -0
  204. package/dist/reputation.test.d.ts.map +1 -0
  205. package/dist/reputation.test.js +265 -0
  206. package/dist/reputation.test.js.map +1 -0
  207. package/dist/rooms.d.ts +96 -0
  208. package/dist/rooms.d.ts.map +1 -0
  209. package/dist/rooms.js +410 -0
  210. package/dist/rooms.js.map +1 -0
  211. package/dist/sdk/client.d.ts +290 -0
  212. package/dist/sdk/client.d.ts.map +1 -0
  213. package/dist/sdk/client.js +1287 -0
  214. package/dist/sdk/client.js.map +1 -0
  215. package/dist/sdk/index.d.ts +32 -0
  216. package/dist/sdk/index.d.ts.map +1 -0
  217. package/dist/sdk/index.js +70 -0
  218. package/dist/sdk/index.js.map +1 -0
  219. package/dist/security.d.ts +230 -0
  220. package/dist/security.d.ts.map +1 -0
  221. package/dist/security.js +652 -0
  222. package/dist/security.js.map +1 -0
  223. package/dist/skills/engine.d.ts +262 -0
  224. package/dist/skills/engine.d.ts.map +1 -0
  225. package/dist/skills/engine.js +788 -0
  226. package/dist/skills/engine.js.map +1 -0
  227. package/dist/skills/engine.test.d.ts +2 -0
  228. package/dist/skills/engine.test.d.ts.map +1 -0
  229. package/dist/skills/engine.test.js +134 -0
  230. package/dist/skills/engine.test.js.map +1 -0
  231. package/dist/skills/parser.d.ts +129 -0
  232. package/dist/skills/parser.d.ts.map +1 -0
  233. package/dist/skills/parser.js +318 -0
  234. package/dist/skills/parser.js.map +1 -0
  235. package/dist/social.d.ts +149 -0
  236. package/dist/social.d.ts.map +1 -0
  237. package/dist/social.js +401 -0
  238. package/dist/social.js.map +1 -0
  239. package/dist/storage-optimized.d.ts +116 -0
  240. package/dist/storage-optimized.d.ts.map +1 -0
  241. package/dist/storage-optimized.js +264 -0
  242. package/dist/storage-optimized.js.map +1 -0
  243. package/dist/storage.d.ts +584 -0
  244. package/dist/storage.d.ts.map +1 -0
  245. package/dist/storage.js +2703 -0
  246. package/dist/storage.js.map +1 -0
  247. package/dist/storage.test.d.ts +2 -0
  248. package/dist/storage.test.d.ts.map +1 -0
  249. package/dist/storage.test.js +78 -0
  250. package/dist/storage.test.js.map +1 -0
  251. package/dist/swp.d.ts +443 -0
  252. package/dist/swp.d.ts.map +1 -0
  253. package/dist/swp.js +223 -0
  254. package/dist/swp.js.map +1 -0
  255. package/dist/swp.test.d.ts +5 -0
  256. package/dist/swp.test.d.ts.map +1 -0
  257. package/dist/swp.test.js +127 -0
  258. package/dist/swp.test.js.map +1 -0
  259. package/dist/templates.d.ts +25 -0
  260. package/dist/templates.d.ts.map +1 -0
  261. package/dist/templates.js +1048 -0
  262. package/dist/templates.js.map +1 -0
  263. package/dist/test-e2e.d.ts +14 -0
  264. package/dist/test-e2e.d.ts.map +1 -0
  265. package/dist/test-e2e.js +266 -0
  266. package/dist/test-e2e.js.map +1 -0
  267. package/dist/workers/research-worker.d.ts +19 -0
  268. package/dist/workers/research-worker.d.ts.map +1 -0
  269. package/dist/workers/research-worker.js +141 -0
  270. package/dist/workers/research-worker.js.map +1 -0
  271. package/package.json +110 -0
@@ -0,0 +1,673 @@
1
+ /**
2
+ * Society Protocol — Collaborative Chain-of-Thought (CoT) Streaming v1.0
3
+ *
4
+ * Killer feature: Real-time distributed reasoning between agents.
5
+ * Each agent publishes reasoning tokens, insights, questions and answers
6
+ * via GossipSub, enabling "pair programming between LLMs" — agents can
7
+ * absorb each other's reasoning in real-time and build on it.
8
+ *
9
+ * Key concepts:
10
+ * - CoT Stream: A reasoning session tied to a room/chain/step
11
+ * - Tokens: Typed reasoning chunks (reasoning, observation, hypothesis, etc.)
12
+ * - Insights: Distilled discoveries that can auto-create Knowledge Cards
13
+ * - Questions/Answers: Inter-agent Socratic dialogue
14
+ * - Branches: Divergent reasoning paths explored in parallel
15
+ * - Merges: Synthesis of multiple reasoning branches
16
+ *
17
+ * Architecture:
18
+ * Agent A ──┐ ┌── Agent C (absorbs A+B reasoning)
19
+ * ├── GossipSub topic ─┤
20
+ * Agent B ──┘ └── Agent D (branches from A's insight)
21
+ */
22
+ import { EventEmitter } from 'events';
23
+ import { ulid } from 'ulid';
24
+ // ─── CoT Stream Engine ──────────────────────────────────────────
25
+ const DEFAULT_CONFIG = {
26
+ maxBufferSize: 100,
27
+ autoCreateCards: true,
28
+ autoCardMinConfidence: 0.7,
29
+ maxStreamsPerRoom: 20,
30
+ batchIntervalMs: 250,
31
+ };
32
+ export class CotStreamEngine extends EventEmitter {
33
+ identity;
34
+ rooms;
35
+ knowledge;
36
+ streams = new Map();
37
+ insights = new Map();
38
+ questions = new Map();
39
+ tokenBuffers = new Map();
40
+ roomStreams = new Map(); // roomId -> streamIds
41
+ batchTimers = new Map();
42
+ config;
43
+ constructor(identity, rooms, knowledge, config) {
44
+ super();
45
+ this.identity = identity;
46
+ this.rooms = rooms;
47
+ this.knowledge = knowledge;
48
+ this.config = { ...DEFAULT_CONFIG, ...config };
49
+ this.bindEvents();
50
+ }
51
+ // ─── Stream Lifecycle ────────────────────────────────────────
52
+ /**
53
+ * Start a new reasoning stream — begins broadcasting thinking tokens.
54
+ */
55
+ async startStream(roomId, goal, options = {}) {
56
+ const streamId = `cot_${ulid()}`;
57
+ // Enforce max streams per room
58
+ const roomStreamSet = this.roomStreams.get(roomId);
59
+ if (roomStreamSet && roomStreamSet.size >= this.config.maxStreamsPerRoom) {
60
+ throw new Error(`Max streams (${this.config.maxStreamsPerRoom}) reached for room ${roomId}`);
61
+ }
62
+ const stream = {
63
+ stream_id: streamId,
64
+ room_id: roomId,
65
+ chain_id: options.chain_id,
66
+ step_id: options.step_id,
67
+ goal,
68
+ model: options.model,
69
+ owner_did: this.identity.did,
70
+ parent_stream_id: options.parent_stream_id,
71
+ status: 'active',
72
+ started_at: Date.now(),
73
+ token_count: 0,
74
+ insight_count: 0,
75
+ question_count: 0,
76
+ branches: [],
77
+ };
78
+ this.streams.set(streamId, stream);
79
+ this.tokenBuffers.set(streamId, []);
80
+ if (!this.roomStreams.has(roomId)) {
81
+ this.roomStreams.set(roomId, new Set());
82
+ }
83
+ this.roomStreams.get(roomId).add(streamId);
84
+ // If this is a branch, register with parent
85
+ if (options.parent_stream_id) {
86
+ const parent = this.streams.get(options.parent_stream_id);
87
+ if (parent) {
88
+ parent.branches.push(streamId);
89
+ }
90
+ }
91
+ const body = {
92
+ stream_id: streamId,
93
+ chain_id: options.chain_id,
94
+ step_id: options.step_id,
95
+ goal,
96
+ model: options.model,
97
+ parent_stream_id: options.parent_stream_id,
98
+ };
99
+ await this.rooms.sendMessage(roomId, body, 'cot.stream.start');
100
+ this.emit('stream:started', streamId, stream);
101
+ return streamId;
102
+ }
103
+ /**
104
+ * Emit a reasoning token — the core of collaborative thinking.
105
+ * Tokens are batched for network efficiency.
106
+ */
107
+ async emitToken(streamId, token, tokenType, options = {}) {
108
+ const stream = this.streams.get(streamId);
109
+ if (!stream || stream.status !== 'active') {
110
+ throw new Error(`Stream ${streamId} not active`);
111
+ }
112
+ stream.token_count++;
113
+ const tokenBody = {
114
+ stream_id: streamId,
115
+ seq: stream.token_count,
116
+ token,
117
+ token_type: tokenType,
118
+ confidence: options.confidence,
119
+ domain: options.domain,
120
+ references: options.references,
121
+ };
122
+ // Buffer tokens and flush in batches for efficiency
123
+ const buffer = this.tokenBuffers.get(streamId);
124
+ buffer.push(tokenBody);
125
+ if (buffer.length >= this.config.maxBufferSize) {
126
+ await this.flushTokenBuffer(streamId);
127
+ }
128
+ else if (!this.batchTimers.has(streamId)) {
129
+ this.batchTimers.set(streamId, setTimeout(() => {
130
+ this.flushTokenBuffer(streamId);
131
+ this.batchTimers.delete(streamId);
132
+ }, this.config.batchIntervalMs));
133
+ }
134
+ this.emit('token:emitted', streamId, tokenBody);
135
+ }
136
+ /**
137
+ * Publish an insight — a distilled discovery from reasoning.
138
+ * Can auto-create a Knowledge Card if configured.
139
+ */
140
+ async publishInsight(streamId, title, content, insightType, options = {}) {
141
+ const stream = this.streams.get(streamId);
142
+ if (!stream)
143
+ throw new Error(`Stream ${streamId} not found`);
144
+ const insightId = `insight_${ulid()}`;
145
+ const confidence = options.confidence ?? 0.5;
146
+ const insight = {
147
+ insight_id: insightId,
148
+ stream_id: streamId,
149
+ title,
150
+ content,
151
+ insight_type: insightType,
152
+ confidence,
153
+ supporting_evidence: options.supporting_evidence || [],
154
+ author_did: this.identity.did,
155
+ created_at: Date.now(),
156
+ };
157
+ this.insights.set(insightId, insight);
158
+ stream.insight_count++;
159
+ // Auto-create knowledge card if configured and confidence is high enough
160
+ const shouldCreateCard = (options.auto_create_card ?? this.config.autoCreateCards)
161
+ && confidence >= this.config.autoCardMinConfidence
162
+ && this.knowledge;
163
+ if (shouldCreateCard) {
164
+ try {
165
+ const card = await this.knowledge.createCard(this.getDefaultSpaceId(stream.room_id), this.insightTypeToKnowledgeType(insightType), title, content, {
166
+ summary: content.slice(0, 200),
167
+ tags: ['cot-insight', insightType],
168
+ domain: [],
169
+ source: {
170
+ type: 'coc',
171
+ id: stream.chain_id,
172
+ context: `CoT Stream ${streamId}`,
173
+ },
174
+ confidence,
175
+ });
176
+ insight.knowledge_card_id = card.id;
177
+ }
178
+ catch {
179
+ // Knowledge pool may not be available; insight still valid
180
+ }
181
+ }
182
+ const body = {
183
+ stream_id: streamId,
184
+ insight_id: insightId,
185
+ title,
186
+ content,
187
+ insight_type: insightType,
188
+ confidence,
189
+ supporting_evidence: options.supporting_evidence || [],
190
+ related_streams: options.related_streams,
191
+ auto_create_card: !!shouldCreateCard,
192
+ };
193
+ await this.rooms.sendMessage(stream.room_id, body, 'cot.stream.insight');
194
+ this.emit('insight:published', streamId, insight);
195
+ return insightId;
196
+ }
197
+ /**
198
+ * Ask a question to other agents in the room — Socratic dialogue.
199
+ */
200
+ async askQuestion(streamId, question, questionType, options = {}) {
201
+ const stream = this.streams.get(streamId);
202
+ if (!stream)
203
+ throw new Error(`Stream ${streamId} not found`);
204
+ const questionId = `q_${ulid()}`;
205
+ const cotQuestion = {
206
+ question_id: questionId,
207
+ stream_id: streamId,
208
+ question,
209
+ question_type: questionType,
210
+ context: options.context || '',
211
+ asked_by: this.identity.did,
212
+ target_did: options.target_did,
213
+ urgency: options.urgency || 'normal',
214
+ asked_at: Date.now(),
215
+ answered: false,
216
+ answers: [],
217
+ };
218
+ this.questions.set(questionId, cotQuestion);
219
+ stream.question_count++;
220
+ const body = {
221
+ stream_id: streamId,
222
+ question_id: questionId,
223
+ question,
224
+ question_type: questionType,
225
+ context: options.context || '',
226
+ target_did: options.target_did,
227
+ urgency: options.urgency || 'normal',
228
+ };
229
+ await this.rooms.sendMessage(stream.room_id, body, 'cot.stream.question');
230
+ this.emit('question:asked', streamId, cotQuestion);
231
+ return questionId;
232
+ }
233
+ /**
234
+ * Answer a question from another agent.
235
+ */
236
+ async answerQuestion(streamId, questionId, answer, options = {}) {
237
+ const stream = this.streams.get(streamId);
238
+ if (!stream)
239
+ throw new Error(`Stream ${streamId} not found`);
240
+ const cotQuestion = this.questions.get(questionId);
241
+ if (!cotQuestion)
242
+ throw new Error(`Question ${questionId} not found`);
243
+ const answerId = `a_${ulid()}`;
244
+ const cotAnswer = {
245
+ answer_id: answerId,
246
+ question_id: questionId,
247
+ stream_id: streamId,
248
+ answer,
249
+ confidence: options.confidence ?? 0.5,
250
+ references: options.references || [],
251
+ answered_by: this.identity.did,
252
+ answered_at: Date.now(),
253
+ };
254
+ cotQuestion.answers.push(cotAnswer);
255
+ cotQuestion.answered = true;
256
+ const body = {
257
+ stream_id: streamId,
258
+ question_id: questionId,
259
+ answer,
260
+ confidence: options.confidence ?? 0.5,
261
+ references: options.references,
262
+ };
263
+ await this.rooms.sendMessage(stream.room_id, body, 'cot.stream.answer');
264
+ this.emit('question:answered', streamId, questionId, cotAnswer);
265
+ }
266
+ /**
267
+ * Branch the reasoning — explore a divergent hypothesis in parallel.
268
+ */
269
+ async branchStream(parentStreamId, hypothesis, branchReason) {
270
+ const parent = this.streams.get(parentStreamId);
271
+ if (!parent)
272
+ throw new Error(`Parent stream ${parentStreamId} not found`);
273
+ // Create a new stream as a branch
274
+ const branchId = await this.startStream(parent.room_id, hypothesis, {
275
+ chain_id: parent.chain_id,
276
+ step_id: parent.step_id,
277
+ model: parent.model,
278
+ parent_stream_id: parentStreamId,
279
+ });
280
+ const body = {
281
+ stream_id: branchId,
282
+ parent_stream_id: parentStreamId,
283
+ branch_reason: branchReason,
284
+ hypothesis,
285
+ };
286
+ await this.rooms.sendMessage(parent.room_id, body, 'cot.stream.branch');
287
+ this.emit('stream:branched', parentStreamId, branchId, hypothesis);
288
+ return branchId;
289
+ }
290
+ /**
291
+ * Merge multiple reasoning branches into a synthesis.
292
+ */
293
+ async mergeStreams(targetStreamId, sourceStreamIds, synthesis, consensusLevel) {
294
+ const target = this.streams.get(targetStreamId);
295
+ if (!target)
296
+ throw new Error(`Target stream ${targetStreamId} not found`);
297
+ // Mark source streams as merged
298
+ for (const srcId of sourceStreamIds) {
299
+ const src = this.streams.get(srcId);
300
+ if (src) {
301
+ src.status = 'merged';
302
+ src.merged_into = targetStreamId;
303
+ src.ended_at = Date.now();
304
+ }
305
+ }
306
+ const body = {
307
+ stream_id: targetStreamId,
308
+ merged_streams: sourceStreamIds,
309
+ synthesis,
310
+ consensus_level: Math.max(0, Math.min(1, consensusLevel)),
311
+ };
312
+ await this.rooms.sendMessage(target.room_id, body, 'cot.stream.merge');
313
+ this.emit('stream:merged', targetStreamId, sourceStreamIds, synthesis);
314
+ }
315
+ /**
316
+ * End a reasoning stream.
317
+ */
318
+ async endStream(streamId, status, summary) {
319
+ const stream = this.streams.get(streamId);
320
+ if (!stream)
321
+ throw new Error(`Stream ${streamId} not found`);
322
+ // Flush any remaining tokens
323
+ await this.flushTokenBuffer(streamId);
324
+ stream.status = status === 'completed' ? 'completed' :
325
+ status === 'paused' ? 'paused' :
326
+ status === 'merged' ? 'merged' : 'abandoned';
327
+ stream.ended_at = Date.now();
328
+ const body = {
329
+ stream_id: streamId,
330
+ status,
331
+ summary,
332
+ insights_generated: stream.insight_count,
333
+ tokens_total: stream.token_count,
334
+ duration_ms: stream.ended_at - stream.started_at,
335
+ };
336
+ await this.rooms.sendMessage(stream.room_id, body, 'cot.stream.end');
337
+ this.emit('stream:ended', streamId, status, summary);
338
+ // Cleanup batch timer
339
+ const timer = this.batchTimers.get(streamId);
340
+ if (timer) {
341
+ clearTimeout(timer);
342
+ this.batchTimers.delete(streamId);
343
+ }
344
+ }
345
+ // ─── Context Retrieval ───────────────────────────────────────
346
+ /**
347
+ * Get the full reasoning context for a stream — enables agents
348
+ * to "absorb" another agent's thinking and build on it.
349
+ */
350
+ getReasoningContext(streamId) {
351
+ const stream = this.streams.get(streamId);
352
+ if (!stream)
353
+ return null;
354
+ const tokens = this.tokenBuffers.get(streamId) || [];
355
+ const streamInsights = Array.from(this.insights.values())
356
+ .filter(i => i.stream_id === streamId);
357
+ const streamQuestions = Array.from(this.questions.values())
358
+ .filter(q => q.stream_id === streamId);
359
+ return {
360
+ stream_id: streamId,
361
+ tokens,
362
+ insights: streamInsights,
363
+ questions: streamQuestions,
364
+ goal: stream.goal,
365
+ branches: stream.branches,
366
+ };
367
+ }
368
+ /**
369
+ * Get all active streams in a room — see what everyone is thinking.
370
+ */
371
+ getRoomStreams(roomId) {
372
+ const streamIds = this.roomStreams.get(roomId);
373
+ if (!streamIds)
374
+ return [];
375
+ return Array.from(streamIds)
376
+ .map(id => this.streams.get(id))
377
+ .filter((s) => s !== undefined);
378
+ }
379
+ /**
380
+ * Get active streams for a specific CoC chain.
381
+ */
382
+ getChainStreams(chainId) {
383
+ return Array.from(this.streams.values())
384
+ .filter(s => s.chain_id === chainId);
385
+ }
386
+ /**
387
+ * Get all unanswered questions targeting this agent.
388
+ */
389
+ getPendingQuestions() {
390
+ return Array.from(this.questions.values())
391
+ .filter(q => !q.answered && (!q.target_did || q.target_did === this.identity.did));
392
+ }
393
+ /**
394
+ * Get the reasoning tree starting from a root stream,
395
+ * including all branches and merges.
396
+ */
397
+ getReasoningTree(rootStreamId) {
398
+ const root = this.streams.get(rootStreamId);
399
+ if (!root)
400
+ return null;
401
+ const branches = [];
402
+ const allInsights = [];
403
+ let maxDepth = 0;
404
+ const traverse = (streamId, depth) => {
405
+ const stream = this.streams.get(streamId);
406
+ if (!stream)
407
+ return;
408
+ maxDepth = Math.max(maxDepth, depth);
409
+ // Collect insights
410
+ for (const insight of this.insights.values()) {
411
+ if (insight.stream_id === streamId) {
412
+ allInsights.push(insight);
413
+ }
414
+ }
415
+ // Traverse branches
416
+ for (const branchId of stream.branches) {
417
+ const branch = this.streams.get(branchId);
418
+ if (branch) {
419
+ branches.push(branch);
420
+ traverse(branchId, depth + 1);
421
+ }
422
+ }
423
+ };
424
+ traverse(rootStreamId, 0);
425
+ return { root, branches, insights: allInsights, depth: maxDepth };
426
+ }
427
+ // ─── Event Handling ──────────────────────────────────────────
428
+ bindEvents() {
429
+ // Handle incoming CoT stream events from other agents
430
+ this.rooms.on('cot:stream:start', (_roomId, envelope) => {
431
+ const body = envelope.body;
432
+ this.handleRemoteStreamStart(envelope.room, body, envelope.from.did);
433
+ });
434
+ this.rooms.on('cot:stream:token', (_roomId, envelope) => {
435
+ const body = envelope.body;
436
+ this.handleRemoteToken(body, envelope.from.did);
437
+ });
438
+ this.rooms.on('cot:stream:insight', (_roomId, envelope) => {
439
+ const body = envelope.body;
440
+ this.handleRemoteInsight(body, envelope.from.did);
441
+ });
442
+ this.rooms.on('cot:stream:question', (_roomId, envelope) => {
443
+ const body = envelope.body;
444
+ this.handleRemoteQuestion(body, envelope.from.did);
445
+ });
446
+ this.rooms.on('cot:stream:answer', (_roomId, envelope) => {
447
+ const body = envelope.body;
448
+ this.handleRemoteAnswer(body, envelope.from.did);
449
+ });
450
+ this.rooms.on('cot:stream:branch', (_roomId, envelope) => {
451
+ const body = envelope.body;
452
+ this.handleRemoteBranch(body, envelope.from.did);
453
+ });
454
+ this.rooms.on('cot:stream:merge', (_roomId, envelope) => {
455
+ const body = envelope.body;
456
+ this.handleRemoteMerge(body, envelope.from.did);
457
+ });
458
+ this.rooms.on('cot:stream:end', (_roomId, envelope) => {
459
+ const body = envelope.body;
460
+ this.handleRemoteStreamEnd(body, envelope.from.did);
461
+ });
462
+ }
463
+ handleRemoteStreamStart(roomId, body, fromDid) {
464
+ if (this.streams.has(body.stream_id))
465
+ return; // Already known
466
+ const stream = {
467
+ stream_id: body.stream_id,
468
+ room_id: roomId,
469
+ chain_id: body.chain_id,
470
+ step_id: body.step_id,
471
+ goal: body.goal,
472
+ model: body.model,
473
+ owner_did: fromDid,
474
+ parent_stream_id: body.parent_stream_id,
475
+ status: 'active',
476
+ started_at: Date.now(),
477
+ token_count: 0,
478
+ insight_count: 0,
479
+ question_count: 0,
480
+ branches: [],
481
+ };
482
+ this.streams.set(body.stream_id, stream);
483
+ this.tokenBuffers.set(body.stream_id, []);
484
+ if (!this.roomStreams.has(roomId)) {
485
+ this.roomStreams.set(roomId, new Set());
486
+ }
487
+ this.roomStreams.get(roomId).add(body.stream_id);
488
+ if (body.parent_stream_id) {
489
+ const parent = this.streams.get(body.parent_stream_id);
490
+ if (parent)
491
+ parent.branches.push(body.stream_id);
492
+ }
493
+ this.emit('stream:remote:started', body.stream_id, stream);
494
+ }
495
+ handleRemoteToken(body, fromDid) {
496
+ const stream = this.streams.get(body.stream_id);
497
+ if (!stream)
498
+ return;
499
+ stream.token_count = Math.max(stream.token_count, body.seq);
500
+ // Store in buffer for context retrieval
501
+ const buffer = this.tokenBuffers.get(body.stream_id);
502
+ if (buffer) {
503
+ buffer.push(body);
504
+ // Keep buffer bounded
505
+ if (buffer.length > this.config.maxBufferSize * 10) {
506
+ buffer.splice(0, buffer.length - this.config.maxBufferSize * 5);
507
+ }
508
+ }
509
+ this.emit('token:received', body.stream_id, body, fromDid);
510
+ }
511
+ handleRemoteInsight(body, fromDid) {
512
+ const insight = {
513
+ insight_id: body.insight_id,
514
+ stream_id: body.stream_id,
515
+ title: body.title,
516
+ content: body.content,
517
+ insight_type: body.insight_type,
518
+ confidence: body.confidence,
519
+ supporting_evidence: body.supporting_evidence,
520
+ author_did: fromDid,
521
+ created_at: Date.now(),
522
+ };
523
+ this.insights.set(body.insight_id, insight);
524
+ const stream = this.streams.get(body.stream_id);
525
+ if (stream)
526
+ stream.insight_count++;
527
+ this.emit('insight:received', body.stream_id, insight);
528
+ }
529
+ handleRemoteQuestion(body, fromDid) {
530
+ const question = {
531
+ question_id: body.question_id,
532
+ stream_id: body.stream_id,
533
+ question: body.question,
534
+ question_type: body.question_type,
535
+ context: body.context,
536
+ asked_by: fromDid,
537
+ target_did: body.target_did,
538
+ urgency: body.urgency,
539
+ asked_at: Date.now(),
540
+ answered: false,
541
+ answers: [],
542
+ };
543
+ this.questions.set(body.question_id, question);
544
+ const stream = this.streams.get(body.stream_id);
545
+ if (stream)
546
+ stream.question_count++;
547
+ // Emit targeted event if this agent is the target
548
+ if (!body.target_did || body.target_did === this.identity.did) {
549
+ this.emit('question:received', body.stream_id, question);
550
+ }
551
+ }
552
+ handleRemoteAnswer(body, fromDid) {
553
+ const question = this.questions.get(body.question_id);
554
+ if (!question)
555
+ return;
556
+ const answer = {
557
+ answer_id: `a_${ulid()}`,
558
+ question_id: body.question_id,
559
+ stream_id: body.stream_id,
560
+ answer: body.answer,
561
+ confidence: body.confidence,
562
+ references: body.references || [],
563
+ answered_by: fromDid,
564
+ answered_at: Date.now(),
565
+ };
566
+ question.answers.push(answer);
567
+ question.answered = true;
568
+ this.emit('answer:received', body.stream_id, body.question_id, answer);
569
+ }
570
+ handleRemoteBranch(body, fromDid) {
571
+ const parent = this.streams.get(body.parent_stream_id);
572
+ if (parent && !parent.branches.includes(body.stream_id)) {
573
+ parent.branches.push(body.stream_id);
574
+ }
575
+ this.emit('stream:remote:branched', body.parent_stream_id, body.stream_id, body.hypothesis);
576
+ }
577
+ handleRemoteMerge(body, fromDid) {
578
+ for (const srcId of body.merged_streams) {
579
+ const src = this.streams.get(srcId);
580
+ if (src) {
581
+ src.status = 'merged';
582
+ src.merged_into = body.stream_id;
583
+ src.ended_at = Date.now();
584
+ }
585
+ }
586
+ this.emit('stream:remote:merged', body.stream_id, body.merged_streams, body.synthesis);
587
+ }
588
+ handleRemoteStreamEnd(body, fromDid) {
589
+ const stream = this.streams.get(body.stream_id);
590
+ if (!stream)
591
+ return;
592
+ stream.status = body.status === 'completed' ? 'completed' :
593
+ body.status === 'paused' ? 'paused' :
594
+ body.status === 'merged' ? 'merged' : 'abandoned';
595
+ stream.ended_at = Date.now();
596
+ this.emit('stream:remote:ended', body.stream_id, body.status, body.summary);
597
+ }
598
+ // ─── Helpers ─────────────────────────────────────────────────
599
+ async flushTokenBuffer(streamId) {
600
+ const buffer = this.tokenBuffers.get(streamId);
601
+ const stream = this.streams.get(streamId);
602
+ if (!buffer || buffer.length === 0 || !stream)
603
+ return;
604
+ // Only flush tokens we own (don't re-broadcast remote tokens)
605
+ const ownTokens = buffer.filter(t => !this.isRemoteToken(t));
606
+ if (ownTokens.length === 0)
607
+ return;
608
+ // Send each token as its own message for real-time streaming
609
+ for (const token of ownTokens) {
610
+ await this.rooms.sendMessage(stream.room_id, token, 'cot.stream.token');
611
+ }
612
+ // Keep remote tokens in buffer, clear own tokens
613
+ const remoteTokens = buffer.filter(t => this.isRemoteToken(t));
614
+ this.tokenBuffers.set(streamId, remoteTokens);
615
+ }
616
+ isRemoteToken(token) {
617
+ // Tokens we emitted locally don't have a 'from' field yet;
618
+ // remote tokens are added via handleRemoteToken.
619
+ // Use a simple heuristic: check if we've already sent this seq
620
+ return false; // Local tokens are always flushed; buffer keeps all for context
621
+ }
622
+ getDefaultSpaceId(roomId) {
623
+ return `space_${roomId}`;
624
+ }
625
+ insightTypeToKnowledgeType(type) {
626
+ const mapping = {
627
+ discovery: 'finding',
628
+ pattern: 'insight',
629
+ contradiction: 'evidence',
630
+ connection: 'insight',
631
+ gap: 'hypothesis',
632
+ confirmation: 'evidence',
633
+ };
634
+ return mapping[type] || 'insight';
635
+ }
636
+ // ─── Getters ─────────────────────────────────────────────────
637
+ getStream(streamId) {
638
+ return this.streams.get(streamId);
639
+ }
640
+ getInsight(insightId) {
641
+ return this.insights.get(insightId);
642
+ }
643
+ getQuestion(questionId) {
644
+ return this.questions.get(questionId);
645
+ }
646
+ getActiveStreams() {
647
+ return Array.from(this.streams.values())
648
+ .filter(s => s.status === 'active');
649
+ }
650
+ getStats() {
651
+ const questions = Array.from(this.questions.values());
652
+ return {
653
+ totalStreams: this.streams.size,
654
+ activeStreams: Array.from(this.streams.values()).filter(s => s.status === 'active').length,
655
+ totalInsights: this.insights.size,
656
+ totalQuestions: questions.length,
657
+ answeredQuestions: questions.filter(q => q.answered).length,
658
+ };
659
+ }
660
+ // ─── Cleanup ─────────────────────────────────────────────────
661
+ destroy() {
662
+ for (const timer of this.batchTimers.values()) {
663
+ clearTimeout(timer);
664
+ }
665
+ this.batchTimers.clear();
666
+ this.streams.clear();
667
+ this.insights.clear();
668
+ this.questions.clear();
669
+ this.tokenBuffers.clear();
670
+ this.roomStreams.clear();
671
+ }
672
+ }
673
+ //# sourceMappingURL=cot-stream.js.map