Why: Old tool results were filling the window, compaction could split a tool group or commit a stale summary, and reminders arrived as extra user messages. Evidence: Compaction retries a conflict and opens the circuit after three failures; clearing keeps the last five tool results; a stale file write is rejected; RPC reports started, queued, or handled. Impact: Requests over the context window replace older tool results with a placeholder. Rewriting an existing file now requires a read in the same run. Subagent text over 32000 characters is capped. Refs: feature/context-engineering Co-authored-by: Cursor <cursoragent@cursor.com>
67 lines
1.3 KiB
Go
67 lines
1.3 KiB
Go
package tools
|
|
|
|
import "strings"
|
|
|
|
// ApplySelection 按 +name / -name 调整默认工具集。
|
|
// 规格为空时返回 base 的副本。出现不带正负号的名字时,先用这些名字替换默认集,再应用增减。
|
|
// 分隔符为空格、逗号或换行。
|
|
func ApplySelection(base []string, spec string) []string {
|
|
spec = strings.TrimSpace(spec)
|
|
if spec == "" {
|
|
return append([]string{}, base...)
|
|
}
|
|
fields := strings.FieldsFunc(spec, func(r rune) bool {
|
|
return r == ',' || r == ' ' || r == '\n' || r == '\t'
|
|
})
|
|
hasBare := false
|
|
for _, f := range fields {
|
|
if f != "" && f[0] != '+' && f[0] != '-' {
|
|
hasBare = true
|
|
break
|
|
}
|
|
}
|
|
var out []string
|
|
if !hasBare {
|
|
out = append(out, base...)
|
|
}
|
|
for _, f := range fields {
|
|
if f == "" {
|
|
continue
|
|
}
|
|
switch f[0] {
|
|
case '+':
|
|
out = addName(out, f[1:])
|
|
case '-':
|
|
out = dropName(out, f[1:])
|
|
default:
|
|
out = addName(out, f)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func addName(names []string, name string) []string {
|
|
if name == "" {
|
|
return names
|
|
}
|
|
for _, n := range names {
|
|
if n == name {
|
|
return names
|
|
}
|
|
}
|
|
return append(names, name)
|
|
}
|
|
|
|
func dropName(names []string, name string) []string {
|
|
if name == "" {
|
|
return names
|
|
}
|
|
out := names[:0]
|
|
for _, n := range names {
|
|
if n != name {
|
|
out = append(out, n)
|
|
}
|
|
}
|
|
return out
|
|
}
|