Sub2API v1.0 - AI API 网关(二开初始版本,基于上游 Wei-Shaw/sub2api)
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/xai"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type grokStandaloneSearchRequest struct {
|
||||
Query string `json:"query"`
|
||||
Input string `json:"input"`
|
||||
MaxResults *int `json:"max_results"`
|
||||
AllowedXHandles []string `json:"allowed_x_handles"`
|
||||
ExcludedXHandles []string `json:"excluded_x_handles"`
|
||||
FromDate string `json:"from_date"`
|
||||
ToDate string `json:"to_date"`
|
||||
EnableImageUnderstanding *bool `json:"enable_image_understanding"`
|
||||
EnableVideoUnderstanding *bool `json:"enable_video_understanding"`
|
||||
}
|
||||
|
||||
// XSearch marks the standalone endpoint so WebSearch can use native x_search
|
||||
// while retaining its dedicated per-call billing contract.
|
||||
func (h *GatewayHandler) XSearch(c *gin.Context) {
|
||||
c.Set("grok_x_search_endpoint", true)
|
||||
h.WebSearch(c)
|
||||
}
|
||||
|
||||
func resolveGrokStandaloneSearchModel() string {
|
||||
return xai.ResolveDefaultTextModel(xai.RuntimeModelMappingOptions().DefaultText)
|
||||
}
|
||||
|
||||
func buildGrokXSearchResponsesBody(req grokStandaloneSearchRequest, model string) ([]byte, error) {
|
||||
input := strings.TrimSpace(req.Query)
|
||||
if input == "" {
|
||||
input = strings.TrimSpace(req.Input)
|
||||
}
|
||||
tool := map[string]any{"type": "x_search"}
|
||||
if len(req.AllowedXHandles) > 0 {
|
||||
tool["allowed_x_handles"] = req.AllowedXHandles
|
||||
}
|
||||
if len(req.ExcludedXHandles) > 0 {
|
||||
tool["excluded_x_handles"] = req.ExcludedXHandles
|
||||
}
|
||||
if strings.TrimSpace(req.FromDate) != "" {
|
||||
tool["from_date"] = strings.TrimSpace(req.FromDate)
|
||||
}
|
||||
if strings.TrimSpace(req.ToDate) != "" {
|
||||
tool["to_date"] = strings.TrimSpace(req.ToDate)
|
||||
}
|
||||
if req.EnableImageUnderstanding != nil {
|
||||
tool["enable_image_understanding"] = *req.EnableImageUnderstanding
|
||||
}
|
||||
if req.EnableVideoUnderstanding != nil {
|
||||
tool["enable_video_understanding"] = *req.EnableVideoUnderstanding
|
||||
}
|
||||
maxResults := 0
|
||||
if req.MaxResults != nil {
|
||||
maxResults = *req.MaxResults
|
||||
}
|
||||
return json.Marshal(map[string]any{
|
||||
"model": xai.ResolveDefaultTextModel(model),
|
||||
"input": buildGrokXSearchPrompt(input, maxResults),
|
||||
"tools": []map[string]any{tool},
|
||||
"tool_choice": "required",
|
||||
"include": []string{"x_search_call.action.sources"},
|
||||
"store": false,
|
||||
"stream": false,
|
||||
})
|
||||
}
|
||||
|
||||
func buildGrokXSearchPrompt(query string, maxResults int) string {
|
||||
return fmt.Sprintf(`Search X for the user query below. Return ONLY valid JSON with this exact shape: {"results":[{"url":"https://...","title":"post or page title","snippet":"concise factual summary"}]}. Return at most %d unique results. Every URL must be an actual x_search source. Populate a non-empty title and snippet for every result. Do not wrap the JSON in markdown.
|
||||
|
||||
User query:
|
||||
%s`, normalizeGrokWebSearchMaxResults(maxResults), query)
|
||||
}
|
||||
Reference in New Issue
Block a user