Skip to content

Commit 366b400

Browse files
metiu1claude
andcommitted
v0.3.65: write_file gains append mode for building large files in chunks
The model could only overwrite a file in one shot, so building a big dataset failed (it wrote just "[" and stopped). write_file now takes append=true to add to the end; the coding prompt and tool descriptions tell the model to build large files in chunks and verify the result. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 3995098 commit 366b400

7 files changed

Lines changed: 53 additions & 14 deletions

File tree

vortelio-pip/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "vortelio"
7-
version = "0.3.64"
7+
version = "0.3.65"
88
description = "Local-first AI platform. Run LLMs, generate images & video, transcribe audio, create 3D — on your own machine. OpenAI & Ollama API compatible. Apache 2.0."
99
readme = "README.md"
1010
requires-python = ">=3.8"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.3.64"
1+
__version__ = "0.3.65"

vortelio-pip/src/vortelio_cli/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import urllib.request
1111
from pathlib import Path
1212

13-
VERSION = "0.3.64"
13+
VERSION = "0.3.65"
1414
RELEASE_BASE = os.environ.get(
1515
"VORTELIO_RELEASE_BASE",
1616
f"https://github.com/metiu1/Vortelio/releases/download/v{VERSION}",
2.5 KB
Binary file not shown.

vortelio/internal/runtime/tools.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ func BuiltinTools() []ToolDef {
182182
Type: "function",
183183
Function: ToolFuncDef{
184184
Name: "write_file",
185-
Description: "Writes content to a file on the local filesystem. Creates the file if it does not exist.",
186-
Parameters: json.RawMessage(`{"type":"object","properties":{"path":{"type":"string","description":"Path to the file"},"content":{"type":"string","description":"Content to write"}},"required":["path","content"]}`),
185+
Description: "Writes content to a file. Creates it if missing. Set append=true to add to the end instead of overwriting — use this to build large files (e.g. a big dataset) in several chunks.",
186+
Parameters: json.RawMessage(`{"type":"object","properties":{"path":{"type":"string","description":"Path to the file"},"content":{"type":"string","description":"Content to write"},"append":{"type":"boolean","description":"If true, append to the end of the file instead of overwriting. Default false."}},"required":["path","content"]}`),
187187
},
188188
},
189189
{
@@ -722,20 +722,37 @@ func toolWriteFile(argsJSON string) (string, error) {
722722
var args struct {
723723
Path string `json:"path"`
724724
Content string `json:"content"`
725+
Append bool `json:"append"`
725726
}
726727
if err := json.Unmarshal([]byte(argsJSON), &args); err != nil || args.Path == "" {
727728
return "", fmt.Errorf("path and content are required")
728729
}
729730
if err := os.MkdirAll(filepath.Dir(args.Path), 0755); err != nil {
730731
return "", fmt.Errorf("cannot create directory: %w", err)
731732
}
732-
if err := os.WriteFile(args.Path, []byte(args.Content), 0644); err != nil {
733+
if args.Append {
734+
f, err := os.OpenFile(args.Path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
735+
if err != nil {
736+
return "", fmt.Errorf("cannot open file %q: %w", args.Path, err)
737+
}
738+
if _, err := f.WriteString(args.Content); err != nil {
739+
f.Close()
740+
return "", fmt.Errorf("cannot append to file %q: %w", args.Path, err)
741+
}
742+
f.Close()
743+
} else if err := os.WriteFile(args.Path, []byte(args.Content), 0644); err != nil {
733744
return "", fmt.Errorf("cannot write file %q: %w", args.Path, err)
734745
}
746+
total := int64(0)
747+
if fi, err := os.Stat(args.Path); err == nil {
748+
total = fi.Size()
749+
}
735750
b, _ := json.Marshal(map[string]interface{}{
736-
"path": args.Path,
737-
"written": len(args.Content),
738-
"status": "ok",
751+
"path": args.Path,
752+
"written": len(args.Content),
753+
"total_size": total,
754+
"appended": args.Append,
755+
"status": "ok",
739756
})
740757
return string(b), nil
741758
}

vortelio/internal/server/server_agentic.go

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ func CodingSystemPrompt(autonomous bool) string {
206206
"l'utente li chiede davvero, e per impostazione predefinita salva gli artefatti dentro la cartella di lavoro. " +
207207
"Dopo che uno strumento restituisce un risultato, scrivi una risposta chiara e completa nella lingua dell'utente; " +
208208
"non limitarti a ripetere il JSON grezzo. " +
209+
"Per file molto grandi (dataset, migliaia di righe) NON tentare un'unica scrittura gigante: " +
210+
"crea il file e poi AGGIUNGI il contenuto a blocchi con write_file e append=true, ripetendo finché è completo, " +
211+
"e alla fine verifica la dimensione/righe con read_file. " +
209212
conciseNudgeIT + " " +
210213
askUserNudgeIT
211214
}
@@ -761,8 +764,8 @@ func (c *codingProvider) Tools() []rt.ToolDef {
761764
`{"type":"object","properties":{"pattern":{"type":"string","description":"Glob pattern relative to workspace root."}},"required":["pattern"]}`),
762765
toolDef("grep_search", "Search file contents for a substring and return matching lines.",
763766
`{"type":"object","properties":{"query":{"type":"string"},"path":{"type":"string","description":"Optional sub-path to search. Defaults to workspace root."}},"required":["query"]}`),
764-
toolDef("write_file", "Create or overwrite a file with the given content. (requires approval)",
765-
`{"type":"object","properties":{"path":{"type":"string"},"content":{"type":"string"}},"required":["path","content"]}`),
767+
toolDef("write_file", "Create or overwrite a file. Set append=true to add to the end instead — use it to build large files (e.g. a big dataset) in several chunks. (requires approval)",
768+
`{"type":"object","properties":{"path":{"type":"string"},"content":{"type":"string"},"append":{"type":"boolean","description":"Append to the end instead of overwriting. Default false."}},"required":["path","content"]}`),
766769
toolDef("edit_file", "Replace the first occurrence of old_text with new_text in a file. (requires approval)",
767770
`{"type":"object","properties":{"path":{"type":"string"},"old_text":{"type":"string"},"new_text":{"type":"string"}},"required":["path","old_text","new_text"]}`),
768771
toolDef("run_shell", "Run a shell command in the workspace and return its output. (requires approval)",
@@ -1070,6 +1073,7 @@ func (c *codingProvider) writeFile(argsJSON string) (string, error) {
10701073
var a struct {
10711074
Path string `json:"path"`
10721075
Content string `json:"content"`
1076+
Append bool `json:"append"`
10731077
}
10741078
json.Unmarshal([]byte(argsJSON), &a)
10751079
full, err := c.resolvePath(a.Path)
@@ -1079,10 +1083,28 @@ func (c *codingProvider) writeFile(argsJSON string) (string, error) {
10791083
if err := os.MkdirAll(filepath.Dir(full), 0755); err != nil {
10801084
return "", err
10811085
}
1082-
if err := os.WriteFile(full, []byte(a.Content), 0644); err != nil {
1086+
if a.Append {
1087+
f, err := os.OpenFile(full, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
1088+
if err != nil {
1089+
return "", err
1090+
}
1091+
if _, err := f.WriteString(a.Content); err != nil {
1092+
f.Close()
1093+
return "", err
1094+
}
1095+
f.Close()
1096+
} else if err := os.WriteFile(full, []byte(a.Content), 0644); err != nil {
10831097
return "", err
10841098
}
1085-
return fmt.Sprintf("wrote %d bytes to %s", len(a.Content), full), nil
1099+
total := int64(0)
1100+
if fi, err := os.Stat(full); err == nil {
1101+
total = fi.Size()
1102+
}
1103+
verb := "wrote"
1104+
if a.Append {
1105+
verb = "appended"
1106+
}
1107+
return fmt.Sprintf("%s %d bytes to %s (total %d bytes)", verb, len(a.Content), full, total), nil
10861108
}
10871109

10881110
func (c *codingProvider) editFile(argsJSON string) (string, error) {

vortelio/internal/version/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ package version
33
// Version è impostabile a build time via:
44
//
55
// -ldflags "-X github.com/vortelio/vortelio/internal/version.Version=X.Y.Z"
6-
var Version = "0.3.64"
6+
var Version = "0.3.65"

0 commit comments

Comments
 (0)