mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-08-17 19:47:10 +08:00
v0.3.8
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
package forwarder
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
modeladapter "cursor/internal/backend/agent/model"
|
||||
)
|
||||
|
||||
func newPromptContextMessage(source string, message modeladapter.Message, persist bool) PromptContextMessage {
|
||||
context := PromptContextMessage{
|
||||
Source: strings.TrimSpace(source),
|
||||
Message: message,
|
||||
Persist: persist,
|
||||
}
|
||||
context.ContentHash = promptContextContentHash(context.Message)
|
||||
return context
|
||||
}
|
||||
|
||||
func normalizePromptContextMessage(context PromptContextMessage) PromptContextMessage {
|
||||
context.Source = strings.TrimSpace(context.Source)
|
||||
context.Message.Role = strings.TrimSpace(context.Message.Role)
|
||||
context.Message.Content = strings.TrimSpace(context.Message.Content)
|
||||
context.ContentHash = strings.TrimSpace(context.ContentHash)
|
||||
if context.ContentHash == "" {
|
||||
context.ContentHash = promptContextContentHash(context.Message)
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
func promptContextContentHash(message modeladapter.Message) string {
|
||||
sum := sha256.Sum256([]byte(strings.TrimSpace(message.Role) + "\x00" + strings.TrimSpace(message.Content)))
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
func filterCurrentTurnPromptContexts(conversation *ConversationFile, contexts []PromptContextMessage) []PromptContextMessage {
|
||||
if len(contexts) == 0 {
|
||||
return nil
|
||||
}
|
||||
seen := collectCurrentTurnPromptContextKeys(conversation)
|
||||
filtered := make([]PromptContextMessage, 0, len(contexts))
|
||||
for _, context := range contexts {
|
||||
context = normalizePromptContextMessage(context)
|
||||
if !isReplayablePromptContext(context) {
|
||||
continue
|
||||
}
|
||||
if context.Persist {
|
||||
if _, ok := seen[promptContextKey(context)]; ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
filtered = append(filtered, context)
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
func collectCurrentTurnPromptContextKeys(conversation *ConversationFile) map[string]struct{} {
|
||||
keys := make(map[string]struct{})
|
||||
if conversation == nil {
|
||||
return keys
|
||||
}
|
||||
currentTurnSeq := conversation.NextTurnSeq - 1
|
||||
if currentTurnSeq <= 0 {
|
||||
return keys
|
||||
}
|
||||
for _, entry := range conversation.Entries {
|
||||
if entry.TurnSeq != currentTurnSeq || strings.TrimSpace(entry.Kind) != "prompt_context" {
|
||||
continue
|
||||
}
|
||||
var payload promptContextEntryPayload
|
||||
if err := json.Unmarshal(entry.Payload, &payload); err != nil {
|
||||
continue
|
||||
}
|
||||
context := normalizePromptContextMessage(PromptContextMessage{
|
||||
Source: payload.Source,
|
||||
ContentHash: payload.ContentHash,
|
||||
Message: modeladapter.Message{
|
||||
Role: payload.Role,
|
||||
Content: payload.Content,
|
||||
},
|
||||
Persist: true,
|
||||
})
|
||||
if !isReplayablePromptContext(context) {
|
||||
continue
|
||||
}
|
||||
keys[promptContextKey(context)] = struct{}{}
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func promptContextKey(context PromptContextMessage) string {
|
||||
context = normalizePromptContextMessage(context)
|
||||
return context.Source + "\x00" + context.ContentHash
|
||||
}
|
||||
|
||||
func isReplayablePromptContext(context PromptContextMessage) bool {
|
||||
context = normalizePromptContextMessage(context)
|
||||
if context.Source == "" || strings.TrimSpace(context.Message.Content) == "" {
|
||||
return false
|
||||
}
|
||||
if context.Message.Role == "" {
|
||||
context.Message.Role = "user"
|
||||
}
|
||||
if context.Message.Role != "user" && context.Message.Role != "system" {
|
||||
return false
|
||||
}
|
||||
if strings.TrimSpace(context.Message.Name) != "" || strings.TrimSpace(context.Message.ToolCallID) != "" {
|
||||
return false
|
||||
}
|
||||
return len(context.Message.ToolCalls) == 0 && len(context.Message.ContentParts) == 0
|
||||
}
|
||||
|
||||
func newPromptContextEntry(turnSeq int64, requestID string, context PromptContextMessage) HistoryEntry {
|
||||
context = normalizePromptContextMessage(context)
|
||||
payload, _ := json.Marshal(promptContextEntryPayload{
|
||||
Source: context.Source,
|
||||
Role: firstNonEmpty(strings.TrimSpace(context.Message.Role), "user"),
|
||||
Content: strings.TrimSpace(context.Message.Content),
|
||||
ContentHash: context.ContentHash,
|
||||
})
|
||||
return HistoryEntry{
|
||||
TurnSeq: turnSeq,
|
||||
RequestID: strings.TrimSpace(requestID),
|
||||
Role: "system",
|
||||
Kind: "prompt_context",
|
||||
Payload: payload,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user