@agent-relay/daemon 0.1.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 (109) hide show
  1. package/dist/agent-manager.d.ts +134 -0
  2. package/dist/agent-manager.d.ts.map +1 -0
  3. package/dist/agent-manager.js +578 -0
  4. package/dist/agent-manager.js.map +1 -0
  5. package/dist/agent-registry.d.ts +99 -0
  6. package/dist/agent-registry.d.ts.map +1 -0
  7. package/dist/agent-registry.js +213 -0
  8. package/dist/agent-registry.js.map +1 -0
  9. package/dist/agent-signing.d.ts +158 -0
  10. package/dist/agent-signing.d.ts.map +1 -0
  11. package/dist/agent-signing.js +523 -0
  12. package/dist/agent-signing.js.map +1 -0
  13. package/dist/api.d.ts +106 -0
  14. package/dist/api.d.ts.map +1 -0
  15. package/dist/api.js +876 -0
  16. package/dist/api.js.map +1 -0
  17. package/dist/auth.d.ts +94 -0
  18. package/dist/auth.d.ts.map +1 -0
  19. package/dist/auth.js +197 -0
  20. package/dist/auth.js.map +1 -0
  21. package/dist/channel-membership-store.d.ts +55 -0
  22. package/dist/channel-membership-store.d.ts.map +1 -0
  23. package/dist/channel-membership-store.js +176 -0
  24. package/dist/channel-membership-store.js.map +1 -0
  25. package/dist/cli-auth.d.ts +89 -0
  26. package/dist/cli-auth.d.ts.map +1 -0
  27. package/dist/cli-auth.js +792 -0
  28. package/dist/cli-auth.js.map +1 -0
  29. package/dist/cloud-sync.d.ts +150 -0
  30. package/dist/cloud-sync.d.ts.map +1 -0
  31. package/dist/cloud-sync.js +446 -0
  32. package/dist/cloud-sync.js.map +1 -0
  33. package/dist/connection.d.ts +130 -0
  34. package/dist/connection.d.ts.map +1 -0
  35. package/dist/connection.js +438 -0
  36. package/dist/connection.js.map +1 -0
  37. package/dist/consensus-integration.d.ts +167 -0
  38. package/dist/consensus-integration.d.ts.map +1 -0
  39. package/dist/consensus-integration.js +371 -0
  40. package/dist/consensus-integration.js.map +1 -0
  41. package/dist/consensus.d.ts +271 -0
  42. package/dist/consensus.d.ts.map +1 -0
  43. package/dist/consensus.js +632 -0
  44. package/dist/consensus.js.map +1 -0
  45. package/dist/delivery-tracker.d.ts +34 -0
  46. package/dist/delivery-tracker.d.ts.map +1 -0
  47. package/dist/delivery-tracker.js +104 -0
  48. package/dist/delivery-tracker.js.map +1 -0
  49. package/dist/enhanced-features.d.ts +118 -0
  50. package/dist/enhanced-features.d.ts.map +1 -0
  51. package/dist/enhanced-features.js +176 -0
  52. package/dist/enhanced-features.js.map +1 -0
  53. package/dist/index.d.ts +31 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +37 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/migrations/index.d.ts +73 -0
  58. package/dist/migrations/index.d.ts.map +1 -0
  59. package/dist/migrations/index.js +241 -0
  60. package/dist/migrations/index.js.map +1 -0
  61. package/dist/orchestrator.d.ts +217 -0
  62. package/dist/orchestrator.d.ts.map +1 -0
  63. package/dist/orchestrator.js +1143 -0
  64. package/dist/orchestrator.js.map +1 -0
  65. package/dist/rate-limiter.d.ts +68 -0
  66. package/dist/rate-limiter.d.ts.map +1 -0
  67. package/dist/rate-limiter.js +130 -0
  68. package/dist/rate-limiter.js.map +1 -0
  69. package/dist/registry.d.ts +9 -0
  70. package/dist/registry.d.ts.map +1 -0
  71. package/dist/registry.js +9 -0
  72. package/dist/registry.js.map +1 -0
  73. package/dist/relay-ledger.d.ts +261 -0
  74. package/dist/relay-ledger.d.ts.map +1 -0
  75. package/dist/relay-ledger.js +532 -0
  76. package/dist/relay-ledger.js.map +1 -0
  77. package/dist/relay-watchdog.d.ts +125 -0
  78. package/dist/relay-watchdog.d.ts.map +1 -0
  79. package/dist/relay-watchdog.js +611 -0
  80. package/dist/relay-watchdog.js.map +1 -0
  81. package/dist/repo-manager.d.ts +116 -0
  82. package/dist/repo-manager.d.ts.map +1 -0
  83. package/dist/repo-manager.js +384 -0
  84. package/dist/repo-manager.js.map +1 -0
  85. package/dist/router.d.ts +370 -0
  86. package/dist/router.d.ts.map +1 -0
  87. package/dist/router.js +1437 -0
  88. package/dist/router.js.map +1 -0
  89. package/dist/server.d.ts +174 -0
  90. package/dist/server.d.ts.map +1 -0
  91. package/dist/server.js +1001 -0
  92. package/dist/server.js.map +1 -0
  93. package/dist/spawn-manager.d.ts +78 -0
  94. package/dist/spawn-manager.d.ts.map +1 -0
  95. package/dist/spawn-manager.js +165 -0
  96. package/dist/spawn-manager.js.map +1 -0
  97. package/dist/sync-queue.d.ts +116 -0
  98. package/dist/sync-queue.d.ts.map +1 -0
  99. package/dist/sync-queue.js +361 -0
  100. package/dist/sync-queue.js.map +1 -0
  101. package/dist/types.d.ts +133 -0
  102. package/dist/types.d.ts.map +1 -0
  103. package/dist/types.js +6 -0
  104. package/dist/types.js.map +1 -0
  105. package/dist/workspace-manager.d.ts +80 -0
  106. package/dist/workspace-manager.d.ts.map +1 -0
  107. package/dist/workspace-manager.js +314 -0
  108. package/dist/workspace-manager.js.map +1 -0
  109. package/package.json +52 -0
@@ -0,0 +1,611 @@
1
+ /**
2
+ * Relay Watchdog - File-based relay message detection and processing
3
+ *
4
+ * Monitors agent outbox directories for new relay files and processes them:
5
+ * 1. Detects new files via fs.watch + periodic reconciliation
6
+ * 2. Validates files (size > 0, not symlink, settled)
7
+ * 3. Claims files atomically via ledger
8
+ * 4. Processes and archives files
9
+ *
10
+ * Features:
11
+ * - fsevents/inotify watchers with overflow fallback
12
+ * - Configurable settle time for file stability
13
+ * - Symlink rejection (security)
14
+ * - Orphaned .pending file cleanup
15
+ * - Crash recovery on startup
16
+ */
17
+ import { EventEmitter } from 'node:events';
18
+ import fs from 'node:fs';
19
+ import path from 'node:path';
20
+ import crypto from 'node:crypto';
21
+ import { RelayLedger } from './relay-ledger.js';
22
+ import { getBaseRelayPaths } from '@agent-relay/config/relay-file-writer';
23
+ // ============================================================================
24
+ // Constants
25
+ // ============================================================================
26
+ const DEFAULT_SETTLE_TIME_MS = parseInt(process.env.RELAY_SETTLE_TIME_MS ?? '500', 10);
27
+ const DEFAULT_MALFORMED_TIMEOUT_MS = parseInt(process.env.RELAY_MALFORMED_TIMEOUT_MS ?? '10000', 10);
28
+ const DEFAULT_RECONCILE_INTERVAL_MS = 30000;
29
+ const DEFAULT_MAX_MESSAGE_SIZE_BYTES = 1024 * 1024; // 1MB
30
+ const DEFAULT_MAX_ATTACHMENT_SIZE_BYTES = 10 * 1024 * 1024; // 10MB
31
+ const DEFAULT_CLEANUP_INTERVAL_MS = 60000;
32
+ const DEFAULT_ORPHANED_PENDING_AGE_MS = 30000;
33
+ const DEFAULT_ARCHIVE_RETENTION_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
34
+ // Files/directories to ignore
35
+ const IGNORE_PATTERNS = [
36
+ /^\./, // Hidden files
37
+ /^\.pending$/, // Pending marker
38
+ /\.tmp$/, // Temp files
39
+ /~$/, // Editor backups
40
+ ];
41
+ // ============================================================================
42
+ // RelayWatchdog Class
43
+ // ============================================================================
44
+ export class RelayWatchdog extends EventEmitter {
45
+ config;
46
+ relayPaths;
47
+ ledger;
48
+ watchers = new Map();
49
+ pendingFiles = new Map();
50
+ reconcileTimer;
51
+ cleanupTimer;
52
+ running = false;
53
+ constructor(config = {}) {
54
+ super();
55
+ this.relayPaths = config.relayPaths ?? getBaseRelayPaths();
56
+ this.config = {
57
+ relayPaths: this.relayPaths,
58
+ ledgerPath: config.ledgerPath ?? path.join(this.relayPaths.metaDir, 'ledger.sqlite'),
59
+ settleTimeMs: config.settleTimeMs ?? DEFAULT_SETTLE_TIME_MS,
60
+ malformedTimeoutMs: config.malformedTimeoutMs ?? DEFAULT_MALFORMED_TIMEOUT_MS,
61
+ reconcileIntervalMs: config.reconcileIntervalMs ?? DEFAULT_RECONCILE_INTERVAL_MS,
62
+ maxMessageSizeBytes: config.maxMessageSizeBytes ?? DEFAULT_MAX_MESSAGE_SIZE_BYTES,
63
+ maxAttachmentSizeBytes: config.maxAttachmentSizeBytes ?? DEFAULT_MAX_ATTACHMENT_SIZE_BYTES,
64
+ cleanupIntervalMs: config.cleanupIntervalMs ?? DEFAULT_CLEANUP_INTERVAL_MS,
65
+ orphanedPendingAgeMs: config.orphanedPendingAgeMs ?? DEFAULT_ORPHANED_PENDING_AGE_MS,
66
+ archiveRetentionMs: config.archiveRetentionMs ?? DEFAULT_ARCHIVE_RETENTION_MS,
67
+ debug: config.debug ?? false,
68
+ };
69
+ // Initialize ledger
70
+ this.ledger = new RelayLedger({
71
+ dbPath: this.config.ledgerPath,
72
+ archiveRetentionMs: this.config.archiveRetentionMs,
73
+ });
74
+ }
75
+ /**
76
+ * Resolve symlinks in relay paths for cloud/production workspace support
77
+ * This ensures we work with canonical paths even when directories are symlinked
78
+ */
79
+ async resolveRelayPaths() {
80
+ const resolvePath = async (p) => {
81
+ try {
82
+ const resolved = await fs.promises.realpath(p);
83
+ if (resolved !== p) {
84
+ this.log(`Resolved symlink: ${p} -> ${resolved}`);
85
+ }
86
+ return resolved;
87
+ }
88
+ catch {
89
+ // Path doesn't exist yet, keep original
90
+ return p;
91
+ }
92
+ };
93
+ // Resolve all relay paths to canonical form
94
+ this.relayPaths = {
95
+ rootDir: await resolvePath(this.relayPaths.rootDir),
96
+ outboxDir: await resolvePath(this.relayPaths.outboxDir),
97
+ attachmentsDir: await resolvePath(this.relayPaths.attachmentsDir),
98
+ metaDir: await resolvePath(this.relayPaths.metaDir),
99
+ legacyOutboxDir: await resolvePath(this.relayPaths.legacyOutboxDir),
100
+ };
101
+ }
102
+ /**
103
+ * Start the watchdog
104
+ */
105
+ async start() {
106
+ if (this.running)
107
+ return;
108
+ this.running = true;
109
+ this.log('Starting relay watchdog...');
110
+ // Resolve symlinks in relay paths for cloud/production workspace support
111
+ await this.resolveRelayPaths();
112
+ // Ensure directories exist
113
+ await this.ensureDirectories();
114
+ // Crash recovery: reset processing files and reconcile
115
+ const resetCount = this.ledger.resetProcessingFiles();
116
+ if (resetCount > 0) {
117
+ this.log(`Crash recovery: reset ${resetCount} processing files to pending`);
118
+ }
119
+ const reconcileResult = this.ledger.reconcileWithFilesystem();
120
+ if (reconcileResult.failed > 0) {
121
+ this.log(`Crash recovery: marked ${reconcileResult.failed} missing files as failed`);
122
+ }
123
+ // Initial scan to seed ledger
124
+ await this.fullReconciliation();
125
+ // Start root watcher for new agents
126
+ this.startRootWatcher();
127
+ // Start watchers for existing agents
128
+ await this.startAgentWatchers();
129
+ // Start periodic reconciliation
130
+ this.reconcileTimer = setInterval(() => {
131
+ this.fullReconciliation().catch(err => {
132
+ this.emit('error', err);
133
+ });
134
+ }, this.config.reconcileIntervalMs);
135
+ this.reconcileTimer.unref();
136
+ // Start cleanup timer
137
+ this.cleanupTimer = setInterval(() => {
138
+ this.cleanupOrphanedFiles();
139
+ this.ledger.cleanupArchivedRecords();
140
+ }, this.config.cleanupIntervalMs);
141
+ this.cleanupTimer.unref();
142
+ this.log('Relay watchdog started');
143
+ }
144
+ /**
145
+ * Stop the watchdog
146
+ */
147
+ async stop() {
148
+ if (!this.running)
149
+ return;
150
+ this.running = false;
151
+ this.log('Stopping relay watchdog...');
152
+ // Clear timers
153
+ if (this.reconcileTimer) {
154
+ clearInterval(this.reconcileTimer);
155
+ this.reconcileTimer = undefined;
156
+ }
157
+ if (this.cleanupTimer) {
158
+ clearInterval(this.cleanupTimer);
159
+ this.cleanupTimer = undefined;
160
+ }
161
+ // Clear pending file timers
162
+ for (const timer of this.pendingFiles.values()) {
163
+ clearTimeout(timer);
164
+ }
165
+ this.pendingFiles.clear();
166
+ // Close all watchers
167
+ for (const [dir, watcher] of this.watchers) {
168
+ watcher.close();
169
+ this.log(`Closed watcher for: ${dir}`);
170
+ }
171
+ this.watchers.clear();
172
+ // Close ledger
173
+ this.ledger.close();
174
+ this.log('Relay watchdog stopped');
175
+ }
176
+ /**
177
+ * Get ledger statistics
178
+ */
179
+ getStats() {
180
+ return this.ledger.getStats();
181
+ }
182
+ /**
183
+ * Get pending file count
184
+ */
185
+ getPendingCount() {
186
+ return this.ledger.getPendingFiles(1).length > 0 ? this.ledger.getStats().pending : 0;
187
+ }
188
+ // ==========================================================================
189
+ // Directory Management
190
+ // ==========================================================================
191
+ async ensureDirectories() {
192
+ const dirs = [
193
+ this.relayPaths.outboxDir,
194
+ this.relayPaths.attachmentsDir,
195
+ this.relayPaths.metaDir,
196
+ path.join(this.relayPaths.rootDir, 'archive'),
197
+ ];
198
+ for (const dir of dirs) {
199
+ if (!fs.existsSync(dir)) {
200
+ await fs.promises.mkdir(dir, { recursive: true });
201
+ this.log(`Created directory: ${dir}`);
202
+ }
203
+ }
204
+ }
205
+ // ==========================================================================
206
+ // File Watching
207
+ // ==========================================================================
208
+ startRootWatcher() {
209
+ const outboxDir = this.relayPaths.outboxDir;
210
+ if (!fs.existsSync(outboxDir)) {
211
+ this.log(`Outbox directory doesn't exist yet: ${outboxDir}`);
212
+ return;
213
+ }
214
+ try {
215
+ const watcher = fs.watch(outboxDir, (eventType, filename) => {
216
+ if (!filename || this.shouldIgnore(filename))
217
+ return;
218
+ const agentDir = path.join(outboxDir, filename);
219
+ // Check if new agent directory was created
220
+ if (eventType === 'rename') {
221
+ this.checkAndWatchAgentDir(agentDir, filename);
222
+ }
223
+ });
224
+ watcher.on('error', (err) => {
225
+ this.log(`Root watcher error: ${err.message}`);
226
+ this.emit('watcher:overflow', outboxDir);
227
+ // Trigger full reconciliation on watcher error
228
+ this.fullReconciliation().catch(e => this.emit('error', e));
229
+ });
230
+ this.watchers.set(outboxDir, watcher);
231
+ this.log(`Started root watcher: ${outboxDir}`);
232
+ }
233
+ catch (err) {
234
+ this.log(`Failed to start root watcher: ${err.message}`);
235
+ }
236
+ }
237
+ async startAgentWatchers() {
238
+ const outboxDir = this.relayPaths.outboxDir;
239
+ if (!fs.existsSync(outboxDir))
240
+ return;
241
+ const entries = await fs.promises.readdir(outboxDir, { withFileTypes: true });
242
+ for (const entry of entries) {
243
+ if (entry.isDirectory() && !this.shouldIgnore(entry.name)) {
244
+ const agentDir = path.join(outboxDir, entry.name);
245
+ this.startAgentWatcher(agentDir, entry.name);
246
+ }
247
+ }
248
+ }
249
+ checkAndWatchAgentDir(agentDir, agentName) {
250
+ try {
251
+ const stats = fs.statSync(agentDir);
252
+ if (stats.isDirectory() && !this.watchers.has(agentDir)) {
253
+ this.startAgentWatcher(agentDir, agentName);
254
+ }
255
+ }
256
+ catch {
257
+ // Directory might not exist yet or was deleted
258
+ }
259
+ }
260
+ startAgentWatcher(agentDir, agentName) {
261
+ if (this.watchers.has(agentDir))
262
+ return;
263
+ try {
264
+ const watcher = fs.watch(agentDir, (eventType, filename) => {
265
+ if (!filename || this.shouldIgnore(filename))
266
+ return;
267
+ const filePath = path.join(agentDir, filename);
268
+ this.handleFileEvent(filePath, agentName, filename);
269
+ });
270
+ watcher.on('error', (err) => {
271
+ this.log(`Agent watcher error (${agentName}): ${err.message}`);
272
+ this.emit('watcher:overflow', agentDir);
273
+ // Remove failed watcher and trigger reconciliation
274
+ this.watchers.delete(agentDir);
275
+ this.fullReconciliation().catch(e => this.emit('error', e));
276
+ });
277
+ this.watchers.set(agentDir, watcher);
278
+ this.log(`Started agent watcher: ${agentDir}`);
279
+ }
280
+ catch (err) {
281
+ this.log(`Failed to start agent watcher (${agentName}): ${err.message}`);
282
+ }
283
+ }
284
+ // ==========================================================================
285
+ // File Event Handling
286
+ // ==========================================================================
287
+ handleFileEvent(filePath, agentName, messageType) {
288
+ // Cancel any existing settle timer for this file
289
+ const existingTimer = this.pendingFiles.get(filePath);
290
+ if (existingTimer) {
291
+ clearTimeout(existingTimer);
292
+ }
293
+ // Start settle timer
294
+ const timer = setTimeout(() => {
295
+ this.pendingFiles.delete(filePath);
296
+ this.processDiscoveredFile(filePath, agentName, messageType).catch(err => {
297
+ this.emit('error', err);
298
+ });
299
+ }, this.config.settleTimeMs);
300
+ this.pendingFiles.set(filePath, timer);
301
+ }
302
+ async processDiscoveredFile(filePath, agentName, messageType) {
303
+ try {
304
+ // SECURITY: Check if the file itself is a symlink BEFORE resolving
305
+ // This prevents symlink attacks where an attacker creates a symlink
306
+ // pointing to a file outside the agent's outbox
307
+ try {
308
+ const lstats = await fs.promises.lstat(filePath);
309
+ if (lstats.isSymbolicLink()) {
310
+ this.log(`Rejected symlink file (security): ${filePath}`);
311
+ return;
312
+ }
313
+ }
314
+ catch {
315
+ // File doesn't exist - will be caught later
316
+ }
317
+ // Resolve symlinks in DIRECTORY path to get canonical path
318
+ // (for cloud workspaces where the outbox directory may be symlinked)
319
+ // Note: The file itself was already verified to NOT be a symlink above
320
+ let canonicalPath;
321
+ let originalPath;
322
+ try {
323
+ canonicalPath = await fs.promises.realpath(filePath);
324
+ // Only store original if it differs (directory was symlinked)
325
+ if (canonicalPath !== filePath) {
326
+ originalPath = filePath;
327
+ this.log(`Resolved directory symlink: ${filePath} -> ${canonicalPath}`);
328
+ }
329
+ }
330
+ catch {
331
+ // File doesn't exist or can't resolve - use original
332
+ canonicalPath = filePath;
333
+ }
334
+ // Validate file exists and get stats (uses canonical path)
335
+ const validation = await this.validateFile(canonicalPath);
336
+ if (!validation.valid) {
337
+ this.log(`File validation failed (${canonicalPath}): ${validation.reason}`);
338
+ return;
339
+ }
340
+ const stats = validation.stats;
341
+ // Check if already registered (by canonical path)
342
+ if (this.ledger.isFileRegistered(canonicalPath)) {
343
+ this.log(`File already registered: ${canonicalPath}`);
344
+ return;
345
+ }
346
+ // Calculate content hash for deduplication
347
+ const contentHash = await this.calculateFileHash(canonicalPath);
348
+ // Register in ledger with both paths
349
+ // sourcePath = canonical (resolved), symlinkPath = original (if symlinked)
350
+ const fileId = this.ledger.registerFile(canonicalPath, agentName, messageType, stats.size, contentHash, undefined, // fileMtimeNs
351
+ undefined, // fileInode
352
+ originalPath // symlinkPath (only set if it was a symlink)
353
+ );
354
+ const discoveredFile = {
355
+ path: canonicalPath,
356
+ agentName,
357
+ messageType,
358
+ size: stats.size,
359
+ mtime: stats.mtimeMs,
360
+ contentHash,
361
+ };
362
+ this.emit('file:discovered', discoveredFile);
363
+ this.log(`Discovered file: ${canonicalPath} (id: ${fileId})`);
364
+ // Attempt to process immediately
365
+ await this.processFile(fileId);
366
+ }
367
+ catch (err) {
368
+ this.log(`Error processing discovered file (${filePath}): ${err.message}`);
369
+ }
370
+ }
371
+ // ==========================================================================
372
+ // File Validation
373
+ // ==========================================================================
374
+ async validateFile(filePath) {
375
+ try {
376
+ // Use lstat to detect symlinks (don't follow them)
377
+ const stats = await fs.promises.lstat(filePath);
378
+ // Reject symlinks (security)
379
+ if (stats.isSymbolicLink()) {
380
+ return { valid: false, reason: 'Symlinks not allowed' };
381
+ }
382
+ // Must be a regular file
383
+ if (!stats.isFile()) {
384
+ return { valid: false, reason: 'Not a regular file' };
385
+ }
386
+ // Skip 0-byte files
387
+ if (stats.size === 0) {
388
+ return { valid: false, reason: 'Empty file (0 bytes)' };
389
+ }
390
+ // Check size limits
391
+ if (stats.size > this.config.maxMessageSizeBytes) {
392
+ return { valid: false, reason: `File too large (${stats.size} > ${this.config.maxMessageSizeBytes})` };
393
+ }
394
+ // Re-stat to check stability (file size hasn't changed)
395
+ await new Promise(resolve => setTimeout(resolve, 50));
396
+ const stats2 = await fs.promises.lstat(filePath);
397
+ if (stats.size !== stats2.size || stats.mtimeMs !== stats2.mtimeMs) {
398
+ return { valid: false, reason: 'File still being written' };
399
+ }
400
+ return { valid: true, stats };
401
+ }
402
+ catch (err) {
403
+ if (err.code === 'ENOENT') {
404
+ return { valid: false, reason: 'File does not exist' };
405
+ }
406
+ return { valid: false, reason: err.message };
407
+ }
408
+ }
409
+ async calculateFileHash(filePath) {
410
+ const content = await fs.promises.readFile(filePath);
411
+ return crypto.createHash('sha256').update(content).digest('hex').slice(0, 16);
412
+ }
413
+ // ==========================================================================
414
+ // File Processing
415
+ // ==========================================================================
416
+ async processFile(fileId) {
417
+ // Atomically claim the file
418
+ const claimResult = this.ledger.claimFile(fileId);
419
+ if (!claimResult.success) {
420
+ this.log(`Failed to claim file ${fileId}: ${claimResult.reason}`);
421
+ return;
422
+ }
423
+ const record = claimResult.record;
424
+ this.emit('file:processing', record);
425
+ try {
426
+ // Read file content
427
+ const content = await fs.promises.readFile(record.sourcePath, 'utf-8');
428
+ // Parse headers and body
429
+ const { headers, body } = this.parseFileContent(content);
430
+ const processedFile = {
431
+ fileId: record.fileId,
432
+ agentName: record.agentName,
433
+ messageType: record.messageType,
434
+ content,
435
+ headers,
436
+ body,
437
+ };
438
+ // Mark as delivered
439
+ this.ledger.markDelivered(fileId);
440
+ this.emit('file:delivered', processedFile);
441
+ // Archive the file
442
+ await this.archiveFile(record);
443
+ this.log(`Processed file: ${record.sourcePath} (id: ${fileId})`);
444
+ }
445
+ catch (err) {
446
+ this.log(`Error processing file ${fileId}: ${err.message}`);
447
+ this.ledger.markFailed(fileId, err.message);
448
+ this.emit('file:failed', record, err);
449
+ }
450
+ }
451
+ parseFileContent(content) {
452
+ const headers = {};
453
+ const lines = content.split('\n');
454
+ let bodyStartIndex = 0;
455
+ // Parse headers until empty line
456
+ for (let i = 0; i < lines.length; i++) {
457
+ const line = lines[i];
458
+ // Empty line marks end of headers
459
+ if (line.trim() === '') {
460
+ bodyStartIndex = i + 1;
461
+ break;
462
+ }
463
+ // Parse header: "KEY: value"
464
+ const colonIndex = line.indexOf(':');
465
+ if (colonIndex > 0) {
466
+ const key = line.slice(0, colonIndex).trim().toUpperCase();
467
+ const value = line.slice(colonIndex + 1).trim();
468
+ headers[key] = value;
469
+ }
470
+ else {
471
+ // No colon found, treat rest as body
472
+ bodyStartIndex = i;
473
+ break;
474
+ }
475
+ }
476
+ const body = lines.slice(bodyStartIndex).join('\n').trim();
477
+ return { headers, body };
478
+ }
479
+ // ==========================================================================
480
+ // File Archiving
481
+ // ==========================================================================
482
+ async archiveFile(record) {
483
+ const archiveDir = path.join(this.relayPaths.rootDir, 'archive', record.agentName, new Date().toISOString().slice(0, 10) // YYYY-MM-DD
484
+ );
485
+ await fs.promises.mkdir(archiveDir, { recursive: true });
486
+ const archivePath = path.join(archiveDir, `${record.fileId}-${record.messageType}`);
487
+ try {
488
+ // Move file to archive
489
+ await fs.promises.rename(record.sourcePath, archivePath);
490
+ this.ledger.markArchived(record.fileId, archivePath);
491
+ this.emit('file:archived', record, archivePath);
492
+ }
493
+ catch (err) {
494
+ // If rename fails (cross-device), copy and delete
495
+ if (err.code === 'EXDEV') {
496
+ await fs.promises.copyFile(record.sourcePath, archivePath);
497
+ await fs.promises.unlink(record.sourcePath);
498
+ this.ledger.markArchived(record.fileId, archivePath);
499
+ this.emit('file:archived', record, archivePath);
500
+ }
501
+ else {
502
+ throw err;
503
+ }
504
+ }
505
+ }
506
+ // ==========================================================================
507
+ // Reconciliation
508
+ // ==========================================================================
509
+ async fullReconciliation() {
510
+ const outboxDir = this.relayPaths.outboxDir;
511
+ let discovered = 0;
512
+ let failed = 0;
513
+ if (!fs.existsSync(outboxDir)) {
514
+ return;
515
+ }
516
+ try {
517
+ // Scan all agent directories
518
+ const agents = await fs.promises.readdir(outboxDir, { withFileTypes: true });
519
+ for (const agent of agents) {
520
+ if (!agent.isDirectory() || this.shouldIgnore(agent.name))
521
+ continue;
522
+ const agentDir = path.join(outboxDir, agent.name);
523
+ // Ensure watcher exists for this agent
524
+ if (!this.watchers.has(agentDir)) {
525
+ this.startAgentWatcher(agentDir, agent.name);
526
+ }
527
+ // Scan agent's outbox
528
+ try {
529
+ const files = await fs.promises.readdir(agentDir, { withFileTypes: true });
530
+ for (const file of files) {
531
+ if (!file.isFile() || this.shouldIgnore(file.name))
532
+ continue;
533
+ const filePath = path.join(agentDir, file.name);
534
+ // Skip if already registered
535
+ if (this.ledger.isFileRegistered(filePath))
536
+ continue;
537
+ try {
538
+ await this.processDiscoveredFile(filePath, agent.name, file.name);
539
+ discovered++;
540
+ }
541
+ catch {
542
+ failed++;
543
+ }
544
+ }
545
+ }
546
+ catch (err) {
547
+ this.log(`Failed to scan agent directory (${agent.name}): ${err.message}`);
548
+ }
549
+ }
550
+ // Process any pending files from ledger
551
+ const pendingFiles = this.ledger.getPendingFiles();
552
+ for (const record of pendingFiles) {
553
+ await this.processFile(record.fileId);
554
+ }
555
+ this.emit('reconcile:complete', { discovered, failed });
556
+ }
557
+ catch (err) {
558
+ this.log(`Reconciliation error: ${err.message}`);
559
+ this.emit('error', err);
560
+ }
561
+ }
562
+ // ==========================================================================
563
+ // Cleanup
564
+ // ==========================================================================
565
+ async cleanupOrphanedFiles() {
566
+ const outboxDir = this.relayPaths.outboxDir;
567
+ const now = Date.now();
568
+ if (!fs.existsSync(outboxDir))
569
+ return;
570
+ try {
571
+ const agents = await fs.promises.readdir(outboxDir, { withFileTypes: true });
572
+ for (const agent of agents) {
573
+ if (!agent.isDirectory())
574
+ continue;
575
+ const agentDir = path.join(outboxDir, agent.name);
576
+ const files = await fs.promises.readdir(agentDir);
577
+ for (const file of files) {
578
+ // Clean up .pending files older than threshold
579
+ if (file.endsWith('.pending')) {
580
+ const filePath = path.join(agentDir, file);
581
+ try {
582
+ const stats = await fs.promises.stat(filePath);
583
+ if (now - stats.mtimeMs > this.config.orphanedPendingAgeMs) {
584
+ await fs.promises.unlink(filePath);
585
+ this.log(`Cleaned up orphaned .pending file: ${filePath}`);
586
+ }
587
+ }
588
+ catch {
589
+ // File may have been deleted
590
+ }
591
+ }
592
+ }
593
+ }
594
+ }
595
+ catch (err) {
596
+ this.log(`Cleanup error: ${err.message}`);
597
+ }
598
+ }
599
+ // ==========================================================================
600
+ // Utilities
601
+ // ==========================================================================
602
+ shouldIgnore(filename) {
603
+ return IGNORE_PATTERNS.some(pattern => pattern.test(filename));
604
+ }
605
+ log(message) {
606
+ if (this.config.debug) {
607
+ console.log(`[relay-watchdog] ${message}`);
608
+ }
609
+ }
610
+ }
611
+ //# sourceMappingURL=relay-watchdog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay-watchdog.js","sourceRoot":"","sources":["../src/relay-watchdog.ts"],"names":[],"mappings":"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"}