@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.mjs
CHANGED
|
@@ -1954,9 +1954,7 @@ var StreamableHttpClient = class {
|
|
|
1954
1954
|
});
|
|
1955
1955
|
await this.handleExtNotification(method, params);
|
|
1956
1956
|
},
|
|
1957
|
-
extMethod: async (method, params) =>
|
|
1958
|
-
return await this.handleExtMethod(method, params);
|
|
1959
|
-
}
|
|
1957
|
+
extMethod: async (method, params) => this.handleExtMethod(method, params)
|
|
1960
1958
|
};
|
|
1961
1959
|
}
|
|
1962
1960
|
/**
|
|
@@ -2176,12 +2174,22 @@ var StreamableHttpClient = class {
|
|
|
2176
2174
|
await this.extensionManager.handleNotification(method, params);
|
|
2177
2175
|
}
|
|
2178
2176
|
async handleExtMethod(method, params) {
|
|
2179
|
-
if (method === ExtensionMethod.QUESTION)
|
|
2177
|
+
if (method === ExtensionMethod.QUESTION) {
|
|
2178
|
+
const response = await this.questionManager.handleRequest(params);
|
|
2179
|
+
if (response.outcome === "submitted" && response.answers) return { outcome: {
|
|
2180
|
+
outcome: "submitted",
|
|
2181
|
+
data: { answers: response.answers }
|
|
2182
|
+
} };
|
|
2183
|
+
else return { outcome: {
|
|
2184
|
+
outcome: "cancelled",
|
|
2185
|
+
reason: response.reason
|
|
2186
|
+
} };
|
|
2187
|
+
}
|
|
2180
2188
|
this.options.logger?.warn(`Unknown extension method: ${method}`);
|
|
2181
|
-
return {
|
|
2189
|
+
return { outcome: {
|
|
2182
2190
|
outcome: "cancelled",
|
|
2183
2191
|
reason: "unknown method"
|
|
2184
|
-
};
|
|
2192
|
+
} };
|
|
2185
2193
|
}
|
|
2186
2194
|
ensureInitialized(operation) {
|
|
2187
2195
|
if (this.state !== "initialized") throw new InvalidStateError(operation, this.state, ["initialized"]);
|
|
@@ -2364,7 +2372,7 @@ var CloudAgentConnection = class {
|
|
|
2364
2372
|
}
|
|
2365
2373
|
async createSession(params) {
|
|
2366
2374
|
return {
|
|
2367
|
-
...await this.client.
|
|
2375
|
+
...await this.client.createSession(this.cwd),
|
|
2368
2376
|
sessionId: this.agentId
|
|
2369
2377
|
};
|
|
2370
2378
|
}
|
|
@@ -5655,6 +5663,11 @@ var AccountService = class {
|
|
|
5655
5663
|
* 导出单例实例
|
|
5656
5664
|
*/
|
|
5657
5665
|
const accountService = new AccountService();
|
|
5666
|
+
/**
|
|
5667
|
+
* 暴露给全局,供 Agent Manager 直接调用 setAccount 刷新 Widget 状态
|
|
5668
|
+
* 这是为了解决 IDE 环境中 IPC 事件无法直接触发 Widget 账号刷新的问题
|
|
5669
|
+
*/
|
|
5670
|
+
if (typeof window !== "undefined") window.__genieAccountService = accountService;
|
|
5658
5671
|
|
|
5659
5672
|
//#endregion
|
|
5660
5673
|
//#region ../agent-provider/src/common/utils/concurrency.ts
|
|
@@ -6262,13 +6275,19 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
6262
6275
|
/**
|
|
6263
6276
|
* Create a new conversation
|
|
6264
6277
|
* POST {endpoint}/console/as/conversations
|
|
6278
|
+
* @param params - Optional session params containing _meta with tags
|
|
6265
6279
|
*/
|
|
6266
|
-
async create() {
|
|
6280
|
+
async create(params) {
|
|
6267
6281
|
try {
|
|
6268
|
-
const
|
|
6282
|
+
const tagsObj = (params?._meta?.["codebuddy.ai"])?.tags;
|
|
6283
|
+
const tagsArray = tagsObj ? Object.entries(tagsObj).map(([key, value]) => `${key}:${value}`) : void 0;
|
|
6284
|
+
const createPayload = {
|
|
6269
6285
|
prompt: "",
|
|
6270
|
-
model: "deepseek-r1"
|
|
6271
|
-
|
|
6286
|
+
model: "deepseek-r1",
|
|
6287
|
+
...tagsArray && tagsArray.length > 0 ? { tags: tagsArray } : {}
|
|
6288
|
+
};
|
|
6289
|
+
console.log("[CloudAgentProvider] Creating conversation with payload:", createPayload);
|
|
6290
|
+
const apiResponse = await httpService.post("/console/as/conversations/", createPayload);
|
|
6272
6291
|
if (!apiResponse.data) throw new Error("No data in API response");
|
|
6273
6292
|
this.logger?.info(`Created conversation: ${apiResponse.data.id}`);
|
|
6274
6293
|
return apiResponse.data.id;
|
|
@@ -6629,6 +6648,28 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
6629
6648
|
}
|
|
6630
6649
|
}
|
|
6631
6650
|
}
|
|
6651
|
+
/**
|
|
6652
|
+
* 获取支持的场景列表
|
|
6653
|
+
* API 端点: GET /console/as/support/scenes
|
|
6654
|
+
* 用于 Welcome 页面的 QuickActions 快捷操作
|
|
6655
|
+
*
|
|
6656
|
+
* @returns Promise<SupportScene[]> 支持的场景列表
|
|
6657
|
+
*/
|
|
6658
|
+
async getSupportScenes() {
|
|
6659
|
+
try {
|
|
6660
|
+
const apiResponse = await httpService.get("/console/as/support/scenes");
|
|
6661
|
+
if (!apiResponse.data) {
|
|
6662
|
+
this.logger?.warn("[CloudAgentProvider] No data in support scenes response");
|
|
6663
|
+
return [];
|
|
6664
|
+
}
|
|
6665
|
+
const scenes = apiResponse.data.scenes || [];
|
|
6666
|
+
this.logger?.info(`[CloudAgentProvider] Retrieved ${scenes.length} support scenes`);
|
|
6667
|
+
return scenes;
|
|
6668
|
+
} catch (error) {
|
|
6669
|
+
this.logger?.error("[CloudAgentProvider] Failed to get support scenes:", error);
|
|
6670
|
+
return [];
|
|
6671
|
+
}
|
|
6672
|
+
}
|
|
6632
6673
|
toAgentState(data) {
|
|
6633
6674
|
const status = data.sessionStatus || data.status;
|
|
6634
6675
|
return {
|
|
@@ -6933,8 +6974,8 @@ var ActiveSessionImpl = class {
|
|
|
6933
6974
|
* await session.setMode('architect');
|
|
6934
6975
|
* ```
|
|
6935
6976
|
*/
|
|
6936
|
-
async setMode(modeId) {
|
|
6937
|
-
if (this._availableModes) {
|
|
6977
|
+
async setMode(modeId, skipAvailableChecker) {
|
|
6978
|
+
if (this._availableModes && !skipAvailableChecker) {
|
|
6938
6979
|
if (!this._availableModes.some((m) => m.id === modeId)) {
|
|
6939
6980
|
const availableIds = this._availableModes.map((m) => m.id).join(", ");
|
|
6940
6981
|
throw new Error(`Invalid modeId: "${modeId}". Available modes: ${availableIds}`);
|
|
@@ -7125,14 +7166,6 @@ var ActiveSessionImpl = class {
|
|
|
7125
7166
|
//#endregion
|
|
7126
7167
|
//#region ../agent-provider/src/common/client/session-manager.ts
|
|
7127
7168
|
/**
|
|
7128
|
-
* SessionManager - Manages session lifecycle and connections
|
|
7129
|
-
*
|
|
7130
|
-
* Provides the core implementation for session-centric API operations:
|
|
7131
|
-
* - list() - Lists sessions (mapped from agents)
|
|
7132
|
-
* - createSession() - Creates new session (auto-creates agent)
|
|
7133
|
-
* - loadSession() - Loads existing session (finds agent by sessionId)
|
|
7134
|
-
*/
|
|
7135
|
-
/**
|
|
7136
7169
|
* SessionManager - Session lifecycle management
|
|
7137
7170
|
*
|
|
7138
7171
|
* This class manages the relationship between sessions and agents.
|
|
@@ -7228,14 +7261,8 @@ var SessionManager = class {
|
|
|
7228
7261
|
connectionInfo
|
|
7229
7262
|
});
|
|
7230
7263
|
session.setModes(response.modes?.availableModes, response.modes?.currentModeId);
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
id: m.modelId,
|
|
7234
|
-
name: m.name,
|
|
7235
|
-
description: m.description ?? void 0
|
|
7236
|
-
}));
|
|
7237
|
-
session.setModels(localModels, response.models?.currentModelId);
|
|
7238
|
-
}
|
|
7264
|
+
const availableModels = this.extractAvailableModels(response);
|
|
7265
|
+
if (availableModels) session.setModels(availableModels, response.models?.currentModelId);
|
|
7239
7266
|
this.logger?.info(`Session created: ${response.sessionId}`);
|
|
7240
7267
|
return session;
|
|
7241
7268
|
}
|
|
@@ -7271,17 +7298,31 @@ var SessionManager = class {
|
|
|
7271
7298
|
mcpServers: params.mcpServers
|
|
7272
7299
|
});
|
|
7273
7300
|
session.setModes(response.modes?.availableModes, response.modes?.currentModeId);
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
id: m.modelId,
|
|
7277
|
-
name: m.name,
|
|
7278
|
-
description: m.description ?? void 0
|
|
7279
|
-
}));
|
|
7280
|
-
session.setModels(localModels, response.models?.currentModelId);
|
|
7281
|
-
}
|
|
7301
|
+
const availableModels = this.extractAvailableModels(response);
|
|
7302
|
+
if (availableModels) session.setModels(availableModels, response.models?.currentModelId);
|
|
7282
7303
|
this.logger?.info(`Session loaded: ${params.sessionId}`);
|
|
7283
7304
|
return session;
|
|
7284
7305
|
}
|
|
7306
|
+
/**
|
|
7307
|
+
* 从 ACP response 中提取可用模型列表
|
|
7308
|
+
*
|
|
7309
|
+
* 优先级:
|
|
7310
|
+
* 1. response.models._meta?.['codebuddy.ai']?.availableModels - 包含完整的模型信息(字段名为 'id')
|
|
7311
|
+
* 2. response.models?.availableModels - 只包含基本信息(字段名为 'modelId')
|
|
7312
|
+
* 3. undefined - 都没有时返回 undefined
|
|
7313
|
+
*
|
|
7314
|
+
* @param response - ACP 响应对象
|
|
7315
|
+
* @returns ModelInfo[] | undefined
|
|
7316
|
+
*/
|
|
7317
|
+
extractAvailableModels(response) {
|
|
7318
|
+
const metaModels = (response.models?._meta?.["codebuddy.ai"])?.availableModels;
|
|
7319
|
+
if (metaModels && Array.isArray(metaModels) && metaModels.length > 0) return metaModels;
|
|
7320
|
+
const availableModels = response.models?.availableModels;
|
|
7321
|
+
if (availableModels && Array.isArray(availableModels) && availableModels.length > 0) return availableModels.map((model) => ({
|
|
7322
|
+
...model,
|
|
7323
|
+
...model._meta?.["codebuddy.ai"] || {}
|
|
7324
|
+
}));
|
|
7325
|
+
}
|
|
7285
7326
|
};
|
|
7286
7327
|
|
|
7287
7328
|
//#endregion
|
|
@@ -7554,6 +7595,28 @@ var AgentClient = class {
|
|
|
7554
7595
|
};
|
|
7555
7596
|
}
|
|
7556
7597
|
},
|
|
7598
|
+
getSubagentList: async (params) => {
|
|
7599
|
+
try {
|
|
7600
|
+
if (this.provider && this.provider.getSubagentList) {
|
|
7601
|
+
const result = await this.provider.getSubagentList(params);
|
|
7602
|
+
this.logger?.info("Subagent list retrieved", {
|
|
7603
|
+
resultCount: result.results.length,
|
|
7604
|
+
hasError: !!result.error
|
|
7605
|
+
});
|
|
7606
|
+
return result;
|
|
7607
|
+
}
|
|
7608
|
+
return {
|
|
7609
|
+
results: [],
|
|
7610
|
+
error: "Provider does not support getSubagentList"
|
|
7611
|
+
};
|
|
7612
|
+
} catch (error) {
|
|
7613
|
+
this.logger?.error("Failed to get subagent list", error);
|
|
7614
|
+
return {
|
|
7615
|
+
results: [],
|
|
7616
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
7617
|
+
};
|
|
7618
|
+
}
|
|
7619
|
+
},
|
|
7557
7620
|
batchTogglePlugins: async (request) => {
|
|
7558
7621
|
try {
|
|
7559
7622
|
if (this.provider && this.provider.batchTogglePlugins) {
|
|
@@ -7598,10 +7661,10 @@ var AgentClient = class {
|
|
|
7598
7661
|
return [];
|
|
7599
7662
|
}
|
|
7600
7663
|
},
|
|
7601
|
-
installPlugins: async (pluginNames, marketplaceName, installScope) => {
|
|
7664
|
+
installPlugins: async (pluginNames, marketplaceName, installScope, marketplaceSource) => {
|
|
7602
7665
|
try {
|
|
7603
7666
|
if (this.provider && "installPlugins" in this.provider && typeof this.provider.installPlugins === "function") {
|
|
7604
|
-
const result = await this.provider.installPlugins(pluginNames, marketplaceName, installScope);
|
|
7667
|
+
const result = await this.provider.installPlugins(pluginNames, marketplaceName, installScope, marketplaceSource);
|
|
7605
7668
|
this.logger?.info("Install plugins", {
|
|
7606
7669
|
pluginNames,
|
|
7607
7670
|
marketplaceName,
|
|
@@ -7622,17 +7685,34 @@ var AgentClient = class {
|
|
|
7622
7685
|
};
|
|
7623
7686
|
}
|
|
7624
7687
|
},
|
|
7625
|
-
|
|
7688
|
+
getSupportScenes: async () => {
|
|
7626
7689
|
try {
|
|
7627
|
-
if (this.provider && "
|
|
7628
|
-
const result = await this.provider.
|
|
7629
|
-
this.logger?.info("Got support
|
|
7690
|
+
if (this.provider && "getSupportScenes" in this.provider && typeof this.provider.getSupportScenes === "function") {
|
|
7691
|
+
const result = await this.provider.getSupportScenes();
|
|
7692
|
+
this.logger?.info("Got support scenes", { count: result?.length ?? 0 });
|
|
7630
7693
|
return result;
|
|
7631
7694
|
}
|
|
7632
|
-
this.logger?.warn("Provider does not support
|
|
7695
|
+
this.logger?.warn("Provider does not support getSupportScenes");
|
|
7633
7696
|
return [];
|
|
7634
7697
|
} catch (error) {
|
|
7635
|
-
this.logger?.error("Failed to get support
|
|
7698
|
+
this.logger?.error("Failed to get support scenes", error);
|
|
7699
|
+
return [];
|
|
7700
|
+
}
|
|
7701
|
+
},
|
|
7702
|
+
getAvailableCommands: async (sessionId) => {
|
|
7703
|
+
try {
|
|
7704
|
+
if (this.provider && "getAvailableCommands" in this.provider && typeof this.provider.getAvailableCommands === "function") {
|
|
7705
|
+
const result = await this.provider.getAvailableCommands(sessionId);
|
|
7706
|
+
this.logger?.info("Got available commands from provider", {
|
|
7707
|
+
sessionId: sessionId ?? "(default)",
|
|
7708
|
+
count: result?.length ?? 0
|
|
7709
|
+
});
|
|
7710
|
+
return result;
|
|
7711
|
+
}
|
|
7712
|
+
this.logger?.warn("Provider does not support getAvailableCommands", { sessionId });
|
|
7713
|
+
return [];
|
|
7714
|
+
} catch (error) {
|
|
7715
|
+
this.logger?.error("Failed to get available commands", error);
|
|
7636
7716
|
return [];
|
|
7637
7717
|
}
|
|
7638
7718
|
},
|
|
@@ -7702,6 +7782,154 @@ let AccountStatus = /* @__PURE__ */ function(AccountStatus) {
|
|
|
7702
7782
|
return AccountStatus;
|
|
7703
7783
|
}({});
|
|
7704
7784
|
|
|
7785
|
+
//#endregion
|
|
7786
|
+
//#region ../agent-provider/src/backend/service/oauth-repository-service.ts
|
|
7787
|
+
/**
|
|
7788
|
+
* OAuth Repository Service
|
|
7789
|
+
*
|
|
7790
|
+
* 封装 OAuth 连接器相关的仓库和分支操作
|
|
7791
|
+
*/
|
|
7792
|
+
/**
|
|
7793
|
+
* OAuth Repository Service
|
|
7794
|
+
*
|
|
7795
|
+
* 提供仓库和分支的查询操作
|
|
7796
|
+
*/
|
|
7797
|
+
var OAuthRepositoryService = class {
|
|
7798
|
+
/**
|
|
7799
|
+
* 获取仓库分支列表
|
|
7800
|
+
* API 端点: GET /console/as/connector/oauth/{name}/branches
|
|
7801
|
+
*
|
|
7802
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
7803
|
+
* @param params 平台特定的查询参数
|
|
7804
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
7805
|
+
* @param perPage 每页数量,最大100
|
|
7806
|
+
* @returns Promise<OauthBranch[]> 分支列表
|
|
7807
|
+
*
|
|
7808
|
+
* @example
|
|
7809
|
+
* ```typescript
|
|
7810
|
+
* // GitHub
|
|
7811
|
+
* const branches = await service.getBranches('github', {
|
|
7812
|
+
* owner: 'CodeBuddy-Official-Account',
|
|
7813
|
+
* repo: 'CodeBuddyIDE'
|
|
7814
|
+
* });
|
|
7815
|
+
*
|
|
7816
|
+
* // Gongfeng
|
|
7817
|
+
* const branches = await service.getBranches('gongfeng', {
|
|
7818
|
+
* project_id: '1611499'
|
|
7819
|
+
* });
|
|
7820
|
+
*
|
|
7821
|
+
* // CNB
|
|
7822
|
+
* const branches = await service.getBranches('cnb', {
|
|
7823
|
+
* repo: 'genie/genie-ide'
|
|
7824
|
+
* });
|
|
7825
|
+
* ```
|
|
7826
|
+
*/
|
|
7827
|
+
async getBranches(connector, params, page = 0, perPage = 100) {
|
|
7828
|
+
try {
|
|
7829
|
+
const url = `/console/as/connector/oauth/${connector}/branches?${this.buildBranchQueryParams(connector, params, page, perPage).toString()}`;
|
|
7830
|
+
console.log(`[OAuthRepositoryService] GET ${url}`);
|
|
7831
|
+
const apiResponse = await httpService.get(url);
|
|
7832
|
+
if (!apiResponse.data) {
|
|
7833
|
+
console.warn(`[OAuthRepositoryService] No data in branches response for ${connector}`);
|
|
7834
|
+
return [];
|
|
7835
|
+
}
|
|
7836
|
+
const branches = apiResponse.data.branches || [];
|
|
7837
|
+
console.log(`[OAuthRepositoryService] Retrieved ${branches.length} branches from ${connector}`);
|
|
7838
|
+
return branches;
|
|
7839
|
+
} catch (error) {
|
|
7840
|
+
console.error(`[OAuthRepositoryService] Failed to get branches from ${connector}:`, error);
|
|
7841
|
+
throw error;
|
|
7842
|
+
}
|
|
7843
|
+
}
|
|
7844
|
+
/**
|
|
7845
|
+
* 获取仓库列表
|
|
7846
|
+
* API 端点: GET /console/as/connector/oauth/{name}/repos
|
|
7847
|
+
*
|
|
7848
|
+
* Note: 由于工蜂原生支持的 Search 能力会匹配 path/name/description 部分,
|
|
7849
|
+
* 且不支持定制,不满足产品要求(只按 name 匹配),因此前端拉取全量数据后做筛选。
|
|
7850
|
+
*
|
|
7851
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
7852
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
7853
|
+
* - GitHub 只支持全量数据,必须传 0
|
|
7854
|
+
* - 工蜂和 CNB 依据前端逻辑而定
|
|
7855
|
+
* @param perPage 每页数量,最大100
|
|
7856
|
+
* @returns Promise<ListReposResponse> 仓库列表响应
|
|
7857
|
+
*
|
|
7858
|
+
* @example
|
|
7859
|
+
* ```typescript
|
|
7860
|
+
* // GitHub - 必须传 page=0 获取全量数据
|
|
7861
|
+
* const response = await service.getRepositories('github', 0, 100);
|
|
7862
|
+
* // response.github_repos 是 map: installation_id => repo[]
|
|
7863
|
+
*
|
|
7864
|
+
* // Gongfeng
|
|
7865
|
+
* const response = await service.getRepositories('gongfeng', 0, 100);
|
|
7866
|
+
* // response.gongfeng_repos 是数组
|
|
7867
|
+
*
|
|
7868
|
+
* // CNB
|
|
7869
|
+
* const response = await service.getRepositories('cnb', 0, 100);
|
|
7870
|
+
* // response.cnb_repos 是数组
|
|
7871
|
+
* ```
|
|
7872
|
+
*/
|
|
7873
|
+
async getRepositories(connector, page = 0, perPage = 100) {
|
|
7874
|
+
try {
|
|
7875
|
+
const queryParams = new URLSearchParams();
|
|
7876
|
+
queryParams.append("page", String(page));
|
|
7877
|
+
queryParams.append("per_page", String(Math.min(perPage, 100)));
|
|
7878
|
+
const url = `/console/as/connector/oauth/${connector}/repos?${queryParams.toString()}`;
|
|
7879
|
+
console.log(`[OAuthRepositoryService] GET ${url}`);
|
|
7880
|
+
const apiResponse = await httpService.get(url);
|
|
7881
|
+
if (!apiResponse.data) {
|
|
7882
|
+
console.warn(`[OAuthRepositoryService] No data in repos response for ${connector}`);
|
|
7883
|
+
return {};
|
|
7884
|
+
}
|
|
7885
|
+
const response = apiResponse.data;
|
|
7886
|
+
this.logRepositoryCounts(response);
|
|
7887
|
+
return response;
|
|
7888
|
+
} catch (error) {
|
|
7889
|
+
console.error(`[OAuthRepositoryService] Failed to get repos from ${connector}:`, error);
|
|
7890
|
+
throw error;
|
|
7891
|
+
}
|
|
7892
|
+
}
|
|
7893
|
+
/**
|
|
7894
|
+
* 构建分支查询参数
|
|
7895
|
+
*/
|
|
7896
|
+
buildBranchQueryParams(connector, params, page, perPage) {
|
|
7897
|
+
const queryParams = new URLSearchParams();
|
|
7898
|
+
queryParams.append("page", String(page));
|
|
7899
|
+
queryParams.append("per_page", String(Math.min(perPage, 100)));
|
|
7900
|
+
if (connector === "github") {
|
|
7901
|
+
const githubParams = params;
|
|
7902
|
+
if (!githubParams.owner || !githubParams.repo) throw new Error("GitHub requires owner and repo parameters");
|
|
7903
|
+
queryParams.append("owner", githubParams.owner);
|
|
7904
|
+
queryParams.append("repo", githubParams.repo);
|
|
7905
|
+
} else if (connector === "gongfeng") {
|
|
7906
|
+
const gongfengParams = params;
|
|
7907
|
+
if (!gongfengParams.project_id) throw new Error("Gongfeng requires project_id parameter");
|
|
7908
|
+
queryParams.append("project_id", gongfengParams.project_id);
|
|
7909
|
+
} else if (connector === "cnb") {
|
|
7910
|
+
const cnbParams = params;
|
|
7911
|
+
if (!cnbParams.repo) throw new Error("CNB requires repo parameter");
|
|
7912
|
+
queryParams.append("repo", cnbParams.repo);
|
|
7913
|
+
} else throw new Error(`Unknown connector: ${connector}`);
|
|
7914
|
+
return queryParams;
|
|
7915
|
+
}
|
|
7916
|
+
/**
|
|
7917
|
+
* 记录仓库数量日志
|
|
7918
|
+
*/
|
|
7919
|
+
logRepositoryCounts(response) {
|
|
7920
|
+
if (response.github_repos) {
|
|
7921
|
+
const totalCount = Object.values(response.github_repos).reduce((sum, repos) => sum + repos.length, 0);
|
|
7922
|
+
console.log(`[OAuthRepositoryService] Retrieved ${totalCount} GitHub repos across ${Object.keys(response.github_repos).length} installations`);
|
|
7923
|
+
}
|
|
7924
|
+
if (response.gongfeng_repos) console.log(`[OAuthRepositoryService] Retrieved ${response.gongfeng_repos.length} Gongfeng repos`);
|
|
7925
|
+
if (response.cnb_repos) console.log(`[OAuthRepositoryService] Retrieved ${response.cnb_repos.length} CNB repos`);
|
|
7926
|
+
}
|
|
7927
|
+
};
|
|
7928
|
+
/**
|
|
7929
|
+
* OAuth Repository Service 单例实例
|
|
7930
|
+
*/
|
|
7931
|
+
const oauthRepositoryService = new OAuthRepositoryService();
|
|
7932
|
+
|
|
7705
7933
|
//#endregion
|
|
7706
7934
|
//#region ../agent-provider/src/backend/backend-provider.ts
|
|
7707
7935
|
/**
|
|
@@ -7709,8 +7937,31 @@ let AccountStatus = /* @__PURE__ */ function(AccountStatus) {
|
|
|
7709
7937
|
*
|
|
7710
7938
|
* 封装与后端 API 的 HTTP 通信
|
|
7711
7939
|
*/
|
|
7712
|
-
/**
|
|
7713
|
-
|
|
7940
|
+
/**
|
|
7941
|
+
* 判断当前账号是否是 SSO 账号
|
|
7942
|
+
* 通过 account.accountType === 'sso' 来判断,这种不行,因为未登录之前account 为空
|
|
7943
|
+
*/
|
|
7944
|
+
const isSSODomain = () => {
|
|
7945
|
+
const { hostname } = window.location;
|
|
7946
|
+
return hostname.includes(".sso.copilot") || hostname.includes("sso.codebuddy.cn") || hostname.includes(".sso.copilot-staging") || hostname.includes(".staging-sso.codebuddy.cn");
|
|
7947
|
+
};
|
|
7948
|
+
/**
|
|
7949
|
+
* 根据路径获取完整 URL
|
|
7950
|
+
* - SSO 账号需要跳转到对应的预发/生产域名
|
|
7951
|
+
* - 非 SSO 账号直接使用当前域名
|
|
7952
|
+
* @param path 路径,如 '/login'、'/logout'、'/home' 等
|
|
7953
|
+
* @returns 完整的 URL 地址
|
|
7954
|
+
*/
|
|
7955
|
+
const getFullUrl = (path) => {
|
|
7956
|
+
const { hostname, protocol } = window.location;
|
|
7957
|
+
if (isSSODomain()) {
|
|
7958
|
+
const isCodebuddy = hostname.includes("codebuddy.cn");
|
|
7959
|
+
const isStaging = hostname.includes("staging");
|
|
7960
|
+
if (isCodebuddy) return isStaging ? `${protocol}//staging.codebuddy.cn${path}` : `${protocol}//www.codebuddy.cn${path}`;
|
|
7961
|
+
else return isStaging ? `${protocol}//staging-copilot.tencent.com${path}` : `${protocol}//copilot.tencent.com${path}`;
|
|
7962
|
+
}
|
|
7963
|
+
return `${window.location.origin}${path}`;
|
|
7964
|
+
};
|
|
7714
7965
|
/** 获取当前域名的账号选择页面 URL */
|
|
7715
7966
|
const getSelectAccountUrl = () => `${window.location.origin}/login/select`;
|
|
7716
7967
|
/** localStorage 中存储选中账号 ID 的 key */
|
|
@@ -7797,7 +8048,7 @@ var BackendProvider = class {
|
|
|
7797
8048
|
return account;
|
|
7798
8049
|
}
|
|
7799
8050
|
const redirectUrl = encodeURIComponent(window.location.href);
|
|
7800
|
-
window.location.href = `${getSelectAccountUrl()}?platform=
|
|
8051
|
+
window.location.href = `${getSelectAccountUrl()}?platform=agents&state=0&redirect_uri=${redirectUrl}`;
|
|
7801
8052
|
accountService.setAccount(null);
|
|
7802
8053
|
return null;
|
|
7803
8054
|
} catch (error) {
|
|
@@ -8159,7 +8410,7 @@ var BackendProvider = class {
|
|
|
8159
8410
|
*/
|
|
8160
8411
|
async login() {
|
|
8161
8412
|
const redirectUrl = encodeURIComponent(window.location.href);
|
|
8162
|
-
window.location.href = `${
|
|
8413
|
+
window.location.href = `${getFullUrl("/login")}?platform=agents&state=0&redirect_uri=${redirectUrl}`;
|
|
8163
8414
|
}
|
|
8164
8415
|
/**
|
|
8165
8416
|
* 登出账号
|
|
@@ -8223,20 +8474,51 @@ var BackendProvider = class {
|
|
|
8223
8474
|
}
|
|
8224
8475
|
}
|
|
8225
8476
|
/**
|
|
8226
|
-
*
|
|
8227
|
-
*
|
|
8228
|
-
*
|
|
8477
|
+
* 刷新 Token
|
|
8478
|
+
* 通过调用 getAccount 刷新 cookie,适用于 Cloud 场景下页面切换回来时刷新登录态
|
|
8479
|
+
* @returns Promise<Account | null> 刷新后的账号信息
|
|
8229
8480
|
*/
|
|
8230
|
-
async
|
|
8481
|
+
async refreshToken() {
|
|
8482
|
+
console.log("[BackendProvider] Refreshing token...");
|
|
8231
8483
|
try {
|
|
8232
|
-
const
|
|
8233
|
-
|
|
8234
|
-
return
|
|
8484
|
+
const account = await this.getAccount();
|
|
8485
|
+
console.log("[BackendProvider] Token refreshed, account:", account?.uid);
|
|
8486
|
+
return account;
|
|
8235
8487
|
} catch (error) {
|
|
8236
|
-
console.error("[BackendProvider]
|
|
8237
|
-
return
|
|
8488
|
+
console.error("[BackendProvider] refreshToken failed:", error);
|
|
8489
|
+
return null;
|
|
8238
8490
|
}
|
|
8239
8491
|
}
|
|
8492
|
+
/**
|
|
8493
|
+
* 获取仓库分支列表
|
|
8494
|
+
* API 端点: GET /console/as/connector/oauth/{name}/branches
|
|
8495
|
+
*
|
|
8496
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
8497
|
+
* @param params 平台特定的查询参数
|
|
8498
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
8499
|
+
* @param perPage 每页数量,最大100
|
|
8500
|
+
* @returns Promise<OauthBranch[]> 分支列表
|
|
8501
|
+
*/
|
|
8502
|
+
async getBranches(connector, params, page = 0, perPage = 100) {
|
|
8503
|
+
return oauthRepositoryService.getBranches(connector, params, page, perPage);
|
|
8504
|
+
}
|
|
8505
|
+
/**
|
|
8506
|
+
* 获取仓库列表
|
|
8507
|
+
* API 端点: GET /console/as/connector/oauth/{name}/repos
|
|
8508
|
+
*
|
|
8509
|
+
* Note: 由于工蜂原生支持的 Search 能力会匹配 path/name/description 部分,
|
|
8510
|
+
* 且不支持定制,不满足产品要求(只按 name 匹配),因此前端拉取全量数据后做筛选。
|
|
8511
|
+
*
|
|
8512
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
8513
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
8514
|
+
* - GitHub 只支持全量数据,必须传 0
|
|
8515
|
+
* - 工蜂和 CNB 依据前端逻辑而定
|
|
8516
|
+
* @param perPage 每页数量,最大100
|
|
8517
|
+
* @returns Promise<ListReposResponse> 仓库列表响应
|
|
8518
|
+
*/
|
|
8519
|
+
async getRepositories(connector, page = 0, perPage = 100) {
|
|
8520
|
+
return oauthRepositoryService.getRepositories(connector, page, perPage);
|
|
8521
|
+
}
|
|
8240
8522
|
};
|
|
8241
8523
|
/**
|
|
8242
8524
|
* 创建 BackendProvider 实例
|
|
@@ -8248,6 +8530,12 @@ function createBackendProvider(config) {
|
|
|
8248
8530
|
//#endregion
|
|
8249
8531
|
//#region ../agent-provider/src/backend/ipc-backend-provider.ts
|
|
8250
8532
|
/**
|
|
8533
|
+
* IPC Backend Provider 实现
|
|
8534
|
+
*
|
|
8535
|
+
* 通过 IWidgetChannel 与后端通信
|
|
8536
|
+
* 使用统一的消息格式: { type: 'backend', requestId, params: { type, params } }
|
|
8537
|
+
*/
|
|
8538
|
+
/**
|
|
8251
8539
|
* Backend 请求类型常量
|
|
8252
8540
|
*/
|
|
8253
8541
|
const BACKEND_REQUEST_TYPES = {
|
|
@@ -8269,8 +8557,10 @@ const BACKEND_REQUEST_TYPES = {
|
|
|
8269
8557
|
REVOKE_ALL: "backend:revoke-all",
|
|
8270
8558
|
GET_FILE: "backend:get-file",
|
|
8271
8559
|
RELOAD_WINDOW: "backend:reload-window",
|
|
8560
|
+
CLOSE_AGENT_MANAGER: "backend:close-agent-manager",
|
|
8561
|
+
OPEN_EXTERNAL: "backend:open-external",
|
|
8272
8562
|
BATCH_TOGGLE_PLUGINS: "backend:batch-toggle-plugins",
|
|
8273
|
-
|
|
8563
|
+
GET_SUPPORT_SCENES: "backend:get-support-scenes"
|
|
8274
8564
|
};
|
|
8275
8565
|
/**
|
|
8276
8566
|
* 生成唯一请求 ID
|
|
@@ -8551,6 +8841,33 @@ var IPCBackendProvider = class {
|
|
|
8551
8841
|
}
|
|
8552
8842
|
}
|
|
8553
8843
|
/**
|
|
8844
|
+
* 关闭 Agent Manager 面板
|
|
8845
|
+
* IDE 环境: 通过 IPC 通知 IDE 关闭 Agent Manager(用于返回 IDE)
|
|
8846
|
+
*/
|
|
8847
|
+
async closeAgentManager() {
|
|
8848
|
+
this.log("Triggering close agent manager via IPC");
|
|
8849
|
+
try {
|
|
8850
|
+
await this.sendBackendRequest(BACKEND_REQUEST_TYPES.CLOSE_AGENT_MANAGER);
|
|
8851
|
+
} catch (error) {
|
|
8852
|
+
this.log("Close agent manager request failed:", error);
|
|
8853
|
+
throw error;
|
|
8854
|
+
}
|
|
8855
|
+
}
|
|
8856
|
+
/**
|
|
8857
|
+
* 在外部浏览器中打开链接
|
|
8858
|
+
* IDE 环境: 通过 IPC 通知 IDE 使用 vscode.env.openExternal 打开 URL
|
|
8859
|
+
* @param url 要打开的 URL
|
|
8860
|
+
*/
|
|
8861
|
+
async openExternal(url) {
|
|
8862
|
+
this.log("Opening external URL via IPC:", url);
|
|
8863
|
+
try {
|
|
8864
|
+
await this.sendBackendRequest(BACKEND_REQUEST_TYPES.OPEN_EXTERNAL, { url });
|
|
8865
|
+
} catch (error) {
|
|
8866
|
+
this.log("Open external request failed:", error);
|
|
8867
|
+
throw error;
|
|
8868
|
+
}
|
|
8869
|
+
}
|
|
8870
|
+
/**
|
|
8554
8871
|
* 批量切换插件状态
|
|
8555
8872
|
* IDE 环境: 通过 IPC 调用 Extension Host 的 PluginService
|
|
8556
8873
|
*/
|
|
@@ -8564,22 +8881,22 @@ var IPCBackendProvider = class {
|
|
|
8564
8881
|
}
|
|
8565
8882
|
}
|
|
8566
8883
|
/**
|
|
8567
|
-
*
|
|
8884
|
+
* 获取支持的场景列表
|
|
8568
8885
|
* IDE 环境: 通过 IPC 调用后端 API
|
|
8569
8886
|
* 用于 Welcome 页面的 QuickActions 快捷操作
|
|
8570
8887
|
*
|
|
8571
8888
|
* 调用链:
|
|
8572
|
-
* 1. agent-ui: IPCBackendProvider.
|
|
8573
|
-
* 2. Extension Host: BackendBridgeService.
|
|
8574
|
-
* 3. Backend API: GET /v2/as/support/
|
|
8575
|
-
* 4. 返回
|
|
8889
|
+
* 1. agent-ui: IPCBackendProvider.getSupportScenes()
|
|
8890
|
+
* 2. Extension Host: BackendBridgeService.handleGetSupportScenes()
|
|
8891
|
+
* 3. Backend API: GET /v2/as/support/scenes
|
|
8892
|
+
* 4. 返回 SupportScene[] 数据给 agent-ui
|
|
8576
8893
|
*/
|
|
8577
|
-
async
|
|
8578
|
-
this.log("Getting support
|
|
8894
|
+
async getSupportScenes() {
|
|
8895
|
+
this.log("Getting support scenes via IPC");
|
|
8579
8896
|
try {
|
|
8580
|
-
return (await this.sendBackendRequest(BACKEND_REQUEST_TYPES.
|
|
8897
|
+
return (await this.sendBackendRequest(BACKEND_REQUEST_TYPES.GET_SUPPORT_SCENES, {}))?.scenes || [];
|
|
8581
8898
|
} catch (error) {
|
|
8582
|
-
this.log("Get support
|
|
8899
|
+
this.log("Get support scenes failed:", error);
|
|
8583
8900
|
return [];
|
|
8584
8901
|
}
|
|
8585
8902
|
}
|