Add projects

This commit is contained in:
Alois 2026-08-24 00:10:41 +02:00
commit 8b607dd700
Signed by: alois
SSH key fingerprint: SHA256:GBzT2DXvAuGV9XIV5W3WrzVpjU54FThmxHXdbz95J24
1802 changed files with 503346 additions and 2 deletions

View file

@ -0,0 +1,336 @@
package openai
import (
"bytes"
"fmt"
"io"
"net/http"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"github.com/router-for-me/CLIProxyAPI/v7/internal/interfaces"
requestlogging "github.com/router-for-me/CLIProxyAPI/v7/internal/logging"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
)
type websocketTimelineAppender interface {
Append(eventType string, payload []byte, timestamp time.Time)
}
type responsesWebsocketPinnedAuthState struct {
authID string
modelKey string
}
type websocketTimelineLog struct {
enabled bool
source *requestlogging.FileBodySource
builder *strings.Builder
currentPart io.WriteCloser
currentPartHasLog bool
}
func newWebsocketTimelineLog(enabled bool, source *requestlogging.FileBodySource) *websocketTimelineLog {
if !enabled {
return &websocketTimelineLog{}
}
if source == nil {
return newInMemoryWebsocketTimelineLog()
}
return &websocketTimelineLog{
enabled: true,
source: source,
}
}
func newInMemoryWebsocketTimelineLog() *websocketTimelineLog {
return &websocketTimelineLog{
enabled: true,
builder: &strings.Builder{},
}
}
func websocketTimelineSourceFromContext(c *gin.Context) *requestlogging.FileBodySource {
if c == nil {
return nil
}
value, exists := c.Get(requestlogging.WebsocketTimelineSourceContextKey)
if !exists {
return nil
}
source, ok := value.(*requestlogging.FileBodySource)
if !ok {
return nil
}
return source
}
func (l *websocketTimelineLog) BeginRequest() {
if l == nil || !l.enabled || l.source == nil {
return
}
l.closeCurrentPart()
part, errCreate := l.source.CreatePart("request")
if errCreate != nil {
log.WithError(errCreate).Warn("failed to create websocket request detail log")
return
}
l.currentPart = part
l.currentPartHasLog = false
}
func (l *websocketTimelineLog) Append(eventType string, payload []byte, timestamp time.Time) {
if l == nil || !l.enabled {
return
}
data := formatWebsocketTimelineEvent(eventType, payload, timestamp)
if len(data) == 0 {
return
}
if l.source != nil {
if l.currentPart == nil {
l.BeginRequest()
}
if l.currentPart == nil {
return
}
if errWrite := writeWebsocketTimelinePart(l.currentPart, data, l.currentPartHasLog); errWrite != nil {
log.WithError(errWrite).Warn("failed to write websocket request detail log")
return
}
l.currentPartHasLog = true
return
}
if l.builder != nil {
writeWebsocketTimelineBuilder(l.builder, data)
}
}
func (l *websocketTimelineLog) SetContext(c *gin.Context) {
if l == nil || !l.enabled {
return
}
l.closeCurrentPart()
if l.source != nil {
if l.source.HasPayload() {
c.Set(requestlogging.WebsocketTimelineSourceContextKey, l.source)
return
}
if errCleanup := l.source.Cleanup(); errCleanup != nil {
log.WithError(errCleanup).Warn("failed to clean up empty websocket timeline log parts")
}
}
if l.builder != nil {
setWebsocketTimelineBody(c, l.builder.String())
}
}
func (l *websocketTimelineLog) String() string {
if l == nil || !l.enabled {
return ""
}
l.closeCurrentPart()
if l.source != nil {
data, errRead := l.source.Bytes()
if errRead != nil {
return ""
}
return string(data)
}
if l.builder == nil {
return ""
}
return l.builder.String()
}
func (l *websocketTimelineLog) closeCurrentPart() {
if l == nil || l.currentPart == nil {
return
}
if errClose := l.currentPart.Close(); errClose != nil {
log.WithError(errClose).Warn("failed to close websocket request detail log")
}
l.currentPart = nil
l.currentPartHasLog = false
}
func writeWebsocketTimelinePart(w io.Writer, data []byte, prependNewline bool) error {
if w == nil || len(data) == 0 {
return nil
}
if prependNewline {
if _, errWrite := io.WriteString(w, "\n"); errWrite != nil {
return errWrite
}
}
_, errWrite := w.Write(data)
return errWrite
}
func writeWebsocketTimelineBuilder(builder *strings.Builder, data []byte) {
if builder == nil || len(data) == 0 {
return
}
if builder.Len() > 0 {
builder.WriteString("\n")
}
builder.Write(data)
}
func appendWebsocketEvent(builder *strings.Builder, eventType string, payload []byte) {
if builder == nil {
return
}
trimmedPayload := bytes.TrimSpace(payload)
if len(trimmedPayload) == 0 {
return
}
if builder.Len() > 0 {
builder.WriteString("\n")
}
builder.WriteString("websocket.")
builder.WriteString(eventType)
builder.WriteString("\n")
builder.Write(trimmedPayload)
builder.WriteString("\n")
}
func websocketPayloadEventType(payload []byte) string {
eventType := strings.TrimSpace(gjson.GetBytes(payload, "type").String())
if eventType == "" {
return "-"
}
return eventType
}
func websocketPayloadPreview(payload []byte) string {
trimmedPayload := bytes.TrimSpace(payload)
if len(trimmedPayload) == 0 {
return "<empty>"
}
previewText := strings.ReplaceAll(string(trimmedPayload), "\n", "\\n")
previewText = strings.ReplaceAll(previewText, "\r", "\\r")
return previewText
}
func isResponsesWebsocketCompletionEvent(eventType string) bool {
return eventType == wsEventTypeCompleted || eventType == wsEventTypeDone
}
type responsesWebsocketPayloadError struct {
status int
payload []byte
}
func (e *responsesWebsocketPayloadError) Error() string {
if e == nil {
return ""
}
return string(e.payload)
}
func (e *responsesWebsocketPayloadError) StatusCode() int {
if e == nil {
return 0
}
return e.status
}
func responsesWebsocketErrorMessageFromPayload(payload []byte) *interfaces.ErrorMessage {
status := int(gjson.GetBytes(payload, "status").Int())
if status <= 0 {
status = int(gjson.GetBytes(payload, "status_code").Int())
}
if status <= 0 {
status = http.StatusInternalServerError
}
trimmedPayload := bytes.TrimSpace(payload)
if len(trimmedPayload) > 0 {
return &interfaces.ErrorMessage{
StatusCode: status,
Error: &responsesWebsocketPayloadError{
status: status,
payload: bytes.Clone(trimmedPayload),
},
}
}
return &interfaces.ErrorMessage{StatusCode: status, Error: fmt.Errorf("%s", http.StatusText(status))}
}
func setWebsocketTimelineBody(c *gin.Context, body string) {
setWebsocketBody(c, wsTimelineBodyKey, body)
}
func setWebsocketBody(c *gin.Context, key string, body string) {
if c == nil {
return
}
trimmedBody := strings.TrimSpace(body)
if trimmedBody == "" {
return
}
c.Set(key, []byte(trimmedBody))
}
func writeResponsesWebsocketPayload(writer *responsesWebsocketWriter, wsTimelineLog websocketTimelineAppender, payload []byte, timestamp time.Time) error {
if wsTimelineLog != nil {
wsTimelineLog.Append("response", payload, timestamp)
}
if writer == nil || writer.conn == nil {
return fmt.Errorf("responses websocket: writer is nil")
}
writer.writeMu.Lock()
defer writer.writeMu.Unlock()
if writer.closing.Load() {
return websocket.ErrCloseSent
}
return writer.conn.WriteMessage(websocket.TextMessage, payload)
}
func appendWebsocketTimelineDisconnect(timeline websocketTimelineAppender, err error, timestamp time.Time) {
if err == nil {
return
}
if timeline != nil {
timeline.Append("disconnect", []byte(err.Error()), timestamp)
}
}
func appendWebsocketTimelineEvent(builder *strings.Builder, eventType string, payload []byte, timestamp time.Time) {
if builder == nil {
return
}
writeWebsocketTimelineBuilder(builder, formatWebsocketTimelineEvent(eventType, payload, timestamp))
}
func formatWebsocketTimelineEvent(eventType string, payload []byte, timestamp time.Time) []byte {
trimmedPayload := bytes.TrimSpace(payload)
if len(trimmedPayload) == 0 {
return nil
}
var builder strings.Builder
builder.WriteString("Timestamp: ")
builder.WriteString(timestamp.Format(time.RFC3339Nano))
builder.WriteString("\n")
builder.WriteString("Event: websocket.")
builder.WriteString(eventType)
builder.WriteString("\n")
builder.Write(trimmedPayload)
builder.WriteString("\n")
return []byte(builder.String())
}
func markAPIResponseTimestamp(c *gin.Context) {
if c == nil {
return
}
if _, exists := c.Get("API_RESPONSE_TIMESTAMP"); exists {
return
}
c.Set("API_RESPONSE_TIMESTAMP", time.Now())
}