Compare commits

...

19 Commits

Author SHA1 Message Date
4a79011793 Update git remote URL from git.ourworld.tf to git.threefold.info 2025-06-15 16:21:09 +02:00
0b62ac9ecd ... 2025-05-24 10:42:24 +04:00
c9b14730ad ... 2025-05-24 10:33:50 +04:00
2ee8a95a90 ... 2025-05-24 09:52:43 +04:00
8bc1759dcb ... 2025-05-24 09:24:19 +04:00
e60b9f62f1 ... 2025-05-24 07:24:17 +04:00
5d241e9ade ... 2025-05-24 07:09:15 +04:00
b8c8da9e31 ... 2025-05-24 06:56:02 +04:00
55a05a5571 ... 2025-05-23 22:12:17 +04:00
2bfe4161b2 ... 2025-05-23 22:09:57 +04:00
0b1d9907a7 ... 2025-05-23 16:30:10 +04:00
c78761fe20 ... 2025-05-23 16:23:41 +04:00
2e8ec1735a ... 2025-05-23 16:19:07 +04:00
29d0d25a3b ... 2025-05-23 16:10:49 +04:00
3f01074e3f ... 2025-05-23 15:56:35 +04:00
532cda72d3 ... 2025-05-23 15:40:41 +04:00
0e545e56de ... 2025-05-23 15:28:30 +04:00
92b9c356b8 ... 2025-05-23 15:11:03 +04:00
c86165f88c ... 2025-05-23 14:05:09 +04:00
231 changed files with 6630 additions and 5019 deletions

View File

@@ -11,7 +11,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/freeflowuniverse/heroagent/pkg/mycelium_client" "git.threefold.info/herocode/heroagent/pkg/mycelium_client"
) )
type config struct { type config struct {

View File

@@ -8,7 +8,7 @@ import (
"os" "os"
"time" "time"
"github.com/freeflowuniverse/heroagent/pkg/mycelium_client" "git.threefold.info/herocode/heroagent/pkg/mycelium_client"
) )
func main() { func main() {

View File

@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/freeflowuniverse/heroagent/pkg/system/stats" "git.threefold.info/herocode/heroagent/pkg/system/stats"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
@@ -77,7 +77,7 @@ func (h *AdminHandler) getProcessStatsJSON(c *fiber.Ctx) error {
if err != nil { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"success": false, "success": false,
"error": "Failed to get process stats: " + err.Error(), "error": "Failed to get process stats: " + err.Error(),
}) })
} }

View File

@@ -3,7 +3,7 @@ package api
import ( import (
"time" "time"
"github.com/freeflowuniverse/heroagent/pkg/sal/executor" "git.threefold.info/herocode/heroagent/pkg/sal/executor"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )

View File

@@ -7,9 +7,9 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/freeflowuniverse/heroagent/pkg/processmanager" "git.threefold.info/herocode/heroagent/pkg/processmanager"
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces" "git.threefold.info/herocode/heroagent/pkg/processmanager/interfaces"
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces/openrpc" "git.threefold.info/herocode/heroagent/pkg/processmanager/interfaces/openrpc"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
@@ -102,26 +102,26 @@ func (h *ServiceHandler) getProcessList() ([]ProcessDisplayInfo, error) {
if !ok { if !ok {
// Try to handle the result as a map or other structure // Try to handle the result as a map or other structure
h.logger.Printf("Warning: unexpected result type from ListProcesses, trying alternative parsing") h.logger.Printf("Warning: unexpected result type from ListProcesses, trying alternative parsing")
// Try to convert the result to JSON and then parse it // Try to convert the result to JSON and then parse it
resultJSON, err := json.Marshal(result) resultJSON, err := json.Marshal(result)
if err != nil { if err != nil {
h.logger.Printf("Error marshaling result to JSON: %v", err) h.logger.Printf("Error marshaling result to JSON: %v", err)
return nil, fmt.Errorf("failed to marshal result: %w", err) return nil, fmt.Errorf("failed to marshal result: %w", err)
} }
var processStatuses []interfaces.ProcessStatus var processStatuses []interfaces.ProcessStatus
if err := json.Unmarshal(resultJSON, &processStatuses); err != nil { if err := json.Unmarshal(resultJSON, &processStatuses); err != nil {
h.logger.Printf("Error unmarshaling result to ProcessStatus: %v", err) h.logger.Printf("Error unmarshaling result to ProcessStatus: %v", err)
return nil, fmt.Errorf("failed to unmarshal process list result: %w", err) return nil, fmt.Errorf("failed to unmarshal process list result: %w", err)
} }
// Convert to display info format // Convert to display info format
displayInfoList := make([]ProcessDisplayInfo, 0, len(processStatuses)) displayInfoList := make([]ProcessDisplayInfo, 0, len(processStatuses))
for _, proc := range processStatuses { for _, proc := range processStatuses {
// Calculate uptime based on start time // Calculate uptime based on start time
uptime := formatUptime(time.Since(proc.StartTime)) uptime := formatUptime(time.Since(proc.StartTime))
displayInfo := ProcessDisplayInfo{ displayInfo := ProcessDisplayInfo{
ID: fmt.Sprintf("%d", proc.PID), ID: fmt.Sprintf("%d", proc.PID),
Name: proc.Name, Name: proc.Name,
@@ -133,7 +133,7 @@ func (h *ServiceHandler) getProcessList() ([]ProcessDisplayInfo, error) {
} }
displayInfoList = append(displayInfoList, displayInfo) displayInfoList = append(displayInfoList, displayInfo)
} }
// Debug: Log the number of processes // Debug: Log the number of processes
h.logger.Printf("Found %d processes", len(displayInfoList)) h.logger.Printf("Found %d processes", len(displayInfoList))
return displayInfoList, nil return displayInfoList, nil
@@ -144,7 +144,7 @@ func (h *ServiceHandler) getProcessList() ([]ProcessDisplayInfo, error) {
for _, proc := range processStatuses { for _, proc := range processStatuses {
// Calculate uptime based on start time // Calculate uptime based on start time
uptime := formatUptime(time.Since(proc.StartTime)) uptime := formatUptime(time.Since(proc.StartTime))
displayInfo := ProcessDisplayInfo{ displayInfo := ProcessDisplayInfo{
ID: fmt.Sprintf("%d", proc.PID), ID: fmt.Sprintf("%d", proc.PID),
Name: proc.Name, Name: proc.Name,
@@ -276,7 +276,7 @@ func (h *ServiceHandler) stopService(c *fiber.Ctx) error {
"error": fmt.Sprintf("Failed to stop service: %v", err), "error": fmt.Sprintf("Failed to stop service: %v", err),
}) })
} }
// Check if the result indicates success // Check if the result indicates success
if !result.Success { if !result.Success {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
@@ -331,7 +331,7 @@ func (h *ServiceHandler) restartService(c *fiber.Ctx) error {
"error": fmt.Sprintf("Failed to restart service: %v", err), "error": fmt.Sprintf("Failed to restart service: %v", err),
}) })
} }
// Check if the result indicates success // Check if the result indicates success
if !result.Success { if !result.Success {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
@@ -382,7 +382,7 @@ func (h *ServiceHandler) deleteService(c *fiber.Ctx) error {
"error": fmt.Sprintf("Failed to delete service: %v", err), "error": fmt.Sprintf("Failed to delete service: %v", err),
}) })
} }
// Check if the result indicates success // Check if the result indicates success
if !result.Success { if !result.Success {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{

View File

@@ -12,16 +12,16 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/freeflowuniverse/heroagent/pkg/heroagent/api" "git.threefold.info/herocode/heroagent/pkg/heroagent/api"
"github.com/freeflowuniverse/heroagent/pkg/heroagent/handlers" "git.threefold.info/herocode/heroagent/pkg/heroagent/handlers"
"github.com/freeflowuniverse/heroagent/pkg/heroagent/pages" "git.threefold.info/herocode/heroagent/pkg/heroagent/pages"
"github.com/freeflowuniverse/heroagent/pkg/processmanager" "git.threefold.info/herocode/heroagent/pkg/processmanager"
"github.com/freeflowuniverse/heroagent/pkg/sal/executor" "git.threefold.info/herocode/heroagent/pkg/sal/executor"
"github.com/freeflowuniverse/heroagent/pkg/servers/redisserver" "git.threefold.info/herocode/heroagent/pkg/servers/redisserver"
"github.com/freeflowuniverse/heroagent/pkg/system/stats" "git.threefold.info/herocode/heroagent/pkg/system/stats"
// "github.com/freeflowuniverse/heroagent/pkg/vfs/interfaces" // "git.threefold.info/herocode/heroagent/pkg/vfs/interfaces"
// "github.com/freeflowuniverse/heroagent/pkg/vfs/interfaces/mock" // "git.threefold.info/herocode/heroagent/pkg/vfs/interfaces/mock"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors" "github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/fiber/v2/middleware/logger"
@@ -239,7 +239,7 @@ func (hl *HeroLauncher) GetUptime() string {
func (hl *HeroLauncher) startProcessManager() error { func (hl *HeroLauncher) startProcessManager() error {
_, filename, _, _ := runtime.Caller(0) _, filename, _, _ := runtime.Caller(0)
projectRoot := filepath.Join(filepath.Dir(filename), "../..") projectRoot := filepath.Join(filepath.Dir(filename), "../..")
processManagerPath := filepath.Join(projectRoot, "cmd/processmanager/main.go") processManagerPath := filepath.Join(projectRoot, "pkg/processmanager/examples/openrpc/main.go")
log.Printf("Starting process manager from: %s", processManagerPath) log.Printf("Starting process manager from: %s", processManagerPath)

View File

@@ -5,7 +5,7 @@ import (
"log" "log"
"strconv" // Added strconv for JobID parsing "strconv" // Added strconv for JobID parsing
"github.com/freeflowuniverse/heroagent/pkg/herojobs" "git.threefold.info/herocode/heroagent/pkg/herojobs"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )

View File

@@ -10,7 +10,7 @@ import (
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"github.com/freeflowuniverse/heroagent/pkg/herojobs" "git.threefold.info/herocode/heroagent/pkg/herojobs"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"

View File

@@ -7,7 +7,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/freeflowuniverse/heroagent/pkg/logger" "git.threefold.info/herocode/heroagent/pkg/logger"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
@@ -65,40 +65,40 @@ func NewLogHandler(logPath string) (*LogHandler, error) {
type LogType string type LogType string
const ( const (
LogTypeSystem LogType = "system" LogTypeSystem LogType = "system"
LogTypeService LogType = "service" LogTypeService LogType = "service"
LogTypeJob LogType = "job" LogTypeJob LogType = "job"
LogTypeProcess LogType = "process" LogTypeProcess LogType = "process"
LogTypeAll LogType = "all" // Special type to retrieve logs from all sources LogTypeAll LogType = "all" // Special type to retrieve logs from all sources
) )
// GetLogs renders the logs page with logs content // GetLogs renders the logs page with logs content
func (h *LogHandler) GetLogs(c *fiber.Ctx) error { func (h *LogHandler) GetLogs(c *fiber.Ctx) error {
// Check which logger to use based on the log type parameter // Check which logger to use based on the log type parameter
logTypeParam := c.Query("log_type", string(LogTypeSystem)) logTypeParam := c.Query("log_type", string(LogTypeSystem))
// Parse query parameters // Parse query parameters
category := c.Query("category", "") category := c.Query("category", "")
logItemType := parseLogType(c.Query("type", "")) logItemType := parseLogType(c.Query("type", ""))
maxItems := c.QueryInt("max_items", 100) maxItems := c.QueryInt("max_items", 100)
page := c.QueryInt("page", 1) page := c.QueryInt("page", 1)
itemsPerPage := 20 // Default items per page itemsPerPage := 20 // Default items per page
// Parse time range // Parse time range
fromTime := parseTimeParam(c.Query("from", "")) fromTime := parseTimeParam(c.Query("from", ""))
toTime := parseTimeParam(c.Query("to", "")) toTime := parseTimeParam(c.Query("to", ""))
// Create search arguments // Create search arguments
searchArgs := logger.SearchArgs{ searchArgs := logger.SearchArgs{
Category: category, Category: category,
LogType: logItemType, LogType: logItemType,
MaxItems: maxItems, MaxItems: maxItems,
} }
if !fromTime.IsZero() { if !fromTime.IsZero() {
searchArgs.TimestampFrom = &fromTime searchArgs.TimestampFrom = &fromTime
} }
if !toTime.IsZero() { if !toTime.IsZero() {
searchArgs.TimestampTo = &toTime searchArgs.TimestampTo = &toTime
} }
@@ -107,7 +107,7 @@ func (h *LogHandler) GetLogs(c *fiber.Ctx) error {
var logs []logger.LogItem var logs []logger.LogItem
var err error var err error
var logTypeTitle string var logTypeTitle string
// Check if we want to merge logs from all sources // Check if we want to merge logs from all sources
if LogType(logTypeParam) == LogTypeAll { if LogType(logTypeParam) == LogTypeAll {
// Get merged logs from all loggers // Get merged logs from all loggers
@@ -116,7 +116,7 @@ func (h *LogHandler) GetLogs(c *fiber.Ctx) error {
} else { } else {
// Select the appropriate logger based on the log type // Select the appropriate logger based on the log type
var selectedLogger *logger.Logger var selectedLogger *logger.Logger
switch LogType(logTypeParam) { switch LogType(logTypeParam) {
case LogTypeService: case LogTypeService:
selectedLogger = h.serviceLogger selectedLogger = h.serviceLogger
@@ -131,13 +131,13 @@ func (h *LogHandler) GetLogs(c *fiber.Ctx) error {
selectedLogger = h.systemLogger selectedLogger = h.systemLogger
logTypeTitle = "System Logs" logTypeTitle = "System Logs"
} }
// Check if the selected logger is properly initialized // Check if the selected logger is properly initialized
if selectedLogger == nil { if selectedLogger == nil {
return c.Render("admin/system/logs", fiber.Map{ return c.Render("admin/system/logs", fiber.Map{
"title": logTypeTitle, "title": logTypeTitle,
"error": "Logger not initialized", "error": "Logger not initialized",
"logTypes": []LogType{LogTypeAll, LogTypeSystem, LogTypeService, LogTypeJob, LogTypeProcess}, "logTypes": []LogType{LogTypeAll, LogTypeSystem, LogTypeService, LogTypeJob, LogTypeProcess},
"selectedLogType": logTypeParam, "selectedLogType": logTypeParam,
}) })
} }
@@ -149,25 +149,24 @@ func (h *LogHandler) GetLogs(c *fiber.Ctx) error {
// Handle search error // Handle search error
if err != nil { if err != nil {
return c.Render("admin/system/logs", fiber.Map{ return c.Render("admin/system/logs", fiber.Map{
"title": logTypeTitle, "title": logTypeTitle,
"error": err.Error(), "error": err.Error(),
"logTypes": []LogType{LogTypeAll, LogTypeSystem, LogTypeService, LogTypeJob, LogTypeProcess}, "logTypes": []LogType{LogTypeAll, LogTypeSystem, LogTypeService, LogTypeJob, LogTypeProcess},
"selectedLogType": logTypeParam, "selectedLogType": logTypeParam,
}) })
} }
// Calculate total pages // Calculate total pages
totalLogs := len(logs) totalLogs := len(logs)
totalPages := (totalLogs + itemsPerPage - 1) / itemsPerPage totalPages := (totalLogs + itemsPerPage - 1) / itemsPerPage
// Apply pagination // Apply pagination
startIndex := (page - 1) * itemsPerPage startIndex := (page - 1) * itemsPerPage
endIndex := startIndex + itemsPerPage endIndex := startIndex + itemsPerPage
if endIndex > totalLogs { if endIndex > totalLogs {
endIndex = totalLogs endIndex = totalLogs
} }
// Slice logs for current page // Slice logs for current page
pagedLogs := logs pagedLogs := logs
if startIndex < totalLogs { if startIndex < totalLogs {
@@ -175,7 +174,7 @@ func (h *LogHandler) GetLogs(c *fiber.Ctx) error {
} else { } else {
pagedLogs = []logger.LogItem{} pagedLogs = []logger.LogItem{}
} }
// Convert logs to a format suitable for the UI // Convert logs to a format suitable for the UI
formattedLogs := make([]fiber.Map, 0, len(pagedLogs)) formattedLogs := make([]fiber.Map, 0, len(pagedLogs))
for _, log := range pagedLogs { for _, log := range pagedLogs {
@@ -185,7 +184,7 @@ func (h *LogHandler) GetLogs(c *fiber.Ctx) error {
logTypeStr = "ERROR" logTypeStr = "ERROR"
logTypeClass = "log-error" logTypeClass = "log-error"
} }
formattedLogs = append(formattedLogs, fiber.Map{ formattedLogs = append(formattedLogs, fiber.Map{
"timestamp": log.Timestamp.Format("2006-01-02T15:04:05"), "timestamp": log.Timestamp.Format("2006-01-02T15:04:05"),
"category": log.Category, "category": log.Category,
@@ -194,20 +193,20 @@ func (h *LogHandler) GetLogs(c *fiber.Ctx) error {
"typeClass": logTypeClass, "typeClass": logTypeClass,
}) })
} }
return c.Render("admin/system/logs", fiber.Map{ return c.Render("admin/system/logs", fiber.Map{
"title": logTypeTitle, "title": logTypeTitle,
"logTypes": []LogType{LogTypeAll, LogTypeSystem, LogTypeService, LogTypeJob, LogTypeProcess}, "logTypes": []LogType{LogTypeAll, LogTypeSystem, LogTypeService, LogTypeJob, LogTypeProcess},
"selectedLogType": logTypeParam, "selectedLogType": logTypeParam,
"logs": formattedLogs, "logs": formattedLogs,
"total": totalLogs, "total": totalLogs,
"showing": len(formattedLogs), "showing": len(formattedLogs),
"page": page, "page": page,
"totalPages": totalPages, "totalPages": totalPages,
"categoryParam": category, "categoryParam": category,
"typeParam": c.Query("type", ""), "typeParam": c.Query("type", ""),
"fromParam": c.Query("from", ""), "fromParam": c.Query("from", ""),
"toParam": c.Query("to", ""), "toParam": c.Query("to", ""),
}) })
} }
@@ -215,27 +214,27 @@ func (h *LogHandler) GetLogs(c *fiber.Ctx) error {
func (h *LogHandler) GetLogsAPI(c *fiber.Ctx) error { func (h *LogHandler) GetLogsAPI(c *fiber.Ctx) error {
// Check which logger to use based on the log type parameter // Check which logger to use based on the log type parameter
logTypeParam := c.Query("log_type", string(LogTypeSystem)) logTypeParam := c.Query("log_type", string(LogTypeSystem))
// Parse query parameters // Parse query parameters
category := c.Query("category", "") category := c.Query("category", "")
logItemType := parseLogType(c.Query("type", "")) logItemType := parseLogType(c.Query("type", ""))
maxItems := c.QueryInt("max_items", 100) maxItems := c.QueryInt("max_items", 100)
// Parse time range // Parse time range
fromTime := parseTimeParam(c.Query("from", "")) fromTime := parseTimeParam(c.Query("from", ""))
toTime := parseTimeParam(c.Query("to", "")) toTime := parseTimeParam(c.Query("to", ""))
// Create search arguments // Create search arguments
searchArgs := logger.SearchArgs{ searchArgs := logger.SearchArgs{
Category: category, Category: category,
LogType: logItemType, LogType: logItemType,
MaxItems: maxItems, MaxItems: maxItems,
} }
if !fromTime.IsZero() { if !fromTime.IsZero() {
searchArgs.TimestampFrom = &fromTime searchArgs.TimestampFrom = &fromTime
} }
if !toTime.IsZero() { if !toTime.IsZero() {
searchArgs.TimestampTo = &toTime searchArgs.TimestampTo = &toTime
} }
@@ -243,7 +242,7 @@ func (h *LogHandler) GetLogsAPI(c *fiber.Ctx) error {
// Variables for logs and error // Variables for logs and error
var logs []logger.LogItem var logs []logger.LogItem
var err error var err error
// Check if we want to merge logs from all sources // Check if we want to merge logs from all sources
if LogType(logTypeParam) == LogTypeAll { if LogType(logTypeParam) == LogTypeAll {
// Get merged logs from all loggers // Get merged logs from all loggers
@@ -251,7 +250,7 @@ func (h *LogHandler) GetLogsAPI(c *fiber.Ctx) error {
} else { } else {
// Select the appropriate logger based on the log type // Select the appropriate logger based on the log type
var selectedLogger *logger.Logger var selectedLogger *logger.Logger
switch LogType(logTypeParam) { switch LogType(logTypeParam) {
case LogTypeService: case LogTypeService:
selectedLogger = h.serviceLogger selectedLogger = h.serviceLogger
@@ -262,7 +261,7 @@ func (h *LogHandler) GetLogsAPI(c *fiber.Ctx) error {
default: default:
selectedLogger = h.systemLogger selectedLogger = h.systemLogger
} }
// Check if the selected logger is properly initialized // Check if the selected logger is properly initialized
if selectedLogger == nil { if selectedLogger == nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
@@ -280,7 +279,7 @@ func (h *LogHandler) GetLogsAPI(c *fiber.Ctx) error {
"error": err.Error(), "error": err.Error(),
}) })
} }
// Convert logs to a format suitable for the UI // Convert logs to a format suitable for the UI
response := make([]fiber.Map, 0, len(logs)) response := make([]fiber.Map, 0, len(logs))
for _, log := range logs { for _, log := range logs {
@@ -288,7 +287,7 @@ func (h *LogHandler) GetLogsAPI(c *fiber.Ctx) error {
if log.LogType == logger.LogTypeError { if log.LogType == logger.LogTypeError {
logTypeStr = "ERROR" logTypeStr = "ERROR"
} }
response = append(response, fiber.Map{ response = append(response, fiber.Map{
"timestamp": log.Timestamp.Format(time.RFC3339), "timestamp": log.Timestamp.Format(time.RFC3339),
"category": log.Category, "category": log.Category,
@@ -296,9 +295,9 @@ func (h *LogHandler) GetLogsAPI(c *fiber.Ctx) error {
"type": logTypeStr, "type": logTypeStr,
}) })
} }
return c.JSON(fiber.Map{ return c.JSON(fiber.Map{
"logs": response, "logs": response,
"total": len(logs), "total": len(logs),
}) })
} }
@@ -309,29 +308,29 @@ func (h *LogHandler) GetLogsFragment(c *fiber.Ctx) error {
// Check which logger to use based on the log type parameter // Check which logger to use based on the log type parameter
logTypeParam := c.Query("log_type", string(LogTypeSystem)) logTypeParam := c.Query("log_type", string(LogTypeSystem))
// Parse query parameters // Parse query parameters
category := c.Query("category", "") category := c.Query("category", "")
logItemType := parseLogType(c.Query("type", "")) logItemType := parseLogType(c.Query("type", ""))
maxItems := c.QueryInt("max_items", 100) maxItems := c.QueryInt("max_items", 100)
page := c.QueryInt("page", 1) page := c.QueryInt("page", 1)
itemsPerPage := 20 // Default items per page itemsPerPage := 20 // Default items per page
// Parse time range // Parse time range
fromTime := parseTimeParam(c.Query("from", "")) fromTime := parseTimeParam(c.Query("from", ""))
toTime := parseTimeParam(c.Query("to", "")) toTime := parseTimeParam(c.Query("to", ""))
// Create search arguments // Create search arguments
searchArgs := logger.SearchArgs{ searchArgs := logger.SearchArgs{
Category: category, Category: category,
LogType: logItemType, LogType: logItemType,
MaxItems: maxItems, MaxItems: maxItems,
} }
if !fromTime.IsZero() { if !fromTime.IsZero() {
searchArgs.TimestampFrom = &fromTime searchArgs.TimestampFrom = &fromTime
} }
if !toTime.IsZero() { if !toTime.IsZero() {
searchArgs.TimestampTo = &toTime searchArgs.TimestampTo = &toTime
} }
@@ -340,7 +339,7 @@ func (h *LogHandler) GetLogsFragment(c *fiber.Ctx) error {
var logs []logger.LogItem var logs []logger.LogItem
var err error var err error
var logTypeTitle string var logTypeTitle string
// Check if we want to merge logs from all sources // Check if we want to merge logs from all sources
if LogType(logTypeParam) == LogTypeAll { if LogType(logTypeParam) == LogTypeAll {
// Get merged logs from all loggers // Get merged logs from all loggers
@@ -349,7 +348,7 @@ func (h *LogHandler) GetLogsFragment(c *fiber.Ctx) error {
} else { } else {
// Select the appropriate logger based on the log type // Select the appropriate logger based on the log type
var selectedLogger *logger.Logger var selectedLogger *logger.Logger
switch LogType(logTypeParam) { switch LogType(logTypeParam) {
case LogTypeService: case LogTypeService:
selectedLogger = h.serviceLogger selectedLogger = h.serviceLogger
@@ -364,13 +363,13 @@ func (h *LogHandler) GetLogsFragment(c *fiber.Ctx) error {
selectedLogger = h.systemLogger selectedLogger = h.systemLogger
logTypeTitle = "System Logs" logTypeTitle = "System Logs"
} }
// Check if the selected logger is properly initialized // Check if the selected logger is properly initialized
if selectedLogger == nil { if selectedLogger == nil {
return c.Render("admin/system/logs_fragment", fiber.Map{ return c.Render("admin/system/logs_fragment", fiber.Map{
"title": logTypeTitle, "title": logTypeTitle,
"error": "Logger not initialized", "error": "Logger not initialized",
"logTypes": []LogType{LogTypeAll, LogTypeSystem, LogTypeService, LogTypeJob, LogTypeProcess}, "logTypes": []LogType{LogTypeAll, LogTypeSystem, LogTypeService, LogTypeJob, LogTypeProcess},
"selectedLogType": logTypeParam, "selectedLogType": logTypeParam,
}) })
} }
@@ -382,24 +381,24 @@ func (h *LogHandler) GetLogsFragment(c *fiber.Ctx) error {
// Handle search error // Handle search error
if err != nil { if err != nil {
return c.Render("admin/system/logs_fragment", fiber.Map{ return c.Render("admin/system/logs_fragment", fiber.Map{
"title": logTypeTitle, "title": logTypeTitle,
"error": err.Error(), "error": err.Error(),
"logTypes": []LogType{LogTypeAll, LogTypeSystem, LogTypeService, LogTypeJob, LogTypeProcess}, "logTypes": []LogType{LogTypeAll, LogTypeSystem, LogTypeService, LogTypeJob, LogTypeProcess},
"selectedLogType": logTypeParam, "selectedLogType": logTypeParam,
}) })
} }
// Calculate total pages // Calculate total pages
totalLogs := len(logs) totalLogs := len(logs)
totalPages := (totalLogs + itemsPerPage - 1) / itemsPerPage totalPages := (totalLogs + itemsPerPage - 1) / itemsPerPage
// Apply pagination // Apply pagination
startIndex := (page - 1) * itemsPerPage startIndex := (page - 1) * itemsPerPage
endIndex := startIndex + itemsPerPage endIndex := startIndex + itemsPerPage
if endIndex > totalLogs { if endIndex > totalLogs {
endIndex = totalLogs endIndex = totalLogs
} }
// Slice logs for current page // Slice logs for current page
pagedLogs := logs pagedLogs := logs
if startIndex < totalLogs { if startIndex < totalLogs {
@@ -407,7 +406,7 @@ func (h *LogHandler) GetLogsFragment(c *fiber.Ctx) error {
} else { } else {
pagedLogs = []logger.LogItem{} pagedLogs = []logger.LogItem{}
} }
// Convert logs to a format suitable for the UI // Convert logs to a format suitable for the UI
formattedLogs := make([]fiber.Map, 0, len(pagedLogs)) formattedLogs := make([]fiber.Map, 0, len(pagedLogs))
for _, log := range pagedLogs { for _, log := range pagedLogs {
@@ -417,7 +416,7 @@ func (h *LogHandler) GetLogsFragment(c *fiber.Ctx) error {
logTypeStr = "ERROR" logTypeStr = "ERROR"
logTypeClass = "log-error" logTypeClass = "log-error"
} }
formattedLogs = append(formattedLogs, fiber.Map{ formattedLogs = append(formattedLogs, fiber.Map{
"timestamp": log.Timestamp.Format("2006-01-02T15:04:05"), "timestamp": log.Timestamp.Format("2006-01-02T15:04:05"),
"category": log.Category, "category": log.Category,
@@ -426,18 +425,18 @@ func (h *LogHandler) GetLogsFragment(c *fiber.Ctx) error {
"typeClass": logTypeClass, "typeClass": logTypeClass,
}) })
} }
// Set layout to empty to disable the layout for fragment responses // Set layout to empty to disable the layout for fragment responses
return c.Render("admin/system/logs_fragment", fiber.Map{ return c.Render("admin/system/logs_fragment", fiber.Map{
"title": logTypeTitle, "title": logTypeTitle,
"logTypes": []LogType{LogTypeAll, LogTypeSystem, LogTypeService, LogTypeJob, LogTypeProcess}, "logTypes": []LogType{LogTypeAll, LogTypeSystem, LogTypeService, LogTypeJob, LogTypeProcess},
"selectedLogType": logTypeParam, "selectedLogType": logTypeParam,
"logs": formattedLogs, "logs": formattedLogs,
"total": totalLogs, "total": totalLogs,
"showing": len(formattedLogs), "showing": len(formattedLogs),
"page": page, "page": page,
"totalPages": totalPages, "totalPages": totalPages,
"layout": "", // Disable layout for partial template "layout": "", // Disable layout for partial template
}) })
} }
@@ -458,12 +457,12 @@ func parseTimeParam(timeStr string) time.Time {
if timeStr == "" { if timeStr == "" {
return time.Time{} return time.Time{}
} }
t, err := time.Parse(time.RFC3339, timeStr) t, err := time.Parse(time.RFC3339, timeStr)
if err != nil { if err != nil {
return time.Time{} return time.Time{}
} }
return t return t
} }
@@ -471,10 +470,10 @@ func parseTimeParam(timeStr string) time.Time {
func (h *LogHandler) getMergedLogs(args logger.SearchArgs) ([]logger.LogItem, error) { func (h *LogHandler) getMergedLogs(args logger.SearchArgs) ([]logger.LogItem, error) {
// Create a slice to hold all logs // Create a slice to hold all logs
allLogs := make([]logger.LogItem, 0) allLogs := make([]logger.LogItem, 0)
// Create a map to track errors // Create a map to track errors
errors := make(map[string]error) errors := make(map[string]error)
// Get logs from system logger if available // Get logs from system logger if available
if h.systemLogger != nil { if h.systemLogger != nil {
systemLogs, err := h.systemLogger.Search(args) systemLogs, err := h.systemLogger.Search(args)
@@ -488,7 +487,7 @@ func (h *LogHandler) getMergedLogs(args logger.SearchArgs) ([]logger.LogItem, er
allLogs = append(allLogs, systemLogs...) allLogs = append(allLogs, systemLogs...)
} }
} }
// Get logs from service logger if available // Get logs from service logger if available
if h.serviceLogger != nil { if h.serviceLogger != nil {
serviceLogs, err := h.serviceLogger.Search(args) serviceLogs, err := h.serviceLogger.Search(args)
@@ -502,7 +501,7 @@ func (h *LogHandler) getMergedLogs(args logger.SearchArgs) ([]logger.LogItem, er
allLogs = append(allLogs, serviceLogs...) allLogs = append(allLogs, serviceLogs...)
} }
} }
// Get logs from job logger if available // Get logs from job logger if available
if h.jobLogger != nil { if h.jobLogger != nil {
jobLogs, err := h.jobLogger.Search(args) jobLogs, err := h.jobLogger.Search(args)
@@ -516,7 +515,7 @@ func (h *LogHandler) getMergedLogs(args logger.SearchArgs) ([]logger.LogItem, er
allLogs = append(allLogs, jobLogs...) allLogs = append(allLogs, jobLogs...)
} }
} }
// Get logs from process logger if available // Get logs from process logger if available
if h.processLogger != nil { if h.processLogger != nil {
processLogs, err := h.processLogger.Search(args) processLogs, err := h.processLogger.Search(args)
@@ -530,7 +529,7 @@ func (h *LogHandler) getMergedLogs(args logger.SearchArgs) ([]logger.LogItem, er
allLogs = append(allLogs, processLogs...) allLogs = append(allLogs, processLogs...)
} }
} }
// Check if we have any logs // Check if we have any logs
if len(allLogs) == 0 && len(errors) > 0 { if len(allLogs) == 0 && len(errors) > 0 {
// Combine error messages // Combine error messages
@@ -540,16 +539,16 @@ func (h *LogHandler) getMergedLogs(args logger.SearchArgs) ([]logger.LogItem, er
} }
return nil, fmt.Errorf("failed to retrieve logs: %s", strings.Join(errorMsgs, "; ")) return nil, fmt.Errorf("failed to retrieve logs: %s", strings.Join(errorMsgs, "; "))
} }
// Sort logs by timestamp (newest first) // Sort logs by timestamp (newest first)
sort.Slice(allLogs, func(i, j int) bool { sort.Slice(allLogs, func(i, j int) bool {
return allLogs[i].Timestamp.After(allLogs[j].Timestamp) return allLogs[i].Timestamp.After(allLogs[j].Timestamp)
}) })
// Apply max items limit if specified // Apply max items limit if specified
if args.MaxItems > 0 && len(allLogs) > args.MaxItems { if args.MaxItems > 0 && len(allLogs) > args.MaxItems {
allLogs = allLogs[:args.MaxItems] allLogs = allLogs[:args.MaxItems]
} }
return allLogs, nil return allLogs, nil
} }

View File

@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/freeflowuniverse/heroagent/pkg/system/stats" "git.threefold.info/herocode/heroagent/pkg/system/stats"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
@@ -43,8 +43,8 @@ func (h *ProcessHandler) GetProcessStatsJSON(c *fiber.Ctx) error {
// Convert to fiber.Map for JSON response // Convert to fiber.Map for JSON response
response := fiber.Map{ response := fiber.Map{
"total": processData.Total, "total": processData.Total,
"filtered": processData.Filtered, "filtered": processData.Filtered,
"timestamp": time.Now().Unix(), "timestamp": time.Now().Unix(),
} }
@@ -61,7 +61,7 @@ func (h *ProcessHandler) GetProcessStatsJSON(c *fiber.Ctx) error {
"is_current": proc.IsCurrent, "is_current": proc.IsCurrent,
} }
} }
response["processes"] = processes response["processes"] = processes
// Return JSON response // Return JSON response
@@ -127,8 +127,8 @@ func (h *ProcessHandler) GetProcessesData(c *fiber.Ctx) error {
// Check if StatsManager is properly initialized // Check if StatsManager is properly initialized
if h.statsManager == nil { if h.statsManager == nil {
return c.Render("admin/system/processes_data", fiber.Map{ return c.Render("admin/system/processes_data", fiber.Map{
"error": "System error: Stats manager not initialized", "error": "System error: Stats manager not initialized",
"layout": "", "layout": "",
}) })
} }
@@ -156,7 +156,7 @@ func (h *ProcessHandler) GetProcessesData(c *fiber.Ctx) error {
} else { } else {
processData, err = h.statsManager.GetProcessStatsFresh(0) processData, err = h.statsManager.GetProcessStatsFresh(0)
} }
if err != nil { if err != nil {
// Handle AJAX requests differently from regular requests // Handle AJAX requests differently from regular requests
isAjax := c.Get("X-Requested-With") == "XMLHttpRequest" isAjax := c.Get("X-Requested-With") == "XMLHttpRequest"
@@ -165,8 +165,8 @@ func (h *ProcessHandler) GetProcessesData(c *fiber.Ctx) error {
} }
// For regular requests, render the error within the fragment // For regular requests, render the error within the fragment
return c.Render("admin/system/processes_data", fiber.Map{ return c.Render("admin/system/processes_data", fiber.Map{
"error": "Failed to get process data: " + err.Error(), "error": "Failed to get process data: " + err.Error(),
"layout": "", "layout": "",
}) })
} }
} }
@@ -197,9 +197,7 @@ func (h *ProcessHandler) GetProcessesData(c *fiber.Ctx) error {
"processStats": processStats, "processStats": processStats,
"layout": "", // Disable layout for partial template "layout": "", // Disable layout for partial template
} }
// Return only the table HTML content directly to be injected into the processes-table-content div // Return only the table HTML content directly to be injected into the processes-table-content div
return c.Render("admin/system/processes_data", templateData) return c.Render("admin/system/processes_data", templateData)
} }

View File

@@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces" "git.threefold.info/herocode/heroagent/pkg/processmanager/interfaces"
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces/openrpc" "git.threefold.info/herocode/heroagent/pkg/processmanager/interfaces/openrpc"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )

View File

@@ -5,7 +5,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/freeflowuniverse/heroagent/pkg/system/stats" "git.threefold.info/herocode/heroagent/pkg/system/stats"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/shirou/gopsutil/v3/host" "github.com/shirou/gopsutil/v3/host"
) )
@@ -335,7 +335,7 @@ func (h *SystemHandler) GetProcessStatsAPI(c *fiber.Ctx) error {
"is_current": proc.IsCurrent, "is_current": proc.IsCurrent,
} }
} }
response["processes"] = processes response["processes"] = processes
// Return JSON response // Return JSON response

View File

@@ -7,8 +7,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/freeflowuniverse/heroagent/pkg/heroagent/handlers" "git.threefold.info/herocode/heroagent/pkg/heroagent/handlers"
"github.com/freeflowuniverse/heroagent/pkg/system/stats" "git.threefold.info/herocode/heroagent/pkg/system/stats"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/shirou/gopsutil/v3/host" "github.com/shirou/gopsutil/v3/host"
) )
@@ -68,12 +68,12 @@ func (h *AdminHandler) RegisterRoutes(app *fiber.App) {
// System routes // System routes
admin.Get("/system/info", h.getSystemInfo) admin.Get("/system/info", h.getSystemInfo)
admin.Get("/system/hardware-stats", h.getHardwareStats) admin.Get("/system/hardware-stats", h.getHardwareStats)
// Create process handler // Create process handler
processHandler := handlers.NewProcessHandler(h.statsManager) processHandler := handlers.NewProcessHandler(h.statsManager)
admin.Get("/system/processes", processHandler.GetProcesses) admin.Get("/system/processes", processHandler.GetProcesses)
admin.Get("/system/processes-data", processHandler.GetProcessesData) admin.Get("/system/processes-data", processHandler.GetProcessesData)
// Create log handler // Create log handler
// Ensure log directory exists // Ensure log directory exists
// Using the same shared logs path as process manager // Using the same shared logs path as process manager
@@ -81,7 +81,7 @@ func (h *AdminHandler) RegisterRoutes(app *fiber.App) {
if err := os.MkdirAll(logDir, 0755); err != nil { if err := os.MkdirAll(logDir, 0755); err != nil {
fmt.Printf("Error creating log directory: %v\n", err) fmt.Printf("Error creating log directory: %v\n", err)
} }
logHandler, err := handlers.NewLogHandler(logDir) logHandler, err := handlers.NewLogHandler(logDir)
if err != nil { if err != nil {
fmt.Printf("Error creating log handler: %v\n", err) fmt.Printf("Error creating log handler: %v\n", err)
@@ -96,11 +96,11 @@ func (h *AdminHandler) RegisterRoutes(app *fiber.App) {
// but it now just redirects to the main logs endpoint // but it now just redirects to the main logs endpoint
admin.Get("/system/logs-fragment", logHandler.GetLogsFragment) admin.Get("/system/logs-fragment", logHandler.GetLogsFragment)
admin.Get("/system/logs-test", h.getSystemLogsTest) // Keep the test logs route admin.Get("/system/logs-test", h.getSystemLogsTest) // Keep the test logs route
// Log API endpoints // Log API endpoints
app.Get("/api/logs", logHandler.GetLogsAPI) app.Get("/api/logs", logHandler.GetLogsAPI)
} }
admin.Get("/system/settings", h.getSystemSettings) admin.Get("/system/settings", h.getSystemSettings)
// OpenRPC routes // OpenRPC routes

View File

@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"log" "log"
"github.com/freeflowuniverse/heroagent/pkg/herojobs" "git.threefold.info/herocode/heroagent/pkg/herojobs"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )

View File

@@ -4,14 +4,14 @@ import (
"fmt" "fmt"
"log" "log"
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces/openrpc" "git.threefold.info/herocode/heroagent/pkg/processmanager/interfaces/openrpc"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
// ServiceHandler handles service-related page routes // ServiceHandler handles service-related page routes
type ServiceHandler struct { type ServiceHandler struct {
client *openrpc.Client client *openrpc.Client
logger *log.Logger logger *log.Logger
} }
// NewServiceHandler creates a new service handler with the provided socket path and secret // NewServiceHandler creates a new service handler with the provided socket path and secret
@@ -90,7 +90,7 @@ func (h *ServiceHandler) getProcessList() ([]ProcessDisplayInfo, error) {
if !ok { if !ok {
continue continue
} }
// Create a ProcessDisplayInfo from the map // Create a ProcessDisplayInfo from the map
displayInfo := ProcessDisplayInfo{ displayInfo := ProcessDisplayInfo{
ID: fmt.Sprintf("%v", procMap["pid"]), ID: fmt.Sprintf("%v", procMap["pid"]),

View File

@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/freeflowuniverse/heroagent/pkg/processmanager" "git.threefold.info/herocode/heroagent/pkg/processmanager"
) )
// ProcessDisplayInfo represents information about a process for display purposes // ProcessDisplayInfo represents information about a process for display purposes
@@ -22,7 +22,7 @@ type ProcessDisplayInfo struct {
func ConvertToDisplayInfo(info *processmanager.ProcessInfo) ProcessDisplayInfo { func ConvertToDisplayInfo(info *processmanager.ProcessInfo) ProcessDisplayInfo {
// Calculate uptime from start time // Calculate uptime from start time
uptime := formatUptime(time.Since(info.StartTime)) uptime := formatUptime(time.Since(info.StartTime))
return ProcessDisplayInfo{ return ProcessDisplayInfo{
ID: fmt.Sprintf("%d", info.PID), ID: fmt.Sprintf("%d", info.PID),
Name: info.Name, Name: info.Name,

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 844 B

After

Width:  |  Height:  |  Size: 844 B

View File

@@ -35,7 +35,7 @@ Key features:
```go ```go
import ( import (
"fmt" "fmt"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook" "git.threefold.info/herocode/heroagent/pkg/heroscript/playbook"
) )
// Create a new playbook from HeroScript text // Create a new playbook from HeroScript text

View File

@@ -7,7 +7,7 @@ import (
"os/signal" "os/signal"
"syscall" "syscall"
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory/herohandler" "git.threefold.info/herocode/heroagent/pkg/handlerfactory/herohandler"
) )
func main() { func main() {
@@ -24,7 +24,7 @@ func main() {
fmt.Printf("Failed to initialize hero handler: %v\n", err) fmt.Printf("Failed to initialize hero handler: %v\n", err)
os.Exit(1) os.Exit(1)
} }
// Get the default instance // Get the default instance
handler := herohandler.DefaultInstance handler := herohandler.DefaultInstance
@@ -43,7 +43,7 @@ func main() {
tcpAddressStr = *tcpAddress tcpAddressStr = *tcpAddress
fmt.Printf("TCP address: %s\n", tcpAddressStr) fmt.Printf("TCP address: %s\n", tcpAddressStr)
} }
err = handler.StartTelnet(socketPathStr, tcpAddressStr) err = handler.StartTelnet(socketPathStr, tcpAddressStr)
if err != nil { if err != nil {
fmt.Printf("Failed to start telnet server: %v\n", err) fmt.Printf("Failed to start telnet server: %v\n", err)

View File

@@ -8,7 +8,7 @@ import (
"os" "os"
"strings" "strings"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook" "git.threefold.info/herocode/heroagent/pkg/heroscript/playbook"
) )
func main() { func main() {

View File

@@ -3,8 +3,8 @@ package internal
import ( import (
"fmt" "fmt"
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory" "git.threefold.info/herocode/heroagent/pkg/handlerfactory"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlers" "git.threefold.info/herocode/heroagent/pkg/heroscript/handlers"
) )
// ExampleHandler handles example actions // ExampleHandler handles example actions

View File

@@ -7,7 +7,7 @@ import (
"os" "os"
"strings" "strings"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/cmd/herohandler/internal" "git.threefold.info/herocode/heroagent/pkg/heroscript/cmd/herohandler/internal"
) )
func main() { func main() {
@@ -30,7 +30,7 @@ func main() {
// Get the command from arguments // Get the command from arguments
command := strings.Join(os.Args[1:], " ") command := strings.Join(os.Args[1:], " ")
// Format as proper HeroScript with !! prefix if not already prefixed // Format as proper HeroScript with !! prefix if not already prefixed
script := command script := command
if !strings.HasPrefix(script, "!!") { if !strings.HasPrefix(script, "!!") {

View File

@@ -10,7 +10,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory/herohandler" "git.threefold.info/herocode/heroagent/pkg/handlerfactory/herohandler"
) )
func main() { func main() {
@@ -92,7 +92,7 @@ func showSupportedActions() {
// We need to implement this function to get supported actions // We need to implement this function to get supported actions
// Since we can't directly access the factory field, we'll use the telnet interface // Since we can't directly access the factory field, we'll use the telnet interface
script := "!!core.actions" script := "!!core.actions"
// Try TCP first, then Unix socket if TCP fails // Try TCP first, then Unix socket if TCP fails
result, err := Send(script, "localhost:8023", false) result, err := Send(script, "localhost:8023", false)
if err != nil { if err != nil {
@@ -103,7 +103,7 @@ func showSupportedActions() {
return return
} }
} }
fmt.Println("Supported actions by actor:") fmt.Println("Supported actions by actor:")
fmt.Println(result) fmt.Println(result)
} }
@@ -151,7 +151,7 @@ func Send(command string, address string, isUnixSocket bool) (string, error) {
return return
} }
response.WriteString(line) response.WriteString(line)
// If we've received a complete response, break // If we've received a complete response, break
if strings.Contains(line, "\n") && strings.TrimSpace(line) == "" { if strings.Contains(line, "\n") && strings.TrimSpace(line) == "" {
break break
@@ -187,7 +187,7 @@ func runTestScript() {
result, err = Send(script, "/tmp/hero.sock", true) result, err = Send(script, "/tmp/hero.sock", true)
if err != nil { if err != nil {
fmt.Printf("Unix socket connection failed: %v\n", err) fmt.Printf("Unix socket connection failed: %v\n", err)
// We can't directly access the factory field, so we'll just report the error // We can't directly access the factory field, so we'll just report the error
fmt.Printf("Error: %v\n", err) fmt.Printf("Error: %v\n", err)
return return

View File

@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"log" "log"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook" "git.threefold.info/herocode/heroagent/pkg/heroscript/playbook"
) )
const exampleScript = ` const exampleScript = `

View File

@@ -16,7 +16,7 @@ The VM handler example shows how to:
To run the example: To run the example:
```bash ```bash
cd ~/code/github/freeflowuniverse/heroagent/pkg/handlerfactory/cmd/vmhandler cd ~/code/github/freeflowuniverse/herocode/heroagent/pkg/handlerfactory/cmd/vmhandler
go run . tutorial go run . tutorial
#to run just the server do #to run just the server do
go run . go run .

View File

@@ -6,7 +6,7 @@ import (
"os" "os"
"time" "time"
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory" "git.threefold.info/herocode/heroagent/pkg/handlerfactory"
) )
// runTutorial runs an interactive tutorial demonstrating the VM handler // runTutorial runs an interactive tutorial demonstrating the VM handler
@@ -50,7 +50,7 @@ func runTutorial() {
// Process heroscript commands // Process heroscript commands
fmt.Println("\nStep 5: Process heroscript commands") fmt.Println("\nStep 5: Process heroscript commands")
// Define a VM // Define a VM
defineScript := `!!vm.define name:'tutorial_vm' cpu:2 memory:'4GB' storage:'50GB' defineScript := `!!vm.define name:'tutorial_vm' cpu:2 memory:'4GB' storage:'50GB'
description: 'A tutorial VM for demonstration purposes'` description: 'A tutorial VM for demonstration purposes'`

View File

@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory" "git.threefold.info/herocode/heroagent/pkg/handlerfactory"
) )
// VMHandler handles VM-related actions // VMHandler handles VM-related actions

View File

@@ -8,7 +8,7 @@ import (
"path/filepath" "path/filepath"
"syscall" "syscall"
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory" "git.threefold.info/herocode/heroagent/pkg/handlerfactory"
) )
// The tutorial functions are defined in tutorial.go // The tutorial functions are defined in tutorial.go

View File

@@ -30,7 +30,7 @@ The Handler Factory exposes two interfaces for communication:
to get started to get started
```bash ```bash
cd /root/code/github/freeflowuniverse/heroagent/pkg/handlerfactory/herohandler/cmd cd /root/code/github/freeflowuniverse/herocode/heroagent/pkg/handlerfactory/herohandler/cmd
go run . go run .
``` ```

View File

@@ -5,8 +5,8 @@ import (
"reflect" "reflect"
"strings" "strings"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/paramsparser" "git.threefold.info/herocode/heroagent/pkg/heroscript/paramsparser"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook" "git.threefold.info/herocode/heroagent/pkg/heroscript/playbook"
) )
// Handler interface defines methods that all handlers must implement // Handler interface defines methods that all handlers must implement

View File

@@ -5,7 +5,7 @@ import (
"reflect" "reflect"
"strings" "strings"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook" "git.threefold.info/herocode/heroagent/pkg/heroscript/playbook"
) )
// HandlerFactory manages a collection of handlers // HandlerFactory manages a collection of handlers

View File

@@ -12,7 +12,7 @@ import (
"sync" "sync"
"syscall" "syscall"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook" "git.threefold.info/herocode/heroagent/pkg/heroscript/playbook"
) )
// ANSI color codes for terminal output // ANSI color codes for terminal output
@@ -43,23 +43,23 @@ type TelnetServer struct {
sigCh chan os.Signal sigCh chan os.Signal
onShutdown func() onShutdown func()
// Map to store client preferences (like json formatting) // Map to store client preferences (like json formatting)
clientPrefs map[net.Conn]map[string]bool clientPrefs map[net.Conn]map[string]bool
prefsMutex sync.RWMutex prefsMutex sync.RWMutex
} }
// NewTelnetServer creates a new telnet server // NewTelnetServer creates a new telnet server
func NewTelnetServer(factory *HandlerFactory, secrets ...string) *TelnetServer { func NewTelnetServer(factory *HandlerFactory, secrets ...string) *TelnetServer {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
return &TelnetServer{ return &TelnetServer{
factory: factory, factory: factory,
secrets: secrets, secrets: secrets,
clients: make(map[net.Conn]bool), clients: make(map[net.Conn]bool),
clientPrefs: make(map[net.Conn]map[string]bool), clientPrefs: make(map[net.Conn]map[string]bool),
running: false, running: false,
ctx: ctx, ctx: ctx,
cancel: cancel, cancel: cancel,
sigCh: make(chan os.Signal, 1), sigCh: make(chan os.Signal, 1),
onShutdown: func() {}, onShutdown: func() {},
} }
} }
@@ -205,7 +205,7 @@ func (ts *TelnetServer) handleConnection(conn net.Conn) {
ts.clientsMutex.Lock() ts.clientsMutex.Lock()
ts.clients[conn] = false ts.clients[conn] = false
ts.clientsMutex.Unlock() ts.clientsMutex.Unlock()
// Initialize client preferences // Initialize client preferences
ts.prefsMutex.Lock() ts.prefsMutex.Lock()
ts.clientPrefs[conn] = make(map[string]bool) ts.clientPrefs[conn] = make(map[string]bool)
@@ -284,7 +284,7 @@ func (ts *TelnetServer) handleConnection(conn net.Conn) {
} }
continue continue
} }
// Handle JSON format toggle // Handle JSON format toggle
if line == "!!json" { if line == "!!json" {
ts.prefsMutex.Lock() ts.prefsMutex.Lock()
@@ -293,12 +293,12 @@ func (ts *TelnetServer) handleConnection(conn net.Conn) {
prefs = make(map[string]bool) prefs = make(map[string]bool)
ts.clientPrefs[conn] = prefs ts.clientPrefs[conn] = prefs
} }
// Toggle JSON format preference // Toggle JSON format preference
currentSetting := prefs["json"] currentSetting := prefs["json"]
prefs["json"] = !currentSetting prefs["json"] = !currentSetting
ts.prefsMutex.Unlock() ts.prefsMutex.Unlock()
if prefs["json"] { if prefs["json"] {
conn.Write([]byte("JSON format will be automatically added to all heroscripts.\n")) conn.Write([]byte("JSON format will be automatically added to all heroscripts.\n"))
} else { } else {
@@ -416,7 +416,7 @@ func (ts *TelnetServer) executeHeroscript(script string, conn net.Conn, interact
ts.prefsMutex.RLock() ts.prefsMutex.RLock()
prefs, exists := ts.clientPrefs[conn] prefs, exists := ts.clientPrefs[conn]
ts.prefsMutex.RUnlock() ts.prefsMutex.RUnlock()
if exists && prefs["json"] { if exists && prefs["json"] {
// Add format:json if not already present // Add format:json if not already present
if !strings.Contains(script, "format:json") { if !strings.Contains(script, "format:json") {
@@ -424,7 +424,7 @@ func (ts *TelnetServer) executeHeroscript(script string, conn net.Conn, interact
} }
} }
} }
if interactive { if interactive {
// Format the script with colors // Format the script with colors
formattedScript := formatHeroscript(script) formattedScript := formatHeroscript(script)
@@ -466,8 +466,6 @@ func (ts *TelnetServer) addJsonFormat(script string) string {
return strings.Join(lines, "\n") return strings.Join(lines, "\n")
} }
// formatHeroscript formats heroscript with colors for console output only // formatHeroscript formats heroscript with colors for console output only
// This is not used for telnet responses, only for server-side logging // This is not used for telnet responses, only for server-side logging
func formatHeroscript(script string) string { func formatHeroscript(script string) string {
@@ -611,12 +609,12 @@ func (ts *TelnetServer) generateHelpText(interactive bool) string {
// Try to call the Help method on each handler using reflection // Try to call the Help method on each handler using reflection
handlerValue := reflect.ValueOf(handler) handlerValue := reflect.ValueOf(handler)
helpMethod := handlerValue.MethodByName("Help") helpMethod := handlerValue.MethodByName("Help")
if helpMethod.IsValid() { if helpMethod.IsValid() {
// Call the Help method // Call the Help method
args := []reflect.Value{reflect.ValueOf("")} args := []reflect.Value{reflect.ValueOf("")}
result := helpMethod.Call(args) result := helpMethod.Call(args)
// Get the result // Get the result
if len(result) > 0 && result[0].Kind() == reflect.String { if len(result) > 0 && result[0].Kind() == reflect.String {
helpText := result[0].String() helpText := result[0].String()

View File

@@ -3,7 +3,7 @@ package handlers
import ( import (
"fmt" "fmt"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core" "git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/core"
) )
// AuthHandler handles authentication actions // AuthHandler handles authentication actions

View File

@@ -5,9 +5,9 @@ import (
"reflect" "reflect"
"strings" "strings"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core" "git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/core"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/paramsparser" "git.threefold.info/herocode/heroagent/pkg/heroscript/paramsparser"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook" "git.threefold.info/herocode/heroagent/pkg/heroscript/playbook"
) )
// BaseHandler provides common functionality for all handlers // BaseHandler provides common functionality for all handlers

View File

@@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core" "git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/core"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook" "git.threefold.info/herocode/heroagent/pkg/heroscript/playbook"
) )
// HandlerFactory manages a collection of handlers for processing HeroScript commands // HandlerFactory manages a collection of handlers for processing HeroScript commands

View File

@@ -1,7 +1,7 @@
package herohandler package herohandler
import ( import (
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core" "git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/core"
) )
// GetFactory returns the handler factory // GetFactory returns the handler factory

View File

@@ -4,7 +4,7 @@ import (
"log" "log"
"sync" "sync"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/herohandler" "git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/herohandler"
) )
func main() { func main() {

View File

@@ -4,10 +4,10 @@ import (
"fmt" "fmt"
"log" "log"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core" "git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/core"
// "github.com/freeflowuniverse/heroagent/pkg/handlerfactory/heroscript/handlerfactory/fakehandler" // "git.threefold.info/herocode/heroagent/pkg/handlerfactory/heroscript/handlerfactory/fakehandler"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/processmanagerhandler" "git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/processmanagerhandler"
) )
// HeroHandler is the main handler factory that manages all registered handlers // HeroHandler is the main handler factory that manages all registered handlers

View File

@@ -3,7 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook" "git.threefold.info/herocode/heroagent/pkg/heroscript/playbook"
) )
func main() { func main() {

View File

@@ -3,8 +3,8 @@ package processmanagerhandler
import ( import (
"fmt" "fmt"
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core" "git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/core"
"github.com/freeflowuniverse/heroagent/pkg/processmanager" "git.threefold.info/herocode/heroagent/pkg/processmanager"
) )
// ProcessManagerHandler handles process manager-related actions // ProcessManagerHandler handles process manager-related actions

Some files were not shown because too many files have changed in this diff Show More