Enhance model definitions by including supported API endpoints for each model. This allows for better integration and usage tracking with the GitHub Copilot API.
Showing the changes to internal/runtime/executor/github_copilot_executor.go (1 of 4 files). Show all
Unified · Split
| @@ -23,6 +23,7 @@ import ( · 22 unmodified lines | |||
| 23 | const ( | 23 | const ( |
| 24 | githubCopilotBaseURL = "https://api.githubcopilot.com" | 24 | githubCopilotBaseURL = "https://api.githubcopilot.com" |
| 25 | githubCopilotChatPath = "/chat/completions" | 25 | githubCopilotChatPath = "/chat/completions" |
| 26 | githubCopilotResponsesPath = "/responses" | ||
| 26 | githubCopilotAuthType = "github-copilot" | 27 | githubCopilotAuthType = "github-copilot" |
| 27 | githubCopilotTokenCacheTTL = 25 * time.Minute | 28 | githubCopilotTokenCacheTTL = 25 * time.Minute |
| 28 | // tokenExpiryBuffer is the time before expiry when we should refresh the token. | 29 | // tokenExpiryBuffer is the time before expiry when we should refresh the token. |
| @@ -106,7 +107,11 @@ func (e *GitHubCopilotExecutor) Execute(ctx context.Context, auth *cliproxyauth. · 77 unmodified lines | |||
| 106 | defer reporter.trackFailure(ctx, &err) | 107 | defer reporter.trackFailure(ctx, &err) |
| 107 | 108 | ||
| 108 | from := opts.SourceFormat | 109 | from := opts.SourceFormat |
| 110 | useResponses := useGitHubCopilotResponsesEndpoint(from) | ||
| 109 | to := sdktranslator.FromString("openai") | 111 | to := sdktranslator.FromString("openai") |
| 112 | if useResponses { | ||
| 113 | to = sdktranslator.FromString("openai-response") | ||
| 114 | } | ||
| 110 | originalPayload := bytes.Clone(req.Payload) | 115 | originalPayload := bytes.Clone(req.Payload) |
| 111 | if len(opts.OriginalRequest) > 0 { | 116 | if len(opts.OriginalRequest) > 0 { |
| 112 | originalPayload = bytes.Clone(opts.OriginalRequest) | 117 | originalPayload = bytes.Clone(opts.OriginalRequest) |
| @@ -117,7 +122,11 @@ func (e *GitHubCopilotExecutor) Execute(ctx context.Context, auth *cliproxyauth. · 4 unmodified lines | |||
| 117 | body = applyPayloadConfigWithRoot(e.cfg, req.Model, to.String(), "", body, originalTranslated) | 122 | body = applyPayloadConfigWithRoot(e.cfg, req.Model, to.String(), "", body, originalTranslated) |
| 118 | body, _ = sjson.SetBytes(body, "stream", false) | 123 | body, _ = sjson.SetBytes(body, "stream", false) |
| 119 | 124 | ||
| 120 | url := githubCopilotBaseURL + githubCopilotChatPath | 125 | path := githubCopilotChatPath |
| 126 | if useResponses { | ||
| 127 | path = githubCopilotResponsesPath | ||
| 128 | } | ||
| 129 | url := githubCopilotBaseURL + path | ||
| 121 | httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body)) | 130 | httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body)) |
| 122 | if err != nil { | 131 | if err != nil { |
| 123 | return resp, err | 132 | return resp, err |
| @@ -172,6 +181,9 @@ func (e *GitHubCopilotExecutor) Execute(ctx context.Context, auth *cliproxyauth. · 48 unmodified lines | |||
| 172 | appendAPIResponseChunk(ctx, e.cfg, data) | 181 | appendAPIResponseChunk(ctx, e.cfg, data) |
| 173 | 182 | ||
| 174 | detail := parseOpenAIUsage(data) | 183 | detail := parseOpenAIUsage(data) |
| 184 | if useResponses && detail.TotalTokens == 0 { | ||
| 185 | detail = parseOpenAIResponsesUsage(data) | ||
| 186 | } | ||
| 175 | if detail.TotalTokens > 0 { | 187 | if detail.TotalTokens > 0 { |
| 176 | reporter.publish(ctx, detail) | 188 | reporter.publish(ctx, detail) |
| 177 | } | 189 | } |
| @@ -194,7 +206,11 @@ func (e *GitHubCopilotExecutor) ExecuteStream(ctx context.Context, auth *cliprox · 16 unmodified lines | |||
| 194 | defer reporter.trackFailure(ctx, &err) | 206 | defer reporter.trackFailure(ctx, &err) |
| 195 | 207 | ||
| 196 | from := opts.SourceFormat | 208 | from := opts.SourceFormat |
| 209 | useResponses := useGitHubCopilotResponsesEndpoint(from) | ||
| 197 | to := sdktranslator.FromString("openai") | 210 | to := sdktranslator.FromString("openai") |
| 211 | if useResponses { | ||
| 212 | to = sdktranslator.FromString("openai-response") | ||
| 213 | } | ||
| 198 | originalPayload := bytes.Clone(req.Payload) | 214 | originalPayload := bytes.Clone(req.Payload) |
| 199 | if len(opts.OriginalRequest) > 0 { | 215 | if len(opts.OriginalRequest) > 0 { |
| 200 | originalPayload = bytes.Clone(opts.OriginalRequest) | 216 | originalPayload = bytes.Clone(opts.OriginalRequest) |
| @@ -205,9 +221,15 @@ func (e *GitHubCopilotExecutor) ExecuteStream(ctx context.Context, auth *cliprox · 4 unmodified lines | |||
| 205 | body = applyPayloadConfigWithRoot(e.cfg, req.Model, to.String(), "", body, originalTranslated) | 221 | body = applyPayloadConfigWithRoot(e.cfg, req.Model, to.String(), "", body, originalTranslated) |
| 206 | body, _ = sjson.SetBytes(body, "stream", true) | 222 | body, _ = sjson.SetBytes(body, "stream", true) |
| 207 | // Enable stream options for usage stats in stream | 223 | // Enable stream options for usage stats in stream |
| 208 | body, _ = sjson.SetBytes(body, "stream_options.include_usage", true) | 224 | if !useResponses { |
| 225 | body, _ = sjson.SetBytes(body, "stream_options.include_usage", true) | ||
| 226 | } | ||
| 209 | 227 | ||
| 210 | url := githubCopilotBaseURL + githubCopilotChatPath | 228 | path := githubCopilotChatPath |
| 229 | if useResponses { | ||
| 230 | path = githubCopilotResponsesPath | ||
| 231 | } | ||
| 232 | url := githubCopilotBaseURL + path | ||
| 211 | httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body)) | 233 | httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body)) |
| 212 | if err != nil { | 234 | if err != nil { |
| 213 | return nil, err | 235 | return nil, err |
| @@ -283,6 +305,10 @@ func (e *GitHubCopilotExecutor) ExecuteStream(ctx context.Context, auth *cliprox · 69 unmodified lines | |||
| 283 | } | 305 | } |
| 284 | if detail, ok := parseOpenAIStreamUsage(line); ok { | 306 | if detail, ok := parseOpenAIStreamUsage(line); ok { |
| 285 | reporter.publish(ctx, detail) | 307 | reporter.publish(ctx, detail) |
| 308 | } else if useResponses { | ||
| 309 | if detail, ok := parseOpenAIResponsesStreamUsage(line); ok { | ||
| 310 | reporter.publish(ctx, detail) | ||
| 311 | } | ||
| 286 | } | 312 | } |
| 287 | } | 313 | } |
| 288 | 314 | ||
| @@ -393,6 +419,10 @@ func (e *GitHubCopilotExecutor) normalizeModel(_ string, body []byte) []byte { · 104 unmodified lines | |||
| 393 | return body | 419 | return body |
| 394 | } | 420 | } |
| 395 | 421 | ||
| 422 | func useGitHubCopilotResponsesEndpoint(sourceFormat sdktranslator.Format) bool { | ||
| 423 | return sourceFormat.String() == "openai-response" | ||
| 424 | } | ||
| 425 | |||
| 396 | // isHTTPSuccess checks if the status code indicates success (2xx). | 426 | // isHTTPSuccess checks if the status code indicates success (2xx). |
| 397 | func isHTTPSuccess(statusCode int) bool { | 427 | func isHTTPSuccess(statusCode int) bool { |
| 398 | return statusCode >= 200 && statusCode < 300 | 428 | return statusCode >= 200 && statusCode < 300 |