Files
kandev/apps/backend/cmd/agentctl/main.go
T
jcfs 20f5f43fb3 feat: complete acp-go-sdk integration with task state updates
- Use acp-go-sdk for all ACP communication in agentctl
- Mark agent as completed when Prompt() returns successfully
- Update task state to COMPLETED when agent completes
- Update task state to FAILED when agent fails and retries exhausted
- Enhanced E2E test to verify agent actually creates files
- E2E test now validates full flow: task creation -> agent work -> file creation -> task completion
2026-01-10 16:46:35 +00:00

104 lines
2.6 KiB
Go

// Package main is the entry point for agentctl - a control process that runs
// inside Docker containers to manage AI agent processes.
//
// agentctl provides:
// - HTTP REST API for control operations (start, stop, pause, resume)
// - WebSocket streaming of agent output
// - Process management for the underlying agent (e.g., auggie --acp)
// - ACP message relay between HTTP API and agent subprocess
package main
import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/kandev/kandev/internal/agentctl/api"
"github.com/kandev/kandev/internal/agentctl/config"
"github.com/kandev/kandev/internal/agentctl/process"
"github.com/kandev/kandev/internal/common/logger"
"go.uber.org/zap"
)
func main() {
// Load configuration
cfg := config.Load()
// Initialize logger
log, err := logger.NewLogger(logger.LoggingConfig{
Level: cfg.LogLevel,
Format: cfg.LogFormat,
OutputPath: "stdout",
})
if err != nil {
fmt.Fprintf(os.Stderr, "failed to initialize logger: %v\n", err)
os.Exit(1)
}
defer log.Sync()
log.Info("starting agentctl",
zap.String("version", "0.1.0"),
zap.Int("port", cfg.Port),
zap.String("agent_command", cfg.AgentCommand),
)
// Create process manager
procMgr := process.NewManager(cfg, log)
// Create API server
apiServer := api.NewServer(cfg, procMgr, log)
// Create HTTP server
server := &http.Server{
Addr: fmt.Sprintf(":%d", cfg.Port),
Handler: apiServer.Router(),
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
}
// Start server in goroutine
go func() {
log.Info("HTTP server listening", zap.String("addr", server.Addr))
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatal("HTTP server error", zap.Error(err))
}
}()
// Auto-start agent if configured
if cfg.AutoStart {
log.Info("auto-starting agent process")
ctx := context.Background()
if err := procMgr.Start(ctx); err != nil {
log.Error("failed to auto-start agent", zap.Error(err))
}
}
// Wait for shutdown signal
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Info("shutting down agentctl")
// Graceful shutdown
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// Stop the agent process
if err := procMgr.Stop(ctx); err != nil {
log.Error("failed to stop agent process", zap.Error(err))
}
// Shutdown HTTP server
if err := server.Shutdown(ctx); err != nil {
log.Error("HTTP server shutdown error", zap.Error(err))
}
log.Info("agentctl stopped")
}