feat(FN-1449): complete agent UI field parity with Agent Companies
This change aligns agent editing surfaces across dashboard UI, API payloads, and import/template flows so every first-class editable agent field is round-trippable. Backend changes: - Add memory and bundleConfig fields to POST/PATCH /api/agents routes - Fix agent-companies-parser to use first-class fields (title, icon, role, reportsTo, instructionsText) instead of metadata fallbacks - Update import dry-run preview to show more manifest fields UI changes: - Enable identity field editing (name, title, icon, role, reportsTo) in AgentDetailView ConfigTab - Add instruction bundle configuration (mode, entry file, files, external path) to ConfigTab - Add memory field to NewAgentDialog - Fix AI generation mapping to preserve systemPrompt as instructionsText - Update AgentImportModal preview to show icon, reportsTo, and instructions Test fixes: - Update parser tests for new first-class field behavior - Add MissionExecutionLoop mock for serve tests Documentation: - Add agent field parity matrix to docs/agents.md - Create changeset for @gsxdsm/fusion
This commit is contained in:
@@ -357,10 +357,9 @@ name: Zip CEO
|
||||
name: "CEO",
|
||||
role: "custom",
|
||||
title: "Chief Executive Officer",
|
||||
instructionsText: "Lead strategy",
|
||||
metadata: {
|
||||
instructions: "Lead strategy",
|
||||
skills: ["review"],
|
||||
reportsTo: null,
|
||||
sources: [{ kind: "git", repo: "acme/repo" }],
|
||||
},
|
||||
});
|
||||
@@ -391,6 +390,45 @@ name: Zip CEO
|
||||
const input = agentManifestToAgentCreateInput({ name: "Generalist" });
|
||||
expect(input.role).toBe("custom");
|
||||
});
|
||||
|
||||
it("maps manifest icon to first-class field", () => {
|
||||
const input = agentManifestToAgentCreateInput({
|
||||
name: "Bot",
|
||||
icon: "🤖",
|
||||
role: "executor",
|
||||
});
|
||||
|
||||
expect(input).toEqual({
|
||||
name: "Bot",
|
||||
role: "executor",
|
||||
icon: "🤖",
|
||||
});
|
||||
});
|
||||
|
||||
it("maps manifest reportsTo to first-class field", () => {
|
||||
const input = agentManifestToAgentCreateInput({
|
||||
name: "Worker",
|
||||
reportsTo: "manager-001",
|
||||
});
|
||||
|
||||
expect(input).toEqual({
|
||||
name: "Worker",
|
||||
role: "custom",
|
||||
reportsTo: "manager-001",
|
||||
});
|
||||
});
|
||||
|
||||
it("maps manifest role to first-class field", () => {
|
||||
const input = agentManifestToAgentCreateInput({
|
||||
name: "Reviewer",
|
||||
role: "reviewer",
|
||||
});
|
||||
|
||||
expect(input).toEqual({
|
||||
name: "Reviewer",
|
||||
role: "reviewer",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("mapRoleToCapability", () => {
|
||||
|
||||
@@ -284,25 +284,29 @@ export async function parseCompanyArchive(archivePath: string): Promise<AgentCom
|
||||
export function agentManifestToAgentCreateInput(agent: AgentManifest): AgentCreateInput {
|
||||
const metadata: Record<string, unknown> = {};
|
||||
|
||||
if (typeof agent.instructionBody === "string") {
|
||||
metadata.instructions = agent.instructionBody;
|
||||
}
|
||||
// Store skills and metadata sources in metadata (skills is not a first-class field)
|
||||
if (Array.isArray(agent.skills) && agent.skills.length > 0) {
|
||||
metadata.skills = agent.skills;
|
||||
}
|
||||
if (agent.reportsTo !== undefined) {
|
||||
metadata.reportsTo = agent.reportsTo;
|
||||
}
|
||||
if (Array.isArray(agent.metadata?.sources) && agent.metadata.sources.length > 0) {
|
||||
metadata.sources = agent.metadata.sources;
|
||||
}
|
||||
|
||||
return {
|
||||
name: agent.name,
|
||||
role: mapRoleToCapability("custom"),
|
||||
role: agent.role ? mapRoleToCapability(agent.role) : mapRoleToCapability("custom"),
|
||||
...(typeof agent.title === "string" && agent.title.trim().length > 0
|
||||
? { title: agent.title }
|
||||
: {}),
|
||||
...(typeof agent.icon === "string" && agent.icon.trim().length > 0
|
||||
? { icon: agent.icon.trim() }
|
||||
: {}),
|
||||
...(typeof agent.reportsTo === "string" && agent.reportsTo.trim().length > 0
|
||||
? { reportsTo: agent.reportsTo.trim() }
|
||||
: {}),
|
||||
...(typeof agent.instructionBody === "string" && agent.instructionBody.trim().length > 0
|
||||
? { instructionsText: agent.instructionBody.trim() }
|
||||
: {}),
|
||||
...(Object.keys(metadata).length > 0 ? { metadata } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user