Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 3 additions & 29 deletions pkg/parser/mcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/githubnext/gh-aw/pkg/constants"
"github.com/githubnext/gh-aw/pkg/logger"
"github.com/githubnext/gh-aw/pkg/stringutil"
"github.com/modelcontextprotocol/go-sdk/mcp"
)

Expand Down Expand Up @@ -369,21 +370,7 @@ func processBuiltinMCPTool(toolName string, toolValue any, serverFilter string)
// Check for custom Docker image version (only applicable in local/Docker mode)
if !useRemote {
if version, exists := toolConfig["version"]; exists {
var versionStr string
switch v := version.(type) {
case string:
versionStr = v
case int:
versionStr = fmt.Sprintf("%d", v)
case int64:
versionStr = fmt.Sprintf("%d", v)
case uint64:
versionStr = fmt.Sprintf("%d", v)
case float64:
// Use %g to avoid trailing zeros and scientific notation for simple numbers
versionStr = fmt.Sprintf("%g", v)
}
if versionStr != "" {
if versionStr := stringutil.ParseVersionValue(version); versionStr != "" {
dockerImage := "ghcr.io/github/github-mcp-server:" + versionStr
// Update the Docker image in args
for i, arg := range config.Args {
Expand Down Expand Up @@ -458,20 +445,7 @@ func processBuiltinMCPTool(toolName string, toolValue any, serverFilter string)

// Check for custom Docker image version
if version, exists := toolConfig["version"]; exists {
var versionStr string
switch v := version.(type) {
case string:
versionStr = v
case int:
versionStr = fmt.Sprintf("%d", v)
case int64:
versionStr = fmt.Sprintf("%d", v)
case uint64:
versionStr = fmt.Sprintf("%d", v)
case float64:
versionStr = fmt.Sprintf("%g", v)
}
if versionStr != "" {
if versionStr := stringutil.ParseVersionValue(version); versionStr != "" {
dockerImage := "mcr.microsoft.com/playwright:" + versionStr
// Update the Docker image in args
for i, arg := range config.Args {
Expand Down
21 changes: 20 additions & 1 deletion pkg/stringutil/stringutil.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Package stringutil provides utility functions for working with strings.
package stringutil

import "strings"
import (
"fmt"
"strings"
)

// Truncate truncates a string to a maximum length, adding "..." if truncated.
// If maxLen is 3 or less, the string is truncated without "...".
Expand Down Expand Up @@ -33,3 +36,19 @@ func NormalizeWhitespace(content string) string {

return normalized
}

// ParseVersionValue converts version values of various types to strings.
// Supports string, int, int64, uint64, and float64 types.
// Returns empty string for unsupported types.
func ParseVersionValue(version any) string {
switch v := version.(type) {
case string:
return v
case int, int64, uint64:
return fmt.Sprintf("%d", v)
case float64:
return fmt.Sprintf("%g", v)
default:
return ""
}
}
87 changes: 87 additions & 0 deletions pkg/stringutil/stringutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,3 +324,90 @@ func BenchmarkNormalizeWhitespace_ManyChanges(b *testing.B) {
NormalizeWhitespace(content)
}
}

func TestParseVersionValue(t *testing.T) {
tests := []struct {
name string
version any
expected string
}{
// String versions
{
name: "string version",
version: "v1.2.3",
expected: "v1.2.3",
},
{
name: "numeric string",
version: "123",
expected: "123",
},
{
name: "empty string",
version: "",
expected: "",
},
// Integer versions
{
name: "int version",
version: 42,
expected: "42",
},
{
name: "int64 version",
version: int64(100),
expected: "100",
},
{
name: "uint64 version",
version: uint64(999),
expected: "999",
},
// Float versions
{
name: "float64 simple",
version: float64(1.5),
expected: "1.5",
},
{
name: "float64 whole number",
version: float64(2.0),
expected: "2",
},
{
name: "float64 with precision",
version: float64(1.234),
expected: "1.234",
},
// Unsupported types
{
name: "nil",
version: nil,
expected: "",
},
{
name: "bool",
version: true,
expected: "",
},
{
name: "slice",
version: []string{"1", "2"},
expected: "",
},
{
name: "map",
version: map[string]string{"version": "1.0"},
expected: "",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := ParseVersionValue(tt.version)
if result != tt.expected {
t.Errorf("ParseVersionValue(%v) = %q, expected %q", tt.version, result, tt.expected)
}
})
}
}
10 changes: 2 additions & 8 deletions pkg/workflow/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"

"github.com/githubnext/gh-aw/pkg/logger"
"github.com/githubnext/gh-aw/pkg/stringutil"
)

var engineLog = logger.New("workflow:engine")
Expand Down Expand Up @@ -64,14 +65,7 @@ func (c *Compiler) ExtractEngineConfig(frontmatter map[string]any) (string, *Eng

// Extract optional 'version' field
if version, hasVersion := engineObj["version"]; hasVersion {
switch v := version.(type) {
case string:
config.Version = v
case int, int64, uint64:
config.Version = fmt.Sprintf("%d", v)
case float64:
config.Version = fmt.Sprintf("%g", v)
}
config.Version = stringutil.ParseVersionValue(version)
}

// Extract optional 'model' field
Expand Down