mirror of
https://github.com/Twigpine/zero.git
synced 2026-11-12 19:13:28 -10:00
edit_file/write_file now append error-severity language diagnostics for the file they just wrote directly to their tool output, so the model sees a break it introduced in the same turn instead of waiting for the batch-level self-correct pass (which still runs and still owns tests and auto-remediation). Warnings/hints are excluded to keep the signal sharp. Wiring: a new RunOptions.Diagnostics callback threads through the agent loop from Options.FileDiagnostics; exec and the TUI build it from the run's lazy lsp.Manager (no server spawns unless the language has one on PATH). Each check is bounded by a 10s timeout so a wedged server can never hang a tool call. In exec the manager now exists even without --self-correct, still lazy and torn down on run exit. Co-Authored-By: Claude Fable 5 <[email protected]>
54 lines
1.9 KiB
Go
54 lines
1.9 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// A wired Diagnostics callback must surface its block in the tool output for
|
|
// both mutating tools, and a clean file (empty block) must leave the output
|
|
// byte-identical to the pre-diagnostics behavior.
|
|
func TestMutatingToolsAppendInlineDiagnostics(t *testing.T) {
|
|
dir := t.TempDir()
|
|
if err := os.WriteFile(filepath.Join(dir, "a.go"), []byte("package a\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
diagnostics := func(_ context.Context, absPath string) string {
|
|
return absPath + ":1:1: error: undefined: x"
|
|
}
|
|
|
|
editResult := NewEditFileTool(dir).(optionsAwareTool).RunWithOptions(context.Background(), map[string]any{
|
|
"path": "a.go",
|
|
"old_string": "package a",
|
|
"new_string": "package b",
|
|
}, RunOptions{Diagnostics: diagnostics})
|
|
if editResult.Status != StatusOK {
|
|
t.Fatalf("edit failed: %q", editResult.Output)
|
|
}
|
|
if !strings.Contains(editResult.Output, "Diagnostics in a.go after this change") || !strings.Contains(editResult.Output, "undefined: x") {
|
|
t.Fatalf("edit output missing diagnostics block: %q", editResult.Output)
|
|
}
|
|
|
|
writeResult := NewWriteFileTool(dir).(optionsAwareTool).RunWithOptions(context.Background(), map[string]any{
|
|
"path": "b.go",
|
|
"content": "package b\n",
|
|
}, RunOptions{Diagnostics: diagnostics})
|
|
if writeResult.Status != StatusOK {
|
|
t.Fatalf("write failed: %q", writeResult.Output)
|
|
}
|
|
if !strings.Contains(writeResult.Output, "Diagnostics in b.go after this change") {
|
|
t.Fatalf("write output missing diagnostics block: %q", writeResult.Output)
|
|
}
|
|
|
|
clean := NewWriteFileTool(dir).(optionsAwareTool).RunWithOptions(context.Background(), map[string]any{
|
|
"path": "c.go",
|
|
"content": "package c\n",
|
|
}, RunOptions{Diagnostics: func(context.Context, string) string { return "" }})
|
|
if strings.Contains(clean.Output, "Diagnostics") {
|
|
t.Fatalf("clean file must not gain a diagnostics block: %q", clean.Output)
|
|
}
|
|
}
|