on main help sign in
chore: improve shell output and summary to include cwd
c8e2938Kujtim Hoxha
internal/llm/agent/agent.go+3
@@ -22,6 +22,7 @@ import (
22 "github.com/charmbracelet/crush/internal/permission"
22 "github.com/charmbracelet/crush/internal/permission"
23 "github.com/charmbracelet/crush/internal/pubsub"
23 "github.com/charmbracelet/crush/internal/pubsub"
24 "github.com/charmbracelet/crush/internal/session"
24 "github.com/charmbracelet/crush/internal/session"
25+ "github.com/charmbracelet/crush/internal/shell"
25)
26)
26
27
27// Common errors
28// Common errors
@@ -762,6 +763,8 @@ func (a *agent) Summarize(ctx context.Context, sessionID string) error {
762 a.Publish(pubsub.CreatedEvent, event)
763 a.Publish(pubsub.CreatedEvent, event)
763 return
764 return
764 }
765 }
766+ shell := shell.GetPersistentShell(config.Get().WorkingDir())
767+ summary += "\n\n**Current working directory of the persistent shell**\n\n" + shell.GetWorkingDir()
765 event = AgentEvent{
768 event = AgentEvent{
766 Type: AgentEventTypeSummarize,
769 Type: AgentEventTypeSummarize,
767 Progress: "Creating new session...",
770 Progress: "Creating new session...",
internal/llm/tools/bash.go+16−17
@@ -4,7 +4,6 @@ import (
4 "context"
4 "context"
5 "encoding/json"
5 "encoding/json"
6 "fmt"
6 "fmt"
7− "log/slog"
8 "strings"
7 "strings"
9 "time"
8 "time"
10
9
@@ -23,8 +22,10 @@ type BashPermissionsParams struct {
23}
22}
24
23
25type BashResponseMetadata struct {
24type BashResponseMetadata struct {
26− StartTime int64 `json:"start_time"`
25+ StartTime int64 `json:"start_time"`
27− EndTime int64 `json:"end_time"`
26+ EndTime int64 `json:"end_time"`
27+ Output string `json:"output"`
28+ WorkingDirectory string `json:"working_directory"`
28}
29}
29type bashTool struct {
30type bashTool struct {
30 permissions permission.Service
31 permissions permission.Service
@@ -146,6 +147,7 @@ Before executing the command, please follow these steps:
1465. Return Result:
1475. Return Result:
147 - Provide the processed output of the command.
148 - Provide the processed output of the command.
148 - If any errors occurred during execution, include those in the output.
149 - If any errors occurred during execution, include those in the output.
150+ - The result will also have metadata like the cwd (current working directory) at the end, included with <cwd></cwd> tags.
149
151
150Usage notes:
152Usage notes:
151- The command argument is required.
153- The command argument is required.
@@ -389,9 +391,12 @@ func (b *bashTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error)
389 ctx, cancel = context.WithTimeout(ctx, time.Duration(params.Timeout)*time.Millisecond)
391 ctx, cancel = context.WithTimeout(ctx, time.Duration(params.Timeout)*time.Millisecond)
390 defer cancel()
392 defer cancel()
391 }
393 }
392− stdout, stderr, err := shell.
394+
393− GetPersistentShell(b.workingDir).
395+ persistentShell := shell.GetPersistentShell(b.workingDir)
394− Exec(ctx, params.Command)
396+ stdout, stderr, err := persistentShell.Exec(ctx, params.Command)
397+
398+ // Get the current working directory after command execution
399+ currentWorkingDir := persistentShell.GetWorkingDir()
395 interrupted := shell.IsInterrupt(err)
400 interrupted := shell.IsInterrupt(err)
396 exitCode := shell.ExitCode(err)
401 exitCode := shell.ExitCode(err)
397 if exitCode == 0 && !interrupted && err != nil {
402 if exitCode == 0 && !interrupted && err != nil {
@@ -401,15 +406,6 @@ func (b *bashTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error)
401 stdout = truncateOutput(stdout)
406 stdout = truncateOutput(stdout)
402 stderr = truncateOutput(stderr)
407 stderr = truncateOutput(stderr)
403
408
404− slog.Info("Bash command executed",
405− "command", params.Command,
406− "stdout", stdout,
407− "stderr", stderr,
408− "exit_code", exitCode,
409− "interrupted", interrupted,
410− "err", err,
411− )
412−
413 errorMessage := stderr
409 errorMessage := stderr
414 if errorMessage == "" && err != nil {
410 if errorMessage == "" && err != nil {
415 errorMessage = err.Error()
411 errorMessage = err.Error()
@@ -438,9 +434,12 @@ func (b *bashTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error)
438 }
434 }
439
435
440 metadata := BashResponseMetadata{
436 metadata := BashResponseMetadata{
441− StartTime: startTime.UnixMilli(),
437+ StartTime: startTime.UnixMilli(),
442− EndTime: time.Now().UnixMilli(),
438+ EndTime: time.Now().UnixMilli(),
439+ Output: stdout,
440+ WorkingDirectory: currentWorkingDir,
443 }
441 }
442+ stdout += fmt.Sprintf("\n\n<cwd>%s</cwd>", currentWorkingDir)
444 if stdout == "" {
443 if stdout == "" {
445 return WithResponseMetadata(NewTextResponse(BashNoOutput), metadata), nil
444 return WithResponseMetadata(NewTextResponse(BashNoOutput), metadata), nil
446 }
445 }
internal/tui/components/chat/messages/renderer.go+11−2
@@ -212,10 +212,19 @@ func (br bashRenderer) Render(v *toolCallCmp) string {
212 args := newParamBuilder().addMain(cmd).build()
212 args := newParamBuilder().addMain(cmd).build()
213
213
214 return br.renderWithParams(v, "Bash", args, func() string {
214 return br.renderWithParams(v, "Bash", args, func() string {
215+ var meta tools.BashResponseMetadata
216+ if err := br.unmarshalParams(v.result.Metadata, &meta); err != nil {
217+ return renderPlainContent(v, v.result.Content)
218+ }
219+ // for backwards compatibility with older tool calls.
215− if v.result.Content == tools.BashNoOutput {
220+ if meta.Output == "" && v.result.Content != tools.BashNoOutput {
221+ meta.Output = v.result.Content
222+ }
223+
224+ if meta.Output == "" {
216 return ""
225 return ""
217 }
226 }
218− return renderPlainContent(v, v.result.Content)
227+ return renderPlainContent(v, meta.Output)
219 })
228 })
220}
229}
221
230