Is your feature request related to a problem? Please describe.
Currently, when using file-based knowledge sources (MarkdownSource, JSONSource, SQLiteSource), any changes to the source files require either:
- Manually calling
kb.sync() to re-index
- Restarting the entire application
This creates a poor developer experience during development and prevents long-running agents from automatically updating their knowledge base when documentation or data files change. For example, a documentation chatbot cannot automatically pick up new articles without a restart.
Describe the solution you'd like
Implement the watch?(): AsyncIterable<ChunkUpdate> method defined in the KnowledgeSource interface for all file-based sources. This will enable automatic detection and incremental updates when source files change.
Implementation Details
1. MarkdownSource Watch Mode
File: packages/toolpack-knowledge/src/sources/markdown.ts
Implementation Steps:
-
Add watch option to constructor - Add a watch?: boolean option to MarkdownSourceOptions interface
-
Implement watch() method using fs.watch - Use Node.js native fs.watch to monitor directories containing matched files, detect file changes/renames, and emit appropriate ChunkUpdate events
-
Add chunk tracking - Maintain a Map<string, Chunk[]> to track which chunks belong to which files for efficient updates
-
Update load() to track chunks - Modify the existing load() method to populate the chunk tracking map during initial ingestion
2. JSONSource Watch Mode
File: packages/toolpack-knowledge/src/sources/json.ts
Implementation Steps:
Similar to MarkdownSource, but:
- Watch single JSON file (not a glob pattern)
- Parse entire file on change with 500ms debounce to handle rapid changes
- Compare chunk IDs to determine what changed (added, updated, deleted)
- Implement
diffChunks() helper to efficiently compute differences
- Emit appropriate ChunkUpdate events based on the diff
3. SQLiteSource Watch Mode (Poll-based)
File: packages/toolpack-knowledge/src/sources/sqlite.ts
Implementation Steps:
SQLite doesn't support native file watching, so use poll-based change detection:
-
Add watch configuration options - watch, pollInterval (default 5000ms), changeDetection strategy, and relevant column names
-
Implement three change detection strategies:
- Watermark mode: Query rows where ID > last seen ID (most efficient for append-only tables)
- Timestamp mode: Query rows where updated_at > last check time (for tables with update timestamps)
- Scan mode: Full table scan with content hash comparison (expensive, for legacy tables without suitable columns)
-
Poll on interval - Continuously check for changes every pollInterval milliseconds
-
Emit ChunkUpdate events - Convert detected changes to appropriate add/update events
4. Knowledge Class Integration
File: packages/toolpack-knowledge/src/knowledge.ts
Implementation Steps:
-
Start watchers after initial sync - Call startWatchers() at the end of Knowledge.create() after the initial sync completes
-
Implement watcher management:
- Maintain array of active watchers
- For each source with
watch() method, start the watcher
- Process updates in background using
processWatchUpdates()
- Handle add/update events by embedding content and adding to provider
- Handle delete events by removing chunks from provider
- Trigger
onSync callbacks for monitoring
- Respect
onError handler for error handling
-
Update stop() method - Properly clean up all watchers by calling their return() method and clearing the watchers array before closing the provider
5. Testing
File: packages/toolpack-knowledge/src/__tests__/watch-mode.test.ts
Create comprehensive tests covering:
- New file detection - Create a new markdown file and verify it gets indexed automatically
- File modification detection - Modify an existing file and verify the chunks are updated
- File deletion detection - Delete a file and verify its chunks are removed from the knowledge base
- Multiple sources - Test watch mode with multiple sources simultaneously
- Error handling - Test behavior when file operations fail
- Cleanup - Verify watchers are properly stopped when
kb.stop() is called
Acceptance Criteria
Describe alternatives you've considered
- Manual sync polling: Require users to call
kb.sync() on a timer - rejected because it's inefficient and requires full re-indexing
- External file watcher service: Use a separate process to watch files - rejected because it adds deployment complexity
- Chokidar library: Use
chokidar instead of native fs.watch - considered for better cross-platform support, but adds dependency
Additional context
- Watch mode is optional and disabled by default to avoid unexpected behavior
- Native
fs.watch is sufficient for most use cases; can add chokidar later if needed
- SQLite watch mode uses polling because SQLite doesn't support change notifications
- This feature enables "live reload" workflows during development
- Critical for long-running agents that need to stay up-to-date with changing documentation
Dependencies:
- No new dependencies required (uses native
fs.watch)
- Optional:
chokidar for better cross-platform file watching (future enhancement)
Related Issues:
- Implements interface defined in
packages/toolpack-knowledge/src/interfaces.ts:49
- Complements
reSync: false option in PersistentKnowledgeProvider
Is your feature request related to a problem? Please describe.
Currently, when using file-based knowledge sources (
MarkdownSource,JSONSource,SQLiteSource), any changes to the source files require either:kb.sync()to re-indexThis creates a poor developer experience during development and prevents long-running agents from automatically updating their knowledge base when documentation or data files change. For example, a documentation chatbot cannot automatically pick up new articles without a restart.
Describe the solution you'd like
Implement the
watch?(): AsyncIterable<ChunkUpdate>method defined in theKnowledgeSourceinterface for all file-based sources. This will enable automatic detection and incremental updates when source files change.Implementation Details
1. MarkdownSource Watch Mode
File:
packages/toolpack-knowledge/src/sources/markdown.tsImplementation Steps:
Add watch option to constructor - Add a
watch?: booleanoption toMarkdownSourceOptionsinterfaceImplement watch() method using fs.watch - Use Node.js native
fs.watchto monitor directories containing matched files, detect file changes/renames, and emit appropriateChunkUpdateeventsAdd chunk tracking - Maintain a
Map<string, Chunk[]>to track which chunks belong to which files for efficient updatesUpdate load() to track chunks - Modify the existing
load()method to populate the chunk tracking map during initial ingestion2. JSONSource Watch Mode
File:
packages/toolpack-knowledge/src/sources/json.tsImplementation Steps:
Similar to MarkdownSource, but:
diffChunks()helper to efficiently compute differences3. SQLiteSource Watch Mode (Poll-based)
File:
packages/toolpack-knowledge/src/sources/sqlite.tsImplementation Steps:
SQLite doesn't support native file watching, so use poll-based change detection:
Add watch configuration options -
watch,pollInterval(default 5000ms),changeDetectionstrategy, and relevant column namesImplement three change detection strategies:
Poll on interval - Continuously check for changes every
pollIntervalmillisecondsEmit ChunkUpdate events - Convert detected changes to appropriate add/update events
4. Knowledge Class Integration
File:
packages/toolpack-knowledge/src/knowledge.tsImplementation Steps:
Start watchers after initial sync - Call
startWatchers()at the end ofKnowledge.create()after the initial sync completesImplement watcher management:
watch()method, start the watcherprocessWatchUpdates()onSynccallbacks for monitoringonErrorhandler for error handlingUpdate stop() method - Properly clean up all watchers by calling their
return()method and clearing the watchers array before closing the provider5. Testing
File:
packages/toolpack-knowledge/src/__tests__/watch-mode.test.tsCreate comprehensive tests covering:
kb.stop()is calledAcceptance Criteria
MarkdownSourceimplementswatch()usingfs.watchJSONSourceimplementswatch()with file watchingSQLiteSourceimplementswatch()with poll-based detectionKnowledge.create()automatically starts watchers for sources that support itkb.stop()properly cleans up all watchersPersistentKnowledgeProviderDescribe alternatives you've considered
kb.sync()on a timer - rejected because it's inefficient and requires full re-indexingchokidarinstead of nativefs.watch- considered for better cross-platform support, but adds dependencyAdditional context
fs.watchis sufficient for most use cases; can addchokidarlater if neededDependencies:
fs.watch)chokidarfor better cross-platform file watching (future enhancement)Related Issues:
packages/toolpack-knowledge/src/interfaces.ts:49reSync: falseoption inPersistentKnowledgeProvider