From 4f80f6596c77248dda593646af1b1267d6b862c6 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Sun, 19 Apr 2026 05:07:00 -0700 Subject: [PATCH] feat(FN-2113): merge fusion/fn-2113 --- packages/engine/src/agent-heartbeat.test.ts | 26 +++++++++---------- packages/engine/src/agent-heartbeat.ts | 10 +++---- .../src/runtimes/in-process-runtime.test.ts | 6 ++--- .../engine/src/runtimes/in-process-runtime.ts | 2 +- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/engine/src/agent-heartbeat.test.ts b/packages/engine/src/agent-heartbeat.test.ts index f057d3d2e..691689a20 100644 --- a/packages/engine/src/agent-heartbeat.test.ts +++ b/packages/engine/src/agent-heartbeat.test.ts @@ -1132,7 +1132,7 @@ describe("HeartbeatMonitor", () => { const config = monitor.getAgentHeartbeatConfig("agent-001"); expect(config.heartbeatTimeoutMs).toBe(5000); - expect(config.pollIntervalMs).toBe(30000); // default + expect(config.pollIntervalMs).toBe(3_600_000); // default expect(config.maxConcurrentRuns).toBe(1); // default }); @@ -3834,45 +3834,45 @@ describe("HeartbeatTriggerScheduler", () => { expect(scheduler.getRegisteredAgents()).not.toContain("agent-001"); }); - it("applies default 30-second interval when intervalMs is undefined", async () => { + it("applies default 3600-second interval when intervalMs is undefined", async () => { vi.useFakeTimers(); scheduler.registerAgent("agent-001", {}); expect(scheduler.getRegisteredAgents()).toContain("agent-001"); - // Verify the default 30-second interval fires + // Verify the default 3600-second interval fires expect(callback).not.toHaveBeenCalled(); - await vi.advanceTimersByTimeAsync(30_000); + await vi.advanceTimersByTimeAsync(3_600_000); expect(callback).toHaveBeenCalledOnce(); vi.useRealTimers(); }); - it("applies default 30-second interval when intervalMs is 0", async () => { + it("applies default 3600-second interval when intervalMs is 0", async () => { vi.useFakeTimers(); scheduler.registerAgent("agent-001", { heartbeatIntervalMs: 0 }); expect(scheduler.getRegisteredAgents()).toContain("agent-001"); - // Verify the default 30-second interval fires + // Verify the default 3600-second interval fires expect(callback).not.toHaveBeenCalled(); - await vi.advanceTimersByTimeAsync(30_000); + await vi.advanceTimersByTimeAsync(3_600_000); expect(callback).toHaveBeenCalledOnce(); vi.useRealTimers(); }); - it("applies default 30-second interval when heartbeatIntervalMs is not set", async () => { + it("applies default 3600-second interval when heartbeatIntervalMs is not set", async () => { vi.useFakeTimers(); scheduler.registerAgent("agent-001", { enabled: true }); expect(scheduler.getRegisteredAgents()).toContain("agent-001"); - // Should fire at exactly 30 seconds (default interval) - await vi.advanceTimersByTimeAsync(29_999); + // Should fire at exactly 3600 seconds (default interval) + await vi.advanceTimersByTimeAsync(3_599_999); expect(callback).not.toHaveBeenCalled(); - await vi.advanceTimersByTimeAsync(1); // Now at exactly 30 seconds + await vi.advanceTimersByTimeAsync(1); // Now at exactly 3600 seconds expect(callback).toHaveBeenCalledOnce(); expect(callback).toHaveBeenCalledWith("agent-001", "timer", { wakeReason: "timer", triggerDetail: "scheduled", - intervalMs: 30_000, + intervalMs: 3_600_000, }); vi.useRealTimers(); }); @@ -3882,7 +3882,7 @@ describe("HeartbeatTriggerScheduler", () => { scheduler.registerAgent("agent-001", { heartbeatIntervalMs: 15_000, enabled: true }); expect(scheduler.getRegisteredAgents()).toContain("agent-001"); - // Should fire at 15 seconds (explicit), not 30 + // Should fire at 15 seconds (explicit), not 3600 await vi.advanceTimersByTimeAsync(14_999); expect(callback).not.toHaveBeenCalled(); diff --git a/packages/engine/src/agent-heartbeat.ts b/packages/engine/src/agent-heartbeat.ts index 3d7c2159c..dd16a3317 100644 --- a/packages/engine/src/agent-heartbeat.ts +++ b/packages/engine/src/agent-heartbeat.ts @@ -46,7 +46,7 @@ export interface HeartbeatMonitorOptions { agentStore?: AgentStore; /** Optional MessageStore for wake-on-message behavior */ messageStore?: MessageStore; - /** Polling interval in milliseconds (default: 30000) */ + /** Polling interval in milliseconds (default: 3600000) */ pollIntervalMs?: number; /** Heartbeat timeout in milliseconds (default: 60000) */ heartbeatTimeoutMs?: number; @@ -247,7 +247,7 @@ export class HeartbeatMonitor { constructor(options: HeartbeatMonitorOptions) { this.store = options.store; this.configStore = options.agentStore ?? options.store; - this.pollIntervalMs = options.pollIntervalMs ?? 30000; + this.pollIntervalMs = options.pollIntervalMs ?? 3_600_000; this.heartbeatTimeoutMs = options.heartbeatTimeoutMs ?? 60000; this.maxConcurrentRuns = options.maxConcurrentRuns ?? 1; this.onMissed = options.onMissed; @@ -1641,7 +1641,7 @@ interface AgentTimer { * const scheduler = new HeartbeatTriggerScheduler(agentStore, async (agentId, source, ctx) => { * await heartbeatMonitor.startRun(agentId, { source, triggerDetail: ctx.triggerDetail, contextSnapshot: { ...ctx } }); * }); - * scheduler.registerAgent("agent-123", { heartbeatIntervalMs: 30000, enabled: true }); + * scheduler.registerAgent("agent-123", { heartbeatIntervalMs: 3600000, enabled: true }); * scheduler.start(); * ``` */ @@ -1701,8 +1701,8 @@ export class HeartbeatTriggerScheduler { return this.running; } - /** Default heartbeat interval when not explicitly configured (30 seconds) */ - private static readonly DEFAULT_HEARTBEAT_INTERVAL_MS = 30_000; + /** Default heartbeat interval when not explicitly configured (3600 seconds / 1 hour) */ + private static readonly DEFAULT_HEARTBEAT_INTERVAL_MS = 3_600_000; /** * Register an agent for timer-based heartbeat triggers. diff --git a/packages/engine/src/runtimes/in-process-runtime.test.ts b/packages/engine/src/runtimes/in-process-runtime.test.ts index 75ba11317..5a3052f38 100644 --- a/packages/engine/src/runtimes/in-process-runtime.test.ts +++ b/packages/engine/src/runtimes/in-process-runtime.test.ts @@ -789,14 +789,14 @@ describe("InProcessRuntime", () => { expect(scheduler!.getRegisteredAgents()).toContain(agent.id); }); - it("registers agent without explicit heartbeatIntervalMs using default 30s interval", async () => { + it("registers agent without explicit heartbeatIntervalMs using default 3600s interval", async () => { // Create a new agent with only enabled: true (no heartbeatIntervalMs) - // This tests that the default 30-second interval is applied + // This tests that the default 3600-second interval (1 hour) is applied const store = getAgentStore(runtime); const agent = await store.createAgent({ name: "test-agent-default-interval", role: "executor", - runtimeConfig: { enabled: true }, // No heartbeatIntervalMs - should use default 30s + runtimeConfig: { enabled: true }, // No heartbeatIntervalMs - should use default 3600s (1 hour) }); // Verify the agent was registered with the trigger scheduler diff --git a/packages/engine/src/runtimes/in-process-runtime.ts b/packages/engine/src/runtimes/in-process-runtime.ts index b1ace0889..d9d57ae2a 100644 --- a/packages/engine/src/runtimes/in-process-runtime.ts +++ b/packages/engine/src/runtimes/in-process-runtime.ts @@ -497,7 +497,7 @@ export class InProcessRuntime this.agentStore.on("agent:updated", this.agentUpdatedListener); // Register existing agents with heartbeat monitoring not explicitly disabled - // Agents without explicit heartbeat config will use the default 30-second interval + // Agents without explicit heartbeat config will use the default 3600-second interval (1 hour) try { const agents = await this.agentStore.listAgents(); let registeredCount = 0;