feat(FN-1618): merge fusion/fn-1618
This commit is contained in:
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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`);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user