import * as fs from 'fs/promises'; import * as path from 'path'; import { SAFE_DESKTOP_PATH, listSafeFiles } from './FileSystemTools.js'; // Handlers async function handleReadAgentMessages(args: any) { const agent = args?.agent || 'claude'; const inboxPath = path.join(SAFE_DESKTOP_PATH, 'agents', agent, 'inbox'); try { const files = await listSafeFiles(inboxPath, false); const messages: any[] = []; for (const file of files) { if (file.type === '.json') { try { const content = await fs.readFile( path.join(inboxPath, file.name), 'utf-8' ); messages.push(JSON.parse(content)); } catch { // Skip invalid JSON } } } return { content: [{ type: 'text', text: JSON.stringify({ agent: agent, inboxPath: inboxPath, messageCount: messages.length, messages: messages }, null, 2) }] }; } catch (error: any) { return { content: [{ type: 'text', text: JSON.stringify({ error: error.message, hint: 'Agent inbox may not exist yet' }, null, 2) }] }; } } async function handleSendAgentMessage(args: any) { const { to, type, subject, body, priority = 'normal' } = args; if (!to || !type || !subject || !body) { throw new Error('to, type, subject, and body are required'); } const timestamp = new Date().toISOString(); const messageId = `msg-${Date.now()}`; const filename = `${timestamp.replace(/[:.]/g, '-')}_claude_${to}_${type}.json`; const message = { id: messageId, timestamp: timestamp, from: 'claude', to: to, type: type, priority: priority, subject: subject, body: body, context: { session: 'neural-bridge', source: 'mcp-tool' }, requires_response: type !== 'status' && type !== 'response' }; // Write to own outbox const outboxPath = path.join(SAFE_DESKTOP_PATH, 'agents', 'claude', 'outbox', filename); await fs.writeFile(outboxPath, JSON.stringify(message, null, 2)); // Copy to recipient's inbox if (to !== 'human') { const recipientInbox = path.join(SAFE_DESKTOP_PATH, 'agents', to, 'inbox', filename); await fs.writeFile(recipientInbox, JSON.stringify(message, null, 2)); } return { content: [{ type: 'text', text: JSON.stringify({ success: true, messageId: messageId, sentTo: to, filename: filename, message: `Message sent to ${to}` }, null, 2) }] }; } async function handleNeuralChatSend(args: any) { const { channel, body, from, priority, type } = args; const { neuralChatService } = await import('../../services/NeuralChat/index.js'); const message = await neuralChatService.sendMessage({ channel: channel || 'core-dev', body, from: from || 'claude', priority: priority || 'normal', type: type || 'chat' }); return { content: [{ type: 'text', text: JSON.stringify({ success: true, message }, null, 2) }] }; } async function handleNeuralChatRead(args: any) { const { channel, limit, since } = args; const { neuralChatService } = await import('../../services/NeuralChat/index.js'); const messages = await neuralChatService.getMessages({ channel, limit: limit || 20, since }); return { content: [{ type: 'text', text: JSON.stringify({ channel: channel || 'all', count: messages.length, messages }, null, 2) }] }; } async function handleNeuralChatChannels(args: any) { const { neuralChatService } = await import('../../services/NeuralChat/index.js'); const channels = neuralChatService.getChannels(); return { content: [{ type: 'text', text: JSON.stringify({ count: channels.length, channels }, null, 2) }] }; } async function handleListAgentCapabilities(args: any) { const { agent } = args; const { capabilityBroker, AGENT_CAPABILITIES } = await import('../../services/NeuralChat/CapabilityBroker.js'); if (agent) { const capabilities = capabilityBroker.getAgentCapabilities(agent); return { content: [{ type: 'text', text: JSON.stringify({ agent, capabilities }, null, 2) }] }; } return { content: [{ type: 'text', text: JSON.stringify({ agents: Object.keys(AGENT_CAPABILITIES), capabilities: AGENT_CAPABILITIES }, null, 2) }] }; } async function handleRequestCapability(args: any) { const { toAgent, capability, params, priority } = args; const { capabilityBroker } = await import('../../services/NeuralChat/CapabilityBroker.js'); const request = await capabilityBroker.requestCapability({ fromAgent: 'claude', toAgent, capability, params: params || {}, priority: priority || 'normal' }); return { content: [{ type: 'text', text: JSON.stringify({ success: true, request, message: `Capability request sent to ${toAgent}` }, null, 2) }] }; } async function handleGetPendingRequests(args: any) { const { agent } = args; const { capabilityBroker } = await import('../../services/NeuralChat/CapabilityBroker.js'); const requests = await capabilityBroker.getPendingRequests(agent); return { content: [{ type: 'text', text: JSON.stringify({ agent, pending: requests.length, requests }, null, 2) }] }; } async function handleSmartRouteTask(args: any) { const { task, context } = args; const { capabilityBroker } = await import('../../services/NeuralChat/CapabilityBroker.js'); const result = await capabilityBroker.smartRoute({ task, context, fromAgent: 'claude' }); if (result) { return { content: [{ type: 'text', text: JSON.stringify({ success: true, recommendation: { agent: result.agent, capability: result.capability.name, confidence: `${(result.confidence * 100).toFixed(0)}%`, description: result.capability.description }, message: `Best match: ${result.agent} for "${result.capability.name}"` }, null, 2) }] }; } return { content: [{ type: 'text', text: JSON.stringify({ success: false, message: 'No suitable agent found for this task' }, null, 2) }] }; } export const AGENT_TOOLS = [ { name: 'read_agent_messages', description: 'Read messages from the agent communication inbox', inputSchema: { type: 'object', properties: { agent: { type: 'string', enum: ['claude', 'gemini'], description: 'Which agent inbox to read' }, unreadOnly: { type: 'boolean', description: 'Only show unread messages' } } }, handler: handleReadAgentMessages }, { name: 'send_agent_message', description: 'Send a message to another agent via the communication protocol', inputSchema: { type: 'object', properties: { to: { type: 'string', enum: ['gemini', 'claude', 'human'], description: 'Recipient agent' }, type: { type: 'string', enum: ['response', 'task', 'question', 'status', 'alert'], description: 'Message type' }, subject: { type: 'string', description: 'Message subject' }, body: { type: 'string', description: 'Message body' }, priority: { type: 'string', enum: ['low', 'normal', 'high', 'critical'], description: 'Message priority' } }, required: ['to', 'type', 'subject', 'body'] }, handler: handleSendAgentMessage }, { name: 'neural_chat_send', description: 'Send a message to a Neural Chat channel for real-time agent communication', inputSchema: { type: 'object', properties: { channel: { type: 'string', description: 'Channel to send to (core-dev, standup, alerts)' }, body: { type: 'string', description: 'Message content' }, from: { type: 'string', enum: ['claude', 'gemini', 'deepseek', 'clak', 'system'], description: 'Sender agent' }, priority: { type: 'string', enum: ['low', 'normal', 'high', 'critical'], description: 'Message priority' }, type: { type: 'string', enum: ['chat', 'task', 'status', 'alert', 'handover', 'response'], description: 'Message type' } }, required: ['channel', 'body', 'from'] }, handler: handleNeuralChatSend }, { name: 'neural_chat_read', description: 'Read messages from Neural Chat channels', inputSchema: { type: 'object', properties: { channel: { type: 'string', description: 'Channel to read from (optional, reads all if not specified)' }, limit: { type: 'number', description: 'Max messages to return (default: 20)' }, since: { type: 'string', description: 'ISO timestamp to read messages since' } } }, handler: handleNeuralChatRead }, { name: 'neural_chat_channels', description: 'List all Neural Chat channels', inputSchema: { type: 'object', properties: {} }, handler: handleNeuralChatChannels }, { name: 'list_agent_capabilities', description: 'List capabilities of agents (what each agent is good at)', inputSchema: { type: 'object', properties: { agent: { type: 'string', enum: ['claude', 'gemini', 'deepseek', 'clak'], description: 'Specific agent to list capabilities for (optional)' } } }, handler: handleListAgentCapabilities }, { name: 'request_capability', description: 'Request another agent to perform a task based on their capabilities', inputSchema: { type: 'object', properties: { toAgent: { type: 'string', enum: ['claude', 'gemini', 'deepseek', 'clak'], description: 'Agent to request capability from' }, capability: { type: 'string', description: 'Capability ID or name to request' }, params: { type: 'object', description: 'Parameters for the capability request' }, priority: { type: 'string', enum: ['low', 'normal', 'high', 'critical'], description: 'Request priority' } }, required: ['toAgent', 'capability'] }, handler: handleRequestCapability }, { name: 'get_pending_requests', description: 'Get pending capability requests assigned to an agent', inputSchema: { type: 'object', properties: { agent: { type: 'string', enum: ['claude', 'gemini', 'deepseek', 'clak'], description: 'Agent to check pending requests for' } }, required: ['agent'] }, handler: handleGetPendingRequests }, { name: 'smart_route_task', description: 'Find the best agent for a task based on capability matching', inputSchema: { type: 'object', properties: { task: { type: 'string', description: 'Description of the task to route' }, context: { type: 'string', description: 'Additional context for routing decision' } }, required: ['task'] }, handler: handleSmartRouteTask } ];