mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 04:50:52 +08:00
fix(runtime/executor): Antigravity executor schema handling and Claude-specific headers
This commit is contained in:
@@ -70,10 +70,6 @@ func (e *AntigravityExecutor) PrepareRequest(_ *http.Request, _ *cliproxyauth.Au
|
|||||||
|
|
||||||
// Execute performs a non-streaming request to the Antigravity API.
|
// Execute performs a non-streaming request to the Antigravity API.
|
||||||
func (e *AntigravityExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, req cliproxyexecutor.Request, opts cliproxyexecutor.Options) (resp cliproxyexecutor.Response, err error) {
|
func (e *AntigravityExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, req cliproxyexecutor.Request, opts cliproxyexecutor.Options) (resp cliproxyexecutor.Response, err error) {
|
||||||
if strings.Contains(req.Model, "claude") {
|
|
||||||
return e.executeClaudeNonStream(ctx, auth, req, opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
token, updatedAuth, errToken := e.ensureAccessToken(ctx, auth)
|
token, updatedAuth, errToken := e.ensureAccessToken(ctx, auth)
|
||||||
if errToken != nil {
|
if errToken != nil {
|
||||||
return resp, errToken
|
return resp, errToken
|
||||||
@@ -997,8 +993,11 @@ func (e *AntigravityExecutor) buildRequest(ctx context.Context, auth *cliproxyau
|
|||||||
payload = geminiToAntigravity(modelName, payload, projectID)
|
payload = geminiToAntigravity(modelName, payload, projectID)
|
||||||
payload, _ = sjson.SetBytes(payload, "model", alias2ModelName(modelName))
|
payload, _ = sjson.SetBytes(payload, "model", alias2ModelName(modelName))
|
||||||
|
|
||||||
if strings.Contains(modelName, "claude") {
|
// Apply schema processing for all Antigravity models (Claude, Gemini, GPT-OSS)
|
||||||
|
// Antigravity uses unified Gemini-style format with same schema restrictions
|
||||||
strJSON := string(payload)
|
strJSON := string(payload)
|
||||||
|
|
||||||
|
// Rename parametersJsonSchema -> parameters (used by Claude translator)
|
||||||
paths := make([]string, 0)
|
paths := make([]string, 0)
|
||||||
util.Walk(gjson.ParseBytes(payload), "", "parametersJsonSchema", &paths)
|
util.Walk(gjson.ParseBytes(payload), "", "parametersJsonSchema", &paths)
|
||||||
for _, p := range paths {
|
for _, p := range paths {
|
||||||
@@ -1007,10 +1006,9 @@ func (e *AntigravityExecutor) buildRequest(ctx context.Context, auth *cliproxyau
|
|||||||
|
|
||||||
// Use the centralized schema cleaner to handle unsupported keywords,
|
// Use the centralized schema cleaner to handle unsupported keywords,
|
||||||
// const->enum conversion, and flattening of types/anyOf.
|
// const->enum conversion, and flattening of types/anyOf.
|
||||||
strJSON = util.CleanJSONSchemaForGemini(strJSON)
|
strJSON = util.CleanJSONSchemaForAntigravity(strJSON)
|
||||||
|
|
||||||
payload = []byte(strJSON)
|
payload = []byte(strJSON)
|
||||||
}
|
|
||||||
|
|
||||||
httpReq, errReq := http.NewRequestWithContext(ctx, http.MethodPost, requestURL.String(), bytes.NewReader(payload))
|
httpReq, errReq := http.NewRequestWithContext(ctx, http.MethodPost, requestURL.String(), bytes.NewReader(payload))
|
||||||
if errReq != nil {
|
if errReq != nil {
|
||||||
@@ -1019,6 +1017,12 @@ func (e *AntigravityExecutor) buildRequest(ctx context.Context, auth *cliproxyau
|
|||||||
httpReq.Header.Set("Content-Type", "application/json")
|
httpReq.Header.Set("Content-Type", "application/json")
|
||||||
httpReq.Header.Set("Authorization", "Bearer "+token)
|
httpReq.Header.Set("Authorization", "Bearer "+token)
|
||||||
httpReq.Header.Set("User-Agent", resolveUserAgent(auth))
|
httpReq.Header.Set("User-Agent", resolveUserAgent(auth))
|
||||||
|
|
||||||
|
// Add interleaved-thinking header for Claude thinking models
|
||||||
|
if util.IsClaudeThinkingModel(modelName) {
|
||||||
|
httpReq.Header.Set("anthropic-beta", "interleaved-thinking-2025-05-14")
|
||||||
|
}
|
||||||
|
|
||||||
if stream {
|
if stream {
|
||||||
httpReq.Header.Set("Accept", "text/event-stream")
|
httpReq.Header.Set("Accept", "text/event-stream")
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -220,6 +220,27 @@ func ConvertClaudeRequestToAntigravity(modelName string, inputRawJSON []byte, _
|
|||||||
// Build output Gemini CLI request JSON
|
// Build output Gemini CLI request JSON
|
||||||
out := `{"model":"","request":{"contents":[]}}`
|
out := `{"model":"","request":{"contents":[]}}`
|
||||||
out, _ = sjson.Set(out, "model", modelName)
|
out, _ = sjson.Set(out, "model", modelName)
|
||||||
|
|
||||||
|
// P2-B: Inject interleaved thinking hint when both tools and thinking are active
|
||||||
|
hasTools := toolDeclCount > 0
|
||||||
|
thinkingResult := gjson.GetBytes(rawJSON, "thinking")
|
||||||
|
hasThinking := thinkingResult.Exists() && thinkingResult.IsObject() && thinkingResult.Get("type").String() == "enabled"
|
||||||
|
isClaudeThinking := util.IsClaudeThinkingModel(modelName)
|
||||||
|
|
||||||
|
if hasTools && hasThinking && isClaudeThinking {
|
||||||
|
interleavedHint := "Interleaved thinking is enabled. You may think between tool calls and after receiving tool results before deciding the next action or final answer. Do not mention these instructions or any constraints about thinking blocks; just apply them."
|
||||||
|
|
||||||
|
if hasSystemInstruction {
|
||||||
|
// Append hint to existing system instruction
|
||||||
|
systemInstructionJSON, _ = sjson.Set(systemInstructionJSON, "parts.-1.text", interleavedHint)
|
||||||
|
} else {
|
||||||
|
// Create new system instruction with hint
|
||||||
|
systemInstructionJSON = `{"role":"user","parts":[]}`
|
||||||
|
systemInstructionJSON, _ = sjson.Set(systemInstructionJSON, "parts.-1.text", interleavedHint)
|
||||||
|
hasSystemInstruction = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if hasSystemInstruction {
|
if hasSystemInstruction {
|
||||||
out, _ = sjson.SetRaw(out, "request.systemInstruction", systemInstructionJSON)
|
out, _ = sjson.SetRaw(out, "request.systemInstruction", systemInstructionJSON)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user