fix(heartbeat): per-agent HEARTBEAT.md and phase-aligned scheduler
Each agent now gets its own .fusion/agents/<id>/HEARTBEAT.md procedure
file instead of sharing a single project-wide file. A one-shot
migration in AgentStore.init() re-points existing agents off the legacy
shared path and copies the legacy file's contents into each agent's
new per-agent location so operator edits are preserved.
The HeartbeatTriggerScheduler now phase-aligns the first tick to
lastHeartbeatAt + intervalMs so a process restart resumes each agent's
existing schedule rather than waiting up to a full interval before
firing again. Overdue ticks fire promptly within a small jitter window
to avoid a thundering herd at boot.
Also fixes three pre-existing QuickChatFAB test failures introduced by
739e899b5: auto-select default model now switches to model mode whether
or not agents are present, the model tag only renders in model mode,
and one test scopes its option lookup to role="option" to disambiguate
the in-header tag from the dropdown entry.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -563,11 +563,15 @@ export class InProcessRuntime
|
||||
for (const agent of agents) {
|
||||
if (!isTimerManagedAgent(agent)) continue;
|
||||
const rc = agent.runtimeConfig;
|
||||
this.triggerScheduler.registerAgent(agent.id, {
|
||||
enabled: rc?.enabled as boolean | undefined,
|
||||
heartbeatIntervalMs: rc?.heartbeatIntervalMs as number | undefined,
|
||||
maxConcurrentRuns: rc?.maxConcurrentRuns as number | undefined,
|
||||
});
|
||||
this.triggerScheduler.registerAgent(
|
||||
agent.id,
|
||||
{
|
||||
enabled: rc?.enabled as boolean | undefined,
|
||||
heartbeatIntervalMs: rc?.heartbeatIntervalMs as number | undefined,
|
||||
maxConcurrentRuns: rc?.maxConcurrentRuns as number | undefined,
|
||||
},
|
||||
{ lastHeartbeatAt: agent.lastHeartbeatAt },
|
||||
);
|
||||
registeredCount++;
|
||||
}
|
||||
if (agents.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user