Add projects
This commit is contained in:
parent
2d3a9ad623
commit
8b607dd700
1802 changed files with 503346 additions and 2 deletions
194
backend/internal/runtime/executor/helps/codex_input_ids.go
Normal file
194
backend/internal/runtime/executor/helps/codex_input_ids.go
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
package helps
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/internal/util"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/tidwall/sjson"
|
||||
)
|
||||
|
||||
const (
|
||||
codexInputItemIDLimit = 64
|
||||
codexMessageItemIDPrefix = "msg"
|
||||
codexReasoningItemIDPrefix = "rs"
|
||||
codexFunctionCallItemIDPrefix = "fc"
|
||||
codexCustomToolCallItemIDPrefix = "ctc"
|
||||
codexCustomToolCallOutputItemIDPrefix = "ctco"
|
||||
|
||||
codexInputItemIDOccupied uint8 = 1 << 0
|
||||
codexInputItemIDPreserved uint8 = 1 << 1
|
||||
)
|
||||
|
||||
// SanitizeCodexInputItemIDs normalizes supported input item IDs for Codex, removes encrypted
|
||||
// reasoning items whose IDs exceed the Codex limit, and deterministically shortens
|
||||
// other overlong input item IDs.
|
||||
func SanitizeCodexInputItemIDs(body []byte) []byte {
|
||||
input := util.GetGJSONBytesNoCopy(body, "input")
|
||||
if !input.IsArray() {
|
||||
return body
|
||||
}
|
||||
|
||||
items := input.Array()
|
||||
idStates := make(map[string]uint8, len(items))
|
||||
for _, item := range items {
|
||||
if shouldDropCodexEncryptedReasoningItem(item) {
|
||||
continue
|
||||
}
|
||||
itemID := item.Get("id")
|
||||
if itemID.Type != gjson.String {
|
||||
continue
|
||||
}
|
||||
originalID := itemID.String()
|
||||
id := normalizeCodexInputItemID(item, originalID)
|
||||
state := idStates[id]
|
||||
if id == originalID {
|
||||
state |= codexInputItemIDPreserved
|
||||
}
|
||||
if len([]rune(id)) <= codexInputItemIDLimit {
|
||||
state |= codexInputItemIDOccupied
|
||||
}
|
||||
if state != 0 {
|
||||
idStates[id] = state
|
||||
}
|
||||
}
|
||||
|
||||
var mapped map[string]string
|
||||
var collisionMapped map[string]string
|
||||
rebuilt := make([]string, 0, len(items))
|
||||
changed := false
|
||||
for _, item := range items {
|
||||
if shouldDropCodexEncryptedReasoningItem(item) {
|
||||
changed = true
|
||||
continue
|
||||
}
|
||||
|
||||
raw := item.Raw
|
||||
itemID := item.Get("id")
|
||||
if itemID.Type == gjson.String {
|
||||
originalID := itemID.String()
|
||||
id := normalizeCodexInputItemID(item, originalID)
|
||||
if id != originalID && idStates[id]&codexInputItemIDPreserved != 0 {
|
||||
collisionID, ok := collisionMapped[id]
|
||||
if !ok {
|
||||
for attempt := 0; ; attempt++ {
|
||||
collisionID = codexInputItemIDWithHashSuffix(id, attempt)
|
||||
if idStates[collisionID]&codexInputItemIDOccupied != 0 {
|
||||
continue
|
||||
}
|
||||
if collisionMapped == nil {
|
||||
collisionMapped = make(map[string]string)
|
||||
}
|
||||
collisionMapped[id] = collisionID
|
||||
idStates[collisionID] |= codexInputItemIDOccupied
|
||||
break
|
||||
}
|
||||
}
|
||||
id = collisionID
|
||||
}
|
||||
if len([]rune(id)) > codexInputItemIDLimit {
|
||||
shortened, ok := mapped[id]
|
||||
if !ok {
|
||||
shortened = shortenCodexInputItemID(id)
|
||||
for attempt := 1; ; attempt++ {
|
||||
if idStates[shortened]&codexInputItemIDOccupied == 0 {
|
||||
break
|
||||
}
|
||||
shortened = shortenCodexInputItemIDWithAttempt(id, attempt)
|
||||
}
|
||||
if mapped == nil {
|
||||
mapped = make(map[string]string)
|
||||
}
|
||||
mapped[id] = shortened
|
||||
idStates[shortened] |= codexInputItemIDOccupied
|
||||
}
|
||||
id = shortened
|
||||
}
|
||||
|
||||
if id != originalID {
|
||||
next, errSet := sjson.SetBytes([]byte(raw), "id", id)
|
||||
if errSet == nil {
|
||||
raw = string(next)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
rebuilt = append(rebuilt, raw)
|
||||
}
|
||||
if !changed {
|
||||
return body
|
||||
}
|
||||
|
||||
updated, errSet := sjson.SetRawBytes(body, "input", []byte("["+strings.Join(rebuilt, ",")+"]"))
|
||||
if errSet != nil {
|
||||
return body
|
||||
}
|
||||
return updated
|
||||
}
|
||||
|
||||
func normalizeCodexInputItemID(item gjson.Result, id string) string {
|
||||
var prefix string
|
||||
switch item.Get("type").String() {
|
||||
case "message":
|
||||
prefix = codexMessageItemIDPrefix
|
||||
case "reasoning":
|
||||
prefix = codexReasoningItemIDPrefix
|
||||
case "function_call":
|
||||
prefix = codexFunctionCallItemIDPrefix
|
||||
case "custom_tool_call":
|
||||
prefix = codexCustomToolCallItemIDPrefix
|
||||
case "custom_tool_call_output":
|
||||
prefix = codexCustomToolCallOutputItemIDPrefix
|
||||
default:
|
||||
return id
|
||||
}
|
||||
if id == "" || strings.HasPrefix(id, prefix) {
|
||||
return id
|
||||
}
|
||||
return prefix + "_" + id
|
||||
}
|
||||
|
||||
func shouldDropCodexEncryptedReasoningItem(item gjson.Result) bool {
|
||||
if item.Get("type").String() != "reasoning" {
|
||||
return false
|
||||
}
|
||||
itemID := item.Get("id")
|
||||
if itemID.Type != gjson.String || len([]rune(itemID.String())) <= codexInputItemIDLimit {
|
||||
return false
|
||||
}
|
||||
encryptedContent := item.Get("encrypted_content")
|
||||
return encryptedContent.Type == gjson.String && encryptedContent.String() != ""
|
||||
}
|
||||
|
||||
func shortenCodexInputItemID(id string) string {
|
||||
return shortenCodexInputItemIDWithAttempt(id, 0)
|
||||
}
|
||||
|
||||
func shortenCodexInputItemIDWithAttempt(id string, attempt int) string {
|
||||
runes := []rune(id)
|
||||
if len(runes) <= codexInputItemIDLimit {
|
||||
return id
|
||||
}
|
||||
return codexInputItemIDWithHashSuffixRunes(id, runes, attempt)
|
||||
}
|
||||
|
||||
func codexInputItemIDWithHashSuffix(id string, attempt int) string {
|
||||
return codexInputItemIDWithHashSuffixRunes(id, []rune(id), attempt)
|
||||
}
|
||||
|
||||
func codexInputItemIDWithHashSuffixRunes(id string, runes []rune, attempt int) string {
|
||||
hashInput := id
|
||||
if attempt > 0 {
|
||||
hashInput += "\x00" + strconv.Itoa(attempt)
|
||||
}
|
||||
sum := sha256.Sum256([]byte(hashInput))
|
||||
suffix := "_" + hex.EncodeToString(sum[:8])
|
||||
prefixLength := codexInputItemIDLimit - len(suffix)
|
||||
if len(runes) < prefixLength {
|
||||
prefixLength = len(runes)
|
||||
}
|
||||
return string(runes[:prefixLength]) + suffix
|
||||
}
|
||||
Loading…
Reference in a new issue