@tencent-ai/cloud-agent-sdk 0.2.12 → 0.2.13-next.bb9822d.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 CHANGED
@@ -2411,7 +2411,7 @@ var CloudAgentConnection = class {
2411
2411
  }
2412
2412
  async createSession(params) {
2413
2413
  return {
2414
- ...await this.client.loadSession(this.agentId, this.cwd),
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) this.notifyListeners();
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
@@ -16922,15 +16947,9 @@ var CloudAgentProvider = class CloudAgentProvider {
16922
16947
  const url = this.buildGetUrl("/console/as/conversations/", params);
16923
16948
  const apiResponse = await httpService.get(url);
16924
16949
  if (!apiResponse.data) throw new Error("No data in API response");
16925
- const agents = apiResponse.data.conversations.map((a) => this.toAgentState(a));
16926
- const pagination = apiResponse.data.pagination;
16927
- console.log("[CloudAgentProvider] API response:", {
16928
- agentsCount: agents.length,
16929
- pagination
16930
- });
16931
16950
  return {
16932
- agents,
16933
- pagination
16951
+ agents: apiResponse.data.conversations.map((a) => this.toAgentState(a)),
16952
+ pagination: apiResponse.data.pagination
16934
16953
  };
16935
16954
  } catch (error) {
16936
16955
  this.logger?.error("Failed to list agents:", error);
@@ -16940,13 +16959,19 @@ var CloudAgentProvider = class CloudAgentProvider {
16940
16959
  /**
16941
16960
  * Create a new conversation
16942
16961
  * POST {endpoint}/console/as/conversations
16962
+ * @param params - Optional session params containing _meta with tags
16943
16963
  */
16944
- async create() {
16964
+ async create(params) {
16945
16965
  try {
16946
- const apiResponse = await httpService.post("/console/as/conversations/", {
16966
+ const tagsObj = (params?._meta?.["codebuddy.ai"])?.tags;
16967
+ const tagsArray = tagsObj ? Object.entries(tagsObj).map(([key, value]) => `${key}:${value}`) : void 0;
16968
+ const createPayload = {
16947
16969
  prompt: "",
16948
- model: "deepseek-r1"
16949
- });
16970
+ model: "deepseek-r1",
16971
+ ...tagsArray && tagsArray.length > 0 ? { tags: tagsArray } : {}
16972
+ };
16973
+ console.log("[CloudAgentProvider] Creating conversation with payload:", createPayload);
16974
+ const apiResponse = await httpService.post("/console/as/conversations/", createPayload);
16950
16975
  if (!apiResponse.data) throw new Error("No data in API response");
16951
16976
  this.logger?.info(`Created conversation: ${apiResponse.data.id}`);
16952
16977
  return apiResponse.data.id;
@@ -17338,7 +17363,8 @@ var CloudAgentProvider = class CloudAgentProvider {
17338
17363
  type: "cloud",
17339
17364
  status,
17340
17365
  createdAt: data.createdAt ? new Date(data.createdAt) : void 0,
17341
- capabilities: this.options.clientCapabilities
17366
+ capabilities: this.options.clientCapabilities,
17367
+ isUserDefinedTitle: data.isUserDefinedTitle
17342
17368
  };
17343
17369
  }
17344
17370
  /**
@@ -17643,8 +17669,8 @@ var ActiveSessionImpl = class {
17643
17669
  * await session.setMode('architect');
17644
17670
  * ```
17645
17671
  */
17646
- async setMode(modeId) {
17647
- if (this._availableModes) {
17672
+ async setMode(modeId, skipAvailableChecker) {
17673
+ if (this._availableModes && !skipAvailableChecker) {
17648
17674
  if (!this._availableModes.some((m) => m.id === modeId)) {
17649
17675
  const availableIds = this._availableModes.map((m) => m.id).join(", ");
17650
17676
  throw new Error(`Invalid modeId: "${modeId}". Available modes: ${availableIds}`);
@@ -17835,14 +17861,6 @@ var ActiveSessionImpl = class {
17835
17861
  //#endregion
17836
17862
  //#region ../agent-provider/src/common/client/session-manager.ts
17837
17863
  /**
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
17864
  * SessionManager - Session lifecycle management
17847
17865
  *
17848
17866
  * This class manages the relationship between sessions and agents.
@@ -17892,7 +17910,8 @@ var SessionManager = class {
17892
17910
  createdAt: agent.createdAt,
17893
17911
  lastActivityAt: agent.updatedAt,
17894
17912
  cwd: agent.type === "local" ? agent.cwd : void 0,
17895
- isPlayground: agent.isPlayground
17913
+ isPlayground: agent.isPlayground,
17914
+ isUserDefinedTitle: agent.isUserDefinedTitle
17896
17915
  }));
17897
17916
  console.log("[SessionManager] Returning sessions:", {
17898
17917
  count: sessions.length,
@@ -17938,14 +17957,8 @@ var SessionManager = class {
17938
17957
  connectionInfo
17939
17958
  });
17940
17959
  session.setModes(response.modes?.availableModes, response.modes?.currentModeId);
17941
- if (response.models?.availableModels) {
17942
- const localModels = response.models.availableModels.map((m) => ({
17943
- id: m.modelId,
17944
- name: m.name,
17945
- description: m.description ?? void 0
17946
- }));
17947
- session.setModels(localModels, response.models?.currentModelId);
17948
- }
17960
+ const availableModels = this.extractAvailableModels(response);
17961
+ if (availableModels) session.setModels(availableModels, response.models?.currentModelId);
17949
17962
  this.logger?.info(`Session created: ${response.sessionId}`);
17950
17963
  return session;
17951
17964
  }
@@ -17981,17 +17994,31 @@ var SessionManager = class {
17981
17994
  mcpServers: params.mcpServers
17982
17995
  });
17983
17996
  session.setModes(response.modes?.availableModes, response.modes?.currentModeId);
17984
- if (response.models?.availableModels) {
17985
- const localModels = response.models.availableModels.map((m) => ({
17986
- id: m.modelId,
17987
- name: m.name,
17988
- description: m.description ?? void 0
17989
- }));
17990
- session.setModels(localModels, response.models?.currentModelId);
17991
- }
17997
+ const availableModels = this.extractAvailableModels(response);
17998
+ if (availableModels) session.setModels(availableModels, response.models?.currentModelId);
17992
17999
  this.logger?.info(`Session loaded: ${params.sessionId}`);
17993
18000
  return session;
17994
18001
  }
18002
+ /**
18003
+ * 从 ACP response 中提取可用模型列表
18004
+ *
18005
+ * 优先级:
18006
+ * 1. response.models._meta?.['codebuddy.ai']?.availableModels - 包含完整的模型信息(字段名为 'id')
18007
+ * 2. response.models?.availableModels - 只包含基本信息(字段名为 'modelId')
18008
+ * 3. undefined - 都没有时返回 undefined
18009
+ *
18010
+ * @param response - ACP 响应对象
18011
+ * @returns ModelInfo[] | undefined
18012
+ */
18013
+ extractAvailableModels(response) {
18014
+ const metaModels = (response.models?._meta?.["codebuddy.ai"])?.availableModels;
18015
+ if (metaModels && Array.isArray(metaModels) && metaModels.length > 0) return metaModels;
18016
+ const availableModels = response.models?.availableModels;
18017
+ if (availableModels && Array.isArray(availableModels) && availableModels.length > 0) return availableModels.map((model) => ({
18018
+ ...model,
18019
+ ...model._meta?.["codebuddy.ai"] || {}
18020
+ }));
18021
+ }
17995
18022
  };
17996
18023
 
17997
18024
  //#endregion
@@ -18264,6 +18291,28 @@ var AgentClient = class {
18264
18291
  };
18265
18292
  }
18266
18293
  },
18294
+ getSubagentList: async (params) => {
18295
+ try {
18296
+ if (this.provider && this.provider.getSubagentList) {
18297
+ const result = await this.provider.getSubagentList(params);
18298
+ this.logger?.info("Subagent list retrieved", {
18299
+ resultCount: result.results.length,
18300
+ hasError: !!result.error
18301
+ });
18302
+ return result;
18303
+ }
18304
+ return {
18305
+ results: [],
18306
+ error: "Provider does not support getSubagentList"
18307
+ };
18308
+ } catch (error) {
18309
+ this.logger?.error("Failed to get subagent list", error);
18310
+ return {
18311
+ results: [],
18312
+ error: error instanceof Error ? error.message : "Unknown error"
18313
+ };
18314
+ }
18315
+ },
18267
18316
  batchTogglePlugins: async (request) => {
18268
18317
  try {
18269
18318
  if (this.provider && this.provider.batchTogglePlugins) {
@@ -18308,10 +18357,10 @@ var AgentClient = class {
18308
18357
  return [];
18309
18358
  }
18310
18359
  },
18311
- installPlugins: async (pluginNames, marketplaceName, installScope) => {
18360
+ installPlugins: async (pluginNames, marketplaceName, installScope, marketplaceSource) => {
18312
18361
  try {
18313
18362
  if (this.provider && "installPlugins" in this.provider && typeof this.provider.installPlugins === "function") {
18314
- const result = await this.provider.installPlugins(pluginNames, marketplaceName, installScope);
18363
+ const result = await this.provider.installPlugins(pluginNames, marketplaceName, installScope, marketplaceSource);
18315
18364
  this.logger?.info("Install plugins", {
18316
18365
  pluginNames,
18317
18366
  marketplaceName,
@@ -18346,6 +18395,23 @@ var AgentClient = class {
18346
18395
  return [];
18347
18396
  }
18348
18397
  },
18398
+ getAvailableCommands: async (sessionId) => {
18399
+ try {
18400
+ if (this.provider && "getAvailableCommands" in this.provider && typeof this.provider.getAvailableCommands === "function") {
18401
+ const result = await this.provider.getAvailableCommands(sessionId);
18402
+ this.logger?.info("Got available commands from provider", {
18403
+ sessionId: sessionId ?? "(default)",
18404
+ count: result?.length ?? 0
18405
+ });
18406
+ return result;
18407
+ }
18408
+ this.logger?.warn("Provider does not support getAvailableCommands", { sessionId });
18409
+ return [];
18410
+ } catch (error) {
18411
+ this.logger?.error("Failed to get available commands", error);
18412
+ return [];
18413
+ }
18414
+ },
18349
18415
  models: this.createModelsResource()
18350
18416
  };
18351
18417
  }
@@ -18412,6 +18478,154 @@ let AccountStatus = /* @__PURE__ */ function(AccountStatus) {
18412
18478
  return AccountStatus;
18413
18479
  }({});
18414
18480
 
18481
+ //#endregion
18482
+ //#region ../agent-provider/src/backend/service/oauth-repository-service.ts
18483
+ /**
18484
+ * OAuth Repository Service
18485
+ *
18486
+ * 封装 OAuth 连接器相关的仓库和分支操作
18487
+ */
18488
+ /**
18489
+ * OAuth Repository Service
18490
+ *
18491
+ * 提供仓库和分支的查询操作
18492
+ */
18493
+ var OAuthRepositoryService = class {
18494
+ /**
18495
+ * 获取仓库分支列表
18496
+ * API 端点: GET /console/as/connector/oauth/{name}/branches
18497
+ *
18498
+ * @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
18499
+ * @param params 平台特定的查询参数
18500
+ * @param page 页码,从1开始,0表示不分页获取全部
18501
+ * @param perPage 每页数量,最大100
18502
+ * @returns Promise<OauthBranch[]> 分支列表
18503
+ *
18504
+ * @example
18505
+ * ```typescript
18506
+ * // GitHub
18507
+ * const branches = await service.getBranches('github', {
18508
+ * owner: 'CodeBuddy-Official-Account',
18509
+ * repo: 'CodeBuddyIDE'
18510
+ * });
18511
+ *
18512
+ * // Gongfeng
18513
+ * const branches = await service.getBranches('gongfeng', {
18514
+ * project_id: '1611499'
18515
+ * });
18516
+ *
18517
+ * // CNB
18518
+ * const branches = await service.getBranches('cnb', {
18519
+ * repo: 'genie/genie-ide'
18520
+ * });
18521
+ * ```
18522
+ */
18523
+ async getBranches(connector, params, page = 0, perPage = 100) {
18524
+ try {
18525
+ const url = `/console/as/connector/oauth/${connector}/branches?${this.buildBranchQueryParams(connector, params, page, perPage).toString()}`;
18526
+ console.log(`[OAuthRepositoryService] GET ${url}`);
18527
+ const apiResponse = await httpService.get(url);
18528
+ if (!apiResponse.data) {
18529
+ console.warn(`[OAuthRepositoryService] No data in branches response for ${connector}`);
18530
+ return [];
18531
+ }
18532
+ const branches = apiResponse.data.branches || [];
18533
+ console.log(`[OAuthRepositoryService] Retrieved ${branches.length} branches from ${connector}`);
18534
+ return branches;
18535
+ } catch (error) {
18536
+ console.error(`[OAuthRepositoryService] Failed to get branches from ${connector}:`, error);
18537
+ throw error;
18538
+ }
18539
+ }
18540
+ /**
18541
+ * 获取仓库列表
18542
+ * API 端点: GET /console/as/connector/oauth/{name}/repos
18543
+ *
18544
+ * Note: 由于工蜂原生支持的 Search 能力会匹配 path/name/description 部分,
18545
+ * 且不支持定制,不满足产品要求(只按 name 匹配),因此前端拉取全量数据后做筛选。
18546
+ *
18547
+ * @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
18548
+ * @param page 页码,从1开始,0表示不分页获取全部
18549
+ * - GitHub 只支持全量数据,必须传 0
18550
+ * - 工蜂和 CNB 依据前端逻辑而定
18551
+ * @param perPage 每页数量,最大100
18552
+ * @returns Promise<ListReposResponse> 仓库列表响应
18553
+ *
18554
+ * @example
18555
+ * ```typescript
18556
+ * // GitHub - 必须传 page=0 获取全量数据
18557
+ * const response = await service.getRepositories('github', 0, 100);
18558
+ * // response.github_repos 是 map: installation_id => repo[]
18559
+ *
18560
+ * // Gongfeng
18561
+ * const response = await service.getRepositories('gongfeng', 0, 100);
18562
+ * // response.gongfeng_repos 是数组
18563
+ *
18564
+ * // CNB
18565
+ * const response = await service.getRepositories('cnb', 0, 100);
18566
+ * // response.cnb_repos 是数组
18567
+ * ```
18568
+ */
18569
+ async getRepositories(connector, page = 0, perPage = 100) {
18570
+ try {
18571
+ const queryParams = new URLSearchParams();
18572
+ queryParams.append("page", String(page));
18573
+ queryParams.append("per_page", String(Math.min(perPage, 100)));
18574
+ const url = `/console/as/connector/oauth/${connector}/repos?${queryParams.toString()}`;
18575
+ console.log(`[OAuthRepositoryService] GET ${url}`);
18576
+ const apiResponse = await httpService.get(url);
18577
+ if (!apiResponse.data) {
18578
+ console.warn(`[OAuthRepositoryService] No data in repos response for ${connector}`);
18579
+ return {};
18580
+ }
18581
+ const response = apiResponse.data;
18582
+ this.logRepositoryCounts(response);
18583
+ return response;
18584
+ } catch (error) {
18585
+ console.error(`[OAuthRepositoryService] Failed to get repos from ${connector}:`, error);
18586
+ throw error;
18587
+ }
18588
+ }
18589
+ /**
18590
+ * 构建分支查询参数
18591
+ */
18592
+ buildBranchQueryParams(connector, params, page, perPage) {
18593
+ const queryParams = new URLSearchParams();
18594
+ queryParams.append("page", String(page));
18595
+ queryParams.append("per_page", String(Math.min(perPage, 100)));
18596
+ if (connector === "github") {
18597
+ const githubParams = params;
18598
+ if (!githubParams.owner || !githubParams.repo) throw new Error("GitHub requires owner and repo parameters");
18599
+ queryParams.append("owner", githubParams.owner);
18600
+ queryParams.append("repo", githubParams.repo);
18601
+ } else if (connector === "gongfeng") {
18602
+ const gongfengParams = params;
18603
+ if (!gongfengParams.project_id) throw new Error("Gongfeng requires project_id parameter");
18604
+ queryParams.append("project_id", gongfengParams.project_id);
18605
+ } else if (connector === "cnb") {
18606
+ const cnbParams = params;
18607
+ if (!cnbParams.repo) throw new Error("CNB requires repo parameter");
18608
+ queryParams.append("repo", cnbParams.repo);
18609
+ } else throw new Error(`Unknown connector: ${connector}`);
18610
+ return queryParams;
18611
+ }
18612
+ /**
18613
+ * 记录仓库数量日志
18614
+ */
18615
+ logRepositoryCounts(response) {
18616
+ if (response.github_repos) {
18617
+ const totalCount = Object.values(response.github_repos).reduce((sum, repos) => sum + repos.length, 0);
18618
+ console.log(`[OAuthRepositoryService] Retrieved ${totalCount} GitHub repos across ${Object.keys(response.github_repos).length} installations`);
18619
+ }
18620
+ if (response.gongfeng_repos) console.log(`[OAuthRepositoryService] Retrieved ${response.gongfeng_repos.length} Gongfeng repos`);
18621
+ if (response.cnb_repos) console.log(`[OAuthRepositoryService] Retrieved ${response.cnb_repos.length} CNB repos`);
18622
+ }
18623
+ };
18624
+ /**
18625
+ * OAuth Repository Service 单例实例
18626
+ */
18627
+ const oauthRepositoryService = new OAuthRepositoryService();
18628
+
18415
18629
  //#endregion
18416
18630
  //#region ../agent-provider/src/backend/backend-provider.ts
18417
18631
  /**
@@ -18420,27 +18634,29 @@ let AccountStatus = /* @__PURE__ */ function(AccountStatus) {
18420
18634
  * 封装与后端 API 的 HTTP 通信
18421
18635
  */
18422
18636
  /**
18423
- * 判断当前是否在 SSO 域名下
18424
- * SSO 域名格式: xxx.sso.copilot.tencent.com xxx.sso.codebuddy.cn
18637
+ * 判断当前账号是否是 SSO 账号
18638
+ * 通过 account.accountType === 'sso' 来判断,这种不行,因为未登录之前account 为空
18425
18639
  */
18426
18640
  const isSSODomain = () => {
18427
18641
  const { hostname } = window.location;
18428
18642
  return hostname.includes(".sso.copilot") || hostname.includes("sso.codebuddy.cn") || hostname.includes(".sso.copilot-staging") || hostname.includes(".staging-sso.codebuddy.cn");
18429
18643
  };
18430
18644
  /**
18431
- * 获取登录页面 URL
18432
- * - SSO 域名下需要跳转到对应的预发/生产域名
18433
- * - 非 SSO 域名直接使用当前域名
18645
+ * 根据路径获取完整 URL
18646
+ * - SSO 账号需要跳转到对应的预发/生产域名
18647
+ * - 非 SSO 账号直接使用当前域名
18648
+ * @param path 路径,如 '/login'、'/logout'、'/home' 等
18649
+ * @returns 完整的 URL 地址
18434
18650
  */
18435
- const getLoginUrl = () => {
18651
+ const getFullUrl = (path) => {
18436
18652
  const { hostname, protocol } = window.location;
18437
18653
  if (isSSODomain()) {
18438
18654
  const isCodebuddy = hostname.includes("codebuddy.cn");
18439
18655
  const isStaging = hostname.includes("staging");
18440
- if (isCodebuddy) return isStaging ? `${protocol}//staging.codebuddy.cn/login` : `${protocol}//www.codebuddy.cn/login`;
18441
- else return isStaging ? `${protocol}//staging-copilot.tencent.com/login` : `${protocol}//copilot.tencent.com/login`;
18656
+ if (isCodebuddy) return isStaging ? `${protocol}//staging.codebuddy.cn${path}` : `${protocol}//www.codebuddy.cn${path}`;
18657
+ else return isStaging ? `${protocol}//staging-copilot.tencent.com${path}` : `${protocol}//copilot.tencent.com${path}`;
18442
18658
  }
18443
- return `${window.location.origin}/login`;
18659
+ return `${window.location.origin}${path}`;
18444
18660
  };
18445
18661
  /** 获取当前域名的账号选择页面 URL */
18446
18662
  const getSelectAccountUrl = () => `${window.location.origin}/login/select`;
@@ -18528,7 +18744,7 @@ var BackendProvider = class {
18528
18744
  return account;
18529
18745
  }
18530
18746
  const redirectUrl = encodeURIComponent(window.location.href);
18531
- window.location.href = `${getSelectAccountUrl()}?platform=website&state=0&redirect_uri=${redirectUrl}`;
18747
+ window.location.href = `${getSelectAccountUrl()}?platform=agents&state=0&redirect_uri=${redirectUrl}`;
18532
18748
  accountService.setAccount(null);
18533
18749
  return null;
18534
18750
  } catch (error) {
@@ -18551,7 +18767,8 @@ var BackendProvider = class {
18551
18767
  activeStatus: connector.active_status,
18552
18768
  displayName: connector.display_name,
18553
18769
  oauthClientId: connector.oauth_client_id,
18554
- oauthRedirectUrl: connector.oauth_redirect_url
18770
+ oauthRedirectUrl: connector.oauth_redirect_url,
18771
+ oauthAppName: connector.oauth_app_name
18555
18772
  })) };
18556
18773
  }
18557
18774
  throw result;
@@ -18633,7 +18850,8 @@ var BackendProvider = class {
18633
18850
  connectStatus: connector.connect_status,
18634
18851
  displayName: connector.display_name,
18635
18852
  oauthClientId: connector.oauth_client_id,
18636
- oauthRedirectUrl: connector.oauth_redirect_url
18853
+ oauthRedirectUrl: connector.oauth_redirect_url,
18854
+ oauthAppName: connector.oauth_app_name
18637
18855
  })) };
18638
18856
  }
18639
18857
  throw result;
@@ -18890,7 +19108,7 @@ var BackendProvider = class {
18890
19108
  */
18891
19109
  async login() {
18892
19110
  const redirectUrl = encodeURIComponent(window.location.href);
18893
- window.location.href = `${getLoginUrl()}?platform=website&state=0&redirect_uri=${redirectUrl}`;
19111
+ window.location.href = `${getFullUrl("/login")}?platform=agents&state=0&redirect_uri=${redirectUrl}`;
18894
19112
  }
18895
19113
  /**
18896
19114
  * 登出账号
@@ -18953,6 +19171,52 @@ var BackendProvider = class {
18953
19171
  return null;
18954
19172
  }
18955
19173
  }
19174
+ /**
19175
+ * 刷新 Token
19176
+ * 通过调用 getAccount 刷新 cookie,适用于 Cloud 场景下页面切换回来时刷新登录态
19177
+ * @returns Promise<Account | null> 刷新后的账号信息
19178
+ */
19179
+ async refreshToken() {
19180
+ console.log("[BackendProvider] Refreshing token...");
19181
+ try {
19182
+ const account = await this.getAccount();
19183
+ console.log("[BackendProvider] Token refreshed, account:", account?.uid);
19184
+ return account;
19185
+ } catch (error) {
19186
+ console.error("[BackendProvider] refreshToken failed:", error);
19187
+ return null;
19188
+ }
19189
+ }
19190
+ /**
19191
+ * 获取仓库分支列表
19192
+ * API 端点: GET /console/as/connector/oauth/{name}/branches
19193
+ *
19194
+ * @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
19195
+ * @param params 平台特定的查询参数
19196
+ * @param page 页码,从1开始,0表示不分页获取全部
19197
+ * @param perPage 每页数量,最大100
19198
+ * @returns Promise<OauthBranch[]> 分支列表
19199
+ */
19200
+ async getBranches(connector, params, page = 0, perPage = 100) {
19201
+ return oauthRepositoryService.getBranches(connector, params, page, perPage);
19202
+ }
19203
+ /**
19204
+ * 获取仓库列表
19205
+ * API 端点: GET /console/as/connector/oauth/{name}/repos
19206
+ *
19207
+ * Note: 由于工蜂原生支持的 Search 能力会匹配 path/name/description 部分,
19208
+ * 且不支持定制,不满足产品要求(只按 name 匹配),因此前端拉取全量数据后做筛选。
19209
+ *
19210
+ * @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
19211
+ * @param page 页码,从1开始,0表示不分页获取全部
19212
+ * - GitHub 只支持全量数据,必须传 0
19213
+ * - 工蜂和 CNB 依据前端逻辑而定
19214
+ * @param perPage 每页数量,最大100
19215
+ * @returns Promise<ListReposResponse> 仓库列表响应
19216
+ */
19217
+ async getRepositories(connector, page = 0, perPage = 100) {
19218
+ return oauthRepositoryService.getRepositories(connector, page, perPage);
19219
+ }
18956
19220
  };
18957
19221
  /**
18958
19222
  * 创建 BackendProvider 实例
@@ -18992,6 +19256,7 @@ const BACKEND_REQUEST_TYPES = {
18992
19256
  GET_FILE: "backend:get-file",
18993
19257
  RELOAD_WINDOW: "backend:reload-window",
18994
19258
  CLOSE_AGENT_MANAGER: "backend:close-agent-manager",
19259
+ OPEN_EXTERNAL: "backend:open-external",
18995
19260
  BATCH_TOGGLE_PLUGINS: "backend:batch-toggle-plugins",
18996
19261
  GET_SUPPORT_SCENES: "backend:get-support-scenes"
18997
19262
  };
@@ -19287,6 +19552,20 @@ var IPCBackendProvider = class {
19287
19552
  }
19288
19553
  }
19289
19554
  /**
19555
+ * 在外部浏览器中打开链接
19556
+ * IDE 环境: 通过 IPC 通知 IDE 使用 vscode.env.openExternal 打开 URL
19557
+ * @param url 要打开的 URL
19558
+ */
19559
+ async openExternal(url) {
19560
+ this.log("Opening external URL via IPC:", url);
19561
+ try {
19562
+ await this.sendBackendRequest(BACKEND_REQUEST_TYPES.OPEN_EXTERNAL, { url });
19563
+ } catch (error) {
19564
+ this.log("Open external request failed:", error);
19565
+ throw error;
19566
+ }
19567
+ }
19568
+ /**
19290
19569
  * 批量切换插件状态
19291
19570
  * IDE 环境: 通过 IPC 调用 Extension Host 的 PluginService
19292
19571
  */