feat(FN-3777): add create_agent and delete_agent tools
Adds agent creation and deletion tools to the pi extension, with engine-side implementation in `agent-tools.ts`, core store integration for agent lifecycle management, and corresponding tests and documentation updates across the workspace. Fusion-Task-Id: FN-3777
This commit is contained in:
@@ -1247,6 +1247,24 @@ describe("AgentStore", () => {
|
||||
expect(handler).toHaveBeenCalledOnce();
|
||||
expect(handler).toHaveBeenCalledWith(created.id);
|
||||
});
|
||||
|
||||
it("blocks delete when checked-out assigned task exists unless force=true", async () => {
|
||||
const taskStore = new TaskStore(rootDir, join(rootDir, ".fusion-global-settings"));
|
||||
await taskStore.init();
|
||||
const linkedStore = new AgentStore({ rootDir, inMemoryDb: true, taskStore });
|
||||
await linkedStore.init();
|
||||
|
||||
const created = await linkedStore.createAgent({ name: "Checked Out", role: "executor" });
|
||||
const task = await taskStore.createTask({ title: "T", description: "D", column: "todo", assignedAgentId: created.id });
|
||||
await taskStore.updateTask(task.id, { checkedOutBy: created.id });
|
||||
|
||||
await expect(linkedStore.deleteAgent(created.id)).rejects.toThrow("holds checkout");
|
||||
await linkedStore.deleteAgent(created.id, { force: true });
|
||||
expect(await taskStore.getTask(task.id)).toEqual(expect.objectContaining({ assignedAgentId: undefined, checkedOutBy: undefined }));
|
||||
|
||||
linkedStore.close();
|
||||
taskStore.close();
|
||||
});
|
||||
});
|
||||
|
||||
// ── listAgents ────────────────────────────────────────────────────
|
||||
|
||||
@@ -1627,13 +1627,27 @@ export class AgentStore extends EventEmitter {
|
||||
* @param agentId - The agent ID
|
||||
* @throws Error if agent not found
|
||||
*/
|
||||
async deleteAgent(agentId: string): Promise<void> {
|
||||
async deleteAgent(agentId: string, options?: { force?: boolean; reassignTo?: string }): Promise<void> {
|
||||
await this.withLock(agentId, async () => {
|
||||
const agent = await this.getAgent(agentId);
|
||||
if (!agent) {
|
||||
throw new Error(`Agent ${agentId} not found`);
|
||||
}
|
||||
|
||||
if (this.taskStore && typeof (this.taskStore as { getTasksByAssignedAgent?: unknown }).getTasksByAssignedAgent === "function") {
|
||||
const assignedTasks = await this.taskStore.getTasksByAssignedAgent(agentId);
|
||||
for (const task of assignedTasks) {
|
||||
if (task.checkedOutBy === agentId && options?.force !== true) {
|
||||
throw new Error(`Agent ${agentId} holds checkout for task ${task.id}; pass force=true to delete`);
|
||||
}
|
||||
|
||||
await this.taskStore.updateTask(task.id, {
|
||||
assignedAgentId: options?.reassignTo ?? null,
|
||||
checkedOutBy: task.checkedOutBy === agentId ? null : undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.db.prepare("DELETE FROM agents WHERE id = ?").run(agentId);
|
||||
this.db.bumpLastModified();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user