feat(FN-1618): merge fusion/fn-1618

This commit is contained in:
gsxdsm
2026-04-14 08:14:28 -07:00
parent 6667fd93c2
commit 78190897be
2 changed files with 38 additions and 1 deletions

View File

@@ -13,6 +13,7 @@ const {
mockRecoverNoProgressNoTaskDoneFailures,
mockRunStartupRecovery,
mockExecutorCtor,
mockMessageStoreSetHook,
} = vi.hoisted(() => ({
mockSelfHealingStart: vi.fn(),
mockSelfHealingStop: vi.fn(),
@@ -20,6 +21,7 @@ const {
mockRecoverNoProgressNoTaskDoneFailures: vi.fn().mockResolvedValue(0),
mockRunStartupRecovery: vi.fn().mockResolvedValue(undefined),
mockExecutorCtor: vi.fn(),
mockMessageStoreSetHook: vi.fn(),
}));
// Mock the TaskStore class
@@ -65,6 +67,12 @@ vi.mock("@fusion/core", async () => {
self.off = vi.fn();
return self;
}),
MessageStore: vi.fn().mockImplementation(function() {
const self = {} as Record<string, unknown>;
self.init = vi.fn().mockResolvedValue(undefined);
self.setMessageToAgentHook = mockMessageStoreSetHook;
return self;
}),
};
});
@@ -564,4 +572,26 @@ describe("InProcessRuntime", () => {
expect(4).toBe(4);
});
});
describe("message store wiring", () => {
it("registers wake-on-message hook when messageStore is provided", async () => {
// Reset the mock to ensure clean state for this test
mockMessageStoreSetHook.mockClear();
await runtime.start();
// Verify that setMessageToAgentHook was called with a function
expect(mockMessageStoreSetHook).toHaveBeenCalledTimes(1);
expect(mockMessageStoreSetHook).toHaveBeenCalledWith(expect.any(Function));
});
it("creates MessageStore with correct rootDir", async () => {
// Start runtime
await runtime.start();
// The MessageStore mock was created - verify the MessageStore constructor was called
const { MessageStore } = await import("@fusion/core");
expect(MessageStore).toHaveBeenCalled();
});
});
});

View File

@@ -8,6 +8,7 @@ import type {
AgentHeartbeatRun,
PluginStore,
PluginLoader,
MessageStore,
} from "@fusion/core";
import { Scheduler } from "../scheduler.js";
import { TaskExecutor, type TaskExecutorOptions } from "../executor.js";
@@ -91,6 +92,7 @@ export class InProcessRuntime
private missionExecutionLoop?: MissionExecutionLoop;
private missionAutopilot?: MissionAutopilot;
private triageProcessor?: TriageProcessor;
private messageStore?: MessageStore;
private concurrencyChangedListener?: (state: { globalMaxConcurrent: number }) => void;
/**
@@ -339,15 +341,20 @@ export class InProcessRuntime
// 6. Initialize AgentStore and HeartbeatMonitor
try {
const { AgentStore: AgentStoreClass } = await import("@fusion/core");
const { AgentStore: AgentStoreClass, MessageStore: MessageStoreClass } = 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({ rootDir: this.taskStore.getFusionDir() });
await this.messageStore.init();
this.heartbeatMonitor = new HeartbeatMonitor({
store: this.agentStore,
agentStore: this.agentStore, // enables per-agent config resolution
taskStore: this.taskStore,
rootDir: this.config.workingDirectory,
messageStore: this.messageStore,
onMissed: (agentId) => {
runtimeLog.warn(`Agent ${agentId} missed heartbeat`);
},