verbesserungen
This commit is contained in:
@@ -18,18 +18,28 @@ const (
|
|||||||
maxTurns = 10
|
maxTurns = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
var systemPrompt = `Du bist ein autonomer Coding-Agent. Du bekommst einen Task und erledigst ihn vollständig.
|
var systemPrompt = `Du bist ein autonomer Coding-Agent.
|
||||||
|
|
||||||
Du hast folgende Tools zur Verfügung:
|
` + BuildToolPrompt() + `
|
||||||
- TOOL:READ_FILE:pfad → Datei lesen
|
|
||||||
- TOOL:WRITE_FILE:pfad:inhalt → Datei schreiben
|
|
||||||
- TOOL:LIST_FILES:pfad → Verzeichnis auflisten
|
|
||||||
|
|
||||||
Regeln:
|
WICHTIGE REGELN:
|
||||||
1. Analysiere den Task zuerst
|
1. Nutze IMMER relative Pfade (z.B. hello.go, nicht /absoluter/pfad/hello.go)
|
||||||
2. Nutze die Tools um Dateien zu lesen/schreiben
|
2. Schreibe Dateiinhalt NIEMALS in Markdown-Codeblöcken (keine Backticks)
|
||||||
3. Wenn der Task vollständig erledigt ist, schreibe am Ende: TASK_COMPLETE
|
3. Nutze IMMER das <<<...>>> Format für WRITE_FILE
|
||||||
4. Bei Fehlern beschreibe das Problem klar`
|
4. Wenn der Task erledigt ist, schreibe EXAKT auf einer eigenen Zeile: TASK_COMPLETE
|
||||||
|
|
||||||
|
Beispiel:
|
||||||
|
TOOL:WRITE_FILE:hello.go
|
||||||
|
<<<
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("Hello World")
|
||||||
|
}
|
||||||
|
>>>
|
||||||
|
TASK_COMPLETE`
|
||||||
|
|
||||||
type AgentLoop struct {
|
type AgentLoop struct {
|
||||||
client *openai.Client
|
client *openai.Client
|
||||||
|
|||||||
@@ -180,6 +180,7 @@ func readFile(absPath, displayPath string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func writeFile(absPath, displayPath, content string) string {
|
func writeFile(absPath, displayPath, content string) string {
|
||||||
|
content = cleanContent(content)
|
||||||
if err := os.MkdirAll(filepath.Dir(absPath), 0755); err != nil {
|
if err := os.MkdirAll(filepath.Dir(absPath), 0755); err != nil {
|
||||||
return fmt.Sprintf("WRITE_FILE ERROR: Verzeichnis anlegen fehlgeschlagen: %v", err)
|
return fmt.Sprintf("WRITE_FILE ERROR: Verzeichnis anlegen fehlgeschlagen: %v", err)
|
||||||
}
|
}
|
||||||
@@ -213,12 +214,22 @@ func listFiles(absPath, displayPath string) string {
|
|||||||
// sanitizePath stellt sicher dass der Pfad innerhalb des workDir bleibt.
|
// sanitizePath stellt sicher dass der Pfad innerhalb des workDir bleibt.
|
||||||
// Verhindert Directory Traversal wie ../../etc/passwd
|
// Verhindert Directory Traversal wie ../../etc/passwd
|
||||||
func sanitizePath(workDir, relPath string) (string, error) {
|
func sanitizePath(workDir, relPath string) (string, error) {
|
||||||
// Absoluten Zielpfad berechnen
|
// Wenn LLM einen absoluten Pfad schickt → relativen Teil extrahieren
|
||||||
abs := filepath.Join(workDir, relPath)
|
if filepath.IsAbs(relPath) {
|
||||||
abs = filepath.Clean(abs)
|
|
||||||
|
|
||||||
// Muss mit workDir beginnen
|
|
||||||
workDirClean := filepath.Clean(workDir)
|
workDirClean := filepath.Clean(workDir)
|
||||||
|
// Prüfen ob der absolute Pfad innerhalb des workDir liegt
|
||||||
|
if strings.HasPrefix(relPath, workDirClean) {
|
||||||
|
// Absoluten Pfad direkt nutzen, kein Join nötig
|
||||||
|
return filepath.Clean(relPath), nil
|
||||||
|
}
|
||||||
|
// Absoluter Pfad außerhalb workDir → nur Dateiname nehmen
|
||||||
|
relPath = filepath.Base(relPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normaler Fall: relativer Pfad
|
||||||
|
abs := filepath.Clean(filepath.Join(workDir, relPath))
|
||||||
|
workDirClean := filepath.Clean(workDir)
|
||||||
|
|
||||||
if !strings.HasPrefix(abs, workDirClean+string(filepath.Separator)) &&
|
if !strings.HasPrefix(abs, workDirClean+string(filepath.Separator)) &&
|
||||||
abs != workDirClean {
|
abs != workDirClean {
|
||||||
return "", fmt.Errorf("Pfad außerhalb des Arbeitsverzeichnisses")
|
return "", fmt.Errorf("Pfad außerhalb des Arbeitsverzeichnisses")
|
||||||
@@ -226,3 +237,21 @@ func sanitizePath(workDir, relPath string) (string, error) {
|
|||||||
|
|
||||||
return abs, nil
|
return abs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cleanContent(content string) string {
|
||||||
|
// Escaped Quotes normalisieren
|
||||||
|
content = strings.ReplaceAll(content, `\"`, `"`)
|
||||||
|
content = strings.ReplaceAll(content, `\\n`, "\n")
|
||||||
|
content = strings.ReplaceAll(content, `\\t`, "\t")
|
||||||
|
|
||||||
|
// Markdown Codeblöcke entfernen
|
||||||
|
lines := strings.Split(content, "\n")
|
||||||
|
var cleaned []string
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.HasPrefix(strings.TrimSpace(line), "```") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cleaned = append(cleaned, line)
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(strings.Join(cleaned, "\n"))
|
||||||
|
}
|
||||||
|
|||||||
5
main.go
5
main.go
@@ -62,11 +62,10 @@ func selectModel(client *openai.Client) string {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Verzeichnis der ausführbaren Binary ermitteln
|
// Verzeichnis der ausführbaren Binary ermitteln
|
||||||
execPath, err := os.Executable()
|
execDir, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Konnte Executable-Pfad nicht ermitteln: %v", err)
|
log.Fatalf("Konnte Arbeitsverzeichnis nicht ermitteln: %v", err)
|
||||||
}
|
}
|
||||||
execDir := filepath.Dir(execPath)
|
|
||||||
|
|
||||||
// Flags definieren
|
// Flags definieren
|
||||||
verbose := flag.Bool("verbose", false, "Zeigt alle Chat-Nachrichten vollständig an")
|
verbose := flag.Bool("verbose", false, "Zeigt alle Chat-Nachrichten vollständig an")
|
||||||
|
|||||||
Reference in New Issue
Block a user