tui: track live working directory

This commit is contained in:
ParthSareen 2026-06-11 20:39:35 -07:00
parent cb8af634b3
commit 76eb5a9dc9
2 changed files with 56 additions and 11 deletions

View file

@ -293,11 +293,12 @@ type chatCompactProgressMsg struct {
type chatTickMsg struct{}
type chatModel struct {
ctx context.Context
opts ChatOptions
chatID string
messages []api.Message
entries []chatEntry
ctx context.Context
opts ChatOptions
chatID string
messages []api.Message
entries []chatEntry
workingDir string
input []rune
queued []string
@ -382,6 +383,7 @@ func RunAgentChat(ctx context.Context, opts ChatOptions) (*ChatResult, error) {
opts: opts,
chatID: opts.ChatID,
messages: slices.Clone(opts.Messages),
workingDir: opts.WorkingDir,
reviewApproval: reviewApproval,
permissionMode: newChatPermissionMode(autoApproveTools),
promptHistory: initialPromptHistory(ctx, opts),
@ -446,7 +448,7 @@ func (m chatModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if msg.result != nil {
m.messages = msg.result.Messages
if msg.result.WorkingDir != "" {
m.opts.WorkingDir = msg.result.WorkingDir
m.workingDir = msg.result.WorkingDir
}
m.refreshContextWindowTokens(m.responseModelName(&msg.result.Latest))
m.contextTokens = m.estimatePromptTokens(m.messages, "")
@ -747,8 +749,10 @@ func (m *chatModel) resetChat(status string) (tea.Model, tea.Cmd) {
func (m *chatModel) resetWorkingDir() {
if m.opts.RootDir != "" {
m.opts.WorkingDir = m.opts.RootDir
m.workingDir = m.opts.RootDir
return
}
m.workingDir = m.opts.WorkingDir
}
func (m *chatModel) startManualCompaction() (tea.Model, tea.Cmd) {
@ -858,7 +862,7 @@ func (m *chatModel) startRunWithPrompt(displayInput, userInput, extraSystemPromp
Events: chatEventSink{ctx: runCtx, ch: events},
Tools: m.opts.Tools,
Approval: m.approvalHandlerForRun(events),
WorkingDir: m.opts.WorkingDir,
WorkingDir: m.currentWorkingDir(),
Compactor: m.opts.Compactor,
}
opts := coreagent.RunOptions{
@ -1388,7 +1392,7 @@ func (m *chatModel) applyAgentEvent(event coreagent.Event) {
m.thinking = false
m.thinkingTokens = 0
if event.WorkingDir != "" {
m.opts.WorkingDir = event.WorkingDir
m.workingDir = event.WorkingDir
}
startedAt := m.toolStartedAt(event.ToolCallID)
status := "done"
@ -2400,7 +2404,7 @@ func (m chatModel) mentionCompletions() []chatCompletion {
return nil
}
workingDir := m.opts.WorkingDir
workingDir := m.currentWorkingDir()
if strings.TrimSpace(workingDir) == "" {
var err error
workingDir, err = os.Getwd()
@ -3561,8 +3565,15 @@ func (m chatModel) responseModelName(response *api.ChatResponse) string {
return m.opts.Model
}
func (m chatModel) currentWorkingDir() string {
if strings.TrimSpace(m.workingDir) != "" {
return m.workingDir
}
return m.opts.WorkingDir
}
func (m chatModel) cwdStatus() string {
workingDir := strings.TrimSpace(m.opts.WorkingDir)
workingDir := strings.TrimSpace(m.currentWorkingDir())
rootDir := strings.TrimSpace(m.opts.RootDir)
if workingDir == "" || rootDir == "" {
return ""

View file

@ -750,6 +750,40 @@ func TestChatViewShowsSessionCWDWhenChanged(t *testing.T) {
}
}
func TestChatToolFinishedUpdatesLiveWorkingDirOnly(t *testing.T) {
root := t.TempDir()
subdir := filepath.Join(root, "sub")
if err := os.Mkdir(subdir, 0o755); err != nil {
t.Fatal(err)
}
m := chatModel{
width: 140,
height: 12,
opts: ChatOptions{
RootDir: root,
WorkingDir: root,
},
workingDir: root,
}
m.applyAgentEvent(coreagent.Event{
Type: coreagent.EventToolFinished,
ToolCallID: "call-1",
ToolName: "bash",
WorkingDir: subdir,
})
if m.workingDir != subdir {
t.Fatalf("workingDir = %q, want %q", m.workingDir, subdir)
}
if m.opts.WorkingDir != root {
t.Fatalf("opts.WorkingDir mutated to %q, want %q", m.opts.WorkingDir, root)
}
if view := stripANSI(m.View()); !strings.Contains(view, "cwd ./sub") {
t.Fatalf("view missing cwd status: %q", view)
}
}
func TestChatViewPadsToTerminalHeight(t *testing.T) {
m := chatModel{
input: []rune("hello"),