Skip to content

Commit 5392775

Browse files
authored
fix(engine): stabilize schema target extraction order (#39)
1 parent c1b9341 commit 5392775

1 file changed

Lines changed: 26 additions & 1 deletion

File tree

internal/engine/stream_tool_exec.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"log/slog"
88
"os"
9+
"slices"
910
"strings"
1011
"sync"
1112

@@ -63,6 +64,18 @@ func extractTargets(tc types.ToolCall) []string {
6364
// discover non-conventional argument names.
6465
var filePathLikeKeySubstrings = []string{"path", "file", "dir", "destination", "target"}
6566

67+
func filePathPropertyPriority(name string) int {
68+
lower := strings.ToLower(name)
69+
switch {
70+
case strings.Contains(lower, "src"), strings.Contains(lower, "source"), strings.Contains(lower, "input"):
71+
return 0
72+
case strings.Contains(lower, "dst"), strings.Contains(lower, "dest"), strings.Contains(lower, "output"), strings.Contains(lower, "target"), strings.Contains(lower, "backup"):
73+
return 2
74+
default:
75+
return 1
76+
}
77+
}
78+
6679
// ExtractTargetsFromSchema walks the tool's JSON Schema to discover file-path
6780
// arguments in the tool call. It does this by:
6881
// 1. Reading `parameters` (the JSON Schema map) to enumerate property names.
@@ -82,7 +95,19 @@ func ExtractTargetsFromSchema(t tool.Tool, tc types.ToolCall) []string {
8295
// a JSON Schema (e.g. an LLM-emitted tool or a tests-only stub).
8396
return extractTargets(tc)
8497
}
85-
for propName, propDef := range props {
98+
propNames := make([]string, 0, len(props))
99+
for propName := range props {
100+
propNames = append(propNames, propName)
101+
}
102+
slices.SortStableFunc(propNames, func(a, b string) int {
103+
pa, pb := filePathPropertyPriority(a), filePathPropertyPriority(b)
104+
if pa != pb {
105+
return pa - pb
106+
}
107+
return strings.Compare(a, b)
108+
})
109+
for _, propName := range propNames {
110+
propDef := props[propName]
86111
propNameLower := strings.ToLower(propName)
87112
// Convention 1: property name contains a file-path substring.
88113
nameMatches := false

0 commit comments

Comments
 (0)