write_file improvements
This commit is contained in:
+136
@@ -2389,3 +2389,139 @@ func TestSanitizeMessagesCleansReasoningContent(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteFileOmittedOrZeroOffsetDoesNotAppend(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
target := filepath.Join(tmp, "test.txt")
|
||||
|
||||
// Create file with initial content
|
||||
if err := os.WriteFile(target, []byte("EXISTING"), 0644); err != nil {
|
||||
t.Fatalf("failed to write initial file: %v", err)
|
||||
}
|
||||
|
||||
// 1. Direct writeFile with offset 0: writes starting at offset 0, does NOT append
|
||||
res, err := writeFile(target, 0, 0, "PREFIX_")
|
||||
if err != nil {
|
||||
t.Fatalf("writeFile: %v", err)
|
||||
}
|
||||
if !strings.Contains(res, "Successfully wrote 7 bytes") {
|
||||
t.Errorf("unexpected res: %q", res)
|
||||
}
|
||||
data, err := os.ReadFile(target)
|
||||
if err != nil {
|
||||
t.Fatalf("readFile: %v", err)
|
||||
}
|
||||
if string(data) != "PREFIX_EXISTING" {
|
||||
t.Errorf("expected 'PREFIX_EXISTING', got %q", string(data))
|
||||
}
|
||||
|
||||
// 2. AL tool dispatch with offset omitted completely: must start writing at offset 0, NOT append
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Messages []Message `json:"messages"`
|
||||
}
|
||||
json.NewDecoder(r.Body).Decode(&req)
|
||||
for _, m := range req.Messages {
|
||||
if m.Role == "tool" {
|
||||
w.Write([]byte(`{"choices":[{"message":{"role":"assistant","content":"done"}}]}`))
|
||||
return
|
||||
}
|
||||
}
|
||||
// Tool call without "offset" parameter
|
||||
args, _ := json.Marshal(map[string]any{
|
||||
"path": target,
|
||||
"content": "START_",
|
||||
})
|
||||
w.Write([]byte(fmt.Sprintf(`{"choices":[{"message":{"role":"assistant","content":null,"tool_calls":[{"id":"c1","type":"function","function":{"name":"write_file","arguments":%s}}]}}]}`, strconv.Quote(string(args)))))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
cfg := defCfg
|
||||
cfg.Endpoint = srv.URL
|
||||
cfg.Stream = false
|
||||
cfg.APIKey = "-"
|
||||
_, _, err = AL(context.Background(), &cfg, []Message{{Role: "user", Content: strp("write")}})
|
||||
if err != nil {
|
||||
t.Fatalf("AL: %v", err)
|
||||
}
|
||||
|
||||
data, err = os.ReadFile(target)
|
||||
if err != nil {
|
||||
t.Fatalf("readFile: %v", err)
|
||||
}
|
||||
if string(data) != "START_PREFIX_EXISTING" {
|
||||
t.Errorf("expected 'START_PREFIX_EXISTING', got %q", string(data))
|
||||
}
|
||||
|
||||
// 3. AL tool dispatch with explicit offset: 0
|
||||
srv2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Messages []Message `json:"messages"`
|
||||
}
|
||||
json.NewDecoder(r.Body).Decode(&req)
|
||||
for _, m := range req.Messages {
|
||||
if m.Role == "tool" {
|
||||
w.Write([]byte(`{"choices":[{"message":{"role":"assistant","content":"done"}}]}`))
|
||||
return
|
||||
}
|
||||
}
|
||||
args, _ := json.Marshal(map[string]any{
|
||||
"path": target,
|
||||
"offset": 0,
|
||||
"del_bytes": 0,
|
||||
"content": "ZERO_",
|
||||
})
|
||||
w.Write([]byte(fmt.Sprintf(`{"choices":[{"message":{"role":"assistant","content":null,"tool_calls":[{"id":"c1","type":"function","function":{"name":"write_file","arguments":%s}}]}}]}`, strconv.Quote(string(args)))))
|
||||
}))
|
||||
defer srv2.Close()
|
||||
|
||||
cfg.Endpoint = srv2.URL
|
||||
_, _, err = AL(context.Background(), &cfg, []Message{{Role: "user", Content: strp("write zero")}})
|
||||
if err != nil {
|
||||
t.Fatalf("AL: %v", err)
|
||||
}
|
||||
|
||||
data, err = os.ReadFile(target)
|
||||
if err != nil {
|
||||
t.Fatalf("readFile: %v", err)
|
||||
}
|
||||
if string(data) != "ZERO_START_PREFIX_EXISTING" {
|
||||
t.Errorf("expected 'ZERO_START_PREFIX_EXISTING', got %q", string(data))
|
||||
}
|
||||
|
||||
// 4. AL tool dispatch with offset: null
|
||||
srv3 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Messages []Message `json:"messages"`
|
||||
}
|
||||
json.NewDecoder(r.Body).Decode(&req)
|
||||
for _, m := range req.Messages {
|
||||
if m.Role == "tool" {
|
||||
w.Write([]byte(`{"choices":[{"message":{"role":"assistant","content":"done"}}]}`))
|
||||
return
|
||||
}
|
||||
}
|
||||
args, _ := json.Marshal(map[string]any{
|
||||
"path": target,
|
||||
"offset": nil,
|
||||
"content": "NULL_",
|
||||
})
|
||||
w.Write([]byte(fmt.Sprintf(`{"choices":[{"message":{"role":"assistant","content":null,"tool_calls":[{"id":"c1","type":"function","function":{"name":"write_file","arguments":%s}}]}}]}`, strconv.Quote(string(args)))))
|
||||
}))
|
||||
defer srv3.Close()
|
||||
|
||||
cfg.Endpoint = srv3.URL
|
||||
_, _, err = AL(context.Background(), &cfg, []Message{{Role: "user", Content: strp("write null")}})
|
||||
if err != nil {
|
||||
t.Fatalf("AL: %v", err)
|
||||
}
|
||||
|
||||
data, err = os.ReadFile(target)
|
||||
if err != nil {
|
||||
t.Fatalf("readFile: %v", err)
|
||||
}
|
||||
if string(data) != "NULL_ZERO_START_PREFIX_EXISTING" {
|
||||
t.Errorf("expected 'NULL_ZERO_START_PREFIX_EXISTING', got %q", string(data))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user