- Implemented `ListResults` and `CountResults` methods in `ExecutionStore` to retrieve and count completed executions with delivery content, supporting filtering by member ID, team ID, trigger type, and keyword. - Developed `ListActivities` method to derive activities from execution status changes, allowing retrieval of recent activities for a team. - Created corresponding unit tests in `execution_test.go` to validate the functionality of results and activities listing, ensuring accurate filtering and pagination. - Updated OpenAPI routes and types to include new endpoints for listing results and activities, enhancing the API's capabilities for managing execution data.
106 lines
2.8 KiB
Go
106 lines
2.8 KiB
Go
package robot
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/yaoapp/kun/log"
|
|
robotapi "github.com/yaoapp/yao/agent/robot/api"
|
|
robottypes "github.com/yaoapp/yao/agent/robot/types"
|
|
"github.com/yaoapp/yao/openapi/oauth/authorized"
|
|
"github.com/yaoapp/yao/openapi/response"
|
|
)
|
|
|
|
// ==================== Activities Handler ====================
|
|
// Activities are derived from execution status changes across all robots in a team
|
|
|
|
// ListActivities lists recent activities for the user's team
|
|
// GET /v1/agent/robots/activities
|
|
func ListActivities(c *gin.Context) {
|
|
// Get authorized information
|
|
authInfo := authorized.GetInfo(c)
|
|
|
|
// Get team_id from auth - activities are team-scoped
|
|
teamID := ""
|
|
if authInfo != nil {
|
|
teamID = authInfo.TeamID
|
|
// If no team_id, fall back to user_id for personal users
|
|
if teamID == "" {
|
|
teamID = authInfo.UserID
|
|
}
|
|
}
|
|
|
|
if teamID == "" {
|
|
errorResp := &response.ErrorResponse{
|
|
Code: response.ErrAccessDenied.Code,
|
|
ErrorDescription: "Unable to determine team scope",
|
|
}
|
|
response.RespondWithError(c, response.StatusForbidden, errorResp)
|
|
return
|
|
}
|
|
|
|
// Parse query parameters
|
|
var filter ActivityFilter
|
|
if err := c.ShouldBindQuery(&filter); err != nil {
|
|
errorResp := &response.ErrorResponse{
|
|
Code: response.ErrInvalidRequest.Code,
|
|
ErrorDescription: "Invalid query parameters: " + err.Error(),
|
|
}
|
|
response.RespondWithError(c, response.StatusBadRequest, errorResp)
|
|
return
|
|
}
|
|
|
|
// Apply defaults
|
|
if filter.Limit <= 0 {
|
|
filter.Limit = 20
|
|
}
|
|
if filter.Limit > 100 {
|
|
filter.Limit = 100
|
|
}
|
|
|
|
// Create robot context
|
|
ctx := &robottypes.Context{}
|
|
|
|
// Build API query
|
|
query := &robotapi.ActivityQuery{
|
|
TeamID: teamID,
|
|
Limit: filter.Limit,
|
|
}
|
|
|
|
// Parse 'since' if provided
|
|
if filter.Since != "" {
|
|
since, err := time.Parse(time.RFC3339, filter.Since)
|
|
if err != nil {
|
|
errorResp := &response.ErrorResponse{
|
|
Code: response.ErrInvalidRequest.Code,
|
|
ErrorDescription: "Invalid 'since' parameter: must be RFC3339 format",
|
|
}
|
|
response.RespondWithError(c, response.StatusBadRequest, errorResp)
|
|
return
|
|
}
|
|
query.Since = &since
|
|
}
|
|
|
|
// Call API layer
|
|
result, err := robotapi.ListActivities(ctx, query)
|
|
if err != nil {
|
|
log.Error("Failed to list activities for team %s: %v", teamID, err)
|
|
errorResp := &response.ErrorResponse{
|
|
Code: response.ErrServerError.Code,
|
|
ErrorDescription: "Failed to list activities: " + err.Error(),
|
|
}
|
|
response.RespondWithError(c, response.StatusInternalServerError, errorResp)
|
|
return
|
|
}
|
|
|
|
// Convert to response
|
|
data := make([]*ActivityResponse, 0, len(result.Data))
|
|
for _, item := range result.Data {
|
|
data = append(data, NewActivityResponse(item))
|
|
}
|
|
|
|
resp := &ActivityListResponse{
|
|
Data: data,
|
|
}
|
|
response.RespondWithSuccess(c, response.StatusOK, resp)
|
|
}
|