@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.mjs CHANGED
@@ -2372,7 +2372,7 @@ var CloudAgentConnection = class {
2372
2372
  }
2373
2373
  async createSession(params) {
2374
2374
  return {
2375
- ...await this.client.loadSession(this.agentId, this.cwd),
2375
+ ...await this.client.createSession(this.cwd),
2376
2376
  sessionId: this.agentId
2377
2377
  };
2378
2378
  }
@@ -5542,6 +5542,7 @@ var AccountService = class {
5542
5542
  this.initPromise = null;
5543
5543
  this.initResolve = null;
5544
5544
  this.requestInterceptorId = null;
5545
+ this.crossTabBroadcaster = null;
5545
5546
  this.initPromise = new Promise((resolve) => {
5546
5547
  this.initResolve = resolve;
5547
5548
  });
@@ -5590,15 +5591,34 @@ var AccountService = class {
5590
5591
  this.initialized = true;
5591
5592
  this.initResolve?.(account);
5592
5593
  }
5593
- if (!wasInitialized || prev?.uid !== account?.uid) this.notifyListeners();
5594
+ if (!wasInitialized || prev?.uid !== account?.uid) {
5595
+ this.notifyListeners();
5596
+ if (account && this.crossTabBroadcaster) this.crossTabBroadcaster.broadcastLogin();
5597
+ }
5594
5598
  }
5595
5599
  /**
5596
5600
  * 清除账号(登出)
5601
+ * 先广播登出消息,再清除本地账号
5597
5602
  */
5598
5603
  clearAccount() {
5604
+ if (this.crossTabBroadcaster) this.crossTabBroadcaster.broadcastLogout();
5605
+ this.setAccount(null);
5606
+ }
5607
+ /**
5608
+ * 静默清除账号(不广播)
5609
+ * 用于收到其他标签页 logout 消息时,避免循环广播
5610
+ */
5611
+ clearAccountSilently() {
5599
5612
  this.setAccount(null);
5600
5613
  }
5601
5614
  /**
5615
+ * 设置跨标签页认证同步广播器
5616
+ * 应在应用初始化时由上层(如 agent-ui)调用
5617
+ */
5618
+ setCrossTabBroadcaster(broadcaster) {
5619
+ this.crossTabBroadcaster = broadcaster;
5620
+ }
5621
+ /**
5602
5622
  * 订阅账号变化
5603
5623
  * @param callback 变化时的回调函数
5604
5624
  * @returns 取消订阅函数
@@ -5663,6 +5683,11 @@ var AccountService = class {
5663
5683
  * 导出单例实例
5664
5684
  */
5665
5685
  const accountService = new AccountService();
5686
+ /**
5687
+ * 暴露给全局,供 Agent Manager 直接调用 setAccount 刷新 Widget 状态
5688
+ * 这是为了解决 IDE 环境中 IPC 事件无法直接触发 Widget 账号刷新的问题
5689
+ */
5690
+ if (typeof window !== "undefined") window.__genieAccountService = accountService;
5666
5691
 
5667
5692
  //#endregion
5668
5693
  //#region ../agent-provider/src/common/utils/concurrency.ts
@@ -6252,15 +6277,9 @@ var CloudAgentProvider = class CloudAgentProvider {
6252
6277
  const url = this.buildGetUrl("/console/as/conversations/", params);
6253
6278
  const apiResponse = await httpService.get(url);
6254
6279
  if (!apiResponse.data) throw new Error("No data in API response");
6255
- const agents = apiResponse.data.conversations.map((a) => this.toAgentState(a));
6256
- const pagination = apiResponse.data.pagination;
6257
- console.log("[CloudAgentProvider] API response:", {
6258
- agentsCount: agents.length,
6259
- pagination
6260
- });
6261
6280
  return {
6262
- agents,
6263
- pagination
6281
+ agents: apiResponse.data.conversations.map((a) => this.toAgentState(a)),
6282
+ pagination: apiResponse.data.pagination
6264
6283
  };
6265
6284
  } catch (error) {
6266
6285
  this.logger?.error("Failed to list agents:", error);
@@ -6270,13 +6289,19 @@ var CloudAgentProvider = class CloudAgentProvider {
6270
6289
  /**
6271
6290
  * Create a new conversation
6272
6291
  * POST {endpoint}/console/as/conversations
6292
+ * @param params - Optional session params containing _meta with tags
6273
6293
  */
6274
- async create() {
6294
+ async create(params) {
6275
6295
  try {
6276
- const apiResponse = await httpService.post("/console/as/conversations/", {
6296
+ const tagsObj = (params?._meta?.["codebuddy.ai"])?.tags;
6297
+ const tagsArray = tagsObj ? Object.entries(tagsObj).map(([key, value]) => `${key}:${value}`) : void 0;
6298
+ const createPayload = {
6277
6299
  prompt: "",
6278
- model: "deepseek-r1"
6279
- });
6300
+ model: "deepseek-r1",
6301
+ ...tagsArray && tagsArray.length > 0 ? { tags: tagsArray } : {}
6302
+ };
6303
+ console.log("[CloudAgentProvider] Creating conversation with payload:", createPayload);
6304
+ const apiResponse = await httpService.post("/console/as/conversations/", createPayload);
6280
6305
  if (!apiResponse.data) throw new Error("No data in API response");
6281
6306
  this.logger?.info(`Created conversation: ${apiResponse.data.id}`);
6282
6307
  return apiResponse.data.id;
@@ -6668,7 +6693,8 @@ var CloudAgentProvider = class CloudAgentProvider {
6668
6693
  type: "cloud",
6669
6694
  status,
6670
6695
  createdAt: data.createdAt ? new Date(data.createdAt) : void 0,
6671
- capabilities: this.options.clientCapabilities
6696
+ capabilities: this.options.clientCapabilities,
6697
+ isUserDefinedTitle: data.isUserDefinedTitle
6672
6698
  };
6673
6699
  }
6674
6700
  /**
@@ -6963,8 +6989,8 @@ var ActiveSessionImpl = class {
6963
6989
  * await session.setMode('architect');
6964
6990
  * ```
6965
6991
  */
6966
- async setMode(modeId) {
6967
- if (this._availableModes) {
6992
+ async setMode(modeId, skipAvailableChecker) {
6993
+ if (this._availableModes && !skipAvailableChecker) {
6968
6994
  if (!this._availableModes.some((m) => m.id === modeId)) {
6969
6995
  const availableIds = this._availableModes.map((m) => m.id).join(", ");
6970
6996
  throw new Error(`Invalid modeId: "${modeId}". Available modes: ${availableIds}`);
@@ -7155,14 +7181,6 @@ var ActiveSessionImpl = class {
7155
7181
  //#endregion
7156
7182
  //#region ../agent-provider/src/common/client/session-manager.ts
7157
7183
  /**
7158
- * SessionManager - Manages session lifecycle and connections
7159
- *
7160
- * Provides the core implementation for session-centric API operations:
7161
- * - list() - Lists sessions (mapped from agents)
7162
- * - createSession() - Creates new session (auto-creates agent)
7163
- * - loadSession() - Loads existing session (finds agent by sessionId)
7164
- */
7165
- /**
7166
7184
  * SessionManager - Session lifecycle management
7167
7185
  *
7168
7186
  * This class manages the relationship between sessions and agents.
@@ -7212,7 +7230,8 @@ var SessionManager = class {
7212
7230
  createdAt: agent.createdAt,
7213
7231
  lastActivityAt: agent.updatedAt,
7214
7232
  cwd: agent.type === "local" ? agent.cwd : void 0,
7215
- isPlayground: agent.isPlayground
7233
+ isPlayground: agent.isPlayground,
7234
+ isUserDefinedTitle: agent.isUserDefinedTitle
7216
7235
  }));
7217
7236
  console.log("[SessionManager] Returning sessions:", {
7218
7237
  count: sessions.length,
@@ -7258,14 +7277,8 @@ var SessionManager = class {
7258
7277
  connectionInfo
7259
7278
  });
7260
7279
  session.setModes(response.modes?.availableModes, response.modes?.currentModeId);
7261
- if (response.models?.availableModels) {
7262
- const localModels = response.models.availableModels.map((m) => ({
7263
- id: m.modelId,
7264
- name: m.name,
7265
- description: m.description ?? void 0
7266
- }));
7267
- session.setModels(localModels, response.models?.currentModelId);
7268
- }
7280
+ const availableModels = this.extractAvailableModels(response);
7281
+ if (availableModels) session.setModels(availableModels, response.models?.currentModelId);
7269
7282
  this.logger?.info(`Session created: ${response.sessionId}`);
7270
7283
  return session;
7271
7284
  }
@@ -7301,17 +7314,31 @@ var SessionManager = class {
7301
7314
  mcpServers: params.mcpServers
7302
7315
  });
7303
7316
  session.setModes(response.modes?.availableModes, response.modes?.currentModeId);
7304
- if (response.models?.availableModels) {
7305
- const localModels = response.models.availableModels.map((m) => ({
7306
- id: m.modelId,
7307
- name: m.name,
7308
- description: m.description ?? void 0
7309
- }));
7310
- session.setModels(localModels, response.models?.currentModelId);
7311
- }
7317
+ const availableModels = this.extractAvailableModels(response);
7318
+ if (availableModels) session.setModels(availableModels, response.models?.currentModelId);
7312
7319
  this.logger?.info(`Session loaded: ${params.sessionId}`);
7313
7320
  return session;
7314
7321
  }
7322
+ /**
7323
+ * 从 ACP response 中提取可用模型列表
7324
+ *
7325
+ * 优先级:
7326
+ * 1. response.models._meta?.['codebuddy.ai']?.availableModels - 包含完整的模型信息(字段名为 'id')
7327
+ * 2. response.models?.availableModels - 只包含基本信息(字段名为 'modelId')
7328
+ * 3. undefined - 都没有时返回 undefined
7329
+ *
7330
+ * @param response - ACP 响应对象
7331
+ * @returns ModelInfo[] | undefined
7332
+ */
7333
+ extractAvailableModels(response) {
7334
+ const metaModels = (response.models?._meta?.["codebuddy.ai"])?.availableModels;
7335
+ if (metaModels && Array.isArray(metaModels) && metaModels.length > 0) return metaModels;
7336
+ const availableModels = response.models?.availableModels;
7337
+ if (availableModels && Array.isArray(availableModels) && availableModels.length > 0) return availableModels.map((model) => ({
7338
+ ...model,
7339
+ ...model._meta?.["codebuddy.ai"] || {}
7340
+ }));
7341
+ }
7315
7342
  };
7316
7343
 
7317
7344
  //#endregion
@@ -7584,6 +7611,28 @@ var AgentClient = class {
7584
7611
  };
7585
7612
  }
7586
7613
  },
7614
+ getSubagentList: async (params) => {
7615
+ try {
7616
+ if (this.provider && this.provider.getSubagentList) {
7617
+ const result = await this.provider.getSubagentList(params);
7618
+ this.logger?.info("Subagent list retrieved", {
7619
+ resultCount: result.results.length,
7620
+ hasError: !!result.error
7621
+ });
7622
+ return result;
7623
+ }
7624
+ return {
7625
+ results: [],
7626
+ error: "Provider does not support getSubagentList"
7627
+ };
7628
+ } catch (error) {
7629
+ this.logger?.error("Failed to get subagent list", error);
7630
+ return {
7631
+ results: [],
7632
+ error: error instanceof Error ? error.message : "Unknown error"
7633
+ };
7634
+ }
7635
+ },
7587
7636
  batchTogglePlugins: async (request) => {
7588
7637
  try {
7589
7638
  if (this.provider && this.provider.batchTogglePlugins) {
@@ -7628,10 +7677,10 @@ var AgentClient = class {
7628
7677
  return [];
7629
7678
  }
7630
7679
  },
7631
- installPlugins: async (pluginNames, marketplaceName, installScope) => {
7680
+ installPlugins: async (pluginNames, marketplaceName, installScope, marketplaceSource) => {
7632
7681
  try {
7633
7682
  if (this.provider && "installPlugins" in this.provider && typeof this.provider.installPlugins === "function") {
7634
- const result = await this.provider.installPlugins(pluginNames, marketplaceName, installScope);
7683
+ const result = await this.provider.installPlugins(pluginNames, marketplaceName, installScope, marketplaceSource);
7635
7684
  this.logger?.info("Install plugins", {
7636
7685
  pluginNames,
7637
7686
  marketplaceName,
@@ -7666,6 +7715,23 @@ var AgentClient = class {
7666
7715
  return [];
7667
7716
  }
7668
7717
  },
7718
+ getAvailableCommands: async (sessionId) => {
7719
+ try {
7720
+ if (this.provider && "getAvailableCommands" in this.provider && typeof this.provider.getAvailableCommands === "function") {
7721
+ const result = await this.provider.getAvailableCommands(sessionId);
7722
+ this.logger?.info("Got available commands from provider", {
7723
+ sessionId: sessionId ?? "(default)",
7724
+ count: result?.length ?? 0
7725
+ });
7726
+ return result;
7727
+ }
7728
+ this.logger?.warn("Provider does not support getAvailableCommands", { sessionId });
7729
+ return [];
7730
+ } catch (error) {
7731
+ this.logger?.error("Failed to get available commands", error);
7732
+ return [];
7733
+ }
7734
+ },
7669
7735
  models: this.createModelsResource()
7670
7736
  };
7671
7737
  }
@@ -7732,6 +7798,154 @@ let AccountStatus = /* @__PURE__ */ function(AccountStatus) {
7732
7798
  return AccountStatus;
7733
7799
  }({});
7734
7800
 
7801
+ //#endregion
7802
+ //#region ../agent-provider/src/backend/service/oauth-repository-service.ts
7803
+ /**
7804
+ * OAuth Repository Service
7805
+ *
7806
+ * 封装 OAuth 连接器相关的仓库和分支操作
7807
+ */
7808
+ /**
7809
+ * OAuth Repository Service
7810
+ *
7811
+ * 提供仓库和分支的查询操作
7812
+ */
7813
+ var OAuthRepositoryService = class {
7814
+ /**
7815
+ * 获取仓库分支列表
7816
+ * API 端点: GET /console/as/connector/oauth/{name}/branches
7817
+ *
7818
+ * @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
7819
+ * @param params 平台特定的查询参数
7820
+ * @param page 页码,从1开始,0表示不分页获取全部
7821
+ * @param perPage 每页数量,最大100
7822
+ * @returns Promise<OauthBranch[]> 分支列表
7823
+ *
7824
+ * @example
7825
+ * ```typescript
7826
+ * // GitHub
7827
+ * const branches = await service.getBranches('github', {
7828
+ * owner: 'CodeBuddy-Official-Account',
7829
+ * repo: 'CodeBuddyIDE'
7830
+ * });
7831
+ *
7832
+ * // Gongfeng
7833
+ * const branches = await service.getBranches('gongfeng', {
7834
+ * project_id: '1611499'
7835
+ * });
7836
+ *
7837
+ * // CNB
7838
+ * const branches = await service.getBranches('cnb', {
7839
+ * repo: 'genie/genie-ide'
7840
+ * });
7841
+ * ```
7842
+ */
7843
+ async getBranches(connector, params, page = 0, perPage = 100) {
7844
+ try {
7845
+ const url = `/console/as/connector/oauth/${connector}/branches?${this.buildBranchQueryParams(connector, params, page, perPage).toString()}`;
7846
+ console.log(`[OAuthRepositoryService] GET ${url}`);
7847
+ const apiResponse = await httpService.get(url);
7848
+ if (!apiResponse.data) {
7849
+ console.warn(`[OAuthRepositoryService] No data in branches response for ${connector}`);
7850
+ return [];
7851
+ }
7852
+ const branches = apiResponse.data.branches || [];
7853
+ console.log(`[OAuthRepositoryService] Retrieved ${branches.length} branches from ${connector}`);
7854
+ return branches;
7855
+ } catch (error) {
7856
+ console.error(`[OAuthRepositoryService] Failed to get branches from ${connector}:`, error);
7857
+ throw error;
7858
+ }
7859
+ }
7860
+ /**
7861
+ * 获取仓库列表
7862
+ * API 端点: GET /console/as/connector/oauth/{name}/repos
7863
+ *
7864
+ * Note: 由于工蜂原生支持的 Search 能力会匹配 path/name/description 部分,
7865
+ * 且不支持定制,不满足产品要求(只按 name 匹配),因此前端拉取全量数据后做筛选。
7866
+ *
7867
+ * @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
7868
+ * @param page 页码,从1开始,0表示不分页获取全部
7869
+ * - GitHub 只支持全量数据,必须传 0
7870
+ * - 工蜂和 CNB 依据前端逻辑而定
7871
+ * @param perPage 每页数量,最大100
7872
+ * @returns Promise<ListReposResponse> 仓库列表响应
7873
+ *
7874
+ * @example
7875
+ * ```typescript
7876
+ * // GitHub - 必须传 page=0 获取全量数据
7877
+ * const response = await service.getRepositories('github', 0, 100);
7878
+ * // response.github_repos 是 map: installation_id => repo[]
7879
+ *
7880
+ * // Gongfeng
7881
+ * const response = await service.getRepositories('gongfeng', 0, 100);
7882
+ * // response.gongfeng_repos 是数组
7883
+ *
7884
+ * // CNB
7885
+ * const response = await service.getRepositories('cnb', 0, 100);
7886
+ * // response.cnb_repos 是数组
7887
+ * ```
7888
+ */
7889
+ async getRepositories(connector, page = 0, perPage = 100) {
7890
+ try {
7891
+ const queryParams = new URLSearchParams();
7892
+ queryParams.append("page", String(page));
7893
+ queryParams.append("per_page", String(Math.min(perPage, 100)));
7894
+ const url = `/console/as/connector/oauth/${connector}/repos?${queryParams.toString()}`;
7895
+ console.log(`[OAuthRepositoryService] GET ${url}`);
7896
+ const apiResponse = await httpService.get(url);
7897
+ if (!apiResponse.data) {
7898
+ console.warn(`[OAuthRepositoryService] No data in repos response for ${connector}`);
7899
+ return {};
7900
+ }
7901
+ const response = apiResponse.data;
7902
+ this.logRepositoryCounts(response);
7903
+ return response;
7904
+ } catch (error) {
7905
+ console.error(`[OAuthRepositoryService] Failed to get repos from ${connector}:`, error);
7906
+ throw error;
7907
+ }
7908
+ }
7909
+ /**
7910
+ * 构建分支查询参数
7911
+ */
7912
+ buildBranchQueryParams(connector, params, page, perPage) {
7913
+ const queryParams = new URLSearchParams();
7914
+ queryParams.append("page", String(page));
7915
+ queryParams.append("per_page", String(Math.min(perPage, 100)));
7916
+ if (connector === "github") {
7917
+ const githubParams = params;
7918
+ if (!githubParams.owner || !githubParams.repo) throw new Error("GitHub requires owner and repo parameters");
7919
+ queryParams.append("owner", githubParams.owner);
7920
+ queryParams.append("repo", githubParams.repo);
7921
+ } else if (connector === "gongfeng") {
7922
+ const gongfengParams = params;
7923
+ if (!gongfengParams.project_id) throw new Error("Gongfeng requires project_id parameter");
7924
+ queryParams.append("project_id", gongfengParams.project_id);
7925
+ } else if (connector === "cnb") {
7926
+ const cnbParams = params;
7927
+ if (!cnbParams.repo) throw new Error("CNB requires repo parameter");
7928
+ queryParams.append("repo", cnbParams.repo);
7929
+ } else throw new Error(`Unknown connector: ${connector}`);
7930
+ return queryParams;
7931
+ }
7932
+ /**
7933
+ * 记录仓库数量日志
7934
+ */
7935
+ logRepositoryCounts(response) {
7936
+ if (response.github_repos) {
7937
+ const totalCount = Object.values(response.github_repos).reduce((sum, repos) => sum + repos.length, 0);
7938
+ console.log(`[OAuthRepositoryService] Retrieved ${totalCount} GitHub repos across ${Object.keys(response.github_repos).length} installations`);
7939
+ }
7940
+ if (response.gongfeng_repos) console.log(`[OAuthRepositoryService] Retrieved ${response.gongfeng_repos.length} Gongfeng repos`);
7941
+ if (response.cnb_repos) console.log(`[OAuthRepositoryService] Retrieved ${response.cnb_repos.length} CNB repos`);
7942
+ }
7943
+ };
7944
+ /**
7945
+ * OAuth Repository Service 单例实例
7946
+ */
7947
+ const oauthRepositoryService = new OAuthRepositoryService();
7948
+
7735
7949
  //#endregion
7736
7950
  //#region ../agent-provider/src/backend/backend-provider.ts
7737
7951
  /**
@@ -7740,27 +7954,29 @@ let AccountStatus = /* @__PURE__ */ function(AccountStatus) {
7740
7954
  * 封装与后端 API 的 HTTP 通信
7741
7955
  */
7742
7956
  /**
7743
- * 判断当前是否在 SSO 域名下
7744
- * SSO 域名格式: xxx.sso.copilot.tencent.com xxx.sso.codebuddy.cn
7957
+ * 判断当前账号是否是 SSO 账号
7958
+ * 通过 account.accountType === 'sso' 来判断,这种不行,因为未登录之前account 为空
7745
7959
  */
7746
7960
  const isSSODomain = () => {
7747
7961
  const { hostname } = window.location;
7748
7962
  return hostname.includes(".sso.copilot") || hostname.includes("sso.codebuddy.cn") || hostname.includes(".sso.copilot-staging") || hostname.includes(".staging-sso.codebuddy.cn");
7749
7963
  };
7750
7964
  /**
7751
- * 获取登录页面 URL
7752
- * - SSO 域名下需要跳转到对应的预发/生产域名
7753
- * - 非 SSO 域名直接使用当前域名
7965
+ * 根据路径获取完整 URL
7966
+ * - SSO 账号需要跳转到对应的预发/生产域名
7967
+ * - 非 SSO 账号直接使用当前域名
7968
+ * @param path 路径,如 '/login'、'/logout'、'/home' 等
7969
+ * @returns 完整的 URL 地址
7754
7970
  */
7755
- const getLoginUrl = () => {
7971
+ const getFullUrl = (path) => {
7756
7972
  const { hostname, protocol } = window.location;
7757
7973
  if (isSSODomain()) {
7758
7974
  const isCodebuddy = hostname.includes("codebuddy.cn");
7759
7975
  const isStaging = hostname.includes("staging");
7760
- if (isCodebuddy) return isStaging ? `${protocol}//staging.codebuddy.cn/login` : `${protocol}//www.codebuddy.cn/login`;
7761
- else return isStaging ? `${protocol}//staging-copilot.tencent.com/login` : `${protocol}//copilot.tencent.com/login`;
7976
+ if (isCodebuddy) return isStaging ? `${protocol}//staging.codebuddy.cn${path}` : `${protocol}//www.codebuddy.cn${path}`;
7977
+ else return isStaging ? `${protocol}//staging-copilot.tencent.com${path}` : `${protocol}//copilot.tencent.com${path}`;
7762
7978
  }
7763
- return `${window.location.origin}/login`;
7979
+ return `${window.location.origin}${path}`;
7764
7980
  };
7765
7981
  /** 获取当前域名的账号选择页面 URL */
7766
7982
  const getSelectAccountUrl = () => `${window.location.origin}/login/select`;
@@ -7848,7 +8064,7 @@ var BackendProvider = class {
7848
8064
  return account;
7849
8065
  }
7850
8066
  const redirectUrl = encodeURIComponent(window.location.href);
7851
- window.location.href = `${getSelectAccountUrl()}?platform=website&state=0&redirect_uri=${redirectUrl}`;
8067
+ window.location.href = `${getSelectAccountUrl()}?platform=agents&state=0&redirect_uri=${redirectUrl}`;
7852
8068
  accountService.setAccount(null);
7853
8069
  return null;
7854
8070
  } catch (error) {
@@ -7871,7 +8087,8 @@ var BackendProvider = class {
7871
8087
  activeStatus: connector.active_status,
7872
8088
  displayName: connector.display_name,
7873
8089
  oauthClientId: connector.oauth_client_id,
7874
- oauthRedirectUrl: connector.oauth_redirect_url
8090
+ oauthRedirectUrl: connector.oauth_redirect_url,
8091
+ oauthAppName: connector.oauth_app_name
7875
8092
  })) };
7876
8093
  }
7877
8094
  throw result;
@@ -7953,7 +8170,8 @@ var BackendProvider = class {
7953
8170
  connectStatus: connector.connect_status,
7954
8171
  displayName: connector.display_name,
7955
8172
  oauthClientId: connector.oauth_client_id,
7956
- oauthRedirectUrl: connector.oauth_redirect_url
8173
+ oauthRedirectUrl: connector.oauth_redirect_url,
8174
+ oauthAppName: connector.oauth_app_name
7957
8175
  })) };
7958
8176
  }
7959
8177
  throw result;
@@ -8210,7 +8428,7 @@ var BackendProvider = class {
8210
8428
  */
8211
8429
  async login() {
8212
8430
  const redirectUrl = encodeURIComponent(window.location.href);
8213
- window.location.href = `${getLoginUrl()}?platform=website&state=0&redirect_uri=${redirectUrl}`;
8431
+ window.location.href = `${getFullUrl("/login")}?platform=agents&state=0&redirect_uri=${redirectUrl}`;
8214
8432
  }
8215
8433
  /**
8216
8434
  * 登出账号
@@ -8273,6 +8491,52 @@ var BackendProvider = class {
8273
8491
  return null;
8274
8492
  }
8275
8493
  }
8494
+ /**
8495
+ * 刷新 Token
8496
+ * 通过调用 getAccount 刷新 cookie,适用于 Cloud 场景下页面切换回来时刷新登录态
8497
+ * @returns Promise<Account | null> 刷新后的账号信息
8498
+ */
8499
+ async refreshToken() {
8500
+ console.log("[BackendProvider] Refreshing token...");
8501
+ try {
8502
+ const account = await this.getAccount();
8503
+ console.log("[BackendProvider] Token refreshed, account:", account?.uid);
8504
+ return account;
8505
+ } catch (error) {
8506
+ console.error("[BackendProvider] refreshToken failed:", error);
8507
+ return null;
8508
+ }
8509
+ }
8510
+ /**
8511
+ * 获取仓库分支列表
8512
+ * API 端点: GET /console/as/connector/oauth/{name}/branches
8513
+ *
8514
+ * @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
8515
+ * @param params 平台特定的查询参数
8516
+ * @param page 页码,从1开始,0表示不分页获取全部
8517
+ * @param perPage 每页数量,最大100
8518
+ * @returns Promise<OauthBranch[]> 分支列表
8519
+ */
8520
+ async getBranches(connector, params, page = 0, perPage = 100) {
8521
+ return oauthRepositoryService.getBranches(connector, params, page, perPage);
8522
+ }
8523
+ /**
8524
+ * 获取仓库列表
8525
+ * API 端点: GET /console/as/connector/oauth/{name}/repos
8526
+ *
8527
+ * Note: 由于工蜂原生支持的 Search 能力会匹配 path/name/description 部分,
8528
+ * 且不支持定制,不满足产品要求(只按 name 匹配),因此前端拉取全量数据后做筛选。
8529
+ *
8530
+ * @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
8531
+ * @param page 页码,从1开始,0表示不分页获取全部
8532
+ * - GitHub 只支持全量数据,必须传 0
8533
+ * - 工蜂和 CNB 依据前端逻辑而定
8534
+ * @param perPage 每页数量,最大100
8535
+ * @returns Promise<ListReposResponse> 仓库列表响应
8536
+ */
8537
+ async getRepositories(connector, page = 0, perPage = 100) {
8538
+ return oauthRepositoryService.getRepositories(connector, page, perPage);
8539
+ }
8276
8540
  };
8277
8541
  /**
8278
8542
  * 创建 BackendProvider 实例
@@ -8312,6 +8576,7 @@ const BACKEND_REQUEST_TYPES = {
8312
8576
  GET_FILE: "backend:get-file",
8313
8577
  RELOAD_WINDOW: "backend:reload-window",
8314
8578
  CLOSE_AGENT_MANAGER: "backend:close-agent-manager",
8579
+ OPEN_EXTERNAL: "backend:open-external",
8315
8580
  BATCH_TOGGLE_PLUGINS: "backend:batch-toggle-plugins",
8316
8581
  GET_SUPPORT_SCENES: "backend:get-support-scenes"
8317
8582
  };
@@ -8607,6 +8872,20 @@ var IPCBackendProvider = class {
8607
8872
  }
8608
8873
  }
8609
8874
  /**
8875
+ * 在外部浏览器中打开链接
8876
+ * IDE 环境: 通过 IPC 通知 IDE 使用 vscode.env.openExternal 打开 URL
8877
+ * @param url 要打开的 URL
8878
+ */
8879
+ async openExternal(url) {
8880
+ this.log("Opening external URL via IPC:", url);
8881
+ try {
8882
+ await this.sendBackendRequest(BACKEND_REQUEST_TYPES.OPEN_EXTERNAL, { url });
8883
+ } catch (error) {
8884
+ this.log("Open external request failed:", error);
8885
+ throw error;
8886
+ }
8887
+ }
8888
+ /**
8610
8889
  * 批量切换插件状态
8611
8890
  * IDE 环境: 通过 IPC 调用 Extension Host 的 PluginService
8612
8891
  */