@tencent-ai/cloud-agent-sdk 0.2.12 → 0.2.13-next.8f136b6.20260204
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/dist/index.cjs +330 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +409 -88
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +409 -88
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +330 -47
- package/dist/index.mjs.map +1 -1
- package/dist/tencent-ai-cloud-agent-sdk-0.2.13-next.8f136b6.20260204.tgz +0 -0
- package/package.json +4 -3
- package/dist/tencent-ai-cloud-agent-sdk-0.2.12.tgz +0 -0
package/dist/index.cjs
CHANGED
|
@@ -2411,7 +2411,7 @@ var CloudAgentConnection = class {
|
|
|
2411
2411
|
}
|
|
2412
2412
|
async createSession(params) {
|
|
2413
2413
|
return {
|
|
2414
|
-
...await this.client.
|
|
2414
|
+
...await this.client.createSession(this.cwd),
|
|
2415
2415
|
sessionId: this.agentId
|
|
2416
2416
|
};
|
|
2417
2417
|
}
|
|
@@ -16212,6 +16212,7 @@ var AccountService = class {
|
|
|
16212
16212
|
this.initPromise = null;
|
|
16213
16213
|
this.initResolve = null;
|
|
16214
16214
|
this.requestInterceptorId = null;
|
|
16215
|
+
this.crossTabBroadcaster = null;
|
|
16215
16216
|
this.initPromise = new Promise((resolve) => {
|
|
16216
16217
|
this.initResolve = resolve;
|
|
16217
16218
|
});
|
|
@@ -16260,15 +16261,34 @@ var AccountService = class {
|
|
|
16260
16261
|
this.initialized = true;
|
|
16261
16262
|
this.initResolve?.(account);
|
|
16262
16263
|
}
|
|
16263
|
-
if (!wasInitialized || prev?.uid !== account?.uid)
|
|
16264
|
+
if (!wasInitialized || prev?.uid !== account?.uid) {
|
|
16265
|
+
this.notifyListeners();
|
|
16266
|
+
if (account && this.crossTabBroadcaster) this.crossTabBroadcaster.broadcastLogin();
|
|
16267
|
+
}
|
|
16264
16268
|
}
|
|
16265
16269
|
/**
|
|
16266
16270
|
* 清除账号(登出)
|
|
16271
|
+
* 先广播登出消息,再清除本地账号
|
|
16267
16272
|
*/
|
|
16268
16273
|
clearAccount() {
|
|
16274
|
+
if (this.crossTabBroadcaster) this.crossTabBroadcaster.broadcastLogout();
|
|
16275
|
+
this.setAccount(null);
|
|
16276
|
+
}
|
|
16277
|
+
/**
|
|
16278
|
+
* 静默清除账号(不广播)
|
|
16279
|
+
* 用于收到其他标签页 logout 消息时,避免循环广播
|
|
16280
|
+
*/
|
|
16281
|
+
clearAccountSilently() {
|
|
16269
16282
|
this.setAccount(null);
|
|
16270
16283
|
}
|
|
16271
16284
|
/**
|
|
16285
|
+
* 设置跨标签页认证同步广播器
|
|
16286
|
+
* 应在应用初始化时由上层(如 agent-ui)调用
|
|
16287
|
+
*/
|
|
16288
|
+
setCrossTabBroadcaster(broadcaster) {
|
|
16289
|
+
this.crossTabBroadcaster = broadcaster;
|
|
16290
|
+
}
|
|
16291
|
+
/**
|
|
16272
16292
|
* 订阅账号变化
|
|
16273
16293
|
* @param callback 变化时的回调函数
|
|
16274
16294
|
* @returns 取消订阅函数
|
|
@@ -16333,6 +16353,11 @@ var AccountService = class {
|
|
|
16333
16353
|
* 导出单例实例
|
|
16334
16354
|
*/
|
|
16335
16355
|
const accountService = new AccountService();
|
|
16356
|
+
/**
|
|
16357
|
+
* 暴露给全局,供 Agent Manager 直接调用 setAccount 刷新 Widget 状态
|
|
16358
|
+
* 这是为了解决 IDE 环境中 IPC 事件无法直接触发 Widget 账号刷新的问题
|
|
16359
|
+
*/
|
|
16360
|
+
if (typeof window !== "undefined") window.__genieAccountService = accountService;
|
|
16336
16361
|
|
|
16337
16362
|
//#endregion
|
|
16338
16363
|
//#region ../agent-provider/src/common/utils/concurrency.ts
|
|
@@ -16940,13 +16965,19 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
16940
16965
|
/**
|
|
16941
16966
|
* Create a new conversation
|
|
16942
16967
|
* POST {endpoint}/console/as/conversations
|
|
16968
|
+
* @param params - Optional session params containing _meta with tags
|
|
16943
16969
|
*/
|
|
16944
|
-
async create() {
|
|
16970
|
+
async create(params) {
|
|
16945
16971
|
try {
|
|
16946
|
-
const
|
|
16972
|
+
const tagsObj = (params?._meta?.["codebuddy.ai"])?.tags;
|
|
16973
|
+
const tagsArray = tagsObj ? Object.entries(tagsObj).map(([key, value]) => `${key}:${value}`) : void 0;
|
|
16974
|
+
const createPayload = {
|
|
16947
16975
|
prompt: "",
|
|
16948
|
-
model: "deepseek-r1"
|
|
16949
|
-
|
|
16976
|
+
model: "deepseek-r1",
|
|
16977
|
+
...tagsArray && tagsArray.length > 0 ? { tags: tagsArray } : {}
|
|
16978
|
+
};
|
|
16979
|
+
console.log("[CloudAgentProvider] Creating conversation with payload:", createPayload);
|
|
16980
|
+
const apiResponse = await httpService.post("/console/as/conversations/", createPayload);
|
|
16950
16981
|
if (!apiResponse.data) throw new Error("No data in API response");
|
|
16951
16982
|
this.logger?.info(`Created conversation: ${apiResponse.data.id}`);
|
|
16952
16983
|
return apiResponse.data.id;
|
|
@@ -17643,8 +17674,8 @@ var ActiveSessionImpl = class {
|
|
|
17643
17674
|
* await session.setMode('architect');
|
|
17644
17675
|
* ```
|
|
17645
17676
|
*/
|
|
17646
|
-
async setMode(modeId) {
|
|
17647
|
-
if (this._availableModes) {
|
|
17677
|
+
async setMode(modeId, skipAvailableChecker) {
|
|
17678
|
+
if (this._availableModes && !skipAvailableChecker) {
|
|
17648
17679
|
if (!this._availableModes.some((m) => m.id === modeId)) {
|
|
17649
17680
|
const availableIds = this._availableModes.map((m) => m.id).join(", ");
|
|
17650
17681
|
throw new Error(`Invalid modeId: "${modeId}". Available modes: ${availableIds}`);
|
|
@@ -17835,14 +17866,6 @@ var ActiveSessionImpl = class {
|
|
|
17835
17866
|
//#endregion
|
|
17836
17867
|
//#region ../agent-provider/src/common/client/session-manager.ts
|
|
17837
17868
|
/**
|
|
17838
|
-
* SessionManager - Manages session lifecycle and connections
|
|
17839
|
-
*
|
|
17840
|
-
* Provides the core implementation for session-centric API operations:
|
|
17841
|
-
* - list() - Lists sessions (mapped from agents)
|
|
17842
|
-
* - createSession() - Creates new session (auto-creates agent)
|
|
17843
|
-
* - loadSession() - Loads existing session (finds agent by sessionId)
|
|
17844
|
-
*/
|
|
17845
|
-
/**
|
|
17846
17869
|
* SessionManager - Session lifecycle management
|
|
17847
17870
|
*
|
|
17848
17871
|
* This class manages the relationship between sessions and agents.
|
|
@@ -17938,14 +17961,8 @@ var SessionManager = class {
|
|
|
17938
17961
|
connectionInfo
|
|
17939
17962
|
});
|
|
17940
17963
|
session.setModes(response.modes?.availableModes, response.modes?.currentModeId);
|
|
17941
|
-
|
|
17942
|
-
|
|
17943
|
-
id: m.modelId,
|
|
17944
|
-
name: m.name,
|
|
17945
|
-
description: m.description ?? void 0
|
|
17946
|
-
}));
|
|
17947
|
-
session.setModels(localModels, response.models?.currentModelId);
|
|
17948
|
-
}
|
|
17964
|
+
const availableModels = this.extractAvailableModels(response);
|
|
17965
|
+
if (availableModels) session.setModels(availableModels, response.models?.currentModelId);
|
|
17949
17966
|
this.logger?.info(`Session created: ${response.sessionId}`);
|
|
17950
17967
|
return session;
|
|
17951
17968
|
}
|
|
@@ -17981,17 +17998,31 @@ var SessionManager = class {
|
|
|
17981
17998
|
mcpServers: params.mcpServers
|
|
17982
17999
|
});
|
|
17983
18000
|
session.setModes(response.modes?.availableModes, response.modes?.currentModeId);
|
|
17984
|
-
|
|
17985
|
-
|
|
17986
|
-
id: m.modelId,
|
|
17987
|
-
name: m.name,
|
|
17988
|
-
description: m.description ?? void 0
|
|
17989
|
-
}));
|
|
17990
|
-
session.setModels(localModels, response.models?.currentModelId);
|
|
17991
|
-
}
|
|
18001
|
+
const availableModels = this.extractAvailableModels(response);
|
|
18002
|
+
if (availableModels) session.setModels(availableModels, response.models?.currentModelId);
|
|
17992
18003
|
this.logger?.info(`Session loaded: ${params.sessionId}`);
|
|
17993
18004
|
return session;
|
|
17994
18005
|
}
|
|
18006
|
+
/**
|
|
18007
|
+
* 从 ACP response 中提取可用模型列表
|
|
18008
|
+
*
|
|
18009
|
+
* 优先级:
|
|
18010
|
+
* 1. response.models._meta?.['codebuddy.ai']?.availableModels - 包含完整的模型信息(字段名为 'id')
|
|
18011
|
+
* 2. response.models?.availableModels - 只包含基本信息(字段名为 'modelId')
|
|
18012
|
+
* 3. undefined - 都没有时返回 undefined
|
|
18013
|
+
*
|
|
18014
|
+
* @param response - ACP 响应对象
|
|
18015
|
+
* @returns ModelInfo[] | undefined
|
|
18016
|
+
*/
|
|
18017
|
+
extractAvailableModels(response) {
|
|
18018
|
+
const metaModels = (response.models?._meta?.["codebuddy.ai"])?.availableModels;
|
|
18019
|
+
if (metaModels && Array.isArray(metaModels) && metaModels.length > 0) return metaModels;
|
|
18020
|
+
const availableModels = response.models?.availableModels;
|
|
18021
|
+
if (availableModels && Array.isArray(availableModels) && availableModels.length > 0) return availableModels.map((model) => ({
|
|
18022
|
+
...model,
|
|
18023
|
+
...model._meta?.["codebuddy.ai"] || {}
|
|
18024
|
+
}));
|
|
18025
|
+
}
|
|
17995
18026
|
};
|
|
17996
18027
|
|
|
17997
18028
|
//#endregion
|
|
@@ -18264,6 +18295,28 @@ var AgentClient = class {
|
|
|
18264
18295
|
};
|
|
18265
18296
|
}
|
|
18266
18297
|
},
|
|
18298
|
+
getSubagentList: async (params) => {
|
|
18299
|
+
try {
|
|
18300
|
+
if (this.provider && this.provider.getSubagentList) {
|
|
18301
|
+
const result = await this.provider.getSubagentList(params);
|
|
18302
|
+
this.logger?.info("Subagent list retrieved", {
|
|
18303
|
+
resultCount: result.results.length,
|
|
18304
|
+
hasError: !!result.error
|
|
18305
|
+
});
|
|
18306
|
+
return result;
|
|
18307
|
+
}
|
|
18308
|
+
return {
|
|
18309
|
+
results: [],
|
|
18310
|
+
error: "Provider does not support getSubagentList"
|
|
18311
|
+
};
|
|
18312
|
+
} catch (error) {
|
|
18313
|
+
this.logger?.error("Failed to get subagent list", error);
|
|
18314
|
+
return {
|
|
18315
|
+
results: [],
|
|
18316
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
18317
|
+
};
|
|
18318
|
+
}
|
|
18319
|
+
},
|
|
18267
18320
|
batchTogglePlugins: async (request) => {
|
|
18268
18321
|
try {
|
|
18269
18322
|
if (this.provider && this.provider.batchTogglePlugins) {
|
|
@@ -18308,10 +18361,10 @@ var AgentClient = class {
|
|
|
18308
18361
|
return [];
|
|
18309
18362
|
}
|
|
18310
18363
|
},
|
|
18311
|
-
installPlugins: async (pluginNames, marketplaceName, installScope) => {
|
|
18364
|
+
installPlugins: async (pluginNames, marketplaceName, installScope, marketplaceSource) => {
|
|
18312
18365
|
try {
|
|
18313
18366
|
if (this.provider && "installPlugins" in this.provider && typeof this.provider.installPlugins === "function") {
|
|
18314
|
-
const result = await this.provider.installPlugins(pluginNames, marketplaceName, installScope);
|
|
18367
|
+
const result = await this.provider.installPlugins(pluginNames, marketplaceName, installScope, marketplaceSource);
|
|
18315
18368
|
this.logger?.info("Install plugins", {
|
|
18316
18369
|
pluginNames,
|
|
18317
18370
|
marketplaceName,
|
|
@@ -18346,6 +18399,23 @@ var AgentClient = class {
|
|
|
18346
18399
|
return [];
|
|
18347
18400
|
}
|
|
18348
18401
|
},
|
|
18402
|
+
getAvailableCommands: async (sessionId) => {
|
|
18403
|
+
try {
|
|
18404
|
+
if (this.provider && "getAvailableCommands" in this.provider && typeof this.provider.getAvailableCommands === "function") {
|
|
18405
|
+
const result = await this.provider.getAvailableCommands(sessionId);
|
|
18406
|
+
this.logger?.info("Got available commands from provider", {
|
|
18407
|
+
sessionId: sessionId ?? "(default)",
|
|
18408
|
+
count: result?.length ?? 0
|
|
18409
|
+
});
|
|
18410
|
+
return result;
|
|
18411
|
+
}
|
|
18412
|
+
this.logger?.warn("Provider does not support getAvailableCommands", { sessionId });
|
|
18413
|
+
return [];
|
|
18414
|
+
} catch (error) {
|
|
18415
|
+
this.logger?.error("Failed to get available commands", error);
|
|
18416
|
+
return [];
|
|
18417
|
+
}
|
|
18418
|
+
},
|
|
18349
18419
|
models: this.createModelsResource()
|
|
18350
18420
|
};
|
|
18351
18421
|
}
|
|
@@ -18412,6 +18482,154 @@ let AccountStatus = /* @__PURE__ */ function(AccountStatus) {
|
|
|
18412
18482
|
return AccountStatus;
|
|
18413
18483
|
}({});
|
|
18414
18484
|
|
|
18485
|
+
//#endregion
|
|
18486
|
+
//#region ../agent-provider/src/backend/service/oauth-repository-service.ts
|
|
18487
|
+
/**
|
|
18488
|
+
* OAuth Repository Service
|
|
18489
|
+
*
|
|
18490
|
+
* 封装 OAuth 连接器相关的仓库和分支操作
|
|
18491
|
+
*/
|
|
18492
|
+
/**
|
|
18493
|
+
* OAuth Repository Service
|
|
18494
|
+
*
|
|
18495
|
+
* 提供仓库和分支的查询操作
|
|
18496
|
+
*/
|
|
18497
|
+
var OAuthRepositoryService = class {
|
|
18498
|
+
/**
|
|
18499
|
+
* 获取仓库分支列表
|
|
18500
|
+
* API 端点: GET /console/as/connector/oauth/{name}/branches
|
|
18501
|
+
*
|
|
18502
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
18503
|
+
* @param params 平台特定的查询参数
|
|
18504
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
18505
|
+
* @param perPage 每页数量,最大100
|
|
18506
|
+
* @returns Promise<OauthBranch[]> 分支列表
|
|
18507
|
+
*
|
|
18508
|
+
* @example
|
|
18509
|
+
* ```typescript
|
|
18510
|
+
* // GitHub
|
|
18511
|
+
* const branches = await service.getBranches('github', {
|
|
18512
|
+
* owner: 'CodeBuddy-Official-Account',
|
|
18513
|
+
* repo: 'CodeBuddyIDE'
|
|
18514
|
+
* });
|
|
18515
|
+
*
|
|
18516
|
+
* // Gongfeng
|
|
18517
|
+
* const branches = await service.getBranches('gongfeng', {
|
|
18518
|
+
* project_id: '1611499'
|
|
18519
|
+
* });
|
|
18520
|
+
*
|
|
18521
|
+
* // CNB
|
|
18522
|
+
* const branches = await service.getBranches('cnb', {
|
|
18523
|
+
* repo: 'genie/genie-ide'
|
|
18524
|
+
* });
|
|
18525
|
+
* ```
|
|
18526
|
+
*/
|
|
18527
|
+
async getBranches(connector, params, page = 0, perPage = 100) {
|
|
18528
|
+
try {
|
|
18529
|
+
const url = `/console/as/connector/oauth/${connector}/branches?${this.buildBranchQueryParams(connector, params, page, perPage).toString()}`;
|
|
18530
|
+
console.log(`[OAuthRepositoryService] GET ${url}`);
|
|
18531
|
+
const apiResponse = await httpService.get(url);
|
|
18532
|
+
if (!apiResponse.data) {
|
|
18533
|
+
console.warn(`[OAuthRepositoryService] No data in branches response for ${connector}`);
|
|
18534
|
+
return [];
|
|
18535
|
+
}
|
|
18536
|
+
const branches = apiResponse.data.branches || [];
|
|
18537
|
+
console.log(`[OAuthRepositoryService] Retrieved ${branches.length} branches from ${connector}`);
|
|
18538
|
+
return branches;
|
|
18539
|
+
} catch (error) {
|
|
18540
|
+
console.error(`[OAuthRepositoryService] Failed to get branches from ${connector}:`, error);
|
|
18541
|
+
throw error;
|
|
18542
|
+
}
|
|
18543
|
+
}
|
|
18544
|
+
/**
|
|
18545
|
+
* 获取仓库列表
|
|
18546
|
+
* API 端点: GET /console/as/connector/oauth/{name}/repos
|
|
18547
|
+
*
|
|
18548
|
+
* Note: 由于工蜂原生支持的 Search 能力会匹配 path/name/description 部分,
|
|
18549
|
+
* 且不支持定制,不满足产品要求(只按 name 匹配),因此前端拉取全量数据后做筛选。
|
|
18550
|
+
*
|
|
18551
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
18552
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
18553
|
+
* - GitHub 只支持全量数据,必须传 0
|
|
18554
|
+
* - 工蜂和 CNB 依据前端逻辑而定
|
|
18555
|
+
* @param perPage 每页数量,最大100
|
|
18556
|
+
* @returns Promise<ListReposResponse> 仓库列表响应
|
|
18557
|
+
*
|
|
18558
|
+
* @example
|
|
18559
|
+
* ```typescript
|
|
18560
|
+
* // GitHub - 必须传 page=0 获取全量数据
|
|
18561
|
+
* const response = await service.getRepositories('github', 0, 100);
|
|
18562
|
+
* // response.github_repos 是 map: installation_id => repo[]
|
|
18563
|
+
*
|
|
18564
|
+
* // Gongfeng
|
|
18565
|
+
* const response = await service.getRepositories('gongfeng', 0, 100);
|
|
18566
|
+
* // response.gongfeng_repos 是数组
|
|
18567
|
+
*
|
|
18568
|
+
* // CNB
|
|
18569
|
+
* const response = await service.getRepositories('cnb', 0, 100);
|
|
18570
|
+
* // response.cnb_repos 是数组
|
|
18571
|
+
* ```
|
|
18572
|
+
*/
|
|
18573
|
+
async getRepositories(connector, page = 0, perPage = 100) {
|
|
18574
|
+
try {
|
|
18575
|
+
const queryParams = new URLSearchParams();
|
|
18576
|
+
queryParams.append("page", String(page));
|
|
18577
|
+
queryParams.append("per_page", String(Math.min(perPage, 100)));
|
|
18578
|
+
const url = `/console/as/connector/oauth/${connector}/repos?${queryParams.toString()}`;
|
|
18579
|
+
console.log(`[OAuthRepositoryService] GET ${url}`);
|
|
18580
|
+
const apiResponse = await httpService.get(url);
|
|
18581
|
+
if (!apiResponse.data) {
|
|
18582
|
+
console.warn(`[OAuthRepositoryService] No data in repos response for ${connector}`);
|
|
18583
|
+
return {};
|
|
18584
|
+
}
|
|
18585
|
+
const response = apiResponse.data;
|
|
18586
|
+
this.logRepositoryCounts(response);
|
|
18587
|
+
return response;
|
|
18588
|
+
} catch (error) {
|
|
18589
|
+
console.error(`[OAuthRepositoryService] Failed to get repos from ${connector}:`, error);
|
|
18590
|
+
throw error;
|
|
18591
|
+
}
|
|
18592
|
+
}
|
|
18593
|
+
/**
|
|
18594
|
+
* 构建分支查询参数
|
|
18595
|
+
*/
|
|
18596
|
+
buildBranchQueryParams(connector, params, page, perPage) {
|
|
18597
|
+
const queryParams = new URLSearchParams();
|
|
18598
|
+
queryParams.append("page", String(page));
|
|
18599
|
+
queryParams.append("per_page", String(Math.min(perPage, 100)));
|
|
18600
|
+
if (connector === "github") {
|
|
18601
|
+
const githubParams = params;
|
|
18602
|
+
if (!githubParams.owner || !githubParams.repo) throw new Error("GitHub requires owner and repo parameters");
|
|
18603
|
+
queryParams.append("owner", githubParams.owner);
|
|
18604
|
+
queryParams.append("repo", githubParams.repo);
|
|
18605
|
+
} else if (connector === "gongfeng") {
|
|
18606
|
+
const gongfengParams = params;
|
|
18607
|
+
if (!gongfengParams.project_id) throw new Error("Gongfeng requires project_id parameter");
|
|
18608
|
+
queryParams.append("project_id", gongfengParams.project_id);
|
|
18609
|
+
} else if (connector === "cnb") {
|
|
18610
|
+
const cnbParams = params;
|
|
18611
|
+
if (!cnbParams.repo) throw new Error("CNB requires repo parameter");
|
|
18612
|
+
queryParams.append("repo", cnbParams.repo);
|
|
18613
|
+
} else throw new Error(`Unknown connector: ${connector}`);
|
|
18614
|
+
return queryParams;
|
|
18615
|
+
}
|
|
18616
|
+
/**
|
|
18617
|
+
* 记录仓库数量日志
|
|
18618
|
+
*/
|
|
18619
|
+
logRepositoryCounts(response) {
|
|
18620
|
+
if (response.github_repos) {
|
|
18621
|
+
const totalCount = Object.values(response.github_repos).reduce((sum, repos) => sum + repos.length, 0);
|
|
18622
|
+
console.log(`[OAuthRepositoryService] Retrieved ${totalCount} GitHub repos across ${Object.keys(response.github_repos).length} installations`);
|
|
18623
|
+
}
|
|
18624
|
+
if (response.gongfeng_repos) console.log(`[OAuthRepositoryService] Retrieved ${response.gongfeng_repos.length} Gongfeng repos`);
|
|
18625
|
+
if (response.cnb_repos) console.log(`[OAuthRepositoryService] Retrieved ${response.cnb_repos.length} CNB repos`);
|
|
18626
|
+
}
|
|
18627
|
+
};
|
|
18628
|
+
/**
|
|
18629
|
+
* OAuth Repository Service 单例实例
|
|
18630
|
+
*/
|
|
18631
|
+
const oauthRepositoryService = new OAuthRepositoryService();
|
|
18632
|
+
|
|
18415
18633
|
//#endregion
|
|
18416
18634
|
//#region ../agent-provider/src/backend/backend-provider.ts
|
|
18417
18635
|
/**
|
|
@@ -18420,27 +18638,29 @@ let AccountStatus = /* @__PURE__ */ function(AccountStatus) {
|
|
|
18420
18638
|
* 封装与后端 API 的 HTTP 通信
|
|
18421
18639
|
*/
|
|
18422
18640
|
/**
|
|
18423
|
-
*
|
|
18424
|
-
*
|
|
18641
|
+
* 判断当前账号是否是 SSO 账号
|
|
18642
|
+
* 通过 account.accountType === 'sso' 来判断,这种不行,因为未登录之前account 为空
|
|
18425
18643
|
*/
|
|
18426
18644
|
const isSSODomain = () => {
|
|
18427
18645
|
const { hostname } = window.location;
|
|
18428
18646
|
return hostname.includes(".sso.copilot") || hostname.includes("sso.codebuddy.cn") || hostname.includes(".sso.copilot-staging") || hostname.includes(".staging-sso.codebuddy.cn");
|
|
18429
18647
|
};
|
|
18430
18648
|
/**
|
|
18431
|
-
*
|
|
18432
|
-
* - SSO
|
|
18433
|
-
* - 非 SSO
|
|
18649
|
+
* 根据路径获取完整 URL
|
|
18650
|
+
* - SSO 账号需要跳转到对应的预发/生产域名
|
|
18651
|
+
* - 非 SSO 账号直接使用当前域名
|
|
18652
|
+
* @param path 路径,如 '/login'、'/logout'、'/home' 等
|
|
18653
|
+
* @returns 完整的 URL 地址
|
|
18434
18654
|
*/
|
|
18435
|
-
const
|
|
18655
|
+
const getFullUrl = (path) => {
|
|
18436
18656
|
const { hostname, protocol } = window.location;
|
|
18437
18657
|
if (isSSODomain()) {
|
|
18438
18658
|
const isCodebuddy = hostname.includes("codebuddy.cn");
|
|
18439
18659
|
const isStaging = hostname.includes("staging");
|
|
18440
|
-
if (isCodebuddy) return isStaging ? `${protocol}//staging.codebuddy.cn
|
|
18441
|
-
else return isStaging ? `${protocol}//staging-copilot.tencent.com
|
|
18660
|
+
if (isCodebuddy) return isStaging ? `${protocol}//staging.codebuddy.cn${path}` : `${protocol}//www.codebuddy.cn${path}`;
|
|
18661
|
+
else return isStaging ? `${protocol}//staging-copilot.tencent.com${path}` : `${protocol}//copilot.tencent.com${path}`;
|
|
18442
18662
|
}
|
|
18443
|
-
return `${window.location.origin}
|
|
18663
|
+
return `${window.location.origin}${path}`;
|
|
18444
18664
|
};
|
|
18445
18665
|
/** 获取当前域名的账号选择页面 URL */
|
|
18446
18666
|
const getSelectAccountUrl = () => `${window.location.origin}/login/select`;
|
|
@@ -18528,7 +18748,7 @@ var BackendProvider = class {
|
|
|
18528
18748
|
return account;
|
|
18529
18749
|
}
|
|
18530
18750
|
const redirectUrl = encodeURIComponent(window.location.href);
|
|
18531
|
-
window.location.href = `${getSelectAccountUrl()}?platform=
|
|
18751
|
+
window.location.href = `${getSelectAccountUrl()}?platform=agents&state=0&redirect_uri=${redirectUrl}`;
|
|
18532
18752
|
accountService.setAccount(null);
|
|
18533
18753
|
return null;
|
|
18534
18754
|
} catch (error) {
|
|
@@ -18551,7 +18771,8 @@ var BackendProvider = class {
|
|
|
18551
18771
|
activeStatus: connector.active_status,
|
|
18552
18772
|
displayName: connector.display_name,
|
|
18553
18773
|
oauthClientId: connector.oauth_client_id,
|
|
18554
|
-
oauthRedirectUrl: connector.oauth_redirect_url
|
|
18774
|
+
oauthRedirectUrl: connector.oauth_redirect_url,
|
|
18775
|
+
oauthAppName: connector.oauth_app_name
|
|
18555
18776
|
})) };
|
|
18556
18777
|
}
|
|
18557
18778
|
throw result;
|
|
@@ -18633,7 +18854,8 @@ var BackendProvider = class {
|
|
|
18633
18854
|
connectStatus: connector.connect_status,
|
|
18634
18855
|
displayName: connector.display_name,
|
|
18635
18856
|
oauthClientId: connector.oauth_client_id,
|
|
18636
|
-
oauthRedirectUrl: connector.oauth_redirect_url
|
|
18857
|
+
oauthRedirectUrl: connector.oauth_redirect_url,
|
|
18858
|
+
oauthAppName: connector.oauth_app_name
|
|
18637
18859
|
})) };
|
|
18638
18860
|
}
|
|
18639
18861
|
throw result;
|
|
@@ -18890,7 +19112,7 @@ var BackendProvider = class {
|
|
|
18890
19112
|
*/
|
|
18891
19113
|
async login() {
|
|
18892
19114
|
const redirectUrl = encodeURIComponent(window.location.href);
|
|
18893
|
-
window.location.href = `${
|
|
19115
|
+
window.location.href = `${getFullUrl("/login")}?platform=agents&state=0&redirect_uri=${redirectUrl}`;
|
|
18894
19116
|
}
|
|
18895
19117
|
/**
|
|
18896
19118
|
* 登出账号
|
|
@@ -18953,6 +19175,52 @@ var BackendProvider = class {
|
|
|
18953
19175
|
return null;
|
|
18954
19176
|
}
|
|
18955
19177
|
}
|
|
19178
|
+
/**
|
|
19179
|
+
* 刷新 Token
|
|
19180
|
+
* 通过调用 getAccount 刷新 cookie,适用于 Cloud 场景下页面切换回来时刷新登录态
|
|
19181
|
+
* @returns Promise<Account | null> 刷新后的账号信息
|
|
19182
|
+
*/
|
|
19183
|
+
async refreshToken() {
|
|
19184
|
+
console.log("[BackendProvider] Refreshing token...");
|
|
19185
|
+
try {
|
|
19186
|
+
const account = await this.getAccount();
|
|
19187
|
+
console.log("[BackendProvider] Token refreshed, account:", account?.uid);
|
|
19188
|
+
return account;
|
|
19189
|
+
} catch (error) {
|
|
19190
|
+
console.error("[BackendProvider] refreshToken failed:", error);
|
|
19191
|
+
return null;
|
|
19192
|
+
}
|
|
19193
|
+
}
|
|
19194
|
+
/**
|
|
19195
|
+
* 获取仓库分支列表
|
|
19196
|
+
* API 端点: GET /console/as/connector/oauth/{name}/branches
|
|
19197
|
+
*
|
|
19198
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
19199
|
+
* @param params 平台特定的查询参数
|
|
19200
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
19201
|
+
* @param perPage 每页数量,最大100
|
|
19202
|
+
* @returns Promise<OauthBranch[]> 分支列表
|
|
19203
|
+
*/
|
|
19204
|
+
async getBranches(connector, params, page = 0, perPage = 100) {
|
|
19205
|
+
return oauthRepositoryService.getBranches(connector, params, page, perPage);
|
|
19206
|
+
}
|
|
19207
|
+
/**
|
|
19208
|
+
* 获取仓库列表
|
|
19209
|
+
* API 端点: GET /console/as/connector/oauth/{name}/repos
|
|
19210
|
+
*
|
|
19211
|
+
* Note: 由于工蜂原生支持的 Search 能力会匹配 path/name/description 部分,
|
|
19212
|
+
* 且不支持定制,不满足产品要求(只按 name 匹配),因此前端拉取全量数据后做筛选。
|
|
19213
|
+
*
|
|
19214
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
19215
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
19216
|
+
* - GitHub 只支持全量数据,必须传 0
|
|
19217
|
+
* - 工蜂和 CNB 依据前端逻辑而定
|
|
19218
|
+
* @param perPage 每页数量,最大100
|
|
19219
|
+
* @returns Promise<ListReposResponse> 仓库列表响应
|
|
19220
|
+
*/
|
|
19221
|
+
async getRepositories(connector, page = 0, perPage = 100) {
|
|
19222
|
+
return oauthRepositoryService.getRepositories(connector, page, perPage);
|
|
19223
|
+
}
|
|
18956
19224
|
};
|
|
18957
19225
|
/**
|
|
18958
19226
|
* 创建 BackendProvider 实例
|
|
@@ -18992,6 +19260,7 @@ const BACKEND_REQUEST_TYPES = {
|
|
|
18992
19260
|
GET_FILE: "backend:get-file",
|
|
18993
19261
|
RELOAD_WINDOW: "backend:reload-window",
|
|
18994
19262
|
CLOSE_AGENT_MANAGER: "backend:close-agent-manager",
|
|
19263
|
+
OPEN_EXTERNAL: "backend:open-external",
|
|
18995
19264
|
BATCH_TOGGLE_PLUGINS: "backend:batch-toggle-plugins",
|
|
18996
19265
|
GET_SUPPORT_SCENES: "backend:get-support-scenes"
|
|
18997
19266
|
};
|
|
@@ -19287,6 +19556,20 @@ var IPCBackendProvider = class {
|
|
|
19287
19556
|
}
|
|
19288
19557
|
}
|
|
19289
19558
|
/**
|
|
19559
|
+
* 在外部浏览器中打开链接
|
|
19560
|
+
* IDE 环境: 通过 IPC 通知 IDE 使用 vscode.env.openExternal 打开 URL
|
|
19561
|
+
* @param url 要打开的 URL
|
|
19562
|
+
*/
|
|
19563
|
+
async openExternal(url) {
|
|
19564
|
+
this.log("Opening external URL via IPC:", url);
|
|
19565
|
+
try {
|
|
19566
|
+
await this.sendBackendRequest(BACKEND_REQUEST_TYPES.OPEN_EXTERNAL, { url });
|
|
19567
|
+
} catch (error) {
|
|
19568
|
+
this.log("Open external request failed:", error);
|
|
19569
|
+
throw error;
|
|
19570
|
+
}
|
|
19571
|
+
}
|
|
19572
|
+
/**
|
|
19290
19573
|
* 批量切换插件状态
|
|
19291
19574
|
* IDE 环境: 通过 IPC 调用 Extension Host 的 PluginService
|
|
19292
19575
|
*/
|