@tokenring-ai/code-watch
The @tokenring-ai/code-watch package provides a file monitoring service for the Token Ring AI ecosystem. It watches configured filesystems for file changes, detects special AI comment patterns (like # AI! or // AI!), and automatically spawns agents to execute code modifications based on those instructions.
This service uses polling-based file system watching with configurable intervals and stability thresholds to debounce rapid file changes. When an AI comment with the AI! marker is detected, the service spawns a configured agent type in headless mode to execute the requested code modifications.
Overview
Code Watch provides real-time file system monitoring for detecting code changes and processing AI instructions embedded in comments. It integrates seamlessly with the Token Ring agent framework, providing background service functionality that operates without chat commands or tools.
Key Features
- File System Monitoring: Watches multiple filesystems for file additions and changes using virtual filesystem providers
- AI Comment Detection: Detects AI triggers in both Python/shell (
#) and C-style (//) comments - Smart Change Handling: Uses stability thresholds to debounce rapid file changes
- Concurrent Processing: Processes files concurrently with configurable worker queue via
async.queue - Agent Integration: Automatically spawns appropriate agents to execute AI instructions in headless mode
- Error Handling: Comprehensive error logging and graceful failure handling
- Ignore Filtering: Respects ignore patterns from filesystem providers
- Background Service: Runs as a background service without chat commands or tools
Core Components
CodeWatchService
The main service responsible for file monitoring and AI comment processing. Implements the TokenRingService interface.
Location: pkg/code-watch/CodeWatchService.ts
Interface: Implements TokenRingService from @tokenring-ai/app
Plugin
Coordinates service registration and configuration handling using the TokenRingPlugin interface.
Location: pkg/code-watch/plugin.ts
Exports: Default token ring plugin configuration
Services
CodeWatchService
The primary service implementation that provides file monitoring and AI comment processing capabilities.
Implements: TokenRingService
Constructor:
constructor(app: TokenRingApp, config: z.output<typeof CodeWatchConfigSchema>)
Parameters:
app: TokenRing application instanceconfig: Configuration object for service settings
Properties:
| Property | Type | Description |
|---|---|---|
name | "CodeWatchService" | Service name |
description | string | Service description: "Provides CodeWatch functionality that monitors files for AI comments" |
app | TokenRingApp | TokenRing application instance |
config | CodeWatchConfig | Service configuration |
workQueue | Async.Queue<{ filePath: string, fileSystemProviderName: string }> | Async queue for concurrent file processing operations |
Methods:
async run(signal: AbortSignal): Promise<void>
Starts the service and begins monitoring files for changes across all configured filesystems.
Parameters:
signal:AbortSignalto cancel the service
Returns: Promise<void> that resolves when all watchers are set up
Behavior:
- Iterates through all configured filesystems
- Calls
watchFileSystem()for each filesystem - Returns after all watchers are set up
- Handles graceful shutdown when signal is aborted
async watchFileSystem(fileSystemProviderName: string, filesystemConfig: FileSystemConfig, signal: AbortSignal): Promise<void>
Configures a new filesystem to watch.
Parameters:
fileSystemProviderName: Unique identifier for the filesystem providerfilesystemConfig: Configuration object includingpollInterval,stabilityThreshold, andagentTypesignal:AbortSignalto cancel the watcher
Returns: Promise<void> that resolves when the watcher is set up
Behavior:
- Retrieves
FileSystemServicefrom the app - Gets the filesystem provider by name
- Creates a file system watcher using the provider's
watch()method - Sets up event handlers for
add,change, andunlinkevents - Implements debouncing using
stabilityThresholdto handle rapid changes - Processes files that pass the stability threshold via
workQueue - Uses ignore patterns from the filesystem provider via
createIgnoreFilter() - Returns after setting up the watcher and waiting for abort signal
Event Handling:
const onFileChanged = (eventType: string, filePath: string) => {
if (modifiedFiles.has(filePath)) {
clearTimeout(modifiedFiles.get(filePath));
modifiedFiles.delete(filePath);
}
if (eventType === "add" || eventType === "change") {
modifiedFiles.set(filePath, setTimeout(() => {
this.workQueue.push({filePath, fileSystemProviderName});
}));
}
};
async processFileForAIComments({filePath, fileSystemProviderName}: {filePath: string, fileSystemProviderName: string}): Promise<void>
Scans a file for AI comments and processes them.
Parameters:
filePath: Path to the filefileSystemProviderName: Name of the filesystem provider
Returns: Promise<void> that resolves when processing is complete
Behavior:
- Reads the file content from the filesystem provider
- Splits content into lines
- Checks each line for AI comment patterns:
- Lines starting with
#(Python/shell style) - Lines starting with
//(C-style)
- Lines starting with
- Calls
checkAndTriggerAIAction()for each comment line
async checkAndTriggerAIAction(line: string, filePath: string, lineNumber: number, fileSystemProviderName: string): Promise<void>
Checks a comment line for AI triggers and initiates action.
Parameters:
line: The comment line content (trimmed)filePath: Path of the file containing the commentlineNumber: Line number in the file (1-indexed)fileSystemProviderName: Name of the filesystem provider
Returns: Promise<void> that resolves when action is initiated
AI Trigger Patterns:
- Lines starting with
# AIor// AI - Lines ending with
AI!
If either pattern matches, calls handleAIComment().
async handleAIComment(commentLine: string, filePath: string, lineNumber: number, fileSystemProviderName: string): Promise<void>
Handles processing of a specific AI comment.
Parameters:
commentLine: The comment line contentfilePath: Path of the filelineNumber: Line number in the filefileSystemProviderName: Name of the filesystem provider
Returns: Promise<void> that resolves when handling is complete
Behavior:
- Extracts the actual comment content (removes
#or//markers) - Checks if comment contains
AI!marker - Triggers code modification if
AI!is present viatriggerCodeModification()
Comment Content Extraction:
let content = commentLine.trim();
if (commentLine.startsWith("# ")) {
content = commentLine.substring(2);
} else if (commentLine.startsWith("// ")) {
content = commentLine.substring(3);
}
async triggerCodeModification(content: string, filePath: string, lineNumber: number, fileSystemProviderName: string): Promise<void>
Triggers code modification agent for an AI! comment.
Parameters:
content: The content of the commentfilePath: Path of the filelineNumber: Line number in the filefileSystemProviderName: Name of the filesystem provider
Returns: Promise<void> that resolves when code modification starts
Behavior:
- Retrieves
AgentManagerandFileSystemServicefrom the app - Gets the agent type from the filesystem configuration
- Spawns agent of specified type in headless mode via
agentManager.spawnAgent() - Sets active filesystem for the agent via
fileSystemService.setActiveFileSystem() - Creates and executes modification prompt
- Calls
runCodeModification()to execute the agent - Agent is responsible for removing the
AI!comment after completion
Prompt Template:
The service generates a prompt that instructs the agent to:
- Look for lines marked with
AI!tag - Complete the instructions in that line or nearby comments
- Update the file using the file_write tool
- Must remove any lines that end with
AI!
async runCodeModification(prompt: string, filePath: string, agent: Agent): Promise<void>
Executes code modification agent.
Parameters:
prompt: The instruction prompt for the agentfilePath: Path of the fileagent: TheAgentinstance to execute commands on
Returns: Promise<void> that resolves when modification is complete
Behavior:
- Adds file to agent's chat context via
fileSystemService.addFileToChat() - Retrieves
AgentCommandServicefrom the agent - Executes
/workcommand with the prompt viaagentCommandService.executeAgentCommand() - Waits for agent to complete the task
Chat Commands
This package does not provide chat commands. It operates as a background service monitoring files for changes.
RPC Endpoints
This package does not define RPC endpoints.
Configuration
Configuration Schema
The plugin configuration is defined in plugin.ts:
import { TokenRingPlugin } from "@tokenring-ai/app";
import { z } from "zod";
import CodeWatchService from "./CodeWatchService.ts";
import { CodeWatchConfigSchema } from "./index.ts";
import packageJSON from './package.json' with {type: 'json'};
const packageConfigSchema = z.object({
codewatch: CodeWatchConfigSchema.optional(),
});
export default {
name: packageJSON.name,
version: packageJSON.version,
description: packageJSON.description,
install(app, config) {
if (config.codewatch) {
app.addServices(new CodeWatchService(app, config.codewatch));
}
},
config: packageConfigSchema
} satisfies TokenRingPlugin<typeof packageConfigSchema>;
The configuration schema is defined in index.ts:
import { z } from "zod";
export const CodeWatchConfigSchema = z.object({
filesystems: z.record(z.string(), z.object({
pollInterval: z.number().default(1000),
stabilityThreshold: z.number().default(2000),
agentType: z.string()
})),
concurrency: z.number().default(1),
});
Configuration Options
Top-Level Configuration
| Field | Type | Default | Description |
|---|---|---|---|
codewatch | CodeWatchConfig | optional | Main configuration for CodeWatch service |
CodeWatchConfig
| Field | Type | Default | Description |
|---|---|---|---|
filesystems | Record<string, FileSystemConfig> | required | Configuration for each filesystem to monitor |
concurrency | number | 1 | Maximum concurrent file processing operations |
FileSystemConfig
| Field | Type | Default | Description |
|---|---|---|---|
pollInterval | number | 1000 | Polling interval in milliseconds for detecting file changes |
stabilityThreshold | number | 2000 | Time in milliseconds to wait after a change before processing |
agentType | string | required | Type of agent to spawn for code modifications |
Configuration Example
{
codewatch: {
filesystems: {
local: {
pollInterval: 1000, // Check for changes every 1 second
stabilityThreshold: 2000, // Wait 2 seconds after last change before processing
agentType: 'code-modification-agent'
}
},
concurrency: 2 // Process up to 2 files concurrently
}
}
Integration
Plugin Registration
The package integrates with the TokenRing application through the plugin system:
import TokenRingApp from '@tokenring-ai/app';
import codeWatch from '@tokenring-ai/code-watch/plugin';
const app = new TokenRingApp();
app.install(codeWatch, {
codewatch: {
filesystems: {
local: {
pollInterval: 1000,
stabilityThreshold: 2000,
agentType: 'code-modification-agent'
}
},
concurrency: 2
}
});
Service Registration
When installed, the plugin automatically registers the CodeWatchService:
if (config.codewatch) {
app.addServices(new CodeWatchService(app, config.codewatch));
}
Required Services
The CodeWatchService requires the following services to be available:
FileSystemService: For file operations and watchingAgentManager: For spawning agents to execute AI instructions
Agent Workflow
When an AI! comment is detected in a file:
- The service spawns an agent of the specified type in headless mode
- The file is added to the agent's chat context using
FileSystemService.addFileToChat() - The agent executes the instruction from the
AI!comment via/workcommand - The agent uses available tools to complete the requested task
- The agent updates the file using the file write tool
- The agent removes the
AI!comment from the file as a completion marker
Usage Examples
Basic Plugin Installation
import TokenRingApp from '@tokenring-ai/app';
import codeWatch from '@tokenring-ai/code-watch/plugin';
const app = new TokenRingApp();
app.install(codeWatch, {
codewatch: {
filesystems: {
local: {
pollInterval: 1000,
stabilityThreshold: 2000,
agentType: 'code-modification-agent'
}
},
concurrency: 2
}
});
// Start the application
await app.run();
Multiple Filesystem Configuration
import TokenRingApp from '@tokenring-ai/app';
import codeWatch from '@tokenring-ai/code-watch/plugin';
const app = new TokenRingApp();
app.install(codeWatch, {
codewatch: {
filesystems: {
local: {
pollInterval: 1000,
stabilityThreshold: 2000,
agentType: 'code-modification-agent'
},
project: {
pollInterval: 1500,
stabilityThreshold: 2500,
agentType: 'project-agent'
}
},
concurrency: 3
}
});
await app.run();
AI Comment Examples
Python/Shell Style Comments
# AI! Fix the off-by-one error in the loop below
for i in range(10):
print(i)
C-Style Comments
// AI! Refactor this function to use async/await
function fetchData() {
return fetch('/api/data').then(res => res.json());
}
Inline AI Instructions
const result = processData(data); // AI! Add error handling here
Comment Detection Patterns
The service detects AI comments using these patterns:
- Lines starting with
# AI(Python/shell style) - Lines starting with
// AI(C-style) - Lines ending with
AI!(any style)
Important: Only comments containing AI! will trigger code modification. Comments that match the prefix patterns but don't contain AI! will be detected but won't trigger action.
Best Practices
Agent Selection
Choose appropriate agent types based on the complexity of tasks:
- Use simpler agents for straightforward modifications
- Use more capable agents for complex refactoring
Balancing Performance
- Adjust
pollIntervalfor responsiveness vs. system load - Set appropriate
stabilityThresholdto avoid processing incomplete writes - Configure
concurrencybased on your system's capabilities - Stability thresholds handle file write completion detection
Error Monitoring
Implement monitoring for service errors to catch issues early:
- File processing errors are logged via
app.serviceError() - Agent execution errors are caught and logged
- Watcher errors are caught and logged via event handlers
File Stability
Ensure files are fully written before triggering processing. The stabilityThreshold handles this by waiting for changes to settle through debouncing.
Provider Configuration
Configure appropriate filesystem providers before starting:
- Each filesystem provider must support watch and readFile operations
- Providers should have appropriate ignore patterns for non-code files
- Polling intervals can vary by filesystem location
Testing and Development
Running Tests
bun test
Running Tests in Watch Mode
bun test:watch
Running Test Coverage
bun test:coverage
Build
bun build
Package Structure
pkg/code-watch/
├── index.ts # Configuration schema and exports
├── CodeWatchService.ts # Main service implementation
├── plugin.ts # Plugin definition and registration
├── package.json # Package metadata and dependencies
├── README.md # Package documentation
├── vitest.config.ts # Test configuration
└── BRAINSTORM.md # Feature brainstorming and roadmap
Test Configuration
Test files are configured in vitest.config.ts:
import {defineConfig} from "vitest/config";
export default defineConfig({
test: {
include: ["**/*.test.ts"],
environment: "node",
globals: true,
isolate: true,
},
});
Note: No test files currently exist in the package. Test infrastructure is configured but individual tests have not been implemented yet.
Dependencies
Production Dependencies
| Package | Version | Description |
|---|---|---|
@tokenring-ai/app | 0.2.0 | Core application framework |
@tokenring-ai/agent | 0.2.0 | Agent management and orchestration |
@tokenring-ai/filesystem | 0.2.0 | File system abstraction and providers |
@tokenring-ai/utility | 0.2.0 | Utility functions and helpers |
@tokenring-ai/chat | 0.2.0 | Chat functionality |
zod | ^4.3.6 | Schema validation |
async | ^3.2.6 | Concurrent processing utilities |
ignore | ^7.0.5 | Ignore pattern matching |
Development Dependencies
| Package | Version | Description |
|---|---|---|
vitest | ^4.1.0 | Testing framework |
typescript | ^5.9.3 | TypeScript compiler |
@types/async | ^3.2.25 | Async type definitions |
Related Components
-
@tokenring-ai/app: Core application framework
TokenRingPlugin: Plugin interface and TokenRingApp accessTokenRingService: Service interface and service registrationTokenRingApp: Main application class
-
@tokenring-ai/agent: Agent management and execution
Agent: Agent class for command executionAgentManager: Agent spawning and managementAgentCommandService: Command execution interface
-
@tokenring-ai/filesystem: File system abstraction
FileSystemService: File system managementFileSystemProvider: File system provider interfacecreateIgnoreFilter: Ignore pattern filter utility
-
@tokenring-ai/utility: Utility functions
waitForAbort: Abort signal handler utility
License
MIT License - see LICENSE file for details.