Skip to content

Commit c938636

Browse files
committed
Add tests
Signed-off-by: David Gageot <david.gageot@docker.com>
1 parent a2ec32d commit c938636

2 files changed

Lines changed: 113 additions & 23 deletions

File tree

pkg/server/server_test.go

Lines changed: 92 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"github.com/docker/cagent/pkg/api"
1919
"github.com/docker/cagent/pkg/config"
2020
latest "github.com/docker/cagent/pkg/config/v2"
21-
v2 "github.com/docker/cagent/pkg/config/v2"
2221
"github.com/docker/cagent/pkg/session"
2322
)
2423

@@ -28,22 +27,26 @@ func TestServer_ListAgents(t *testing.T) {
2827
t.Setenv("ANTHROPIC_API_KEY", "dummy")
2928

3029
ctx := t.Context()
31-
lnPath := startServer(t, ctx, prepareAgentsDir(t, "pirate.yaml", "contradict.yaml"))
30+
lnPath := startServer(t, ctx, prepareAgentsDir(t, "pirate.yaml", "contradict.yaml", "multi_agents.yaml"))
3231

3332
buf := httpGET(t, ctx, lnPath, "/api/agents")
3433

3534
var agents []api.Agent
3635
unmarshal(t, buf, &agents)
3736

38-
assert.Len(t, agents, 2)
37+
assert.Len(t, agents, 3)
3938

4039
assert.Equal(t, "contradict.yaml", agents[0].Name)
4140
assert.Equal(t, "Contrarian viewpoint provider", agents[0].Description)
4241
assert.False(t, agents[0].Multi)
4342

44-
assert.Equal(t, "pirate.yaml", agents[1].Name)
45-
assert.Equal(t, "Talk like a pirate", agents[1].Description)
46-
assert.False(t, agents[1].Multi)
43+
assert.Equal(t, "multi_agents.yaml", agents[1].Name)
44+
assert.Equal(t, "Multi Agent", agents[1].Description)
45+
assert.True(t, agents[1].Multi)
46+
47+
assert.Equal(t, "pirate.yaml", agents[2].Name)
48+
assert.Equal(t, "Talk like a pirate", agents[2].Description)
49+
assert.False(t, agents[2].Multi)
4750
}
4851

4952
func TestServer_GetAgent_NoExtension(t *testing.T) {
@@ -58,7 +61,7 @@ func TestServer_GetAgent_NoExtension(t *testing.T) {
5861
unmarshal(t, buf, &cfg)
5962

6063
assert.NotEmpty(t, cfg.Version)
61-
require.NotEmpty(t, cfg.Agents)
64+
require.Len(t, cfg.Agents, 1)
6265
assert.Contains(t, cfg.Agents["root"].Instruction, "pirate")
6366
}
6467

@@ -74,7 +77,7 @@ func TestServer_GetAgent(t *testing.T) {
7477
unmarshal(t, buf, &cfg)
7578

7679
assert.NotEmpty(t, cfg.Version)
77-
require.NotEmpty(t, cfg.Agents)
80+
require.Len(t, cfg.Agents, 1)
7881
assert.Contains(t, cfg.Agents["root"].Instruction, "pirate")
7982
}
8083

@@ -123,18 +126,83 @@ func TestServer_Edit_Noop(t *testing.T) {
123126

124127
edit := api.EditAgentConfigRequest{
125128
Filename: "pirate.yaml",
126-
AgentConfig: v2.Config{},
129+
AgentConfig: latest.Config{},
127130
}
128131
httpPUT(t, ctx, lnPath, "/api/agents/config", edit)
129132

130133
buf := httpGET(t, ctx, lnPath, "/api/agents/pirate.yaml")
131134
var cfg latest.Config
132135
unmarshal(t, buf, &cfg)
133136
assert.NotEmpty(t, cfg.Version)
134-
require.NotEmpty(t, cfg.Agents)
137+
require.Len(t, cfg.Agents, 1)
135138
assert.Contains(t, cfg.Agents["root"].Instruction, "pirate")
136139
}
137140

141+
func TestServer_Edit_Instruction(t *testing.T) {
142+
// t.Parallel()
143+
t.Setenv("OPENAI_API_KEY", "dummy")
144+
145+
ctx := t.Context()
146+
lnPath := startServer(t, ctx, prepareAgentsDir(t, "pirate.yaml"))
147+
148+
edit := api.EditAgentConfigRequest{
149+
Filename: "pirate.yaml",
150+
AgentConfig: latest.Config{
151+
Agents: map[string]latest.AgentConfig{
152+
"root": {
153+
Instruction: "New Instructions",
154+
Model: "openai/gpt-4o",
155+
},
156+
},
157+
},
158+
}
159+
httpPUT(t, ctx, lnPath, "/api/agents/config", edit)
160+
161+
buf := httpGET(t, ctx, lnPath, "/api/agents/pirate.yaml")
162+
var cfg latest.Config
163+
unmarshal(t, buf, &cfg)
164+
assert.NotEmpty(t, cfg.Version)
165+
require.Len(t, cfg.Agents, 1)
166+
require.Len(t, cfg.Models, 1)
167+
assert.Equal(t, "New Instructions", cfg.Agents["root"].Instruction)
168+
assert.Empty(t, cfg.Agents["root"].Description)
169+
}
170+
171+
func TestServer_Edit_OnlyOneSubAgent(t *testing.T) {
172+
// t.Parallel()
173+
t.Setenv("OPENAI_API_KEY", "dummy")
174+
t.Setenv("ANTHROPIC_API_KEY", "dummy")
175+
176+
ctx := t.Context()
177+
lnPath := startServer(t, ctx, prepareAgentsDir(t, "multi_agents.yaml"))
178+
179+
edit := api.EditAgentConfigRequest{
180+
Filename: "multi_agents.yaml",
181+
AgentConfig: latest.Config{
182+
Agents: map[string]latest.AgentConfig{
183+
"root": {
184+
Instruction: "New Instructions",
185+
Model: "openai/gpt-4o",
186+
},
187+
},
188+
},
189+
}
190+
httpPUT(t, ctx, lnPath, "/api/agents/config", edit)
191+
192+
buf := httpGET(t, ctx, lnPath, "/api/agents/multi_agents.yaml")
193+
var cfg latest.Config
194+
unmarshal(t, buf, &cfg)
195+
assert.NotEmpty(t, cfg.Version)
196+
require.Len(t, cfg.Agents, 3)
197+
require.Len(t, cfg.Models, 2)
198+
assert.Equal(t, "New Instructions", cfg.Agents["root"].Instruction)
199+
assert.Empty(t, cfg.Agents["root"].Description)
200+
assert.Equal(t, "Pirate", cfg.Agents["pirate"].Description)
201+
assert.NotEmpty(t, cfg.Agents["pirate"].Instruction)
202+
assert.Equal(t, "Contradict", cfg.Agents["contradict"].Description)
203+
assert.NotEmpty(t, cfg.Agents["contradict"].Instruction)
204+
}
205+
138206
func TestServer_ListSessions(t *testing.T) {
139207
t.Parallel()
140208

@@ -194,23 +262,26 @@ func httpGET(t *testing.T, ctx context.Context, socketPath, path string) []byte
194262
return httpDo(t, ctx, http.MethodGet, socketPath, path, nil)
195263
}
196264

197-
func httpPUT(t *testing.T, ctx context.Context, socketPath, path string, payload any) []byte {
265+
func httpPUT(t *testing.T, ctx context.Context, socketPath, path string, payload any) {
198266
t.Helper()
199-
return httpDo(t, ctx, http.MethodPut, socketPath, path, payload)
267+
httpDo(t, ctx, http.MethodPut, socketPath, path, payload)
200268
}
201269

202270
func httpDo(t *testing.T, ctx context.Context, method, socketPath, path string, payload any) []byte {
203271
t.Helper()
204272

205-
var body io.Reader
206-
var contentType string
207-
if payload == nil {
273+
var (
274+
body io.Reader
275+
contentType string
276+
)
277+
switch v := payload.(type) {
278+
case nil:
208279
body = http.NoBody
209-
} else if text, ok := payload.([]byte); ok {
210-
body = bytes.NewReader(text)
211-
} else if text, ok := payload.(string); ok {
212-
body = strings.NewReader(text)
213-
} else {
280+
case []byte:
281+
body = bytes.NewReader(v)
282+
case string:
283+
body = strings.NewReader(v)
284+
default:
214285
buf, err := json.Marshal(payload)
215286
require.NoError(t, err)
216287
body = bytes.NewReader(buf)
@@ -220,9 +291,7 @@ func httpDo(t *testing.T, ctx context.Context, method, socketPath, path string,
220291
req, err := http.NewRequestWithContext(ctx, method, "http://_"+path, body)
221292
require.NoError(t, err)
222293

223-
if contentType != "" {
224-
req.Header.Set("Content-Type", contentType)
225-
}
294+
req.Header.Set("Content-Type", contentType)
226295

227296
client := &http.Client{
228297
Transport: &http.Transport{
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env cagent run
2+
3+
version: "2"
4+
5+
agents:
6+
root:
7+
description: Multi Agent
8+
instruction: Either talk like a pirate or contradict the user.
9+
model: openai/gpt-4o
10+
sub_agents: ["contradict", "pirate"]
11+
12+
pirate:
13+
description: Pirate
14+
instruction: Always answer by talking like a pirate.
15+
model: openai/gpt-4o
16+
17+
contradict:
18+
description: Contradict
19+
instruction: |
20+
Engage with users by consistently providing responses that contradict or oppose their statements, questions, or claims. Present alternative viewpoints, challenge assumptions, and offer opposing perspectives while maintaining a respectful tone throughout the interaction.
21+
model: anthropic/claude-3-5-sonnet-latest

0 commit comments

Comments
 (0)