mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-21 05:40:51 +08:00
feat: add per-auth tool_prefix_disabled option
Allow disabling the proxy_ tool name prefix on a per-account basis. Users who route their own Anthropic account through CPA can set "tool_prefix_disabled": true in their OAuth auth JSON to send tool names unchanged to Anthropic. Default behavior is fully preserved — prefix is applied unless explicitly disabled. Changes: - Add ToolPrefixDisabled() accessor to Auth (reads metadata key "tool_prefix_disabled" or "tool-prefix-disabled") - Gate all 6 prefix apply/strip points with the new flag - Add unit tests for the accessor
This commit is contained in:
@@ -134,7 +134,7 @@ func (e *ClaudeExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, r
|
|||||||
extraBetas, body = extractAndRemoveBetas(body)
|
extraBetas, body = extractAndRemoveBetas(body)
|
||||||
bodyForTranslation := body
|
bodyForTranslation := body
|
||||||
bodyForUpstream := body
|
bodyForUpstream := body
|
||||||
if isClaudeOAuthToken(apiKey) {
|
if isClaudeOAuthToken(apiKey) && !auth.ToolPrefixDisabled() {
|
||||||
bodyForUpstream = applyClaudeToolPrefix(body, claudeToolPrefix)
|
bodyForUpstream = applyClaudeToolPrefix(body, claudeToolPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +208,7 @@ func (e *ClaudeExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, r
|
|||||||
} else {
|
} else {
|
||||||
reporter.publish(ctx, parseClaudeUsage(data))
|
reporter.publish(ctx, parseClaudeUsage(data))
|
||||||
}
|
}
|
||||||
if isClaudeOAuthToken(apiKey) {
|
if isClaudeOAuthToken(apiKey) && !auth.ToolPrefixDisabled() {
|
||||||
data = stripClaudeToolPrefixFromResponse(data, claudeToolPrefix)
|
data = stripClaudeToolPrefixFromResponse(data, claudeToolPrefix)
|
||||||
}
|
}
|
||||||
var param any
|
var param any
|
||||||
@@ -275,7 +275,7 @@ func (e *ClaudeExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A
|
|||||||
extraBetas, body = extractAndRemoveBetas(body)
|
extraBetas, body = extractAndRemoveBetas(body)
|
||||||
bodyForTranslation := body
|
bodyForTranslation := body
|
||||||
bodyForUpstream := body
|
bodyForUpstream := body
|
||||||
if isClaudeOAuthToken(apiKey) {
|
if isClaudeOAuthToken(apiKey) && !auth.ToolPrefixDisabled() {
|
||||||
bodyForUpstream = applyClaudeToolPrefix(body, claudeToolPrefix)
|
bodyForUpstream = applyClaudeToolPrefix(body, claudeToolPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +348,7 @@ func (e *ClaudeExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A
|
|||||||
if detail, ok := parseClaudeStreamUsage(line); ok {
|
if detail, ok := parseClaudeStreamUsage(line); ok {
|
||||||
reporter.publish(ctx, detail)
|
reporter.publish(ctx, detail)
|
||||||
}
|
}
|
||||||
if isClaudeOAuthToken(apiKey) {
|
if isClaudeOAuthToken(apiKey) && !auth.ToolPrefixDisabled() {
|
||||||
line = stripClaudeToolPrefixFromStreamLine(line, claudeToolPrefix)
|
line = stripClaudeToolPrefixFromStreamLine(line, claudeToolPrefix)
|
||||||
}
|
}
|
||||||
// Forward the line as-is to preserve SSE format
|
// Forward the line as-is to preserve SSE format
|
||||||
@@ -375,7 +375,7 @@ func (e *ClaudeExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A
|
|||||||
if detail, ok := parseClaudeStreamUsage(line); ok {
|
if detail, ok := parseClaudeStreamUsage(line); ok {
|
||||||
reporter.publish(ctx, detail)
|
reporter.publish(ctx, detail)
|
||||||
}
|
}
|
||||||
if isClaudeOAuthToken(apiKey) {
|
if isClaudeOAuthToken(apiKey) && !auth.ToolPrefixDisabled() {
|
||||||
line = stripClaudeToolPrefixFromStreamLine(line, claudeToolPrefix)
|
line = stripClaudeToolPrefixFromStreamLine(line, claudeToolPrefix)
|
||||||
}
|
}
|
||||||
chunks := sdktranslator.TranslateStream(
|
chunks := sdktranslator.TranslateStream(
|
||||||
@@ -423,7 +423,7 @@ func (e *ClaudeExecutor) CountTokens(ctx context.Context, auth *cliproxyauth.Aut
|
|||||||
// Extract betas from body and convert to header (for count_tokens too)
|
// Extract betas from body and convert to header (for count_tokens too)
|
||||||
var extraBetas []string
|
var extraBetas []string
|
||||||
extraBetas, body = extractAndRemoveBetas(body)
|
extraBetas, body = extractAndRemoveBetas(body)
|
||||||
if isClaudeOAuthToken(apiKey) {
|
if isClaudeOAuthToken(apiKey) && !auth.ToolPrefixDisabled() {
|
||||||
body = applyClaudeToolPrefix(body, claudeToolPrefix)
|
body = applyClaudeToolPrefix(body, claudeToolPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -213,6 +213,23 @@ func (a *Auth) DisableCoolingOverride() (bool, bool) {
|
|||||||
return false, false
|
return false, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToolPrefixDisabled returns whether the proxy_ tool name prefix should be
|
||||||
|
// skipped for this auth. When true, tool names are sent to Anthropic unchanged.
|
||||||
|
// The value is read from metadata key "tool_prefix_disabled" (or "tool-prefix-disabled").
|
||||||
|
func (a *Auth) ToolPrefixDisabled() bool {
|
||||||
|
if a == nil || a.Metadata == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, key := range []string{"tool_prefix_disabled", "tool-prefix-disabled"} {
|
||||||
|
if val, ok := a.Metadata[key]; ok {
|
||||||
|
if parsed, okParse := parseBoolAny(val); okParse {
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// RequestRetryOverride returns the auth-file scoped request_retry override when present.
|
// RequestRetryOverride returns the auth-file scoped request_retry override when present.
|
||||||
// The value is read from metadata key "request_retry" (or legacy "request-retry").
|
// The value is read from metadata key "request_retry" (or legacy "request-retry").
|
||||||
func (a *Auth) RequestRetryOverride() (int, bool) {
|
func (a *Auth) RequestRetryOverride() (int, bool) {
|
||||||
|
|||||||
35
sdk/cliproxy/auth/types_test.go
Normal file
35
sdk/cliproxy/auth/types_test.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestToolPrefixDisabled(t *testing.T) {
|
||||||
|
var a *Auth
|
||||||
|
if a.ToolPrefixDisabled() {
|
||||||
|
t.Error("nil auth should return false")
|
||||||
|
}
|
||||||
|
|
||||||
|
a = &Auth{}
|
||||||
|
if a.ToolPrefixDisabled() {
|
||||||
|
t.Error("empty auth should return false")
|
||||||
|
}
|
||||||
|
|
||||||
|
a = &Auth{Metadata: map[string]any{"tool_prefix_disabled": true}}
|
||||||
|
if !a.ToolPrefixDisabled() {
|
||||||
|
t.Error("should return true when set to true")
|
||||||
|
}
|
||||||
|
|
||||||
|
a = &Auth{Metadata: map[string]any{"tool_prefix_disabled": "true"}}
|
||||||
|
if !a.ToolPrefixDisabled() {
|
||||||
|
t.Error("should return true when set to string 'true'")
|
||||||
|
}
|
||||||
|
|
||||||
|
a = &Auth{Metadata: map[string]any{"tool-prefix-disabled": true}}
|
||||||
|
if !a.ToolPrefixDisabled() {
|
||||||
|
t.Error("should return true with kebab-case key")
|
||||||
|
}
|
||||||
|
|
||||||
|
a = &Auth{Metadata: map[string]any{"tool_prefix_disabled": false}}
|
||||||
|
if a.ToolPrefixDisabled() {
|
||||||
|
t.Error("should return false when set to false")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user