feat(FN-1976): forward mailbox message events end to end

- Wire MessageStore into the in-process executor runtime and project engine
- Forward MessageStore events through dashboard SSE infrastructure for mailbox updates
- Close mailbox pipeline gaps across API routes, server wiring, and mailbox UI components
- Add regression coverage for messaging routes, SSE forwarding, and agent tool behavior
- Document the MessageStore SSE wiring pattern in .fusion/memory.md
This commit is contained in:
Fusion
2026-04-16 16:32:56 -07:00
committed by gsxdsm
parent ca2e085d76
commit 80e49b8e40
13 changed files with 624 additions and 41 deletions

View File

@@ -131,7 +131,12 @@ export class InProcessRuntime
try {
// 1. Initialize TaskStore (use external if provided, otherwise create new)
const { TaskStore, PluginStore: PluginStoreClass, PluginLoader: PluginLoaderClass } = await import("@fusion/core");
const {
TaskStore,
PluginStore: PluginStoreClass,
PluginLoader: PluginLoaderClass,
MessageStore: MessageStoreClass,
} = await import("@fusion/core");
if (this.config.externalTaskStore) {
this.taskStore = this.config.externalTaskStore;
runtimeLog.log(`TaskStore provided externally for project ${this.config.projectId}`);
@@ -141,6 +146,9 @@ export class InProcessRuntime
runtimeLog.log(`TaskStore initialized for project ${this.config.projectId}`);
}
// Initialize MessageStore early so TaskExecutor receives send_message capability.
this.messageStore = new MessageStoreClass(this.taskStore.getDatabase());
// 2. Initialize Plugin system (PluginStore + PluginLoader + PluginRunner)
this.pluginStore = new PluginStoreClass(this.taskStore.getFusionDir());
await this.pluginStore.init();
@@ -263,6 +271,7 @@ export class InProcessRuntime
usageLimitPauser: this.usageLimitPauser,
stuckTaskDetector: this.stuckTaskDetector,
pluginRunner: this.pluginRunner,
messageStore: this.messageStore,
missionStore,
onSliceComplete: (slice) => {
void this.scheduler.onSliceComplete(slice);
@@ -353,13 +362,10 @@ export class InProcessRuntime
// 6. Initialize AgentStore and HeartbeatMonitor
try {
const { AgentStore: AgentStoreClass, MessageStore: MessageStoreClass } = await import("@fusion/core");
const { AgentStore: AgentStoreClass } = await import("@fusion/core");
this.agentStore = new AgentStoreClass({ rootDir: this.taskStore.getFusionDir() });
await this.agentStore.init();
// Initialize MessageStore for wake-on-message behavior
this.messageStore = new MessageStoreClass(this.taskStore.getDatabase());
this.heartbeatMonitor = new HeartbeatMonitor({
store: this.agentStore,
agentStore: this.agentStore, // enables per-agent config resolution
@@ -718,6 +724,14 @@ export class InProcessRuntime
return this.agentStore;
}
/**
* Get the MessageStore instance (if initialized).
* Returns undefined before start() or if initialization fails.
*/
getMessageStore(): import("@fusion/core").MessageStore | undefined {
return this.messageStore;
}
/**
* Get the project's Scheduler instance.
* @throws Error if runtime has not been started