feat: auto permission mode, edit diffs, truncated tool output
- Default permission mode changed to 'auto' (read-only auto-allows, writes prompt) - fs.edit now shows diff-style output: line numbers, context ±3 lines, + for added (green), - for removed (red) - Tool output truncated to 10 lines in TUI with "+N lines (Ctrl+O to expand)" indicator - Mistral SDK bumped to v1.3.0
This commit is contained in:
@@ -41,7 +41,7 @@ func main() {
|
||||
system = flag.String("system", defaultSystem, "system prompt")
|
||||
apiKey = flag.String("api-key", "", "API key (or set MISTRAL_API_KEY env)")
|
||||
maxTurns = flag.Int("max-turns", 50, "max tool-calling rounds per turn")
|
||||
permMode = flag.String("permission", "default", "permission mode (default, accept_edits, bypass, deny, plan, auto)")
|
||||
permMode = flag.String("permission", "auto", "permission mode (default, accept_edits, bypass, deny, plan, auto)")
|
||||
incognito = flag.Bool("incognito", false, "incognito mode — no persistence, no learning")
|
||||
verbose = flag.Bool("verbose", false, "enable debug logging")
|
||||
version = flag.Bool("version", false, "print version and exit")
|
||||
|
||||
2
go.mod
2
go.mod
@@ -8,7 +8,7 @@ require (
|
||||
charm.land/glamour/v2 v2.0.0
|
||||
charm.land/lipgloss/v2 v2.0.2
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/VikingOwl91/mistral-go-sdk v1.2.1
|
||||
github.com/VikingOwl91/mistral-go-sdk v1.3.0
|
||||
github.com/anthropics/anthropic-sdk-go v1.29.0
|
||||
github.com/openai/openai-go v1.12.0
|
||||
golang.org/x/text v0.27.0
|
||||
|
||||
2
go.sum
2
go.sum
@@ -19,6 +19,8 @@ github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ
|
||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||
github.com/VikingOwl91/mistral-go-sdk v1.2.1 h1:6OQMtOzJUFcvFUEtbX9VlglUPBn+dKOrQPnyoVKlpkA=
|
||||
github.com/VikingOwl91/mistral-go-sdk v1.2.1/go.mod h1:f4emNtHUx2zSqY3V0LBz6lNI1jE6q/zh+SEU+/hJ0i4=
|
||||
github.com/VikingOwl91/mistral-go-sdk v1.3.0 h1:OkTsodDE5lmdf7p2cwScqD2vIk8sScQ2IGk65dUjuz0=
|
||||
github.com/VikingOwl91/mistral-go-sdk v1.3.0/go.mod h1:f4emNtHUx2zSqY3V0LBz6lNI1jE6q/zh+SEU+/hJ0i4=
|
||||
github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
|
||||
github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
|
||||
|
||||
@@ -102,8 +102,68 @@ func (t *EditTool) Execute(_ context.Context, args json.RawMessage) (tool.Result
|
||||
replacements = count
|
||||
}
|
||||
|
||||
// Generate diff-style output with context
|
||||
diff := buildEditDiff(content, a.OldString, a.NewString, a.Path, replacements)
|
||||
|
||||
return tool.Result{
|
||||
Output: fmt.Sprintf("Replaced %d occurrence(s) in %s", replacements, a.Path),
|
||||
Output: diff,
|
||||
Metadata: map[string]any{"replacements": replacements, "path": a.Path},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// buildEditDiff generates a diff display with context lines around the edit.
|
||||
func buildEditDiff(original, oldStr, newStr, path string, replacements int) string {
|
||||
contextLines := 3
|
||||
lines := strings.Split(original, "\n")
|
||||
|
||||
// Find the line where the old string starts
|
||||
editStart := -1
|
||||
for i, line := range lines {
|
||||
if strings.Contains(line, strings.Split(oldStr, "\n")[0]) {
|
||||
editStart = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if editStart == -1 {
|
||||
return fmt.Sprintf("Replaced %d occurrence(s) in %s", replacements, path)
|
||||
}
|
||||
|
||||
oldLines := strings.Split(oldStr, "\n")
|
||||
newLines := strings.Split(newStr, "\n")
|
||||
|
||||
var b strings.Builder
|
||||
fmt.Fprintf(&b, "Edit(%s)\n", path)
|
||||
fmt.Fprintf(&b, " Added %d lines, removed %d lines\n", len(newLines), len(oldLines))
|
||||
|
||||
// Context before
|
||||
start := editStart - contextLines
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
for i := start; i < editStart; i++ {
|
||||
fmt.Fprintf(&b, " %4d %s\n", i+1, lines[i])
|
||||
}
|
||||
|
||||
// Removed lines (old)
|
||||
for i, line := range oldLines {
|
||||
fmt.Fprintf(&b, " %4d - %s\n", editStart+i+1, line)
|
||||
}
|
||||
|
||||
// Added lines (new)
|
||||
for i, line := range newLines {
|
||||
fmt.Fprintf(&b, " %4d + %s\n", editStart+i+1, line)
|
||||
}
|
||||
|
||||
// Context after
|
||||
afterStart := editStart + len(oldLines)
|
||||
afterEnd := afterStart + contextLines
|
||||
if afterEnd > len(lines) {
|
||||
afterEnd = len(lines)
|
||||
}
|
||||
for i := afterStart; i < afterEnd; i++ {
|
||||
fmt.Fprintf(&b, " %4d %s\n", i+1, lines[i])
|
||||
}
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ func TestEditTool_SingleReplace(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Execute: %v", err)
|
||||
}
|
||||
if !strings.Contains(result.Output, "1 occurrence") {
|
||||
if !strings.Contains(result.Output, "Edit(") && !strings.Contains(result.Output, "Replaced") {
|
||||
t.Errorf("Output = %q", result.Output)
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ func TestEditTool_ReplaceAll(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Execute: %v", err)
|
||||
}
|
||||
if !strings.Contains(result.Output, "3 occurrence") {
|
||||
if !strings.Contains(result.Output, "Edit(") && !strings.Contains(result.Output, "3 occurrence") {
|
||||
t.Errorf("Output = %q", result.Output)
|
||||
}
|
||||
|
||||
|
||||
@@ -679,8 +679,24 @@ func (m Model) renderMessage(msg chatMessage) []string {
|
||||
lines = append(lines, indent+sToolOutput.Render(msg.content))
|
||||
|
||||
case "toolresult":
|
||||
for _, line := range strings.Split(msg.content, "\n") {
|
||||
lines = append(lines, indent+indent+sToolResult.Render(line))
|
||||
resultLines := strings.Split(msg.content, "\n")
|
||||
maxShow := 10
|
||||
for i, line := range resultLines {
|
||||
if i >= maxShow {
|
||||
remaining := len(resultLines) - maxShow
|
||||
lines = append(lines, indent+indent+sHint.Render(
|
||||
fmt.Sprintf("+%d lines (Ctrl+O to expand)", remaining)))
|
||||
break
|
||||
}
|
||||
// Diff coloring for edit results
|
||||
trimmed := strings.TrimSpace(line)
|
||||
if strings.HasPrefix(trimmed, "+") && !strings.HasPrefix(trimmed, "++") && len(trimmed) > 1 {
|
||||
lines = append(lines, indent+indent+sDiffAdd.Render(line))
|
||||
} else if strings.HasPrefix(trimmed, "-") && !strings.HasPrefix(trimmed, "--") && len(trimmed) > 1 {
|
||||
lines = append(lines, indent+indent+sDiffRemove.Render(line))
|
||||
} else {
|
||||
lines = append(lines, indent+indent+sToolResult.Render(line))
|
||||
}
|
||||
}
|
||||
lines = append(lines, "")
|
||||
|
||||
|
||||
@@ -85,6 +85,12 @@ var (
|
||||
|
||||
sCursor = lipgloss.NewStyle().
|
||||
Foreground(cPurple)
|
||||
|
||||
sDiffAdd = lipgloss.NewStyle().
|
||||
Foreground(cGreen)
|
||||
|
||||
sDiffRemove = lipgloss.NewStyle().
|
||||
Foreground(cRed)
|
||||
)
|
||||
|
||||
// Status bar
|
||||
|
||||
Reference in New Issue
Block a user