opencode-cursor-agent/internal/winlimit/winlimit.go

133 lines
3.1 KiB
Go

package winlimit
import (
"cursor-api-proxy/internal/env"
"runtime"
)
const WinPromptOmissionPrefix = "[Earlier messages omitted: Windows command-line length limit.]\n\n"
type FitPromptResult struct {
OK bool
Args []string
Truncated bool
OriginalLength int
FinalPromptLength int
Error string
}
func estimateCmdlineLength(resolved env.AgentCommand) int {
argv := append([]string{resolved.Command}, resolved.Args...)
if resolved.WindowsVerbatimArguments {
n := 0
for _, a := range argv {
n += len(a)
}
if len(argv) > 1 {
n += len(argv) - 1
}
return n + 512
}
dstLen := 0
for _, a := range argv {
dstLen += len(a)
}
dstLen = dstLen*2 + len(argv)*2
if len(argv) > 1 {
dstLen += len(argv) - 1
}
return dstLen + 512
}
func FitPromptToWinCmdline(agentBin string, fixedArgs []string, prompt string, maxCmdline int, cwd string) FitPromptResult {
if runtime.GOOS != "windows" {
args := make([]string, len(fixedArgs)+1)
copy(args, fixedArgs)
args[len(fixedArgs)] = prompt
return FitPromptResult{
OK: true,
Args: args,
Truncated: false,
OriginalLength: len(prompt),
FinalPromptLength: len(prompt),
}
}
e := env.OsEnvToMap()
measured := func(p string) int {
args := make([]string, len(fixedArgs)+1)
copy(args, fixedArgs)
args[len(fixedArgs)] = p
resolved := env.ResolveAgentCommand(agentBin, args, e, cwd)
return estimateCmdlineLength(resolved)
}
if measured("") > maxCmdline {
return FitPromptResult{
OK: false,
Error: "Windows command line exceeds the configured limit even without a prompt; shorten workspace path, model id, or CURSOR_BRIDGE_WIN_CMDLINE_MAX.",
}
}
if measured(prompt) <= maxCmdline {
args := make([]string, len(fixedArgs)+1)
copy(args, fixedArgs)
args[len(fixedArgs)] = prompt
return FitPromptResult{
OK: true,
Args: args,
Truncated: false,
OriginalLength: len(prompt),
FinalPromptLength: len(prompt),
}
}
prefix := WinPromptOmissionPrefix
if measured(prefix) > maxCmdline {
return FitPromptResult{
OK: false,
Error: "Windows command line too long to fit even the truncation notice; shorten workspace path or flags.",
}
}
lo, hi, best := 0, len(prompt), 0
for lo <= hi {
mid := (lo + hi) / 2
var tail string
if mid > 0 {
tail = prompt[len(prompt)-mid:]
}
candidate := prefix + tail
if measured(candidate) <= maxCmdline {
best = mid
lo = mid + 1
} else {
hi = mid - 1
}
}
var finalPrompt string
if best == 0 {
finalPrompt = prefix
} else {
finalPrompt = prefix + prompt[len(prompt)-best:]
}
args := make([]string, len(fixedArgs)+1)
copy(args, fixedArgs)
args[len(fixedArgs)] = finalPrompt
return FitPromptResult{
OK: true,
Args: args,
Truncated: true,
OriginalLength: len(prompt),
FinalPromptLength: len(finalPrompt),
}
}
func WarnPromptTruncated(originalLength, finalLength int) {
_ = originalLength
_ = finalLength
// fmt.Fprintf skipped to avoid import; caller may log as needed
}