...
This commit is contained in:
@@ -35,7 +35,7 @@ Key features:
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
// Create a new playbook from HeroScript text
|
||||
|
@@ -7,7 +7,7 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory/herohandler"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory/herohandler"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -24,7 +24,7 @@ func main() {
|
||||
fmt.Printf("Failed to initialize hero handler: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
||||
// Get the default instance
|
||||
handler := herohandler.DefaultInstance
|
||||
|
||||
@@ -43,7 +43,7 @@ func main() {
|
||||
tcpAddressStr = *tcpAddress
|
||||
fmt.Printf("TCP address: %s\n", tcpAddressStr)
|
||||
}
|
||||
|
||||
|
||||
err = handler.StartTelnet(socketPathStr, tcpAddressStr)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to start telnet server: %v\n", err)
|
||||
|
@@ -8,7 +8,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@@ -3,8 +3,8 @@ package internal
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlers"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlers"
|
||||
)
|
||||
|
||||
// ExampleHandler handles example actions
|
||||
|
@@ -7,7 +7,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/cmd/herohandler/internal"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/cmd/herohandler/internal"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -30,7 +30,7 @@ func main() {
|
||||
|
||||
// Get the command from arguments
|
||||
command := strings.Join(os.Args[1:], " ")
|
||||
|
||||
|
||||
// Format as proper HeroScript with !! prefix if not already prefixed
|
||||
script := command
|
||||
if !strings.HasPrefix(script, "!!") {
|
||||
|
@@ -10,7 +10,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory/herohandler"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory/herohandler"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -92,7 +92,7 @@ func showSupportedActions() {
|
||||
// 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
|
||||
script := "!!core.actions"
|
||||
|
||||
|
||||
// Try TCP first, then Unix socket if TCP fails
|
||||
result, err := Send(script, "localhost:8023", false)
|
||||
if err != nil {
|
||||
@@ -103,7 +103,7 @@ func showSupportedActions() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fmt.Println("Supported actions by actor:")
|
||||
fmt.Println(result)
|
||||
}
|
||||
@@ -151,7 +151,7 @@ func Send(command string, address string, isUnixSocket bool) (string, error) {
|
||||
return
|
||||
}
|
||||
response.WriteString(line)
|
||||
|
||||
|
||||
// If we've received a complete response, break
|
||||
if strings.Contains(line, "\n") && strings.TrimSpace(line) == "" {
|
||||
break
|
||||
@@ -187,7 +187,7 @@ func runTestScript() {
|
||||
result, err = Send(script, "/tmp/hero.sock", true)
|
||||
if err != nil {
|
||||
fmt.Printf("Unix socket connection failed: %v\n", err)
|
||||
|
||||
|
||||
// We can't directly access the factory field, so we'll just report the error
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
return
|
||||
|
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
const exampleScript = `
|
||||
|
@@ -16,7 +16,7 @@ The VM handler example shows how to:
|
||||
To run the example:
|
||||
|
||||
```bash
|
||||
cd ~/code/github/freeflowuniverse/heroagent/pkg/handlerfactory/cmd/vmhandler
|
||||
cd ~/code/github/freeflowuniverse/herocode/heroagent/pkg/handlerfactory/cmd/vmhandler
|
||||
go run . tutorial
|
||||
#to run just the server do
|
||||
go run .
|
||||
|
@@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory"
|
||||
)
|
||||
|
||||
// runTutorial runs an interactive tutorial demonstrating the VM handler
|
||||
@@ -50,7 +50,7 @@ func runTutorial() {
|
||||
|
||||
// Process heroscript commands
|
||||
fmt.Println("\nStep 5: Process heroscript commands")
|
||||
|
||||
|
||||
// Define a VM
|
||||
defineScript := `!!vm.define name:'tutorial_vm' cpu:2 memory:'4GB' storage:'50GB'
|
||||
description: 'A tutorial VM for demonstration purposes'`
|
||||
|
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory"
|
||||
)
|
||||
|
||||
// VMHandler handles VM-related actions
|
||||
|
@@ -8,7 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory"
|
||||
)
|
||||
|
||||
// The tutorial functions are defined in tutorial.go
|
||||
|
@@ -30,7 +30,7 @@ The Handler Factory exposes two interfaces for communication:
|
||||
to get started
|
||||
|
||||
```bash
|
||||
cd /root/code/github/freeflowuniverse/heroagent/pkg/handlerfactory/herohandler/cmd
|
||||
cd /root/code/github/freeflowuniverse/herocode/heroagent/pkg/handlerfactory/herohandler/cmd
|
||||
go run .
|
||||
```
|
||||
|
||||
|
@@ -5,8 +5,8 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/paramsparser"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
// Handler interface defines methods that all handlers must implement
|
||||
|
@@ -5,7 +5,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
// HandlerFactory manages a collection of handlers
|
||||
|
@@ -12,7 +12,7 @@ import (
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
// ANSI color codes for terminal output
|
||||
@@ -43,23 +43,23 @@ type TelnetServer struct {
|
||||
sigCh chan os.Signal
|
||||
onShutdown func()
|
||||
// Map to store client preferences (like json formatting)
|
||||
clientPrefs map[net.Conn]map[string]bool
|
||||
prefsMutex sync.RWMutex
|
||||
clientPrefs map[net.Conn]map[string]bool
|
||||
prefsMutex sync.RWMutex
|
||||
}
|
||||
|
||||
// NewTelnetServer creates a new telnet server
|
||||
func NewTelnetServer(factory *HandlerFactory, secrets ...string) *TelnetServer {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
return &TelnetServer{
|
||||
factory: factory,
|
||||
secrets: secrets,
|
||||
clients: make(map[net.Conn]bool),
|
||||
factory: factory,
|
||||
secrets: secrets,
|
||||
clients: make(map[net.Conn]bool),
|
||||
clientPrefs: make(map[net.Conn]map[string]bool),
|
||||
running: false,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
sigCh: make(chan os.Signal, 1),
|
||||
onShutdown: func() {},
|
||||
running: false,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
sigCh: make(chan os.Signal, 1),
|
||||
onShutdown: func() {},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ func (ts *TelnetServer) handleConnection(conn net.Conn) {
|
||||
ts.clientsMutex.Lock()
|
||||
ts.clients[conn] = false
|
||||
ts.clientsMutex.Unlock()
|
||||
|
||||
|
||||
// Initialize client preferences
|
||||
ts.prefsMutex.Lock()
|
||||
ts.clientPrefs[conn] = make(map[string]bool)
|
||||
@@ -284,7 +284,7 @@ func (ts *TelnetServer) handleConnection(conn net.Conn) {
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
// Handle JSON format toggle
|
||||
if line == "!!json" {
|
||||
ts.prefsMutex.Lock()
|
||||
@@ -293,12 +293,12 @@ func (ts *TelnetServer) handleConnection(conn net.Conn) {
|
||||
prefs = make(map[string]bool)
|
||||
ts.clientPrefs[conn] = prefs
|
||||
}
|
||||
|
||||
|
||||
// Toggle JSON format preference
|
||||
currentSetting := prefs["json"]
|
||||
prefs["json"] = !currentSetting
|
||||
ts.prefsMutex.Unlock()
|
||||
|
||||
|
||||
if prefs["json"] {
|
||||
conn.Write([]byte("JSON format will be automatically added to all heroscripts.\n"))
|
||||
} else {
|
||||
@@ -416,7 +416,7 @@ func (ts *TelnetServer) executeHeroscript(script string, conn net.Conn, interact
|
||||
ts.prefsMutex.RLock()
|
||||
prefs, exists := ts.clientPrefs[conn]
|
||||
ts.prefsMutex.RUnlock()
|
||||
|
||||
|
||||
if exists && prefs["json"] {
|
||||
// Add format:json if not already present
|
||||
if !strings.Contains(script, "format:json") {
|
||||
@@ -424,7 +424,7 @@ func (ts *TelnetServer) executeHeroscript(script string, conn net.Conn, interact
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if interactive {
|
||||
// Format the script with colors
|
||||
formattedScript := formatHeroscript(script)
|
||||
@@ -466,8 +466,6 @@ func (ts *TelnetServer) addJsonFormat(script string) string {
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
|
||||
|
||||
// formatHeroscript formats heroscript with colors for console output only
|
||||
// This is not used for telnet responses, only for server-side logging
|
||||
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
|
||||
handlerValue := reflect.ValueOf(handler)
|
||||
helpMethod := handlerValue.MethodByName("Help")
|
||||
|
||||
|
||||
if helpMethod.IsValid() {
|
||||
// Call the Help method
|
||||
args := []reflect.Value{reflect.ValueOf("")}
|
||||
result := helpMethod.Call(args)
|
||||
|
||||
|
||||
// Get the result
|
||||
if len(result) > 0 && result[0].Kind() == reflect.String {
|
||||
helpText := result[0].String()
|
||||
|
@@ -3,7 +3,7 @@ package handlers
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
)
|
||||
|
||||
// AuthHandler handles authentication actions
|
||||
|
@@ -5,9 +5,9 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/paramsparser"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
// BaseHandler provides common functionality for all handlers
|
||||
|
@@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
// HandlerFactory manages a collection of handlers for processing HeroScript commands
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package herohandler
|
||||
|
||||
import (
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
)
|
||||
|
||||
// GetFactory returns the handler factory
|
||||
|
@@ -4,7 +4,7 @@ import (
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/herohandler"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/herohandler"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@@ -4,10 +4,10 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
|
||||
// "github.com/freeflowuniverse/heroagent/pkg/handlerfactory/heroscript/handlerfactory/fakehandler"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/processmanagerhandler"
|
||||
// "git.ourworld.tf/herocode/heroagent/pkg/handlerfactory/heroscript/handlerfactory/fakehandler"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/processmanagerhandler"
|
||||
)
|
||||
|
||||
// HeroHandler is the main handler factory that manages all registered handlers
|
||||
|
@@ -3,7 +3,7 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@@ -3,8 +3,8 @@ package processmanagerhandler
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager"
|
||||
)
|
||||
|
||||
// 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
|
||||
import (
|
||||
"github.com/freeflowuniverse/heroagent/pkg/paramsparser"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/paramsparser"
|
||||
)
|
||||
|
||||
// Create a new parser
|
||||
|
@@ -4,7 +4,7 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/paramsparser"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@@ -9,7 +9,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/tools"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
||||
)
|
||||
|
||||
// ParamsParser represents a parameter parser that can handle various parameter sources
|
||||
@@ -32,12 +32,12 @@ func New() *ParamsParser {
|
||||
func (p *ParamsParser) Parse(input string) error {
|
||||
// Normalize line endings
|
||||
input = strings.ReplaceAll(input, "\r\n", "\n")
|
||||
|
||||
|
||||
// Track the current state
|
||||
var currentKey string
|
||||
var currentValue strings.Builder
|
||||
var inMultilineString bool
|
||||
|
||||
|
||||
// Process each line
|
||||
lines := strings.Split(input, "\n")
|
||||
for i := 0; i < len(lines); i++ {
|
||||
@@ -48,12 +48,12 @@ func (p *ParamsParser) Parse(input string) error {
|
||||
} else {
|
||||
line = lines[i]
|
||||
}
|
||||
|
||||
|
||||
// Skip empty lines unless we're in a multiline string
|
||||
if line == "" && !inMultilineString {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
// If we're in a multiline string
|
||||
if inMultilineString {
|
||||
// Check if this line ends the multiline string
|
||||
@@ -71,7 +71,7 @@ func (p *ParamsParser) Parse(input string) error {
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
// Process the line to extract key-value pairs
|
||||
var processedPos int
|
||||
for processedPos < len(line) {
|
||||
@@ -79,62 +79,62 @@ func (p *ParamsParser) Parse(input string) error {
|
||||
for processedPos < len(line) && (line[processedPos] == ' ' || line[processedPos] == '\t') {
|
||||
processedPos++
|
||||
}
|
||||
|
||||
|
||||
if processedPos >= len(line) {
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
// Find the next key by looking for a colon
|
||||
keyStart := processedPos
|
||||
colonPos := -1
|
||||
|
||||
|
||||
for j := processedPos; j < len(line); j++ {
|
||||
if line[j] == ':' {
|
||||
colonPos = j
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if colonPos == -1 {
|
||||
// No colon found, skip this part
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
// Extract key and use NameFix to standardize it
|
||||
rawKey := strings.TrimSpace(line[keyStart:colonPos])
|
||||
key := tools.NameFix(rawKey)
|
||||
|
||||
|
||||
if key == "" {
|
||||
// Invalid key, move past the colon and continue
|
||||
processedPos = colonPos + 1
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
// Move position past the colon
|
||||
processedPos = colonPos + 1
|
||||
|
||||
|
||||
if processedPos >= len(line) {
|
||||
// End of line reached, store empty value
|
||||
p.params[key] = ""
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
// Skip whitespace after the colon
|
||||
for processedPos < len(line) && (line[processedPos] == ' ' || line[processedPos] == '\t') {
|
||||
processedPos++
|
||||
}
|
||||
|
||||
|
||||
if processedPos >= len(line) {
|
||||
// End of line reached after whitespace, store empty value
|
||||
p.params[key] = ""
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
// Check if the value is quoted
|
||||
if line[processedPos] == '\'' {
|
||||
// This is a quoted string
|
||||
processedPos++ // Skip the opening quote
|
||||
|
||||
|
||||
// Look for the closing quote
|
||||
quoteEnd := -1
|
||||
for j := processedPos; j < len(line); j++ {
|
||||
@@ -144,7 +144,7 @@ func (p *ParamsParser) Parse(input string) error {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if quoteEnd != -1 {
|
||||
// Single-line quoted string
|
||||
value := line[processedPos:quoteEnd]
|
||||
@@ -167,12 +167,12 @@ func (p *ParamsParser) Parse(input string) error {
|
||||
// This is an unquoted value
|
||||
valueStart := processedPos
|
||||
valueEnd := valueStart
|
||||
|
||||
|
||||
// Find the end of the value (space or end of line)
|
||||
for valueEnd < len(line) && line[valueEnd] != ' ' && line[valueEnd] != '\t' {
|
||||
valueEnd++
|
||||
}
|
||||
|
||||
|
||||
value := line[valueStart:valueEnd]
|
||||
// For unquoted values, use NameFix to standardize them
|
||||
// This handles the 'without' keyword and other special cases
|
||||
@@ -181,12 +181,12 @@ func (p *ParamsParser) Parse(input string) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If we're still in a multiline string at the end, that's an error
|
||||
if inMultilineString {
|
||||
return errors.New("unterminated multiline string")
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ func (p *ParamsParser) Parse(input string) error {
|
||||
func (p *ParamsParser) ParseString(input string) error {
|
||||
// Trim the input
|
||||
input = strings.TrimSpace(input)
|
||||
|
||||
|
||||
// Process the input to extract key-value pairs
|
||||
var processedPos int
|
||||
for processedPos < len(input) {
|
||||
@@ -204,62 +204,62 @@ func (p *ParamsParser) ParseString(input string) error {
|
||||
for processedPos < len(input) && (input[processedPos] == ' ' || input[processedPos] == '\t') {
|
||||
processedPos++
|
||||
}
|
||||
|
||||
|
||||
if processedPos >= len(input) {
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
// Find the next key by looking for a colon
|
||||
keyStart := processedPos
|
||||
colonPos := -1
|
||||
|
||||
|
||||
for j := processedPos; j < len(input); j++ {
|
||||
if input[j] == ':' {
|
||||
colonPos = j
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if colonPos == -1 {
|
||||
// No colon found, skip this part
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
// Extract key and use NameFix to standardize it
|
||||
rawKey := strings.TrimSpace(input[keyStart:colonPos])
|
||||
key := tools.NameFix(rawKey)
|
||||
|
||||
|
||||
if key == "" {
|
||||
// Invalid key, move past the colon and continue
|
||||
processedPos = colonPos + 1
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
// Move position past the colon
|
||||
processedPos = colonPos + 1
|
||||
|
||||
|
||||
if processedPos >= len(input) {
|
||||
// End of input reached, store empty value
|
||||
p.params[key] = ""
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
// Skip whitespace after the colon
|
||||
for processedPos < len(input) && (input[processedPos] == ' ' || input[processedPos] == '\t') {
|
||||
processedPos++
|
||||
}
|
||||
|
||||
|
||||
if processedPos >= len(input) {
|
||||
// End of input reached after whitespace, store empty value
|
||||
p.params[key] = ""
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
// Check if the value is quoted
|
||||
if input[processedPos] == '\'' {
|
||||
// This is a quoted string
|
||||
processedPos++ // Skip the opening quote
|
||||
|
||||
|
||||
// Look for the closing quote
|
||||
quoteEnd := -1
|
||||
for j := processedPos; j < len(input); j++ {
|
||||
@@ -269,11 +269,11 @@ func (p *ParamsParser) ParseString(input string) error {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if quoteEnd == -1 {
|
||||
return errors.New("unterminated quoted string")
|
||||
}
|
||||
|
||||
|
||||
value := input[processedPos:quoteEnd]
|
||||
// For quoted values in ParseString, we can apply NameFix
|
||||
// since this method doesn't handle multiline strings
|
||||
@@ -286,12 +286,12 @@ func (p *ParamsParser) ParseString(input string) error {
|
||||
// This is an unquoted value
|
||||
valueStart := processedPos
|
||||
valueEnd := valueStart
|
||||
|
||||
|
||||
// Find the end of the value (space or end of input)
|
||||
for valueEnd < len(input) && input[valueEnd] != ' ' && input[valueEnd] != '\t' {
|
||||
valueEnd++
|
||||
}
|
||||
|
||||
|
||||
value := input[valueStart:valueEnd]
|
||||
// For unquoted values, use NameFix to standardize them
|
||||
// This handles the 'without' keyword and other special cases
|
||||
@@ -299,7 +299,7 @@ func (p *ParamsParser) ParseString(input string) error {
|
||||
processedPos = valueEnd
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -364,7 +364,7 @@ func (p *ParamsParser) GetBool(key string) bool {
|
||||
if value == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
// Check for common boolean string representations
|
||||
value = strings.ToLower(value)
|
||||
return value == "true" || value == "yes" || value == "1" || value == "on"
|
||||
@@ -405,17 +405,17 @@ func (p *ParamsParser) Has(key string) bool {
|
||||
// GetAll returns all parameters as a map
|
||||
func (p *ParamsParser) GetAll() map[string]string {
|
||||
result := make(map[string]string)
|
||||
|
||||
|
||||
// First add defaults
|
||||
for k, v := range p.defaultParams {
|
||||
result[k] = v
|
||||
}
|
||||
|
||||
|
||||
// Then override with actual params
|
||||
for k, v := range p.params {
|
||||
result[k] = v
|
||||
}
|
||||
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
@@ -3,8 +3,8 @@ package playbook
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/paramsparser"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/tools"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
||||
)
|
||||
|
||||
// State represents the parser state
|
||||
|
@@ -7,7 +7,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/paramsparser"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||
)
|
||||
|
||||
// ActionType represents the type of action
|
||||
|
Reference in New Issue
Block a user