@tencent-ai/cloud-agent-sdk 0.2.11 → 0.2.12-next.21a87f3.20260203
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 +385 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +462 -129
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +462 -129
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +385 -68
- package/dist/index.mjs.map +1 -1
- package/dist/tencent-ai-cloud-agent-sdk-0.2.12-next.21a87f3.20260203.tgz +0 -0
- package/package.json +4 -3
- package/dist/tencent-ai-cloud-agent-sdk-0.2.11.tgz +0 -0
package/dist/index.cjs
CHANGED
|
@@ -1993,9 +1993,7 @@ var StreamableHttpClient = class {
|
|
|
1993
1993
|
});
|
|
1994
1994
|
await this.handleExtNotification(method, params);
|
|
1995
1995
|
},
|
|
1996
|
-
extMethod: async (method, params) =>
|
|
1997
|
-
return await this.handleExtMethod(method, params);
|
|
1998
|
-
}
|
|
1996
|
+
extMethod: async (method, params) => this.handleExtMethod(method, params)
|
|
1999
1997
|
};
|
|
2000
1998
|
}
|
|
2001
1999
|
/**
|
|
@@ -2215,12 +2213,22 @@ var StreamableHttpClient = class {
|
|
|
2215
2213
|
await this.extensionManager.handleNotification(method, params);
|
|
2216
2214
|
}
|
|
2217
2215
|
async handleExtMethod(method, params) {
|
|
2218
|
-
if (method === ExtensionMethod.QUESTION)
|
|
2216
|
+
if (method === ExtensionMethod.QUESTION) {
|
|
2217
|
+
const response = await this.questionManager.handleRequest(params);
|
|
2218
|
+
if (response.outcome === "submitted" && response.answers) return { outcome: {
|
|
2219
|
+
outcome: "submitted",
|
|
2220
|
+
data: { answers: response.answers }
|
|
2221
|
+
} };
|
|
2222
|
+
else return { outcome: {
|
|
2223
|
+
outcome: "cancelled",
|
|
2224
|
+
reason: response.reason
|
|
2225
|
+
} };
|
|
2226
|
+
}
|
|
2219
2227
|
this.options.logger?.warn(`Unknown extension method: ${method}`);
|
|
2220
|
-
return {
|
|
2228
|
+
return { outcome: {
|
|
2221
2229
|
outcome: "cancelled",
|
|
2222
2230
|
reason: "unknown method"
|
|
2223
|
-
};
|
|
2231
|
+
} };
|
|
2224
2232
|
}
|
|
2225
2233
|
ensureInitialized(operation) {
|
|
2226
2234
|
if (this.state !== "initialized") throw new InvalidStateError(operation, this.state, ["initialized"]);
|
|
@@ -2403,7 +2411,7 @@ var CloudAgentConnection = class {
|
|
|
2403
2411
|
}
|
|
2404
2412
|
async createSession(params) {
|
|
2405
2413
|
return {
|
|
2406
|
-
...await this.client.
|
|
2414
|
+
...await this.client.createSession(this.cwd),
|
|
2407
2415
|
sessionId: this.agentId
|
|
2408
2416
|
};
|
|
2409
2417
|
}
|
|
@@ -16325,6 +16333,11 @@ var AccountService = class {
|
|
|
16325
16333
|
* 导出单例实例
|
|
16326
16334
|
*/
|
|
16327
16335
|
const accountService = new AccountService();
|
|
16336
|
+
/**
|
|
16337
|
+
* 暴露给全局,供 Agent Manager 直接调用 setAccount 刷新 Widget 状态
|
|
16338
|
+
* 这是为了解决 IDE 环境中 IPC 事件无法直接触发 Widget 账号刷新的问题
|
|
16339
|
+
*/
|
|
16340
|
+
if (typeof window !== "undefined") window.__genieAccountService = accountService;
|
|
16328
16341
|
|
|
16329
16342
|
//#endregion
|
|
16330
16343
|
//#region ../agent-provider/src/common/utils/concurrency.ts
|
|
@@ -16932,13 +16945,19 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
16932
16945
|
/**
|
|
16933
16946
|
* Create a new conversation
|
|
16934
16947
|
* POST {endpoint}/console/as/conversations
|
|
16948
|
+
* @param params - Optional session params containing _meta with tags
|
|
16935
16949
|
*/
|
|
16936
|
-
async create() {
|
|
16950
|
+
async create(params) {
|
|
16937
16951
|
try {
|
|
16938
|
-
const
|
|
16952
|
+
const tagsObj = (params?._meta?.["codebuddy.ai"])?.tags;
|
|
16953
|
+
const tagsArray = tagsObj ? Object.entries(tagsObj).map(([key, value]) => `${key}:${value}`) : void 0;
|
|
16954
|
+
const createPayload = {
|
|
16939
16955
|
prompt: "",
|
|
16940
|
-
model: "deepseek-r1"
|
|
16941
|
-
|
|
16956
|
+
model: "deepseek-r1",
|
|
16957
|
+
...tagsArray && tagsArray.length > 0 ? { tags: tagsArray } : {}
|
|
16958
|
+
};
|
|
16959
|
+
console.log("[CloudAgentProvider] Creating conversation with payload:", createPayload);
|
|
16960
|
+
const apiResponse = await httpService.post("/console/as/conversations/", createPayload);
|
|
16942
16961
|
if (!apiResponse.data) throw new Error("No data in API response");
|
|
16943
16962
|
this.logger?.info(`Created conversation: ${apiResponse.data.id}`);
|
|
16944
16963
|
return apiResponse.data.id;
|
|
@@ -17299,6 +17318,28 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17299
17318
|
}
|
|
17300
17319
|
}
|
|
17301
17320
|
}
|
|
17321
|
+
/**
|
|
17322
|
+
* 获取支持的场景列表
|
|
17323
|
+
* API 端点: GET /console/as/support/scenes
|
|
17324
|
+
* 用于 Welcome 页面的 QuickActions 快捷操作
|
|
17325
|
+
*
|
|
17326
|
+
* @returns Promise<SupportScene[]> 支持的场景列表
|
|
17327
|
+
*/
|
|
17328
|
+
async getSupportScenes() {
|
|
17329
|
+
try {
|
|
17330
|
+
const apiResponse = await httpService.get("/console/as/support/scenes");
|
|
17331
|
+
if (!apiResponse.data) {
|
|
17332
|
+
this.logger?.warn("[CloudAgentProvider] No data in support scenes response");
|
|
17333
|
+
return [];
|
|
17334
|
+
}
|
|
17335
|
+
const scenes = apiResponse.data.scenes || [];
|
|
17336
|
+
this.logger?.info(`[CloudAgentProvider] Retrieved ${scenes.length} support scenes`);
|
|
17337
|
+
return scenes;
|
|
17338
|
+
} catch (error) {
|
|
17339
|
+
this.logger?.error("[CloudAgentProvider] Failed to get support scenes:", error);
|
|
17340
|
+
return [];
|
|
17341
|
+
}
|
|
17342
|
+
}
|
|
17302
17343
|
toAgentState(data) {
|
|
17303
17344
|
const status = data.sessionStatus || data.status;
|
|
17304
17345
|
return {
|
|
@@ -17613,8 +17654,8 @@ var ActiveSessionImpl = class {
|
|
|
17613
17654
|
* await session.setMode('architect');
|
|
17614
17655
|
* ```
|
|
17615
17656
|
*/
|
|
17616
|
-
async setMode(modeId) {
|
|
17617
|
-
if (this._availableModes) {
|
|
17657
|
+
async setMode(modeId, skipAvailableChecker) {
|
|
17658
|
+
if (this._availableModes && !skipAvailableChecker) {
|
|
17618
17659
|
if (!this._availableModes.some((m) => m.id === modeId)) {
|
|
17619
17660
|
const availableIds = this._availableModes.map((m) => m.id).join(", ");
|
|
17620
17661
|
throw new Error(`Invalid modeId: "${modeId}". Available modes: ${availableIds}`);
|
|
@@ -17805,14 +17846,6 @@ var ActiveSessionImpl = class {
|
|
|
17805
17846
|
//#endregion
|
|
17806
17847
|
//#region ../agent-provider/src/common/client/session-manager.ts
|
|
17807
17848
|
/**
|
|
17808
|
-
* SessionManager - Manages session lifecycle and connections
|
|
17809
|
-
*
|
|
17810
|
-
* Provides the core implementation for session-centric API operations:
|
|
17811
|
-
* - list() - Lists sessions (mapped from agents)
|
|
17812
|
-
* - createSession() - Creates new session (auto-creates agent)
|
|
17813
|
-
* - loadSession() - Loads existing session (finds agent by sessionId)
|
|
17814
|
-
*/
|
|
17815
|
-
/**
|
|
17816
17849
|
* SessionManager - Session lifecycle management
|
|
17817
17850
|
*
|
|
17818
17851
|
* This class manages the relationship between sessions and agents.
|
|
@@ -17908,14 +17941,8 @@ var SessionManager = class {
|
|
|
17908
17941
|
connectionInfo
|
|
17909
17942
|
});
|
|
17910
17943
|
session.setModes(response.modes?.availableModes, response.modes?.currentModeId);
|
|
17911
|
-
|
|
17912
|
-
|
|
17913
|
-
id: m.modelId,
|
|
17914
|
-
name: m.name,
|
|
17915
|
-
description: m.description ?? void 0
|
|
17916
|
-
}));
|
|
17917
|
-
session.setModels(localModels, response.models?.currentModelId);
|
|
17918
|
-
}
|
|
17944
|
+
const availableModels = this.extractAvailableModels(response);
|
|
17945
|
+
if (availableModels) session.setModels(availableModels, response.models?.currentModelId);
|
|
17919
17946
|
this.logger?.info(`Session created: ${response.sessionId}`);
|
|
17920
17947
|
return session;
|
|
17921
17948
|
}
|
|
@@ -17951,17 +17978,31 @@ var SessionManager = class {
|
|
|
17951
17978
|
mcpServers: params.mcpServers
|
|
17952
17979
|
});
|
|
17953
17980
|
session.setModes(response.modes?.availableModes, response.modes?.currentModeId);
|
|
17954
|
-
|
|
17955
|
-
|
|
17956
|
-
id: m.modelId,
|
|
17957
|
-
name: m.name,
|
|
17958
|
-
description: m.description ?? void 0
|
|
17959
|
-
}));
|
|
17960
|
-
session.setModels(localModels, response.models?.currentModelId);
|
|
17961
|
-
}
|
|
17981
|
+
const availableModels = this.extractAvailableModels(response);
|
|
17982
|
+
if (availableModels) session.setModels(availableModels, response.models?.currentModelId);
|
|
17962
17983
|
this.logger?.info(`Session loaded: ${params.sessionId}`);
|
|
17963
17984
|
return session;
|
|
17964
17985
|
}
|
|
17986
|
+
/**
|
|
17987
|
+
* 从 ACP response 中提取可用模型列表
|
|
17988
|
+
*
|
|
17989
|
+
* 优先级:
|
|
17990
|
+
* 1. response.models._meta?.['codebuddy.ai']?.availableModels - 包含完整的模型信息(字段名为 'id')
|
|
17991
|
+
* 2. response.models?.availableModels - 只包含基本信息(字段名为 'modelId')
|
|
17992
|
+
* 3. undefined - 都没有时返回 undefined
|
|
17993
|
+
*
|
|
17994
|
+
* @param response - ACP 响应对象
|
|
17995
|
+
* @returns ModelInfo[] | undefined
|
|
17996
|
+
*/
|
|
17997
|
+
extractAvailableModels(response) {
|
|
17998
|
+
const metaModels = (response.models?._meta?.["codebuddy.ai"])?.availableModels;
|
|
17999
|
+
if (metaModels && Array.isArray(metaModels) && metaModels.length > 0) return metaModels;
|
|
18000
|
+
const availableModels = response.models?.availableModels;
|
|
18001
|
+
if (availableModels && Array.isArray(availableModels) && availableModels.length > 0) return availableModels.map((model) => ({
|
|
18002
|
+
...model,
|
|
18003
|
+
...model._meta?.["codebuddy.ai"] || {}
|
|
18004
|
+
}));
|
|
18005
|
+
}
|
|
17965
18006
|
};
|
|
17966
18007
|
|
|
17967
18008
|
//#endregion
|
|
@@ -18234,6 +18275,28 @@ var AgentClient = class {
|
|
|
18234
18275
|
};
|
|
18235
18276
|
}
|
|
18236
18277
|
},
|
|
18278
|
+
getSubagentList: async (params) => {
|
|
18279
|
+
try {
|
|
18280
|
+
if (this.provider && this.provider.getSubagentList) {
|
|
18281
|
+
const result = await this.provider.getSubagentList(params);
|
|
18282
|
+
this.logger?.info("Subagent list retrieved", {
|
|
18283
|
+
resultCount: result.results.length,
|
|
18284
|
+
hasError: !!result.error
|
|
18285
|
+
});
|
|
18286
|
+
return result;
|
|
18287
|
+
}
|
|
18288
|
+
return {
|
|
18289
|
+
results: [],
|
|
18290
|
+
error: "Provider does not support getSubagentList"
|
|
18291
|
+
};
|
|
18292
|
+
} catch (error) {
|
|
18293
|
+
this.logger?.error("Failed to get subagent list", error);
|
|
18294
|
+
return {
|
|
18295
|
+
results: [],
|
|
18296
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
18297
|
+
};
|
|
18298
|
+
}
|
|
18299
|
+
},
|
|
18237
18300
|
batchTogglePlugins: async (request) => {
|
|
18238
18301
|
try {
|
|
18239
18302
|
if (this.provider && this.provider.batchTogglePlugins) {
|
|
@@ -18278,10 +18341,10 @@ var AgentClient = class {
|
|
|
18278
18341
|
return [];
|
|
18279
18342
|
}
|
|
18280
18343
|
},
|
|
18281
|
-
installPlugins: async (pluginNames, marketplaceName, installScope) => {
|
|
18344
|
+
installPlugins: async (pluginNames, marketplaceName, installScope, marketplaceSource) => {
|
|
18282
18345
|
try {
|
|
18283
18346
|
if (this.provider && "installPlugins" in this.provider && typeof this.provider.installPlugins === "function") {
|
|
18284
|
-
const result = await this.provider.installPlugins(pluginNames, marketplaceName, installScope);
|
|
18347
|
+
const result = await this.provider.installPlugins(pluginNames, marketplaceName, installScope, marketplaceSource);
|
|
18285
18348
|
this.logger?.info("Install plugins", {
|
|
18286
18349
|
pluginNames,
|
|
18287
18350
|
marketplaceName,
|
|
@@ -18302,17 +18365,34 @@ var AgentClient = class {
|
|
|
18302
18365
|
};
|
|
18303
18366
|
}
|
|
18304
18367
|
},
|
|
18305
|
-
|
|
18368
|
+
getSupportScenes: async () => {
|
|
18369
|
+
try {
|
|
18370
|
+
if (this.provider && "getSupportScenes" in this.provider && typeof this.provider.getSupportScenes === "function") {
|
|
18371
|
+
const result = await this.provider.getSupportScenes();
|
|
18372
|
+
this.logger?.info("Got support scenes", { count: result?.length ?? 0 });
|
|
18373
|
+
return result;
|
|
18374
|
+
}
|
|
18375
|
+
this.logger?.warn("Provider does not support getSupportScenes");
|
|
18376
|
+
return [];
|
|
18377
|
+
} catch (error) {
|
|
18378
|
+
this.logger?.error("Failed to get support scenes", error);
|
|
18379
|
+
return [];
|
|
18380
|
+
}
|
|
18381
|
+
},
|
|
18382
|
+
getAvailableCommands: async (sessionId) => {
|
|
18306
18383
|
try {
|
|
18307
|
-
if (this.provider && "
|
|
18308
|
-
const result = await this.provider.
|
|
18309
|
-
this.logger?.info("Got
|
|
18384
|
+
if (this.provider && "getAvailableCommands" in this.provider && typeof this.provider.getAvailableCommands === "function") {
|
|
18385
|
+
const result = await this.provider.getAvailableCommands(sessionId);
|
|
18386
|
+
this.logger?.info("Got available commands from provider", {
|
|
18387
|
+
sessionId: sessionId ?? "(default)",
|
|
18388
|
+
count: result?.length ?? 0
|
|
18389
|
+
});
|
|
18310
18390
|
return result;
|
|
18311
18391
|
}
|
|
18312
|
-
this.logger?.warn("Provider does not support
|
|
18392
|
+
this.logger?.warn("Provider does not support getAvailableCommands", { sessionId });
|
|
18313
18393
|
return [];
|
|
18314
18394
|
} catch (error) {
|
|
18315
|
-
this.logger?.error("Failed to get
|
|
18395
|
+
this.logger?.error("Failed to get available commands", error);
|
|
18316
18396
|
return [];
|
|
18317
18397
|
}
|
|
18318
18398
|
},
|
|
@@ -18382,6 +18462,154 @@ let AccountStatus = /* @__PURE__ */ function(AccountStatus) {
|
|
|
18382
18462
|
return AccountStatus;
|
|
18383
18463
|
}({});
|
|
18384
18464
|
|
|
18465
|
+
//#endregion
|
|
18466
|
+
//#region ../agent-provider/src/backend/service/oauth-repository-service.ts
|
|
18467
|
+
/**
|
|
18468
|
+
* OAuth Repository Service
|
|
18469
|
+
*
|
|
18470
|
+
* 封装 OAuth 连接器相关的仓库和分支操作
|
|
18471
|
+
*/
|
|
18472
|
+
/**
|
|
18473
|
+
* OAuth Repository Service
|
|
18474
|
+
*
|
|
18475
|
+
* 提供仓库和分支的查询操作
|
|
18476
|
+
*/
|
|
18477
|
+
var OAuthRepositoryService = class {
|
|
18478
|
+
/**
|
|
18479
|
+
* 获取仓库分支列表
|
|
18480
|
+
* API 端点: GET /console/as/connector/oauth/{name}/branches
|
|
18481
|
+
*
|
|
18482
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
18483
|
+
* @param params 平台特定的查询参数
|
|
18484
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
18485
|
+
* @param perPage 每页数量,最大100
|
|
18486
|
+
* @returns Promise<OauthBranch[]> 分支列表
|
|
18487
|
+
*
|
|
18488
|
+
* @example
|
|
18489
|
+
* ```typescript
|
|
18490
|
+
* // GitHub
|
|
18491
|
+
* const branches = await service.getBranches('github', {
|
|
18492
|
+
* owner: 'CodeBuddy-Official-Account',
|
|
18493
|
+
* repo: 'CodeBuddyIDE'
|
|
18494
|
+
* });
|
|
18495
|
+
*
|
|
18496
|
+
* // Gongfeng
|
|
18497
|
+
* const branches = await service.getBranches('gongfeng', {
|
|
18498
|
+
* project_id: '1611499'
|
|
18499
|
+
* });
|
|
18500
|
+
*
|
|
18501
|
+
* // CNB
|
|
18502
|
+
* const branches = await service.getBranches('cnb', {
|
|
18503
|
+
* repo: 'genie/genie-ide'
|
|
18504
|
+
* });
|
|
18505
|
+
* ```
|
|
18506
|
+
*/
|
|
18507
|
+
async getBranches(connector, params, page = 0, perPage = 100) {
|
|
18508
|
+
try {
|
|
18509
|
+
const url = `/console/as/connector/oauth/${connector}/branches?${this.buildBranchQueryParams(connector, params, page, perPage).toString()}`;
|
|
18510
|
+
console.log(`[OAuthRepositoryService] GET ${url}`);
|
|
18511
|
+
const apiResponse = await httpService.get(url);
|
|
18512
|
+
if (!apiResponse.data) {
|
|
18513
|
+
console.warn(`[OAuthRepositoryService] No data in branches response for ${connector}`);
|
|
18514
|
+
return [];
|
|
18515
|
+
}
|
|
18516
|
+
const branches = apiResponse.data.branches || [];
|
|
18517
|
+
console.log(`[OAuthRepositoryService] Retrieved ${branches.length} branches from ${connector}`);
|
|
18518
|
+
return branches;
|
|
18519
|
+
} catch (error) {
|
|
18520
|
+
console.error(`[OAuthRepositoryService] Failed to get branches from ${connector}:`, error);
|
|
18521
|
+
throw error;
|
|
18522
|
+
}
|
|
18523
|
+
}
|
|
18524
|
+
/**
|
|
18525
|
+
* 获取仓库列表
|
|
18526
|
+
* API 端点: GET /console/as/connector/oauth/{name}/repos
|
|
18527
|
+
*
|
|
18528
|
+
* Note: 由于工蜂原生支持的 Search 能力会匹配 path/name/description 部分,
|
|
18529
|
+
* 且不支持定制,不满足产品要求(只按 name 匹配),因此前端拉取全量数据后做筛选。
|
|
18530
|
+
*
|
|
18531
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
18532
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
18533
|
+
* - GitHub 只支持全量数据,必须传 0
|
|
18534
|
+
* - 工蜂和 CNB 依据前端逻辑而定
|
|
18535
|
+
* @param perPage 每页数量,最大100
|
|
18536
|
+
* @returns Promise<ListReposResponse> 仓库列表响应
|
|
18537
|
+
*
|
|
18538
|
+
* @example
|
|
18539
|
+
* ```typescript
|
|
18540
|
+
* // GitHub - 必须传 page=0 获取全量数据
|
|
18541
|
+
* const response = await service.getRepositories('github', 0, 100);
|
|
18542
|
+
* // response.github_repos 是 map: installation_id => repo[]
|
|
18543
|
+
*
|
|
18544
|
+
* // Gongfeng
|
|
18545
|
+
* const response = await service.getRepositories('gongfeng', 0, 100);
|
|
18546
|
+
* // response.gongfeng_repos 是数组
|
|
18547
|
+
*
|
|
18548
|
+
* // CNB
|
|
18549
|
+
* const response = await service.getRepositories('cnb', 0, 100);
|
|
18550
|
+
* // response.cnb_repos 是数组
|
|
18551
|
+
* ```
|
|
18552
|
+
*/
|
|
18553
|
+
async getRepositories(connector, page = 0, perPage = 100) {
|
|
18554
|
+
try {
|
|
18555
|
+
const queryParams = new URLSearchParams();
|
|
18556
|
+
queryParams.append("page", String(page));
|
|
18557
|
+
queryParams.append("per_page", String(Math.min(perPage, 100)));
|
|
18558
|
+
const url = `/console/as/connector/oauth/${connector}/repos?${queryParams.toString()}`;
|
|
18559
|
+
console.log(`[OAuthRepositoryService] GET ${url}`);
|
|
18560
|
+
const apiResponse = await httpService.get(url);
|
|
18561
|
+
if (!apiResponse.data) {
|
|
18562
|
+
console.warn(`[OAuthRepositoryService] No data in repos response for ${connector}`);
|
|
18563
|
+
return {};
|
|
18564
|
+
}
|
|
18565
|
+
const response = apiResponse.data;
|
|
18566
|
+
this.logRepositoryCounts(response);
|
|
18567
|
+
return response;
|
|
18568
|
+
} catch (error) {
|
|
18569
|
+
console.error(`[OAuthRepositoryService] Failed to get repos from ${connector}:`, error);
|
|
18570
|
+
throw error;
|
|
18571
|
+
}
|
|
18572
|
+
}
|
|
18573
|
+
/**
|
|
18574
|
+
* 构建分支查询参数
|
|
18575
|
+
*/
|
|
18576
|
+
buildBranchQueryParams(connector, params, page, perPage) {
|
|
18577
|
+
const queryParams = new URLSearchParams();
|
|
18578
|
+
queryParams.append("page", String(page));
|
|
18579
|
+
queryParams.append("per_page", String(Math.min(perPage, 100)));
|
|
18580
|
+
if (connector === "github") {
|
|
18581
|
+
const githubParams = params;
|
|
18582
|
+
if (!githubParams.owner || !githubParams.repo) throw new Error("GitHub requires owner and repo parameters");
|
|
18583
|
+
queryParams.append("owner", githubParams.owner);
|
|
18584
|
+
queryParams.append("repo", githubParams.repo);
|
|
18585
|
+
} else if (connector === "gongfeng") {
|
|
18586
|
+
const gongfengParams = params;
|
|
18587
|
+
if (!gongfengParams.project_id) throw new Error("Gongfeng requires project_id parameter");
|
|
18588
|
+
queryParams.append("project_id", gongfengParams.project_id);
|
|
18589
|
+
} else if (connector === "cnb") {
|
|
18590
|
+
const cnbParams = params;
|
|
18591
|
+
if (!cnbParams.repo) throw new Error("CNB requires repo parameter");
|
|
18592
|
+
queryParams.append("repo", cnbParams.repo);
|
|
18593
|
+
} else throw new Error(`Unknown connector: ${connector}`);
|
|
18594
|
+
return queryParams;
|
|
18595
|
+
}
|
|
18596
|
+
/**
|
|
18597
|
+
* 记录仓库数量日志
|
|
18598
|
+
*/
|
|
18599
|
+
logRepositoryCounts(response) {
|
|
18600
|
+
if (response.github_repos) {
|
|
18601
|
+
const totalCount = Object.values(response.github_repos).reduce((sum, repos) => sum + repos.length, 0);
|
|
18602
|
+
console.log(`[OAuthRepositoryService] Retrieved ${totalCount} GitHub repos across ${Object.keys(response.github_repos).length} installations`);
|
|
18603
|
+
}
|
|
18604
|
+
if (response.gongfeng_repos) console.log(`[OAuthRepositoryService] Retrieved ${response.gongfeng_repos.length} Gongfeng repos`);
|
|
18605
|
+
if (response.cnb_repos) console.log(`[OAuthRepositoryService] Retrieved ${response.cnb_repos.length} CNB repos`);
|
|
18606
|
+
}
|
|
18607
|
+
};
|
|
18608
|
+
/**
|
|
18609
|
+
* OAuth Repository Service 单例实例
|
|
18610
|
+
*/
|
|
18611
|
+
const oauthRepositoryService = new OAuthRepositoryService();
|
|
18612
|
+
|
|
18385
18613
|
//#endregion
|
|
18386
18614
|
//#region ../agent-provider/src/backend/backend-provider.ts
|
|
18387
18615
|
/**
|
|
@@ -18389,8 +18617,31 @@ let AccountStatus = /* @__PURE__ */ function(AccountStatus) {
|
|
|
18389
18617
|
*
|
|
18390
18618
|
* 封装与后端 API 的 HTTP 通信
|
|
18391
18619
|
*/
|
|
18392
|
-
/**
|
|
18393
|
-
|
|
18620
|
+
/**
|
|
18621
|
+
* 判断当前账号是否是 SSO 账号
|
|
18622
|
+
* 通过 account.accountType === 'sso' 来判断,这种不行,因为未登录之前account 为空
|
|
18623
|
+
*/
|
|
18624
|
+
const isSSODomain = () => {
|
|
18625
|
+
const { hostname } = window.location;
|
|
18626
|
+
return hostname.includes(".sso.copilot") || hostname.includes("sso.codebuddy.cn") || hostname.includes(".sso.copilot-staging") || hostname.includes(".staging-sso.codebuddy.cn");
|
|
18627
|
+
};
|
|
18628
|
+
/**
|
|
18629
|
+
* 根据路径获取完整 URL
|
|
18630
|
+
* - SSO 账号需要跳转到对应的预发/生产域名
|
|
18631
|
+
* - 非 SSO 账号直接使用当前域名
|
|
18632
|
+
* @param path 路径,如 '/login'、'/logout'、'/home' 等
|
|
18633
|
+
* @returns 完整的 URL 地址
|
|
18634
|
+
*/
|
|
18635
|
+
const getFullUrl = (path) => {
|
|
18636
|
+
const { hostname, protocol } = window.location;
|
|
18637
|
+
if (isSSODomain()) {
|
|
18638
|
+
const isCodebuddy = hostname.includes("codebuddy.cn");
|
|
18639
|
+
const isStaging = hostname.includes("staging");
|
|
18640
|
+
if (isCodebuddy) return isStaging ? `${protocol}//staging.codebuddy.cn${path}` : `${protocol}//www.codebuddy.cn${path}`;
|
|
18641
|
+
else return isStaging ? `${protocol}//staging-copilot.tencent.com${path}` : `${protocol}//copilot.tencent.com${path}`;
|
|
18642
|
+
}
|
|
18643
|
+
return `${window.location.origin}${path}`;
|
|
18644
|
+
};
|
|
18394
18645
|
/** 获取当前域名的账号选择页面 URL */
|
|
18395
18646
|
const getSelectAccountUrl = () => `${window.location.origin}/login/select`;
|
|
18396
18647
|
/** localStorage 中存储选中账号 ID 的 key */
|
|
@@ -18477,7 +18728,7 @@ var BackendProvider = class {
|
|
|
18477
18728
|
return account;
|
|
18478
18729
|
}
|
|
18479
18730
|
const redirectUrl = encodeURIComponent(window.location.href);
|
|
18480
|
-
window.location.href = `${getSelectAccountUrl()}?platform=
|
|
18731
|
+
window.location.href = `${getSelectAccountUrl()}?platform=agents&state=0&redirect_uri=${redirectUrl}`;
|
|
18481
18732
|
accountService.setAccount(null);
|
|
18482
18733
|
return null;
|
|
18483
18734
|
} catch (error) {
|
|
@@ -18839,7 +19090,7 @@ var BackendProvider = class {
|
|
|
18839
19090
|
*/
|
|
18840
19091
|
async login() {
|
|
18841
19092
|
const redirectUrl = encodeURIComponent(window.location.href);
|
|
18842
|
-
window.location.href = `${
|
|
19093
|
+
window.location.href = `${getFullUrl("/login")}?platform=agents&state=0&redirect_uri=${redirectUrl}`;
|
|
18843
19094
|
}
|
|
18844
19095
|
/**
|
|
18845
19096
|
* 登出账号
|
|
@@ -18903,20 +19154,51 @@ var BackendProvider = class {
|
|
|
18903
19154
|
}
|
|
18904
19155
|
}
|
|
18905
19156
|
/**
|
|
18906
|
-
*
|
|
18907
|
-
*
|
|
18908
|
-
*
|
|
19157
|
+
* 刷新 Token
|
|
19158
|
+
* 通过调用 getAccount 刷新 cookie,适用于 Cloud 场景下页面切换回来时刷新登录态
|
|
19159
|
+
* @returns Promise<Account | null> 刷新后的账号信息
|
|
18909
19160
|
*/
|
|
18910
|
-
async
|
|
19161
|
+
async refreshToken() {
|
|
19162
|
+
console.log("[BackendProvider] Refreshing token...");
|
|
18911
19163
|
try {
|
|
18912
|
-
const
|
|
18913
|
-
|
|
18914
|
-
return
|
|
19164
|
+
const account = await this.getAccount();
|
|
19165
|
+
console.log("[BackendProvider] Token refreshed, account:", account?.uid);
|
|
19166
|
+
return account;
|
|
18915
19167
|
} catch (error) {
|
|
18916
|
-
console.error("[BackendProvider]
|
|
18917
|
-
return
|
|
19168
|
+
console.error("[BackendProvider] refreshToken failed:", error);
|
|
19169
|
+
return null;
|
|
18918
19170
|
}
|
|
18919
19171
|
}
|
|
19172
|
+
/**
|
|
19173
|
+
* 获取仓库分支列表
|
|
19174
|
+
* API 端点: GET /console/as/connector/oauth/{name}/branches
|
|
19175
|
+
*
|
|
19176
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
19177
|
+
* @param params 平台特定的查询参数
|
|
19178
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
19179
|
+
* @param perPage 每页数量,最大100
|
|
19180
|
+
* @returns Promise<OauthBranch[]> 分支列表
|
|
19181
|
+
*/
|
|
19182
|
+
async getBranches(connector, params, page = 0, perPage = 100) {
|
|
19183
|
+
return oauthRepositoryService.getBranches(connector, params, page, perPage);
|
|
19184
|
+
}
|
|
19185
|
+
/**
|
|
19186
|
+
* 获取仓库列表
|
|
19187
|
+
* API 端点: GET /console/as/connector/oauth/{name}/repos
|
|
19188
|
+
*
|
|
19189
|
+
* Note: 由于工蜂原生支持的 Search 能力会匹配 path/name/description 部分,
|
|
19190
|
+
* 且不支持定制,不满足产品要求(只按 name 匹配),因此前端拉取全量数据后做筛选。
|
|
19191
|
+
*
|
|
19192
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
19193
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
19194
|
+
* - GitHub 只支持全量数据,必须传 0
|
|
19195
|
+
* - 工蜂和 CNB 依据前端逻辑而定
|
|
19196
|
+
* @param perPage 每页数量,最大100
|
|
19197
|
+
* @returns Promise<ListReposResponse> 仓库列表响应
|
|
19198
|
+
*/
|
|
19199
|
+
async getRepositories(connector, page = 0, perPage = 100) {
|
|
19200
|
+
return oauthRepositoryService.getRepositories(connector, page, perPage);
|
|
19201
|
+
}
|
|
18920
19202
|
};
|
|
18921
19203
|
/**
|
|
18922
19204
|
* 创建 BackendProvider 实例
|
|
@@ -18928,6 +19210,12 @@ function createBackendProvider(config) {
|
|
|
18928
19210
|
//#endregion
|
|
18929
19211
|
//#region ../agent-provider/src/backend/ipc-backend-provider.ts
|
|
18930
19212
|
/**
|
|
19213
|
+
* IPC Backend Provider 实现
|
|
19214
|
+
*
|
|
19215
|
+
* 通过 IWidgetChannel 与后端通信
|
|
19216
|
+
* 使用统一的消息格式: { type: 'backend', requestId, params: { type, params } }
|
|
19217
|
+
*/
|
|
19218
|
+
/**
|
|
18931
19219
|
* Backend 请求类型常量
|
|
18932
19220
|
*/
|
|
18933
19221
|
const BACKEND_REQUEST_TYPES = {
|
|
@@ -18949,8 +19237,10 @@ const BACKEND_REQUEST_TYPES = {
|
|
|
18949
19237
|
REVOKE_ALL: "backend:revoke-all",
|
|
18950
19238
|
GET_FILE: "backend:get-file",
|
|
18951
19239
|
RELOAD_WINDOW: "backend:reload-window",
|
|
19240
|
+
CLOSE_AGENT_MANAGER: "backend:close-agent-manager",
|
|
19241
|
+
OPEN_EXTERNAL: "backend:open-external",
|
|
18952
19242
|
BATCH_TOGGLE_PLUGINS: "backend:batch-toggle-plugins",
|
|
18953
|
-
|
|
19243
|
+
GET_SUPPORT_SCENES: "backend:get-support-scenes"
|
|
18954
19244
|
};
|
|
18955
19245
|
/**
|
|
18956
19246
|
* 生成唯一请求 ID
|
|
@@ -19231,6 +19521,33 @@ var IPCBackendProvider = class {
|
|
|
19231
19521
|
}
|
|
19232
19522
|
}
|
|
19233
19523
|
/**
|
|
19524
|
+
* 关闭 Agent Manager 面板
|
|
19525
|
+
* IDE 环境: 通过 IPC 通知 IDE 关闭 Agent Manager(用于返回 IDE)
|
|
19526
|
+
*/
|
|
19527
|
+
async closeAgentManager() {
|
|
19528
|
+
this.log("Triggering close agent manager via IPC");
|
|
19529
|
+
try {
|
|
19530
|
+
await this.sendBackendRequest(BACKEND_REQUEST_TYPES.CLOSE_AGENT_MANAGER);
|
|
19531
|
+
} catch (error) {
|
|
19532
|
+
this.log("Close agent manager request failed:", error);
|
|
19533
|
+
throw error;
|
|
19534
|
+
}
|
|
19535
|
+
}
|
|
19536
|
+
/**
|
|
19537
|
+
* 在外部浏览器中打开链接
|
|
19538
|
+
* IDE 环境: 通过 IPC 通知 IDE 使用 vscode.env.openExternal 打开 URL
|
|
19539
|
+
* @param url 要打开的 URL
|
|
19540
|
+
*/
|
|
19541
|
+
async openExternal(url) {
|
|
19542
|
+
this.log("Opening external URL via IPC:", url);
|
|
19543
|
+
try {
|
|
19544
|
+
await this.sendBackendRequest(BACKEND_REQUEST_TYPES.OPEN_EXTERNAL, { url });
|
|
19545
|
+
} catch (error) {
|
|
19546
|
+
this.log("Open external request failed:", error);
|
|
19547
|
+
throw error;
|
|
19548
|
+
}
|
|
19549
|
+
}
|
|
19550
|
+
/**
|
|
19234
19551
|
* 批量切换插件状态
|
|
19235
19552
|
* IDE 环境: 通过 IPC 调用 Extension Host 的 PluginService
|
|
19236
19553
|
*/
|
|
@@ -19244,22 +19561,22 @@ var IPCBackendProvider = class {
|
|
|
19244
19561
|
}
|
|
19245
19562
|
}
|
|
19246
19563
|
/**
|
|
19247
|
-
*
|
|
19564
|
+
* 获取支持的场景列表
|
|
19248
19565
|
* IDE 环境: 通过 IPC 调用后端 API
|
|
19249
19566
|
* 用于 Welcome 页面的 QuickActions 快捷操作
|
|
19250
19567
|
*
|
|
19251
19568
|
* 调用链:
|
|
19252
|
-
* 1. agent-ui: IPCBackendProvider.
|
|
19253
|
-
* 2. Extension Host: BackendBridgeService.
|
|
19254
|
-
* 3. Backend API: GET /v2/as/support/
|
|
19255
|
-
* 4. 返回
|
|
19569
|
+
* 1. agent-ui: IPCBackendProvider.getSupportScenes()
|
|
19570
|
+
* 2. Extension Host: BackendBridgeService.handleGetSupportScenes()
|
|
19571
|
+
* 3. Backend API: GET /v2/as/support/scenes
|
|
19572
|
+
* 4. 返回 SupportScene[] 数据给 agent-ui
|
|
19256
19573
|
*/
|
|
19257
|
-
async
|
|
19258
|
-
this.log("Getting support
|
|
19574
|
+
async getSupportScenes() {
|
|
19575
|
+
this.log("Getting support scenes via IPC");
|
|
19259
19576
|
try {
|
|
19260
|
-
return (await this.sendBackendRequest(BACKEND_REQUEST_TYPES.
|
|
19577
|
+
return (await this.sendBackendRequest(BACKEND_REQUEST_TYPES.GET_SUPPORT_SCENES, {}))?.scenes || [];
|
|
19261
19578
|
} catch (error) {
|
|
19262
|
-
this.log("Get support
|
|
19579
|
+
this.log("Get support scenes failed:", error);
|
|
19263
19580
|
return [];
|
|
19264
19581
|
}
|
|
19265
19582
|
}
|