Spaces:
Paused
Paused
| 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 | |
| } | |
| ]; | |