gsd-agent 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/README.md +221 -0
  2. package/bin/cli.js +313 -0
  3. package/dist/auth-flow.d.ts +50 -0
  4. package/dist/auth-flow.d.ts.map +1 -0
  5. package/dist/auth-flow.js +233 -0
  6. package/dist/auth-flow.js.map +1 -0
  7. package/dist/auth.d.ts +42 -0
  8. package/dist/auth.d.ts.map +1 -0
  9. package/dist/auth.js +117 -0
  10. package/dist/auth.js.map +1 -0
  11. package/dist/command-executor.d.ts +44 -0
  12. package/dist/command-executor.d.ts.map +1 -0
  13. package/dist/command-executor.js +193 -0
  14. package/dist/command-executor.js.map +1 -0
  15. package/dist/command-executor.test.d.ts +8 -0
  16. package/dist/command-executor.test.d.ts.map +1 -0
  17. package/dist/command-executor.test.js +87 -0
  18. package/dist/command-executor.test.js.map +1 -0
  19. package/dist/command-queue.d.ts +44 -0
  20. package/dist/command-queue.d.ts.map +1 -0
  21. package/dist/command-queue.js +184 -0
  22. package/dist/command-queue.js.map +1 -0
  23. package/dist/command-queue.test.d.ts +7 -0
  24. package/dist/command-queue.test.d.ts.map +1 -0
  25. package/dist/command-queue.test.js +220 -0
  26. package/dist/command-queue.test.js.map +1 -0
  27. package/dist/config.d.ts +25 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +103 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/conflict-resolver.d.ts +43 -0
  32. package/dist/conflict-resolver.d.ts.map +1 -0
  33. package/dist/conflict-resolver.js +91 -0
  34. package/dist/conflict-resolver.js.map +1 -0
  35. package/dist/conflict-resolver.test.d.ts +7 -0
  36. package/dist/conflict-resolver.test.d.ts.map +1 -0
  37. package/dist/conflict-resolver.test.js +123 -0
  38. package/dist/conflict-resolver.test.js.map +1 -0
  39. package/dist/discovery.d.ts +59 -0
  40. package/dist/discovery.d.ts.map +1 -0
  41. package/dist/discovery.js +180 -0
  42. package/dist/discovery.js.map +1 -0
  43. package/dist/discovery.test.d.ts +8 -0
  44. package/dist/discovery.test.d.ts.map +1 -0
  45. package/dist/discovery.test.js +132 -0
  46. package/dist/discovery.test.js.map +1 -0
  47. package/dist/hash.d.ts +20 -0
  48. package/dist/hash.d.ts.map +1 -0
  49. package/dist/hash.js +35 -0
  50. package/dist/hash.js.map +1 -0
  51. package/dist/hash.test.d.ts +7 -0
  52. package/dist/hash.test.d.ts.map +1 -0
  53. package/dist/hash.test.js +58 -0
  54. package/dist/hash.test.js.map +1 -0
  55. package/dist/index.d.ts +11 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +202 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/integration.test.d.ts +8 -0
  60. package/dist/integration.test.d.ts.map +1 -0
  61. package/dist/integration.test.js +37 -0
  62. package/dist/integration.test.js.map +1 -0
  63. package/dist/logger.d.ts +68 -0
  64. package/dist/logger.d.ts.map +1 -0
  65. package/dist/logger.js +159 -0
  66. package/dist/logger.js.map +1 -0
  67. package/dist/output-streamer.d.ts +27 -0
  68. package/dist/output-streamer.d.ts.map +1 -0
  69. package/dist/output-streamer.js +71 -0
  70. package/dist/output-streamer.js.map +1 -0
  71. package/dist/output-streamer.test.d.ts +7 -0
  72. package/dist/output-streamer.test.d.ts.map +1 -0
  73. package/dist/output-streamer.test.js +90 -0
  74. package/dist/output-streamer.test.js.map +1 -0
  75. package/dist/realtime-subscriber.d.ts +63 -0
  76. package/dist/realtime-subscriber.d.ts.map +1 -0
  77. package/dist/realtime-subscriber.js +201 -0
  78. package/dist/realtime-subscriber.js.map +1 -0
  79. package/dist/realtime-subscriber.test.d.ts +7 -0
  80. package/dist/realtime-subscriber.test.d.ts.map +1 -0
  81. package/dist/realtime-subscriber.test.js +183 -0
  82. package/dist/realtime-subscriber.test.js.map +1 -0
  83. package/dist/reconnection-manager.d.ts +88 -0
  84. package/dist/reconnection-manager.d.ts.map +1 -0
  85. package/dist/reconnection-manager.js +229 -0
  86. package/dist/reconnection-manager.js.map +1 -0
  87. package/dist/reconnection-manager.test.d.ts +8 -0
  88. package/dist/reconnection-manager.test.d.ts.map +1 -0
  89. package/dist/reconnection-manager.test.js +151 -0
  90. package/dist/reconnection-manager.test.js.map +1 -0
  91. package/dist/remote-sync-handler.d.ts +61 -0
  92. package/dist/remote-sync-handler.d.ts.map +1 -0
  93. package/dist/remote-sync-handler.js +197 -0
  94. package/dist/remote-sync-handler.js.map +1 -0
  95. package/dist/remote-sync-handler.test.d.ts +7 -0
  96. package/dist/remote-sync-handler.test.d.ts.map +1 -0
  97. package/dist/remote-sync-handler.test.js +212 -0
  98. package/dist/remote-sync-handler.test.js.map +1 -0
  99. package/dist/retry.d.ts +35 -0
  100. package/dist/retry.d.ts.map +1 -0
  101. package/dist/retry.js +63 -0
  102. package/dist/retry.js.map +1 -0
  103. package/dist/retry.test.d.ts +5 -0
  104. package/dist/retry.test.d.ts.map +1 -0
  105. package/dist/retry.test.js +84 -0
  106. package/dist/retry.test.js.map +1 -0
  107. package/dist/storage-client.d.ts +69 -0
  108. package/dist/storage-client.d.ts.map +1 -0
  109. package/dist/storage-client.js +168 -0
  110. package/dist/storage-client.js.map +1 -0
  111. package/dist/storage-client.test.d.ts +7 -0
  112. package/dist/storage-client.test.d.ts.map +1 -0
  113. package/dist/storage-client.test.js +126 -0
  114. package/dist/storage-client.test.js.map +1 -0
  115. package/dist/supabase.d.ts +82 -0
  116. package/dist/supabase.d.ts.map +1 -0
  117. package/dist/supabase.js +341 -0
  118. package/dist/supabase.js.map +1 -0
  119. package/dist/supabase.test.d.ts +7 -0
  120. package/dist/supabase.test.d.ts.map +1 -0
  121. package/dist/supabase.test.js +273 -0
  122. package/dist/supabase.test.js.map +1 -0
  123. package/dist/sync-engine.d.ts +84 -0
  124. package/dist/sync-engine.d.ts.map +1 -0
  125. package/dist/sync-engine.js +251 -0
  126. package/dist/sync-engine.js.map +1 -0
  127. package/dist/sync-engine.test.d.ts +7 -0
  128. package/dist/sync-engine.test.d.ts.map +1 -0
  129. package/dist/sync-engine.test.js +241 -0
  130. package/dist/sync-engine.test.js.map +1 -0
  131. package/dist/sync-state.d.ts +82 -0
  132. package/dist/sync-state.d.ts.map +1 -0
  133. package/dist/sync-state.js +145 -0
  134. package/dist/sync-state.js.map +1 -0
  135. package/dist/sync-state.test.d.ts +7 -0
  136. package/dist/sync-state.test.d.ts.map +1 -0
  137. package/dist/sync-state.test.js +129 -0
  138. package/dist/sync-state.test.js.map +1 -0
  139. package/dist/types.d.ts +148 -0
  140. package/dist/types.d.ts.map +1 -0
  141. package/dist/types.js +8 -0
  142. package/dist/types.js.map +1 -0
  143. package/dist/types.test.d.ts +7 -0
  144. package/dist/types.test.d.ts.map +1 -0
  145. package/dist/types.test.js +73 -0
  146. package/dist/types.test.js.map +1 -0
  147. package/dist/watcher.d.ts +55 -0
  148. package/dist/watcher.d.ts.map +1 -0
  149. package/dist/watcher.js +214 -0
  150. package/dist/watcher.js.map +1 -0
  151. package/dist/watcher.test.d.ts +8 -0
  152. package/dist/watcher.test.d.ts.map +1 -0
  153. package/dist/watcher.test.js +164 -0
  154. package/dist/watcher.test.js.map +1 -0
  155. package/package.json +58 -0
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Core type definitions for GSD Agent
3
+ *
4
+ * These types define the data structures used throughout the agent for
5
+ * workspace management, file change tracking, and synchronization.
6
+ */
7
+ /**
8
+ * Workspace represents a discovered GSD project
9
+ *
10
+ * Each workspace corresponds to a directory containing a .planning/ folder.
11
+ * The agent tracks multiple workspaces and syncs their files independently.
12
+ */
13
+ export interface Workspace {
14
+ /** Unique identifier for the workspace */
15
+ id: string;
16
+ /** Absolute path to the workspace root directory */
17
+ root_path: string;
18
+ /** Human-readable name (derived from directory name) */
19
+ name: string;
20
+ /** Current workspace status */
21
+ status: 'active' | 'paused' | 'archived';
22
+ /** ISO timestamp of last successful sync */
23
+ last_sync: string;
24
+ /** ISO timestamp when workspace was first discovered */
25
+ discovered_at: string;
26
+ }
27
+ /**
28
+ * FileChangeEvent represents a single file system change
29
+ *
30
+ * Events are generated by the filesystem watcher and queued for sync to Supabase.
31
+ * Each event captures the file state at the time of change.
32
+ */
33
+ export interface FileChangeEvent {
34
+ /** Unique identifier for this event */
35
+ id: string;
36
+ /** Reference to the workspace this file belongs to */
37
+ workspace_id: string;
38
+ /** File path relative to workspace root (e.g., ".planning/STATE.md") */
39
+ file_path: string;
40
+ /** Type of filesystem event */
41
+ event_type: 'add' | 'change' | 'unlink';
42
+ /** SHA-256 hash of file content (for deduplication) */
43
+ content_hash: string;
44
+ /** File content (null for unlink events) */
45
+ content?: string;
46
+ /** Source of the change */
47
+ source: 'cli' | 'web' | 'sync';
48
+ /** ISO timestamp when event occurred */
49
+ timestamp: string;
50
+ /** Additional metadata about the file */
51
+ metadata: {
52
+ /** File size in bytes */
53
+ size: number;
54
+ /** ISO timestamp of file modification time */
55
+ mtime: string;
56
+ /** Agent version that generated this event */
57
+ agent_version: string;
58
+ };
59
+ }
60
+ /**
61
+ * SyncConfig defines agent configuration
62
+ *
63
+ * Configuration is loaded from ~/.gsd-agent/config.json with fallback to defaults.
64
+ * All paths are expanded (~ becomes home directory).
65
+ */
66
+ export interface SyncConfig {
67
+ /** Supabase project URL */
68
+ supabase_url: string;
69
+ /** Supabase service role key (stored securely) */
70
+ supabase_key: string;
71
+ /** Parent directories to watch for .planning/ folders */
72
+ watch_dirs: string[];
73
+ /** Glob patterns to ignore during watching */
74
+ ignored_patterns: string[];
75
+ /** Debounce delay in milliseconds (default: 300) */
76
+ debounce_ms: number;
77
+ /** Maximum files per batch sync (default: 50) */
78
+ batch_size: number;
79
+ /** Logging level */
80
+ log_level: 'ERROR' | 'WARN' | 'INFO' | 'DEBUG';
81
+ /** Path to log file */
82
+ log_file: string;
83
+ /** Number of days to keep log files (default: 7) */
84
+ log_rotation_days: number;
85
+ }
86
+ /**
87
+ * AgentState represents the runtime state of the agent
88
+ *
89
+ * This is the in-memory state maintained during agent execution.
90
+ * Not persisted to disk (workspaces are persisted separately).
91
+ */
92
+ export interface AgentState {
93
+ /** Map of workspace ID to workspace metadata */
94
+ workspaces: Map<string, Workspace>;
95
+ /** Queue of pending file change events awaiting sync */
96
+ sync_queue: FileChangeEvent[];
97
+ /** Whether a sync operation is currently in progress */
98
+ is_syncing: boolean;
99
+ /** ISO timestamp of last heartbeat sent to Supabase */
100
+ last_heartbeat: string;
101
+ }
102
+ /**
103
+ * RemoteChangeEvent represents a file change from Supabase Realtime
104
+ *
105
+ * These events come from the web UI or other agents modifying files.
106
+ * The agent must apply these changes to the local filesystem.
107
+ */
108
+ export interface RemoteChangeEvent {
109
+ /** Database record ID */
110
+ id: string;
111
+ /** Reference to the workspace this file belongs to */
112
+ workspace_id: string;
113
+ /** File path relative to workspace root */
114
+ file_path: string;
115
+ /** File content (null for large files in Storage) */
116
+ content: string | null;
117
+ /** SHA-256 hash of file content */
118
+ content_hash: string;
119
+ /** File size in bytes */
120
+ size: number;
121
+ /** ISO timestamp when remote change occurred */
122
+ updated_at: string;
123
+ /** Storage URL for large files (>200KB) */
124
+ storage_url?: string;
125
+ }
126
+ /**
127
+ * ConflictEvent represents a detected conflict between local and remote versions
128
+ *
129
+ * Conflict occurs when both local and remote versions changed since last sync.
130
+ * Agent creates git-style conflict markers and commits the conflicted file.
131
+ */
132
+ export interface ConflictEvent {
133
+ /** Reference to the workspace */
134
+ workspace_id: string;
135
+ /** File path relative to workspace root */
136
+ file_path: string;
137
+ /** SHA-256 hash of local version */
138
+ local_hash: string;
139
+ /** SHA-256 hash of remote version */
140
+ remote_hash: string;
141
+ /** Local file content */
142
+ local_content: string;
143
+ /** Remote file content */
144
+ remote_content: string;
145
+ /** ISO timestamp when conflict detected */
146
+ detected_at: string;
147
+ }
148
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Core type definitions for GSD Agent
3
+ *
4
+ * These types define the data structures used throughout the agent for
5
+ * workspace management, file change tracking, and synchronization.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Tests for type definitions
3
+ *
4
+ * Validates that new types compile correctly and have expected structure.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.test.d.ts","sourceRoot":"","sources":["../src/types.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Tests for type definitions
3
+ *
4
+ * Validates that new types compile correctly and have expected structure.
5
+ */
6
+ import { describe, it, expect } from 'vitest';
7
+ describe('RemoteChangeEvent type', () => {
8
+ it('should compile with all required fields', () => {
9
+ const event = {
10
+ id: 'evt_123',
11
+ workspace_id: 'ws_456',
12
+ file_path: '.planning/STATE.md',
13
+ content: '# State content',
14
+ content_hash: 'abc123',
15
+ size: 1024,
16
+ updated_at: '2026-03-27T01:00:00Z'
17
+ };
18
+ expect(event.id).toBe('evt_123');
19
+ expect(event.workspace_id).toBe('ws_456');
20
+ expect(event.file_path).toBe('.planning/STATE.md');
21
+ expect(event.content).toBe('# State content');
22
+ expect(event.content_hash).toBe('abc123');
23
+ expect(event.size).toBe(1024);
24
+ expect(event.updated_at).toBe('2026-03-27T01:00:00Z');
25
+ });
26
+ it('should allow null content for large files', () => {
27
+ const event = {
28
+ id: 'evt_789',
29
+ workspace_id: 'ws_456',
30
+ file_path: '.planning/large-file.md',
31
+ content: null,
32
+ content_hash: 'def456',
33
+ size: 300000,
34
+ updated_at: '2026-03-27T01:00:00Z',
35
+ storage_url: 'https://storage.supabase.co/bucket/file.md'
36
+ };
37
+ expect(event.content).toBeNull();
38
+ expect(event.storage_url).toBe('https://storage.supabase.co/bucket/file.md');
39
+ });
40
+ it('should allow optional storage_url', () => {
41
+ const event = {
42
+ id: 'evt_999',
43
+ workspace_id: 'ws_456',
44
+ file_path: '.planning/small.md',
45
+ content: 'small content',
46
+ content_hash: 'ghi789',
47
+ size: 100,
48
+ updated_at: '2026-03-27T01:00:00Z'
49
+ };
50
+ expect(event.storage_url).toBeUndefined();
51
+ });
52
+ });
53
+ describe('ConflictEvent type', () => {
54
+ it('should compile with all required fields', () => {
55
+ const conflict = {
56
+ workspace_id: 'ws_456',
57
+ file_path: '.planning/PROJECT.md',
58
+ local_hash: 'local_abc',
59
+ remote_hash: 'remote_def',
60
+ local_content: 'Local version',
61
+ remote_content: 'Remote version',
62
+ detected_at: '2026-03-27T01:30:00Z'
63
+ };
64
+ expect(conflict.workspace_id).toBe('ws_456');
65
+ expect(conflict.file_path).toBe('.planning/PROJECT.md');
66
+ expect(conflict.local_hash).toBe('local_abc');
67
+ expect(conflict.remote_hash).toBe('remote_def');
68
+ expect(conflict.local_content).toBe('Local version');
69
+ expect(conflict.remote_content).toBe('Remote version');
70
+ expect(conflict.detected_at).toBe('2026-03-27T01:30:00Z');
71
+ });
72
+ });
73
+ //# sourceMappingURL=types.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.test.js","sourceRoot":"","sources":["../src/types.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Filesystem watcher for GSD Agent
3
+ *
4
+ * Watches .planning/ directories for file changes using chokidar.
5
+ * Handles atomic writes, debouncing, and ignored patterns per research findings.
6
+ */
7
+ import { EventEmitter } from 'events';
8
+ import { Workspace, SyncConfig } from './types.js';
9
+ import { Logger } from './logger.js';
10
+ /**
11
+ * FileWatcher class monitors .planning/ directories for changes
12
+ */
13
+ export declare class FileWatcher extends EventEmitter {
14
+ private workspaces;
15
+ private config;
16
+ private logger;
17
+ private watcher;
18
+ private debounceTimers;
19
+ constructor(workspaces: Workspace[], config: SyncConfig, logger: Logger);
20
+ /**
21
+ * Start watching all workspace .planning/ directories
22
+ */
23
+ start(): void;
24
+ /**
25
+ * Stop watching and clean up
26
+ */
27
+ stop(): void;
28
+ /**
29
+ * Handle file system events with debouncing
30
+ * @param filePath Absolute path to changed file
31
+ * @param eventType Type of change event
32
+ */
33
+ private handleFileEvent;
34
+ /**
35
+ * Process a file event and emit FileChangeEvent
36
+ * @param filePath Absolute path to changed file
37
+ * @param eventType Type of change event
38
+ */
39
+ private processFileEvent;
40
+ /**
41
+ * Find workspace that contains the given file path
42
+ * @param filePath Absolute path to file
43
+ * @returns Workspace object or null if not found
44
+ */
45
+ private findWorkspaceForFile;
46
+ }
47
+ /**
48
+ * Create and start a filesystem watcher
49
+ * @param workspaces Array of workspaces to watch
50
+ * @param config SyncConfig with watch settings
51
+ * @param logger Logger instance
52
+ * @returns FileWatcher instance
53
+ */
54
+ export declare function createWatcher(workspaces: Workspace[], config: SyncConfig, logger: Logger): FileWatcher;
55
+ //# sourceMappingURL=watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAmB,MAAM,YAAY,CAAA;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAGpC;;GAEG;AACH,qBAAa,WAAY,SAAQ,YAAY;IAC3C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,cAAc,CAAyC;gBAEnD,UAAU,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM;IAOvE;;OAEG;IACH,KAAK,IAAI,IAAI;IA2Db;;OAEG;IACH,IAAI,IAAI,IAAI;IAeZ;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAqBvB;;;;OAIG;YACW,gBAAgB;IAmE9B;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;CAQ7B;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,SAAS,EAAE,EACvB,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,GACb,WAAW,CAIb"}
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Filesystem watcher for GSD Agent
3
+ *
4
+ * Watches .planning/ directories for file changes using chokidar.
5
+ * Handles atomic writes, debouncing, and ignored patterns per research findings.
6
+ */
7
+ import chokidar from 'chokidar';
8
+ import fs from 'fs';
9
+ import path from 'path';
10
+ import { randomUUID } from 'crypto';
11
+ import { EventEmitter } from 'events';
12
+ import { hashFile } from './hash.js';
13
+ /**
14
+ * FileWatcher class monitors .planning/ directories for changes
15
+ */
16
+ export class FileWatcher extends EventEmitter {
17
+ workspaces;
18
+ config;
19
+ logger;
20
+ watcher = null;
21
+ debounceTimers = new Map();
22
+ constructor(workspaces, config, logger) {
23
+ super();
24
+ this.workspaces = workspaces;
25
+ this.config = config;
26
+ this.logger = logger;
27
+ }
28
+ /**
29
+ * Start watching all workspace .planning/ directories
30
+ */
31
+ start() {
32
+ if (this.watcher) {
33
+ this.logger.warn('Watcher already started');
34
+ return;
35
+ }
36
+ // Build list of paths to watch
37
+ const watchPaths = this.workspaces.map(ws => path.join(ws.root_path, '.planning'));
38
+ // Filter out non-existent paths
39
+ const existingPaths = watchPaths.filter(p => {
40
+ if (!fs.existsSync(p)) {
41
+ this.logger.warn(`Watch path does not exist: ${p}`);
42
+ return false;
43
+ }
44
+ return true;
45
+ });
46
+ if (existingPaths.length === 0) {
47
+ this.logger.warn('No valid watch paths found');
48
+ return;
49
+ }
50
+ // Configure chokidar with atomic write handling and ignored patterns
51
+ this.watcher = chokidar.watch(existingPaths, {
52
+ ignored: [
53
+ /node_modules/,
54
+ /\.git/,
55
+ /dist/,
56
+ /build/,
57
+ /\.log$/,
58
+ /\.DS_Store$/
59
+ ],
60
+ persistent: true,
61
+ ignoreInitial: false, // emit events for existing files on startup
62
+ awaitWriteFinish: {
63
+ stabilityThreshold: 300, // wait 300ms for file size to stabilize
64
+ pollInterval: 100
65
+ },
66
+ atomic: true, // filter atomic write temp files
67
+ depth: 5 // limit recursion depth
68
+ });
69
+ // Set up event handlers
70
+ this.watcher
71
+ .on('add', (filePath) => this.handleFileEvent(filePath, 'add'))
72
+ .on('change', (filePath) => this.handleFileEvent(filePath, 'change'))
73
+ .on('unlink', (filePath) => this.handleFileEvent(filePath, 'unlink'))
74
+ .on('error', (error) => {
75
+ this.logger.error('Watcher error', { error });
76
+ })
77
+ .on('ready', () => {
78
+ this.logger.info('Filesystem watcher ready', {
79
+ paths: existingPaths,
80
+ workspaces: this.workspaces.length
81
+ });
82
+ });
83
+ }
84
+ /**
85
+ * Stop watching and clean up
86
+ */
87
+ stop() {
88
+ if (this.watcher) {
89
+ this.watcher.close();
90
+ this.watcher = null;
91
+ }
92
+ // Clear all pending debounce timers
93
+ for (const timer of this.debounceTimers.values()) {
94
+ clearTimeout(timer);
95
+ }
96
+ this.debounceTimers.clear();
97
+ this.logger.info('Filesystem watcher stopped');
98
+ }
99
+ /**
100
+ * Handle file system events with debouncing
101
+ * @param filePath Absolute path to changed file
102
+ * @param eventType Type of change event
103
+ */
104
+ handleFileEvent(filePath, eventType) {
105
+ // For unlink events, emit immediately (no debounce)
106
+ if (eventType === 'unlink') {
107
+ void this.processFileEvent(filePath, eventType);
108
+ return;
109
+ }
110
+ // For add/change events, debounce to handle rapid changes
111
+ const existingTimer = this.debounceTimers.get(filePath);
112
+ if (existingTimer) {
113
+ clearTimeout(existingTimer);
114
+ }
115
+ const timer = setTimeout(() => {
116
+ this.debounceTimers.delete(filePath);
117
+ void this.processFileEvent(filePath, eventType);
118
+ }, this.config.debounce_ms);
119
+ this.debounceTimers.set(filePath, timer);
120
+ }
121
+ /**
122
+ * Process a file event and emit FileChangeEvent
123
+ * @param filePath Absolute path to changed file
124
+ * @param eventType Type of change event
125
+ */
126
+ async processFileEvent(filePath, eventType) {
127
+ try {
128
+ // Find workspace for this file
129
+ const workspace = this.findWorkspaceForFile(filePath);
130
+ if (!workspace) {
131
+ this.logger.warn(`No workspace found for file: ${filePath}`);
132
+ return;
133
+ }
134
+ // Compute relative path from workspace root
135
+ const relativePath = path.relative(workspace.root_path, filePath);
136
+ // Build FileChangeEvent
137
+ let contentHash = '';
138
+ let content;
139
+ let metadata;
140
+ if (eventType !== 'unlink') {
141
+ try {
142
+ // Read file content and compute hash
143
+ content = fs.readFileSync(filePath, 'utf-8');
144
+ contentHash = await hashFile(filePath);
145
+ // Get file stats
146
+ const stats = fs.statSync(filePath);
147
+ metadata = {
148
+ size: stats.size,
149
+ mtime: stats.mtime.toISOString(),
150
+ agent_version: '0.1.0'
151
+ };
152
+ }
153
+ catch (error) {
154
+ this.logger.error(`Failed to read file: ${filePath}`, { error });
155
+ return;
156
+ }
157
+ }
158
+ else {
159
+ // For unlink events, no content or metadata
160
+ metadata = {
161
+ size: 0,
162
+ mtime: new Date().toISOString(),
163
+ agent_version: '0.1.0'
164
+ };
165
+ }
166
+ const event = {
167
+ id: randomUUID(),
168
+ workspace_id: workspace.id,
169
+ file_path: relativePath,
170
+ event_type: eventType,
171
+ content_hash: contentHash,
172
+ content,
173
+ source: 'cli',
174
+ timestamp: new Date().toISOString(),
175
+ metadata
176
+ };
177
+ // Emit the event
178
+ this.emit('change', event);
179
+ this.logger.debug(`File event processed: ${eventType} ${relativePath}`, {
180
+ workspace_id: workspace.id,
181
+ content_hash: contentHash
182
+ });
183
+ }
184
+ catch (error) {
185
+ this.logger.error(`Error processing file event: ${filePath}`, { error });
186
+ }
187
+ }
188
+ /**
189
+ * Find workspace that contains the given file path
190
+ * @param filePath Absolute path to file
191
+ * @returns Workspace object or null if not found
192
+ */
193
+ findWorkspaceForFile(filePath) {
194
+ for (const workspace of this.workspaces) {
195
+ if (filePath.startsWith(workspace.root_path)) {
196
+ return workspace;
197
+ }
198
+ }
199
+ return null;
200
+ }
201
+ }
202
+ /**
203
+ * Create and start a filesystem watcher
204
+ * @param workspaces Array of workspaces to watch
205
+ * @param config SyncConfig with watch settings
206
+ * @param logger Logger instance
207
+ * @returns FileWatcher instance
208
+ */
209
+ export function createWatcher(workspaces, config, logger) {
210
+ const watcher = new FileWatcher(workspaces, config, logger);
211
+ watcher.start();
212
+ return watcher;
213
+ }
214
+ //# sourceMappingURL=watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,QAAuB,MAAM,UAAU,CAAA;AAC9C,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAGrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEpC;;GAEG;AACH,MAAM,OAAO,WAAY,SAAQ,YAAY;IACnC,UAAU,CAAa;IACvB,MAAM,CAAY;IAClB,MAAM,CAAQ;IACd,OAAO,GAAqB,IAAI,CAAA;IAChC,cAAc,GAAgC,IAAI,GAAG,EAAE,CAAA;IAE/D,YAAY,UAAuB,EAAE,MAAkB,EAAE,MAAc;QACrE,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAA;YAC3C,OAAM;QACR,CAAC;QAED,+BAA+B;QAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAA;QAElF,gCAAgC;QAChC,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;YAC1C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,EAAE,CAAC,CAAA;gBACnD,OAAO,KAAK,CAAA;YACd,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC,CAAC,CAAA;QAEF,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAA;YAC9C,OAAM;QACR,CAAC;QAED,qEAAqE;QACrE,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,aAAa,EAAE;YAC3C,OAAO,EAAE;gBACP,cAAc;gBACd,OAAO;gBACP,MAAM;gBACN,OAAO;gBACP,QAAQ;gBACR,aAAa;aACd;YACD,UAAU,EAAE,IAAI;YAChB,aAAa,EAAE,KAAK,EAAE,4CAA4C;YAClE,gBAAgB,EAAE;gBAChB,kBAAkB,EAAE,GAAG,EAAE,wCAAwC;gBACjE,YAAY,EAAE,GAAG;aAClB;YACD,MAAM,EAAE,IAAI,EAAE,iCAAiC;YAC/C,KAAK,EAAE,CAAC,CAAC,wBAAwB;SAClC,CAAC,CAAA;QAEF,wBAAwB;QACxB,IAAI,CAAC,OAAO;aACT,EAAE,CAAC,KAAK,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;aACtE,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;aAC5E,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;aAC5E,EAAE,CAAC,OAAO,EAAE,CAAC,KAAc,EAAE,EAAE;YAC9B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QAC/C,CAAC,CAAC;aACD,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAChB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE;gBAC3C,KAAK,EAAE,aAAa;gBACpB,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM;aACnC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACN,CAAC;IAED;;OAEG;IACH,IAAI;QACF,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;YACpB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QACrB,CAAC;QAED,oCAAoC;QACpC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC;YACjD,YAAY,CAAC,KAAK,CAAC,CAAA;QACrB,CAAC;QACD,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAA;QAE3B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAA;IAChD,CAAC;IAED;;;;OAIG;IACK,eAAe,CAAC,QAAgB,EAAE,SAAsC;QAC9E,oDAAoD;QACpD,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC3B,KAAK,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;YAC/C,OAAM;QACR,CAAC;QAED,0DAA0D;QAC1D,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACvD,IAAI,aAAa,EAAE,CAAC;YAClB,YAAY,CAAC,aAAa,CAAC,CAAA;QAC7B,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;YACpC,KAAK,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;QACjD,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;QAE3B,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;IAC1C,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,gBAAgB,CAAC,QAAgB,EAAE,SAAsC;QACrF,IAAI,CAAC;YACH,+BAA+B;YAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAA;YACrD,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gCAAgC,QAAQ,EAAE,CAAC,CAAA;gBAC5D,OAAM;YACR,CAAC;YAED,4CAA4C;YAC5C,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;YAEjE,wBAAwB;YACxB,IAAI,WAAW,GAAG,EAAE,CAAA;YACpB,IAAI,OAA2B,CAAA;YAC/B,IAAI,QAAiD,CAAA;YAErD,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;gBAC3B,IAAI,CAAC;oBACH,qCAAqC;oBACrC,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;oBAC5C,WAAW,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAA;oBAEtC,iBAAiB;oBACjB,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;oBACnC,QAAQ,GAAG;wBACT,IAAI,EAAE,KAAK,CAAC,IAAI;wBAChB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE;wBAChC,aAAa,EAAE,OAAO;qBACvB,CAAA;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;oBAChE,OAAM;gBACR,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,4CAA4C;gBAC5C,QAAQ,GAAG;oBACT,IAAI,EAAE,CAAC;oBACP,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oBAC/B,aAAa,EAAE,OAAO;iBACvB,CAAA;YACH,CAAC;YAED,MAAM,KAAK,GAAoB;gBAC7B,EAAE,EAAE,UAAU,EAAE;gBAChB,YAAY,EAAE,SAAS,CAAC,EAAE;gBAC1B,SAAS,EAAE,YAAY;gBACvB,UAAU,EAAE,SAAS;gBACrB,YAAY,EAAE,WAAW;gBACzB,OAAO;gBACP,MAAM,EAAE,KAAK;gBACb,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,QAAQ;aACT,CAAA;YAED,iBAAiB;YACjB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;YAE1B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,SAAS,IAAI,YAAY,EAAE,EAAE;gBACtE,YAAY,EAAE,SAAS,CAAC,EAAE;gBAC1B,YAAY,EAAE,WAAW;aAC1B,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;QAC1E,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,oBAAoB,CAAC,QAAgB;QAC3C,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACxC,IAAI,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC7C,OAAO,SAAS,CAAA;YAClB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,UAAuB,EACvB,MAAkB,EAClB,MAAc;IAEd,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAC3D,OAAO,CAAC,KAAK,EAAE,CAAA;IACf,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Tests for filesystem watcher
3
+ *
4
+ * Verifies that the watcher detects file changes, debounces events,
5
+ * handles atomic writes, and ignores excluded patterns.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=watcher.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.test.d.ts","sourceRoot":"","sources":["../src/watcher.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}