feat(FN-3321): add agent self-improvement service and heartbeat evaluation
This merge delivers agent self-improvement (FN-3321) — adding evaluation identity tools, wiring evaluation into the heartbeat loop, implementing a self-improvement service, and providing test coverage. It also expands the dashboard guide view with regression tests, adds org chart full-view mode with Fusion-Task-Id: FN-3321
This commit is contained in:
98
packages/engine/src/agent-self-improve.ts
Normal file
98
packages/engine/src/agent-self-improve.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import type { AgentHeartbeatConfig, AgentStore, ReflectionStore } from "@fusion/core";
|
||||
import { createLogger } from "./logger.js";
|
||||
|
||||
const selfImproveLog = createLogger("agent-self-improve");
|
||||
|
||||
const DEFAULT_SELF_IMPROVE_INTERVAL_MS = 14_400_000;
|
||||
const MIN_SELF_IMPROVE_INTERVAL_MS = 3_600_000;
|
||||
|
||||
export interface AgentSelfImproveServiceOptions {
|
||||
agentStore: AgentStore;
|
||||
reflectionStore: ReflectionStore;
|
||||
rootDir: string;
|
||||
}
|
||||
|
||||
export class AgentSelfImproveService {
|
||||
private readonly agentStore: AgentStore;
|
||||
private readonly reflectionStore: ReflectionStore;
|
||||
private readonly rootDir: string;
|
||||
|
||||
constructor(options: AgentSelfImproveServiceOptions) {
|
||||
this.agentStore = options.agentStore;
|
||||
this.reflectionStore = options.reflectionStore;
|
||||
this.rootDir = options.rootDir;
|
||||
}
|
||||
|
||||
async shouldRunSelfImprove(agentId: string): Promise<boolean> {
|
||||
void this.reflectionStore;
|
||||
void this.rootDir;
|
||||
|
||||
const agent = await this.agentStore.getAgent(agentId);
|
||||
if (!agent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const runtimeConfig = (agent.runtimeConfig ?? {}) as AgentHeartbeatConfig;
|
||||
if (runtimeConfig.selfImproveEnabled === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const intervalMs = typeof runtimeConfig.selfImproveIntervalMs === "number" && Number.isFinite(runtimeConfig.selfImproveIntervalMs)
|
||||
? Math.max(MIN_SELF_IMPROVE_INTERVAL_MS, runtimeConfig.selfImproveIntervalMs)
|
||||
: DEFAULT_SELF_IMPROVE_INTERVAL_MS;
|
||||
|
||||
const lastSelfImproveAt = runtimeConfig.lastSelfImproveAt;
|
||||
if (!lastSelfImproveAt) {
|
||||
const summary = await this.agentStore.getRatingSummary(agentId);
|
||||
return summary.totalRatings > 0;
|
||||
}
|
||||
|
||||
const lastMs = Date.parse(lastSelfImproveAt);
|
||||
if (!Number.isFinite(lastMs)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Date.now() - lastMs > intervalMs;
|
||||
}
|
||||
|
||||
async getSelfImprovePrompt(agentId: string): Promise<string> {
|
||||
const agent = await this.agentStore.getAgent(agentId);
|
||||
const runtimeConfig = (agent?.runtimeConfig ?? {}) as AgentHeartbeatConfig;
|
||||
const lastSelfImproveAt = runtimeConfig.lastSelfImproveAt ?? "never";
|
||||
|
||||
return `## Self-Improvement Phase
|
||||
|
||||
It is time for your periodic self-improvement review. Your last self-improvement was at ${lastSelfImproveAt}.
|
||||
|
||||
Follow this process:
|
||||
1. Call fn_read_evaluations to review your ratings, reflections, and feedback.
|
||||
2. Analyze the data for actionable patterns:
|
||||
- Declining scores or negative trends
|
||||
- Recurring error categories
|
||||
- Repeated negative feedback themes
|
||||
- Suggestions from reflections you haven't addressed
|
||||
3. Based on your analysis, call fn_update_identity to update your instructions, soul, or memory:
|
||||
- Update instructionsText to incorporate new operating procedures or avoid repeated mistakes
|
||||
- Update soul to refine your personality/behavior based on feedback
|
||||
- Update memory to record self-improvement observations and commitments
|
||||
4. Be conservative: only make changes you're confident will improve performance based on concrete evidence.
|
||||
5. Document your self-improvement decisions concisely.`;
|
||||
}
|
||||
|
||||
async recordSelfImprove(agentId: string): Promise<void> {
|
||||
const agent = await this.agentStore.getAgent(agentId);
|
||||
if (!agent) {
|
||||
return;
|
||||
}
|
||||
|
||||
const existingRuntime = (agent.runtimeConfig ?? {}) as Record<string, unknown>;
|
||||
await this.agentStore.updateAgent(agentId, {
|
||||
runtimeConfig: {
|
||||
...existingRuntime,
|
||||
lastSelfImproveAt: new Date().toISOString(),
|
||||
},
|
||||
});
|
||||
|
||||
selfImproveLog.log(`Recorded self-improve checkpoint for ${agentId}`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user