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
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
run: go build -v ./...

- name: unit-test
run: go test -v ./...
run: go test -v -cover ./...

golangci:
runs-on: ubuntu-latest
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
agent
build/*
docs/generated
data
data
*agentcli.md
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ Build agent CLI
make build
```

Run the agent ()
Run the documentation agent
```
./build/agent-cli run documentor --repo https://github.com/ATMackay/agent.git --output agentcli-doc.md
```
./build/agent-cli run documentor --repo https://github.com/ATMackay/agent
```

Documentation will be written to `doc.agentcli.md`.
1 change: 1 addition & 0 deletions agents/documentor/prompt.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Workflow:
3. Prefer entry points, cmd/, internal/, pkg/, config, and core domain files.
4. Skip tests, generated files, vendor, binaries, and irrelevant assets unless they are central.
5. Do not read more than max_files files.
6. Use resources efficiently. Reading files can be expensive so inspect them in the order that gets highest insight, you may reach the max_files limit before all files can be read.
6. Call read_repo_file for each selected file.
7. Write detailed maintainers' documentation in markdown.
8. Call write_output_file with the completed markdown and output_path.
Expand Down
18 changes: 15 additions & 3 deletions cmd/documentor.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"log/slog"
"os"
"time"

"github.com/ATMackay/agent/agents/documentor"
"github.com/ATMackay/agent/model"
Expand Down Expand Up @@ -133,13 +134,24 @@ func NewDocumentorCmd() *cobra.Command {
"session_id", resp.Session.ID(),
)

start := time.Now()
for event, err := range r.Run(ctx, userCLI, resp.Session.ID(), userMsg, agentpkg.RunConfig{}) {
if err != nil {
return fmt.Errorf("agent error: %w", err)
}
// handle event (log)
slog.Info("event", "id", event.ID, "author", event.Author)
if event.UsageMetadata == nil {
continue
}
slog.Info("event", "author", event.Author, "event_id", event.ID, "prompt_tokens", event.UsageMetadata.PromptTokenCount, "total_tokens", event.UsageMetadata.TotalTokenCount)
if event.Content == nil {
continue
}
for _, p := range event.Content.Parts {
slog.Debug("response_content", "role", event.Content.Role, "text", p.Text, "function_call", p.FunctionCall)
}
}
slog.Info("Agent execution complete", "time_taken", time.Since(start))

if _, err := os.Stat(output); err != nil {
return fmt.Errorf("agent finished but output file was not created: %w", err)
Expand All @@ -153,9 +165,9 @@ func NewDocumentorCmd() *cobra.Command {
cmd.Flags().StringVar(&repoURL, "repo", "", "GitHub repository URL")
cmd.Flags().StringVar(&ref, "ref", "", "Optional branch, tag, or commit")
cmd.Flags().StringVar(&pathPrefix, "path", "", "Optional subdirectory to document")
cmd.Flags().StringVar(&output, "output", "", "Output file path for the generated markdown")
cmd.Flags().StringVar(&output, "output", "doc.agentcli.md", "Output file path for the generated markdown")
cmd.Flags().IntVar(&maxFiles, "max-files", 50, "Maximum number of files to read")
cmd.Flags().StringVar(&modelName, "model", "", "LLM to use")
cmd.Flags().StringVar(&modelName, "model", "claude-opus-4-1-20250805", "Language model to use")
cmd.Flags().StringVar(&modelProvider, "provider", "claude", "LLM provider to use (claude or gemini)")

// Bind flags to environment variables
Expand Down
12 changes: 4 additions & 8 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ func NewRunCmd() *cobra.Command {
if err := initLogging(logLevel, logFormat); err != nil {
return fmt.Errorf("failed to initialize logger: %w", err)
}

return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
if isBuildDirty() {
slog.Warn("running a DIRTY build (uncommitted changes present) — do not run in production")
}
Expand All @@ -43,12 +39,12 @@ func NewRunCmd() *cobra.Command {
// TODO - more agent types

// Bind flags and ENV vars
cmd.Flags().String("log-level", "info", "Log level (debug, info, warn, error, fatal, panic)")
cmd.Flags().String("log-format", "text", "Log format (text, json)")
cmd.PersistentFlags().String("log-level", "info", "Log level (debug, info, warn, error, fatal, panic)")
cmd.PersistentFlags().String("log-format", "text", "Log format (text, json)")

// Bind flags to environment variables
must(viper.BindPFlag("log-level", cmd.Flags().Lookup("log-level")))
must(viper.BindPFlag("log-format", cmd.Flags().Lookup("log-format")))
must(viper.BindPFlag("log-level", cmd.PersistentFlags().Lookup("log-level")))
must(viper.BindPFlag("log-format", cmd.PersistentFlags().Lookup("log-format")))

// Set environment variable prefix and read from environment
viper.SetEnvPrefix(EnvPrefix) // Environment variables will be prefixed with CHECKOUT_
Expand Down
2 changes: 1 addition & 1 deletion model/claude.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func newClaude(ctx context.Context, cfg *Config) (model.LLM, error) {
return nil, fmt.Errorf("anthropic api key is required for claude")
}
if cfg.Model == "" {
cfg.Model = string(anthropic.ModelClaudeSonnet4_20250514)
cfg.Model = string(anthropic.ModelClaudeOpus4_1_20250805)
}
return anthropicadk.NewModel(cfg.Model, anthropicadk.AnthropicOption(option.WithAPIKey(cfg.apiKey))), nil
}
41 changes: 41 additions & 0 deletions model/model_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package model

import (
"context"
"testing"
)

func Test_NewModel(t *testing.T) {
t.Run("unsupported-provider", func(t *testing.T) {
_, err := New(context.Background(), &Config{Provider: "not-supported"})
if err == nil {
t.Fatal("expected non-nil error")
}
})
t.Run("empty-config-claude", func(t *testing.T) {
_, err := New(context.Background(), &Config{})
if err == nil {
t.Fatal("expected non-nil error")
}
})
t.Run("empty-config-gemini", func(t *testing.T) {
_, err := New(context.Background(), &Config{Provider: ProviderGemini})
if err == nil {
t.Fatal("expected non-nil error")
}
})

t.Run("happy-path-claude", func(t *testing.T) {
cfg := &Config{}
_, err := New(context.Background(), cfg.WithAPIKey("api-key"))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
})
t.Run("happy-path-gemini", func(t *testing.T) {
_, err := New(context.Background(), &Config{Provider: ProviderGemini, apiKey: "api-key"})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
})
}
Loading