Compare commits
3 Commits
2ee8a95a90
...
main
Author | SHA1 | Date | |
---|---|---|---|
4a79011793 | |||
0b62ac9ecd | |||
c9b14730ad |
@@ -11,7 +11,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/mycelium_client"
|
"git.threefold.info/herocode/heroagent/pkg/mycelium_client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
|
@@ -8,7 +8,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/mycelium_client"
|
"git.threefold.info/herocode/heroagent/pkg/mycelium_client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
"git.threefold.info/herocode/heroagent/pkg/system/stats"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@ package api
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/sal/executor"
|
"git.threefold.info/herocode/heroagent/pkg/sal/executor"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
@@ -7,9 +7,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager"
|
"git.threefold.info/herocode/heroagent/pkg/processmanager"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces"
|
"git.threefold.info/herocode/heroagent/pkg/processmanager/interfaces"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces/openrpc"
|
"git.threefold.info/herocode/heroagent/pkg/processmanager/interfaces/openrpc"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -12,16 +12,16 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroagent/api"
|
"git.threefold.info/herocode/heroagent/pkg/heroagent/api"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroagent/handlers"
|
"git.threefold.info/herocode/heroagent/pkg/heroagent/handlers"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroagent/pages"
|
"git.threefold.info/herocode/heroagent/pkg/heroagent/pages"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager"
|
"git.threefold.info/herocode/heroagent/pkg/processmanager"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/sal/executor"
|
"git.threefold.info/herocode/heroagent/pkg/sal/executor"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/redisserver"
|
"git.threefold.info/herocode/heroagent/pkg/servers/redisserver"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
"git.threefold.info/herocode/heroagent/pkg/system/stats"
|
||||||
|
|
||||||
// "git.ourworld.tf/herocode/heroagent/pkg/vfs/interfaces"
|
// "git.threefold.info/herocode/heroagent/pkg/vfs/interfaces"
|
||||||
// "git.ourworld.tf/herocode/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"
|
||||||
|
@@ -5,7 +5,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"strconv" // Added strconv for JobID parsing
|
"strconv" // Added strconv for JobID parsing
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/herojobs"
|
"git.threefold.info/herocode/heroagent/pkg/herojobs"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@ import (
|
|||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/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"
|
||||||
|
@@ -7,7 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/logger"
|
"git.threefold.info/herocode/heroagent/pkg/logger"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
"git.threefold.info/herocode/heroagent/pkg/system/stats"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces"
|
"git.threefold.info/herocode/heroagent/pkg/processmanager/interfaces"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces/openrpc"
|
"git.threefold.info/herocode/heroagent/pkg/processmanager/interfaces/openrpc"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/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"
|
||||||
)
|
)
|
||||||
|
@@ -7,8 +7,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroagent/handlers"
|
"git.threefold.info/herocode/heroagent/pkg/heroagent/handlers"
|
||||||
"git.ourworld.tf/herocode/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"
|
||||||
)
|
)
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/herojobs"
|
"git.threefold.info/herocode/heroagent/pkg/herojobs"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces/openrpc"
|
"git.threefold.info/herocode/heroagent/pkg/processmanager/interfaces/openrpc"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/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
|
||||||
|
@@ -35,7 +35,7 @@ Key features:
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.ourworld.tf/herocode/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
|
||||||
|
@@ -7,7 +7,7 @@ import (
|
|||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory/herohandler"
|
"git.threefold.info/herocode/heroagent/pkg/handlerfactory/herohandler"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -8,7 +8,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/playbook"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -3,8 +3,8 @@ package internal
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory"
|
"git.threefold.info/herocode/heroagent/pkg/handlerfactory"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlers"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/handlers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExampleHandler handles example actions
|
// ExampleHandler handles example actions
|
||||||
|
@@ -7,7 +7,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/cmd/herohandler/internal"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/cmd/herohandler/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -10,7 +10,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory/herohandler"
|
"git.threefold.info/herocode/heroagent/pkg/handlerfactory/herohandler"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/playbook"
|
||||||
)
|
)
|
||||||
|
|
||||||
const exampleScript = `
|
const exampleScript = `
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/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
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory"
|
"git.threefold.info/herocode/heroagent/pkg/handlerfactory"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VMHandler handles VM-related actions
|
// VMHandler handles VM-related actions
|
||||||
|
@@ -8,7 +8,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/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
|
||||||
|
@@ -5,8 +5,8 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||||
"git.ourworld.tf/herocode/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
|
||||||
|
@@ -5,7 +5,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/playbook"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HandlerFactory manages a collection of handlers
|
// HandlerFactory manages a collection of handlers
|
||||||
|
@@ -12,7 +12,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/playbook"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ANSI color codes for terminal output
|
// ANSI color codes for terminal output
|
||||||
|
@@ -3,7 +3,7 @@ package handlers
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AuthHandler handles authentication actions
|
// AuthHandler handles authentication actions
|
||||||
|
@@ -5,9 +5,9 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||||
"git.ourworld.tf/herocode/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
|
||||||
|
@@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||||
"git.ourworld.tf/herocode/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
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package herohandler
|
package herohandler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetFactory returns the handler factory
|
// GetFactory returns the handler factory
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/herohandler"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/herohandler"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -4,10 +4,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||||
|
|
||||||
// "git.ourworld.tf/herocode/heroagent/pkg/handlerfactory/heroscript/handlerfactory/fakehandler"
|
// "git.threefold.info/herocode/heroagent/pkg/handlerfactory/heroscript/handlerfactory/fakehandler"
|
||||||
"git.ourworld.tf/herocode/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
|
||||||
|
@@ -3,7 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/playbook"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -3,8 +3,8 @@ package processmanagerhandler
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager"
|
"git.threefold.info/herocode/heroagent/pkg/processmanager"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProcessManagerHandler handles process manager-related actions
|
// ProcessManagerHandler handles process manager-related actions
|
||||||
|
@@ -19,7 +19,7 @@ A Go package for parsing and manipulating parameters from text in a key-value fo
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/paramsparser"
|
"git.threefold.info/herocode/heroagent/pkg/paramsparser"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create a new parser
|
// Create a new parser
|
||||||
|
@@ -4,7 +4,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -9,7 +9,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
"git.threefold.info/herocode/heroagent/pkg/tools"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParamsParser represents a parameter parser that can handle various parameter sources
|
// ParamsParser represents a parameter parser that can handle various parameter sources
|
||||||
|
@@ -3,8 +3,8 @@ package playbook
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
"git.threefold.info/herocode/heroagent/pkg/tools"
|
||||||
)
|
)
|
||||||
|
|
||||||
// State represents the parser state
|
// State represents the parser state
|
||||||
|
@@ -7,7 +7,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
"git.threefold.info/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ActionType represents the type of action
|
// ActionType represents the type of action
|
||||||
|
@@ -11,7 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/heroservices/billing/models"
|
"git.threefold.info/herocode/heroagent/pkg/heroservices/billing/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@@ -7,9 +7,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/data/ourdb"
|
"git.threefold.info/herocode/heroagent/pkg/data/ourdb"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/data/radixtree"
|
"git.threefold.info/herocode/heroagent/pkg/data/radixtree"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
"git.threefold.info/herocode/heroagent/pkg/tools"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DBStore represents the central database store for all models
|
// DBStore represents the central database store for all models
|
||||||
|
@@ -9,7 +9,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
openaiproxy "git.ourworld.tf/herocode/heroagent/pkg/heroservices/openaiproxy"
|
openaiproxy "git.threefold.info/herocode/heroagent/pkg/heroservices/openaiproxy"
|
||||||
"github.com/openai/openai-go/option"
|
"github.com/openai/openai-go/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/jobsmanager"
|
"git.threefold.info/herocode/heroagent/pkg/jobsmanager"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||||
)
|
)
|
||||||
|
@@ -7,7 +7,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/heroagent"
|
"git.threefold.info/herocode/heroagent/pkg/servers/heroagent"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -8,7 +8,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/heroagent"
|
"git.threefold.info/herocode/heroagent/pkg/servers/heroagent"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/openrpc"
|
"git.threefold.info/herocode/heroagent/pkg/openrpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
2
go.mod
2
go.mod
@@ -1,4 +1,4 @@
|
|||||||
module git.ourworld.tf/herocode/heroagent
|
module git.threefold.info/herocode/heroagent
|
||||||
|
|
||||||
go 1.23.0
|
go 1.23.0
|
||||||
|
|
||||||
|
@@ -14,7 +14,7 @@ Dedupestor is a Go package that provides a key-value store with deduplication ba
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/dedupestor"
|
"git.threefold.info/herocode/heroagent/pkg/dedupestor"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create a new dedupe store
|
// Create a new dedupe store
|
||||||
|
@@ -7,8 +7,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/data/ourdb"
|
"git.threefold.info/herocode/heroagent/pkg/data/ourdb"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/data/radixtree"
|
"git.threefold.info/herocode/heroagent/pkg/data/radixtree"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MaxValueSize is the maximum allowed size for values (1MB)
|
// MaxValueSize is the maximum allowed size for values (1MB)
|
||||||
|
@@ -18,7 +18,7 @@ The DocTree package provides functionality for managing collections of markdown
|
|||||||
### Creating a DocTree
|
### Creating a DocTree
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "git.ourworld.tf/herocode/heroagent/pkg/doctree"
|
import "git.threefold.info/herocode/heroagent/pkg/doctree"
|
||||||
|
|
||||||
// Create a new DocTree with a path and name
|
// Create a new DocTree with a path and name
|
||||||
dt, err := doctree.New("/path/to/collection", "My Collection")
|
dt, err := doctree.New("/path/to/collection", "My Collection")
|
||||||
|
@@ -7,7 +7,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
"git.threefold.info/herocode/heroagent/pkg/tools"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Collection represents a collection of markdown pages and files
|
// Collection represents a collection of markdown pages and files
|
||||||
|
@@ -5,7 +5,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
"git.threefold.info/herocode/heroagent/pkg/tools"
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
"github.com/yuin/goldmark"
|
"github.com/yuin/goldmark"
|
||||||
"github.com/yuin/goldmark/extension"
|
"github.com/yuin/goldmark/extension"
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
"git.threefold.info/herocode/heroagent/pkg/tools"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Global variable to track the current DocTree instance
|
// Global variable to track the current DocTree instance
|
||||||
|
@@ -34,7 +34,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/ourdb"
|
"git.threefold.info/herocode/heroagent/pkg/ourdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -78,7 +78,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/ourdb"
|
"git.threefold.info/herocode/heroagent/pkg/ourdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -4,7 +4,7 @@ package radixtree
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/data/ourdb"
|
"git.threefold.info/herocode/heroagent/pkg/data/ourdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Node represents a node in the radix tree
|
// Node represents a node in the radix tree
|
||||||
|
@@ -7,8 +7,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/data/ourdb"
|
"git.threefold.info/herocode/heroagent/pkg/data/ourdb"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
"git.threefold.info/herocode/heroagent/pkg/tools"
|
||||||
)
|
)
|
||||||
|
|
||||||
// JobStatus represents the status of a job
|
// JobStatus represents the status of a job
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
"git.threefold.info/herocode/heroagent/pkg/tools"
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/logger"
|
"git.threefold.info/herocode/heroagent/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -7,7 +7,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/openrpc/models"
|
"git.threefold.info/herocode/heroagent/pkg/openrpc/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ORPCManager manages OpenRPC specifications
|
// ORPCManager manages OpenRPC specifications
|
||||||
|
@@ -3,8 +3,8 @@ package heroagent
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/ui"
|
"git.threefold.info/herocode/heroagent/pkg/servers/ui"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/webdavserver"
|
"git.threefold.info/herocode/heroagent/pkg/servers/webdavserver"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config holds the configuration for the HeroAgent server factory
|
// Config holds the configuration for the HeroAgent server factory
|
||||||
|
@@ -5,9 +5,9 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/redisserver"
|
"git.threefold.info/herocode/heroagent/pkg/servers/redisserver"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/ui"
|
"git.threefold.info/herocode/heroagent/pkg/servers/ui"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/webdavserver"
|
"git.threefold.info/herocode/heroagent/pkg/servers/webdavserver"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/data/ourdb"
|
"git.threefold.info/herocode/heroagent/pkg/data/ourdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// JobManager handles job management between OurDB and Redis
|
// JobManager handles job management between OurDB and Redis
|
||||||
|
@@ -24,7 +24,7 @@ The server implements the following Redis commands:
|
|||||||
### Basic Usage
|
### Basic Usage
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "git.ourworld.tf/herocode/heroagent/pkg/redisserver"
|
import "git.threefold.info/herocode/heroagent/pkg/redisserver"
|
||||||
|
|
||||||
// Create a new server with default configuration
|
// Create a new server with default configuration
|
||||||
server := redisserver.NewServer(redisserver.ServerConfig{
|
server := redisserver.NewServer(redisserver.ServerConfig{
|
||||||
|
@@ -11,7 +11,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/redisserver"
|
"git.threefold.info/herocode/heroagent/pkg/servers/redisserver"
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/redisserver"
|
"git.threefold.info/herocode/heroagent/pkg/servers/redisserver"
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/ui/routes" // Import the routes package
|
"git.threefold.info/herocode/heroagent/pkg/servers/ui/routes" // Import the routes package
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
jetadapter "github.com/gofiber/template/jet/v2" // Aliased for clarity
|
jetadapter "github.com/gofiber/template/jet/v2" // Aliased for clarity
|
||||||
)
|
)
|
||||||
|
@@ -4,8 +4,8 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/herojobs"
|
"git.threefold.info/herocode/heroagent/pkg/herojobs"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/ui/models"
|
"git.threefold.info/herocode/heroagent/pkg/servers/ui/models"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/ui/models"
|
"git.threefold.info/herocode/heroagent/pkg/servers/ui/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
// JobPageData represents the data needed for the jobs page
|
// JobPageData represents the data needed for the jobs page
|
||||||
|
173
pkg/servers/ui/controllers/openrpc_controller.go
Normal file
173
pkg/servers/ui/controllers/openrpc_controller.go
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
orpcmodels "git.threefold.info/herocode/heroagent/pkg/openrpc/models"
|
||||||
|
uimodels "git.threefold.info/herocode/heroagent/pkg/servers/ui/models"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OpenRPCController handles requests related to OpenRPC specifications
|
||||||
|
type OpenRPCController struct {
|
||||||
|
openrpcManager uimodels.OpenRPCUIManager
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOpenRPCController creates a new instance of OpenRPCController
|
||||||
|
func NewOpenRPCController(openrpcManager uimodels.OpenRPCUIManager) *OpenRPCController {
|
||||||
|
return &OpenRPCController{
|
||||||
|
openrpcManager: openrpcManager,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenRPCPageData represents the data needed for the OpenRPC UI pages
|
||||||
|
type OpenRPCPageData struct {
|
||||||
|
Title string
|
||||||
|
Specs []string
|
||||||
|
SelectedSpec string
|
||||||
|
Methods []string
|
||||||
|
SelectedMethod string
|
||||||
|
Method *orpcmodels.Method
|
||||||
|
SocketPath string
|
||||||
|
ExampleParams string
|
||||||
|
Result string
|
||||||
|
Error string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShowOpenRPCUI renders the OpenRPC UI page
|
||||||
|
func (c *OpenRPCController) ShowOpenRPCUI(ctx *fiber.Ctx) error {
|
||||||
|
// Get query parameters
|
||||||
|
selectedSpec := ctx.Query("spec", "")
|
||||||
|
selectedMethod := ctx.Query("method", "")
|
||||||
|
socketPath := ctx.Query("socketPath", "")
|
||||||
|
|
||||||
|
// Get all specs
|
||||||
|
specs := c.openrpcManager.ListSpecs()
|
||||||
|
|
||||||
|
// Initialize page data using fiber.Map instead of struct
|
||||||
|
pageData := fiber.Map{
|
||||||
|
"Title": "OpenRPC UI",
|
||||||
|
"SpecList": specs,
|
||||||
|
"SelectedSpec": selectedSpec,
|
||||||
|
"SocketPath": socketPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a spec is selected, get its methods
|
||||||
|
if selectedSpec != "" {
|
||||||
|
methods := c.openrpcManager.ListMethods(selectedSpec)
|
||||||
|
pageData["Methods"] = methods
|
||||||
|
pageData["SelectedMethod"] = selectedMethod
|
||||||
|
|
||||||
|
// If a method is selected, get its details
|
||||||
|
if selectedMethod != "" {
|
||||||
|
method := c.openrpcManager.GetMethod(selectedSpec, selectedMethod)
|
||||||
|
if method != nil {
|
||||||
|
pageData["Method"] = method
|
||||||
|
|
||||||
|
// Generate example parameters if available
|
||||||
|
if len(method.Examples) > 0 {
|
||||||
|
exampleParams, err := json.MarshalIndent(method.Examples[0].Params, "", " ")
|
||||||
|
if err == nil {
|
||||||
|
pageData["ExampleParams"] = string(exampleParams)
|
||||||
|
}
|
||||||
|
} else if len(method.Params) > 0 {
|
||||||
|
// Generate example from parameter schema
|
||||||
|
exampleParams := generateExampleParams(method.Params)
|
||||||
|
jsonParams, err := json.MarshalIndent(exampleParams, "", " ")
|
||||||
|
if err == nil {
|
||||||
|
pageData["ExampleParams"] = string(jsonParams)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.Render("pages/rpcui", pageData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExecuteRPC handles RPC execution requests
|
||||||
|
func (c *OpenRPCController) ExecuteRPC(ctx *fiber.Ctx) error {
|
||||||
|
// Parse request
|
||||||
|
var request struct {
|
||||||
|
Spec string `json:"spec"`
|
||||||
|
Method string `json:"method"`
|
||||||
|
SocketPath string `json:"socketPath"`
|
||||||
|
Params json.RawMessage `json:"params"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.BodyParser(&request); err != nil {
|
||||||
|
return ctx.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||||
|
"error": "Invalid request: " + err.Error(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate request
|
||||||
|
if request.Spec == "" || request.Method == "" || request.SocketPath == "" {
|
||||||
|
return ctx.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||||
|
"error": "Missing required fields: spec, method, or socketPath",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse params
|
||||||
|
var params interface{}
|
||||||
|
if len(request.Params) > 0 {
|
||||||
|
if err := json.Unmarshal(request.Params, ¶ms); err != nil {
|
||||||
|
return ctx.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||||
|
"error": "Invalid parameters: " + err.Error(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute RPC
|
||||||
|
result, err := c.openrpcManager.ExecuteRPC(request.Spec, request.Method, request.SocketPath, params)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error executing RPC: %v", err)
|
||||||
|
return ctx.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return result
|
||||||
|
return ctx.JSON(fiber.Map{
|
||||||
|
"result": result,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateExampleParams generates example parameters from parameter schemas
|
||||||
|
func generateExampleParams(params []orpcmodels.Parameter) map[string]interface{} {
|
||||||
|
example := make(map[string]interface{})
|
||||||
|
|
||||||
|
for _, param := range params {
|
||||||
|
example[param.Name] = generateExampleValue(param.Schema)
|
||||||
|
}
|
||||||
|
|
||||||
|
return example
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateExampleValue generates an example value from a schema
|
||||||
|
func generateExampleValue(schema orpcmodels.SchemaObject) interface{} {
|
||||||
|
switch schema.Type {
|
||||||
|
case "string":
|
||||||
|
return "example"
|
||||||
|
case "number":
|
||||||
|
return 0
|
||||||
|
case "integer":
|
||||||
|
return 0
|
||||||
|
case "boolean":
|
||||||
|
return false
|
||||||
|
case "array":
|
||||||
|
if schema.Items != nil {
|
||||||
|
return []interface{}{generateExampleValue(*schema.Items)}
|
||||||
|
}
|
||||||
|
return []interface{}{}
|
||||||
|
case "object":
|
||||||
|
obj := make(map[string]interface{})
|
||||||
|
for name, propSchema := range schema.Properties {
|
||||||
|
obj[name] = generateExampleValue(propSchema)
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/ui/models"
|
"git.threefold.info/herocode/heroagent/pkg/servers/ui/models"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/herojobs"
|
"git.threefold.info/herocode/heroagent/pkg/herojobs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// JobManager provides an interface for job management operations
|
// JobManager provides an interface for job management operations
|
||||||
|
190
pkg/servers/ui/models/openrpc_manager.go
Normal file
190
pkg/servers/ui/models/openrpc_manager.go
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.threefold.info/herocode/heroagent/pkg/openrpc"
|
||||||
|
"git.threefold.info/herocode/heroagent/pkg/openrpc/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OpenRPCUIManager is the interface for managing OpenRPC specifications in the UI
|
||||||
|
type OpenRPCUIManager interface {
|
||||||
|
// ListSpecs returns a list of all loaded specification names
|
||||||
|
ListSpecs() []string
|
||||||
|
|
||||||
|
// GetSpec returns an OpenRPC specification by name
|
||||||
|
GetSpec(name string) *models.OpenRPCSpec
|
||||||
|
|
||||||
|
// ListMethods returns a list of all method names in a specification
|
||||||
|
ListMethods(specName string) []string
|
||||||
|
|
||||||
|
// GetMethod returns a method from a specification
|
||||||
|
GetMethod(specName, methodName string) *models.Method
|
||||||
|
|
||||||
|
// ExecuteRPC executes an RPC call
|
||||||
|
ExecuteRPC(specName, methodName, socketPath string, params interface{}) (interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenRPCManager implements the OpenRPCUIManager interface
|
||||||
|
type OpenRPCManager struct {
|
||||||
|
manager *openrpc.ORPCManager
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOpenRPCManager creates a new OpenRPCUIManager
|
||||||
|
func NewOpenRPCManager() OpenRPCUIManager {
|
||||||
|
manager := openrpc.NewORPCManager()
|
||||||
|
|
||||||
|
// Try to load specs from the default directory
|
||||||
|
specDirs := []string{
|
||||||
|
"./pkg/openrpc/services",
|
||||||
|
"./pkg/openrpc/specs",
|
||||||
|
"./specs/openrpc",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dir := range specDirs {
|
||||||
|
err := manager.LoadSpecs(dir)
|
||||||
|
if err == nil {
|
||||||
|
// Successfully loaded specs from this directory
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OpenRPCManager{
|
||||||
|
manager: manager,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListSpecs returns a list of all loaded specification names
|
||||||
|
func (m *OpenRPCManager) ListSpecs() []string {
|
||||||
|
return m.manager.ListSpecs()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSpec returns an OpenRPC specification by name
|
||||||
|
func (m *OpenRPCManager) GetSpec(name string) *models.OpenRPCSpec {
|
||||||
|
return m.manager.GetSpec(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMethods returns a list of all method names in a specification
|
||||||
|
func (m *OpenRPCManager) ListMethods(specName string) []string {
|
||||||
|
return m.manager.ListMethods(specName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMethod returns a method from a specification
|
||||||
|
func (m *OpenRPCManager) GetMethod(specName, methodName string) *models.Method {
|
||||||
|
return m.manager.GetMethod(specName, methodName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExecuteRPC executes an RPC call
|
||||||
|
func (m *OpenRPCManager) ExecuteRPC(specName, methodName, socketPath string, params interface{}) (interface{}, error) {
|
||||||
|
// Create JSON-RPC request
|
||||||
|
request := map[string]interface{}{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": methodName,
|
||||||
|
"params": params,
|
||||||
|
"id": 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal request to JSON
|
||||||
|
requestJSON, err := json.Marshal(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to marshal request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if socket path is a Unix socket or HTTP endpoint
|
||||||
|
if socketPath[:1] == "/" {
|
||||||
|
// Unix socket
|
||||||
|
return executeUnixSocketRPC(socketPath, requestJSON)
|
||||||
|
} else {
|
||||||
|
// HTTP endpoint
|
||||||
|
return executeHTTPRPC(socketPath, requestJSON)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// executeUnixSocketRPC executes an RPC call over a Unix socket
|
||||||
|
func executeUnixSocketRPC(socketPath string, requestJSON []byte) (interface{}, error) {
|
||||||
|
// Connect to Unix socket
|
||||||
|
conn, err := net.Dial("unix", socketPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to connect to socket %s: %w", socketPath, err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
// Set timeout
|
||||||
|
deadline := time.Now().Add(10 * time.Second)
|
||||||
|
if err := conn.SetDeadline(deadline); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to set deadline: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request
|
||||||
|
if _, err := conn.Write(requestJSON); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to send request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read response
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if _, err := buf.ReadFrom(conn); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse response
|
||||||
|
var response map[string]interface{}
|
||||||
|
if err := json.Unmarshal(buf.Bytes(), &response); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for error
|
||||||
|
if errObj, ok := response["error"]; ok {
|
||||||
|
return nil, fmt.Errorf("RPC error: %v", errObj)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return result
|
||||||
|
return response["result"], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// executeHTTPRPC executes an RPC call over HTTP
|
||||||
|
func executeHTTPRPC(endpoint string, requestJSON []byte) (interface{}, error) {
|
||||||
|
// Create HTTP request
|
||||||
|
req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(requestJSON))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create HTTP request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set headers
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
// Create HTTP client with timeout
|
||||||
|
client := &http.Client{
|
||||||
|
Timeout: 10 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to send HTTP request: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// Check status code
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("HTTP error: %s", resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse response
|
||||||
|
var response map[string]interface{}
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for error
|
||||||
|
if errObj, ok := response["error"]; ok {
|
||||||
|
return nil, fmt.Errorf("RPC error: %v", errObj)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return result
|
||||||
|
return response["result"], nil
|
||||||
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
package routes
|
package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/ui/controllers"
|
"git.threefold.info/herocode/heroagent/pkg/servers/ui/controllers"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/ui/models"
|
"git.threefold.info/herocode/heroagent/pkg/servers/ui/models"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -12,11 +12,13 @@ func SetupRoutes(app *fiber.App) {
|
|||||||
// For now, using the mock process manager
|
// For now, using the mock process manager
|
||||||
processManagerService := models.NewMockProcessManager()
|
processManagerService := models.NewMockProcessManager()
|
||||||
jobManagerService := models.NewMockJobManager()
|
jobManagerService := models.NewMockJobManager()
|
||||||
|
openrpcManagerService := models.NewOpenRPCManager()
|
||||||
|
|
||||||
dashboardController := controllers.NewDashboardController()
|
dashboardController := controllers.NewDashboardController()
|
||||||
processController := controllers.NewProcessController(processManagerService)
|
processController := controllers.NewProcessController(processManagerService)
|
||||||
jobController := controllers.NewJobController(jobManagerService)
|
jobController := controllers.NewJobController(jobManagerService)
|
||||||
authController := controllers.NewAuthController()
|
authController := controllers.NewAuthController()
|
||||||
|
openrpcController := controllers.NewOpenRPCController(openrpcManagerService)
|
||||||
|
|
||||||
// --- Public Routes ---
|
// --- Public Routes ---
|
||||||
// Login and Logout
|
// Login and Logout
|
||||||
@@ -43,6 +45,10 @@ func SetupRoutes(app *fiber.App) {
|
|||||||
app.Get("/jobs", jobController.ShowJobsPage)
|
app.Get("/jobs", jobController.ShowJobsPage)
|
||||||
app.Get("/jobs/:id", jobController.ShowJobDetails)
|
app.Get("/jobs/:id", jobController.ShowJobDetails)
|
||||||
|
|
||||||
|
// OpenRPC UI routes
|
||||||
|
app.Get("/rpcui", openrpcController.ShowOpenRPCUI)
|
||||||
|
app.Post("/api/rpcui/execute", openrpcController.ExecuteRPC)
|
||||||
|
|
||||||
// Debug routes
|
// Debug routes
|
||||||
app.Get("/debug", func(c *fiber.Ctx) error {
|
app.Get("/debug", func(c *fiber.Ctx) error {
|
||||||
// Get all data from the jobs page to debug
|
// Get all data from the jobs page to debug
|
||||||
|
144
pkg/servers/ui/static/css/rpcui.css
Normal file
144
pkg/servers/ui/static/css/rpcui.css
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/* OpenRPC UI Styles */
|
||||||
|
|
||||||
|
.method-tree {
|
||||||
|
max-height: 600px;
|
||||||
|
overflow-y: auto;
|
||||||
|
border-right: 1px solid #dee2e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.method-item {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 8px 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.method-item:hover {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.method-item.active {
|
||||||
|
background-color: #e9ecef;
|
||||||
|
font-weight: bold;
|
||||||
|
border-left: 3px solid #0d6efd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.param-card {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-container {
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 15px;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-editor {
|
||||||
|
font-family: 'Courier New', Courier, monospace;
|
||||||
|
min-height: 200px;
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
white-space: pre;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.schema-table {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.schema-table th {
|
||||||
|
font-weight: 600;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.schema-required {
|
||||||
|
color: #dc3545;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.schema-optional {
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.method-description {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #6c757d;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
border-bottom: 1px solid #dee2e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-container {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-header {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-content {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Socket path input styling */
|
||||||
|
.socket-path-container {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.socket-path-label {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Execute button styling */
|
||||||
|
.execute-button {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Response styling */
|
||||||
|
.response-success {
|
||||||
|
border-left: 4px solid #28a745;
|
||||||
|
}
|
||||||
|
|
||||||
|
.response-error {
|
||||||
|
border-left: 4px solid #dc3545;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading indicator */
|
||||||
|
.loading-spinner {
|
||||||
|
display: inline-block;
|
||||||
|
width: 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
border: 0.2em solid currentColor;
|
||||||
|
border-right-color: transparent;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spinner-border .75s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spinner-border {
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
141
pkg/servers/ui/static/js/rpcui.js
Normal file
141
pkg/servers/ui/static/js/rpcui.js
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
/**
|
||||||
|
* OpenRPC UI JavaScript
|
||||||
|
* Handles the interactive functionality of the OpenRPC UI
|
||||||
|
*/
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Initialize form elements
|
||||||
|
const specForm = document.getElementById('specForm');
|
||||||
|
const rpcForm = document.getElementById('rpcForm');
|
||||||
|
const paramsEditor = document.getElementById('paramsEditor');
|
||||||
|
const resultContainer = document.getElementById('resultContainer');
|
||||||
|
const resultOutput = document.getElementById('resultOutput');
|
||||||
|
const errorContainer = document.getElementById('errorContainer');
|
||||||
|
const errorOutput = document.getElementById('errorOutput');
|
||||||
|
|
||||||
|
// Format JSON in the parameters editor
|
||||||
|
if (paramsEditor && paramsEditor.value) {
|
||||||
|
try {
|
||||||
|
const params = JSON.parse(paramsEditor.value);
|
||||||
|
paramsEditor.value = JSON.stringify(params, null, 2);
|
||||||
|
} catch (e) {
|
||||||
|
// If not valid JSON, leave as is
|
||||||
|
console.warn('Could not format parameters as JSON:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle RPC execution
|
||||||
|
if (rpcForm) {
|
||||||
|
rpcForm.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// Hide previous results
|
||||||
|
if (resultContainer) resultContainer.classList.add('d-none');
|
||||||
|
if (errorContainer) errorContainer.classList.add('d-none');
|
||||||
|
|
||||||
|
// Get form data
|
||||||
|
const spec = document.getElementById('spec').value;
|
||||||
|
const method = document.querySelector('input[name="selectedMethod"]').value;
|
||||||
|
const socketPath = document.getElementById('socketPath').value;
|
||||||
|
const paramsText = paramsEditor.value;
|
||||||
|
|
||||||
|
// Show loading indicator
|
||||||
|
const submitButton = rpcForm.querySelector('button[type="submit"]');
|
||||||
|
const originalButtonText = submitButton.innerHTML;
|
||||||
|
submitButton.disabled = true;
|
||||||
|
submitButton.innerHTML = '<span class="loading-spinner me-2"></span>Executing...';
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
if (!spec || !method || !socketPath) {
|
||||||
|
showError('Missing required fields: spec, method, or socketPath');
|
||||||
|
resetButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse params
|
||||||
|
let params;
|
||||||
|
try {
|
||||||
|
params = JSON.parse(paramsText);
|
||||||
|
} catch (e) {
|
||||||
|
showError('Invalid JSON parameters: ' + e.message);
|
||||||
|
resetButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute RPC
|
||||||
|
fetch('/api/rpcui/execute', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
spec: spec,
|
||||||
|
method: method,
|
||||||
|
socketPath: socketPath,
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.error) {
|
||||||
|
showError(data.error);
|
||||||
|
} else {
|
||||||
|
showResult(data.result);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
showError('Request failed: ' + error.message);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
resetButton();
|
||||||
|
});
|
||||||
|
|
||||||
|
function resetButton() {
|
||||||
|
submitButton.disabled = false;
|
||||||
|
submitButton.innerHTML = originalButtonText;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showError(message) {
|
||||||
|
if (errorContainer && errorOutput) {
|
||||||
|
errorContainer.classList.remove('d-none');
|
||||||
|
errorOutput.textContent = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showResult(result) {
|
||||||
|
if (resultContainer && resultOutput) {
|
||||||
|
resultContainer.classList.remove('d-none');
|
||||||
|
resultOutput.textContent = JSON.stringify(result, null, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method tree navigation
|
||||||
|
const methodItems = document.querySelectorAll('.method-item');
|
||||||
|
methodItems.forEach(item => {
|
||||||
|
item.addEventListener('click', function(e) {
|
||||||
|
// Already handled by href, but could add additional functionality here
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Format JSON examples
|
||||||
|
const jsonExamples = document.querySelectorAll('pre code');
|
||||||
|
jsonExamples.forEach(example => {
|
||||||
|
try {
|
||||||
|
const content = example.textContent;
|
||||||
|
const json = JSON.parse(content);
|
||||||
|
example.textContent = JSON.stringify(json, null, 2);
|
||||||
|
} catch (e) {
|
||||||
|
// If not valid JSON, leave as is
|
||||||
|
console.warn('Could not format example as JSON:', e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add syntax highlighting if a library like highlight.js is available
|
||||||
|
if (typeof hljs !== 'undefined') {
|
||||||
|
document.querySelectorAll('pre code').forEach((block) => {
|
||||||
|
hljs.highlightBlock(block);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
@@ -18,6 +18,12 @@
|
|||||||
Job Manager
|
Job Manager
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/rpcui">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-code"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>
|
||||||
|
OpenRPC UI
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<!-- Add more menu items here as needed -->
|
<!-- Add more menu items here as needed -->
|
||||||
</ul>
|
</ul>
|
||||||
{{ end }}
|
{{ end }}
|
157
pkg/servers/ui/views/pages/rpcui.jet
Normal file
157
pkg/servers/ui/views/pages/rpcui.jet
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
{{extends "../layouts/base"}}
|
||||||
|
|
||||||
|
{{block title()}}
|
||||||
|
OpenRPC UI
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{block css()}}
|
||||||
|
<link rel="stylesheet" href="/static/css/rpcui.css">
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{block body()}}
|
||||||
|
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||||
|
<h1 class="h2">OpenRPC UI</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-4">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h5>Select OpenRPC Specification</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form id="specForm" action="/rpcui" method="get" class="row g-3">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="spec" class="form-label">Specification</label>
|
||||||
|
<select class="form-select" id="spec" name="spec" onchange="this.form.submit()">
|
||||||
|
<option value="">Select a specification</option>
|
||||||
|
{{ if SpecList }}
|
||||||
|
{{ range spec := SpecList }}
|
||||||
|
<option value="{{ spec }}" >
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
<option value="" disabled>No specifications available</option>
|
||||||
|
{{ end }}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="socketPath" class="form-label">Socket Path</label>
|
||||||
|
<input type="text" class="form-control" id="socketPath" name="socketPath" value="{{ SocketPath }}" placeholder="e.g., /tmp/rpc.sock">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 d-flex align-items-end">
|
||||||
|
<button type="submit" class="btn btn-primary">Apply</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="alert alert-info">
|
||||||
|
<p>This is the OpenRPC UI page. It allows you to interact with OpenRPC specifications.</p>
|
||||||
|
<p>Currently available specs: {{ if SpecList }}{{ len(SpecList) }}{{ else }}0{{ end }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ if SelectedSpec }}
|
||||||
|
<div class="row">
|
||||||
|
<!-- Method Tree -->
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header"><h5>Methods</h5></div>
|
||||||
|
<div class="card-body p-0">
|
||||||
|
<div class="method-tree list-group list-group-flush">
|
||||||
|
{{ if Methods }}
|
||||||
|
{{ range m := Methods }}
|
||||||
|
<a href="/rpcui?spec={{ SelectedSpec }}&method={{ m }}&socketPath={{ SocketPath }}"
|
||||||
|
class="list-group-item list-group-item-action method-item {{ if eq(m, SelectedMethod) }}active{{ end }}">
|
||||||
|
{{ m }}
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
<div class="list-group-item">No methods available</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Method Details -->
|
||||||
|
<div class="col-md-9">
|
||||||
|
{{ if Method }}
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-header">
|
||||||
|
<h5>{{ Method.Name }}</h5>
|
||||||
|
{{ if Method.Description }}<p class="text-muted mb-0">{{ Method.Description }}</p>{{ end }}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<!-- Parameters -->
|
||||||
|
<h6>Parameters</h6>
|
||||||
|
<table class="table table-sm schema-table">
|
||||||
|
<thead><tr><th>Name</th><th>Type</th><th>Required</th><th>Description</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
{{ if Method.Params }}
|
||||||
|
{{ range p := Method.Params }}
|
||||||
|
<tr>
|
||||||
|
<td>{{ p.Name }}</td>
|
||||||
|
<td><code>{{ p.Schema.Type }}</code></td>
|
||||||
|
<td>{{ if p.Required }}<span class="schema-required">Yes</span>{{ else }}<span class="schema-optional">No</span>{{ end }}</td>
|
||||||
|
<td>{{ p.Description }}</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
<tr><td colspan="4">No parameters</td></tr>
|
||||||
|
{{ end }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- Result -->
|
||||||
|
<h6 class="mt-4">Result</h6>
|
||||||
|
<table class="table table-sm schema-table">
|
||||||
|
<thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>{{ Method.Result.Name }}</td>
|
||||||
|
<td><code>{{ Method.Result.Schema.Type }}</code></td>
|
||||||
|
<td>{{ Method.Result.Description }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- Try It -->
|
||||||
|
<h6 class="mt-4">Try It</h6>
|
||||||
|
<form id="rpcForm" class="mb-3">
|
||||||
|
<input type="hidden" name="selectedMethod" value="{{ SelectedMethod }}">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="paramsEditor" class="form-label">Parameters:</label>
|
||||||
|
<textarea class="form-control code-editor" id="paramsEditor" rows="10">{{ ExampleParams }}</textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Execute</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="resultContainer" class="result-container d-none">
|
||||||
|
<h6>Result:</h6>
|
||||||
|
<pre id="resultOutput" class="bg-light p-2 rounded"></pre>
|
||||||
|
</div>
|
||||||
|
<div id="errorContainer" class="result-container d-none">
|
||||||
|
<h6>Error:</h6>
|
||||||
|
<pre id="errorOutput" class="bg-light p-2 rounded text-danger"></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ else if SelectedMethod }}
|
||||||
|
<div class="alert alert-warning">Method not found: {{ SelectedMethod }}</div>
|
||||||
|
{{ else }}
|
||||||
|
<div class="alert alert-info">Select a method from the list to view details.</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{block scripts()}}
|
||||||
|
<script src="/static/js/rpcui.js"></script>
|
||||||
|
{{end}}
|
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/builders/hetznerinstall"
|
"git.threefold.info/herocode/heroagent/pkg/system/builders/hetznerinstall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -6,10 +6,10 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/dependencies"
|
"git.threefold.info/herocode/heroagent/pkg/system/builders/postgresql/dependencies"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/gosp"
|
"git.threefold.info/herocode/heroagent/pkg/system/builders/postgresql/gosp"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/postgres"
|
"git.threefold.info/herocode/heroagent/pkg/system/builders/postgresql/postgres"
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/verification"
|
"git.threefold.info/herocode/heroagent/pkg/system/builders/postgresql/verification"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Constants for PostgreSQL installation
|
// Constants for PostgreSQL installation
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql"
|
"git.threefold.info/herocode/heroagent/pkg/system/builders/postgresql"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/postgres"
|
"git.threefold.info/herocode/heroagent/pkg/system/builders/postgresql/postgres"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Constants for Go stored procedure
|
// Constants for Go stored procedure
|
||||||
|
@@ -26,7 +26,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/processmanager"
|
"git.threefold.info/herocode/heroagent/pkg/system/processmanager"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -14,7 +14,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/logger"
|
"git.threefold.info/herocode/heroagent/pkg/logger"
|
||||||
"github.com/shirou/gopsutil/v3/process"
|
"github.com/shirou/gopsutil/v3/process"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
"git.threefold.info/herocode/heroagent/pkg/system/stats"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@@ -11,7 +11,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
"git.threefold.info/herocode/heroagent/pkg/system/stats"
|
||||||
"github.com/shirou/gopsutil/v3/cpu"
|
"github.com/shirou/gopsutil/v3/cpu"
|
||||||
"github.com/shirou/gopsutil/v3/process"
|
"github.com/shirou/gopsutil/v3/process"
|
||||||
)
|
)
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
"git.threefold.info/herocode/heroagent/pkg/system/stats"
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
"git.threefold.info/herocode/heroagent/pkg/system/stats"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
Reference in New Issue
Block a user