feat(FN-1444): complete Step 1 — add soul to POST/PATCH agent routes with validation
This commit is contained in:
@@ -10286,6 +10286,7 @@ describe("Agent create/update routes", () => {
|
|||||||
permissions: { read: true },
|
permissions: { read: true },
|
||||||
instructionsPath: "docs/reviewer.md",
|
instructionsPath: "docs/reviewer.md",
|
||||||
instructionsText: "Check test quality.",
|
instructionsText: "Check test quality.",
|
||||||
|
soul: "Analytical and thorough.",
|
||||||
}),
|
}),
|
||||||
{ "Content-Type": "application/json" },
|
{ "Content-Type": "application/json" },
|
||||||
);
|
);
|
||||||
@@ -10302,6 +10303,7 @@ describe("Agent create/update routes", () => {
|
|||||||
permissions: { read: true },
|
permissions: { read: true },
|
||||||
instructionsPath: "docs/reviewer.md",
|
instructionsPath: "docs/reviewer.md",
|
||||||
instructionsText: "Check test quality.",
|
instructionsText: "Check test quality.",
|
||||||
|
soul: "Analytical and thorough.",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -10324,6 +10326,7 @@ describe("Agent create/update routes", () => {
|
|||||||
totalOutputTokens: 21,
|
totalOutputTokens: 21,
|
||||||
instructionsPath: "agents/infra.md",
|
instructionsPath: "agents/infra.md",
|
||||||
instructionsText: "Focus on reliability.",
|
instructionsText: "Focus on reliability.",
|
||||||
|
soul: "Pragmatic and efficient.",
|
||||||
}),
|
}),
|
||||||
{ "Content-Type": "application/json" },
|
{ "Content-Type": "application/json" },
|
||||||
);
|
);
|
||||||
@@ -10344,9 +10347,44 @@ describe("Agent create/update routes", () => {
|
|||||||
totalOutputTokens: 21,
|
totalOutputTokens: 21,
|
||||||
instructionsPath: "agents/infra.md",
|
instructionsPath: "agents/infra.md",
|
||||||
instructionsText: "Focus on reliability.",
|
instructionsText: "Focus on reliability.",
|
||||||
|
soul: "Pragmatic and efficient.",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("POST /api/agents returns 400 when soul exceeds 10,000 characters", async () => {
|
||||||
|
const longSoul = "x".repeat(10001);
|
||||||
|
const res = await REQUEST(
|
||||||
|
buildAgentApp(),
|
||||||
|
"POST",
|
||||||
|
"/api/agents",
|
||||||
|
JSON.stringify({
|
||||||
|
name: "Soul Test Agent",
|
||||||
|
role: "executor",
|
||||||
|
soul: longSoul,
|
||||||
|
}),
|
||||||
|
{ "Content-Type": "application/json" },
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
expect(res.body.error).toContain("soul must be at most 10,000 characters");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("PATCH /api/agents/:id returns 400 when soul exceeds 10,000 characters", async () => {
|
||||||
|
const longSoul = "x".repeat(10001);
|
||||||
|
const res = await REQUEST(
|
||||||
|
buildAgentApp(),
|
||||||
|
"PATCH",
|
||||||
|
`/api/agents/${agentId}`,
|
||||||
|
JSON.stringify({
|
||||||
|
soul: longSoul,
|
||||||
|
}),
|
||||||
|
{ "Content-Type": "application/json" },
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
expect(res.body.error).toContain("soul must be at most 10,000 characters");
|
||||||
|
});
|
||||||
|
|
||||||
it("POST /api/agents/:id/state returns 400 for invalid state transitions", async () => {
|
it("POST /api/agents/:id/state returns 400 for invalid state transitions", async () => {
|
||||||
const res = await REQUEST(
|
const res = await REQUEST(
|
||||||
buildAgentApp(),
|
buildAgentApp(),
|
||||||
|
|||||||
@@ -8998,6 +8998,7 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
|
|||||||
permissions,
|
permissions,
|
||||||
instructionsPath,
|
instructionsPath,
|
||||||
instructionsText,
|
instructionsText,
|
||||||
|
soul,
|
||||||
} = req.body ?? {};
|
} = req.body ?? {};
|
||||||
|
|
||||||
if (!name || typeof name !== "string") {
|
if (!name || typeof name !== "string") {
|
||||||
@@ -9027,6 +9028,12 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
|
|||||||
if (!validateAgentInstructionsPayload(res, instructionsPath, instructionsText)) {
|
if (!validateAgentInstructionsPayload(res, instructionsPath, instructionsText)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (soul !== undefined && soul !== null && typeof soul !== "string") {
|
||||||
|
throw badRequest("soul must be a string");
|
||||||
|
}
|
||||||
|
if (typeof soul === "string" && soul.length > 10000) {
|
||||||
|
throw badRequest("soul must be at most 10,000 characters");
|
||||||
|
}
|
||||||
|
|
||||||
const scopedStore = await getScopedStore(req);
|
const scopedStore = await getScopedStore(req);
|
||||||
const { AgentStore } = await import("@fusion/core");
|
const { AgentStore } = await import("@fusion/core");
|
||||||
@@ -9044,6 +9051,7 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
|
|||||||
permissions,
|
permissions,
|
||||||
instructionsPath: instructionsPath ?? undefined,
|
instructionsPath: instructionsPath ?? undefined,
|
||||||
instructionsText: instructionsText ?? undefined,
|
instructionsText: instructionsText ?? undefined,
|
||||||
|
soul: soul ?? undefined,
|
||||||
});
|
});
|
||||||
res.status(201).json(agent);
|
res.status(201).json(agent);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
@@ -9473,6 +9481,16 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
|
|||||||
updates.instructionsText = body.instructionsText ?? undefined;
|
updates.instructionsText = body.instructionsText ?? undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ("soul" in body) {
|
||||||
|
if (body.soul !== null && typeof body.soul !== "string") {
|
||||||
|
throw badRequest("soul must be a string");
|
||||||
|
}
|
||||||
|
if (typeof body.soul === "string" && body.soul.length > 10000) {
|
||||||
|
throw badRequest("soul must be at most 10,000 characters");
|
||||||
|
}
|
||||||
|
updates.soul = body.soul ?? undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const scopedStore = await getScopedStore(req);
|
const scopedStore = await getScopedStore(req);
|
||||||
const { AgentStore } = await import("@fusion/core");
|
const { AgentStore } = await import("@fusion/core");
|
||||||
const agentStore = new AgentStore({ rootDir: scopedStore.getFusionDir() });
|
const agentStore = new AgentStore({ rootDir: scopedStore.getFusionDir() });
|
||||||
|
|||||||
Reference in New Issue
Block a user