fix(FN-1952): bound recovery and task log growth
This commit is contained in:
@@ -487,6 +487,26 @@ describe("GET /tasks/:id", () => {
|
||||
expect(res.body.prompt).toBe("# KB-001\n\nTest task");
|
||||
});
|
||||
|
||||
it("caps task detail activity logs to keep the modal payload bounded", async () => {
|
||||
const log = Array.from({ length: 510 }, (_, index) => ({
|
||||
timestamp: `2026-01-01T00:${String(index % 60).padStart(2, "0")}:00.000Z`,
|
||||
action: `entry-${index}`,
|
||||
}));
|
||||
(store.getTask as ReturnType<typeof vi.fn>).mockResolvedValue({
|
||||
...FAKE_TASK_DETAIL,
|
||||
log,
|
||||
});
|
||||
|
||||
const res = await GET(buildApp(), "/api/tasks/KB-001");
|
||||
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.body.log).toHaveLength(500);
|
||||
expect(res.body.log[0].action).toBe("entry-10");
|
||||
expect(res.body.log[499].action).toBe("entry-509");
|
||||
expect(res.body.activityLogTotal).toBe(510);
|
||||
expect(res.body.activityLogTruncatedCount).toBe(10);
|
||||
});
|
||||
|
||||
it("returns 404 when task genuinely does not exist (ENOENT)", async () => {
|
||||
const err: NodeJS.ErrnoException = new Error("ENOENT: no such file or directory");
|
||||
err.code = "ENOENT";
|
||||
|
||||
@@ -64,6 +64,8 @@ import {
|
||||
import { rateLimit, RATE_LIMITS } from "./rate-limit.js";
|
||||
import { resolvePluginManifest } from "./plugin-routes.js";
|
||||
|
||||
const TASK_DETAIL_ACTIVITY_LOG_LIMIT = 500;
|
||||
|
||||
/**
|
||||
* Minimal interface matching pi-coding-agent's ModelRegistry API surface
|
||||
* used by the models route. Avoids a direct dependency on the pi-coding-agent package.
|
||||
@@ -642,6 +644,19 @@ function logEntryToTimelineEntry(entry: import("@fusion/core").AgentLogEntry): T
|
||||
};
|
||||
}
|
||||
|
||||
function trimTaskDetailActivityLog<T extends Task>(task: T): T {
|
||||
if (!Array.isArray(task.log) || task.log.length <= TASK_DETAIL_ACTIVITY_LOG_LIMIT) {
|
||||
return task;
|
||||
}
|
||||
|
||||
return {
|
||||
...task,
|
||||
log: task.log.slice(-TASK_DETAIL_ACTIVITY_LOG_LIMIT),
|
||||
activityLogTotal: task.log.length,
|
||||
activityLogTruncatedCount: task.log.length - TASK_DETAIL_ACTIVITY_LOG_LIMIT,
|
||||
} as T;
|
||||
}
|
||||
|
||||
// ── Git Remote Detection ──────────────────────────────────────────
|
||||
|
||||
/** Git remote info returned by the remotes endpoint */
|
||||
@@ -3784,8 +3799,10 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
|
||||
router.get("/tasks/:id", async (req, res) => {
|
||||
try {
|
||||
const { store: scopedStore } = await getProjectContext(req);
|
||||
const task = await scopedStore.getTask(req.params.id);
|
||||
res.json(task);
|
||||
const task = await scopedStore.getTask(req.params.id, {
|
||||
activityLogLimit: TASK_DETAIL_ACTIVITY_LOG_LIMIT,
|
||||
});
|
||||
res.json(trimTaskDetailActivityLog(task));
|
||||
} catch (err: unknown) {
|
||||
if (err instanceof ApiError) {
|
||||
throw err;
|
||||
|
||||
Reference in New Issue
Block a user