Add real-time developer messaging via NATS
- Add SendMessageTool for sending messages to other devs
- Add ReceiveMessagesTool for receiving messages
- Auto-detect sender role from workspace path (admin-dev/api-dev/web-dev)
- Messages published to NATS channels: dev.messages.{role}
- Enable real-time communication between Claude instances
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -8,9 +8,10 @@ const logger = createLogger('ToolRegistry');
|
||||
|
||||
export class ToolRegistry {
|
||||
private tools = new Map<string, ToolDefinition>();
|
||||
private builtinHandlers = createBuiltinTools();
|
||||
private builtinHandlers: Map<string, ToolHandler>;
|
||||
|
||||
constructor(private natsClient: NatsClient) {
|
||||
this.builtinHandlers = createBuiltinTools(natsClient);
|
||||
this.registerBuiltinTools();
|
||||
}
|
||||
|
||||
|
||||
115
src/tools/builtin/messaging.ts
Normal file
115
src/tools/builtin/messaging.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { ToolHandler } from '../base/ToolHandler';
|
||||
import { NatsClient } from '../../nats/NatsClient';
|
||||
|
||||
// Detect current developer role from workspace
|
||||
function detectRole(): string {
|
||||
const cwd = process.cwd();
|
||||
if (cwd.includes('joylo-admin')) return 'admin-dev';
|
||||
if (cwd.includes('joylo-api')) return 'api-dev';
|
||||
if (cwd.includes('joylo-web')) return 'web-dev';
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
export class SendMessageTool extends ToolHandler {
|
||||
name = 'send_message';
|
||||
description = 'Send real-time message to another developer via NATS';
|
||||
|
||||
inputSchema = {
|
||||
type: 'object' as const,
|
||||
properties: {
|
||||
to: {
|
||||
type: 'string',
|
||||
description: 'Recipient role: admin-dev, api-dev, or web-dev',
|
||||
enum: ['admin-dev', 'api-dev', 'web-dev'],
|
||||
},
|
||||
subject: {
|
||||
type: 'string',
|
||||
description: 'Message subject/title',
|
||||
},
|
||||
message: {
|
||||
type: 'string',
|
||||
description: 'Message content',
|
||||
},
|
||||
data: {
|
||||
type: 'object',
|
||||
description: 'Optional structured data',
|
||||
},
|
||||
},
|
||||
required: ['to', 'subject', 'message'],
|
||||
};
|
||||
|
||||
constructor(private natsClient: NatsClient) {
|
||||
super();
|
||||
}
|
||||
|
||||
async execute(input: any): Promise<any> {
|
||||
const { to, subject, message, data } = input;
|
||||
const from = detectRole();
|
||||
|
||||
const payload = {
|
||||
from,
|
||||
to,
|
||||
subject,
|
||||
message,
|
||||
data,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
|
||||
// Publish to NATS channel for recipient
|
||||
const channel = `dev.messages.${to}`;
|
||||
await this.natsClient.publish(channel, payload);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: `Message sent from ${from} to ${to}`,
|
||||
channel,
|
||||
payload,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class ReceiveMessagesTool extends ToolHandler {
|
||||
name = 'receive_messages';
|
||||
description = 'Receive real-time messages from other developers via NATS';
|
||||
|
||||
inputSchema = {
|
||||
type: 'object' as const,
|
||||
properties: {
|
||||
limit: {
|
||||
type: 'number',
|
||||
description: 'Maximum number of messages to return (default: 10)',
|
||||
default: 10,
|
||||
},
|
||||
},
|
||||
required: [],
|
||||
};
|
||||
|
||||
private messages: any[] = [];
|
||||
|
||||
constructor(private natsClient: NatsClient) {
|
||||
super();
|
||||
this.setupSubscription();
|
||||
}
|
||||
|
||||
private setupSubscription() {
|
||||
const myRole = detectRole();
|
||||
const channel = `dev.messages.${myRole}`;
|
||||
|
||||
// Subscribe to messages for this role
|
||||
this.natsClient.subscribe(channel, (msg) => {
|
||||
this.messages.push(msg);
|
||||
});
|
||||
}
|
||||
|
||||
async execute(input: any): Promise<any> {
|
||||
const limit = input.limit || 10;
|
||||
const recentMessages = this.messages.slice(-limit);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
role: detectRole(),
|
||||
count: recentMessages.length,
|
||||
messages: recentMessages,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -4,24 +4,26 @@ import { FileWriteTool } from './builtin/FileWriteTool';
|
||||
import { FileListTool } from './builtin/FileListTool';
|
||||
import { SystemCommandTool } from './builtin/SystemCommandTool';
|
||||
import { HttpRequestTool } from './builtin/HttpRequestTool';
|
||||
import { SendMessageTool, ReceiveMessagesTool } from './builtin/messaging';
|
||||
import { NatsClient } from '../nats/NatsClient';
|
||||
|
||||
export * from './base/ToolHandler';
|
||||
|
||||
// Registry of all built-in tools
|
||||
export const builtinTools: ToolHandler[] = [
|
||||
new FileReadTool(),
|
||||
new FileWriteTool(),
|
||||
new FileListTool(),
|
||||
new SystemCommandTool(),
|
||||
new HttpRequestTool(),
|
||||
];
|
||||
|
||||
export function createBuiltinTools(): Map<string, ToolHandler> {
|
||||
export function createBuiltinTools(natsClient: NatsClient): Map<string, ToolHandler> {
|
||||
const tools = new Map<string, ToolHandler>();
|
||||
|
||||
for (const tool of builtinTools) {
|
||||
tools.set(tool.name, tool);
|
||||
}
|
||||
// File operation tools
|
||||
tools.set('file_read', new FileReadTool());
|
||||
tools.set('file_write', new FileWriteTool());
|
||||
tools.set('file_list', new FileListTool());
|
||||
|
||||
// System tools
|
||||
tools.set('system_command', new SystemCommandTool());
|
||||
tools.set('http_request', new HttpRequestTool());
|
||||
|
||||
// Messaging tools (require NATS client)
|
||||
tools.set('send_message', new SendMessageTool(natsClient));
|
||||
tools.set('receive_messages', new ReceiveMessagesTool(natsClient));
|
||||
|
||||
return tools;
|
||||
}
|
||||
Reference in New Issue
Block a user