7b3e94d6dc
- Add AgentSession database entity with SQLite persistence - Implement AgentSession CRUD operations in repository layer - Update executor to use hybrid cache + database approach - Add session restoration on startup (LoadActiveSessionsFromDB) - Link comments to agent sessions via agent_session_id - Fix SQLite NULL handling for nullable task fields - Add dev database setup with seed data (make dev, make dev-db-reset) - Update Makefile with dev targets for development mode This enables agent sessions to persist across backend restarts, solving the 'execution not found' error for resumed conversations.
130 lines
3.8 KiB
Go
130 lines
3.8 KiB
Go
// Package controller provides the business logic coordination layer for the orchestrator.
|
|
package controller
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/kandev/kandev/internal/orchestrator"
|
|
"github.com/kandev/kandev/internal/orchestrator/dto"
|
|
)
|
|
|
|
// Controller coordinates orchestrator business logic
|
|
type Controller struct {
|
|
service *orchestrator.Service
|
|
}
|
|
|
|
// NewController creates a new orchestrator controller
|
|
func NewController(svc *orchestrator.Service) *Controller {
|
|
return &Controller{
|
|
service: svc,
|
|
}
|
|
}
|
|
|
|
// GetStatus returns the orchestrator status
|
|
func (c *Controller) GetStatus(ctx context.Context, req dto.GetStatusRequest) (dto.StatusResponse, error) {
|
|
status := c.service.GetStatus()
|
|
return dto.StatusResponse{
|
|
Running: status.Running,
|
|
ActiveAgents: status.ActiveAgents,
|
|
QueuedTasks: status.QueuedTasks,
|
|
MaxConcurrent: 0, // Not available from service Status; would need scheduler access
|
|
}, nil
|
|
}
|
|
|
|
// GetQueue returns the queued tasks
|
|
func (c *Controller) GetQueue(ctx context.Context, req dto.GetQueueRequest) (dto.QueueResponse, error) {
|
|
queuedTasks := c.service.GetQueuedTasks()
|
|
|
|
tasks := make([]dto.QueuedTaskDTO, 0, len(queuedTasks))
|
|
for _, qt := range queuedTasks {
|
|
tasks = append(tasks, dto.QueuedTaskDTO{
|
|
TaskID: qt.TaskID,
|
|
Priority: qt.Priority,
|
|
QueuedAt: qt.QueuedAt.Format("2006-01-02T15:04:05Z"),
|
|
})
|
|
}
|
|
|
|
return dto.QueueResponse{
|
|
Tasks: tasks,
|
|
Total: len(tasks),
|
|
}, nil
|
|
}
|
|
|
|
// TriggerTask triggers a task for execution
|
|
func (c *Controller) TriggerTask(ctx context.Context, req dto.TriggerTaskRequest) (dto.TriggerTaskResponse, error) {
|
|
// For now, just return success - the service would need task details
|
|
return dto.TriggerTaskResponse{
|
|
Success: true,
|
|
Message: "Task triggered",
|
|
TaskID: req.TaskID,
|
|
}, nil
|
|
}
|
|
|
|
// StartTask starts task execution
|
|
func (c *Controller) StartTask(ctx context.Context, req dto.StartTaskRequest) (dto.StartTaskResponse, error) {
|
|
execution, err := c.service.StartTask(ctx, req.TaskID, req.AgentType, req.Priority)
|
|
if err != nil {
|
|
return dto.StartTaskResponse{}, err
|
|
}
|
|
|
|
return dto.StartTaskResponse{
|
|
Success: true,
|
|
TaskID: execution.TaskID,
|
|
AgentInstanceID: execution.AgentInstanceID,
|
|
Status: string(execution.Status),
|
|
}, nil
|
|
}
|
|
|
|
// StopTask stops task execution
|
|
func (c *Controller) StopTask(ctx context.Context, req dto.StopTaskRequest) (dto.SuccessResponse, error) {
|
|
reason := req.Reason
|
|
if reason == "" {
|
|
reason = "stopped via API"
|
|
}
|
|
|
|
if err := c.service.StopTask(ctx, req.TaskID, reason, req.Force); err != nil {
|
|
return dto.SuccessResponse{}, err
|
|
}
|
|
|
|
return dto.SuccessResponse{Success: true}, nil
|
|
}
|
|
|
|
// PromptTask sends a prompt to a running task
|
|
func (c *Controller) PromptTask(ctx context.Context, req dto.PromptTaskRequest) (dto.PromptTaskResponse, error) {
|
|
result, err := c.service.PromptTask(ctx, req.TaskID, req.Prompt)
|
|
if err != nil {
|
|
return dto.PromptTaskResponse{}, err
|
|
}
|
|
|
|
return dto.PromptTaskResponse{
|
|
Success: true,
|
|
StopReason: result.StopReason,
|
|
}, nil
|
|
}
|
|
|
|
// CompleteTask marks a task as complete
|
|
func (c *Controller) CompleteTask(ctx context.Context, req dto.CompleteTaskRequest) (dto.CompleteTaskResponse, error) {
|
|
if err := c.service.CompleteTask(ctx, req.TaskID); err != nil {
|
|
return dto.CompleteTaskResponse{}, err
|
|
}
|
|
|
|
return dto.CompleteTaskResponse{
|
|
Success: true,
|
|
Message: "task completed",
|
|
}, nil
|
|
}
|
|
|
|
// RespondToPermission responds to a permission request
|
|
func (c *Controller) RespondToPermission(ctx context.Context, req dto.PermissionRespondRequest) (dto.PermissionRespondResponse, error) {
|
|
if err := c.service.RespondToPermission(ctx, req.TaskID, req.PendingID, req.OptionID, req.Cancelled); err != nil {
|
|
return dto.PermissionRespondResponse{}, err
|
|
}
|
|
|
|
return dto.PermissionRespondResponse{
|
|
Success: true,
|
|
TaskID: req.TaskID,
|
|
PendingID: req.PendingID,
|
|
}, nil
|
|
}
|
|
|