From f25e0f9a10fb85a747c5b91d62b4972d1be2c3cd Mon Sep 17 00:00:00 2001 From: gavrielc Date: Sun, 1 Feb 2026 16:00:44 +0200 Subject: [PATCH] Remove redundant comments throughout codebase Keep only comments that explain non-obvious behavior or add context not apparent from reading the code. Co-Authored-By: Claude Opus 4.5 --- container/agent-runner/src/index.ts | 10 +--------- container/agent-runner/src/ipc-mcp.ts | 13 ++----------- src/auth.ts | 1 - src/config.ts | 9 ++++----- src/container-runner.ts | 25 ++----------------------- src/db.ts | 2 -- src/index.ts | 11 +---------- src/scheduler.ts | 6 +----- 8 files changed, 11 insertions(+), 66 deletions(-) diff --git a/container/agent-runner/src/index.ts b/container/agent-runner/src/index.ts index 60125f1..652654b 100644 --- a/container/agent-runner/src/index.ts +++ b/container/agent-runner/src/index.ts @@ -52,11 +52,8 @@ function log(message: string): void { console.error(`[agent-runner] ${message}`); } -/** - * Find session summary from sessions-index.json - */ function getSessionSummary(sessionId: string, transcriptPath: string): string | null { - // The sessions-index.json is in the same directory as the transcript + // sessions-index.json is in the same directory as the transcript const projectDir = path.dirname(transcriptPath); const indexPath = path.join(projectDir, 'sessions-index.json'); @@ -101,7 +98,6 @@ function createPreCompactHook(): HookCallback { return {}; } - // Get summary from sessions-index.json for the filename const summary = getSessionSummary(sessionId, transcriptPath); const name = summary ? sanitizeFilename(summary) : generateFallbackName(); @@ -124,9 +120,6 @@ function createPreCompactHook(): HookCallback { }; } -/** - * Sanitize a summary string into a valid filename. - */ function sanitizeFilename(summary: string): string { return summary .toLowerCase() @@ -165,7 +158,6 @@ function parseTranscript(content: string): ParsedMessage[] { if (text) messages.push({ role: 'assistant', content: text }); } } catch { - // Skip malformed lines } } diff --git a/container/agent-runner/src/ipc-mcp.ts b/container/agent-runner/src/ipc-mcp.ts index 18f7435..37ffd94 100644 --- a/container/agent-runner/src/ipc-mcp.ts +++ b/container/agent-runner/src/ipc-mcp.ts @@ -19,14 +19,12 @@ export interface IpcMcpContext { } function writeIpcFile(dir: string, data: object): string { - // Ensure directory exists fs.mkdirSync(dir, { recursive: true }); - // Use timestamp + random suffix for unique filename const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}.json`; const filepath = path.join(dir, filename); - // Write atomically: write to temp file, then rename + // Atomic write: temp file then rename const tempPath = `${filepath}.tmp`; fs.writeFileSync(tempPath, JSON.stringify(data, null, 2)); fs.renameSync(tempPath, filepath); @@ -41,7 +39,6 @@ export function createIpcMcp(ctx: IpcMcpContext) { name: 'nanoclaw', version: '1.0.0', tools: [ - // Send a message to the WhatsApp group tool( 'send_message', 'Send a message to the current WhatsApp group. Use this to proactively share information or updates.', @@ -68,7 +65,6 @@ export function createIpcMcp(ctx: IpcMcpContext) { } ), - // Schedule a new task tool( 'schedule_task', 'Schedule a recurring or one-time task. The task will run as a full agent with access to all tools.', @@ -104,13 +100,12 @@ export function createIpcMcp(ctx: IpcMcpContext) { } ), - // List tasks (reads from a mounted file that host keeps updated) + // Reads from current_tasks.json which host keeps updated tool( 'list_tasks', 'List all scheduled tasks. From main: shows all tasks. From other groups: shows only that group\'s tasks.', {}, async () => { - // Host process writes current tasks to this file const tasksFile = path.join(IPC_DIR, 'current_tasks.json'); try { @@ -125,7 +120,6 @@ export function createIpcMcp(ctx: IpcMcpContext) { const allTasks = JSON.parse(fs.readFileSync(tasksFile, 'utf-8')); - // Filter to current group unless main const tasks = isMain ? allTasks : allTasks.filter((t: { groupFolder: string }) => t.groupFolder === groupFolder); @@ -160,7 +154,6 @@ export function createIpcMcp(ctx: IpcMcpContext) { } ), - // Pause a task tool( 'pause_task', 'Pause a scheduled task. It will not run until resumed.', @@ -187,7 +180,6 @@ export function createIpcMcp(ctx: IpcMcpContext) { } ), - // Resume a task tool( 'resume_task', 'Resume a paused task.', @@ -214,7 +206,6 @@ export function createIpcMcp(ctx: IpcMcpContext) { } ), - // Cancel a task tool( 'cancel_task', 'Cancel and delete a scheduled task.', diff --git a/src/auth.ts b/src/auth.ts index 0635d2c..5ca64d0 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -28,7 +28,6 @@ async function authenticate(): Promise { const { state, saveCreds } = await useMultiFileAuthState(AUTH_DIR); - // Check if already authenticated if (state.creds.registered) { console.log('✓ Already authenticated with WhatsApp'); console.log(' To re-authenticate, delete the store/auth folder and run again.'); diff --git a/src/config.ts b/src/config.ts index d275f4e..1d29490 100644 --- a/src/config.ts +++ b/src/config.ts @@ -2,18 +2,17 @@ import path from 'path'; export const ASSISTANT_NAME = process.env.ASSISTANT_NAME || 'Andy'; export const POLL_INTERVAL = 2000; -export const SCHEDULER_POLL_INTERVAL = 60000; // Check for due tasks every minute +export const SCHEDULER_POLL_INTERVAL = 60000; -// Use absolute paths for container mounts +// Absolute paths needed for container mounts const PROJECT_ROOT = process.cwd(); export const STORE_DIR = path.resolve(PROJECT_ROOT, 'store'); export const GROUPS_DIR = path.resolve(PROJECT_ROOT, 'groups'); export const DATA_DIR = path.resolve(PROJECT_ROOT, 'data'); export const MAIN_GROUP_FOLDER = 'main'; -// Container configuration export const CONTAINER_IMAGE = process.env.CONTAINER_IMAGE || 'nanoclaw-agent:latest'; -export const CONTAINER_TIMEOUT = parseInt(process.env.CONTAINER_TIMEOUT || '300000', 10); // 5 minutes default -export const IPC_POLL_INTERVAL = 1000; // Check IPC directories every second +export const CONTAINER_TIMEOUT = parseInt(process.env.CONTAINER_TIMEOUT || '300000', 10); +export const IPC_POLL_INTERVAL = 1000; export const TRIGGER_PATTERN = new RegExp(`^@${ASSISTANT_NAME}\\b`, 'i'); diff --git a/src/container-runner.ts b/src/container-runner.ts index ee4a684..ef025e1 100644 --- a/src/container-runner.ts +++ b/src/container-runner.ts @@ -90,7 +90,6 @@ function buildVolumeMounts(group: RegisteredGroup, isMain: boolean): VolumeMount }); } - // Gmail MCP credentials const gmailDir = path.join(homeDir, '.gmail-mcp'); if (fs.existsSync(gmailDir)) { mounts.push({ @@ -100,7 +99,6 @@ function buildVolumeMounts(group: RegisteredGroup, isMain: boolean): VolumeMount }); } - // IPC directory for messages and tasks const ipcDir = path.join(DATA_DIR, 'ipc'); fs.mkdirSync(path.join(ipcDir, 'messages'), { recursive: true }); fs.mkdirSync(path.join(ipcDir, 'tasks'), { recursive: true }); @@ -115,7 +113,6 @@ function buildVolumeMounts(group: RegisteredGroup, isMain: boolean): VolumeMount fs.mkdirSync(envDir, { recursive: true }); const envFile = path.join(projectRoot, '.env'); if (fs.existsSync(envFile)) { - // Copy .env to the env directory as a plain file called 'env' fs.copyFileSync(envFile, path.join(envDir, 'env')); mounts.push({ hostPath: envDir, @@ -124,10 +121,8 @@ function buildVolumeMounts(group: RegisteredGroup, isMain: boolean): VolumeMount }); } - // Additional mounts from group config if (group.containerConfig?.additionalMounts) { for (const mount of group.containerConfig.additionalMounts) { - // Resolve home directory in path const hostPath = mount.hostPath.startsWith('~') ? path.join(homeDir, mount.hostPath.slice(1)) : mount.hostPath; @@ -150,8 +145,7 @@ function buildVolumeMounts(group: RegisteredGroup, isMain: boolean): VolumeMount function buildContainerArgs(mounts: VolumeMount[]): string[] { const args: string[] = ['run', '-i', '--rm']; - // Add volume mounts - // Apple Container: use --mount for readonly, -v for read-write + // Apple Container: --mount for readonly, -v for read-write for (const mount of mounts) { if (mount.readonly) { args.push('--mount', `type=bind,source=${mount.hostPath},target=${mount.containerPath},readonly`); @@ -160,7 +154,6 @@ function buildContainerArgs(mounts: VolumeMount[]): string[] { } } - // Add the image name args.push(CONTAINER_IMAGE); return args; @@ -172,15 +165,12 @@ export async function runContainerAgent( ): Promise { const startTime = Date.now(); - // Ensure group directory exists const groupDir = path.join(GROUPS_DIR, group.folder); fs.mkdirSync(groupDir, { recursive: true }); - // Build volume mounts const mounts = buildVolumeMounts(group, input.isMain); const containerArgs = buildContainerArgs(mounts); - // Log detailed mount info at debug level logger.debug({ group: group.name, mounts: mounts.map(m => `${m.hostPath} -> ${m.containerPath}${m.readonly ? ' (ro)' : ''}`), @@ -193,7 +183,6 @@ export async function runContainerAgent( isMain: input.isMain }, 'Spawning container agent'); - // Create logs directory for this group const logsDir = path.join(GROUPS_DIR, group.folder, 'logs'); fs.mkdirSync(logsDir, { recursive: true }); @@ -205,7 +194,6 @@ export async function runContainerAgent( let stdout = ''; let stderr = ''; - // Send input JSON to container stdin container.stdin.write(JSON.stringify(input)); container.stdin.end(); @@ -215,14 +203,12 @@ export async function runContainerAgent( container.stderr.on('data', (data) => { stderr += data.toString(); - // Log container stderr in real-time const lines = data.toString().trim().split('\n'); for (const line of lines) { if (line) logger.debug({ container: group.folder }, line); } }); - // Timeout handler const timeout = setTimeout(() => { logger.error({ group: group.name }, 'Container timeout, killing'); container.kill('SIGKILL'); @@ -237,12 +223,10 @@ export async function runContainerAgent( clearTimeout(timeout); const duration = Date.now() - startTime; - // Write container log file const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const logFile = path.join(logsDir, `container-${timestamp}.log`); const isVerbose = process.env.LOG_LEVEL === 'debug' || process.env.LOG_LEVEL === 'trace'; - // Build log content - only include full input/output in verbose mode const logLines = [ `=== Container Run Log ===`, `Timestamp: ${new Date().toISOString()}`, @@ -254,7 +238,6 @@ export async function runContainerAgent( ]; if (isVerbose) { - // Full content logging only in debug/trace mode logLines.push( `=== Input ===`, JSON.stringify(input, null, 2), @@ -272,7 +255,6 @@ export async function runContainerAgent( stdout ); } else { - // Minimal logging by default - no message content logLines.push( `=== Input Summary ===`, `Prompt length: ${input.prompt.length} chars`, @@ -283,7 +265,6 @@ export async function runContainerAgent( `` ); - // Only include stderr/stdout if there was an error if (code !== 0) { logLines.push( `=== Stderr (last 500 chars) ===`, @@ -313,9 +294,8 @@ export async function runContainerAgent( return; } - // Parse JSON output from stdout try { - // Find the JSON line (last non-empty line should be the output) + // Last non-empty line is the JSON output const lines = stdout.trim().split('\n'); const jsonLine = lines[lines.length - 1]; const output: ContainerOutput = JSON.parse(jsonLine); @@ -355,7 +335,6 @@ export async function runContainerAgent( }); } -// Export task snapshot for container IPC export function writeTasksSnapshot(tasks: Array<{ id: string; groupFolder: string; diff --git a/src/db.ts b/src/db.ts index 855054c..def0114 100644 --- a/src/db.ts +++ b/src/db.ts @@ -129,8 +129,6 @@ export function getMessagesSince(chatJid: string, sinceTimestamp: string): NewMe return db.prepare(sql).all(chatJid, sinceTimestamp) as NewMessage[]; } -// Scheduled Tasks - export function createTask(task: Omit): void { db.prepare(` INSERT INTO scheduled_tasks (id, group_folder, chat_jid, prompt, schedule_type, schedule_value, next_run, status, created_at) diff --git a/src/index.ts b/src/index.ts index e37cf0d..9fa25b0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -81,11 +81,10 @@ async function processMessage(msg: NewMessage): Promise { if (!TRIGGER_PATTERN.test(content)) return; - // Get messages since last agent interaction to catch up the session + // Get all messages since last agent interaction so the session has full context const sinceTimestamp = lastAgentTimestamp[msg.chat_jid] || ''; const missedMessages = getMessagesSince(msg.chat_jid, sinceTimestamp); - // Build prompt with conversation history const lines = missedMessages.map(m => { const d = new Date(m.timestamp); const date = d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); @@ -102,7 +101,6 @@ async function processMessage(msg: NewMessage): Promise { const response = await runAgent(group, prompt, msg.chat_jid); await setTyping(msg.chat_jid, false); - // Update last agent timestamp lastAgentTimestamp[msg.chat_jid] = msg.timestamp; if (response) { @@ -135,7 +133,6 @@ async function runAgent(group: RegisteredGroup, prompt: string, chatJid: string) isMain }); - // Update session if changed if (output.newSessionId) { sessions[group.folder] = output.newSessionId; saveJson(path.join(DATA_DIR, 'sessions.json'), sessions); @@ -162,7 +159,6 @@ async function sendMessage(jid: string, text: string): Promise { } } -// IPC watcher for container messages and tasks function startIpcWatcher(): void { const messagesDir = path.join(DATA_DIR, 'ipc', 'messages'); const tasksDir = path.join(DATA_DIR, 'ipc', 'tasks'); @@ -171,7 +167,6 @@ function startIpcWatcher(): void { fs.mkdirSync(tasksDir, { recursive: true }); const processIpcFiles = async () => { - // Process pending messages try { const messageFiles = fs.readdirSync(messagesDir).filter(f => f.endsWith('.json')); for (const file of messageFiles) { @@ -195,7 +190,6 @@ function startIpcWatcher(): void { logger.error({ err }, 'Error reading IPC messages directory'); } - // Process pending task operations try { const taskFiles = fs.readdirSync(tasksDir).filter(f => f.endsWith('.json')); for (const file of taskFiles) { @@ -241,7 +235,6 @@ async function processTaskIpc(data: { if (data.prompt && data.schedule_type && data.schedule_value && data.groupFolder && data.chatJid) { const scheduleType = data.schedule_type as 'cron' | 'interval' | 'once'; - // Calculate next run time let nextRun: string | null = null; if (scheduleType === 'cron') { const interval = CronExpressionParser.parse(data.schedule_value); @@ -395,11 +388,9 @@ async function startMessageLoop(): Promise { function ensureContainerSystemRunning(): void { try { - // Check if container system is already running execSync('container system status', { stdio: 'pipe' }); logger.debug('Apple Container system already running'); } catch { - // Not running, try to start it logger.info('Starting Apple Container system...'); try { execSync('container system start', { stdio: 'pipe', timeout: 30000 }); diff --git a/src/scheduler.ts b/src/scheduler.ts index b6bb5b9..0eb463a 100644 --- a/src/scheduler.ts +++ b/src/scheduler.ts @@ -24,7 +24,6 @@ async function runTask(task: ScheduledTask, deps: SchedulerDependencies): Promis logger.info({ taskId: task.id, group: task.group_folder }, 'Running scheduled task'); - // Find the group config for this task const groups = deps.registeredGroups(); const group = Object.values(groups).find(g => g.folder === task.group_folder); @@ -78,7 +77,6 @@ async function runTask(task: ScheduledTask, deps: SchedulerDependencies): Promis const durationMs = Date.now() - startTime; - // Log the run logTaskRun({ task_id: task.id, run_at: new Date().toISOString(), @@ -88,7 +86,6 @@ async function runTask(task: ScheduledTask, deps: SchedulerDependencies): Promis error }); - // Calculate next run let nextRun: string | null = null; if (task.schedule_type === 'cron') { const interval = CronExpressionParser.parse(task.schedule_value); @@ -97,9 +94,8 @@ async function runTask(task: ScheduledTask, deps: SchedulerDependencies): Promis const ms = parseInt(task.schedule_value, 10); nextRun = new Date(Date.now() + ms).toISOString(); } - // 'once' tasks don't have a next run + // 'once' tasks have no next run - // Update task const resultSummary = error ? `Error: ${error}` : (result ? result.slice(0, 200) : 'Completed'); updateTaskAfterRun(task.id, nextRun, resultSummary); }