Skip to content

Commit d66fa53

Browse files
committed
wip
Signed-off-by: David Gageot <david.gageot@docker.com>
1 parent 223dde3 commit d66fa53

7 files changed

Lines changed: 230 additions & 20 deletions

File tree

pkg/agent/agent.go

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,18 @@ import (
1414

1515
// Agent represents an AI agent
1616
type Agent struct {
17-
name string
18-
description string
19-
instruction string
20-
toolsets []tools.ToolSet
21-
toolsetsStarted atomic.Bool
22-
models []provider.Provider
23-
subAgents []*Agent
24-
parents []*Agent
25-
addDate bool
26-
toolWrapper toolWrapper
27-
memoryManager memorymanager.Manager
17+
name string
18+
description string
19+
instruction string
20+
toolsets []tools.ToolSet
21+
toolsetsStarted atomic.Bool
22+
models []provider.Provider
23+
subAgents []*Agent
24+
parents []*Agent
25+
addDate bool
26+
addEnvironmentInfo bool
27+
toolWrapper toolWrapper
28+
memoryManager memorymanager.Manager
2829
}
2930

3031
// New creates a new agent
@@ -54,6 +55,10 @@ func (a *Agent) AddDate() bool {
5455
return a.addDate
5556
}
5657

58+
func (a *Agent) AddEnvironmentInfo() bool {
59+
return a.addEnvironmentInfo
60+
}
61+
5762
// Description returns the agent's description
5863
func (a *Agent) Description() string {
5964
return a.description

pkg/agent/opts.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ func WithAddDate(addDate bool) Opt {
6161
}
6262
}
6363

64+
func WithAddEnvironmentInfo(addEnvironmentInfo bool) Opt {
65+
return func(a *Agent) {
66+
a.addEnvironmentInfo = addEnvironmentInfo
67+
}
68+
}
69+
6470
func WithMemoryManager(mm memorymanager.Manager) Opt {
6571
return func(a *Agent) {
6672
a.memoryManager = mm

pkg/config/v1/types.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,13 @@ func (t *Toolset) UnmarshalYAML(unmarshal func(any) error) error {
7272

7373
// AgentConfig represents a single agent configuration
7474
type AgentConfig struct {
75-
Model string `json:"model,omitempty" yaml:"model,omitempty"`
76-
Description string `json:"description,omitempty" yaml:"description,omitempty"`
77-
Toolsets []Toolset `json:"toolsets,omitempty" yaml:"toolsets,omitempty"`
78-
Instruction string `json:"instruction,omitempty" yaml:"instruction,omitempty"`
79-
SubAgents []string `json:"sub_agents,omitempty" yaml:"sub_agents,omitempty"`
80-
AddDate bool `json:"add_date,omitempty" yaml:"add_date,omitempty"`
75+
Model string `json:"model,omitempty" yaml:"model,omitempty"`
76+
Description string `json:"description,omitempty" yaml:"description,omitempty"`
77+
Toolsets []Toolset `json:"toolsets,omitempty" yaml:"toolsets,omitempty"`
78+
Instruction string `json:"instruction,omitempty" yaml:"instruction,omitempty"`
79+
SubAgents []string `json:"sub_agents,omitempty" yaml:"sub_agents,omitempty"`
80+
AddDate bool `json:"add_date,omitempty" yaml:"add_date,omitempty"`
81+
AddEnvironmentInfo bool `json:"add_environment_info,omitempty" yaml:"add_environment_info,omitempty"`
8182
}
8283

8384
// ModelConfig represents the configuration for a model

pkg/session/environment.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package session
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
"runtime"
8+
)
9+
10+
// getEnvironmentInfo returns formatted environment information including
11+
// working directory, git repository status, and platform information
12+
func getEnvironmentInfo(workingDir string) string {
13+
return fmt.Sprintf(`Here is useful information about the environment you are running in:
14+
<env>
15+
Working directory: %s
16+
Is directory a git repo: %s
17+
Platform: %s
18+
</env>`, workingDir, boolToYesNo(isGitRepo(workingDir)), runtime.GOOS)
19+
}
20+
21+
// isGitRepo checks if the given directory is a git repository
22+
func isGitRepo(dir string) bool {
23+
_, err := os.Stat(filepath.Join(dir, ".git"))
24+
return err == nil
25+
}
26+
27+
// boolToYesNo converts a boolean to "Yes" or "No" string
28+
func boolToYesNo(b bool) string {
29+
if b {
30+
return "Yes"
31+
}
32+
return "No"
33+
}

pkg/session/environment_test.go

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package session
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"runtime"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestGetEnvironmentInfo(t *testing.T) {
14+
tests := []struct {
15+
name string
16+
setupFunc func() string
17+
expectGit bool
18+
}{
19+
{
20+
name: "with git repo",
21+
setupFunc: func() string {
22+
tmpDir := t.TempDir()
23+
require.NoError(t, os.Mkdir(filepath.Join(tmpDir, ".git"), 0755))
24+
return tmpDir
25+
},
26+
expectGit: true,
27+
},
28+
{
29+
name: "without git repo",
30+
setupFunc: func() string {
31+
return t.TempDir()
32+
},
33+
expectGit: false,
34+
},
35+
{
36+
name: "nonexistent directory",
37+
setupFunc: func() string {
38+
return "/path/that/does/not/exist"
39+
},
40+
expectGit: false,
41+
},
42+
{
43+
name: "empty directory path",
44+
setupFunc: func() string {
45+
return ""
46+
},
47+
expectGit: false,
48+
},
49+
}
50+
51+
for _, tt := range tests {
52+
t.Run(tt.name, func(t *testing.T) {
53+
dir := tt.setupFunc()
54+
info := getEnvironmentInfo(dir)
55+
56+
gitStatus := "No"
57+
if tt.expectGit {
58+
gitStatus = "Yes"
59+
}
60+
61+
expected := `Here is useful information about the environment you are running in:
62+
<env>
63+
Working directory: ` + dir + `
64+
Is directory a git repo: ` + gitStatus + `
65+
Platform: ` + runtime.GOOS + `
66+
</env>`
67+
68+
assert.Equal(t, expected, info)
69+
})
70+
}
71+
}
72+
73+
func TestIsGitRepo(t *testing.T) {
74+
tests := []struct {
75+
name string
76+
setupFunc func() string
77+
}{
78+
{
79+
name: "git folder",
80+
setupFunc: func() string {
81+
tmpDir := t.TempDir()
82+
require.NoError(t, os.Mkdir(filepath.Join(tmpDir, ".git"), 0755))
83+
return tmpDir
84+
},
85+
},
86+
{
87+
name: "git file",
88+
setupFunc: func() string {
89+
tmpDir := t.TempDir()
90+
require.NoError(t, os.WriteFile(filepath.Join(tmpDir, ".git"), []byte("gitdir: /some/other/path"), 0644))
91+
return tmpDir
92+
},
93+
},
94+
}
95+
96+
for _, tt := range tests {
97+
t.Run(tt.name, func(t *testing.T) {
98+
dir := tt.setupFunc()
99+
assert.True(t, isGitRepo(dir))
100+
})
101+
}
102+
}
103+
104+
func TestIsNotGitRepo(t *testing.T) {
105+
tests := []struct {
106+
name string
107+
setupFunc func() string
108+
}{
109+
{
110+
name: "no git",
111+
setupFunc: func() string {
112+
return t.TempDir()
113+
},
114+
},
115+
{
116+
name: "nonexistent directory",
117+
setupFunc: func() string {
118+
return "/path/that/does/not/exist"
119+
},
120+
},
121+
{
122+
name: "empty path",
123+
setupFunc: func() string {
124+
return ""
125+
},
126+
},
127+
}
128+
129+
for _, tt := range tests {
130+
t.Run(tt.name, func(t *testing.T) {
131+
dir := tt.setupFunc()
132+
assert.False(t, isGitRepo(dir))
133+
})
134+
}
135+
}
136+
137+
func TestBoolToYesNo(t *testing.T) {
138+
assert.Equal(t, "Yes", boolToYesNo(true))
139+
assert.Equal(t, "No", boolToYesNo(false))
140+
}
141+
142+
func TestGetEnvironmentInfoIntegration(t *testing.T) {
143+
wd, err := os.Getwd()
144+
require.NoError(t, err)
145+
146+
info := getEnvironmentInfo(wd)
147+
148+
assert.Contains(t, info, "Here is useful information about the environment you are running in:")
149+
assert.Contains(t, info, "<env>")
150+
assert.Contains(t, info, "</env>")
151+
assert.Contains(t, info, "Working directory: "+wd)
152+
assert.Contains(t, info, "Platform: "+runtime.GOOS)
153+
154+
if isGitRepo(wd) {
155+
assert.Contains(t, info, "Is directory a git repo: Yes")
156+
} else {
157+
assert.Contains(t, info, "Is directory a git repo: No")
158+
}
159+
}

pkg/session/session.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,14 +206,19 @@ func (s *Session) GetMessages(a *agent.Agent) []chat.Message {
206206
})
207207
}
208208

209-
date := ""
209+
content := a.Instruction()
210+
210211
if a.AddDate() {
211-
date = "Date today is: " + time.Now().Format("2006-01-02") + "\n"
212+
content += "\n\n" + "Today's date: " + time.Now().Format("2006-01-02")
213+
}
214+
215+
if a.AddEnvironmentInfo() {
216+
content += "\n\n" + getEnvironmentInfo(s.GetWorkingDir())
212217
}
213218

214219
messages = append(messages, chat.Message{
215220
Role: chat.MessageRoleSystem,
216-
Content: a.Instruction() + "\n\n" + date,
221+
Content: content,
217222
})
218223

219224
for _, tool := range a.ToolSets() {

pkg/teamloader/teamloader.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ func Load(ctx context.Context, path string, runConfig latest.RuntimeConfig) (*te
101101
agent.WithName(name),
102102
agent.WithDescription(agentConfig.Description),
103103
agent.WithAddDate(agentConfig.AddDate),
104+
agent.WithAddEnvironmentInfo(agentConfig.AddEnvironmentInfo),
104105
}
105106
models, err := getModelsForAgent(ctx, cfg, &agentConfig, absEnvFiles, options.WithGateway(runConfig.ModelsGateway))
106107
if err != nil {

0 commit comments

Comments
 (0)