diff --git a/cameleer-server-app/src/main/java/com/cameleer/server/app/controller/AgentEventsController.java b/cameleer-server-app/src/main/java/com/cameleer/server/app/controller/AgentEventsController.java index 119aea41..5ea1d51b 100644 --- a/cameleer-server-app/src/main/java/com/cameleer/server/app/controller/AgentEventsController.java +++ b/cameleer-server-app/src/main/java/com/cameleer/server/app/controller/AgentEventsController.java @@ -1,7 +1,9 @@ package com.cameleer.server.app.controller; +import com.cameleer.server.app.dto.AgentEventPageResponse; import com.cameleer.server.app.dto.AgentEventResponse; import com.cameleer.server.app.web.EnvPath; +import com.cameleer.server.core.agent.AgentEventPage; import com.cameleer.server.core.agent.AgentEventService; import com.cameleer.server.core.runtime.Environment; import io.swagger.v3.oas.annotations.Operation; @@ -14,7 +16,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.time.Instant; -import java.util.List; @RestController @RequestMapping("/api/v1/environments/{envSlug}/agents/events") @@ -29,24 +30,25 @@ public class AgentEventsController { @GetMapping @Operation(summary = "Query agent events in this environment", - description = "Returns agent lifecycle events, optionally filtered by app and/or agent ID") - @ApiResponse(responseCode = "200", description = "Events returned") - public ResponseEntity> getEvents( + description = "Cursor-paginated. Returns newest first. Pass nextCursor back as ?cursor= for the next page.") + @ApiResponse(responseCode = "200", description = "Event page returned") + public ResponseEntity getEvents( @EnvPath Environment env, @RequestParam(required = false) String appId, @RequestParam(required = false) String agentId, @RequestParam(required = false) String from, @RequestParam(required = false) String to, + @RequestParam(required = false) String cursor, @RequestParam(defaultValue = "50") int limit) { Instant fromInstant = from != null ? Instant.parse(from) : null; Instant toInstant = to != null ? Instant.parse(to) : null; - var events = agentEventService.queryEvents(appId, agentId, env.slug(), fromInstant, toInstant, limit) - .stream() - .map(AgentEventResponse::from) - .toList(); + AgentEventPage page = agentEventService.queryEventPage( + appId, agentId, env.slug(), fromInstant, toInstant, cursor, limit); - return ResponseEntity.ok(events); + var data = page.data().stream().map(AgentEventResponse::from).toList(); + + return ResponseEntity.ok(new AgentEventPageResponse(data, page.nextCursor(), page.hasMore())); } } diff --git a/cameleer-server-app/src/main/java/com/cameleer/server/app/dto/AgentEventPageResponse.java b/cameleer-server-app/src/main/java/com/cameleer/server/app/dto/AgentEventPageResponse.java new file mode 100644 index 00000000..177b06b8 --- /dev/null +++ b/cameleer-server-app/src/main/java/com/cameleer/server/app/dto/AgentEventPageResponse.java @@ -0,0 +1,12 @@ +package com.cameleer.server.app.dto; + +import io.swagger.v3.oas.annotations.media.Schema; + +import java.util.List; + +@Schema(description = "Cursor-paginated agent event list") +public record AgentEventPageResponse( + List data, + String nextCursor, + boolean hasMore +) {}