feat: publish sanitized custom.97 source
This commit is contained in:
1022 files changed
+69903
-19207
No files matched your search
@@ -93,6 +93,7 @@ type GeneralOpenAIRequest struct {
|
||||
ThinkingBudget json.RawMessage `json:"thinking_budget,omitempty"`
|
||||
ChatTemplateKwargs json.RawMessage `json:"chat_template_kwargs,omitempty"`
|
||||
EnableSearch json.RawMessage `json:"enable_search,omitempty"`
|
||||
SearchOptions json.RawMessage `json:"search_options,omitempty"`
|
||||
// ollama Params
|
||||
Think json.RawMessage `json:"think,omitempty"`
|
||||
// baidu v2
|
||||
@@ -251,6 +252,14 @@ func (r *GeneralOpenAIRequest) GetTokenCountMeta() *types.TokenCountMeta {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Assistant tool calls replayed in agent loops are part of the prompt.
|
||||
for _, toolCall := range message.ParseToolCalls() {
|
||||
if len(toolCall.Custom) > 0 {
|
||||
texts = append(texts, string(toolCall.Custom))
|
||||
continue
|
||||
}
|
||||
texts = append(texts, toolCall.Function.Name, toolCall.Function.Arguments)
|
||||
}
|
||||
}
|
||||
|
||||
tools := r.Tools
|
||||
@@ -259,12 +268,17 @@ func (r *GeneralOpenAIRequest) GetTokenCountMeta() *types.TokenCountMeta {
|
||||
}
|
||||
for _, tool := range tools {
|
||||
tokenCountMeta.ToolsCount++
|
||||
if len(tool.Custom) > 0 {
|
||||
texts = append(texts, string(tool.Custom))
|
||||
continue
|
||||
}
|
||||
texts = append(texts, tool.Function.Name)
|
||||
if tool.Function.Description != "" {
|
||||
texts = append(texts, tool.Function.Description)
|
||||
}
|
||||
if tool.Function.Parameters != nil {
|
||||
texts = append(texts, fmt.Sprintf("%v", tool.Function.Parameters))
|
||||
parameters, _ := kitutil.Marshal(tool.Function.Parameters)
|
||||
texts = append(texts, string(parameters))
|
||||
}
|
||||
}
|
||||
//toolTokens := CountTokenInput(countStr, request.Model)
|
||||
@@ -329,7 +343,8 @@ func GetOpenAIChatCapabilities(modelName, reasoningEffort string) OpenAIChatCapa
|
||||
}
|
||||
|
||||
isGPT5Model := IsOpenAIGPT5Model(modelName)
|
||||
if !isGPT5Model && !isOpenAIModelSnapshot(modelName, "gpt-6-astra") {
|
||||
isGPT6SolLuna := isOpenAIModelSnapshot(modelName, "gpt-6-sol") || isOpenAIModelSnapshot(modelName, "gpt-6-luna")
|
||||
if !isGPT5Model && !isGPT6SolLuna && !isOpenAIModelSnapshot(modelName, "gpt-6-astra") {
|
||||
return capabilities
|
||||
}
|
||||
capabilities.UseMaxCompletionTokens = true
|
||||
@@ -337,12 +352,15 @@ func GetOpenAIChatCapabilities(modelName, reasoningEffort string) OpenAIChatCapa
|
||||
|
||||
// These standard GPT-5 models default to none and support sampling only
|
||||
// without reasoning. Named variants (pro, codex, chat-latest, etc.) do not
|
||||
// inherit this exception. GPT-6 Astra never supports these parameters.
|
||||
// inherit this exception. GPT-6 Sol and Luna follow the same rule. GPT-6
|
||||
// Astra never supports these parameters.
|
||||
// https://developers.openai.com/api/docs/guides/latest-model?model=gpt-5.2
|
||||
// https://developers.openai.com/api/docs/guides/latest-model?model=gpt-5.4
|
||||
// https://developers.openai.com/api/docs/guides/latest-model?model=gpt-6-astra
|
||||
// https://developers.openai.com/api/docs/guides/latest-model?model=gpt-6-luna
|
||||
supportsSampling := false
|
||||
if isGPT5Model && (reasoningEffort == "" || reasoningEffort == "none") {
|
||||
if reasoningEffort == "" || reasoningEffort == "none" {
|
||||
supportsSampling = isGPT6SolLuna
|
||||
for _, model := range []string{"gpt-5.1", "gpt-5.2", "gpt-5.4"} {
|
||||
if isOpenAIModelSnapshot(modelName, model) {
|
||||
supportsSampling = true
|
||||
@@ -390,6 +408,19 @@ type ToolCallRequest struct {
|
||||
Type string `json:"type"`
|
||||
Function FunctionRequest `json:"function"`
|
||||
Custom json.RawMessage `json:"custom,omitempty"`
|
||||
// Native is a complete vendor tool object sent instead of the fields
|
||||
// above. Function has no omitempty, so a non-function tool would
|
||||
// otherwise carry "function":{"name":""}, which vendor schemas with
|
||||
// additionalProperties:false reject. Never read from client JSON.
|
||||
Native json.RawMessage `json:"-"`
|
||||
}
|
||||
|
||||
func (t ToolCallRequest) MarshalJSON() ([]byte, error) {
|
||||
if len(t.Native) > 0 {
|
||||
return t.Native, nil
|
||||
}
|
||||
type Alias ToolCallRequest
|
||||
return kitutil.Marshal((*Alias)(&t))
|
||||
}
|
||||
|
||||
type FunctionRequest struct {
|
||||
@@ -567,9 +598,11 @@ func (m *MediaContent) ToFileSource() types.FileSource {
|
||||
}
|
||||
|
||||
type MessageImageUrl struct {
|
||||
Url string `json:"url"`
|
||||
Detail string `json:"detail,omitempty"`
|
||||
MimeType string
|
||||
Url string `json:"url"`
|
||||
Detail string `json:"detail,omitempty"`
|
||||
// MimeType is in-memory metadata for converters and token counting; it is
|
||||
// not part of the Chat image_url object.
|
||||
MimeType string `json:"-"`
|
||||
}
|
||||
|
||||
func (m *MessageImageUrl) IsRemoteImage() bool {
|
||||
@@ -743,9 +776,9 @@ func (m *Message) ParseContent() []MediaContent {
|
||||
|
||||
case ContentTypeImageURL:
|
||||
imageUrl := contentItem["image_url"]
|
||||
temp := &MessageImageUrl{
|
||||
Detail: "high",
|
||||
}
|
||||
// An omitted detail stays empty: upstream defaults it to auto, which
|
||||
// costs more than high on gpt-5.5 and later.
|
||||
temp := &MessageImageUrl{}
|
||||
switch v := imageUrl.(type) {
|
||||
case string:
|
||||
temp.Url = v
|
||||
@@ -1103,7 +1136,12 @@ func (r *OpenAIResponsesRequest) GetTokenCountMeta() *types.TokenCountMeta {
|
||||
}
|
||||
|
||||
if len(r.Instructions) > 0 {
|
||||
texts = append(texts, string(r.Instructions))
|
||||
var instructions string
|
||||
if kitutil.GetJsonType(r.Instructions) == "string" && kitutil.Unmarshal(r.Instructions, &instructions) == nil {
|
||||
texts = append(texts, instructions)
|
||||
} else {
|
||||
texts = append(texts, string(r.Instructions))
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.Metadata) > 0 {
|
||||
@@ -1162,6 +1200,11 @@ type Input struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Role string `json:"role,omitempty"`
|
||||
Content json.RawMessage `json:"content,omitempty"`
|
||||
// Tool-call items replayed in agent loops.
|
||||
Name string `json:"name,omitempty"`
|
||||
Arguments json.RawMessage `json:"arguments,omitempty"`
|
||||
ToolInput json.RawMessage `json:"input,omitempty"`
|
||||
Output json.RawMessage `json:"output,omitempty"`
|
||||
}
|
||||
|
||||
type MediaInput struct {
|
||||
@@ -1176,7 +1219,8 @@ type MediaInput struct {
|
||||
// Reference implementation mirrors Message.ParseContent:
|
||||
// - input can be a string, treated as an input_text item
|
||||
// - input can be an array of objects with a `type` field
|
||||
// supported types: input_text, input_image, input_file
|
||||
// supported types: input_text, output_text, input_image, input_file
|
||||
// - tool-call items contribute their name, arguments or input, and output as input_text
|
||||
func (r *OpenAIResponsesRequest) ParseInput() []MediaInput {
|
||||
if r.Input == nil {
|
||||
return nil
|
||||
@@ -1201,15 +1245,28 @@ func (r *OpenAIResponsesRequest) ParseInput() []MediaInput {
|
||||
var inputs []Input
|
||||
_ = kitutil.Unmarshal(r.Input, &inputs)
|
||||
for _, input := range inputs {
|
||||
if kitutil.GetJsonType(input.Content) == "string" {
|
||||
content := input.Content
|
||||
switch input.Type {
|
||||
case "function_call":
|
||||
content = input.Arguments
|
||||
case "custom_tool_call":
|
||||
content = input.ToolInput
|
||||
case "function_call_output", "custom_tool_call_output", "local_shell_call_output":
|
||||
content = input.Output
|
||||
}
|
||||
if input.Name != "" {
|
||||
mediaInputs = append(mediaInputs, MediaInput{Type: "input_text", Text: input.Name})
|
||||
}
|
||||
|
||||
if kitutil.GetJsonType(content) == "string" {
|
||||
var str string
|
||||
_ = kitutil.Unmarshal(input.Content, &str)
|
||||
_ = kitutil.Unmarshal(content, &str)
|
||||
mediaInputs = append(mediaInputs, MediaInput{Type: "input_text", Text: str})
|
||||
}
|
||||
|
||||
if kitutil.GetJsonType(input.Content) == "array" {
|
||||
if kitutil.GetJsonType(content) == "array" {
|
||||
var array []any
|
||||
_ = kitutil.Unmarshal(input.Content, &array)
|
||||
_ = kitutil.Unmarshal(content, &array)
|
||||
for _, itemAny := range array {
|
||||
// Already parsed MediaContent
|
||||
if media, ok := itemAny.(MediaInput); ok {
|
||||
@@ -1228,7 +1285,7 @@ func (r *OpenAIResponsesRequest) ParseInput() []MediaInput {
|
||||
continue
|
||||
}
|
||||
switch typeVal {
|
||||
case "input_text":
|
||||
case "input_text", "output_text":
|
||||
text, _ := item["text"].(string)
|
||||
mediaInputs = append(mediaInputs, MediaInput{Type: "input_text", Text: text})
|
||||
case "input_image":
|
||||
|
||||
Reference in new issue
Block a user