Skip to main content

tokn_provider_copilot/
lib.rs

1pub mod auth;
2pub mod github_copilot;
3pub mod headers;
4pub mod import;
5pub mod models;
6pub mod oauth;
7pub mod token;
8pub mod user;
9
10pub mod config;
11
12pub use tokn_catalogue as catalogue;
13pub use tokn_core::provider::{
14  error, AuthKind, Endpoint, EndpointRule, HeaderPatchCtx, Provider, ProviderInfo, RequestCtx, Result, TemplateVars,
15  ID_GITHUB_COPILOT,
16};
17pub use tokn_core::{provider, util};
18
19pub use github_copilot::*;
20
21use std::sync::Arc;
22use tokn_auth::descriptor::{EndpointSpec, ProviderDescriptor};
23use tokn_auth::provider::CredentialFlavor;
24
25pub const COPILOT_BASE_URL: &str = "https://api.githubcopilot.com";
26pub const COPILOT_DEVICE_CODE_URL: &str = "https://github.com/login/device/code";
27pub const COPILOT_ACCESS_TOKEN_URL: &str = "https://github.com/login/oauth/access_token";
28pub const COPILOT_TOKEN_EXCHANGE_URL: &str = "https://api.github.com/copilot_internal/v2/token";
29pub const COPILOT_USER_INFO_URL: &str = "https://api.github.com/copilot_internal/user";
30
31/// Endpoints Copilot serves; mirrored on `DESCRIPTOR.endpoints` and used
32/// to populate `ProviderInfo::default_endpoints`.
33pub static DEFAULT_ENDPOINTS: &[Endpoint] = &[Endpoint::ChatCompletions, Endpoint::Responses, Endpoint::Messages];
34
35/// Per-model endpoint rules. Mirrors what the official Copilot CLI / VSCode
36/// plugin route — Copilot ships new ids continuously and `/models` does
37/// not annotate per-endpoint support, so we pattern-match the id.
38///
39/// First match wins: an unmatched model falls back to
40/// `DEFAULT_ENDPOINTS` (every endpoint allowed) — optimistic by design.
41pub static MODEL_ENDPOINT_RULES: &[EndpointRule] = &[
42  EndpointRule {
43    pattern: "claude-*",
44    endpoints: &[Endpoint::Messages, Endpoint::ChatCompletions],
45  },
46  EndpointRule {
47    pattern: "gpt-5-mini",
48    endpoints: &[Endpoint::ChatCompletions, Endpoint::Responses],
49  },
50  EndpointRule {
51    pattern: "gpt-5*",
52    endpoints: &[Endpoint::Responses],
53  },
54  EndpointRule {
55    pattern: "o1*",
56    endpoints: &[Endpoint::Responses, Endpoint::ChatCompletions],
57  },
58  EndpointRule {
59    pattern: "o3*",
60    endpoints: &[Endpoint::Responses, Endpoint::ChatCompletions],
61  },
62  EndpointRule {
63    pattern: "o4*",
64    endpoints: &[Endpoint::Responses, Endpoint::ChatCompletions],
65  },
66];
67
68pub static DESCRIPTOR: ProviderDescriptor = ProviderDescriptor {
69  id: ID_GITHUB_COPILOT,
70  display_name: "GitHub Copilot",
71  hosts: &["api.github.com", "api.githubcopilot.com"],
72  base_url: COPILOT_BASE_URL,
73  credentials: &[CredentialFlavor::RefreshToken],
74  endpoints: &[
75    EndpointSpec {
76      endpoint: Endpoint::ChatCompletions,
77      method: "POST",
78      path: "/v1/chat/completions",
79      aliases: &[],
80    },
81    EndpointSpec {
82      endpoint: Endpoint::Messages,
83      method: "POST",
84      path: "/v1/messages",
85      aliases: &[],
86    },
87    EndpointSpec {
88      endpoint: Endpoint::Responses,
89      method: "POST",
90      path: "/v1/responses",
91      aliases: &[],
92    },
93  ],
94  model_endpoint_rules: Some(MODEL_ENDPOINT_RULES),
95  rewrites: &[],
96  auth_urls: &[
97    ("device_authorize", COPILOT_DEVICE_CODE_URL),
98    ("device_token", COPILOT_ACCESS_TOKEN_URL),
99    ("token_exchange", COPILOT_TOKEN_EXCHANGE_URL),
100    ("user_info", COPILOT_USER_INFO_URL),
101  ],
102  matches_url,
103  validate,
104  build,
105  build_auth: Some(crate::auth::provider_auth),
106};
107
108pub fn matches_url(host: &str, _path: &str, _id: &'static str) -> bool {
109  DESCRIPTOR.hosts.contains(&host)
110}
111
112pub fn validate(account: &tokn_core::account::AccountConfig) -> tokn_core::provider::Result<()> {
113  github_copilot::CopilotProvider::validate_account(account)
114}
115
116pub fn build(
117  account: Arc<tokn_core::account::AccountConfig>,
118) -> tokn_core::provider::Result<Arc<dyn tokn_core::provider::Provider>> {
119  Ok(Arc::new(github_copilot::CopilotProvider::from_account(account)?))
120}