Skip to content

Commit 4c48e86

Browse files
committed
refactor(core): unify User-Agent into single source (EasyCode brand)
Add core/utils/userAgent.ts as the single source of truth for the client User-Agent, formatted as EasyCode/<client>/<version> (<platform>; <arch>). VSCode vs CLI is detected from the CLI_VERSION 'VSCode-' prefix. Replace all scattered/inconsistent UA strings (DeepVCode, GeminiCLI, DeepCode CLI, DeepCode-CLI/1.0.0, DeepV-Code-Agent) across proxyAuth, authServer, authenticatedHttpClient, serverConfig, contentGenerator, pptGenerateTool and binaryManager. Also remove dead httpOptions in contentGenerator. Note: server-side UA recognition/stats must switch from DeepVCode to EasyCode accordingly.
1 parent 8c785b8 commit 4c48e86

10 files changed

Lines changed: 133 additions & 52 deletions

File tree

packages/core/src/auth/authenticatedHttpClient.ts

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88

99
import { logIfNotSilent } from '../utils/logging.js';
10+
import { getUserAgent } from '../utils/userAgent.js';
1011

1112
/**
1213
* 认证HTTP客户端
@@ -44,10 +45,10 @@ export class AuthenticatedHttpClient {
4445
options: RequestInit = {}
4546
): Promise<Response> {
4647
const url = `${this.baseURL}${endpoint}`;
47-
48+
4849
// 准备请求选项
4950
const requestOptions = await this.prepareRequestOptions(options);
50-
51+
5152
// 发送请求
5253
let response = await fetch(url, requestOptions);
5354

@@ -70,8 +71,8 @@ export class AuthenticatedHttpClient {
7071
* POST请求
7172
*/
7273
async post(
73-
endpoint: string,
74-
body?: any,
74+
endpoint: string,
75+
body?: any,
7576
options: RequestInit = {}
7677
): Promise<Response> {
7778
const requestOptions: RequestInit = {
@@ -94,8 +95,8 @@ export class AuthenticatedHttpClient {
9495
* PUT请求
9596
*/
9697
async put(
97-
endpoint: string,
98-
body?: any,
98+
endpoint: string,
99+
body?: any,
99100
options: RequestInit = {}
100101
): Promise<Response> {
101102
const requestOptions: RequestInit = {
@@ -126,7 +127,7 @@ export class AuthenticatedHttpClient {
126127
*/
127128
private async prepareRequestOptions(options: RequestInit): Promise<RequestInit> {
128129
const headers: HeadersInit = {
129-
'User-Agent': 'DeepCode CLI',
130+
'User-Agent': getUserAgent(),
130131
...options.headers
131132
};
132133

@@ -159,7 +160,7 @@ export class AuthenticatedHttpClient {
159160
* 处理401未授权响应
160161
*/
161162
private async handleUnauthorized(
162-
url: string,
163+
url: string,
163164
originalOptions: RequestInit
164165
): Promise<Response> {
165166
if (this.isRefreshing) {
@@ -177,13 +178,13 @@ export class AuthenticatedHttpClient {
177178

178179
try {
179180
logIfNotSilent('log', '🔄 Access token expired, attempting refresh...');
180-
181+
181182
// 尝试刷新令牌
182183
const newToken = await this.tokenManager.refreshAccessToken();
183-
184+
184185
if (newToken) {
185186
logIfNotSilent('log', '✅ Token refreshed successfully');
186-
187+
187188
// 更新请求头中的令牌
188189
const updatedOptions = {
189190
...originalOptions,
@@ -205,23 +206,23 @@ export class AuthenticatedHttpClient {
205206
}
206207
} catch (error) {
207208
console.error('❌ Token refresh failed:', error);
208-
209+
209210
// 清除令牌
210211
if (this.tokenManager.clearTokens) {
211212
await this.tokenManager.clearTokens();
212213
} else if (this.tokenManager.clear) {
213214
this.tokenManager.clear();
214215
}
215-
216+
216217
// 拒绝队列中的所有请求
217218
this.rejectRequestQueue(new Error('Authentication required'));
218-
219+
219220
// 触发重新认证流程
220221
if (this.onAuthenticationRequired) {
221222
logIfNotSilent('log', '🔄 Authentication required, triggering auth flow...');
222223
this.onAuthenticationRequired();
223224
}
224-
225+
225226
// 抛出认证错误
226227
throw new AuthenticationError('Authentication required - please re-authenticate');
227228
} finally {
@@ -234,7 +235,7 @@ export class AuthenticatedHttpClient {
234235
*/
235236
private processRequestQueue(newToken: string): void {
236237
const queue = this.requestQueue.splice(0);
237-
238+
238239
queue.forEach(({ resolve, reject, request }) => {
239240
request()
240241
.then((response) => resolve(response))
@@ -247,7 +248,7 @@ export class AuthenticatedHttpClient {
247248
*/
248249
private rejectRequestQueue(error: Error): void {
249250
const queue = this.requestQueue.splice(0);
250-
251+
251252
queue.forEach(({ reject }) => {
252253
reject(error);
253254
});

packages/core/src/auth/login/authServer.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { createDeepvlabAuthHandler } from './deepvlabAuth.js';
1414
import { getFeishuConfigFromServer, getFeishuTenantsFromServer } from '../../config/serverConfig.js';
1515
import { ProxyAuthManager } from '../../core/proxyAuth.js';
1616
import { AuthTemplates } from './templates/index.js';
17+
import { getUserAgent } from '../../utils/userAgent.js';
1718

1819

1920

@@ -289,7 +290,7 @@ export class AuthServer {
289290
method: 'GET',
290291
headers: {
291292
'Content-Type': 'application/json',
292-
'User-Agent': 'DeepCode-CLI/1.0.0'
293+
'User-Agent': getUserAgent()
293294
}
294295
});
295296
} catch (fetchError: any) {
@@ -531,7 +532,7 @@ export class AuthServer {
531532
method: 'POST',
532533
headers: {
533534
'Content-Type': 'application/json',
534-
'User-Agent': 'DeepCode-CLI/1.0.0'
535+
'User-Agent': getUserAgent()
535536
},
536537
body: JSON.stringify({
537538
email: email,
@@ -540,7 +541,7 @@ export class AuthServer {
540541
platform: process.platform,
541542
version: process.version,
542543
timestamp: Date.now(),
543-
userAgent: 'DeepCode-CLI/1.0.0'
544+
userAgent: getUserAgent()
544545
}
545546
})
546547
});
@@ -819,7 +820,7 @@ export class AuthServer {
819820
method: 'POST',
820821
headers: {
821822
'Content-Type': 'application/json',
822-
'User-Agent': 'DeepCode-CLI/1.0.0'
823+
'User-Agent': getUserAgent()
823824
},
824825
body: JSON.stringify({ code })
825826
});
@@ -846,7 +847,7 @@ export class AuthServer {
846847
method: 'POST',
847848
headers: {
848849
'Content-Type': 'application/json',
849-
'User-Agent': 'DeepCode-CLI/1.0.0'
850+
'User-Agent': getUserAgent()
850851
},
851852
body: JSON.stringify({ code })
852853
});
@@ -1042,7 +1043,7 @@ export class AuthServer {
10421043
method: 'POST',
10431044
headers: {
10441045
'Content-Type': 'application/json',
1045-
'User-Agent': 'DeepCode-CLI/1.0.0'
1046+
'User-Agent': getUserAgent()
10461047
},
10471048
body: JSON.stringify({
10481049
plat: 'deepvlab',
@@ -1052,7 +1053,7 @@ export class AuthServer {
10521053
platform: process.platform,
10531054
version: process.version,
10541055
timestamp: Date.now(),
1055-
userAgent: 'DeepCode-CLI/1.0.0'
1056+
userAgent: getUserAgent()
10561057
}
10571058
})
10581059
});
@@ -1162,7 +1163,7 @@ export class AuthServer {
11621163
method: 'POST',
11631164
headers: {
11641165
'Content-Type': 'application/json',
1165-
'User-Agent': 'DeepCode-CLI/1.0.0'
1166+
'User-Agent': getUserAgent()
11661167
},
11671168
body: JSON.stringify({
11681169
code: code,
@@ -1204,15 +1205,15 @@ export class AuthServer {
12041205
method: 'POST',
12051206
headers: {
12061207
'Content-Type': 'application/json',
1207-
'User-Agent': 'DeepCode-CLI/1.0.0'
1208+
'User-Agent': getUserAgent()
12081209
},
12091210
body: JSON.stringify({
12101211
feishuAccessToken: accessToken,
12111212
clientInfo: {
12121213
platform: process.platform,
12131214
version: process.version,
12141215
timestamp: Date.now(),
1215-
userAgent: 'DeepCode-CLI/1.0.0'
1216+
userAgent: getUserAgent()
12161217
}
12171218
})
12181219
});

packages/core/src/config/serverConfig.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
* 从DeepX_Code_server获取客户端所需的配置信息
1212
*/
1313

14+
import { getUserAgent } from '../utils/userAgent.js';
15+
1416
export interface FeishuTenantInfo {
1517
appId: string;
1618
label: string;
@@ -82,7 +84,7 @@ export class ServerConfigFetcher {
8284
method: 'GET',
8385
headers: {
8486
'Content-Type': 'application/json',
85-
'User-Agent': 'DeepCode-CLI/1.0.0',
87+
'User-Agent': getUserAgent(),
8688
},
8789
// 超时设置
8890
signal: AbortSignal.timeout(10000), // 10秒超时

packages/core/src/core/contentGenerator.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,10 @@ export async function createContentGenerator(
7979
gcConfig: Config,
8080
sessionId?: string,
8181
): Promise<ContentGenerator> {
82-
const version = process.env.CLI_VERSION || process.version;
83-
const httpOptions = {
84-
headers: {
85-
'User-Agent': `GeminiCLI/${version} (${process.platform}; ${process.arch})`,
86-
},
87-
};
82+
// NOTE: The DeepV server path below (the only active path) builds its request
83+
// headers — including the User-Agent — via proxyAuthManager.getUserHeaders(),
84+
// which uses the unified getUserAgent() from utils/userAgent.ts. No local
85+
// httpOptions/User-Agent is needed here.
8886

8987
// 🎯 统一DeepV Server处理:所有模型都使用DeepVServerAdapter,但路由逻辑会自动选择正确的API端点
9088
const isDeepVServer = true; // 现在所有模型都通过DeepV Server,适配器内部会根据模型类型选择正确路径

packages/core/src/core/proxyAuth.ts

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import { getActiveProxyServerUrl } from '../config/proxyConfig.js';
2121
import { logIfNotSilent } from '../utils/logging.js';
2222
import { getSessionId } from '../utils/session.js';
23+
import { getUserAgent } from '../utils/userAgent.js';
2324
import * as fs from 'fs';
2425
import * as path from 'path';
2526
import * as os from 'os';
@@ -82,21 +83,11 @@ export class ProxyAuthManager {
8283

8384
/**
8485
* 🎯 生成规范的 User-Agent 字符串
85-
* 格式: DeepVCode/<client>/<version> (<platform>; <arch>)
86+
* 委托给 core 统一的单一事实来源 utils/userAgent.ts。
87+
* 格式: EasyCode/<client>/<version> (<platform>; <arch>)
8688
*/
8789
private getUserAgent(): string {
88-
const version = this.cliVersion;
89-
const platform = process.platform;
90-
const arch = process.arch;
91-
92-
// 检查是否是 VSCode 插件(版本以 VSCode- 开头)
93-
if (version.startsWith('VSCode-')) {
94-
const actualVersion = version.replace('VSCode-', '');
95-
return `DeepVCode/VSCode/${actualVersion} (${platform}; ${arch})`;
96-
}
97-
98-
// CLI 模式
99-
return `DeepVCode/CLI/${version} (${platform}; ${arch})`;
90+
return getUserAgent(this.cliVersion);
10091
}
10192

10293
/**
@@ -579,7 +570,7 @@ export class ProxyAuthManager {
579570
method: 'POST',
580571
headers: {
581572
'Content-Type': 'application/json',
582-
'User-Agent': 'DeepCode CLI ProxyAuthManager'
573+
'User-Agent': this.getUserAgent()
583574
},
584575
body: JSON.stringify({
585576
refreshToken: this.jwtTokenData.refreshToken

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export * from './code_assist/inlineCompletion.js';
5252

5353
// Export utilities
5454
export * from './utils/paths.js';
55+
export * from './utils/userAgent.js';
5556
export * from './utils/schemaValidator.js';
5657
export * from './utils/errors.js';
5758
export * from './utils/httpErrorFallback.js';

packages/core/src/lsp/binaryManager.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import * as zlib from 'node:zlib';
1313
import { spawn, spawnSync } from 'node:child_process';
1414
import { request } from 'undici';
1515
import JSZip from 'jszip';
16+
import { getUserAgent } from '../utils/userAgent.js';
1617

1718
/**
1819
* 递归删除目录
@@ -269,7 +270,7 @@ export class BinaryManager {
269270
console.log(`[LSP] Downloading ${repo} from GitHub ${owner}/${repo}...`);
270271

271272
const token = process.env.GITHUB_TOKEN || process.env.GITHUB_PAT;
272-
const headers: Record<string, string> = { 'User-Agent': 'DeepV-Code-Agent' };
273+
const headers: Record<string, string> = { 'User-Agent': getUserAgent() };
273274
if (token) {
274275
headers['Authorization'] = `Bearer ${token}`;
275276
}

packages/core/src/tools/ppt/pptGenerateTool.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { ProxyAuthManager } from '../../core/proxyAuth.js';
1414
import open from 'open';
1515
import { logger } from '../../utils/enhancedLogger.js';
1616
import { t } from '../../utils/simpleI18n.js';
17+
import { getUserAgent } from '../../utils/userAgent.js';
1718

1819
export interface PptGenerateToolParams {
1920
/** 确认提交(默认true) */
@@ -258,7 +259,7 @@ PPT模式已退出。`,
258259
headers: {
259260
'Content-Type': 'application/json',
260261
'Authorization': `Bearer ${accessToken}`,
261-
'User-Agent': 'DeepCode CLI',
262+
'User-Agent': getUserAgent(),
262263
},
263264
body: JSON.stringify({
264265
topic: state.topic,
@@ -287,7 +288,7 @@ PPT模式已退出。`,
287288
headers: {
288289
'Content-Type': 'application/json',
289290
'Authorization': `Bearer ${accessToken}`,
290-
'User-Agent': 'DeepCode CLI',
291+
'User-Agent': getUserAgent(),
291292
},
292293
signal,
293294
});
@@ -309,7 +310,7 @@ PPT模式已退出。`,
309310
headers: {
310311
'Content-Type': 'application/json',
311312
'Authorization': `Bearer ${accessToken}`,
312-
'User-Agent': 'DeepCode CLI',
313+
'User-Agent': getUserAgent(),
313314
},
314315
body: JSON.stringify({
315316
expiresIn: 600, // 10分钟有效期

0 commit comments

Comments
 (0)