agenthub/src/cli/commands/message.ts
chahinebrini 07afa717ac feat(messaging): agent messaging — agenthub_message / agenthub_inbox (cross-agent via MCP)
Direct messages between agents through the hub — architect↔agent and agent↔agent
questions, clarifications and pings that handoffs/memories don't cover. Built as
MCP tools so kimi + codex get it too (not Claude-only), plus REST + CLI.

- Message entity (MSG-NNNN): schema, counter, messages/ dir, messageService
  (createMessage / listInbox / listMessages / markMessageRead).
- REST: POST /messages, GET /messages[?agent&unread], POST /messages/:id/read,
  with SSE emit. fsWatch + statusRefresh wired ('message' events; status skips them).
- MCP: agenthub_message {from,to,text,taskId?} + agenthub_inbox {agent,unreadOnly?}.
  agenthub_work now surfaces + drains unread messages and wakes on message events,
  so an agent sees messages inside its work loop. (18 tools total.)
- CLI: `agenthub message <to> <text> --from <agent>` + `agenthub inbox --agent`.
  watch stream shows "Message" events (architect-visible).
- Architect-visible by design: the hub stays the coordination point.

Bump 0.7.5 -> 0.8.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 03:20:38 +02:00

22 lines
775 B
TypeScript

import { createMessage, listInbox } from '../../core/services/messageService.js';
export function messageSend(
cwd: string,
opts: { from: string; to: string; text: string; taskId?: string },
): void {
const m = createMessage(cwd, opts);
console.log(`AgentHub: Message sent ${m.id} (${m.from}${m.to})`);
}
export function inboxList(cwd: string, opts: { agent: string; unreadOnly?: boolean }): void {
const msgs = listInbox(cwd, opts.agent, { unreadOnly: opts.unreadOnly });
if (msgs.length === 0) {
console.log(`No messages for ${opts.agent}.`);
return;
}
for (const m of msgs) {
const flag = m.status === 'unread' ? '●' : ' ';
console.log(`${flag} ${m.id} ${m.from}${m.to}${m.taskId ? ` [${m.taskId}]` : ''}: ${m.text}`);
}
}