Skip to content

Commit cf605d9

Browse files
committed
Make it clearer which toolsets can use which configuration
Signed-off-by: David Gageot <david.gageot@docker.com>
1 parent 018cdbc commit cf605d9

5 files changed

Lines changed: 61 additions & 20 deletions

File tree

File renamed without changes.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
version: "2"
2+
3+
agents:
4+
root:
5+
model: openai/gpt-4o
6+
toolsets:
7+
- type: mcp
8+
post_edit:
9+
- path: /path

pkg/config/v2/types.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,24 +67,29 @@ type PostEditConfig struct {
6767

6868
// Toolset represents a tool configuration
6969
type Toolset struct {
70-
Type string `json:"type,omitempty" yaml:"type,omitempty"`
71-
Ref string `json:"ref,omitempty" yaml:"ref,omitempty"`
72-
Config any `json:"config,omitempty" yaml:"config,omitempty"`
73-
Command string `json:"command,omitempty" yaml:"command,omitempty"`
74-
Remote Remote `json:"remote,omitempty" yaml:"remote,omitempty"`
75-
Args []string `json:"args,omitempty" yaml:"args,omitempty"`
76-
Tools []string `json:"tools,omitempty" yaml:"tools,omitempty"`
77-
Env map[string]string `json:"env,omitempty" yaml:"env,omitempty"`
78-
79-
// For the think tool
70+
Type string `json:"type,omitempty" yaml:"type,omitempty"`
71+
Tools []string `json:"tools,omitempty" yaml:"tools,omitempty"`
72+
73+
// For the `mcp` tool
74+
Command string `json:"command,omitempty" yaml:"command,omitempty"`
75+
Args []string `json:"args,omitempty" yaml:"args,omitempty"`
76+
Ref string `json:"ref,omitempty" yaml:"ref,omitempty"`
77+
Remote Remote `json:"remote,omitempty" yaml:"remote,omitempty"`
78+
Config any `json:"config,omitempty" yaml:"config,omitempty"`
79+
80+
// For `shell`, `script` or `mcp` tools
81+
Env map[string]string `json:"env,omitempty" yaml:"env,omitempty"`
82+
83+
// For the `todo` tool
8084
Shared bool `json:"shared,omitempty" yaml:"shared,omitempty"`
81-
// For the memory tool
85+
86+
// For the `memory` tool
8287
Path string `json:"path,omitempty" yaml:"path,omitempty"`
8388

84-
// For the script tool
89+
// For the `script` tool
8590
Shell map[string]ScriptShellToolConfig `json:"shell,omitempty" yaml:"shell,omitempty"`
8691

87-
// For the filesystem tool - post-edit commands
92+
// For the `filesystem` tool - post-edit commands
8893
PostEdit []PostEditConfig `json:"post_edit,omitempty" yaml:"post_edit,omitempty"`
8994
}
9095

pkg/config/v2/validate.go

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ func (t *Config) UnmarshalYAML(unmarshal func(any) error) error {
1717

1818
func (t *Config) validate() error {
1919
for _, agent := range t.Agents {
20-
for _, toolSet := range agent.Toolsets {
21-
if err := toolSet.validate(); err != nil {
20+
for i := range agent.Toolsets {
21+
if err := agent.Toolsets[i].validate(); err != nil {
2222
return err
2323
}
2424
}
@@ -27,19 +27,42 @@ func (t *Config) validate() error {
2727
return nil
2828
}
2929

30-
// Ensure that either Command, Remote or Ref is set, but not all empty
3130
func (t *Toolset) validate() error {
3231
// Attributes used on the wrong toolset type.
3332
if len(t.Shell) > 0 && t.Type != "script" {
3433
return errors.New("shell can only be used with type 'script'")
3534
}
36-
if len(t.Path) > 0 && t.Type != "memory" {
35+
if t.Path != "" && t.Type != "memory" {
3736
return errors.New("path can only be used with type 'memory'")
3837
}
38+
if len(t.PostEdit) > 0 && t.Type != "filesystem" {
39+
return errors.New("post_edit can only be used with type 'filesystem'")
40+
}
41+
if len(t.Env) > 0 && (t.Type != "shell" && t.Type != "script" && t.Type != "mcp") {
42+
return errors.New("env can only be used with type 'shell', 'script' or 'mcp'")
43+
}
44+
if t.Shared && t.Type != "todo" {
45+
return errors.New("shared can only be used with type 'todo'")
46+
}
47+
if t.Command != "" && t.Type != "mcp" {
48+
return errors.New("command can only be used with type 'mcp'")
49+
}
50+
if len(t.Args) > 0 && t.Type != "mcp" {
51+
return errors.New("args can only be used with type 'mcp'")
52+
}
53+
if t.Ref != "" && t.Type != "mcp" {
54+
return errors.New("ref can only be used with type 'mcp'")
55+
}
56+
if (t.Remote.URL != "" || t.Remote.TransportType != "" || len(t.Remote.Headers) > 0) && t.Type != "mcp" {
57+
return errors.New("remote can only be used with type 'mcp'")
58+
}
59+
if t.Config != nil && t.Type != "mcp" {
60+
return errors.New("config can only be used with type 'mcp'")
61+
}
3962

4063
switch t.Type {
4164
case "memory":
42-
if len(t.Path) == 0 {
65+
if t.Path == "" {
4366
return errors.New("memory toolset requires a path to be set")
4467
}
4568
case "mcp":

pkg/config/validation_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,19 @@ func TestValidationErrors(t *testing.T) {
120120
},
121121
{
122122
name: "path in non memory toolset",
123-
path: "testdata/invalid_mcp_path_v2.yaml",
123+
path: "testdata/invalid_path_v2.yaml",
124+
},
125+
{
126+
name: "post_edit in non filesystem toolset",
127+
path: "testdata/invalid_post_edit_v2.yaml",
124128
},
125129
}
126130

127131
for _, tt := range tests {
128132
t.Run(tt.name, func(t *testing.T) {
129133
t.Parallel()
130134

131-
_, err := loadConfig("testdata/missing_memory_path.yaml")
135+
_, err := loadConfig(tt.path)
132136
require.Error(t, err)
133137
})
134138
}

0 commit comments

Comments
 (0)