Add projects
This commit is contained in:
parent
2d3a9ad623
commit
8b607dd700
1802 changed files with 503346 additions and 2 deletions
84
backend/internal/client/grokbuild/keepalive.go
Normal file
84
backend/internal/client/grokbuild/keepalive.go
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
package grokbuild
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
var keepaliveSSEComment = []byte(": keepalive\n\n")
|
||||
|
||||
// KeepaliveSSEComment returns the standard SSE comment used for keepalive.
|
||||
func KeepaliveSSEComment() []byte {
|
||||
return bytes.Clone(keepaliveSSEComment)
|
||||
}
|
||||
|
||||
// IsGrokClientUserAgent checks if the user agent contains "grok-pager" or "grok-shell".
|
||||
func IsGrokClientUserAgent(userAgent string) bool {
|
||||
ua := strings.ToLower(userAgent)
|
||||
return strings.Contains(ua, "grok-pager") || strings.Contains(ua, "grok-shell")
|
||||
}
|
||||
|
||||
// IsGrokClientHeaders checks if the provided HTTP headers indicate a Grok client.
|
||||
func IsGrokClientHeaders(headers http.Header) bool {
|
||||
if headers == nil {
|
||||
return false
|
||||
}
|
||||
for key, values := range headers {
|
||||
if strings.EqualFold(key, "User-Agent") {
|
||||
if slices.ContainsFunc(values, IsGrokClientUserAgent) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsGrokClientContext checks if either the context (e.g. Gin context) or headers indicate a Grok client.
|
||||
func IsGrokClientContext(ctx context.Context, headers http.Header) bool {
|
||||
if ctx != nil {
|
||||
if ginCtx, ok := ctx.Value("gin").(*gin.Context); ok && ginCtx != nil && ginCtx.Request != nil {
|
||||
if IsGrokClientHeaders(ginCtx.Request.Header) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return IsGrokClientHeaders(headers)
|
||||
}
|
||||
|
||||
// IsKeepalivePayload reports whether a JSON payload has type "keepalive".
|
||||
func IsKeepalivePayload(payload []byte) bool {
|
||||
return gjson.GetBytes(payload, "type").String() == "keepalive"
|
||||
}
|
||||
|
||||
// IsKeepaliveSSELine reports whether an SSE line represents a keepalive event or data frame.
|
||||
func IsKeepaliveSSELine(line []byte) bool {
|
||||
trimmed := bytes.TrimSpace(line)
|
||||
if bytes.HasPrefix(trimmed, []byte("event:")) {
|
||||
eventName := bytes.TrimSpace(trimmed[6:])
|
||||
return bytes.Equal(eventName, []byte("keepalive"))
|
||||
}
|
||||
if bytes.HasPrefix(trimmed, []byte("data:")) {
|
||||
data := bytes.TrimSpace(trimmed[5:])
|
||||
return IsKeepalivePayload(data)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// TransformKeepaliveSSELine transforms a keepalive SSE line into an SSE comment line
|
||||
// when isGrokClient is true. If the line is not a keepalive line or isGrokClient is false,
|
||||
// it returns the original line and false.
|
||||
func TransformKeepaliveSSELine(line []byte, isGrokClient bool) ([]byte, bool) {
|
||||
if !isGrokClient {
|
||||
return line, false
|
||||
}
|
||||
if IsKeepaliveSSELine(line) {
|
||||
return bytes.Clone(keepaliveSSEComment), true
|
||||
}
|
||||
return line, false
|
||||
}
|
||||
Loading…
Reference in a new issue