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
20 changes: 20 additions & 0 deletions pkg/config/examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,23 @@ func TestJsonSchemaWorksForExamples(t *testing.T) {
})
}
}

func TestParseExamplesAfterMarshalling(t *testing.T) {
for _, file := range collectExamples(t) {
t.Run(file, func(t *testing.T) {
t.Parallel()

src := NewFileSource(file)
cfg, err := Load(t.Context(), NewFileSource(file))
require.NoError(t, err)

// Make sure that a config can be marshalled and parsed again.
// We've had marshalling issues in the past.
buf, err := yaml.Marshal(cfg)
require.NoError(t, err)

_, err = Load(t.Context(), NewBytesSource(src.Name(), buf))
require.NoError(t, err)
})
}
}
42 changes: 21 additions & 21 deletions pkg/config/latest/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (c *Agents) UnmarshalYAML(unmarshal func(any) error) error {
return nil
}

func (c Agents) MarshalYAML() ([]byte, error) {
func (c Agents) MarshalYAML() (any, error) {
mapSlice := make(yaml.MapSlice, 0, len(c))

for _, agent := range c {
Expand All @@ -69,7 +69,7 @@ func (c Agents) MarshalYAML() ([]byte, error) {
})
}

return yaml.Marshal(mapSlice)
return mapSlice, nil
}

func (c *Agents) First() AgentConfig {
Expand Down Expand Up @@ -165,11 +165,11 @@ func (d *Duration) UnmarshalYAML(unmarshal func(any) error) error {
}

// MarshalYAML implements custom marshaling for Duration to string format
func (d Duration) MarshalYAML() ([]byte, error) {
func (d Duration) MarshalYAML() (any, error) {
if d.Duration == 0 {
return yaml.Marshal("")
return "", nil
}
return yaml.Marshal(d.String())
return d.String(), nil
}

// UnmarshalJSON implements custom unmarshaling for Duration from string format
Expand Down Expand Up @@ -288,14 +288,14 @@ func (s *SkillsConfig) UnmarshalYAML(unmarshal func(any) error) error {
return nil
}

func (s SkillsConfig) MarshalYAML() ([]byte, error) {
func (s SkillsConfig) MarshalYAML() (any, error) {
if len(s.Sources) == 0 {
return yaml.Marshal(false)
return false, nil
}
if len(s.Sources) == 1 && s.Sources[0] == SkillSourceLocal {
return yaml.Marshal(true)
return true, nil
}
return yaml.Marshal(s.Sources)
return s.Sources, nil
}

func (s *SkillsConfig) UnmarshalJSON(data []byte) error {
Expand Down Expand Up @@ -438,11 +438,11 @@ func (f *FlexibleModelConfig) UnmarshalYAML(unmarshal func(any) error) error {
}

// MarshalYAML outputs shorthand format if only provider/model are set
func (f FlexibleModelConfig) MarshalYAML() ([]byte, error) {
func (f FlexibleModelConfig) MarshalYAML() (any, error) {
if f.isShorthandOnly() {
return yaml.Marshal(f.Provider + "/" + f.Model)
return f.Provider + "/" + f.Model, nil
}
return yaml.Marshal(f.ModelConfig)
return f.ModelConfig, nil
}

// isShorthandOnly returns true if only provider and model are set
Expand Down Expand Up @@ -640,15 +640,15 @@ func (d *DeferConfig) UnmarshalYAML(unmarshal func(any) error) error {
return nil
}

func (d DeferConfig) MarshalYAML() ([]byte, error) {
func (d DeferConfig) MarshalYAML() (any, error) {
if d.DeferAll {
return yaml.Marshal(true)
return true, nil
}
if len(d.Tools) == 0 {
// Return false for empty config - this will be omitted by yaml encoder
return yaml.Marshal(false)
return false, nil
}
return yaml.Marshal(d.Tools)
return d.Tools, nil
}

// ThinkingBudget represents reasoning budget configuration.
Expand Down Expand Up @@ -681,14 +681,14 @@ func (t *ThinkingBudget) UnmarshalYAML(unmarshal func(any) error) error {
}

// MarshalYAML implements custom marshaling to output simple string or int format
func (t ThinkingBudget) MarshalYAML() ([]byte, error) {
func (t ThinkingBudget) MarshalYAML() (any, error) {
// If Effort string is set (non-empty), marshal as string
if t.Effort != "" {
return yaml.Marshal(t.Effort)
return t.Effort, nil
}

// Otherwise marshal as integer (includes 0, -1, and positive values)
return yaml.Marshal(t.Tokens)
return t.Tokens, nil
}

// MarshalJSON implements custom marshaling to output simple string or int format
Expand Down Expand Up @@ -829,9 +829,9 @@ func (s *RAGStrategyConfig) UnmarshalYAML(unmarshal func(any) error) error {
}

// MarshalYAML implements custom marshaling to flatten Params into parent level
func (s RAGStrategyConfig) MarshalYAML() ([]byte, error) {
func (s RAGStrategyConfig) MarshalYAML() (any, error) {
result := s.buildFlattenedMap()
return yaml.Marshal(result)
return result, nil
}

// MarshalJSON implements custom marshaling to flatten Params into parent level
Expand Down
12 changes: 5 additions & 7 deletions pkg/config/v2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"fmt"
"maps"

"github.com/goccy/go-yaml"

"github.com/docker/cagent/pkg/config/types"
)

Expand Down Expand Up @@ -319,9 +317,9 @@ func (s *RAGStrategyConfig) UnmarshalYAML(unmarshal func(any) error) error {
}

// MarshalYAML implements custom marshaling to flatten Params into parent level
func (s RAGStrategyConfig) MarshalYAML() ([]byte, error) {
func (s RAGStrategyConfig) MarshalYAML() (any, error) {
result := s.buildFlattenedMap()
return yaml.Marshal(result)
return result, nil
}

// MarshalJSON implements custom marshaling to flatten Params into parent level
Expand Down Expand Up @@ -508,11 +506,11 @@ func (d *RAGDatabaseConfig) IsEmpty() bool {
}

// MarshalYAML implements custom marshaling for DatabaseConfig
func (d RAGDatabaseConfig) MarshalYAML() ([]byte, error) {
func (d RAGDatabaseConfig) MarshalYAML() (any, error) {
if d.value == nil {
return yaml.Marshal(nil)
return nil, nil
}
return yaml.Marshal(d.value)
return d.value, nil
}

// MarshalJSON implements custom marshaling for DatabaseConfig
Expand Down
20 changes: 9 additions & 11 deletions pkg/config/v3/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"fmt"
"maps"

"github.com/goccy/go-yaml"

"github.com/docker/cagent/pkg/config/types"
)

Expand Down Expand Up @@ -260,15 +258,15 @@ func (d *DeferConfig) UnmarshalYAML(unmarshal func(any) error) error {
return nil
}

func (d DeferConfig) MarshalYAML() ([]byte, error) {
func (d DeferConfig) MarshalYAML() (any, error) {
if d.DeferAll {
return yaml.Marshal(true)
return true, nil
}
if len(d.Tools) == 0 {
// Return false for empty config - this will be omitted by yaml encoder
return yaml.Marshal(false)
return false, nil
}
return yaml.Marshal(d.Tools)
return d.Tools, nil
}

// ThinkingBudget represents reasoning budget configuration.
Expand Down Expand Up @@ -301,14 +299,14 @@ func (t *ThinkingBudget) UnmarshalYAML(unmarshal func(any) error) error {
}

// MarshalYAML implements custom marshaling to output simple string or int format
func (t ThinkingBudget) MarshalYAML() ([]byte, error) {
func (t ThinkingBudget) MarshalYAML() (any, error) {
// If Effort string is set (non-empty), marshal as string
if t.Effort != "" {
return yaml.Marshal(t.Effort)
return t.Effort, nil
}

// Otherwise marshal as integer (includes 0, -1, and positive values)
return yaml.Marshal(t.Tokens)
return t.Tokens, nil
}

// MarshalJSON implements custom marshaling to output simple string or int format
Expand Down Expand Up @@ -449,9 +447,9 @@ func (s *RAGStrategyConfig) UnmarshalYAML(unmarshal func(any) error) error {
}

// MarshalYAML implements custom marshaling to flatten Params into parent level
func (s RAGStrategyConfig) MarshalYAML() ([]byte, error) {
func (s RAGStrategyConfig) MarshalYAML() (any, error) {
result := s.buildFlattenedMap()
return yaml.Marshal(result)
return result, nil
}

// MarshalJSON implements custom marshaling to flatten Params into parent level
Expand Down
34 changes: 17 additions & 17 deletions pkg/config/v4/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (c *Agents) UnmarshalYAML(unmarshal func(any) error) error {
return nil
}

func (c Agents) MarshalYAML() ([]byte, error) {
func (c Agents) MarshalYAML() (any, error) {
mapSlice := make(yaml.MapSlice, 0, len(c))

for _, agent := range c {
Expand All @@ -68,7 +68,7 @@ func (c Agents) MarshalYAML() ([]byte, error) {
})
}

return yaml.Marshal(mapSlice)
return mapSlice, nil
}

func (c *Agents) First() AgentConfig {
Expand Down Expand Up @@ -164,11 +164,11 @@ func (d *Duration) UnmarshalYAML(unmarshal func(any) error) error {
}

// MarshalYAML implements custom marshaling for Duration to string format
func (d Duration) MarshalYAML() ([]byte, error) {
func (d Duration) MarshalYAML() (any, error) {
if d.Duration == 0 {
return yaml.Marshal("")
return "", nil
}
return yaml.Marshal(d.String())
return d.String(), nil
}

// UnmarshalJSON implements custom unmarshaling for Duration from string format
Expand Down Expand Up @@ -316,11 +316,11 @@ func (f *FlexibleModelConfig) UnmarshalYAML(unmarshal func(any) error) error {
}

// MarshalYAML outputs shorthand format if only provider/model are set
func (f FlexibleModelConfig) MarshalYAML() ([]byte, error) {
func (f FlexibleModelConfig) MarshalYAML() (any, error) {
if f.isShorthandOnly() {
return yaml.Marshal(f.Provider + "/" + f.Model)
return f.Provider + "/" + f.Model, nil
}
return yaml.Marshal(f.ModelConfig)
return f.ModelConfig, nil
}

// isShorthandOnly returns true if only provider and model are set
Expand Down Expand Up @@ -518,15 +518,15 @@ func (d *DeferConfig) UnmarshalYAML(unmarshal func(any) error) error {
return nil
}

func (d DeferConfig) MarshalYAML() ([]byte, error) {
func (d DeferConfig) MarshalYAML() (any, error) {
if d.DeferAll {
return yaml.Marshal(true)
return true, nil
}
if len(d.Tools) == 0 {
// Return false for empty config - this will be omitted by yaml encoder
return yaml.Marshal(false)
return false, nil
}
return yaml.Marshal(d.Tools)
return d.Tools, nil
}

// ThinkingBudget represents reasoning budget configuration.
Expand Down Expand Up @@ -559,14 +559,14 @@ func (t *ThinkingBudget) UnmarshalYAML(unmarshal func(any) error) error {
}

// MarshalYAML implements custom marshaling to output simple string or int format
func (t ThinkingBudget) MarshalYAML() ([]byte, error) {
func (t ThinkingBudget) MarshalYAML() (any, error) {
// If Effort string is set (non-empty), marshal as string
if t.Effort != "" {
return yaml.Marshal(t.Effort)
return t.Effort, nil
}

// Otherwise marshal as integer (includes 0, -1, and positive values)
return yaml.Marshal(t.Tokens)
return t.Tokens, nil
}

// MarshalJSON implements custom marshaling to output simple string or int format
Expand Down Expand Up @@ -707,9 +707,9 @@ func (s *RAGStrategyConfig) UnmarshalYAML(unmarshal func(any) error) error {
}

// MarshalYAML implements custom marshaling to flatten Params into parent level
func (s RAGStrategyConfig) MarshalYAML() ([]byte, error) {
func (s RAGStrategyConfig) MarshalYAML() (any, error) {
result := s.buildFlattenedMap()
return yaml.Marshal(result)
return result, nil
}

// MarshalJSON implements custom marshaling to flatten Params into parent level
Expand Down
Loading