feat(FN-989): add inter-agent messaging system with mailbox UI and CLI commands

- Add Message types (Message, MessageThread, MessageRecipient) and exports to @fusion/core
- Create MessageStore with full CRUD: send, read, delete, inbox, threads, and search
- Add messages table migration (schema v12) with SQLite full-text search support
- Add REST API routes for messaging (CRUD, search, broadcast, unread count)
- Add frontend API client functions for all messaging endpoints
- Build MailboxModal and MessageComposer dashboard components with header integration
- Add CLI message commands (inbox, send, read, delete) with rich output formatting
- Add comprehensive test coverage for MessageStore, CLI commands, and UI components
- Update documentation (CLI STANDALONE.md, dashboard README) with messaging usage
This commit is contained in:
gsxdsm
2026-04-07 11:21:59 -07:00
parent 7af1317f34
commit 43b1f6e772
20 changed files with 3972 additions and 17 deletions

View File

@@ -1,5 +1,5 @@
import { useState, useEffect, useRef, useCallback, useMemo } from "react";
import { Settings, Pause, Play, Square, LayoutGrid, List, Terminal, Lightbulb, Search, X, Activity, MoreHorizontal, Clock, Folder, History, GitBranch, Workflow, Bot, ChevronLeft, Target, ChevronRight, FileCode, Loader2, Grid3X3 } from "lucide-react";
import { Settings, Pause, Play, Square, LayoutGrid, List, Terminal, Lightbulb, Search, X, Activity, MoreHorizontal, Clock, Folder, History, GitBranch, Workflow, Bot, ChevronLeft, Target, ChevronRight, FileCode, Loader2, Grid3X3, Mail } from "lucide-react";
import type { ProjectInfo } from "../api";
import { fetchScripts } from "../api";
import { ProjectSelector } from "./ProjectSelector";
@@ -30,6 +30,10 @@ export interface HeaderProps {
activePlanningSessionCount?: number;
onOpenUsage?: () => void;
onOpenActivityLog?: () => void;
/** Opens the mailbox modal */
onOpenMailbox?: () => void;
/** Unread message count for badge display */
mailboxUnreadCount?: number;
onOpenSchedules?: () => void;
onOpenGitManager?: () => void;
onOpenWorkflowSteps?: () => void;
@@ -103,6 +107,8 @@ export function Header({
activePlanningSessionCount = 0,
onOpenUsage,
onOpenActivityLog,
onOpenMailbox,
mailboxUnreadCount = 0,
onOpenSchedules,
onOpenGitManager,
onOpenWorkflowSteps,
@@ -417,6 +423,23 @@ export function Header({
</button>
)}
{/* Mailbox button - desktop only */}
{!isCompact && onOpenMailbox && (
<button
className={`btn-icon${mailboxUnreadCount > 0 ? " btn-icon--has-indicator" : ""}`}
onClick={onOpenMailbox}
title={`Mailbox${mailboxUnreadCount > 0 ? ` (${mailboxUnreadCount} unread)` : ""}`}
data-testid="header-mailbox-btn"
>
<Mail size={16} />
{mailboxUnreadCount > 0 && (
<span className="btn-icon-indicator" data-testid="header-mailbox-badge">
{mailboxUnreadCount > 9 ? "9+" : mailboxUnreadCount}
</span>
)}
</button>
)}
{/* Desktop actions */}
{!isCompact && (
<button className="btn-icon" onClick={onOpenGitHubImport} title="Import from GitHub">
@@ -736,6 +759,18 @@ export function Header({
<span>View Activity Log</span>
</button>
)}
{/* Mailbox - in overflow on mobile */}
{onOpenMailbox && (
<button
className="mobile-overflow-item"
onClick={() => handleOverflowAction(onOpenMailbox)}
role="menuitem"
data-testid="overflow-mailbox-btn"
>
<Mail size={16} />
<span>Mailbox{mailboxUnreadCount > 0 ? ` (${mailboxUnreadCount})` : ""}</span>
</button>
)}
{/* Usage - in overflow on mobile */}
{onOpenUsage && (
<button