ghc-proxy 0.5.4 → 0.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/dist/main.mjs +279 -122
- package/dist/main.mjs.map +1 -1
- package/package.json +1 -1
package/dist/main.mjs
CHANGED
|
@@ -5389,7 +5389,8 @@ const configFileSchema = object({
|
|
|
5389
5389
|
to: string()
|
|
5390
5390
|
})).optional(),
|
|
5391
5391
|
contextUpgrade: boolean().optional(),
|
|
5392
|
-
contextUpgradeTokenThreshold: number().int().positive().optional()
|
|
5392
|
+
contextUpgradeTokenThreshold: number().int().positive().optional(),
|
|
5393
|
+
gheDomain: string().optional()
|
|
5393
5394
|
}).passthrough();
|
|
5394
5395
|
const KNOWN_CONFIG_KEYS = new Set(Object.keys(configFileSchema.shape));
|
|
5395
5396
|
let cachedConfig = {};
|
|
@@ -5499,6 +5500,105 @@ async function applyConfigFilePermissions(filePath) {
|
|
|
5499
5500
|
}
|
|
5500
5501
|
}
|
|
5501
5502
|
|
|
5503
|
+
//#endregion
|
|
5504
|
+
//#region src/lib/api-config.ts
|
|
5505
|
+
function standardHeaders() {
|
|
5506
|
+
return {
|
|
5507
|
+
"content-type": "application/json",
|
|
5508
|
+
"accept": "application/json"
|
|
5509
|
+
};
|
|
5510
|
+
}
|
|
5511
|
+
const COPILOT_VERSION = "0.26.7";
|
|
5512
|
+
const EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`;
|
|
5513
|
+
const USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`;
|
|
5514
|
+
const API_VERSION = "2025-04-01";
|
|
5515
|
+
const TRAILING_SLASHES_RE$1 = /\/+$/;
|
|
5516
|
+
/** Headers shared by both Copilot and GitHub API requests (editor identity + versioning) */
|
|
5517
|
+
function editorHeaders(config) {
|
|
5518
|
+
return {
|
|
5519
|
+
"editor-version": `vscode/${config.vsCodeVersion ?? "unknown"}`,
|
|
5520
|
+
"editor-plugin-version": EDITOR_PLUGIN_VERSION,
|
|
5521
|
+
"user-agent": USER_AGENT,
|
|
5522
|
+
"x-github-api-version": API_VERSION,
|
|
5523
|
+
"x-vscode-user-agent-library-version": "electron-fetch"
|
|
5524
|
+
};
|
|
5525
|
+
}
|
|
5526
|
+
function copilotBaseUrl(config) {
|
|
5527
|
+
if (config.copilotApiBase) return config.copilotApiBase.replace(TRAILING_SLASHES_RE$1, "");
|
|
5528
|
+
return config.accountType === "individual" ? "https://api.githubcopilot.com" : `https://api.${config.accountType}.githubcopilot.com`;
|
|
5529
|
+
}
|
|
5530
|
+
function copilotHeaders(auth, config, options = {}) {
|
|
5531
|
+
const requestContext = options.requestContext;
|
|
5532
|
+
const headers = {
|
|
5533
|
+
"Authorization": `Bearer ${auth.copilotToken}`,
|
|
5534
|
+
"content-type": standardHeaders()["content-type"],
|
|
5535
|
+
"copilot-integration-id": "vscode-chat",
|
|
5536
|
+
...editorHeaders(config),
|
|
5537
|
+
"openai-intent": "conversation-panel",
|
|
5538
|
+
"x-request-id": randomUUID()
|
|
5539
|
+
};
|
|
5540
|
+
if (options.vision) headers["copilot-vision-request"] = "true";
|
|
5541
|
+
if (options.initiator) headers["X-Initiator"] = options.initiator;
|
|
5542
|
+
if (requestContext?.interactionType) headers["X-Interaction-Type"] = requestContext.interactionType;
|
|
5543
|
+
if (requestContext?.agentTaskId) headers["X-Agent-Task-Id"] = requestContext.agentTaskId;
|
|
5544
|
+
if (requestContext?.parentAgentTaskId) headers["X-Parent-Agent-Id"] = requestContext.parentAgentTaskId;
|
|
5545
|
+
if (requestContext?.clientSessionId) headers["X-Client-Session-Id"] = requestContext.clientSessionId;
|
|
5546
|
+
if (requestContext?.interactionId) headers["X-Interaction-Id"] = requestContext.interactionId;
|
|
5547
|
+
if (requestContext?.clientMachineId) headers["X-Client-Machine-Id"] = requestContext.clientMachineId;
|
|
5548
|
+
return headers;
|
|
5549
|
+
}
|
|
5550
|
+
const GITHUB_API_BASE_URL = "https://api.github.com";
|
|
5551
|
+
function githubHeaders(auth, config) {
|
|
5552
|
+
return {
|
|
5553
|
+
...standardHeaders(),
|
|
5554
|
+
authorization: `token ${auth.githubToken}`,
|
|
5555
|
+
...editorHeaders(config)
|
|
5556
|
+
};
|
|
5557
|
+
}
|
|
5558
|
+
const GITHUB_BASE_URL = "https://github.com";
|
|
5559
|
+
const GITHUB_CLIENT_ID = "Iv1.b507a08c87ecfe98";
|
|
5560
|
+
const GITHUB_APP_SCOPES = ["read:user"].join(" ");
|
|
5561
|
+
|
|
5562
|
+
//#endregion
|
|
5563
|
+
//#region src/lib/ghe-domain.ts
|
|
5564
|
+
const GHE_SUFFIX = ".ghe.com";
|
|
5565
|
+
/**
|
|
5566
|
+
* Normalize a GHE domain input to a lowercase bare domain.
|
|
5567
|
+
*
|
|
5568
|
+
* Accepted inputs: `company.ghe.com`, `https://company.ghe.com`,
|
|
5569
|
+
* `https://Company.GHE.com/`, etc.
|
|
5570
|
+
*
|
|
5571
|
+
* @returns Bare lowercase domain, e.g. `company.ghe.com`
|
|
5572
|
+
* @throws {Error} If the input is empty or does not end with `.ghe.com`
|
|
5573
|
+
*/
|
|
5574
|
+
function normalizeGheDomain(input) {
|
|
5575
|
+
const trimmed = input.trim();
|
|
5576
|
+
if (!trimmed) throw new Error("GHE domain must not be empty");
|
|
5577
|
+
let domain;
|
|
5578
|
+
try {
|
|
5579
|
+
domain = (trimmed.includes("://") ? new URL(trimmed) : new URL(`https://${trimmed}`)).hostname.toLowerCase();
|
|
5580
|
+
} catch {
|
|
5581
|
+
throw new Error(`Invalid GHE domain: ${trimmed}`);
|
|
5582
|
+
}
|
|
5583
|
+
if (!domain.endsWith(GHE_SUFFIX) || domain === GHE_SUFFIX.slice(1)) throw new Error(`GHE domain must end with ${GHE_SUFFIX} (got "${domain}")`);
|
|
5584
|
+
return domain;
|
|
5585
|
+
}
|
|
5586
|
+
/**
|
|
5587
|
+
* Build GitHub base URL and API base URL for a given GHE domain,
|
|
5588
|
+
* or return the public GitHub defaults when no domain is provided.
|
|
5589
|
+
*/
|
|
5590
|
+
function buildGitHubUrls(gheDomain) {
|
|
5591
|
+
if (!gheDomain) return {
|
|
5592
|
+
baseUrl: GITHUB_BASE_URL,
|
|
5593
|
+
apiBaseUrl: GITHUB_API_BASE_URL
|
|
5594
|
+
};
|
|
5595
|
+
const domain = normalizeGheDomain(gheDomain);
|
|
5596
|
+
return {
|
|
5597
|
+
baseUrl: `https://${domain}`,
|
|
5598
|
+
apiBaseUrl: `https://api.${domain}`
|
|
5599
|
+
};
|
|
5600
|
+
}
|
|
5601
|
+
|
|
5502
5602
|
//#endregion
|
|
5503
5603
|
//#region node_modules/fetch-event-stream/esm/deps/jsr.io/@std/streams/0.221.0/text_line_stream.js
|
|
5504
5604
|
/**
|
|
@@ -5624,65 +5724,6 @@ async function* events(res, signal) {
|
|
|
5624
5724
|
}
|
|
5625
5725
|
}
|
|
5626
5726
|
|
|
5627
|
-
//#endregion
|
|
5628
|
-
//#region src/lib/api-config.ts
|
|
5629
|
-
function standardHeaders() {
|
|
5630
|
-
return {
|
|
5631
|
-
"content-type": "application/json",
|
|
5632
|
-
"accept": "application/json"
|
|
5633
|
-
};
|
|
5634
|
-
}
|
|
5635
|
-
const COPILOT_VERSION = "0.26.7";
|
|
5636
|
-
const EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`;
|
|
5637
|
-
const USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`;
|
|
5638
|
-
const API_VERSION = "2025-04-01";
|
|
5639
|
-
const TRAILING_SLASHES_RE$1 = /\/+$/;
|
|
5640
|
-
/** Headers shared by both Copilot and GitHub API requests (editor identity + versioning) */
|
|
5641
|
-
function editorHeaders(config) {
|
|
5642
|
-
return {
|
|
5643
|
-
"editor-version": `vscode/${config.vsCodeVersion ?? "unknown"}`,
|
|
5644
|
-
"editor-plugin-version": EDITOR_PLUGIN_VERSION,
|
|
5645
|
-
"user-agent": USER_AGENT,
|
|
5646
|
-
"x-github-api-version": API_VERSION,
|
|
5647
|
-
"x-vscode-user-agent-library-version": "electron-fetch"
|
|
5648
|
-
};
|
|
5649
|
-
}
|
|
5650
|
-
function copilotBaseUrl(config) {
|
|
5651
|
-
if (config.copilotApiBase) return config.copilotApiBase.replace(TRAILING_SLASHES_RE$1, "");
|
|
5652
|
-
return config.accountType === "individual" ? "https://api.githubcopilot.com" : `https://api.${config.accountType}.githubcopilot.com`;
|
|
5653
|
-
}
|
|
5654
|
-
function copilotHeaders(auth, config, options = {}) {
|
|
5655
|
-
const requestContext = options.requestContext;
|
|
5656
|
-
const headers = {
|
|
5657
|
-
"Authorization": `Bearer ${auth.copilotToken}`,
|
|
5658
|
-
"content-type": standardHeaders()["content-type"],
|
|
5659
|
-
"copilot-integration-id": "vscode-chat",
|
|
5660
|
-
...editorHeaders(config),
|
|
5661
|
-
"openai-intent": "conversation-panel",
|
|
5662
|
-
"x-request-id": randomUUID()
|
|
5663
|
-
};
|
|
5664
|
-
if (options.vision) headers["copilot-vision-request"] = "true";
|
|
5665
|
-
if (options.initiator) headers["X-Initiator"] = options.initiator;
|
|
5666
|
-
if (requestContext?.interactionType) headers["X-Interaction-Type"] = requestContext.interactionType;
|
|
5667
|
-
if (requestContext?.agentTaskId) headers["X-Agent-Task-Id"] = requestContext.agentTaskId;
|
|
5668
|
-
if (requestContext?.parentAgentTaskId) headers["X-Parent-Agent-Id"] = requestContext.parentAgentTaskId;
|
|
5669
|
-
if (requestContext?.clientSessionId) headers["X-Client-Session-Id"] = requestContext.clientSessionId;
|
|
5670
|
-
if (requestContext?.interactionId) headers["X-Interaction-Id"] = requestContext.interactionId;
|
|
5671
|
-
if (requestContext?.clientMachineId) headers["X-Client-Machine-Id"] = requestContext.clientMachineId;
|
|
5672
|
-
return headers;
|
|
5673
|
-
}
|
|
5674
|
-
const GITHUB_API_BASE_URL = "https://api.github.com";
|
|
5675
|
-
function githubHeaders(auth, config) {
|
|
5676
|
-
return {
|
|
5677
|
-
...standardHeaders(),
|
|
5678
|
-
authorization: `token ${auth.githubToken}`,
|
|
5679
|
-
...editorHeaders(config)
|
|
5680
|
-
};
|
|
5681
|
-
}
|
|
5682
|
-
const GITHUB_BASE_URL = "https://github.com";
|
|
5683
|
-
const GITHUB_CLIENT_ID = "Iv1.b507a08c87ecfe98";
|
|
5684
|
-
const GITHUB_APP_SCOPES = ["read:user"].join(" ");
|
|
5685
|
-
|
|
5686
5727
|
//#endregion
|
|
5687
5728
|
//#region src/lib/error.ts
|
|
5688
5729
|
/**
|
|
@@ -5915,13 +5956,13 @@ var GitHubClient = class {
|
|
|
5915
5956
|
return await response.json();
|
|
5916
5957
|
}
|
|
5917
5958
|
async getCopilotUsage() {
|
|
5918
|
-
return this.requestJson(`${GITHUB_API_BASE_URL}/copilot_internal/user`, { headers: githubHeaders(this.auth, this.config) }, "Failed to get Copilot usage");
|
|
5959
|
+
return this.requestJson(`${this.config.githubApiBaseUrl ?? GITHUB_API_BASE_URL}/copilot_internal/user`, { headers: githubHeaders(this.auth, this.config) }, "Failed to get Copilot usage");
|
|
5919
5960
|
}
|
|
5920
5961
|
async getCopilotToken() {
|
|
5921
|
-
return this.requestJson(`${GITHUB_API_BASE_URL}/copilot_internal/v2/token`, { headers: githubHeaders(this.auth, this.config) }, "Failed to get Copilot token");
|
|
5962
|
+
return this.requestJson(`${this.config.githubApiBaseUrl ?? GITHUB_API_BASE_URL}/copilot_internal/v2/token`, { headers: githubHeaders(this.auth, this.config) }, "Failed to get Copilot token");
|
|
5922
5963
|
}
|
|
5923
5964
|
async getDeviceCode() {
|
|
5924
|
-
return this.requestJson(`${GITHUB_BASE_URL}/login/device/code`, {
|
|
5965
|
+
return this.requestJson(`${this.config.githubBaseUrl ?? GITHUB_BASE_URL}/login/device/code`, {
|
|
5925
5966
|
method: "POST",
|
|
5926
5967
|
headers: standardHeaders(),
|
|
5927
5968
|
body: JSON.stringify({
|
|
@@ -5935,7 +5976,7 @@ var GitHubClient = class {
|
|
|
5935
5976
|
const sleepDuration = (deviceCode.interval + 1) * 1e3;
|
|
5936
5977
|
consola.debug(`Polling access token with interval of ${sleepDuration}ms`);
|
|
5937
5978
|
for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {
|
|
5938
|
-
const response = await this.fetchImpl(`${GITHUB_BASE_URL}/login/oauth/access_token`, {
|
|
5979
|
+
const response = await this.fetchImpl(`${this.config.githubBaseUrl ?? GITHUB_BASE_URL}/login/oauth/access_token`, {
|
|
5939
5980
|
method: "POST",
|
|
5940
5981
|
headers: standardHeaders(),
|
|
5941
5982
|
body: JSON.stringify({
|
|
@@ -5957,7 +5998,7 @@ var GitHubClient = class {
|
|
|
5957
5998
|
throw new Error("Device code authorization timed out");
|
|
5958
5999
|
}
|
|
5959
6000
|
async getGitHubUser() {
|
|
5960
|
-
return this.requestJson(`${GITHUB_API_BASE_URL}/user`, { headers: {
|
|
6001
|
+
return this.requestJson(`${this.config.githubApiBaseUrl ?? GITHUB_API_BASE_URL}/user`, { headers: {
|
|
5961
6002
|
authorization: `token ${this.auth.githubToken}`,
|
|
5962
6003
|
...standardHeaders()
|
|
5963
6004
|
} }, "Failed to get GitHub user");
|
|
@@ -6277,10 +6318,13 @@ const state = {
|
|
|
6277
6318
|
responsesEmulator: responsesEmulatorState
|
|
6278
6319
|
};
|
|
6279
6320
|
function getClientConfig() {
|
|
6321
|
+
const { baseUrl, apiBaseUrl } = buildGitHubUrls(state.auth.gheDomain);
|
|
6280
6322
|
return {
|
|
6281
6323
|
accountType: state.config.accountType,
|
|
6282
6324
|
vsCodeVersion: state.cache.vsCodeVersion,
|
|
6283
|
-
copilotApiBase: state.auth.copilotApiBase
|
|
6325
|
+
copilotApiBase: state.auth.copilotApiBase,
|
|
6326
|
+
githubBaseUrl: baseUrl,
|
|
6327
|
+
githubApiBaseUrl: apiBaseUrl
|
|
6284
6328
|
};
|
|
6285
6329
|
}
|
|
6286
6330
|
function createCopilotClient() {
|
|
@@ -6296,6 +6340,33 @@ async function cacheVSCodeVersion() {
|
|
|
6296
6340
|
consola.debug(`Using VSCode version: ${response}`);
|
|
6297
6341
|
}
|
|
6298
6342
|
|
|
6343
|
+
//#endregion
|
|
6344
|
+
//#region src/lib/retry.ts
|
|
6345
|
+
/**
|
|
6346
|
+
* Retry an async operation with exponential backoff.
|
|
6347
|
+
* Delay schedule: baseDelayMs * 2^attempt (0-indexed), e.g. 5s, 10s, 20s, 40s.
|
|
6348
|
+
*/
|
|
6349
|
+
async function retryWithBackoff(fn, options) {
|
|
6350
|
+
const maxRetries = options?.maxRetries ?? 4;
|
|
6351
|
+
const baseDelayMs = options?.baseDelayMs ?? 5e3;
|
|
6352
|
+
const shouldRetry = options?.shouldRetry ?? (() => true);
|
|
6353
|
+
const onRetry = options?.onRetry;
|
|
6354
|
+
let lastError;
|
|
6355
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) try {
|
|
6356
|
+
return await fn();
|
|
6357
|
+
} catch (error) {
|
|
6358
|
+
lastError = error;
|
|
6359
|
+
if (!shouldRetry(error) || attempt >= maxRetries) throw error;
|
|
6360
|
+
const delay = baseDelayMs * 2 ** attempt;
|
|
6361
|
+
onRetry?.(error, attempt, delay);
|
|
6362
|
+
await sleep(delay);
|
|
6363
|
+
}
|
|
6364
|
+
throw lastError;
|
|
6365
|
+
}
|
|
6366
|
+
function formatErrorMessage(error) {
|
|
6367
|
+
return error instanceof Error ? error.message : String(error);
|
|
6368
|
+
}
|
|
6369
|
+
|
|
6299
6370
|
//#endregion
|
|
6300
6371
|
//#region src/lib/token.ts
|
|
6301
6372
|
const TRAILING_SLASHES_RE = /\/+$/;
|
|
@@ -6310,25 +6381,38 @@ async function setupCopilotToken() {
|
|
|
6310
6381
|
consola.debug("GitHub Copilot Token fetched successfully!");
|
|
6311
6382
|
if (state.config.showToken) consola.info("Copilot token:", response.token);
|
|
6312
6383
|
const refreshInterval = (response.refresh_in - 60) * 1e3;
|
|
6313
|
-
const
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
applyCopilotTokenState(refreshed);
|
|
6318
|
-
consola.debug("Copilot token refreshed");
|
|
6319
|
-
if (state.config.showToken) consola.info("Refreshed Copilot token:", refreshed.token);
|
|
6320
|
-
} catch (error) {
|
|
6321
|
-
consola.error("Failed to refresh Copilot token:", error);
|
|
6322
|
-
}
|
|
6384
|
+
const scheduleRefresh = () => {
|
|
6385
|
+
setTimeout(() => {
|
|
6386
|
+
refreshCopilotToken(githubClient).then(scheduleRefresh);
|
|
6387
|
+
}, refreshInterval);
|
|
6323
6388
|
};
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6389
|
+
scheduleRefresh();
|
|
6390
|
+
}
|
|
6391
|
+
async function refreshCopilotToken(githubClient) {
|
|
6392
|
+
consola.debug("Refreshing Copilot token");
|
|
6393
|
+
try {
|
|
6394
|
+
const refreshed = await retryWithBackoff(() => githubClient.getCopilotToken(), {
|
|
6395
|
+
shouldRetry: (error) => !(error instanceof HTTPError) || isTransientHttpError(error),
|
|
6396
|
+
onRetry: (error, attempt, delayMs) => {
|
|
6397
|
+
consola.warn(`Token refresh failed (attempt ${attempt + 1}), retrying in ${delayMs / 1e3}s:`, formatErrorMessage(error));
|
|
6398
|
+
}
|
|
6399
|
+
});
|
|
6400
|
+
applyCopilotTokenState(refreshed);
|
|
6401
|
+
consola.debug("Copilot token refreshed");
|
|
6402
|
+
if (state.config.showToken) consola.info("Refreshed Copilot token:", refreshed.token);
|
|
6403
|
+
} catch (error) {
|
|
6404
|
+
consola.error("Failed to refresh Copilot token:", error);
|
|
6405
|
+
}
|
|
6327
6406
|
}
|
|
6328
6407
|
async function setupGitHubToken(options) {
|
|
6329
6408
|
try {
|
|
6330
6409
|
await ensureVSCodeVersion();
|
|
6331
6410
|
const githubToken = getCachedConfig().githubToken?.trim() || "";
|
|
6411
|
+
if (githubToken && !options?.force && isDomainChanged()) {
|
|
6412
|
+
consola.warn("GHE domain changed — cached token is for a different GitHub instance. Re-authenticating...");
|
|
6413
|
+
await setupGitHubToken({ force: true });
|
|
6414
|
+
return;
|
|
6415
|
+
}
|
|
6332
6416
|
if (githubToken && !options?.force) {
|
|
6333
6417
|
state.auth.githubToken = githubToken;
|
|
6334
6418
|
if (state.config.showToken) consola.info("GitHub token:", githubToken);
|
|
@@ -6352,6 +6436,7 @@ async function setupGitHubToken(options) {
|
|
|
6352
6436
|
const token = await githubClient.pollAccessToken(response);
|
|
6353
6437
|
await writeGithubToken(token);
|
|
6354
6438
|
state.auth.githubToken = token;
|
|
6439
|
+
await writeConfigField("gheDomain", state.auth.gheDomain);
|
|
6355
6440
|
if (state.config.showToken) consola.info("GitHub token:", token);
|
|
6356
6441
|
await logUser();
|
|
6357
6442
|
} catch (error) {
|
|
@@ -6366,6 +6451,17 @@ async function setupGitHubToken(options) {
|
|
|
6366
6451
|
function isAuthError(error) {
|
|
6367
6452
|
return error instanceof HTTPError && (error.status === 401 || error.status === 403);
|
|
6368
6453
|
}
|
|
6454
|
+
const TRANSIENT_HTTP_STATUSES = new Set([
|
|
6455
|
+
408,
|
|
6456
|
+
429,
|
|
6457
|
+
500,
|
|
6458
|
+
502,
|
|
6459
|
+
503,
|
|
6460
|
+
504
|
|
6461
|
+
]);
|
|
6462
|
+
function isTransientHttpError(error) {
|
|
6463
|
+
return TRANSIENT_HTTP_STATUSES.has(error.status);
|
|
6464
|
+
}
|
|
6369
6465
|
async function logUser() {
|
|
6370
6466
|
const user = await createGitHubClient().getGitHubUser();
|
|
6371
6467
|
state.cache.githubLogin = user.login;
|
|
@@ -6382,6 +6478,13 @@ function normalizeCopilotApiBase(value) {
|
|
|
6382
6478
|
if (!value) return;
|
|
6383
6479
|
return value.replace(TRAILING_SLASHES_RE, "");
|
|
6384
6480
|
}
|
|
6481
|
+
/**
|
|
6482
|
+
* Detects whether the runtime GHE domain differs from the previously persisted one.
|
|
6483
|
+
* Both `undefined` means "public github.com" → no change → returns false.
|
|
6484
|
+
*/
|
|
6485
|
+
function isDomainChanged() {
|
|
6486
|
+
return state.auth.gheDomain !== getCachedConfig().gheDomain;
|
|
6487
|
+
}
|
|
6385
6488
|
async function ensureVSCodeVersion() {
|
|
6386
6489
|
if (!state.cache.vsCodeVersion) await cacheVSCodeVersion();
|
|
6387
6490
|
}
|
|
@@ -6396,6 +6499,9 @@ async function runAuth(options) {
|
|
|
6396
6499
|
state.config.showToken = options.showToken;
|
|
6397
6500
|
await ensurePaths();
|
|
6398
6501
|
await readConfig();
|
|
6502
|
+
state.auth.gheDomain = getCachedConfig().gheDomain;
|
|
6503
|
+
if (options.gheDomain !== void 0) state.auth.gheDomain = options.gheDomain ? normalizeGheDomain(options.gheDomain) : void 0;
|
|
6504
|
+
if (state.auth.gheDomain && state.config.accountType === "individual") state.config.accountType = "enterprise";
|
|
6399
6505
|
await cacheVSCodeVersion();
|
|
6400
6506
|
await setupGitHubToken({ force: true });
|
|
6401
6507
|
consola.success("GitHub token written to config.json");
|
|
@@ -6416,12 +6522,18 @@ const auth = defineCommand({
|
|
|
6416
6522
|
type: "boolean",
|
|
6417
6523
|
default: false,
|
|
6418
6524
|
description: "Show GitHub token on auth"
|
|
6525
|
+
},
|
|
6526
|
+
"ghe-domain": {
|
|
6527
|
+
alias: "ghe",
|
|
6528
|
+
type: "string",
|
|
6529
|
+
description: "Company GHE domain for GitHub Enterprise Cloud (e.g. company.ghe.com)"
|
|
6419
6530
|
}
|
|
6420
6531
|
},
|
|
6421
6532
|
run({ args }) {
|
|
6422
6533
|
return runAuth({
|
|
6423
6534
|
verbose: args.verbose,
|
|
6424
|
-
showToken: args["show-token"]
|
|
6535
|
+
showToken: args["show-token"],
|
|
6536
|
+
gheDomain: args["ghe-domain"]
|
|
6425
6537
|
});
|
|
6426
6538
|
}
|
|
6427
6539
|
});
|
|
@@ -6436,6 +6548,7 @@ const checkUsage = defineCommand({
|
|
|
6436
6548
|
async run() {
|
|
6437
6549
|
await ensurePaths();
|
|
6438
6550
|
await readConfig();
|
|
6551
|
+
state.auth.gheDomain = getCachedConfig().gheDomain;
|
|
6439
6552
|
await cacheVSCodeVersion();
|
|
6440
6553
|
await setupGitHubToken();
|
|
6441
6554
|
try {
|
|
@@ -6466,7 +6579,7 @@ const checkUsage = defineCommand({
|
|
|
6466
6579
|
|
|
6467
6580
|
//#endregion
|
|
6468
6581
|
//#region src/lib/version.ts
|
|
6469
|
-
const VERSION = "0.5.
|
|
6582
|
+
const VERSION = "0.5.7";
|
|
6470
6583
|
|
|
6471
6584
|
//#endregion
|
|
6472
6585
|
//#region src/debug.ts
|
|
@@ -6495,6 +6608,7 @@ async function checkConfigExists() {
|
|
|
6495
6608
|
}
|
|
6496
6609
|
}
|
|
6497
6610
|
async function getDebugInfo() {
|
|
6611
|
+
await readConfig();
|
|
6498
6612
|
const configExists = await checkConfigExists();
|
|
6499
6613
|
return {
|
|
6500
6614
|
version: VERSION,
|
|
@@ -6504,7 +6618,8 @@ async function getDebugInfo() {
|
|
|
6504
6618
|
CONFIG_PATH: PATHS.CONFIG_PATH
|
|
6505
6619
|
},
|
|
6506
6620
|
configExists,
|
|
6507
|
-
tokenExists: hasToken()
|
|
6621
|
+
tokenExists: hasToken(),
|
|
6622
|
+
gheDomain: getCachedConfig().gheDomain
|
|
6508
6623
|
};
|
|
6509
6624
|
}
|
|
6510
6625
|
function printDebugInfoPlain(info) {
|
|
@@ -6518,7 +6633,8 @@ Paths:
|
|
|
6518
6633
|
- CONFIG_PATH: ${info.paths.CONFIG_PATH}
|
|
6519
6634
|
|
|
6520
6635
|
Config exists: ${info.configExists ? "Yes" : "No"}
|
|
6521
|
-
Token exists: ${info.tokenExists ? "Yes" : "No"}
|
|
6636
|
+
Token exists: ${info.tokenExists ? "Yes" : "No"}
|
|
6637
|
+
GHE Domain: ${info.gheDomain ?? "none"}`);
|
|
6522
6638
|
}
|
|
6523
6639
|
async function runDebug(options) {
|
|
6524
6640
|
const debugInfo = await getDebugInfo();
|
|
@@ -46809,20 +46925,29 @@ const methodColors = {
|
|
|
46809
46925
|
function colorizeMethod(method) {
|
|
46810
46926
|
return colorize(methodColors[method] ?? "white", method);
|
|
46811
46927
|
}
|
|
46928
|
+
function getEffectiveModel(info) {
|
|
46929
|
+
return info.steps.length > 0 ? info.steps.at(-1).result : info.originalModel ?? "-";
|
|
46930
|
+
}
|
|
46931
|
+
function appendModelStep(info, tag, newModel) {
|
|
46932
|
+
if (newModel === getEffectiveModel(info)) return info;
|
|
46933
|
+
return {
|
|
46934
|
+
originalModel: info.originalModel,
|
|
46935
|
+
steps: [...info.steps, {
|
|
46936
|
+
tag,
|
|
46937
|
+
result: newModel
|
|
46938
|
+
}]
|
|
46939
|
+
};
|
|
46940
|
+
}
|
|
46812
46941
|
function formatModelMapping(info) {
|
|
46813
46942
|
if (!info) return "";
|
|
46814
|
-
const { originalModel,
|
|
46815
|
-
if (!originalModel &&
|
|
46816
|
-
const parts = [];
|
|
46817
|
-
|
|
46818
|
-
|
|
46819
|
-
|
|
46820
|
-
parts.push(colorize("dim",
|
|
46821
|
-
parts.push(colorize("cyanBright",
|
|
46822
|
-
}
|
|
46823
|
-
if (mappedModel && mappedModel !== (rewrittenModel ?? displayOriginal)) {
|
|
46824
|
-
parts.push(colorize("dim", "→"));
|
|
46825
|
-
parts.push(colorize("greenBright", mappedModel));
|
|
46943
|
+
const { originalModel, steps } = info;
|
|
46944
|
+
if (!originalModel && steps.length === 0) return "";
|
|
46945
|
+
const parts = [colorize("blueBright", originalModel ?? "-")];
|
|
46946
|
+
for (let i = 0; i < steps.length; i++) {
|
|
46947
|
+
const step = steps[i];
|
|
46948
|
+
const isLast = i === steps.length - 1;
|
|
46949
|
+
parts.push(colorize("dim", `-[${step.tag}]->`));
|
|
46950
|
+
parts.push(colorize(isLast ? "greenBright" : "cyanBright", step.result));
|
|
46826
46951
|
}
|
|
46827
46952
|
return ` ${colorize("dim", "model=")}${parts.join(" ")}`;
|
|
46828
46953
|
}
|
|
@@ -48499,13 +48624,15 @@ function rewriteModel(modelId) {
|
|
|
48499
48624
|
if (userRules) {
|
|
48500
48625
|
for (const rule of userRules) if (matchesGlob(rule.from, modelId)) return {
|
|
48501
48626
|
originalModel: modelId,
|
|
48502
|
-
model: normalizeToKnownModel(rule.to) ?? rule.to
|
|
48627
|
+
model: normalizeToKnownModel(rule.to) ?? rule.to,
|
|
48628
|
+
reason: "CONFIG_REWRITE"
|
|
48503
48629
|
};
|
|
48504
48630
|
}
|
|
48505
48631
|
const normalized = normalizeToKnownModel(modelId);
|
|
48506
48632
|
if (normalized && normalized !== modelId) return {
|
|
48507
48633
|
originalModel: modelId,
|
|
48508
|
-
model: normalized
|
|
48634
|
+
model: normalized,
|
|
48635
|
+
reason: "AUTO_CORRECT"
|
|
48509
48636
|
};
|
|
48510
48637
|
return {
|
|
48511
48638
|
originalModel: modelId,
|
|
@@ -49209,8 +49336,13 @@ const responsesReasoningSummarySchema = object({
|
|
|
49209
49336
|
const responsesReasoningInputSchema = object({
|
|
49210
49337
|
id: string().optional(),
|
|
49211
49338
|
type: literal("reasoning"),
|
|
49212
|
-
summary: array(responsesReasoningSummarySchema),
|
|
49213
|
-
encrypted_content: string().
|
|
49339
|
+
summary: array(responsesReasoningSummarySchema).optional(),
|
|
49340
|
+
encrypted_content: string().nullable().optional(),
|
|
49341
|
+
status: _enum([
|
|
49342
|
+
"in_progress",
|
|
49343
|
+
"completed",
|
|
49344
|
+
"incomplete"
|
|
49345
|
+
]).optional()
|
|
49214
49346
|
}).loose();
|
|
49215
49347
|
const responsesCompactionInputSchema = object({
|
|
49216
49348
|
id: string().min(1),
|
|
@@ -49443,7 +49575,11 @@ async function handleCompletionCore({ body, signal, headers }) {
|
|
|
49443
49575
|
const requestContext = normalizeChatRequestContext(payload, headers);
|
|
49444
49576
|
consola.debug("Request payload:", JSON.stringify(payload).slice(-400));
|
|
49445
49577
|
const rewrite = applyModelRewrite(payload);
|
|
49446
|
-
const
|
|
49578
|
+
const steps = [];
|
|
49579
|
+
if (rewrite.reason) steps.push({
|
|
49580
|
+
tag: rewrite.reason,
|
|
49581
|
+
result: rewrite.model
|
|
49582
|
+
});
|
|
49447
49583
|
const selectedModel = findModelById(payload.model);
|
|
49448
49584
|
try {
|
|
49449
49585
|
if (selectedModel) {
|
|
@@ -49462,11 +49598,10 @@ async function handleCompletionCore({ body, signal, headers }) {
|
|
|
49462
49598
|
}
|
|
49463
49599
|
const upstreamSignal = createUpstreamSignalFromConfig(signal);
|
|
49464
49600
|
const plan = adapter.toCapiPlan(payload, { requestContext });
|
|
49465
|
-
const modelMapping = {
|
|
49466
|
-
originalModel,
|
|
49467
|
-
|
|
49468
|
-
|
|
49469
|
-
};
|
|
49601
|
+
const modelMapping = appendModelStep({
|
|
49602
|
+
originalModel: rewrite.originalModel,
|
|
49603
|
+
steps
|
|
49604
|
+
}, "MODEL_RESOLVE", plan.resolvedModel);
|
|
49470
49605
|
const transport = new CopilotTransport(createCopilotClient());
|
|
49471
49606
|
consola.debug("Streaming response");
|
|
49472
49607
|
return {
|
|
@@ -50843,10 +50978,6 @@ const responsesApiEntry = {
|
|
|
50843
50978
|
if (error instanceof TranslationFailure) throw fromTranslationFailure(error);
|
|
50844
50979
|
throw error;
|
|
50845
50980
|
}
|
|
50846
|
-
const modelMapping = {
|
|
50847
|
-
originalModel: ctx.modelMapping.originalModel,
|
|
50848
|
-
mappedModel: responsesPayload.model
|
|
50849
|
-
};
|
|
50850
50981
|
applyContextManagement(responsesPayload, ctx.selectedModel?.capabilities.limits.max_prompt_tokens);
|
|
50851
50982
|
compactInputByLatestCompaction(responsesPayload);
|
|
50852
50983
|
const { vision, initiator } = getResponsesRequestOptions(responsesPayload);
|
|
@@ -50857,7 +50988,7 @@ const responsesApiEntry = {
|
|
|
50857
50988
|
signal: ctx.upstreamSignal.signal,
|
|
50858
50989
|
requestContext: ctx.requestContext
|
|
50859
50990
|
}), ctx.upstreamSignal),
|
|
50860
|
-
modelMapping
|
|
50991
|
+
modelMapping: ctx.modelMapping
|
|
50861
50992
|
};
|
|
50862
50993
|
}
|
|
50863
50994
|
};
|
|
@@ -50873,10 +51004,7 @@ const chatCompletionsEntry = {
|
|
|
50873
51004
|
if (error instanceof TranslationFailure) throw fromTranslationFailure(error);
|
|
50874
51005
|
throw error;
|
|
50875
51006
|
}
|
|
50876
|
-
const modelMapping =
|
|
50877
|
-
originalModel: ctx.modelMapping.originalModel,
|
|
50878
|
-
mappedModel: plan.resolvedModel
|
|
50879
|
-
};
|
|
51007
|
+
const modelMapping = appendModelStep(ctx.modelMapping, "MODEL_RESOLVE", plan.resolvedModel);
|
|
50880
51008
|
consola.debug("Claude Code requested model:", ctx.anthropicPayload.model, "-> Copilot model:", plan.resolvedModel);
|
|
50881
51009
|
if (consola.level >= 4) consola.debug("Planned Copilot request payload:", JSON.stringify(plan.payload));
|
|
50882
51010
|
return {
|
|
@@ -50926,17 +51054,33 @@ async function handleMessagesCore({ body, signal, headers }) {
|
|
|
50926
51054
|
const requestContext = normalizeAnthropicRequestContext(anthropicPayload, headers);
|
|
50927
51055
|
if (consola.level >= 4) consola.debug("Anthropic request payload:", JSON.stringify(anthropicPayload));
|
|
50928
51056
|
const rewrite = applyModelRewrite(anthropicPayload);
|
|
51057
|
+
const steps = [];
|
|
51058
|
+
if (rewrite.reason) steps.push({
|
|
51059
|
+
tag: rewrite.reason,
|
|
51060
|
+
result: rewrite.model
|
|
51061
|
+
});
|
|
50929
51062
|
const betaResult = processAnthropicBetaHeader(headers.get("anthropic-beta"), anthropicPayload.model);
|
|
50930
51063
|
if (betaResult.upgradeTarget) {
|
|
50931
51064
|
consola.debug(`Beta header context upgrade: ${anthropicPayload.model} → ${betaResult.upgradeTarget}`);
|
|
50932
51065
|
anthropicPayload.model = betaResult.upgradeTarget;
|
|
51066
|
+
steps.push({
|
|
51067
|
+
tag: "BETA_UPGRADE",
|
|
51068
|
+
result: betaResult.upgradeTarget
|
|
51069
|
+
});
|
|
50933
51070
|
}
|
|
50934
51071
|
const anthropicBetaHeader = betaResult.header;
|
|
50935
51072
|
const modelRouting = applyMessagesModelPolicy(anthropicPayload, { betaUpgraded: !!betaResult.upgradeTarget });
|
|
51073
|
+
if (modelRouting.reason === "context-upgrade") steps.push({
|
|
51074
|
+
tag: "CONTEXT_UPGRADE",
|
|
51075
|
+
result: modelRouting.routedModel
|
|
51076
|
+
});
|
|
51077
|
+
else if (modelRouting.reason === "compact") steps.push({
|
|
51078
|
+
tag: "COMPACT",
|
|
51079
|
+
result: modelRouting.routedModel
|
|
51080
|
+
});
|
|
50936
51081
|
const modelMapping = {
|
|
50937
51082
|
originalModel: rewrite.originalModel,
|
|
50938
|
-
|
|
50939
|
-
mappedModel: modelRouting.routedModel
|
|
51083
|
+
steps
|
|
50940
51084
|
};
|
|
50941
51085
|
if (modelRouting.reason) consola.debug(`Routed anthropic request via ${modelRouting.reason}:`, `${modelRouting.originalModel} -> ${modelRouting.routedModel}`);
|
|
50942
51086
|
const selectedModel = findModelById(anthropicPayload.model);
|
|
@@ -50970,8 +51114,10 @@ async function handleMessagesCore({ body, signal, headers }) {
|
|
|
50970
51114
|
upstreamSignal: retrySignal,
|
|
50971
51115
|
modelMapping: {
|
|
50972
51116
|
originalModel: rewrite.originalModel,
|
|
50973
|
-
|
|
50974
|
-
|
|
51117
|
+
steps: [...steps, {
|
|
51118
|
+
tag: "RETRY_UPGRADE",
|
|
51119
|
+
result: upgradeTarget
|
|
51120
|
+
}]
|
|
50975
51121
|
}
|
|
50976
51122
|
});
|
|
50977
51123
|
}
|
|
@@ -51388,8 +51534,10 @@ async function handleResponsesCore({ body, signal, headers }) {
|
|
|
51388
51534
|
result,
|
|
51389
51535
|
modelMapping: {
|
|
51390
51536
|
originalModel: rewrite.originalModel,
|
|
51391
|
-
|
|
51392
|
-
|
|
51537
|
+
steps: rewrite.reason ? [{
|
|
51538
|
+
tag: rewrite.reason,
|
|
51539
|
+
result: rewrite.model
|
|
51540
|
+
}] : []
|
|
51393
51541
|
}
|
|
51394
51542
|
};
|
|
51395
51543
|
}
|
|
@@ -51635,7 +51783,7 @@ function createServer(options) {
|
|
|
51635
51783
|
const model = body && typeof body === "object" && "model" in body ? body.model : void 0;
|
|
51636
51784
|
if (typeof model === "string") setRequestModelMapping(request, {
|
|
51637
51785
|
originalModel: model,
|
|
51638
|
-
|
|
51786
|
+
steps: []
|
|
51639
51787
|
});
|
|
51640
51788
|
}).onAfterResponse(({ request, requestStart, set }) => {
|
|
51641
51789
|
const elapsed = formatElapsed(requestStart);
|
|
@@ -51701,6 +51849,9 @@ async function runServer(options) {
|
|
|
51701
51849
|
state.config.upstreamTimeoutSeconds = options.upstreamTimeoutSeconds;
|
|
51702
51850
|
await ensurePaths();
|
|
51703
51851
|
await readConfig();
|
|
51852
|
+
state.auth.gheDomain = getCachedConfig().gheDomain;
|
|
51853
|
+
if (options.gheDomain !== void 0) state.auth.gheDomain = options.gheDomain ? normalizeGheDomain(options.gheDomain) : void 0;
|
|
51854
|
+
if (state.auth.gheDomain && state.config.accountType === "individual") state.config.accountType = "enterprise";
|
|
51704
51855
|
await cacheVSCodeVersion();
|
|
51705
51856
|
if (!options.githubToken) await setupGitHubToken();
|
|
51706
51857
|
await setupCopilotToken();
|
|
@@ -51792,6 +51943,11 @@ const start = defineCommand({
|
|
|
51792
51943
|
type: "string",
|
|
51793
51944
|
default: "1800",
|
|
51794
51945
|
description: "Upstream request timeout in seconds (0 to disable)"
|
|
51946
|
+
},
|
|
51947
|
+
"ghe-domain": {
|
|
51948
|
+
alias: "ghe",
|
|
51949
|
+
type: "string",
|
|
51950
|
+
description: "Company GHE domain for GitHub Enterprise Cloud (e.g. company.ghe.com)"
|
|
51795
51951
|
}
|
|
51796
51952
|
},
|
|
51797
51953
|
run({ args }) {
|
|
@@ -51810,7 +51966,8 @@ const start = defineCommand({
|
|
|
51810
51966
|
showToken: args["show-token"],
|
|
51811
51967
|
proxyEnv: args["proxy-env"],
|
|
51812
51968
|
idleTimeoutSeconds,
|
|
51813
|
-
upstreamTimeoutSeconds
|
|
51969
|
+
upstreamTimeoutSeconds,
|
|
51970
|
+
gheDomain: args["ghe-domain"]
|
|
51814
51971
|
});
|
|
51815
51972
|
}
|
|
51816
51973
|
});
|