Skip to content

fix model typo and limit project size in system prompt to 4K max #239

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ func configureViper() {
viper.AddConfigPath("$HOME")
viper.AddConfigPath(fmt.Sprintf("$XDG_CONFIG_HOME/%s", appName))
viper.AddConfigPath(fmt.Sprintf("$HOME/.config/%s", appName))
// this allows set variables more easily
// e.g. OPENCODE_AGENTS_CODER_MODEL=gpt-4.1-mini
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.SetEnvPrefix(strings.ToUpper(appName))
viper.AutomaticEnv()
}
Expand Down
2 changes: 1 addition & 1 deletion internal/llm/models/openai.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ var OpenAIModels = map[ModelID]Model{
ID: GPT41Mini,
Name: "GPT 4.1 mini",
Provider: ProviderOpenAI,
APIModel: "gpt-4.1",
APIModel: "gpt-4.1-mini",
CostPer1MIn: 0.40,
CostPer1MInCached: 0.10,
CostPer1MOutCached: 0.0,
Expand Down
17 changes: 13 additions & 4 deletions internal/llm/prompt/coder.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package prompt

import (
"context"
"fmt"
"os"
"path/filepath"
Expand Down Expand Up @@ -167,15 +166,25 @@ NEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTAN

You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail.`

// MAX_PROJECT_SIZE limits the project hierarchy to 4K
const MAX_PROJECT_SIZE = 4 * 1024

func getEnvironmentInfo() string {
cwd := config.WorkingDirectory()
isGit := isGitRepo(cwd)
platform := runtime.GOOS
date := time.Now().Format("1/2/2006")
ls := tools.NewLsTool()
r, _ := ls.Run(context.Background(), tools.ToolCall{
Input: `{"path":"."}`,
r, _ := ls.RunWithParams(tools.LSParams{
Path: ".",
MaxDepth: 6,
})

// no more than 4k
projectContent := r.Content
if len(r.Content) > MAX_PROJECT_SIZE {
projectContent = r.Content[:MAX_PROJECT_SIZE] + "..."
}
return fmt.Sprintf(`Here is useful information about the environment you are running in:
<env>
Working directory: %s
Expand All @@ -186,7 +195,7 @@ Today's date: %s
<project>
%s
</project>
`, cwd, boolToYesNo(isGit), platform, date, r.Content)
`, cwd, boolToYesNo(isGit), platform, date, projectContent)
}

func isGitRepo(dir string) bool {
Expand Down
53 changes: 48 additions & 5 deletions internal/llm/tools/ls.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import (
)

type LSParams struct {
Path string `json:"path"`
Ignore []string `json:"ignore"`
Path string `json:"path"`
MaxDepth int `json:"max_depth"`
Ignore []string `json:"ignore"`
}

type TreeNode struct {
Expand Down Expand Up @@ -63,7 +64,7 @@ TIPS:
- Combine with other tools for more effective exploration`
)

func NewLsTool() BaseTool {
func NewLsTool() *lsTool {
return &lsTool{}
}

Expand All @@ -76,6 +77,11 @@ func (l *lsTool) Info() ToolInfo {
"type": "string",
"description": "The path to the directory to list (defaults to current working directory)",
},
"max_depth": map[string]any{
// json schema integer: https://json-schema.org/understanding-json-schema/reference/numeric
"type": "integer",
"description": "Limit the maximum depth to traversing depths(defaults to no limit, 0 or negative values also treated as no limit)",
},
"ignore": map[string]any{
"type": "array",
"description": "List of glob patterns to ignore",
Expand All @@ -93,7 +99,10 @@ func (l *lsTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error) {
if err := json.Unmarshal([]byte(call.Input), &params); err != nil {
return NewTextErrorResponse(fmt.Sprintf("error parsing parameters: %s", err)), nil
}
return l.RunWithParams(params)
}

func (l *lsTool) RunWithParams(params LSParams) (ToolResponse, error) {
searchPath := params.Path
if searchPath == "" {
searchPath = config.WorkingDirectory()
Expand All @@ -107,7 +116,7 @@ func (l *lsTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error) {
return NewTextErrorResponse(fmt.Sprintf("path does not exist: %s", searchPath)), nil
}

files, truncated, err := listDirectory(searchPath, params.Ignore, MaxLSFiles)
files, truncated, err := listDirectory(searchPath, params.Ignore, MaxLSFiles, params.MaxDepth)
if err != nil {
return ToolResponse{}, fmt.Errorf("error listing directory: %w", err)
}
Expand All @@ -128,7 +137,31 @@ func (l *lsTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error) {
), nil
}

func listDirectory(initialPath string, ignorePatterns []string, limit int) ([]string, bool, error) {
// shouldSkipDirDueToDepth checks if a directory should be skipped due to depth limits
// Returns true if the directory should be skipped, false otherwise
func shouldSkipDirDueToDepth(initialPath, currentPath string, maxDepth int) bool {
if maxDepth <= 0 {
return false
}

relPath, err := filepath.Rel(initialPath, currentPath)
if err != nil {
return false // Don't skip on error
}

// Calculate depth by counting directory separators
depth := 0
if relPath != "." {
// If there are no separators, it's still depth 1 (direct child)
// If there are separators, count them and add 1
depth = strings.Count(relPath, string(filepath.Separator)) + 1
}

// Skip directory traversal if we're at or beyond max depth
return depth >= maxDepth
}

func listDirectory(initialPath string, ignorePatterns []string, limit int, maxDepth int) ([]string, bool, error) {
var results []string
truncated := false

Expand All @@ -144,6 +177,16 @@ func listDirectory(initialPath string, ignorePatterns []string, limit int) ([]st
return nil
}

// Check if we should skip due to depth limits (only for directories)
if info.IsDir() && shouldSkipDirDueToDepth(initialPath, path, maxDepth) {
// Still include this directory in results if it's not the initial path
if path != initialPath {
path = path + string(filepath.Separator)
results = append(results, path)
}
return filepath.SkipDir
}

if path != initialPath {
if info.IsDir() {
path = path + string(filepath.Separator)
Expand Down
Loading