mirror of
https://github.com/router-for-me/CLIProxyAPIPlus.git
synced 2026-05-13 23:41:36 +00:00
feat(cursor): implement StatusError for conductor cooldown integration
Cursor executor errors were plain fmt.Errorf — the conductor couldn't
extract HTTP status codes, so exhausted accounts never entered cooldown.
Changes:
- Add ConnectError struct to proto/connect.go: ParseConnectEndStream now
returns *ConnectError with Code/Message fields for precise matching
- Add cursorStatusErr implementing StatusError + RetryAfter interfaces
- Add classifyCursorError() with two-layer classification:
Layer 1: exact match on ConnectError.Code (gRPC standard codes)
resource_exhausted → 429, unauthenticated → 401,
permission_denied → 403, unavailable → 503, internal → 500
Layer 2: fuzzy string match for H2 errors (RST_STREAM → 502)
- Log all ConnectError code/message pairs for observing real server
error codes (we have no samples yet)
- Wrap Execute and ExecuteStream error returns with classifyCursorError
Now the conductor properly marks Cursor auths as cooldown on quota errors,
enabling exponential backoff and round-robin failover.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -41,8 +41,21 @@ func ParseConnectFrame(buf []byte) (flags byte, payload []byte, consumed int, ok
|
||||
return flags, buf[5:total], total, true
|
||||
}
|
||||
|
||||
// ConnectError is a structured error from the Connect protocol end-of-stream trailer.
|
||||
// The Code field contains the server-defined error code (e.g. gRPC standard codes
|
||||
// like "resource_exhausted", "unauthenticated", "permission_denied", "unavailable").
|
||||
type ConnectError struct {
|
||||
Code string // server-defined error code
|
||||
Message string // human-readable error description
|
||||
}
|
||||
|
||||
func (e *ConnectError) Error() string {
|
||||
return fmt.Sprintf("Connect error %s: %s", e.Code, e.Message)
|
||||
}
|
||||
|
||||
// ParseConnectEndStream parses a Connect end-of-stream frame payload (JSON).
|
||||
// Returns nil if there is no error in the trailer.
|
||||
// On error, returns a *ConnectError with the server's error code and message.
|
||||
func ParseConnectEndStream(data []byte) error {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
@@ -65,7 +78,7 @@ func ParseConnectEndStream(data []byte) error {
|
||||
if msg == "" {
|
||||
msg = "Unknown error"
|
||||
}
|
||||
return fmt.Errorf("Connect error %s: %s", code, msg)
|
||||
return &ConnectError{Code: code, Message: msg}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user