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 {
|
export class ToolRegistry {
|
||||||
private tools = new Map<string, ToolDefinition>();
|
private tools = new Map<string, ToolDefinition>();
|
||||||
private builtinHandlers = createBuiltinTools();
|
private builtinHandlers: Map<string, ToolHandler>;
|
||||||
|
|
||||||
constructor(private natsClient: NatsClient) {
|
constructor(private natsClient: NatsClient) {
|
||||||
|
this.builtinHandlers = createBuiltinTools(natsClient);
|
||||||
this.registerBuiltinTools();
|
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 { FileListTool } from './builtin/FileListTool';
|
||||||
import { SystemCommandTool } from './builtin/SystemCommandTool';
|
import { SystemCommandTool } from './builtin/SystemCommandTool';
|
||||||
import { HttpRequestTool } from './builtin/HttpRequestTool';
|
import { HttpRequestTool } from './builtin/HttpRequestTool';
|
||||||
|
import { SendMessageTool, ReceiveMessagesTool } from './builtin/messaging';
|
||||||
|
import { NatsClient } from '../nats/NatsClient';
|
||||||
|
|
||||||
export * from './base/ToolHandler';
|
export * from './base/ToolHandler';
|
||||||
|
|
||||||
// Registry of all built-in tools
|
export function createBuiltinTools(natsClient: NatsClient): Map<string, ToolHandler> {
|
||||||
export const builtinTools: ToolHandler[] = [
|
|
||||||
new FileReadTool(),
|
|
||||||
new FileWriteTool(),
|
|
||||||
new FileListTool(),
|
|
||||||
new SystemCommandTool(),
|
|
||||||
new HttpRequestTool(),
|
|
||||||
];
|
|
||||||
|
|
||||||
export function createBuiltinTools(): Map<string, ToolHandler> {
|
|
||||||
const tools = new Map<string, ToolHandler>();
|
const tools = new Map<string, ToolHandler>();
|
||||||
|
|
||||||
for (const tool of builtinTools) {
|
// File operation tools
|
||||||
tools.set(tool.name, tool);
|
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;
|
return tools;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user