fix(FN-000): restore memory compaction and log pagination
This commit is contained in:
@@ -117,6 +117,7 @@ function createMockStore(overrides: Partial<TaskStore> = {}): TaskStore {
|
||||
getGlobalSettingsStore: vi.fn().mockReturnValue(createMockGlobalSettingsStore()),
|
||||
logEntry: vi.fn().mockResolvedValue(undefined),
|
||||
getAgentLogs: vi.fn().mockResolvedValue([]),
|
||||
getAgentLogCount: vi.fn().mockResolvedValue(0),
|
||||
getAgentLogsByTimeRange: vi.fn().mockResolvedValue([]),
|
||||
addSteeringComment: vi.fn(),
|
||||
addTaskComment: vi.fn(),
|
||||
@@ -3228,6 +3229,23 @@ describe("Attachment routes", () => {
|
||||
expect(store.getAgentLogs).toHaveBeenCalledWith("KB-001", undefined);
|
||||
});
|
||||
|
||||
it("GET /tasks/:id/logs — includes pagination headers on bounded initial load", async () => {
|
||||
const fakeLogs = [
|
||||
{ timestamp: "2026-01-01T00:00:00Z", taskId: "FN-001", text: "Hello", type: "text" },
|
||||
{ timestamp: "2026-01-01T00:00:01Z", taskId: "FN-001", text: "Read", type: "tool" },
|
||||
];
|
||||
(store.getAgentLogs as ReturnType<typeof vi.fn>).mockResolvedValue(fakeLogs);
|
||||
(store.getAgentLogCount as ReturnType<typeof vi.fn>).mockResolvedValue(5);
|
||||
|
||||
const res = await performGet(buildApp(), "/api/tasks/KB-001/logs?limit=2");
|
||||
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.body).toEqual(fakeLogs);
|
||||
expect(store.getAgentLogs).toHaveBeenCalledWith("KB-001", { limit: 2 });
|
||||
expect(res.headers["x-total-count"]).toBe("5");
|
||||
expect(res.headers["x-has-more"]).toBe("true");
|
||||
});
|
||||
|
||||
it("GET /tasks/:id/logs — returns empty array when no logs", async () => {
|
||||
(store.getAgentLogs as ReturnType<typeof vi.fn>).mockResolvedValue([]);
|
||||
|
||||
|
||||
@@ -3895,7 +3895,7 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
|
||||
// Get historical agent logs for a task.
|
||||
// Per-entry text and detail fields are returned in full — no truncation.
|
||||
// The 500-entry cap (MAX_LOG_ENTRIES) is a client-side whole-list limit.
|
||||
// When offset query param is provided, includes X-Total-Count and X-Has-More headers for pagination.
|
||||
// When limit is provided, includes X-Total-Count and X-Has-More headers for pagination.
|
||||
router.get("/tasks/:id/logs", async (req, res) => {
|
||||
try {
|
||||
const { store: scopedStore } = await getProjectContext(req);
|
||||
@@ -3914,13 +3914,14 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
|
||||
|
||||
const logs = await scopedStore.getAgentLogs(req.params.id, options);
|
||||
|
||||
// Include pagination headers when offset is explicitly provided (even if 0)
|
||||
// This enables the frontend to know total count and whether more entries exist
|
||||
if (offset !== undefined && Number.isFinite(offset)) {
|
||||
// Include pagination headers for bounded reads, including the initial page.
|
||||
// This enables the frontend to show Load More before an offset is present.
|
||||
if (limit !== undefined && Number.isFinite(limit)) {
|
||||
const total = await scopedStore.getAgentLogCount(req.params.id);
|
||||
res.setHeader("X-Total-Count", String(total));
|
||||
|
||||
const hasMore = total > (offset + logs.length);
|
||||
const effectiveOffset = offset !== undefined && Number.isFinite(offset) ? offset : 0;
|
||||
const hasMore = total > (effectiveOffset + logs.length);
|
||||
res.setHeader("X-Has-More", hasMore ? "true" : "false");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user