Files
CLIProxyAPI/internal/runtime/executor/helps/codex_input_ids.go
Luis Pater 1cfe529f32 feat(executor): add ID shortening for overlong Codex input items
- Implemented deterministic shortening of overlong Codex input item IDs to meet 64-character limit.
- Added `SanitizeCodexInputItemIDs` helper for efficient ID shortening in request bodies.
- Updated Codex executor and websocket implementations to utilize the new helper.
- Introduced unit tests to validate ID length restrictions, avoidance of collisions, and deterministic behavior.

Closes: #4401
2026-07-17 23:52:58 +08:00

86 lines
1.9 KiB
Go

package helps
import (
"crypto/sha256"
"encoding/hex"
"strconv"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
)
const codexInputItemIDLimit = 64
// SanitizeCodexInputItemIDs deterministically shortens overlong Responses input item IDs.
func SanitizeCodexInputItemIDs(body []byte) []byte {
input := gjson.GetBytes(body, "input")
if !input.IsArray() {
return body
}
items := input.Array()
occupied := make(map[string]struct{}, len(items))
for _, item := range items {
itemID := item.Get("id")
if itemID.Type != gjson.String {
continue
}
id := itemID.String()
if len([]rune(id)) <= codexInputItemIDLimit {
occupied[id] = struct{}{}
}
}
mapped := make(map[string]string, len(items))
updated := body
for index, item := range items {
itemID := item.Get("id")
if itemID.Type != gjson.String {
continue
}
id := itemID.String()
if len([]rune(id)) <= codexInputItemIDLimit {
continue
}
shortened, ok := mapped[id]
if !ok {
shortened = shortenCodexInputItemID(id)
for attempt := 1; ; attempt++ {
if _, exists := occupied[shortened]; !exists {
break
}
shortened = shortenCodexInputItemIDWithAttempt(id, attempt)
}
mapped[id] = shortened
occupied[shortened] = struct{}{}
}
next, errSet := sjson.SetBytes(updated, "input."+strconv.Itoa(index)+".id", shortened)
if errSet == nil {
updated = next
}
}
return updated
}
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
}
hashInput := id
if attempt > 0 {
hashInput += "\x00" + strconv.Itoa(attempt)
}
sum := sha256.Sum256([]byte(hashInput))
suffix := "_" + hex.EncodeToString(sum[:8])
prefixLength := codexInputItemIDLimit - len(suffix)
return string(runes[:prefixLength]) + suffix
}