agent-relay 1.3.1 → 1.3.3

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 (202) hide show
  1. package/.trajectories/active/traj_3yx9dy148mge.json +42 -0
  2. package/.trajectories/completed/2026-01/traj_1g7yx6qtg4ai.json +49 -0
  3. package/.trajectories/completed/2026-01/traj_1g7yx6qtg4ai.md +31 -0
  4. package/.trajectories/completed/2026-01/traj_4qwd4zmhfwp4.json +49 -0
  5. package/.trajectories/completed/2026-01/traj_4qwd4zmhfwp4.md +31 -0
  6. package/.trajectories/completed/2026-01/traj_6unwwmgyj5sq.json +109 -0
  7. package/.trajectories/completed/2026-01/traj_a0tqx8biw9c4.json +49 -0
  8. package/.trajectories/completed/2026-01/traj_a0tqx8biw9c4.md +31 -0
  9. package/.trajectories/completed/2026-01/traj_ax8uungxz2qh.json +66 -0
  10. package/.trajectories/completed/2026-01/traj_ax8uungxz2qh.md +36 -0
  11. package/.trajectories/completed/2026-01/traj_c9izbh2snpzf.json +49 -0
  12. package/.trajectories/completed/2026-01/traj_c9izbh2snpzf.md +31 -0
  13. package/.trajectories/completed/2026-01/traj_cpn70dw066nt.json +65 -0
  14. package/.trajectories/completed/2026-01/traj_cpn70dw066nt.md +37 -0
  15. package/.trajectories/completed/2026-01/traj_erglv2f8t9eh.json +36 -0
  16. package/.trajectories/completed/2026-01/traj_erglv2f8t9eh.md +21 -0
  17. package/.trajectories/completed/2026-01/traj_he75f24d1xfm.json +101 -0
  18. package/.trajectories/completed/2026-01/traj_he75f24d1xfm.md +52 -0
  19. package/.trajectories/completed/2026-01/traj_lgtodco7dp1n.json +61 -0
  20. package/.trajectories/completed/2026-01/traj_lgtodco7dp1n.md +36 -0
  21. package/.trajectories/completed/2026-01/traj_oszg9flv74pk.json +73 -0
  22. package/.trajectories/completed/2026-01/traj_oszg9flv74pk.md +41 -0
  23. package/.trajectories/completed/2026-01/traj_pulomd3y8cvj.json +77 -0
  24. package/.trajectories/completed/2026-01/traj_pulomd3y8cvj.md +42 -0
  25. package/.trajectories/completed/2026-01/traj_rsavt0jipi3c.json +109 -0
  26. package/.trajectories/completed/2026-01/traj_rsavt0jipi3c.md +56 -0
  27. package/.trajectories/completed/2026-01/traj_x721m1j9rzup.json +113 -0
  28. package/.trajectories/completed/2026-01/traj_x721m1j9rzup.md +57 -0
  29. package/.trajectories/completed/2026-01/traj_xjqvmep5ed3h.json +61 -0
  30. package/.trajectories/completed/2026-01/traj_xjqvmep5ed3h.md +36 -0
  31. package/.trajectories/completed/2026-01/traj_y7n6hfbf7dmg.json +49 -0
  32. package/.trajectories/completed/2026-01/traj_y7n6hfbf7dmg.md +31 -0
  33. package/.trajectories/completed/2026-01/traj_yvfkwnkdiso2.json +49 -0
  34. package/.trajectories/completed/2026-01/traj_yvfkwnkdiso2.md +31 -0
  35. package/.trajectories/index.json +140 -1
  36. package/README.md +23 -9
  37. package/TRAIL_GIT_AUTH_FIX.md +113 -0
  38. package/deploy/workspace/codex.config.toml +1 -1
  39. package/deploy/workspace/entrypoint.sh +20 -79
  40. package/deploy/workspace/gh-relay +156 -0
  41. package/deploy/workspace/git-credential-relay +5 -1
  42. package/dist/bridge/multi-project-client.js +13 -10
  43. package/dist/bridge/spawner.d.ts +2 -0
  44. package/dist/bridge/spawner.js +58 -76
  45. package/dist/bridge/types.d.ts +2 -0
  46. package/dist/cli/index.d.ts +8 -6
  47. package/dist/cli/index.js +297 -30
  48. package/dist/cloud/api/admin.js +16 -3
  49. package/dist/cloud/api/codex-auth-helper.js +28 -8
  50. package/dist/cloud/api/consensus.d.ts +13 -0
  51. package/dist/cloud/api/consensus.js +259 -0
  52. package/dist/cloud/api/daemons.js +205 -1
  53. package/dist/cloud/api/git.js +37 -7
  54. package/dist/cloud/api/onboarding.js +4 -1
  55. package/dist/cloud/api/provider-env.d.ts +5 -0
  56. package/dist/cloud/api/provider-env.js +27 -0
  57. package/dist/cloud/api/providers.js +2 -0
  58. package/dist/cloud/api/test-helpers.js +130 -0
  59. package/dist/cloud/api/workspaces.js +38 -3
  60. package/dist/cloud/db/bulk-ingest.d.ts +88 -0
  61. package/dist/cloud/db/bulk-ingest.js +268 -0
  62. package/dist/cloud/db/drizzle.d.ts +33 -0
  63. package/dist/cloud/db/drizzle.js +174 -2
  64. package/dist/cloud/db/index.d.ts +24 -5
  65. package/dist/cloud/db/index.js +19 -4
  66. package/dist/cloud/db/schema.d.ts +397 -3
  67. package/dist/cloud/db/schema.js +75 -1
  68. package/dist/cloud/provisioner/index.d.ts +8 -0
  69. package/dist/cloud/provisioner/index.js +256 -50
  70. package/dist/cloud/server.js +47 -3
  71. package/dist/cloud/services/index.d.ts +1 -0
  72. package/dist/cloud/services/index.js +2 -0
  73. package/dist/cloud/services/nango.d.ts +3 -4
  74. package/dist/cloud/services/nango.js +11 -33
  75. package/dist/cloud/services/workspace-keepalive.d.ts +76 -0
  76. package/dist/cloud/services/workspace-keepalive.js +234 -0
  77. package/dist/config/relay-config.d.ts +23 -0
  78. package/dist/config/relay-config.js +23 -0
  79. package/dist/daemon/agent-manager.d.ts +20 -1
  80. package/dist/daemon/agent-manager.js +51 -0
  81. package/dist/daemon/agent-registry.js +4 -4
  82. package/dist/daemon/agent-signing.d.ts +158 -0
  83. package/dist/daemon/agent-signing.js +523 -0
  84. package/dist/daemon/api.js +18 -1
  85. package/dist/daemon/cli-auth.d.ts +4 -1
  86. package/dist/daemon/cli-auth.js +55 -11
  87. package/dist/daemon/cloud-sync.d.ts +47 -1
  88. package/dist/daemon/cloud-sync.js +152 -3
  89. package/dist/daemon/connection.d.ts +28 -0
  90. package/dist/daemon/connection.js +113 -22
  91. package/dist/daemon/consensus-integration.d.ts +167 -0
  92. package/dist/daemon/consensus-integration.js +371 -0
  93. package/dist/daemon/consensus.d.ts +271 -0
  94. package/dist/daemon/consensus.js +632 -0
  95. package/dist/daemon/delivery-tracker.d.ts +34 -0
  96. package/dist/daemon/delivery-tracker.js +104 -0
  97. package/dist/daemon/enhanced-features.d.ts +118 -0
  98. package/dist/daemon/enhanced-features.js +178 -0
  99. package/dist/daemon/index.d.ts +4 -0
  100. package/dist/daemon/index.js +5 -0
  101. package/dist/daemon/rate-limiter.d.ts +68 -0
  102. package/dist/daemon/rate-limiter.js +130 -0
  103. package/dist/daemon/router.d.ts +18 -11
  104. package/dist/daemon/router.js +57 -113
  105. package/dist/daemon/server.d.ts +13 -1
  106. package/dist/daemon/server.js +71 -9
  107. package/dist/daemon/sync-queue.d.ts +116 -0
  108. package/dist/daemon/sync-queue.js +361 -0
  109. package/dist/dashboard/out/404.html +1 -1
  110. package/dist/dashboard/out/_next/static/chunks/116-de2a4ac06e5000dc.js +1 -0
  111. package/dist/dashboard/out/_next/static/chunks/847-f1f467060f32afff.js +1 -0
  112. package/dist/dashboard/out/_next/static/chunks/919-87d604a5d76c1fbd.js +1 -0
  113. package/dist/dashboard/out/_next/static/chunks/app/app/{page-c617745b81344f4f.js → page-7f64824ae7d06707.js} +1 -1
  114. package/dist/dashboard/out/_next/static/chunks/app/cloud/link/page-3f559d393902aad2.js +1 -0
  115. package/dist/dashboard/out/_next/static/chunks/app/login/page-16d1715ddaa874ee.js +1 -0
  116. package/dist/dashboard/out/_next/static/chunks/app/{page-dc786c183425c2ac.js → page-814efc4d77b4191d.js} +1 -1
  117. package/dist/dashboard/out/_next/static/chunks/{main-2ee6beb2ae96d210.js → main-5a40a5ae29646e1b.js} +1 -1
  118. package/dist/dashboard/out/_next/static/css/44d2b52637b511bc.css +1 -0
  119. package/dist/dashboard/out/app/onboarding.html +1 -1
  120. package/dist/dashboard/out/app/onboarding.txt +1 -1
  121. package/dist/dashboard/out/app.html +1 -1
  122. package/dist/dashboard/out/app.txt +2 -2
  123. package/dist/dashboard/out/cloud/link.html +1 -0
  124. package/dist/dashboard/out/cloud/link.txt +7 -0
  125. package/dist/dashboard/out/connect-repos.html +1 -1
  126. package/dist/dashboard/out/connect-repos.txt +1 -1
  127. package/dist/dashboard/out/history.html +1 -1
  128. package/dist/dashboard/out/history.txt +2 -2
  129. package/dist/dashboard/out/index.html +1 -1
  130. package/dist/dashboard/out/index.txt +2 -2
  131. package/dist/dashboard/out/login.html +2 -3
  132. package/dist/dashboard/out/login.txt +2 -2
  133. package/dist/dashboard/out/metrics.html +1 -1
  134. package/dist/dashboard/out/metrics.txt +2 -2
  135. package/dist/dashboard/out/pricing.html +2 -2
  136. package/dist/dashboard/out/pricing.txt +1 -1
  137. package/dist/dashboard/out/providers/setup/claude.html +1 -1
  138. package/dist/dashboard/out/providers/setup/claude.txt +1 -1
  139. package/dist/dashboard/out/providers/setup/codex.html +1 -1
  140. package/dist/dashboard/out/providers/setup/codex.txt +1 -1
  141. package/dist/dashboard/out/providers.html +1 -1
  142. package/dist/dashboard/out/providers.txt +1 -1
  143. package/dist/dashboard/out/signup.html +2 -2
  144. package/dist/dashboard/out/signup.txt +1 -1
  145. package/dist/dashboard-server/server.js +244 -28
  146. package/dist/health-worker-manager.d.ts +62 -0
  147. package/dist/health-worker-manager.js +144 -0
  148. package/dist/health-worker.d.ts +9 -0
  149. package/dist/health-worker.js +79 -0
  150. package/dist/index.d.ts +2 -1
  151. package/dist/index.js +5 -1
  152. package/dist/memory/context-compaction.d.ts +156 -0
  153. package/dist/memory/context-compaction.js +453 -0
  154. package/dist/memory/index.d.ts +1 -0
  155. package/dist/memory/index.js +1 -0
  156. package/dist/protocol/channels.js +4 -4
  157. package/dist/protocol/framing.d.ts +72 -10
  158. package/dist/protocol/framing.js +194 -25
  159. package/dist/storage/adapter.d.ts +8 -1
  160. package/dist/storage/adapter.js +11 -0
  161. package/dist/storage/batched-sqlite-adapter.d.ts +71 -0
  162. package/dist/storage/batched-sqlite-adapter.js +183 -0
  163. package/dist/storage/dead-letter-queue.d.ts +196 -0
  164. package/dist/storage/dead-letter-queue.js +427 -0
  165. package/dist/storage/dlq-adapter.d.ts +195 -0
  166. package/dist/storage/dlq-adapter.js +664 -0
  167. package/dist/trajectory/config.d.ts +32 -14
  168. package/dist/trajectory/config.js +38 -16
  169. package/dist/trajectory/integration.js +217 -64
  170. package/dist/utils/git-remote.d.ts +47 -0
  171. package/dist/utils/git-remote.js +125 -0
  172. package/dist/utils/id-generator.d.ts +35 -0
  173. package/dist/utils/id-generator.js +60 -0
  174. package/dist/utils/index.d.ts +1 -0
  175. package/dist/utils/index.js +1 -0
  176. package/dist/utils/precompiled-patterns.d.ts +110 -0
  177. package/dist/utils/precompiled-patterns.js +322 -0
  178. package/dist/wrapper/auth-detection.js +1 -1
  179. package/dist/wrapper/base-wrapper.d.ts +40 -0
  180. package/dist/wrapper/base-wrapper.js +60 -6
  181. package/dist/wrapper/client.d.ts +14 -4
  182. package/dist/wrapper/client.js +89 -31
  183. package/dist/wrapper/idle-detector.d.ts +102 -0
  184. package/dist/wrapper/idle-detector.js +279 -0
  185. package/dist/wrapper/parser.d.ts +4 -0
  186. package/dist/wrapper/parser.js +19 -1
  187. package/dist/wrapper/pty-wrapper.d.ts +14 -2
  188. package/dist/wrapper/pty-wrapper.js +132 -32
  189. package/dist/wrapper/shared.d.ts +1 -1
  190. package/dist/wrapper/shared.js +1 -1
  191. package/dist/wrapper/tmux-wrapper.d.ts +20 -2
  192. package/dist/wrapper/tmux-wrapper.js +163 -40
  193. package/package.json +3 -1
  194. package/scripts/run-migrations.js +43 -0
  195. package/scripts/verify-schema.js +134 -0
  196. package/tests/benchmarks/protocol.bench.ts +310 -0
  197. package/dist/dashboard/out/_next/static/chunks/116-2502180def231162.js +0 -1
  198. package/dist/dashboard/out/_next/static/chunks/899-fc02ed79e3de4302.js +0 -1
  199. package/dist/dashboard/out/_next/static/chunks/app/login/page-c22d080201cbd9fb.js +0 -1
  200. package/dist/dashboard/out/_next/static/css/48a8fbe3e659080e.css +0 -1
  201. /package/dist/dashboard/out/_next/static/{sDcbGRTYLcpPvyTs_rsNb → R-uQOUcOLINtsp6ACeZa9}/_buildManifest.js +0 -0
  202. /package/dist/dashboard/out/_next/static/{sDcbGRTYLcpPvyTs_rsNb → R-uQOUcOLINtsp6ACeZa9}/_ssgManifest.js +0 -0
@@ -7,14 +7,12 @@
7
7
  * v v
8
8
  * ERROR -------> CLOSED
9
9
  */
10
- import { v4 as uuid } from 'uuid';
10
+ import { generateId } from '../utils/id-generator.js';
11
11
  import { PROTOCOL_VERSION, } from '../protocol/types.js';
12
- import { encodeFrame, FrameParser } from '../protocol/framing.js';
12
+ import { encodeFrameLegacy as encodeFrame, FrameParser } from '../protocol/framing.js';
13
+ import { DEFAULT_CONNECTION_CONFIG } from '../config/relay-config.js';
13
14
  export const DEFAULT_CONFIG = {
14
- maxFrameBytes: 1024 * 1024,
15
- heartbeatMs: 5000,
16
- // 6x multiplier = 30 second timeout, more tolerant for AI agents processing long responses
17
- heartbeatTimeoutMultiplier: 6,
15
+ ...DEFAULT_CONNECTION_CONFIG,
18
16
  };
19
17
  export class Connection {
20
18
  id;
@@ -38,6 +36,11 @@ export class Connection {
38
36
  lastPongReceived;
39
37
  // Sequence numbers per (topic, peer) stream
40
38
  sequences = new Map();
39
+ // Write queue for backpressure handling
40
+ writeQueue = [];
41
+ draining = false;
42
+ _backpressured = false;
43
+ socketDrainHandler;
41
44
  // Event handlers
42
45
  onMessage;
43
46
  onClose;
@@ -45,13 +48,16 @@ export class Connection {
45
48
  onActive; // Fires when connection transitions to ACTIVE state
46
49
  onAck;
47
50
  onPong; // Fires on successful heartbeat response
51
+ /** Fires when write queue crosses high/low water marks */
52
+ onBackpressure;
48
53
  constructor(socket, config = {}) {
49
- this.id = uuid();
54
+ this.id = generateId();
50
55
  this.socket = socket;
51
56
  this.config = { ...DEFAULT_CONFIG, ...config };
52
57
  this.parser = new FrameParser(this.config.maxFrameBytes);
53
- this._sessionId = uuid();
54
- this._resumeToken = uuid();
58
+ this.parser.setLegacyMode(true); // Use 4-byte header for backwards compatibility
59
+ this._sessionId = generateId();
60
+ this._resumeToken = generateId();
55
61
  this.setupSocketHandlers();
56
62
  this._state = 'HANDSHAKING';
57
63
  }
@@ -94,6 +100,14 @@ export class Connection {
94
100
  get isResumed() {
95
101
  return this._isResumed;
96
102
  }
103
+ /** Whether this connection is currently backpressured (write queue above high water mark) */
104
+ get backpressured() {
105
+ return this._backpressured;
106
+ }
107
+ /** Current number of messages queued for writing */
108
+ get writeQueueLength() {
109
+ return this.writeQueue.length;
110
+ }
97
111
  setupSocketHandlers() {
98
112
  this.socket.on('data', (data) => this.handleData(data));
99
113
  this.socket.on('close', () => this.handleClose());
@@ -187,7 +201,7 @@ export class Connection {
187
201
  const welcome = {
188
202
  v: PROTOCOL_VERSION,
189
203
  type: 'WELCOME',
190
- id: uuid(),
204
+ id: generateId(),
191
205
  ts: Date.now(),
192
206
  payload: {
193
207
  session_id: this._sessionId,
@@ -244,11 +258,11 @@ export class Connection {
244
258
  }
245
259
  }
246
260
  // Send ping
247
- const nonce = uuid();
261
+ const nonce = generateId();
248
262
  this.send({
249
263
  v: PROTOCOL_VERSION,
250
264
  type: 'PING',
251
- id: uuid(),
265
+ id: generateId(),
252
266
  ts: now,
253
267
  payload: { nonce },
254
268
  });
@@ -281,14 +295,33 @@ export class Connection {
281
295
  }
282
296
  /**
283
297
  * Send an envelope to this connection.
298
+ *
299
+ * Uses a write queue to prevent blocking on slow consumers.
300
+ * Returns false if the connection is closed or the queue is full.
284
301
  */
285
302
  send(envelope) {
286
- if (this._state === 'CLOSED' || this._state === 'ERROR') {
303
+ if (this._state === 'CLOSED' || this._state === 'ERROR' || this._state === 'CLOSING') {
304
+ console.log(`[connection] Send to ${this._agentName} blocked - state: ${this._state}`);
305
+ return false;
306
+ }
307
+ const maxQueueSize = this.config.maxWriteQueueSize ?? 2000;
308
+ const highWaterMark = this.config.writeQueueHighWaterMark ?? 1500;
309
+ // Check queue capacity
310
+ if (this.writeQueue.length >= maxQueueSize) {
311
+ // Queue full - this is a serious condition, log it
312
+ console.warn(`[connection] Write queue full for ${this._agentName ?? this.id}, dropping message`);
287
313
  return false;
288
314
  }
289
315
  try {
290
316
  const frame = encodeFrame(envelope);
291
- this.socket.write(frame);
317
+ this.writeQueue.push(frame);
318
+ // Check if we should signal backpressure
319
+ if (!this._backpressured && this.writeQueue.length >= highWaterMark) {
320
+ this._backpressured = true;
321
+ this.onBackpressure?.(true);
322
+ }
323
+ // Schedule drain if not already draining
324
+ this.scheduleDrain();
292
325
  return true;
293
326
  }
294
327
  catch (err) {
@@ -296,11 +329,53 @@ export class Connection {
296
329
  return false;
297
330
  }
298
331
  }
332
+ /**
333
+ * Schedule the drain loop to run on next tick if not already running.
334
+ */
335
+ scheduleDrain() {
336
+ if (this.draining)
337
+ return;
338
+ this.draining = true;
339
+ setImmediate(() => this.drain());
340
+ }
341
+ /**
342
+ * Drain the write queue to the socket.
343
+ * Respects socket backpressure by waiting for 'drain' events.
344
+ */
345
+ drain() {
346
+ while (this.writeQueue.length > 0) {
347
+ if (this._state === 'CLOSED' || this._state === 'ERROR' || this._state === 'CLOSING') {
348
+ this.draining = false;
349
+ return;
350
+ }
351
+ const frame = this.writeQueue[0];
352
+ const canWrite = this.socket.write(frame);
353
+ this.writeQueue.shift();
354
+ if (!canWrite) {
355
+ // Socket buffer full - wait for drain event
356
+ if (!this.socketDrainHandler) {
357
+ this.socketDrainHandler = () => {
358
+ this.socketDrainHandler = undefined;
359
+ this.drain();
360
+ };
361
+ this.socket.once('drain', this.socketDrainHandler);
362
+ }
363
+ return;
364
+ }
365
+ }
366
+ this.draining = false;
367
+ // Check if we should release backpressure
368
+ const lowWaterMark = this.config.writeQueueLowWaterMark ?? 500;
369
+ if (this._backpressured && this.writeQueue.length <= lowWaterMark) {
370
+ this._backpressured = false;
371
+ this.onBackpressure?.(false);
372
+ }
373
+ }
299
374
  sendError(code, message, fatal) {
300
375
  const error = {
301
376
  v: PROTOCOL_VERSION,
302
377
  type: 'ERROR',
303
- id: uuid(),
378
+ id: generateId(),
304
379
  ts: Date.now(),
305
380
  payload: {
306
381
  code: code,
@@ -329,18 +404,34 @@ export class Connection {
329
404
  }
330
405
  cleanup() {
331
406
  this.parser.reset();
407
+ // Clear write queue
408
+ this.writeQueue = [];
409
+ this.draining = false;
410
+ this._backpressured = false;
411
+ // Remove drain handler if registered
412
+ if (this.socketDrainHandler) {
413
+ this.socket.removeListener('drain', this.socketDrainHandler);
414
+ this.socketDrainHandler = undefined;
415
+ }
332
416
  }
333
417
  close() {
334
418
  if (this._state === 'CLOSED' || this._state === 'CLOSING')
335
419
  return;
336
420
  this._state = 'CLOSING';
337
- this.send({
338
- v: PROTOCOL_VERSION,
339
- type: 'BYE',
340
- id: uuid(),
341
- ts: Date.now(),
342
- payload: {},
343
- });
421
+ // Write BYE message directly (not via queue) to avoid race with socket.end()
422
+ try {
423
+ const byeFrame = encodeFrame({
424
+ v: PROTOCOL_VERSION,
425
+ type: 'BYE',
426
+ id: generateId(),
427
+ ts: Date.now(),
428
+ payload: {},
429
+ });
430
+ this.socket.write(byeFrame);
431
+ }
432
+ catch {
433
+ // Ignore write errors during close
434
+ }
344
435
  this.socket.end();
345
436
  }
346
437
  }
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Consensus Integration for Agent Relay
3
+ *
4
+ * Integrates the consensus mechanism with the router/daemon.
5
+ * This is an optional feature that can be enabled to allow agents
6
+ * to participate in distributed decision-making.
7
+ *
8
+ * Usage:
9
+ * 1. Create a ConsensusIntegration with the router and optional config
10
+ * 2. Call processIncomingMessage() on each received message to detect votes
11
+ * 3. Use createProposal() to start a new consensus vote
12
+ *
13
+ * Example:
14
+ * ```typescript
15
+ * const consensus = new ConsensusIntegration(router, { enabled: true });
16
+ *
17
+ * // Create a proposal
18
+ * consensus.createProposal({
19
+ * title: 'Approve API design',
20
+ * description: 'Should we proceed with the REST API design?',
21
+ * proposer: 'Architect',
22
+ * participants: ['Developer', 'Reviewer', 'Lead'],
23
+ * consensusType: 'majority',
24
+ * });
25
+ *
26
+ * // Process incoming messages to detect votes
27
+ * consensus.processIncomingMessage(from, body);
28
+ * ```
29
+ */
30
+ import { ConsensusEngine, createConsensusEngine, formatProposalMessage, formatResultMessage, parseVoteCommand, parseProposalCommand, isConsensusCommand, type Proposal, type ConsensusResult, type ConsensusConfig, type VoteValue, type ConsensusType, type ParsedProposalCommand } from './consensus.js';
31
+ import type { Router } from './router.js';
32
+ export interface CloudSyncConfig {
33
+ /** Cloud API base URL (defaults to AGENT_RELAY_CLOUD_URL or https://agent-relay.com) */
34
+ url?: string;
35
+ /** Daemon API key for authentication (defaults to AGENT_RELAY_API_KEY) */
36
+ apiKey?: string;
37
+ /** Workspace ID for self-hosted setups (optional - cloud can derive from API key) */
38
+ workspaceId?: string;
39
+ }
40
+ export interface ConsensusIntegrationConfig {
41
+ /** Enable consensus feature (default: true) */
42
+ enabled: boolean;
43
+ /** Consensus engine configuration */
44
+ consensus?: Partial<ConsensusConfig>;
45
+ /** Auto-broadcast proposals to participants (default: true) */
46
+ autoBroadcast?: boolean;
47
+ /** Auto-broadcast results when resolved (default: true) */
48
+ autoResultBroadcast?: boolean;
49
+ /** Log consensus events (default: true) */
50
+ logEvents?: boolean;
51
+ /** Cloud sync configuration (optional) */
52
+ cloudSync?: CloudSyncConfig;
53
+ }
54
+ export interface ProposalOptions {
55
+ title: string;
56
+ description: string;
57
+ proposer: string;
58
+ participants: string[];
59
+ consensusType?: ConsensusType;
60
+ timeoutMs?: number;
61
+ quorum?: number;
62
+ threshold?: number;
63
+ metadata?: Record<string, unknown>;
64
+ }
65
+ /**
66
+ * Integrates consensus mechanism with the relay router.
67
+ * Provides automatic proposal broadcasting and vote detection.
68
+ */
69
+ export declare class ConsensusIntegration {
70
+ private config;
71
+ private engine;
72
+ private router;
73
+ private log;
74
+ constructor(router: Router, config?: Partial<ConsensusIntegrationConfig>);
75
+ /**
76
+ * Check if consensus is enabled.
77
+ */
78
+ get enabled(): boolean;
79
+ /**
80
+ * Get the underlying consensus engine.
81
+ */
82
+ getEngine(): ConsensusEngine;
83
+ /**
84
+ * Create a new proposal and optionally broadcast to participants.
85
+ */
86
+ createProposal(options: ProposalOptions): Proposal;
87
+ /**
88
+ * Process an incoming message to detect and handle consensus commands.
89
+ * Handles both PROPOSE and VOTE commands.
90
+ */
91
+ processIncomingMessage(from: string, body: string): {
92
+ isConsensusCommand: boolean;
93
+ type?: 'propose' | 'vote';
94
+ result?: {
95
+ success: boolean;
96
+ error?: string;
97
+ proposal?: Proposal;
98
+ };
99
+ };
100
+ /**
101
+ * Check if a message is a consensus command without processing it.
102
+ */
103
+ isConsensusMessage(body: string): boolean;
104
+ /**
105
+ * Get pending proposals for an agent.
106
+ */
107
+ getPendingVotes(agentName: string): Proposal[];
108
+ /**
109
+ * Get all proposals for an agent.
110
+ */
111
+ getProposals(agentName: string): Proposal[];
112
+ /**
113
+ * Get a specific proposal by ID.
114
+ */
115
+ getProposal(proposalId: string): Proposal | null;
116
+ /**
117
+ * Cancel a proposal.
118
+ */
119
+ cancelProposal(proposalId: string, agentName: string): {
120
+ success: boolean;
121
+ error?: string;
122
+ };
123
+ /**
124
+ * Get consensus statistics.
125
+ */
126
+ getStats(): {
127
+ total: number;
128
+ pending: number;
129
+ approved: number;
130
+ rejected: number;
131
+ expired: number;
132
+ cancelled: number;
133
+ avgParticipation: number;
134
+ };
135
+ /**
136
+ * Cleanup resources.
137
+ */
138
+ cleanup(): void;
139
+ /**
140
+ * Sync a proposal to the cloud dashboard.
141
+ *
142
+ * Auto-detects cloud settings from workspace env vars:
143
+ * - CLOUD_API_URL / AGENT_RELAY_CLOUD_URL - cloud URL
144
+ * - WORKSPACE_ID / AGENT_RELAY_WORKSPACE_ID - workspace ID
145
+ * - WORKSPACE_TOKEN / AGENT_RELAY_API_KEY - auth token
146
+ */
147
+ private syncToCloud;
148
+ private setupEventHandlers;
149
+ /**
150
+ * Broadcast a proposal to all participants via the router.
151
+ */
152
+ private broadcastProposal;
153
+ /**
154
+ * Broadcast the result of a proposal to all participants.
155
+ */
156
+ private broadcastResult;
157
+ /**
158
+ * Send a message to an agent via the router.
159
+ */
160
+ private sendToAgent;
161
+ }
162
+ /**
163
+ * Create a consensus integration instance.
164
+ */
165
+ export declare function createConsensusIntegration(router: Router, config?: Partial<ConsensusIntegrationConfig>): ConsensusIntegration;
166
+ export { ConsensusEngine, createConsensusEngine, formatProposalMessage, formatResultMessage, parseVoteCommand, parseProposalCommand, isConsensusCommand, type Proposal, type ConsensusResult, type ConsensusConfig, type VoteValue, type ConsensusType, type ParsedProposalCommand, };
167
+ //# sourceMappingURL=consensus-integration.d.ts.map