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
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@
!./**/*.template
!./**/*.go
!./**/*.txt
!./**/*.txt
!/pkg/config/default-agent.yaml
3 changes: 1 addition & 2 deletions cmd/root/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

"github.com/docker/cagent/pkg/build"
"github.com/docker/cagent/pkg/cli"
"github.com/docker/cagent/pkg/filesystem"
"github.com/docker/cagent/pkg/telemetry"
)

Expand Down Expand Up @@ -44,5 +43,5 @@ func (f *buildFlags) runBuildCommand(cmd *cobra.Command, args []string) error {
dockerImageName = args[1]
}

return build.DockerImage(ctx, out, agentFilename, filesystem.AllowAll, dockerImageName, f.opts)
return build.DockerImage(ctx, out, agentFilename, dockerImageName, f.opts)
}
2 changes: 1 addition & 1 deletion cmd/root/feedback.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ func newFeedbackCmd() *cobra.Command {
func runFeedbackCommand(cmd *cobra.Command, args []string) error {
telemetry.TrackCommand("feedback", args)

fmt.Fprintln(cmd.OutOrStdout(), "Feel free to give feedback:\n", feedback.FeedbackLink)
fmt.Fprintln(cmd.OutOrStdout(), "Feel free to give feedback:\n", feedback.Link)
return nil
}
2 changes: 1 addition & 1 deletion cmd/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ For any feedback, please visit: %s
We collect anonymous usage data to help improve cagent. To disable:
- Set environment variable: TELEMETRY_ENABLED=false

`, feedback.FeedbackLink)
`, feedback.Link)
fmt.Fprint(stderr, startupMsg)
}

Expand Down
4 changes: 2 additions & 2 deletions docs/PROVIDERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

## Add provider alias

Add a new `Alias` to `ProviderAliases` [`pkg/model/provider/provider.go`](https://github.com/docker/cagent/blob/main/pkg/model/provider/provider.go)
Add a new `Alias` to `Aliases` [`pkg/model/provider/provider.go`](https://github.com/docker/cagent/blob/main/pkg/model/provider/provider.go)

```go
var ProviderAliases = map[string]Alias{
var Aliases = map[string]Alias{
"requesty": {
APIType: "openai",
BaseURL: "https://router.requesty.ai/v1",
Expand Down
4 changes: 2 additions & 2 deletions pkg/a2a/executor_wrapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ type mockQueue struct {
events []a2a.Event
}

func (m *mockQueue) Write(ctx context.Context, event a2a.Event) error {
func (m *mockQueue) Write(_ context.Context, event a2a.Event) error {
m.events = append(m.events, event)
return nil
}

func (m *mockQueue) Read(ctx context.Context) (a2a.Event, error) {
func (m *mockQueue) Read(context.Context) (a2a.Event, error) {
return nil, nil
}

Expand Down
18 changes: 9 additions & 9 deletions pkg/acp/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func (a *Agent) Initialize(ctx context.Context, params acp.InitializeRequest) (a
}

// NewSession implements [acp.Agent]
func (a *Agent) NewSession(ctx context.Context, params acp.NewSessionRequest) (acp.NewSessionResponse, error) {
func (a *Agent) NewSession(context.Context, acp.NewSessionRequest) (acp.NewSessionResponse, error) {
sid := uuid.New().String()
slog.Debug("ACP NewSession called", "session_id", sid)

Expand All @@ -110,19 +110,19 @@ func (a *Agent) NewSession(ctx context.Context, params acp.NewSessionRequest) (a
}

// Authenticate implements [acp.Agent]
func (a *Agent) Authenticate(ctx context.Context, params acp.AuthenticateRequest) (acp.AuthenticateResponse, error) {
func (a *Agent) Authenticate(context.Context, acp.AuthenticateRequest) (acp.AuthenticateResponse, error) {
slog.Debug("ACP Authenticate called")
return acp.AuthenticateResponse{}, nil
}

// LoadSession implements [acp.Agent] (optional, not supported)
func (a *Agent) LoadSession(ctx context.Context, params acp.LoadSessionRequest) (acp.LoadSessionResponse, error) {
func (a *Agent) LoadSession(context.Context, acp.LoadSessionRequest) (acp.LoadSessionResponse, error) {
slog.Debug("ACP LoadSession called (not supported)")
return acp.LoadSessionResponse{}, fmt.Errorf("load session not supported")
}

// Cancel implements [acp.Agent]
func (a *Agent) Cancel(ctx context.Context, params acp.CancelNotification) error {
func (a *Agent) Cancel(_ context.Context, params acp.CancelNotification) error {
sid := string(params.SessionId)
slog.Debug("ACP Cancel called", "session_id", sid)

Expand All @@ -138,7 +138,7 @@ func (a *Agent) Cancel(ctx context.Context, params acp.CancelNotification) error
}

// Prompt implements [acp.Agent]
func (a *Agent) Prompt(ctx context.Context, params acp.PromptRequest) (acp.PromptResponse, error) {
func (a *Agent) Prompt(_ context.Context, params acp.PromptRequest) (acp.PromptResponse, error) {
sid := string(params.SessionId)
slog.Debug("ACP Prompt called", "session_id", sid)

Expand Down Expand Up @@ -201,7 +201,7 @@ func (a *Agent) Prompt(ctx context.Context, params acp.PromptRequest) (acp.Promp
}

// SetSessionMode implements acp.Agent (optional)
func (a *Agent) SetSessionMode(ctx context.Context, params acp.SetSessionModeRequest) (acp.SetSessionModeResponse, error) {
func (a *Agent) SetSessionMode(context.Context, acp.SetSessionModeRequest) (acp.SetSessionModeResponse, error) {
// We don't implement session modes, cagent agents have only one mode (for now? ;) ).
return acp.SetSessionModeResponse{}, nil
}
Expand Down Expand Up @@ -325,7 +325,7 @@ func (a *Agent) handleMaxIterationsReached(ctx context.Context, acpSess *Session
permResp, err := a.conn.RequestPermission(ctx, acp.RequestPermissionRequest{
SessionId: acp.SessionId(acpSess.id),
ToolCall: acp.RequestPermissionToolCall{
ToolCallId: acp.ToolCallId("max_iterations"),
ToolCallId: "max_iterations",
Title: acp.Ptr(fmt.Sprintf("Maximum iterations (%d) reached", e.MaxIterations)),
Kind: acp.Ptr(acp.ToolKindExecute),
Status: acp.Ptr(acp.ToolCallStatusPending),
Expand All @@ -334,12 +334,12 @@ func (a *Agent) handleMaxIterationsReached(ctx context.Context, acpSess *Session
{
Kind: acp.PermissionOptionKindAllowOnce,
Name: "Continue",
OptionId: acp.PermissionOptionId("continue"),
OptionId: "continue",
},
{
Kind: acp.PermissionOptionKindRejectOnce,
Name: "Stop",
OptionId: acp.PermissionOptionId("stop"),
OptionId: "stop",
},
},
})
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/pagination_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func TestPaginateMessages_MaxLimit(t *testing.T) {
}

func TestPaginateMessages_EmptyMessages(t *testing.T) {
messages := []session.Message{}
var messages []session.Message

params := PaginationParams{
Limit: 10,
Expand Down
3 changes: 1 addition & 2 deletions pkg/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"github.com/goccy/go-yaml"

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

//go:embed Dockerfile.template
Expand All @@ -31,7 +30,7 @@ type Printer interface {
Println(a ...any)
}

func DockerImage(ctx context.Context, out Printer, agentFilename string, fs filesystem.FS, dockerImageName string, opts Options) error {
func DockerImage(ctx context.Context, out Printer, agentFilename, dockerImageName string, opts Options) error {
agentSource, err := config.Resolve(agentFilename)
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion pkg/config/auto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type mockEnvProvider struct {
envVars map[string]string
}

func (m *mockEnvProvider) Get(ctx context.Context, name string) string {
func (m *mockEnvProvider) Get(_ context.Context, name string) string {
return m.envVars[name]
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/config/gather.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func GatherEnvVarsForModels(cfg *latest.Config) []string {
model := cfg.Models[modelName]

// Use the token environment variable from the alias if available
if alias, exists := provider.ProviderAliases[model.Provider]; exists {
if alias, exists := provider.Aliases[model.Provider]; exists {
if alias.TokenEnvVar != "" {
requiredEnv[alias.TokenEnvVar] = true
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/config/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
//go:embed default-agent.yaml
var defaultAgent []byte

// ResolveSource resolves an agent file reference (local file or OCI image) to a local file path
// ResolveSources resolves an agent file reference (local file or OCI image) to a local file path
// For OCI references, always checks remote for updates but falls back to local cache if offline
func ResolveSources(agentsPath string) (Sources, error) {
resolvedPath, err := resolve(agentsPath)
Expand Down
34 changes: 0 additions & 34 deletions pkg/config/resolve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,40 +203,6 @@ agents:
assert.Equal(t, absPath, resolved)
}

func TestResolveAgentFile_RelativeDirectory(t *testing.T) {
t.Parallel()

tmpDir := t.TempDir()
agentContent := `version: "1"
agents:
root:
model: openai/gpt-4o
description: Test agent
instruction: You are a test agent
`
agentFile := filepath.Join(tmpDir, "agent.yaml")
require.NoError(t, os.WriteFile(agentFile, []byte(agentContent), 0o644))

// Change to temp directory and use relative path
originalWd, err := os.Getwd()
require.NoError(t, err)
defer func() {
if err := os.Chdir(originalWd); err != nil {
t.Logf("Failed to restore working directory: %v", err)
}
}()

require.NoError(t, os.Chdir(tmpDir))

// Resolve relative path "."
resolved, err := resolve(".")
require.NoError(t, err)

absPath, err := filepath.Abs(".")
require.NoError(t, err)
assert.Equal(t, absPath, resolved)
}

func TestResolveAgentFile_NonExistentDirectory(t *testing.T) {
t.Parallel()

Expand Down
55 changes: 0 additions & 55 deletions pkg/creator/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,10 @@ import (
_ "embed"
"encoding/json"
"fmt"
"log/slog"
"os"
"strings"

"github.com/docker/cagent/pkg/agent"
"github.com/docker/cagent/pkg/config"
"github.com/docker/cagent/pkg/config/latest"
"github.com/docker/cagent/pkg/environment"
"github.com/docker/cagent/pkg/model/provider/anthropic"
"github.com/docker/cagent/pkg/model/provider/options"
"github.com/docker/cagent/pkg/runtime"
"github.com/docker/cagent/pkg/session"
"github.com/docker/cagent/pkg/team"
"github.com/docker/cagent/pkg/teamloader"
"github.com/docker/cagent/pkg/tools"
Expand Down Expand Up @@ -76,53 +68,6 @@ func (f *fsToolset) customWriteFileHandler(ctx context.Context, toolCall tools.T
return f.originalWriteFileHandler(ctx, toolCall)
}

func CreateAgent(ctx context.Context, baseDir, prompt string, runConfig *config.RuntimeConfig) (out, path string, err error) {
llm, err := anthropic.NewClient(
ctx,
&latest.ModelConfig{
Provider: "anthropic",
Model: "claude-sonnet-4-0",
MaxTokens: 64000,
},
environment.NewDefaultProvider(),
options.WithGateway(runConfig.ModelsGateway),
)
if err != nil {
return "", "", fmt.Errorf("failed to create LLM client: %w", err)
}

slog.Info("Generating agent configuration....")

fsToolset := fsToolset{inner: builtin.NewFilesystemTool([]string{baseDir})}
newTeam := team.New(
team.WithAgents(
agent.New(
"root",
agentBuilderInstructions,
agent.WithModel(llm),
agent.WithToolSets(
builtin.NewShellTool(os.Environ(), runConfig),
&fsToolset,
),
)))
rt, err := runtime.New(newTeam)
if err != nil {
return "", "", fmt.Errorf("failed to create runtime: %w", err)
}

sess := session.New(
session.WithUserMessage(prompt),
session.WithToolsApproved(true),
)

messages, err := rt.Run(ctx, sess)
if err != nil {
return "", "", fmt.Errorf("failed to run session: %w", err)
}

return messages[len(messages)-1].Message.Content, fsToolset.path, nil
}

func Agent(ctx context.Context, runConfig *config.RuntimeConfig, modelNameOverride string) (*team.Team, error) {
usableProviders := config.AvailableProviders(ctx, runConfig.ModelsGateway, runConfig.EnvProvider())

Expand Down
2 changes: 1 addition & 1 deletion pkg/feedback/feedback.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package feedback

var FeedbackLink = "https://docker.qualtrics.com/jfe/form/SV_cNsCIg92nQemlfw"
var Link = "https://docker.qualtrics.com/jfe/form/SV_cNsCIg92nQemlfw"
17 changes: 0 additions & 17 deletions pkg/filesystem/config.go

This file was deleted.

2 changes: 1 addition & 1 deletion pkg/js/expand.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (exp *Expander) Expand(ctx context.Context, text string) string {
return fmt.Sprintf("%v", result.Export())
}

func ExpandString(ctx context.Context, str string, values map[string]string) (string, error) {
func ExpandString(_ context.Context, str string, values map[string]string) (string, error) {
vm := goja.New()

for k, v := range values {
Expand Down
12 changes: 6 additions & 6 deletions pkg/model/provider/anthropic/beta_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ func TestCountAnthropicTokensBeta_Success(t *testing.T) {

// TestCountAnthropicTokensBeta_NoAPIKey tests error when API key is missing
func TestCountAnthropicTokensBeta_NoAPIKey(t *testing.T) {
messages := []anthropic.BetaMessageParam{}
system := []anthropic.BetaTextBlockParam{}
var messages []anthropic.BetaMessageParam
var system []anthropic.BetaTextBlockParam

client := anthropic.NewClient(
option.WithAPIKey("test-key"),
Expand All @@ -80,8 +80,8 @@ func TestCountAnthropicTokensBeta_ServerError(t *testing.T) {
}))
defer server.Close()

messages := []anthropic.BetaMessageParam{}
system := []anthropic.BetaTextBlockParam{}
var messages []anthropic.BetaMessageParam
var system []anthropic.BetaTextBlockParam

client := anthropic.NewClient(
option.WithAPIKey("test-key"),
Expand Down Expand Up @@ -111,8 +111,8 @@ func TestCountAnthropicTokensBeta_WithTools(t *testing.T) {
}))
defer server.Close()

messages := []anthropic.BetaMessageParam{}
system := []anthropic.BetaTextBlockParam{}
var messages []anthropic.BetaMessageParam
var system []anthropic.BetaTextBlockParam
tools := []anthropic.BetaToolUnionParam{
{OfTool: &anthropic.BetaToolParam{
Name: "test_tool",
Expand Down
Loading