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
@@ -0,0 +1,361 @@
1
+ /**
2
+ * Optimized Cloud Sync Queue
3
+ *
4
+ * Handles batched, compressed, resilient message syncing to cloud.
5
+ * Features:
6
+ * - Adaptive batching (size/time/bytes triggers)
7
+ * - Gzip compression for payloads over threshold
8
+ * - Disk spillover for offline resilience
9
+ * - Retry with exponential backoff
10
+ * - Startup reconciliation
11
+ */
12
+ import * as fs from 'node:fs/promises';
13
+ import * as path from 'node:path';
14
+ import * as os from 'node:os';
15
+ import { gzip } from 'node:zlib';
16
+ import { promisify } from 'node:util';
17
+ import { generateId } from '../utils/id-generator.js';
18
+ import { createLogger } from '../utils/logger.js';
19
+ const gzipAsync = promisify(gzip);
20
+ const log = createLogger('sync-queue');
21
+ export const DEFAULT_SYNC_QUEUE_CONFIG = {
22
+ cloudUrl: 'https://agent-relay.com',
23
+ apiKey: '',
24
+ batchSize: 100,
25
+ batchDelayMs: 200,
26
+ maxBatchBytes: 512 * 1024, // 512KB
27
+ compressionThreshold: 1024, // 1KB
28
+ spillDir: path.join(os.tmpdir(), 'agent-relay-sync'),
29
+ maxSpillFiles: 100,
30
+ maxRetries: 3,
31
+ retryDelayMs: 1000,
32
+ verbose: false,
33
+ };
34
+ export class SyncQueue {
35
+ config;
36
+ queue = [];
37
+ queueBytes = 0;
38
+ flushTimer;
39
+ flushing = false;
40
+ flushPromise;
41
+ // Stats
42
+ stats = {
43
+ queuedMessages: 0,
44
+ queuedBytes: 0,
45
+ totalSynced: 0,
46
+ totalFailed: 0,
47
+ totalCompressed: 0,
48
+ totalBytesTransferred: 0,
49
+ spilledFiles: 0,
50
+ };
51
+ constructor(config) {
52
+ this.config = { ...DEFAULT_SYNC_QUEUE_CONFIG, ...config };
53
+ }
54
+ /**
55
+ * Queue a message for sync to cloud.
56
+ * May trigger an immediate flush if thresholds are exceeded.
57
+ */
58
+ async enqueue(message) {
59
+ // Wait for any in-progress flush
60
+ if (this.flushPromise) {
61
+ await this.flushPromise;
62
+ }
63
+ const msgJson = JSON.stringify(message);
64
+ const sizeBytes = Buffer.byteLength(msgJson, 'utf-8');
65
+ this.queue.push({ message, sizeBytes });
66
+ this.queueBytes += sizeBytes;
67
+ this.stats.queuedMessages = this.queue.length;
68
+ this.stats.queuedBytes = this.queueBytes;
69
+ // Check flush triggers
70
+ const shouldFlush = this.queue.length >= this.config.batchSize ||
71
+ this.queueBytes >= this.config.maxBatchBytes;
72
+ if (shouldFlush) {
73
+ await this.flush();
74
+ }
75
+ else if (!this.flushTimer) {
76
+ this.flushTimer = setTimeout(() => {
77
+ this.flush().catch((err) => {
78
+ log.error('Timer flush failed', { error: String(err) });
79
+ });
80
+ }, this.config.batchDelayMs);
81
+ }
82
+ }
83
+ /**
84
+ * Enqueue multiple messages at once.
85
+ */
86
+ async enqueueBatch(messages) {
87
+ for (const msg of messages) {
88
+ await this.enqueue(msg);
89
+ }
90
+ }
91
+ /**
92
+ * Flush all queued messages to cloud.
93
+ */
94
+ async flush() {
95
+ // Clear timer
96
+ if (this.flushTimer) {
97
+ clearTimeout(this.flushTimer);
98
+ this.flushTimer = undefined;
99
+ }
100
+ // Skip if empty or already flushing
101
+ if (this.queue.length === 0 || this.flushing) {
102
+ return { synced: 0, duplicates: 0, failed: 0, compressed: false, bytesTransferred: 0 };
103
+ }
104
+ this.flushing = true;
105
+ // Take current batch
106
+ const batch = this.queue;
107
+ const batchBytes = this.queueBytes;
108
+ this.queue = [];
109
+ this.queueBytes = 0;
110
+ this.stats.queuedMessages = 0;
111
+ this.stats.queuedBytes = 0;
112
+ this.flushPromise = this.syncBatch(batch, batchBytes);
113
+ try {
114
+ const result = await this.flushPromise;
115
+ return result;
116
+ }
117
+ finally {
118
+ this.flushing = false;
119
+ this.flushPromise = undefined;
120
+ }
121
+ }
122
+ /**
123
+ * Sync a batch of messages to cloud with retry and spillover.
124
+ */
125
+ async syncBatch(batch, batchBytes) {
126
+ const messages = batch.map((q) => q.message);
127
+ let lastError = null;
128
+ for (let attempt = 0; attempt < this.config.maxRetries; attempt++) {
129
+ try {
130
+ const result = await this.sendToCloud(messages, batchBytes);
131
+ this.stats.totalSynced += result.synced;
132
+ this.stats.totalBytesTransferred += result.bytesTransferred;
133
+ if (result.compressed) {
134
+ this.stats.totalCompressed++;
135
+ }
136
+ this.stats.lastSyncAt = Date.now();
137
+ return result;
138
+ }
139
+ catch (err) {
140
+ lastError = err;
141
+ this.stats.lastError = lastError.message;
142
+ if (attempt < this.config.maxRetries - 1) {
143
+ // Exponential backoff
144
+ const delay = this.config.retryDelayMs * Math.pow(2, attempt);
145
+ if (this.config.verbose) {
146
+ log.warn(`Sync attempt ${attempt + 1} failed, retrying in ${delay}ms`, {
147
+ error: lastError.message,
148
+ });
149
+ }
150
+ await this.sleep(delay);
151
+ }
152
+ }
153
+ }
154
+ // All retries failed - spill to disk
155
+ log.error('Sync failed after retries, spilling to disk', {
156
+ count: messages.length,
157
+ error: lastError?.message,
158
+ });
159
+ await this.spillToDisk(messages);
160
+ this.stats.totalFailed += messages.length;
161
+ return {
162
+ synced: 0,
163
+ duplicates: 0,
164
+ failed: messages.length,
165
+ compressed: false,
166
+ bytesTransferred: 0,
167
+ };
168
+ }
169
+ /**
170
+ * Send messages to cloud API with optional compression.
171
+ */
172
+ async sendToCloud(messages, _estimatedBytes) {
173
+ // Transform to API format
174
+ const syncPayload = {
175
+ messages: messages.map((msg) => ({
176
+ id: msg.id,
177
+ ts: msg.ts,
178
+ from: msg.from,
179
+ to: msg.to,
180
+ body: msg.body,
181
+ kind: msg.kind,
182
+ topic: msg.topic,
183
+ thread: msg.thread,
184
+ is_broadcast: msg.is_broadcast,
185
+ is_urgent: msg.is_urgent,
186
+ data: msg.data,
187
+ payload_meta: msg.payloadMeta,
188
+ })),
189
+ };
190
+ const payloadJson = JSON.stringify(syncPayload);
191
+ const payloadBytes = Buffer.byteLength(payloadJson, 'utf-8');
192
+ // Determine if we should compress
193
+ const shouldCompress = payloadBytes > this.config.compressionThreshold;
194
+ let body;
195
+ let contentEncoding;
196
+ if (shouldCompress) {
197
+ body = await gzipAsync(Buffer.from(payloadJson));
198
+ contentEncoding = 'gzip';
199
+ if (this.config.verbose) {
200
+ const ratio = ((1 - body.length / payloadBytes) * 100).toFixed(1);
201
+ log.info(`Compressed ${payloadBytes} → ${body.length} bytes (${ratio}% reduction)`);
202
+ }
203
+ }
204
+ else {
205
+ body = payloadJson;
206
+ }
207
+ const headers = {
208
+ Authorization: `Bearer ${this.config.apiKey}`,
209
+ 'Content-Type': 'application/json',
210
+ };
211
+ if (contentEncoding) {
212
+ headers['Content-Encoding'] = contentEncoding;
213
+ }
214
+ const response = await fetch(`${this.config.cloudUrl}/api/daemons/messages/sync`, {
215
+ method: 'POST',
216
+ headers,
217
+ body,
218
+ });
219
+ if (!response.ok) {
220
+ const errorText = await response.text();
221
+ throw new Error(`Sync failed: ${response.status} - ${errorText}`);
222
+ }
223
+ const result = (await response.json());
224
+ return {
225
+ synced: result.synced,
226
+ duplicates: result.duplicates,
227
+ failed: 0,
228
+ compressed: shouldCompress,
229
+ bytesTransferred: typeof body === 'string' ? Buffer.byteLength(body) : body.length,
230
+ };
231
+ }
232
+ /**
233
+ * Spill failed batch to disk for later recovery.
234
+ */
235
+ async spillToDisk(messages) {
236
+ try {
237
+ await fs.mkdir(this.config.spillDir, { recursive: true });
238
+ const filename = `spill-${Date.now()}-${generateId().replace(/-/g, '')}.json`;
239
+ const filepath = path.join(this.config.spillDir, filename);
240
+ await fs.writeFile(filepath, JSON.stringify(messages));
241
+ this.stats.spilledFiles++;
242
+ if (this.config.verbose) {
243
+ log.info(`Spilled ${messages.length} messages to ${filename}`);
244
+ }
245
+ // Cleanup old spill files
246
+ await this.cleanupSpillFiles();
247
+ }
248
+ catch (err) {
249
+ log.error('Failed to spill to disk', { error: String(err) });
250
+ }
251
+ }
252
+ /**
253
+ * Recover and sync messages from spill files.
254
+ * Call this on startup to resume failed syncs.
255
+ */
256
+ async recoverSpilledMessages() {
257
+ let recovered = 0;
258
+ let failed = 0;
259
+ try {
260
+ const files = await fs.readdir(this.config.spillDir);
261
+ const spillFiles = files.filter((f) => f.startsWith('spill-')).sort();
262
+ for (const file of spillFiles) {
263
+ const filepath = path.join(this.config.spillDir, file);
264
+ try {
265
+ const content = await fs.readFile(filepath, 'utf-8');
266
+ const messages = JSON.parse(content);
267
+ // Try to sync
268
+ const result = await this.sendToCloud(messages, Buffer.byteLength(content, 'utf-8'));
269
+ if (result.synced > 0 || result.duplicates > 0) {
270
+ // Success - remove spill file
271
+ await fs.unlink(filepath);
272
+ recovered += messages.length;
273
+ this.stats.spilledFiles = Math.max(0, this.stats.spilledFiles - 1);
274
+ if (this.config.verbose) {
275
+ log.info(`Recovered ${messages.length} messages from ${file}`);
276
+ }
277
+ }
278
+ else {
279
+ failed += messages.length;
280
+ }
281
+ }
282
+ catch (err) {
283
+ log.warn(`Failed to recover ${file}`, { error: String(err) });
284
+ failed++;
285
+ }
286
+ }
287
+ }
288
+ catch (err) {
289
+ // Directory doesn't exist or other error
290
+ if (err.code !== 'ENOENT') {
291
+ log.error('Failed to scan spill directory', { error: String(err) });
292
+ }
293
+ }
294
+ if (recovered > 0) {
295
+ log.info(`Recovered ${recovered} messages from spill files`);
296
+ }
297
+ return { recovered, failed };
298
+ }
299
+ /**
300
+ * Cleanup old spill files beyond the limit.
301
+ */
302
+ async cleanupSpillFiles() {
303
+ try {
304
+ const files = await fs.readdir(this.config.spillDir);
305
+ const spillFiles = files.filter((f) => f.startsWith('spill-')).sort();
306
+ if (spillFiles.length > this.config.maxSpillFiles) {
307
+ const toDelete = spillFiles.slice(0, spillFiles.length - this.config.maxSpillFiles);
308
+ for (const file of toDelete) {
309
+ await fs.unlink(path.join(this.config.spillDir, file)).catch(() => { });
310
+ }
311
+ if (this.config.verbose) {
312
+ log.info(`Cleaned up ${toDelete.length} old spill files`);
313
+ }
314
+ }
315
+ }
316
+ catch {
317
+ // Ignore cleanup errors
318
+ }
319
+ }
320
+ /**
321
+ * Get sync queue statistics.
322
+ */
323
+ getStats() {
324
+ return { ...this.stats };
325
+ }
326
+ /**
327
+ * Reset statistics (for testing or periodic reporting).
328
+ */
329
+ resetStats() {
330
+ this.stats = {
331
+ queuedMessages: this.queue.length,
332
+ queuedBytes: this.queueBytes,
333
+ totalSynced: 0,
334
+ totalFailed: 0,
335
+ totalCompressed: 0,
336
+ totalBytesTransferred: 0,
337
+ spilledFiles: this.stats.spilledFiles, // Preserve spill count
338
+ };
339
+ }
340
+ /**
341
+ * Gracefully close the queue, flushing any pending messages.
342
+ */
343
+ async close() {
344
+ if (this.flushTimer) {
345
+ clearTimeout(this.flushTimer);
346
+ this.flushTimer = undefined;
347
+ }
348
+ // Wait for any in-progress flush
349
+ if (this.flushPromise) {
350
+ await this.flushPromise;
351
+ }
352
+ // Flush remaining
353
+ if (this.queue.length > 0) {
354
+ await this.flush();
355
+ }
356
+ }
357
+ sleep(ms) {
358
+ return new Promise((resolve) => setTimeout(resolve, ms));
359
+ }
360
+ }
361
+ //# sourceMappingURL=sync-queue.js.map
@@ -1 +1 @@
1
- <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/48a8fbe3e659080e.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-1cdd8ed57114d5e1.js"/><script src="/_next/static/chunks/fd9d1056-609918ca7b6280bb.js" async=""></script><script src="/_next/static/chunks/117-f7b8ab0809342e77.js" async=""></script><script src="/_next/static/chunks/main-app-6e8e8d3ef4e0192a.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>Agent Relay Dashboard</title><meta name="description" content="Fleet control dashboard for Agent Relay"/><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><script src="/_next/static/chunks/webpack-1cdd8ed57114d5e1.js" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/_next/static/css/48a8fbe3e659080e.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"2:I[2846,[],\"\"]\n4:I[4707,[],\"\"]\n5:I[6423,[],\"\"]\nb:I[1060,[],\"\"]\n6:{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"}\n7:{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"}\n8:{\"display\":\"inline-block\"}\n9:{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0}\nc:[]\n"])</script><script>self.__next_f.push([1,"0:[\"$\",\"$L2\",null,{\"buildId\":\"sDcbGRTYLcpPvyTs_rsNb\",\"assetPrefix\":\"\",\"urlParts\":[\"\",\"_not-found\"],\"initialTree\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{},[[\"$L3\",[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null],null],null]},[null,[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\",\"/_not-found\",\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"notFoundStyles\":\"$undefined\"}]],null]},[[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/48a8fbe3e659080e.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"children\":[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$6\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$7\",\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":\"$8\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$9\",\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[]}]}]}]],null],null],\"couldBeIntercepted\":false,\"initialHead\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],\"$La\"],\"globalErrorComponent\":\"$b\",\"missingSlots\":\"$Wc\"}]\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"Agent Relay Dashboard\"}],[\"$\",\"meta\",\"3\",{\"name\":\"description\",\"content\":\"Fleet control dashboard for Agent Relay\"}]]\n3:null\n"])</script></body></html>
1
+ <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/44d2b52637b511bc.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-1cdd8ed57114d5e1.js"/><script src="/_next/static/chunks/fd9d1056-609918ca7b6280bb.js" async=""></script><script src="/_next/static/chunks/117-f7b8ab0809342e77.js" async=""></script><script src="/_next/static/chunks/main-app-6e8e8d3ef4e0192a.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>Agent Relay Dashboard</title><meta name="description" content="Fleet control dashboard for Agent Relay"/><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><script src="/_next/static/chunks/webpack-1cdd8ed57114d5e1.js" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/_next/static/css/44d2b52637b511bc.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"2:I[2846,[],\"\"]\n4:I[4707,[],\"\"]\n5:I[6423,[],\"\"]\nb:I[1060,[],\"\"]\n6:{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"}\n7:{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"}\n8:{\"display\":\"inline-block\"}\n9:{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0}\nc:[]\n"])</script><script>self.__next_f.push([1,"0:[\"$\",\"$L2\",null,{\"buildId\":\"R-uQOUcOLINtsp6ACeZa9\",\"assetPrefix\":\"\",\"urlParts\":[\"\",\"_not-found\"],\"initialTree\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{},[[\"$L3\",[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null],null],null]},[null,[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\",\"/_not-found\",\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"notFoundStyles\":\"$undefined\"}]],null]},[[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/44d2b52637b511bc.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"children\":[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$6\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$7\",\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":\"$8\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$9\",\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[]}]}]}]],null],null],\"couldBeIntercepted\":false,\"initialHead\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],\"$La\"],\"globalErrorComponent\":\"$b\",\"missingSlots\":\"$Wc\"}]\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"Agent Relay Dashboard\"}],[\"$\",\"meta\",\"3\",{\"name\":\"description\",\"content\":\"Fleet control dashboard for Agent Relay\"}]]\n3:null\n"])</script></body></html>
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[116],{9116:function(e,r,t){t.d(r,{$3:function(){return i},XP:function(){return y},aM:function(){return o},hc:function(){return n},hi:function(){return w},kG:function(){return d}});let s="agentrelay_workspace_id",a=null,c=null;function o(e){c=e}function n(e){a=e,e?localStorage.setItem(s,e):localStorage.removeItem(s)}function i(){if(a)return a;{let e=localStorage.getItem(s);if(e)return a=e,e}return null}let u=["/api/daemons/","/api/workspaces/","/api/providers/","/api/auth/","/api/billing/","/api/usage/","/api/admin/","/api/onboarding/","/api/repos/","/api/project-groups/","/api/github-app/"];function d(e){if(a){if(u.some(r=>e.startsWith(r)))return"".concat("").concat(e);let r=e.startsWith("/api/")?e.substring(5):e.replace(/^\//,"");return"/api/workspaces/".concat(a,"/proxy/").concat(r)}return"".concat("").concat(e)}async function l(e){var r;let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},s=(null===(r=t.method)||void 0===r?void 0:r.toUpperCase())||"GET",a={...t.headers};"GET"!==s&&"HEAD"!==s&&"OPTIONS"!==s&&(c&&(a["X-CSRF-Token"]=c),t.body&&!a["Content-Type"]&&(a["Content-Type"]="application/json"));let o=await fetch(e,{...t,headers:a,credentials:"include"});return!function(e){let r=e.headers.get("X-CSRF-Token");r&&(c=r)}(o),o}let w={async get(e){let r=await l(d(e),{method:"GET"});if(!r.ok)throw Error("HTTP ".concat(r.status,": ").concat(r.statusText));return await r.json()},async post(e,r){let t=await l(d(e),{method:"POST",body:r?JSON.stringify(r):void 0});if(!t.ok)throw Error("HTTP ".concat(t.status,": ").concat(t.statusText));return await t.json()},async patch(e,r){let t=await l(d(e),{method:"PATCH",body:r?JSON.stringify(r):void 0});if(!t.ok)throw Error("HTTP ".concat(t.status,": ").concat(t.statusText));return await t.json()},async delete(e){let r=await l(d(e),{method:"DELETE"});if(!r.ok)throw Error("HTTP ".concat(r.status,": ").concat(r.statusText));return await r.json()},async sendMessage(e){try{let r=await l(d("/api/send"),{method:"POST",body:JSON.stringify(e)}),t=await r.json();if(r.ok&&t.success)return{success:!0};return{success:!1,error:t.error||"Failed to send message"}}catch(e){return{success:!1,error:"Network error"}}},async uploadAttachment(e){try{let r,t,s;e instanceof File?(r=e.name,t=e.type,s=await new Promise((r,t)=>{let s=new FileReader;s.onload=()=>r(s.result),s.onerror=t,s.readAsDataURL(e)})):(r=e.filename,t=e.mimeType,s=e.data);let a=await l(d("/api/upload"),{method:"POST",body:JSON.stringify({filename:r,mimeType:t,data:s})}),c=await a.json();if(a.ok&&c.success&&c.attachment)return{success:!0,data:{attachment:c.attachment}};return{success:!1,error:c.error||"Failed to upload attachment"}}catch(e){return{success:!1,error:"Network error"}}},async spawnAgent(e){try{let r=await l(d("/api/spawn"),{method:"POST",body:JSON.stringify(e)});return await r.json()}catch(r){return{success:!1,name:e.name,error:"Network error"}}},async getSpawnedAgents(){try{let e=await l(d("/api/spawned")),r=await e.json();if(e.ok&&r.success)return{success:!0,data:{agents:r.agents||[]}};return{success:!1,error:r.error}}catch(e){return{success:!1,error:"Network error"}}},async releaseAgent(e){try{let r=await l(d("/api/spawned/".concat(encodeURIComponent(e))),{method:"DELETE"}),t=await r.json();if(r.ok&&t.success)return{success:!0};return{success:!1,error:t.error}}catch(e){return{success:!1,error:"Network error"}}},async interruptAgent(e){try{let r=await l(d("/api/agents/by-name/".concat(encodeURIComponent(e),"/interrupt")),{method:"POST"}),t=await r.json();if(r.ok&&t.success)return{success:!0};return{success:!1,error:t.error||"Failed to interrupt agent"}}catch(e){return{success:!1,error:"Network error"}}},async getData(){try{let e=await l(d("/api/data")),r=await e.json();if(e.ok)return{success:!0,data:r};return{success:!1,error:"Failed to fetch data"}}catch(e){return{success:!1,error:"Network error"}}},async getBridgeData(){try{let e=await l(d("/api/bridge")),r=await e.json();if(e.ok)return{success:!0,data:r};return{success:!1,error:"Failed to fetch bridge data"}}catch(e){return{success:!1,error:"Network error"}}},async getMetrics(){try{let e=await l(d("/api/metrics")),r=await e.json();if(e.ok)return{success:!0,data:r};return{success:!1,error:"Failed to fetch metrics"}}catch(e){return{success:!1,error:"Network error"}}},async getHistorySessions(e){try{let r=new URLSearchParams;(null==e?void 0:e.agent)&&r.set("agent",e.agent),(null==e?void 0:e.since)&&r.set("since",String(e.since)),(null==e?void 0:e.limit)&&r.set("limit",String(e.limit));let t=await l(d("/api/history/sessions?".concat(r))),s=await t.json();if(t.ok)return{success:!0,data:s};return{success:!1,error:"Failed to fetch sessions"}}catch(e){return{success:!1,error:"Network error"}}},async getHistoryMessages(e){try{let r=new URLSearchParams;(null==e?void 0:e.from)&&r.set("from",e.from),(null==e?void 0:e.to)&&r.set("to",e.to),(null==e?void 0:e.thread)&&r.set("thread",e.thread),(null==e?void 0:e.since)&&r.set("since",String(e.since)),(null==e?void 0:e.limit)&&r.set("limit",String(e.limit)),(null==e?void 0:e.order)&&r.set("order",e.order),(null==e?void 0:e.search)&&r.set("search",e.search);let t=await l(d("/api/history/messages?".concat(r))),s=await t.json();if(t.ok)return{success:!0,data:s};return{success:!1,error:"Failed to fetch messages"}}catch(e){return{success:!1,error:"Network error"}}},async getHistoryConversations(){try{let e=await l(d("/api/history/conversations")),r=await e.json();if(e.ok)return{success:!0,data:r};return{success:!1,error:"Failed to fetch conversations"}}catch(e){return{success:!1,error:"Network error"}}},async getHistoryMessage(e){try{let r=await l(d("/api/history/message/".concat(encodeURIComponent(e)))),t=await r.json();if(r.ok)return{success:!0,data:t};return{success:!1,error:t.error||"Failed to fetch message"}}catch(e){return{success:!1,error:"Network error"}}},async getHistoryStats(){try{let e=await l(d("/api/history/stats")),r=await e.json();if(e.ok)return{success:!0,data:r};return{success:!1,error:"Failed to fetch stats"}}catch(e){return{success:!1,error:"Network error"}}},async searchFiles(e){try{let r=new URLSearchParams;(null==e?void 0:e.query)&&r.set("q",e.query),(null==e?void 0:e.limit)&&r.set("limit",String(e.limit));let t=await l(d("/api/files?".concat(r))),s=await t.json();if(t.ok)return{success:!0,data:s};return{success:!1,error:"Failed to search files"}}catch(e){return{success:!1,error:"Network error"}}},async getDecisions(){try{let e=await l(d("/api/decisions")),r=await e.json();if(e.ok&&r.success)return{success:!0,data:{decisions:r.decisions||[]}};return{success:!1,error:r.error||"Failed to fetch decisions"}}catch(e){return{success:!1,error:"Network error"}}},async approveDecision(e,r,t){try{let s=await l(d("/api/decisions/".concat(encodeURIComponent(e),"/approve")),{method:"POST",body:JSON.stringify({optionId:r,response:t})}),a=await s.json();if(s.ok&&a.success)return{success:!0};return{success:!1,error:a.error||"Failed to approve decision"}}catch(e){return{success:!1,error:"Network error"}}},async rejectDecision(e,r){try{let t=await l(d("/api/decisions/".concat(encodeURIComponent(e),"/reject")),{method:"POST",body:JSON.stringify({reason:r})}),s=await t.json();if(t.ok&&s.success)return{success:!0};return{success:!1,error:s.error||"Failed to reject decision"}}catch(e){return{success:!1,error:"Network error"}}},async dismissDecision(e){try{let r=await l(d("/api/decisions/".concat(encodeURIComponent(e))),{method:"DELETE"}),t=await r.json();if(r.ok&&t.success)return{success:!0};return{success:!1,error:t.error||"Failed to dismiss decision"}}catch(e){return{success:!1,error:"Network error"}}},async getFleetServers(){try{let e=await l(d("/api/fleet/servers")),r=await e.json();if(e.ok&&r.success)return{success:!0,data:{servers:r.servers||[]}};return{success:!1,error:r.error||"Failed to fetch fleet servers"}}catch(e){return{success:!1,error:"Network error"}}},async getFleetStats(){try{let e=await l(d("/api/fleet/stats")),r=await e.json();if(e.ok&&r.success)return{success:!0,data:{stats:r.stats}};return{success:!1,error:r.error||"Failed to fetch fleet stats"}}catch(e){return{success:!1,error:"Network error"}}},async getTasks(e){try{let r=new URLSearchParams;(null==e?void 0:e.status)&&r.set("status",e.status),(null==e?void 0:e.agent)&&r.set("agent",e.agent);let t=await l(d("/api/tasks?".concat(r))),s=await t.json();if(t.ok&&s.success)return{success:!0,data:{tasks:s.tasks||[]}};return{success:!1,error:s.error||"Failed to fetch tasks"}}catch(e){return{success:!1,error:"Network error"}}},async createTask(e){try{let r=await l(d("/api/tasks"),{method:"POST",body:JSON.stringify(e)}),t=await r.json();if(r.ok&&t.success)return{success:!0,data:{task:t.task}};return{success:!1,error:t.error||"Failed to create task"}}catch(e){return{success:!1,error:"Network error"}}},async updateTask(e,r){try{let t=await l(d("/api/tasks/".concat(encodeURIComponent(e))),{method:"PATCH",body:JSON.stringify(r)}),s=await t.json();if(t.ok&&s.success)return{success:!0,data:{task:s.task}};return{success:!1,error:s.error||"Failed to update task"}}catch(e){return{success:!1,error:"Network error"}}},async cancelTask(e){try{let r=await l(d("/api/tasks/".concat(encodeURIComponent(e))),{method:"DELETE"}),t=await r.json();if(r.ok&&t.success)return{success:!0};return{success:!1,error:t.error||"Failed to cancel task"}}catch(e){return{success:!1,error:"Network error"}}},async createBead(e){try{let r=await l(d("/api/beads"),{method:"POST",body:JSON.stringify(e)}),t=await r.json();if(r.ok&&t.success)return{success:!0,data:{bead:t.bead}};return{success:!1,error:t.error||"Failed to create bead"}}catch(e){return{success:!1,error:"Network error"}}},async sendRelayMessage(e){try{let r=await l(d("/api/relay/send"),{method:"POST",body:JSON.stringify(e)}),t=await r.json();if(r.ok&&t.success)return{success:!0,data:{messageId:t.messageId}};return{success:!1,error:t.error||"Failed to send message"}}catch(e){return{success:!1,error:"Network error"}}}};function y(e){return{id:e.id,agentName:e.agentName,timestamp:e.createdAt,type:e.category,title:e.title,description:e.description,options:e.options,priority:e.urgency,context:e.context,expiresAt:e.expiresAt}}}}]);
@@ -0,0 +1 @@
1
+ (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[847],{9376:function(e,t,n){"use strict";var r=n(5475);n.o(r,"useRouter")&&n.d(t,{useRouter:function(){return r.useRouter}}),n.o(r,"useSearchParams")&&n.d(t,{useSearchParams:function(){return r.useSearchParams}})},257:function(e,t,n){"use strict";var r,i;e.exports=(null==(r=n.g.process)?void 0:r.env)&&"object"==typeof(null==(i=n.g.process)?void 0:i.env)?n.g.process:n(4227)},4601:function(){},4227:function(e){!function(){var t={229:function(e){var t,n,r,i=e.exports={};function s(){throw Error("setTimeout has not been defined")}function o(){throw Error("clearTimeout has not been defined")}function u(e){if(t===setTimeout)return setTimeout(e,0);if((t===s||!t)&&setTimeout)return t=setTimeout,setTimeout(e,0);try{return t(e,0)}catch(n){try{return t.call(null,e,0)}catch(n){return t.call(this,e,0)}}}!function(){try{t="function"==typeof setTimeout?setTimeout:s}catch(e){t=s}try{n="function"==typeof clearTimeout?clearTimeout:o}catch(e){n=o}}();var c=[],l=!1,a=-1;function h(){l&&r&&(l=!1,r.length?c=r.concat(c):a=-1,c.length&&d())}function d(){if(!l){var e=u(h);l=!0;for(var t=c.length;t;){for(r=c,c=[];++a<t;)r&&r[a].run();a=-1,t=c.length}r=null,l=!1,function(e){if(n===clearTimeout)return clearTimeout(e);if((n===o||!n)&&clearTimeout)return n=clearTimeout,clearTimeout(e);try{n(e)}catch(t){try{return n.call(null,e)}catch(t){return n.call(this,e)}}}(e)}}function f(e,t){this.fun=e,this.array=t}function p(){}i.nextTick=function(e){var t=Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];c.push(new f(e,t)),1!==c.length||l||u(d)},f.prototype.run=function(){this.fun.apply(null,this.array)},i.title="browser",i.browser=!0,i.env={},i.argv=[],i.version="",i.versions={},i.on=p,i.addListener=p,i.once=p,i.off=p,i.removeListener=p,i.removeAllListeners=p,i.emit=p,i.prependListener=p,i.prependOnceListener=p,i.listeners=function(e){return[]},i.binding=function(e){throw Error("process.binding is not supported")},i.cwd=function(){return"/"},i.chdir=function(e){throw Error("process.chdir is not supported")},i.umask=function(){return 0}}},n={};function r(e){var i=n[e];if(void 0!==i)return i.exports;var s=n[e]={exports:{}},o=!0;try{t[e](s,s.exports,r),o=!1}finally{o&&delete n[e]}return s.exports}r.ab="//";var i=r(229);e.exports=i}()},8975:function(e,t,n){"use strict";var r=n(257);n(4601);var i=n(2265),s=i&&"object"==typeof i&&"default"in i?i:{default:i},o=void 0!==r&&r.env&&!0,u=function(e){return"[object String]"===Object.prototype.toString.call(e)},c=function(){function e(e){var t=void 0===e?{}:e,n=t.name,r=void 0===n?"stylesheet":n,i=t.optimizeForSpeed,s=void 0===i?o:i;l(u(r),"`name` must be a string"),this._name=r,this._deletedRulePlaceholder="#"+r+"-deleted-rule____{}",l("boolean"==typeof s,"`optimizeForSpeed` must be a boolean"),this._optimizeForSpeed=s,this._serverSheet=void 0,this._tags=[],this._injected=!1,this._rulesCount=0;var c="undefined"!=typeof window&&document.querySelector('meta[property="csp-nonce"]');this._nonce=c?c.getAttribute("content"):null}var t=e.prototype;return t.setOptimizeForSpeed=function(e){l("boolean"==typeof e,"`setOptimizeForSpeed` accepts a boolean"),l(0===this._rulesCount,"optimizeForSpeed cannot be when rules have already been inserted"),this.flush(),this._optimizeForSpeed=e,this.inject()},t.isOptimizeForSpeed=function(){return this._optimizeForSpeed},t.inject=function(){var e=this;if(l(!this._injected,"sheet already injected"),this._injected=!0,"undefined"!=typeof window&&this._optimizeForSpeed){this._tags[0]=this.makeStyleTag(this._name),this._optimizeForSpeed="insertRule"in this.getSheet(),this._optimizeForSpeed||(o||console.warn("StyleSheet: optimizeForSpeed mode not supported falling back to standard mode."),this.flush(),this._injected=!0);return}this._serverSheet={cssRules:[],insertRule:function(t,n){return"number"==typeof n?e._serverSheet.cssRules[n]={cssText:t}:e._serverSheet.cssRules.push({cssText:t}),n},deleteRule:function(t){e._serverSheet.cssRules[t]=null}}},t.getSheetForTag=function(e){if(e.sheet)return e.sheet;for(var t=0;t<document.styleSheets.length;t++)if(document.styleSheets[t].ownerNode===e)return document.styleSheets[t]},t.getSheet=function(){return this.getSheetForTag(this._tags[this._tags.length-1])},t.insertRule=function(e,t){if(l(u(e),"`insertRule` accepts only strings"),"undefined"==typeof window)return"number"!=typeof t&&(t=this._serverSheet.cssRules.length),this._serverSheet.insertRule(e,t),this._rulesCount++;if(this._optimizeForSpeed){var n=this.getSheet();"number"!=typeof t&&(t=n.cssRules.length);try{n.insertRule(e,t)}catch(t){return o||console.warn("StyleSheet: illegal rule: \n\n"+e+"\n\nSee https://stackoverflow.com/q/20007992 for more info"),-1}}else{var r=this._tags[t];this._tags.push(this.makeStyleTag(this._name,e,r))}return this._rulesCount++},t.replaceRule=function(e,t){if(this._optimizeForSpeed||"undefined"==typeof window){var n="undefined"!=typeof window?this.getSheet():this._serverSheet;if(t.trim()||(t=this._deletedRulePlaceholder),!n.cssRules[e])return e;n.deleteRule(e);try{n.insertRule(t,e)}catch(r){o||console.warn("StyleSheet: illegal rule: \n\n"+t+"\n\nSee https://stackoverflow.com/q/20007992 for more info"),n.insertRule(this._deletedRulePlaceholder,e)}}else{var r=this._tags[e];l(r,"old rule at index `"+e+"` not found"),r.textContent=t}return e},t.deleteRule=function(e){if("undefined"==typeof window){this._serverSheet.deleteRule(e);return}if(this._optimizeForSpeed)this.replaceRule(e,"");else{var t=this._tags[e];l(t,"rule at index `"+e+"` not found"),t.parentNode.removeChild(t),this._tags[e]=null}},t.flush=function(){this._injected=!1,this._rulesCount=0,"undefined"!=typeof window?(this._tags.forEach(function(e){return e&&e.parentNode.removeChild(e)}),this._tags=[]):this._serverSheet.cssRules=[]},t.cssRules=function(){var e=this;return"undefined"==typeof window?this._serverSheet.cssRules:this._tags.reduce(function(t,n){return n?t=t.concat(Array.prototype.map.call(e.getSheetForTag(n).cssRules,function(t){return t.cssText===e._deletedRulePlaceholder?null:t})):t.push(null),t},[])},t.makeStyleTag=function(e,t,n){t&&l(u(t),"makeStyleTag accepts only strings as second parameter");var r=document.createElement("style");this._nonce&&r.setAttribute("nonce",this._nonce),r.type="text/css",r.setAttribute("data-"+e,""),t&&r.appendChild(document.createTextNode(t));var i=document.head||document.getElementsByTagName("head")[0];return n?i.insertBefore(r,n):i.appendChild(r),r},function(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(e.prototype,[{key:"length",get:function(){return this._rulesCount}}]),e}();function l(e,t){if(!e)throw Error("StyleSheet: "+t+".")}var a=function(e){for(var t=5381,n=e.length;n;)t=33*t^e.charCodeAt(--n);return t>>>0},h={};function d(e,t){if(!t)return"jsx-"+e;var n=String(t),r=e+n;return h[r]||(h[r]="jsx-"+a(e+"-"+n)),h[r]}function f(e,t){"undefined"==typeof window&&(t=t.replace(/\/style/gi,"\\/style"));var n=e+t;return h[n]||(h[n]=t.replace(/__jsx-style-dynamic-selector/g,e)),h[n]}var p=function(){function e(e){var t=void 0===e?{}:e,n=t.styleSheet,r=void 0===n?null:n,i=t.optimizeForSpeed,s=void 0!==i&&i;this._sheet=r||new c({name:"styled-jsx",optimizeForSpeed:s}),this._sheet.inject(),r&&"boolean"==typeof s&&(this._sheet.setOptimizeForSpeed(s),this._optimizeForSpeed=this._sheet.isOptimizeForSpeed()),this._fromServer=void 0,this._indices={},this._instancesCounts={}}var t=e.prototype;return t.add=function(e){var t=this;void 0===this._optimizeForSpeed&&(this._optimizeForSpeed=Array.isArray(e.children),this._sheet.setOptimizeForSpeed(this._optimizeForSpeed),this._optimizeForSpeed=this._sheet.isOptimizeForSpeed()),"undefined"==typeof window||this._fromServer||(this._fromServer=this.selectFromServer(),this._instancesCounts=Object.keys(this._fromServer).reduce(function(e,t){return e[t]=0,e},{}));var n=this.getIdAndRules(e),r=n.styleId,i=n.rules;if(r in this._instancesCounts){this._instancesCounts[r]+=1;return}var s=i.map(function(e){return t._sheet.insertRule(e)}).filter(function(e){return -1!==e});this._indices[r]=s,this._instancesCounts[r]=1},t.remove=function(e){var t=this,n=this.getIdAndRules(e).styleId;if(function(e,t){if(!e)throw Error("StyleSheetRegistry: "+t+".")}(n in this._instancesCounts,"styleId: `"+n+"` not found"),this._instancesCounts[n]-=1,this._instancesCounts[n]<1){var r=this._fromServer&&this._fromServer[n];r?(r.parentNode.removeChild(r),delete this._fromServer[n]):(this._indices[n].forEach(function(e){return t._sheet.deleteRule(e)}),delete this._indices[n]),delete this._instancesCounts[n]}},t.update=function(e,t){this.add(t),this.remove(e)},t.flush=function(){this._sheet.flush(),this._sheet.inject(),this._fromServer=void 0,this._indices={},this._instancesCounts={}},t.cssRules=function(){var e=this,t=this._fromServer?Object.keys(this._fromServer).map(function(t){return[t,e._fromServer[t]]}):[],n=this._sheet.cssRules();return t.concat(Object.keys(this._indices).map(function(t){return[t,e._indices[t].map(function(e){return n[e].cssText}).join(e._optimizeForSpeed?"":"\n")]}).filter(function(e){return!!e[1]}))},t.styles=function(e){var t,n;return t=this.cssRules(),void 0===(n=e)&&(n={}),t.map(function(e){var t=e[0],r=e[1];return s.default.createElement("style",{id:"__"+t,key:"__"+t,nonce:n.nonce?n.nonce:void 0,dangerouslySetInnerHTML:{__html:r}})})},t.getIdAndRules=function(e){var t=e.children,n=e.dynamic,r=e.id;if(n){var i=d(r,n);return{styleId:i,rules:Array.isArray(t)?t.map(function(e){return f(i,e)}):[f(i,t)]}}return{styleId:d(r),rules:Array.isArray(t)?t:[t]}},t.selectFromServer=function(){return Array.prototype.slice.call(document.querySelectorAll('[id^="__jsx-"]')).reduce(function(e,t){return e[t.id.slice(2)]=t,e},{})},e}(),m=i.createContext(null);m.displayName="StyleSheetContext";var _=s.default.useInsertionEffect||s.default.useLayoutEffect,v="undefined"!=typeof window?new p:void 0;function y(e){var t=v||i.useContext(m);return t&&("undefined"==typeof window?t.add(e):_(function(){return t.add(e),function(){t.remove(e)}},[e.id,String(e.dynamic)])),null}y.dynamic=function(e){return e.map(function(e){return d(e[0],e[1])}).join(" ")},t.style=y},29:function(e,t,n){"use strict";e.exports=n(8975).style}}]);