cmd: put current working dir in the system prompt (#17188)

This commit is contained in:
Parth Sareen
2026-07-15 12:10:28 -07:00
committed by GitHub
parent d590830091
commit 30c390384e
2 changed files with 76 additions and 12 deletions
+37 -12
View File
@@ -215,10 +215,7 @@ func prepareAgentModel(cmd *cobra.Command, client *api.Client, opts *agentTUIOpt
}
func GenerateAgentTUI(cmd *cobra.Command, client *api.Client, opts agentTUIOptions) error {
cwd, err := os.Getwd()
if err != nil {
cwd = ""
}
cwd := agentWorkingDir()
contextWindowForModel := func(ctx context.Context, model string, fallback int) int {
return agentContextWindowForModel(ctx, client, model, fallback)
}
@@ -230,9 +227,9 @@ func GenerateAgentTUI(cmd *cobra.Command, client *api.Client, opts agentTUIOptio
if opts.Model != "" {
registry = agentToolsRegistry(cmd.Context(), client, opts.Model)
}
systemPrompt := agentSystemPrompt(opts.Model, opts.System, "")
systemPrompt := agentSystemPromptWithWorkingDir(opts.Model, opts.System, "", cwd)
_, err = agentchat.Run(cmd.Context(), agentchat.Options{
_, err := agentchat.Run(cmd.Context(), agentchat.Options{
Model: opts.Model,
Client: client,
Tools: registry,
@@ -248,7 +245,7 @@ func GenerateAgentTUI(cmd *cobra.Command, client *api.Client, opts agentTUIOptio
return config.SetLastModel(model)
},
SystemPromptForModel: func(ctx context.Context, model string, registry *coreagent.Registry) string {
return agentSystemPrompt(model, agentSystemFromShow(ctx, client, model), "")
return agentSystemPromptWithWorkingDir(model, agentSystemFromShow(ctx, client, model), "", cwd)
},
SystemPrompt: systemPrompt,
WorkingDir: cwd,
@@ -324,13 +321,31 @@ func agentSelectionDescription(model agentchat.ModelOption) string {
return strings.TrimSpace(model.Description)
}
var agentGetwd = os.Getwd
func agentWorkingDir() string {
cwd, err := agentGetwd()
if err != nil {
return ""
}
return cwd
}
func agentSystemPrompt(modelName string, modelSystem string, extra string) string {
return agentSystemPromptAt(time.Now(), modelName, modelSystem, extra)
return agentSystemPromptWithWorkingDir(modelName, modelSystem, extra, agentWorkingDir())
}
func agentSystemPromptWithWorkingDir(modelName string, modelSystem string, extra string, workingDir string) string {
return agentSystemPromptAtWithWorkingDir(time.Now(), modelName, modelSystem, extra, workingDir)
}
func agentSystemPromptAt(now time.Time, modelName string, modelSystem string, extra string) string {
return agentSystemPromptAtWithWorkingDir(now, modelName, modelSystem, extra, agentWorkingDir())
}
func agentSystemPromptAtWithWorkingDir(now time.Time, modelName string, modelSystem string, extra string, workingDir string) string {
var parts []string
parts = append(parts, agentDefaultSystemPrompt(now, modelName))
parts = append(parts, agentDefaultSystemPromptWithWorkingDir(now, modelName, workingDir))
if strings.TrimSpace(modelSystem) != "" {
parts = append(parts, strings.TrimSpace(modelSystem))
}
@@ -341,22 +356,32 @@ func agentSystemPromptAt(now time.Time, modelName string, modelSystem string, ex
}
func agentDefaultSystemPrompt(now time.Time, modelName string) string {
return agentDefaultSystemPromptWithWorkingDir(now, modelName, agentWorkingDir())
}
func agentDefaultSystemPromptWithWorkingDir(now time.Time, modelName string, workingDir string) string {
date := now.Format("Monday, January 2, 2006")
shellName := "bash"
if runtime.GOOS == "windows" {
shellName = "PowerShell"
}
return strings.Join([]string{
parts := []string{
"You are running in Ollama, in a harness to help the user accomplish tasks, and the model is " + modelName + ".",
"",
"Current date: " + date + ".",
"",
}
if workingDir != "" {
parts = append(parts, "Current working directory: "+strconv.Quote(workingDir)+".", "")
}
parts = append(parts,
"Be concise, practical, and action-oriented. Use tools when they materially help. Verify current or fast-changing facts with web tools when available; otherwise state uncertainty.",
"",
"Use " + shellName + " carefully. Prefer read-only inspection first. Stay within the current working directory unless explicitly asked. Surface intent before risky actions such as writes, deletes, moves, installs, git state changes, service changes, sudo, secrets access, network scripts, or commands outside the working directory. Request approval when required and do not work around denied approvals.",
"Use "+shellName+" carefully. Prefer read-only inspection first. Stay within the current working directory unless explicitly asked. Surface intent before risky actions such as writes, deletes, moves, installs, git state changes, service changes, sudo, secrets access, network scripts, or commands outside the working directory. Request approval when required and do not work around denied approvals.",
"",
"Tell the user about meaningful changes, verification, failures, blockers, assumptions, and risks. Summarize routine tool output instead of dumping it.",
}, "\n")
)
return strings.Join(parts, "\n")
}
func agentSystemFromShow(ctx context.Context, client *api.Client, modelName string) string {
+39
View File
@@ -1,7 +1,11 @@
package cmd
import (
"errors"
"strconv"
"strings"
"testing"
"time"
"github.com/spf13/cobra"
@@ -10,6 +14,41 @@ import (
agentchat "github.com/ollama/ollama/cmd/tui/chat"
)
func TestAgentSystemPromptIncludesSessionWorkingDirOnce(t *testing.T) {
workingDir := t.TempDir()
prompt := agentSystemPromptAtWithWorkingDir(
time.Date(2026, time.July, 14, 0, 0, 0, 0, time.UTC),
"test-model",
"model instruction",
"caller instruction",
workingDir,
)
workingDirInstruction := "Current working directory: " + strconv.Quote(workingDir) + "."
if got := strings.Count(prompt, workingDirInstruction); got != 1 {
t.Fatalf("working directory instruction count = %d, want 1:\n%s", got, prompt)
}
for _, want := range []string{"model instruction", "caller instruction"} {
if !strings.Contains(prompt, want) {
t.Fatalf("prompt missing %q:\n%s", want, prompt)
}
}
}
func TestAgentWorkingDirIgnoresGetwdFailure(t *testing.T) {
original := agentGetwd
agentGetwd = func() (string, error) {
return "", errors.New("getwd failed")
}
t.Cleanup(func() {
agentGetwd = original
})
if got := agentWorkingDir(); got != "" {
t.Fatalf("working directory = %q, want empty on getwd failure", got)
}
}
func TestAgentSelectionItemsUseLaunchSections(t *testing.T) {
items := agentSelectionItems([]agentchat.ModelOption{
{Name: "glm-5.2:cloud", Description: "cloud", Recommended: true, Cloud: true},