mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-08-18 03:57:06 +08:00
v0.3.8
This commit is contained in:
@@ -0,0 +1,394 @@
|
||||
package forwarder
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
projectedReplayKiB = 1024
|
||||
|
||||
projectedReadReplayLimit = 64 * projectedReplayKiB
|
||||
projectedShellReplayLimit = 128 * projectedReplayKiB
|
||||
projectedShellStreamLimit = 16 * projectedReplayKiB
|
||||
projectedShellInterleavedLimit = 32 * projectedReplayKiB
|
||||
projectedGrepReplayLimit = 32 * projectedReplayKiB
|
||||
projectedEditReplayLimit = 32 * projectedReplayKiB
|
||||
projectedPatchEditReplayLimit = 4 * projectedReplayKiB
|
||||
projectedWebFetchReplayLimit = 32 * projectedReplayKiB
|
||||
projectedWebSearchReplayLimit = 16 * projectedReplayKiB
|
||||
projectedMcpReplayLimit = 32 * projectedReplayKiB
|
||||
)
|
||||
|
||||
func limitProjectedToolResultReplay(toolName string, content string, resultText string, fromStoredToolCall bool, historical bool) string {
|
||||
if compacted, ok := compactProjectedGenerateImageResultReplay(toolName, content, resultText); ok {
|
||||
return compacted
|
||||
}
|
||||
if historical {
|
||||
if compacted, ok := compactHistoricalEditErrorReplay(toolName, content); ok {
|
||||
content = compacted
|
||||
fromStoredToolCall = false
|
||||
}
|
||||
}
|
||||
if compacted, ok := compactProjectedEditToolResultReplay(toolName, content); ok {
|
||||
content = compacted
|
||||
fromStoredToolCall = false
|
||||
}
|
||||
if compacted, ok := compactProjectedShellToolResultReplay(toolName, content); ok {
|
||||
content = compacted
|
||||
fromStoredToolCall = false
|
||||
}
|
||||
limit, ok := projectedToolReplayLimit(toolName)
|
||||
if !ok {
|
||||
return strings.TrimSpace(content)
|
||||
}
|
||||
content = strings.TrimSpace(content)
|
||||
if len(content) <= limit {
|
||||
return content
|
||||
}
|
||||
if fromStoredToolCall {
|
||||
fallback := strings.TrimSpace(resultText)
|
||||
notice := fmt.Sprintf("[tool result replay truncated: stored ToolCall result exceeded %d bytes]", limit)
|
||||
if fallback == "" {
|
||||
fallback = notice
|
||||
} else {
|
||||
fallback += "\n\n" + notice
|
||||
}
|
||||
return truncateProjectedReplayText(toolName, fallback, limit)
|
||||
}
|
||||
return truncateProjectedReplayText(toolName, content, limit)
|
||||
}
|
||||
|
||||
func projectedToolReplayLimit(toolName string) (int, bool) {
|
||||
switch strings.TrimSpace(toolName) {
|
||||
case "GenerateImage":
|
||||
return projectedWebSearchReplayLimit, true
|
||||
case "Read":
|
||||
return projectedReadReplayLimit, true
|
||||
case "Shell":
|
||||
return projectedShellReplayLimit, true
|
||||
case "Grep":
|
||||
return projectedGrepReplayLimit, true
|
||||
case "PatchEdit", "PatchEditLines", "PatchEditSpan":
|
||||
return projectedPatchEditReplayLimit, true
|
||||
case "Edit", "Write":
|
||||
return projectedEditReplayLimit, true
|
||||
case "WebFetch":
|
||||
return projectedWebFetchReplayLimit, true
|
||||
case "WebSearch":
|
||||
return projectedWebSearchReplayLimit, true
|
||||
case "CallMcpTool", "FetchMcpResource", "ListMcpResources":
|
||||
return projectedMcpReplayLimit, true
|
||||
default:
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
|
||||
func compactProjectedGenerateImageResultReplay(toolName string, content string, resultText string) (string, bool) {
|
||||
if strings.TrimSpace(toolName) != "GenerateImage" {
|
||||
return "", false
|
||||
}
|
||||
fallback := strings.TrimSpace(resultText)
|
||||
trimmed := strings.TrimSpace(content)
|
||||
if trimmed == "" || trimmed == "{}" || trimmed == "null" {
|
||||
if fallback == "" {
|
||||
return "", false
|
||||
}
|
||||
return fallback, true
|
||||
}
|
||||
var payload any
|
||||
if err := json.Unmarshal([]byte(trimmed), &payload); err != nil {
|
||||
if fallback == "" {
|
||||
return truncateProjectedReplayText("GenerateImage", trimmed, projectedWebSearchReplayLimit), true
|
||||
}
|
||||
return fallback, true
|
||||
}
|
||||
if compactGenerateImagePayload(payload) {
|
||||
encoded, err := json.Marshal(payload)
|
||||
if err == nil {
|
||||
return string(encoded), true
|
||||
}
|
||||
}
|
||||
if fallback != "" {
|
||||
return fallback, true
|
||||
}
|
||||
return trimmed, true
|
||||
}
|
||||
|
||||
func compactGenerateImagePayload(value any) bool {
|
||||
changed := false
|
||||
switch item := value.(type) {
|
||||
case map[string]any:
|
||||
for key, child := range item {
|
||||
if text, ok := child.(string); ok {
|
||||
switch key {
|
||||
case "image_data", "imageData":
|
||||
item[key] = fmt.Sprintf("[base64 image data omitted from replay; bytes=%d]", len(strings.TrimSpace(text)))
|
||||
changed = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
if compactGenerateImagePayload(child) {
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
case []any:
|
||||
for _, child := range item {
|
||||
if compactGenerateImagePayload(child) {
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed
|
||||
}
|
||||
|
||||
func patchEditReplayLimit(toolName string) int {
|
||||
switch strings.TrimSpace(toolName) {
|
||||
case "PatchEdit", "PatchEditLines", "PatchEditSpan":
|
||||
return projectedPatchEditReplayLimit
|
||||
default:
|
||||
return projectedEditReplayLimit
|
||||
}
|
||||
}
|
||||
|
||||
func compactProjectedShellToolResultReplay(toolName string, content string) (string, bool) {
|
||||
if strings.TrimSpace(toolName) != "Shell" {
|
||||
return "", false
|
||||
}
|
||||
trimmed := strings.TrimSpace(content)
|
||||
if trimmed == "" || trimmed == "{}" || trimmed == "null" {
|
||||
return "", false
|
||||
}
|
||||
var payload any
|
||||
if err := json.Unmarshal([]byte(trimmed), &payload); err != nil {
|
||||
return "", false
|
||||
}
|
||||
if !compactProjectedShellFields(payload) {
|
||||
return "", false
|
||||
}
|
||||
encoded, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
return string(encoded), true
|
||||
}
|
||||
|
||||
func compactProjectedShellFields(value any) bool {
|
||||
changed := false
|
||||
switch item := value.(type) {
|
||||
case map[string]any:
|
||||
for key, child := range item {
|
||||
if text, ok := child.(string); ok {
|
||||
switch key {
|
||||
case "stdout", "stderr":
|
||||
next := truncateProjectedReplayTextMiddle("Shell "+key, text, projectedShellStreamLimit)
|
||||
if next != text {
|
||||
item[key] = next
|
||||
changed = true
|
||||
}
|
||||
continue
|
||||
case "interleaved_output", "interleavedOutput":
|
||||
next := truncateProjectedReplayTextMiddle("Shell interleaved output", text, projectedShellInterleavedLimit)
|
||||
if next != text {
|
||||
item[key] = next
|
||||
changed = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
if compactProjectedShellFields(child) {
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
case []any:
|
||||
for _, child := range item {
|
||||
if compactProjectedShellFields(child) {
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed
|
||||
}
|
||||
|
||||
func compactProjectedEditToolResultReplay(toolName string, content string) (string, bool) {
|
||||
switch strings.TrimSpace(toolName) {
|
||||
case "PatchEdit", "PatchEditLines", "PatchEditSpan", "Edit", "Write":
|
||||
default:
|
||||
return "", false
|
||||
}
|
||||
trimmed := strings.TrimSpace(content)
|
||||
if trimmed == "" || trimmed == "{}" || trimmed == "null" {
|
||||
return "", false
|
||||
}
|
||||
var payload map[string]any
|
||||
if err := json.Unmarshal([]byte(trimmed), &payload); err != nil {
|
||||
return "", false
|
||||
}
|
||||
success, ok := payload["success"].(map[string]any)
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
diffString := firstJSONText(success, "diff_string", "diffString")
|
||||
beforeContent := ""
|
||||
afterContent := ""
|
||||
if diffString == "" {
|
||||
beforeContent = firstJSONText(success, "before_full_file_content", "beforeFullFileContent")
|
||||
afterContent = firstJSONText(success, "after_full_file_content", "afterFullFileContent")
|
||||
if beforeContent != "" {
|
||||
diffString, _, _ = computeEditDiff(beforeContent, afterContent)
|
||||
}
|
||||
}
|
||||
if diffString != "" {
|
||||
diffString = truncateProjectedReplayText(firstNonEmpty(strings.TrimSpace(toolName), "PatchEdit"), diffString, patchEditReplayLimit(toolName))
|
||||
encoded, err := json.Marshal(map[string]any{
|
||||
"success": map[string]any{
|
||||
"diff_string": diffString,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
return string(encoded), true
|
||||
}
|
||||
if afterContent != "" {
|
||||
afterContent = truncateProjectedReplayText(firstNonEmpty(strings.TrimSpace(toolName), "Write"), afterContent, patchEditReplayLimit(toolName))
|
||||
encoded, err := json.Marshal(map[string]any{
|
||||
"success": map[string]any{
|
||||
"after_full_file_content": afterContent,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
return string(encoded), true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func compactHistoricalEditErrorReplay(toolName string, content string) (string, bool) {
|
||||
switch strings.TrimSpace(toolName) {
|
||||
case "PatchEdit", "PatchEditLines", "PatchEditSpan", "Edit", "Write":
|
||||
default:
|
||||
return "", false
|
||||
}
|
||||
trimmed := strings.TrimSpace(content)
|
||||
if trimmed == "" {
|
||||
return "", false
|
||||
}
|
||||
var payload map[string]any
|
||||
if err := json.Unmarshal([]byte(trimmed), &payload); err != nil {
|
||||
return "", false
|
||||
}
|
||||
errorPayload, ok := payload["error"].(map[string]any)
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
if firstJSONText(errorPayload, "error", "modelVisibleError") == "" {
|
||||
return "", false
|
||||
}
|
||||
encoded, err := json.Marshal(map[string]any{
|
||||
"error": map[string]any{
|
||||
"error": "historical edit error omitted from replay; re-read the file before editing",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
return string(encoded), true
|
||||
}
|
||||
|
||||
func firstJSONText(payload map[string]any, keys ...string) string {
|
||||
for _, key := range keys {
|
||||
if value, ok := payload[key].(string); ok {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func truncateProjectedReplayText(toolName string, text string, limit int) string {
|
||||
if limit <= 0 || len(text) <= limit {
|
||||
return strings.TrimSpace(text)
|
||||
}
|
||||
original := len(text)
|
||||
notice := fmt.Sprintf("\n\n[truncated: %s result exceeded %d bytes; showing %d of %d bytes]", toolName, limit, limit, original)
|
||||
for {
|
||||
keep := limit - len(notice)
|
||||
if keep <= 0 {
|
||||
return truncateProjectedUTF8(text, limit)
|
||||
}
|
||||
kept := truncateProjectedUTF8(text, keep)
|
||||
nextNotice := fmt.Sprintf("\n\n[truncated: %s result exceeded %d bytes; showing %d of %d bytes]", toolName, limit, len(kept), original)
|
||||
output := strings.TrimRight(kept, "\n") + nextNotice
|
||||
if len(output) <= limit || nextNotice == notice {
|
||||
return output
|
||||
}
|
||||
notice = nextNotice
|
||||
}
|
||||
}
|
||||
|
||||
func truncateProjectedReplayTextMiddle(toolName string, text string, limit int) string {
|
||||
if limit <= 0 {
|
||||
return ""
|
||||
}
|
||||
if len(text) <= limit {
|
||||
return text
|
||||
}
|
||||
original := len(text)
|
||||
notice := fmt.Sprintf("\n\n[truncated: %s result exceeded %d bytes; omitted middle; showing %d of %d bytes]\n\n", toolName, limit, limit, original)
|
||||
for {
|
||||
keep := limit - len(notice)
|
||||
if keep <= 0 {
|
||||
return truncateProjectedUTF8(text, limit)
|
||||
}
|
||||
headLimit := keep / 2
|
||||
tailLimit := keep - headLimit
|
||||
head := truncateProjectedUTF8(text, headLimit)
|
||||
tail := truncateProjectedUTF8Suffix(text, tailLimit)
|
||||
kept := len(head) + len(tail)
|
||||
nextNotice := fmt.Sprintf("\n\n[truncated: %s result exceeded %d bytes; omitted middle; showing %d of %d bytes]\n\n", toolName, limit, kept, original)
|
||||
output := head + nextNotice + tail
|
||||
if len(output) <= limit || nextNotice == notice {
|
||||
return output
|
||||
}
|
||||
notice = nextNotice
|
||||
}
|
||||
}
|
||||
|
||||
func truncateProjectedUTF8(text string, limit int) string {
|
||||
if limit <= 0 {
|
||||
return ""
|
||||
}
|
||||
if len(text) <= limit {
|
||||
return text
|
||||
}
|
||||
if limit > len(text) {
|
||||
limit = len(text)
|
||||
}
|
||||
truncated := text[:limit]
|
||||
for !utf8.ValidString(truncated) && len(truncated) > 0 {
|
||||
truncated = truncated[:len(truncated)-1]
|
||||
}
|
||||
return truncated
|
||||
}
|
||||
|
||||
func truncateProjectedUTF8Suffix(text string, limit int) string {
|
||||
if limit <= 0 {
|
||||
return ""
|
||||
}
|
||||
if len(text) <= limit {
|
||||
return text
|
||||
}
|
||||
start := len(text) - limit
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
suffix := text[start:]
|
||||
for !utf8.ValidString(suffix) && start < len(text) {
|
||||
start++
|
||||
suffix = text[start:]
|
||||
}
|
||||
return suffix
|
||||
}
|
||||
Reference in New Issue
Block a user