feat(FN-2673): stream automation schedule events over SSE

- Wire AutomationStore into dashboard SSE setup for both default and project-scoped /api/events streams
- Emit schedule:created, schedule:updated, schedule:deleted, and schedule:run events to connected SSE clients
- Add SSE coverage for automation event subscription, relay payloads, cleanup on disconnect, and graceful behavior without automation store
- Add server events integration coverage for automationStore wiring and document automation schedule events in architecture docs
This commit is contained in:
Fusion
2026-04-27 03:21:59 -07:00
committed by gsxdsm
parent f928f0a92e
commit ae988d0ef7
5 changed files with 185 additions and 2 deletions

View File

@@ -617,6 +617,7 @@ export function createServer(store: TaskStore, options?: ServerOptions): ReturnT
defaultAgentStore,
defaultMessageStore,
chatStore,
options?.automationStore,
)(req, res);
return;
}
@@ -628,12 +629,14 @@ export function createServer(store: TaskStore, options?: ServerOptions): ReturnT
let scopedStore: TaskStore;
let agentStore;
let messageStore: MessageStore | undefined;
let automationStore: AutomationStore | undefined;
if (engineManager) {
const engine = engineManager.getEngine(projectId);
scopedStore = engine?.getTaskStore() ?? await getOrCreateProjectStore(projectId);
// Use the engine's stores if available
agentStore = engine?.getAgentStore();
messageStore = engine?.getMessageStore();
automationStore = engine?.getAutomationStore();
} else {
scopedStore = await getOrCreateProjectStore(projectId);
}
@@ -643,6 +646,9 @@ export function createServer(store: TaskStore, options?: ServerOptions): ReturnT
agentStore = new AgentStoreClass({ rootDir: scopedStore.getFusionDir() });
await agentStore.init();
}
if (!automationStore) {
automationStore = options?.automationStore;
}
createSSE(
scopedStore,
scopedStore.getMissionStore(),
@@ -654,6 +660,7 @@ export function createServer(store: TaskStore, options?: ServerOptions): ReturnT
agentStore,
messageStore,
chatStore,
automationStore,
)(req, res);
} catch (err: unknown) {
sendErrorResponse(res, 500, err instanceof Error ? err.message : "Failed to open project event stream");