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

This commit is contained in:
gsxdsm
2026-04-18 22:52:33 -07:00
parent d642af311d
commit ecafaf496c
3 changed files with 50 additions and 6 deletions

View File

@@ -3118,6 +3118,54 @@ describe("HeartbeatMonitor", () => {
const responseText = result.content[0] && "text" in result.content[0] ? result.content[0].text : "";
expect(responseText).toContain("Created FN-100");
expect(result.details).toEqual({ taskId: "FN-100" });
});
it("task_create tracking uses details.taskId instead of regex", async () => {
const store = createMockStore();
const prefixedTaskStore = createMockTaskStoreForTools({
createTask: vi.fn().mockResolvedValue({
id: "ABC-999",
description: "Follow-up task",
dependencies: [],
column: "triage",
}),
});
const monitor = new HeartbeatMonitor({ store, taskStore: prefixedTaskStore, rootDir: "/tmp" });
const tools = monitor.createHeartbeatTools("agent-001", prefixedTaskStore, "FN-001");
await tools[0]!.execute("call-1", { description: "Follow-up task" }, undefined as any, undefined as any, undefined as any);
expect(prefixedTaskStore.logEntry).toHaveBeenCalledWith(
"ABC-999",
"Created by agent agent-001 during heartbeat run",
undefined,
undefined,
);
});
it("task_create tracking handles missing details gracefully", async () => {
const store = createMockStore();
const missingDetailsTaskStore = createMockTaskStoreForTools({
createTask: vi.fn().mockResolvedValue({
id: undefined,
description: "Follow-up task",
dependencies: [],
column: "triage",
}),
});
const monitor = new HeartbeatMonitor({ store, taskStore: missingDetailsTaskStore, rootDir: "/tmp" });
const tools = monitor.createHeartbeatTools("agent-001", missingDetailsTaskStore, "FN-001");
const result = await tools[0]!.execute("call-1", { description: "Follow-up task" }, undefined as any, undefined as any, undefined as any);
expect(result).toBeDefined();
expect(missingDetailsTaskStore.logEntry).toHaveBeenCalledWith(
"unknown",
"Created by agent agent-001 during heartbeat run",
undefined,
undefined,
);
});
it("logs agent link on created task", async () => {

View File

@@ -1421,11 +1421,7 @@ export class HeartbeatMonitor {
execute: async (id: string, params: Static<typeof taskCreateParams>, signal, onUpdate, ctx) => {
const result = await baseCreateTool.execute(id, params, signal, onUpdate, ctx);
// Extract created task ID from the response text ("Created FN-XXX: ...")
const firstContent = result.content[0];
const responseText = firstContent && "text" in firstContent ? firstContent.text : "";
const taskIdMatch = responseText.match(/Created (FN-\d+|KB-\d+|\w+-\d+):/);
const createdTaskId = taskIdMatch?.[1] ?? "unknown";
const createdTaskId = (result.details as { taskId?: string })?.taskId ?? "unknown";
// Log agent link on the created task with run context for correlation
try {

View File

@@ -443,7 +443,7 @@ export function createTaskCreateTool(store: TaskStore): ToolDefinition {
type: "text" as const,
text: `Created ${task.id}: ${params.description}${deps}`,
}],
details: {},
details: { taskId: task.id },
};
},
};