Files
kandev/apps/backend/internal/agent/controller/controller.go
T
2026-02-14 15:54:11 +00:00

166 lines
4.6 KiB
Go

// Package controller provides the business logic coordination layer for the agent module.
package controller
import (
"context"
"github.com/kandev/kandev/internal/agent/dto"
"github.com/kandev/kandev/internal/agent/lifecycle"
"github.com/kandev/kandev/internal/agent/registry"
)
// Controller coordinates agent business logic
type Controller struct {
lifecycle *lifecycle.Manager
registry *registry.Registry
}
// NewController creates a new agent controller
func NewController(lm *lifecycle.Manager, reg *registry.Registry) *Controller {
return &Controller{
lifecycle: lm,
registry: reg,
}
}
// ListAgents returns all agent instances
func (c *Controller) ListAgents(ctx context.Context, req dto.ListAgentsRequest) (dto.ListAgentsResponse, error) {
if c.lifecycle == nil {
return dto.ListAgentsResponse{}, ErrLifecycleManagerNotAvailable
}
agents := c.lifecycle.ListExecutions()
resp := dto.ListAgentsResponse{
Agents: make([]dto.AgentDTO, 0, len(agents)),
Total: len(agents),
}
for _, a := range agents {
agent := dto.FromAgentExecution(&dto.AgentExecutionData{
ID: a.ID,
TaskID: a.TaskID,
AgentProfileID: a.AgentProfileID,
ContainerID: a.ContainerID,
Status: string(a.Status),
StartedAt: a.StartedAt,
FinishedAt: a.FinishedAt,
ExitCode: a.ExitCode,
ErrorMessage: a.ErrorMessage,
})
resp.Agents = append(resp.Agents, agent)
}
return resp, nil
}
// LaunchAgent launches a new agent instance
func (c *Controller) LaunchAgent(ctx context.Context, req dto.LaunchAgentRequest) (dto.LaunchAgentResponse, error) {
if c.lifecycle == nil {
return dto.LaunchAgentResponse{}, ErrLifecycleManagerNotAvailable
}
launchReq := &lifecycle.LaunchRequest{
TaskID: req.TaskID,
AgentProfileID: req.AgentProfileID,
WorkspacePath: req.WorkspacePath,
Env: req.Env,
}
execution, err := c.lifecycle.Launch(ctx, launchReq)
if err != nil {
return dto.LaunchAgentResponse{}, err
}
return dto.LaunchAgentResponse{
Success: true,
AgentID: execution.ID,
TaskID: req.TaskID,
}, nil
}
// GetAgentStatus returns the status of a specific agent
func (c *Controller) GetAgentStatus(ctx context.Context, req dto.GetAgentStatusRequest) (dto.AgentDTO, error) {
if c.lifecycle == nil {
return dto.AgentDTO{}, ErrLifecycleManagerNotAvailable
}
agent, found := c.lifecycle.GetExecution(req.AgentID)
if !found {
return dto.AgentDTO{}, ErrAgentNotFound
}
return dto.FromAgentExecution(&dto.AgentExecutionData{
ID: agent.ID,
TaskID: agent.TaskID,
AgentProfileID: agent.AgentProfileID,
ContainerID: agent.ContainerID,
Status: string(agent.Status),
StartedAt: agent.StartedAt,
FinishedAt: agent.FinishedAt,
ExitCode: agent.ExitCode,
ErrorMessage: agent.ErrorMessage,
}), nil
}
// GetAgentLogs returns logs for a specific agent
func (c *Controller) GetAgentLogs(ctx context.Context, req dto.GetAgentLogsRequest) (dto.GetAgentLogsResponse, error) {
if c.lifecycle == nil {
return dto.GetAgentLogsResponse{}, ErrLifecycleManagerNotAvailable
}
_, found := c.lifecycle.GetExecution(req.AgentID)
if !found {
return dto.GetAgentLogsResponse{}, ErrAgentNotFound
}
// Note: Log retrieval requires Docker client access which is not available here
return dto.GetAgentLogsResponse{
AgentID: req.AgentID,
Logs: []string{},
Message: "Use HTTP API for full log retrieval",
}, nil
}
// StopAgent stops a running agent
func (c *Controller) StopAgent(ctx context.Context, req dto.StopAgentRequest) (dto.SuccessResponse, error) {
if c.lifecycle == nil {
return dto.SuccessResponse{}, ErrLifecycleManagerNotAvailable
}
if err := c.lifecycle.StopAgent(ctx, req.AgentID, false); err != nil {
return dto.SuccessResponse{}, err
}
return dto.SuccessResponse{Success: true}, nil
}
// ListAgentTypes returns all available agent types
func (c *Controller) ListAgentTypes(ctx context.Context, req dto.ListAgentTypesRequest) (dto.ListAgentTypesResponse, error) {
if c.registry == nil {
return dto.ListAgentTypesResponse{}, ErrRegistryNotAvailable
}
types := c.registry.List()
resp := dto.ListAgentTypesResponse{
Types: make([]dto.AgentTypeDTO, 0, len(types)),
Total: len(types),
}
for _, t := range types {
var image string
if rt := t.Runtime(); rt != nil {
image = rt.Image
}
resp.Types = append(resp.Types, dto.FromAgentType(&dto.AgentTypeData{
ID: t.ID(),
Name: t.Name(),
Description: t.Description(),
Image: image,
Capabilities: t.Runtime().Capabilities,
Enabled: t.Enabled(),
}))
}
return resp, nil
}