@tencent-ai/cloud-agent-sdk 0.2.12 → 0.2.13-next.00cf97b.20260317
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 +2337 -348
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1964 -201
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1964 -201
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2335 -346
- package/dist/index.mjs.map +1 -1
- package/dist/tencent-ai-cloud-agent-sdk-0.2.13-next.00cf97b.20260317.tgz +0 -0
- package/package.json +6 -5
- package/dist/tencent-ai-cloud-agent-sdk-0.2.12.tgz +0 -0
package/dist/index.cjs
CHANGED
|
@@ -93,7 +93,6 @@ const ToolInputSchemas = {
|
|
|
93
93
|
queryString: zod.z.string().describe("用户的实际问题或搜索查询"),
|
|
94
94
|
knowledgeBaseNames: zod.z.string().describe("知识库名称,多个用逗号分隔")
|
|
95
95
|
}),
|
|
96
|
-
read_rules: zod.z.object({ ruleNames: zod.z.string().describe("要读取的规则关键词,用逗号分隔,格式:{ruleName}_{ruleId}") }),
|
|
97
96
|
mcp_get_tool_description: zod.z.object({ toolRequests: zod.z.string().describe("JSON 字符串,二维数组格式:[[\"server1\", \"tool1\"], [\"server2\", \"tool2\"]]") }),
|
|
98
97
|
mcp_call_tool: zod.z.object({
|
|
99
98
|
serverName: zod.z.string().describe("MCP 服务器名称"),
|
|
@@ -107,13 +106,6 @@ const ToolInputSchemas = {
|
|
|
107
106
|
arguments: zod.z.record(zod.z.unknown()).optional().describe("资源模板的参数"),
|
|
108
107
|
downloadPath: zod.z.string().optional().describe("可选的绝对路径,用于保存资源到磁盘")
|
|
109
108
|
}),
|
|
110
|
-
create_rule: zod.z.object({
|
|
111
|
-
ruleScope: zod.z.string().describe("规则范围,project rule 或 user rule"),
|
|
112
|
-
ruleName: zod.z.string().describe("规则文件名,不带扩展名"),
|
|
113
|
-
ruleType: zod.z.string().describe("规则类型,always、manual 或 requested"),
|
|
114
|
-
ruleContent: zod.z.string().describe("规则内容,使用 Markdown 格式"),
|
|
115
|
-
ruleDescription: zod.z.string().optional().describe("规则描述,使用 Markdown 格式")
|
|
116
|
-
}),
|
|
117
109
|
update_memory: zod.z.object({
|
|
118
110
|
action: zod.z.enum([
|
|
119
111
|
"create",
|
|
@@ -172,7 +164,6 @@ const ToolInputSchemas = {
|
|
|
172
164
|
cloud_studio_fetch_log: zod.z.object({}).passthrough(),
|
|
173
165
|
cloud_studio_execute_command: zod.z.object({}).passthrough(),
|
|
174
166
|
cloud_studio_deploy_sandbox: zod.z.object({}).passthrough(),
|
|
175
|
-
component_get_prompt: zod.z.object({}).passthrough(),
|
|
176
167
|
web_fetch: zod.z.object({
|
|
177
168
|
url: zod.z.string().describe("要获取内容的 URL"),
|
|
178
169
|
fetchInfo: zod.z.string().describe("用户想要获取的信息描述")
|
|
@@ -180,7 +171,9 @@ const ToolInputSchemas = {
|
|
|
180
171
|
use_skill: zod.z.object({ command: zod.z.string().describe("技能名称(不含参数),如 \"pdf\" 或 \"xlsx\"") }),
|
|
181
172
|
web_search: zod.z.object({
|
|
182
173
|
explanation: zod.z.string().describe("为什么使用此工具的一句话解释"),
|
|
183
|
-
|
|
174
|
+
query: zod.z.string().describe("搜索关键词"),
|
|
175
|
+
max_results: zod.z.number().optional().describe("最大返回数量"),
|
|
176
|
+
language: zod.z.string().optional().describe("语言代码,例如 zh-CN")
|
|
184
177
|
}),
|
|
185
178
|
task: zod.z.object({
|
|
186
179
|
subagent_name: zod.z.string().describe("要调用的子代理名称"),
|
|
@@ -258,11 +251,6 @@ const ToolOutputSchemas = {
|
|
|
258
251
|
selectedKnowledgeBases: zod.z.string(),
|
|
259
252
|
queryInput: zod.z.string()
|
|
260
253
|
}),
|
|
261
|
-
read_rules: zod.z.object({
|
|
262
|
-
type: zod.z.literal("rule_match_result"),
|
|
263
|
-
ruleDescription: zod.z.string(),
|
|
264
|
-
filePaths: zod.z.array(zod.z.string())
|
|
265
|
-
}),
|
|
266
254
|
mcp_get_tool_description: zod.z.object({}).passthrough(),
|
|
267
255
|
mcp_call_tool: zod.z.object({
|
|
268
256
|
type: zod.z.literal("mcp_call_tool_result"),
|
|
@@ -299,17 +287,6 @@ const ToolOutputSchemas = {
|
|
|
299
287
|
content: zod.z.string(),
|
|
300
288
|
downloadPath: zod.z.string().optional()
|
|
301
289
|
}),
|
|
302
|
-
create_rule: zod.z.object({
|
|
303
|
-
type: zod.z.literal("rule_create_result"),
|
|
304
|
-
ruleName: zod.z.string(),
|
|
305
|
-
createState: zod.z.enum([
|
|
306
|
-
"success",
|
|
307
|
-
"invoke",
|
|
308
|
-
"cancelled"
|
|
309
|
-
]),
|
|
310
|
-
hint: zod.z.string().optional(),
|
|
311
|
-
filePath: zod.z.string().optional()
|
|
312
|
-
}),
|
|
313
290
|
update_memory: zod.z.object({
|
|
314
291
|
type: zod.z.literal("update_memory_result"),
|
|
315
292
|
success: zod.z.boolean(),
|
|
@@ -323,9 +300,9 @@ const ToolOutputSchemas = {
|
|
|
323
300
|
}),
|
|
324
301
|
search_content: zod.z.object({
|
|
325
302
|
type: zod.z.literal("search_content_result"),
|
|
326
|
-
|
|
303
|
+
path: zod.z.string(),
|
|
327
304
|
pattern: zod.z.string(),
|
|
328
|
-
|
|
305
|
+
glob: zod.z.string(),
|
|
329
306
|
matches: zod.z.array(zod.z.object({
|
|
330
307
|
filePath: zod.z.string(),
|
|
331
308
|
content: zod.z.string(),
|
|
@@ -337,7 +314,7 @@ const ToolOutputSchemas = {
|
|
|
337
314
|
totalCount: zod.z.number(),
|
|
338
315
|
hasMore: zod.z.boolean(),
|
|
339
316
|
offset: zod.z.number(),
|
|
340
|
-
|
|
317
|
+
headLimit: zod.z.number(),
|
|
341
318
|
contextBefore: zod.z.number(),
|
|
342
319
|
contextAfter: zod.z.number(),
|
|
343
320
|
contextAround: zod.z.number().optional(),
|
|
@@ -523,15 +500,6 @@ const ToolOutputSchemas = {
|
|
|
523
500
|
}).optional()
|
|
524
501
|
}))
|
|
525
502
|
}),
|
|
526
|
-
component_get_prompt: zod.z.object({
|
|
527
|
-
type: zod.z.literal("component_get_prompt_result"),
|
|
528
|
-
componentType: zod.z.string(),
|
|
529
|
-
webFramework: zod.z.string(),
|
|
530
|
-
data: zod.z.object({
|
|
531
|
-
type: zod.z.literal("text"),
|
|
532
|
-
text: zod.z.string()
|
|
533
|
-
})
|
|
534
|
-
}),
|
|
535
503
|
web_fetch: zod.z.object({
|
|
536
504
|
type: zod.z.literal("web_fetch_tool_result"),
|
|
537
505
|
message: zod.z.string(),
|
|
@@ -547,14 +515,29 @@ const ToolOutputSchemas = {
|
|
|
547
515
|
}),
|
|
548
516
|
web_search: zod.z.object({
|
|
549
517
|
type: zod.z.literal("web_search_tool_result"),
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
518
|
+
query: zod.z.string().optional(),
|
|
519
|
+
searchType: zod.z.literal("text2text").optional(),
|
|
520
|
+
provider: zod.z.string().optional(),
|
|
521
|
+
results: zod.z.array(zod.z.object({
|
|
554
522
|
title: zod.z.string(),
|
|
555
|
-
|
|
556
|
-
|
|
523
|
+
url: zod.z.string(),
|
|
524
|
+
snippet: zod.z.string().optional(),
|
|
525
|
+
site: zod.z.string().optional(),
|
|
526
|
+
highlights: zod.z.array(zod.z.string()).optional(),
|
|
527
|
+
content: zod.z.string().optional(),
|
|
528
|
+
favicon: zod.z.string().optional()
|
|
557
529
|
})),
|
|
530
|
+
images: zod.z.array(zod.z.object({
|
|
531
|
+
url: zod.z.string(),
|
|
532
|
+
description: zod.z.string().optional(),
|
|
533
|
+
sourceUrl: zod.z.string().optional(),
|
|
534
|
+
width: zod.z.number().optional(),
|
|
535
|
+
height: zod.z.number().optional(),
|
|
536
|
+
title: zod.z.string().optional(),
|
|
537
|
+
siteName: zod.z.string().optional()
|
|
538
|
+
})),
|
|
539
|
+
totalResults: zod.z.number().optional(),
|
|
540
|
+
responseTimeMs: zod.z.number().optional(),
|
|
558
541
|
searchInput: zod.z.string().optional()
|
|
559
542
|
}),
|
|
560
543
|
task: zod.z.object({
|
|
@@ -700,7 +683,11 @@ const ExtensionMethod = {
|
|
|
700
683
|
CHECKPOINT: "_codebuddy.ai/checkpoint",
|
|
701
684
|
USAGE: "_codebuddy.ai/usage",
|
|
702
685
|
COMMAND: "_codebuddy.ai/command",
|
|
703
|
-
AUTH_URL: "_codebuddy.ai/authUrl"
|
|
686
|
+
AUTH_URL: "_codebuddy.ai/authUrl",
|
|
687
|
+
FILE_HISTORY_SNAPSHOT: "_codebuddy.ai/file_history_snapshot",
|
|
688
|
+
DELEGATE_TOOL: "_codebuddy.ai/delegateTool",
|
|
689
|
+
DELEGATE_TOOLS_CHANGED: "_codebuddy.ai/delegateToolsChanged",
|
|
690
|
+
UI_CONTROL: "_codebuddy.ai/uiControl"
|
|
704
691
|
};
|
|
705
692
|
/**
|
|
706
693
|
* All known extension methods
|
|
@@ -711,7 +698,10 @@ const KNOWN_EXTENSIONS = [
|
|
|
711
698
|
ExtensionMethod.CHECKPOINT,
|
|
712
699
|
ExtensionMethod.USAGE,
|
|
713
700
|
ExtensionMethod.COMMAND,
|
|
714
|
-
ExtensionMethod.AUTH_URL
|
|
701
|
+
ExtensionMethod.AUTH_URL,
|
|
702
|
+
ExtensionMethod.FILE_HISTORY_SNAPSHOT,
|
|
703
|
+
ExtensionMethod.DELEGATE_TOOL,
|
|
704
|
+
ExtensionMethod.DELEGATE_TOOLS_CHANGED
|
|
715
705
|
];
|
|
716
706
|
|
|
717
707
|
//#endregion
|
|
@@ -762,7 +752,7 @@ function parseSSELine(line, currentEvent) {
|
|
|
762
752
|
};
|
|
763
753
|
}
|
|
764
754
|
function streamableHttp(options) {
|
|
765
|
-
const { endpoint, authToken, headers: customHeaders = {}, reconnect = {}, signal: externalSignal, fetch: customFetch = globalThis.fetch, onConnect, onDisconnect, onError, heartbeatTimeout = 6e4, postTimeout = 3e4, backpressure = {} } = options;
|
|
755
|
+
const { endpoint, authToken, headers: customHeaders = {}, reconnect = {}, signal: externalSignal, fetch: customFetch = globalThis.fetch, onConnect, onDisconnect, onError, heartbeatTimeout = 6e4, connectionTimeout = 3e4, postTimeout = 3e4, backpressure = {} } = options;
|
|
766
756
|
const { enabled: reconnectEnabled = true, initialDelay = 1e3, maxDelay = 3e4, maxRetries = Infinity, jitter: jitterEnabled = true } = reconnect;
|
|
767
757
|
const { highWaterMark = 100, lowWaterMark = 50, pauseTimeout = 5e3 } = backpressure;
|
|
768
758
|
let connectionId;
|
|
@@ -973,11 +963,21 @@ function streamableHttp(options) {
|
|
|
973
963
|
const headers = buildHeaders();
|
|
974
964
|
headers["Accept"] = "text/event-stream";
|
|
975
965
|
if (lastEventId) headers["Last-Event-ID"] = lastEventId;
|
|
976
|
-
const
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
});
|
|
966
|
+
const connectTimeoutMs = connectionTimeout > 0 ? connectionTimeout : 3e4;
|
|
967
|
+
const connectController = new AbortController();
|
|
968
|
+
const connectTimer = setTimeout(() => connectController.abort(), connectTimeoutMs);
|
|
969
|
+
if (externalSignal) externalSignal.addEventListener("abort", () => connectController.abort(), { once: true });
|
|
970
|
+
abortController.signal.addEventListener("abort", () => connectController.abort(), { once: true });
|
|
971
|
+
let response;
|
|
972
|
+
try {
|
|
973
|
+
response = await customFetch(endpoint, {
|
|
974
|
+
method: "GET",
|
|
975
|
+
headers,
|
|
976
|
+
signal: connectController.signal
|
|
977
|
+
});
|
|
978
|
+
} finally {
|
|
979
|
+
clearTimeout(connectTimer);
|
|
980
|
+
}
|
|
981
981
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
982
982
|
const newConnectionId = response.headers.get("Acp-Connection-Id");
|
|
983
983
|
if (!newConnectionId) throw new Error("Server did not return Acp-Connection-Id header");
|
|
@@ -1913,6 +1913,9 @@ var StreamableHttpClient = class {
|
|
|
1913
1913
|
headers: this.options.headers,
|
|
1914
1914
|
reconnect: this.options.reconnect,
|
|
1915
1915
|
fetch: this.options.fetch,
|
|
1916
|
+
heartbeatTimeout: this.options.heartbeatTimeout,
|
|
1917
|
+
postTimeout: this.options.postTimeout,
|
|
1918
|
+
connectionTimeout: this.options.connectionTimeout,
|
|
1916
1919
|
onConnect: (connectionId) => {
|
|
1917
1920
|
this.options.logger?.debug(`Transport connected: ${connectionId}`);
|
|
1918
1921
|
},
|
|
@@ -1987,10 +1990,6 @@ var StreamableHttpClient = class {
|
|
|
1987
1990
|
},
|
|
1988
1991
|
requestPermission: async (params) => this.handleRequestPermission(params),
|
|
1989
1992
|
extNotification: async (method, params) => {
|
|
1990
|
-
console.log("[ACP-Client] extNotification callback invoked:", {
|
|
1991
|
-
method,
|
|
1992
|
-
paramsKeys: Object.keys(params)
|
|
1993
|
-
});
|
|
1994
1993
|
await this.handleExtNotification(method, params);
|
|
1995
1994
|
},
|
|
1996
1995
|
extMethod: async (method, params) => this.handleExtMethod(method, params)
|
|
@@ -1998,10 +1997,15 @@ var StreamableHttpClient = class {
|
|
|
1998
1997
|
}
|
|
1999
1998
|
/**
|
|
2000
1999
|
* Create a new session
|
|
2000
|
+
*
|
|
2001
|
+
* Retries on transient network errors (e.g., proxy connection reset)
|
|
2002
|
+
* since session/new is idempotent and safe to retry.
|
|
2001
2003
|
*/
|
|
2002
2004
|
async createSession(cwd) {
|
|
2003
2005
|
this.ensureInitialized("createSession");
|
|
2004
|
-
|
|
2006
|
+
const maxRetries = 2;
|
|
2007
|
+
let lastError;
|
|
2008
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) try {
|
|
2005
2009
|
const response = await this.connection.newSession({
|
|
2006
2010
|
cwd,
|
|
2007
2011
|
mcpServers: []
|
|
@@ -2009,8 +2013,16 @@ var StreamableHttpClient = class {
|
|
|
2009
2013
|
this.options.logger?.info(`Session created: ${response.sessionId}`);
|
|
2010
2014
|
return response;
|
|
2011
2015
|
} catch (err) {
|
|
2012
|
-
|
|
2016
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
2017
|
+
if (attempt < maxRetries && isRetryableNetworkError(err)) {
|
|
2018
|
+
const delay = 500 * Math.pow(2, attempt);
|
|
2019
|
+
this.options.logger?.warn(`session/new network error, retrying in ${delay}ms (attempt ${attempt + 1}/${maxRetries}): ${lastError.message}`);
|
|
2020
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
2021
|
+
continue;
|
|
2022
|
+
}
|
|
2023
|
+
throw new SessionError(`Failed to create session: ${lastError.message}`, void 0, lastError);
|
|
2013
2024
|
}
|
|
2025
|
+
throw new SessionError(`Failed to create session: ${lastError?.message}`, void 0, lastError);
|
|
2014
2026
|
}
|
|
2015
2027
|
/**
|
|
2016
2028
|
* Load an existing session
|
|
@@ -2234,6 +2246,18 @@ var StreamableHttpClient = class {
|
|
|
2234
2246
|
if (this.state !== "initialized") throw new InvalidStateError(operation, this.state, ["initialized"]);
|
|
2235
2247
|
}
|
|
2236
2248
|
};
|
|
2249
|
+
/**
|
|
2250
|
+
* Check if an error is a retryable network-level error.
|
|
2251
|
+
* Only network failures (TypeError from fetch) are retried, NOT HTTP errors (4xx/5xx).
|
|
2252
|
+
*/
|
|
2253
|
+
function isRetryableNetworkError(error) {
|
|
2254
|
+
if (error instanceof TypeError) return true;
|
|
2255
|
+
if (error instanceof Error) {
|
|
2256
|
+
const msg = error.message.toLowerCase();
|
|
2257
|
+
return msg.includes("failed to fetch") || msg.includes("fetch failed") || msg.includes("network request failed") || msg.includes("econnreset") || msg.includes("econnrefused") || msg.includes("socket hang up");
|
|
2258
|
+
}
|
|
2259
|
+
return false;
|
|
2260
|
+
}
|
|
2237
2261
|
|
|
2238
2262
|
//#endregion
|
|
2239
2263
|
//#region ../agent-provider/src/common/providers/cloud-agent-provider/cloud-connection.ts
|
|
@@ -2269,7 +2293,7 @@ var CloudAgentConnection = class {
|
|
|
2269
2293
|
fetch: config.fetch,
|
|
2270
2294
|
clientCapabilities: config.clientCapabilities,
|
|
2271
2295
|
onSessionUpdate: (update) => {
|
|
2272
|
-
if (!this._isStreaming) this.emit("sessionUpdate", update);
|
|
2296
|
+
if (!this._isStreaming && this.isOwnSessionNotification(update)) this.emit("sessionUpdate", update);
|
|
2273
2297
|
},
|
|
2274
2298
|
onArtifact: (artifact, event) => {
|
|
2275
2299
|
console.log("[CloudConnection] onArtifact callback:", {
|
|
@@ -2283,10 +2307,41 @@ var CloudAgentConnection = class {
|
|
|
2283
2307
|
},
|
|
2284
2308
|
onUsageUpdate: (usage) => {
|
|
2285
2309
|
this.emit("usageUpdate", usage);
|
|
2310
|
+
},
|
|
2311
|
+
onExtNotification: (method, params) => {
|
|
2312
|
+
console.log("[CloudConnection] Received extNotification:", {
|
|
2313
|
+
method,
|
|
2314
|
+
paramsKeys: Object.keys(params)
|
|
2315
|
+
});
|
|
2316
|
+
if (method === ExtensionMethod.COMMAND) {
|
|
2317
|
+
const action = params.action;
|
|
2318
|
+
const commandParams = params.params;
|
|
2319
|
+
console.log("[CloudConnection] Emitting command event:", {
|
|
2320
|
+
action,
|
|
2321
|
+
paramsKeys: commandParams ? Object.keys(commandParams) : []
|
|
2322
|
+
});
|
|
2323
|
+
this.emit("command", {
|
|
2324
|
+
action,
|
|
2325
|
+
params: commandParams
|
|
2326
|
+
});
|
|
2327
|
+
}
|
|
2286
2328
|
}
|
|
2287
2329
|
});
|
|
2288
2330
|
this.setupEventForwarding();
|
|
2289
2331
|
}
|
|
2332
|
+
/**
|
|
2333
|
+
* Check whether a notification belongs to this connection's own session.
|
|
2334
|
+
*
|
|
2335
|
+
* CloudConnection.createSession() overrides sessionId to agentId, so the
|
|
2336
|
+
* rest of the client stack uses agentId as the canonical session
|
|
2337
|
+
* identifier. Notifications whose sessionId differs from agentId
|
|
2338
|
+
* originate from sub-agent sessions running inside the same sandbox and
|
|
2339
|
+
* should be silently ignored at this layer — the adapter layer handles
|
|
2340
|
+
* sub-agent messages independently via parentToolUseId in _meta.
|
|
2341
|
+
*/
|
|
2342
|
+
isOwnSessionNotification(notification) {
|
|
2343
|
+
return notification.sessionId === this.agentId;
|
|
2344
|
+
}
|
|
2290
2345
|
setupEventForwarding() {
|
|
2291
2346
|
this.client.on("connecting", () => {
|
|
2292
2347
|
this.emit("connecting", void 0);
|
|
@@ -2411,7 +2466,7 @@ var CloudAgentConnection = class {
|
|
|
2411
2466
|
}
|
|
2412
2467
|
async createSession(params) {
|
|
2413
2468
|
return {
|
|
2414
|
-
...await this.client.
|
|
2469
|
+
...await this.client.createSession(this.cwd),
|
|
2415
2470
|
sessionId: this.agentId
|
|
2416
2471
|
};
|
|
2417
2472
|
}
|
|
@@ -2447,6 +2502,7 @@ var CloudAgentConnection = class {
|
|
|
2447
2502
|
let resolveUpdate = null;
|
|
2448
2503
|
let done = false;
|
|
2449
2504
|
const listener = (update) => {
|
|
2505
|
+
if (!this.isOwnSessionNotification(update)) return;
|
|
2450
2506
|
if (resolveUpdate) {
|
|
2451
2507
|
resolveUpdate(update);
|
|
2452
2508
|
resolveUpdate = null;
|
|
@@ -2529,6 +2585,16 @@ var CloudAgentConnection = class {
|
|
|
2529
2585
|
get sessionConnectionInfo() {
|
|
2530
2586
|
return this._sessionConnectionInfo;
|
|
2531
2587
|
}
|
|
2588
|
+
async reportTelemetry(eventName, payload) {
|
|
2589
|
+
try {
|
|
2590
|
+
await this.client.extMethod("reportTelemetry", {
|
|
2591
|
+
eventName,
|
|
2592
|
+
payload
|
|
2593
|
+
});
|
|
2594
|
+
} catch (error) {
|
|
2595
|
+
console.warn("[CloudAgentConnection] reportTelemetry failed:", error);
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2532
2598
|
async extMethod(method, params) {
|
|
2533
2599
|
return this.client.extMethod(method, params);
|
|
2534
2600
|
}
|
|
@@ -3131,7 +3197,7 @@ var utils_default = {
|
|
|
3131
3197
|
*
|
|
3132
3198
|
* @returns {Error} The created error.
|
|
3133
3199
|
*/
|
|
3134
|
-
function AxiosError(message, code, config, request, response) {
|
|
3200
|
+
function AxiosError$1(message, code, config, request, response) {
|
|
3135
3201
|
Error.call(this);
|
|
3136
3202
|
if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
|
|
3137
3203
|
else this.stack = (/* @__PURE__ */ new Error()).stack;
|
|
@@ -3145,7 +3211,7 @@ function AxiosError(message, code, config, request, response) {
|
|
|
3145
3211
|
this.status = response.status ? response.status : null;
|
|
3146
3212
|
}
|
|
3147
3213
|
}
|
|
3148
|
-
utils_default.inherits(AxiosError, Error, { toJSON: function toJSON() {
|
|
3214
|
+
utils_default.inherits(AxiosError$1, Error, { toJSON: function toJSON() {
|
|
3149
3215
|
return {
|
|
3150
3216
|
message: this.message,
|
|
3151
3217
|
name: this.name,
|
|
@@ -3160,7 +3226,7 @@ utils_default.inherits(AxiosError, Error, { toJSON: function toJSON() {
|
|
|
3160
3226
|
status: this.status
|
|
3161
3227
|
};
|
|
3162
3228
|
} });
|
|
3163
|
-
const prototype$1 = AxiosError.prototype;
|
|
3229
|
+
const prototype$1 = AxiosError$1.prototype;
|
|
3164
3230
|
const descriptors = {};
|
|
3165
3231
|
[
|
|
3166
3232
|
"ERR_BAD_OPTION_VALUE",
|
|
@@ -3178,22 +3244,22 @@ const descriptors = {};
|
|
|
3178
3244
|
].forEach((code) => {
|
|
3179
3245
|
descriptors[code] = { value: code };
|
|
3180
3246
|
});
|
|
3181
|
-
Object.defineProperties(AxiosError, descriptors);
|
|
3247
|
+
Object.defineProperties(AxiosError$1, descriptors);
|
|
3182
3248
|
Object.defineProperty(prototype$1, "isAxiosError", { value: true });
|
|
3183
|
-
AxiosError.from = (error, code, config, request, response, customProps) => {
|
|
3249
|
+
AxiosError$1.from = (error, code, config, request, response, customProps) => {
|
|
3184
3250
|
const axiosError = Object.create(prototype$1);
|
|
3185
3251
|
utils_default.toFlatObject(error, axiosError, function filter(obj) {
|
|
3186
3252
|
return obj !== Error.prototype;
|
|
3187
3253
|
}, (prop) => {
|
|
3188
3254
|
return prop !== "isAxiosError";
|
|
3189
3255
|
});
|
|
3190
|
-
AxiosError.call(axiosError, error.message, code, config, request, response);
|
|
3256
|
+
AxiosError$1.call(axiosError, error.message, code, config, request, response);
|
|
3191
3257
|
axiosError.cause = error;
|
|
3192
3258
|
axiosError.name = error.name;
|
|
3193
3259
|
customProps && Object.assign(axiosError, customProps);
|
|
3194
3260
|
return axiosError;
|
|
3195
3261
|
};
|
|
3196
|
-
var AxiosError_default = AxiosError;
|
|
3262
|
+
var AxiosError_default = AxiosError$1;
|
|
3197
3263
|
|
|
3198
3264
|
//#endregion
|
|
3199
3265
|
//#region ../../node_modules/delayed-stream/lib/delayed_stream.js
|
|
@@ -11920,7 +11986,7 @@ const predicates = utils_default.toFlatObject(utils_default, {}, null, function
|
|
|
11920
11986
|
*
|
|
11921
11987
|
* @returns
|
|
11922
11988
|
*/
|
|
11923
|
-
function toFormData(obj, formData, options) {
|
|
11989
|
+
function toFormData$1(obj, formData, options) {
|
|
11924
11990
|
if (!utils_default.isObject(obj)) throw new TypeError("target must be an object");
|
|
11925
11991
|
formData = formData || new (FormData_default || FormData)();
|
|
11926
11992
|
options = utils_default.toFlatObject(options, {
|
|
@@ -11991,7 +12057,7 @@ function toFormData(obj, formData, options) {
|
|
|
11991
12057
|
build(obj);
|
|
11992
12058
|
return formData;
|
|
11993
12059
|
}
|
|
11994
|
-
var toFormData_default = toFormData;
|
|
12060
|
+
var toFormData_default = toFormData$1;
|
|
11995
12061
|
|
|
11996
12062
|
//#endregion
|
|
11997
12063
|
//#region ../agent-provider/node_modules/axios/lib/helpers/AxiosURLSearchParams.js
|
|
@@ -12515,7 +12581,7 @@ function buildAccessors(obj, header) {
|
|
|
12515
12581
|
});
|
|
12516
12582
|
});
|
|
12517
12583
|
}
|
|
12518
|
-
var AxiosHeaders = class {
|
|
12584
|
+
var AxiosHeaders$1 = class {
|
|
12519
12585
|
constructor(headers) {
|
|
12520
12586
|
headers && this.set(headers);
|
|
12521
12587
|
}
|
|
@@ -12653,7 +12719,7 @@ var AxiosHeaders = class {
|
|
|
12653
12719
|
return this;
|
|
12654
12720
|
}
|
|
12655
12721
|
};
|
|
12656
|
-
AxiosHeaders.accessor([
|
|
12722
|
+
AxiosHeaders$1.accessor([
|
|
12657
12723
|
"Content-Type",
|
|
12658
12724
|
"Content-Length",
|
|
12659
12725
|
"Accept",
|
|
@@ -12661,7 +12727,7 @@ AxiosHeaders.accessor([
|
|
|
12661
12727
|
"User-Agent",
|
|
12662
12728
|
"Authorization"
|
|
12663
12729
|
]);
|
|
12664
|
-
utils_default.reduceDescriptors(AxiosHeaders.prototype, ({ value }, key) => {
|
|
12730
|
+
utils_default.reduceDescriptors(AxiosHeaders$1.prototype, ({ value }, key) => {
|
|
12665
12731
|
let mapped = key[0].toUpperCase() + key.slice(1);
|
|
12666
12732
|
return {
|
|
12667
12733
|
get: () => value,
|
|
@@ -12670,8 +12736,8 @@ utils_default.reduceDescriptors(AxiosHeaders.prototype, ({ value }, key) => {
|
|
|
12670
12736
|
}
|
|
12671
12737
|
};
|
|
12672
12738
|
});
|
|
12673
|
-
utils_default.freezeMethods(AxiosHeaders);
|
|
12674
|
-
var AxiosHeaders_default = AxiosHeaders;
|
|
12739
|
+
utils_default.freezeMethods(AxiosHeaders$1);
|
|
12740
|
+
var AxiosHeaders_default = AxiosHeaders$1;
|
|
12675
12741
|
|
|
12676
12742
|
//#endregion
|
|
12677
12743
|
//#region ../agent-provider/node_modules/axios/lib/core/transformData.js
|
|
@@ -12697,7 +12763,7 @@ function transformData(fns, response) {
|
|
|
12697
12763
|
|
|
12698
12764
|
//#endregion
|
|
12699
12765
|
//#region ../agent-provider/node_modules/axios/lib/cancel/isCancel.js
|
|
12700
|
-
function isCancel(value) {
|
|
12766
|
+
function isCancel$1(value) {
|
|
12701
12767
|
return !!(value && value.__CANCEL__);
|
|
12702
12768
|
}
|
|
12703
12769
|
|
|
@@ -12712,12 +12778,12 @@ function isCancel(value) {
|
|
|
12712
12778
|
*
|
|
12713
12779
|
* @returns {CanceledError} The created error.
|
|
12714
12780
|
*/
|
|
12715
|
-
function CanceledError(message, config, request) {
|
|
12781
|
+
function CanceledError$1(message, config, request) {
|
|
12716
12782
|
AxiosError_default.call(this, message == null ? "canceled" : message, AxiosError_default.ERR_CANCELED, config, request);
|
|
12717
12783
|
this.name = "CanceledError";
|
|
12718
12784
|
}
|
|
12719
|
-
utils_default.inherits(CanceledError, AxiosError_default, { __CANCEL__: true });
|
|
12720
|
-
var CanceledError_default = CanceledError;
|
|
12785
|
+
utils_default.inherits(CanceledError$1, AxiosError_default, { __CANCEL__: true });
|
|
12786
|
+
var CanceledError_default = CanceledError$1;
|
|
12721
12787
|
|
|
12722
12788
|
//#endregion
|
|
12723
12789
|
//#region ../agent-provider/node_modules/axios/lib/core/settle.js
|
|
@@ -14119,7 +14185,9 @@ var require_follow_redirects = /* @__PURE__ */ __commonJSMin(((exports, module)
|
|
|
14119
14185
|
|
|
14120
14186
|
//#endregion
|
|
14121
14187
|
//#region ../agent-provider/node_modules/axios/lib/env/data.js
|
|
14122
|
-
|
|
14188
|
+
var import_follow_redirects = /* @__PURE__ */ __toESM(require_follow_redirects(), 1);
|
|
14189
|
+
var import_proxy_from_env = /* @__PURE__ */ __toESM(require_proxy_from_env(), 1);
|
|
14190
|
+
const VERSION$1 = "1.10.0";
|
|
14123
14191
|
|
|
14124
14192
|
//#endregion
|
|
14125
14193
|
//#region ../agent-provider/node_modules/axios/lib/helpers/parseProtocol.js
|
|
@@ -14482,8 +14550,6 @@ const asyncDecorator = (fn) => (...args) => utils_default.asap(() => fn(...args)
|
|
|
14482
14550
|
|
|
14483
14551
|
//#endregion
|
|
14484
14552
|
//#region ../agent-provider/node_modules/axios/lib/adapters/http.js
|
|
14485
|
-
var import_proxy_from_env = /* @__PURE__ */ __toESM(require_proxy_from_env(), 1);
|
|
14486
|
-
var import_follow_redirects = /* @__PURE__ */ __toESM(require_follow_redirects(), 1);
|
|
14487
14553
|
const zlibOptions = {
|
|
14488
14554
|
flush: zlib.default.constants.Z_SYNC_FLUSH,
|
|
14489
14555
|
finishFlush: zlib.default.constants.Z_SYNC_FLUSH
|
|
@@ -14649,7 +14715,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
14649
14715
|
}
|
|
14650
14716
|
if (supportedProtocols.indexOf(protocol) === -1) return reject(new AxiosError_default("Unsupported protocol " + protocol, AxiosError_default.ERR_BAD_REQUEST, config));
|
|
14651
14717
|
const headers = AxiosHeaders_default.from(config.headers).normalize();
|
|
14652
|
-
headers.set("User-Agent", "axios/" + VERSION, false);
|
|
14718
|
+
headers.set("User-Agent", "axios/" + VERSION$1, false);
|
|
14653
14719
|
const { onUploadProgress, onDownloadProgress } = config;
|
|
14654
14720
|
const maxRate = config.maxRate;
|
|
14655
14721
|
let maxUploadRate = void 0;
|
|
@@ -14659,7 +14725,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
14659
14725
|
data = formDataToStream_default(data, (formHeaders) => {
|
|
14660
14726
|
headers.set(formHeaders);
|
|
14661
14727
|
}, {
|
|
14662
|
-
tag: `axios-${VERSION}-boundary`,
|
|
14728
|
+
tag: `axios-${VERSION$1}-boundary`,
|
|
14663
14729
|
boundary: userBoundary && userBoundary[1] || void 0
|
|
14664
14730
|
});
|
|
14665
14731
|
} else if (utils_default.isFormData(data) && utils_default.isFunction(data.getHeaders)) {
|
|
@@ -14924,7 +14990,7 @@ const headersToObject = (thing) => thing instanceof AxiosHeaders_default ? { ...
|
|
|
14924
14990
|
*
|
|
14925
14991
|
* @returns {Object} New object resulting from merging config2 to config1
|
|
14926
14992
|
*/
|
|
14927
|
-
function mergeConfig(config1, config2) {
|
|
14993
|
+
function mergeConfig$1(config1, config2) {
|
|
14928
14994
|
config2 = config2 || {};
|
|
14929
14995
|
const config = {};
|
|
14930
14996
|
function getMergedValue(target, source, prop, caseless) {
|
|
@@ -14990,7 +15056,7 @@ function mergeConfig(config1, config2) {
|
|
|
14990
15056
|
//#endregion
|
|
14991
15057
|
//#region ../agent-provider/node_modules/axios/lib/helpers/resolveConfig.js
|
|
14992
15058
|
var resolveConfig_default = (config) => {
|
|
14993
|
-
const newConfig = mergeConfig({}, config);
|
|
15059
|
+
const newConfig = mergeConfig$1({}, config);
|
|
14994
15060
|
let { data, withXSRFToken, xsrfHeaderName, xsrfCookieName, headers, auth } = newConfig;
|
|
14995
15061
|
newConfig.headers = headers = AxiosHeaders_default.from(headers);
|
|
14996
15062
|
newConfig.url = buildURL(buildFullPath(newConfig.baseURL, newConfig.url, newConfig.allowAbsoluteUrls), config.params, config.paramsSerializer);
|
|
@@ -15421,7 +15487,7 @@ function dispatchRequest(config) {
|
|
|
15421
15487
|
response.headers = AxiosHeaders_default.from(response.headers);
|
|
15422
15488
|
return response;
|
|
15423
15489
|
}, function onAdapterRejection(reason) {
|
|
15424
|
-
if (!isCancel(reason)) {
|
|
15490
|
+
if (!isCancel$1(reason)) {
|
|
15425
15491
|
throwIfCancellationRequested(config);
|
|
15426
15492
|
if (reason && reason.response) {
|
|
15427
15493
|
reason.response.data = transformData.call(config, config.transformResponse, reason.response);
|
|
@@ -15459,7 +15525,7 @@ const deprecatedWarnings = {};
|
|
|
15459
15525
|
*/
|
|
15460
15526
|
validators$1.transitional = function transitional(validator, version, message) {
|
|
15461
15527
|
function formatMessage(opt, desc) {
|
|
15462
|
-
return "[Axios v" + VERSION + "] Transitional option '" + opt + "'" + desc + (message ? ". " + message : "");
|
|
15528
|
+
return "[Axios v" + VERSION$1 + "] Transitional option '" + opt + "'" + desc + (message ? ". " + message : "");
|
|
15463
15529
|
}
|
|
15464
15530
|
return (value, opt, opts) => {
|
|
15465
15531
|
if (validator === false) throw new AxiosError_default(formatMessage(opt, " has been removed" + (version ? " in " + version : "")), AxiosError_default.ERR_DEPRECATED);
|
|
@@ -15516,7 +15582,7 @@ const validators = validator_default.validators;
|
|
|
15516
15582
|
*
|
|
15517
15583
|
* @return {Axios} A new instance of Axios
|
|
15518
15584
|
*/
|
|
15519
|
-
var Axios = class {
|
|
15585
|
+
var Axios$1 = class {
|
|
15520
15586
|
constructor(instanceConfig) {
|
|
15521
15587
|
this.defaults = instanceConfig || {};
|
|
15522
15588
|
this.interceptors = {
|
|
@@ -15553,7 +15619,7 @@ var Axios = class {
|
|
|
15553
15619
|
config = config || {};
|
|
15554
15620
|
config.url = configOrUrl;
|
|
15555
15621
|
} else config = configOrUrl || {};
|
|
15556
|
-
config = mergeConfig(this.defaults, config);
|
|
15622
|
+
config = mergeConfig$1(this.defaults, config);
|
|
15557
15623
|
const { transitional, paramsSerializer, headers } = config;
|
|
15558
15624
|
if (transitional !== void 0) validator_default.assertOptions(transitional, {
|
|
15559
15625
|
silentJSONParsing: validators.transitional(validators.boolean),
|
|
@@ -15632,7 +15698,7 @@ var Axios = class {
|
|
|
15632
15698
|
return promise;
|
|
15633
15699
|
}
|
|
15634
15700
|
getUri(config) {
|
|
15635
|
-
config = mergeConfig(this.defaults, config);
|
|
15701
|
+
config = mergeConfig$1(this.defaults, config);
|
|
15636
15702
|
return buildURL(buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls), config.params, config.paramsSerializer);
|
|
15637
15703
|
}
|
|
15638
15704
|
};
|
|
@@ -15642,8 +15708,8 @@ utils_default.forEach([
|
|
|
15642
15708
|
"head",
|
|
15643
15709
|
"options"
|
|
15644
15710
|
], function forEachMethodNoData(method) {
|
|
15645
|
-
Axios.prototype[method] = function(url, config) {
|
|
15646
|
-
return this.request(mergeConfig(config || {}, {
|
|
15711
|
+
Axios$1.prototype[method] = function(url, config) {
|
|
15712
|
+
return this.request(mergeConfig$1(config || {}, {
|
|
15647
15713
|
method,
|
|
15648
15714
|
url,
|
|
15649
15715
|
data: (config || {}).data
|
|
@@ -15657,7 +15723,7 @@ utils_default.forEach([
|
|
|
15657
15723
|
], function forEachMethodWithData(method) {
|
|
15658
15724
|
function generateHTTPMethod(isForm) {
|
|
15659
15725
|
return function httpMethod(url, data, config) {
|
|
15660
|
-
return this.request(mergeConfig(config || {}, {
|
|
15726
|
+
return this.request(mergeConfig$1(config || {}, {
|
|
15661
15727
|
method,
|
|
15662
15728
|
headers: isForm ? { "Content-Type": "multipart/form-data" } : {},
|
|
15663
15729
|
url,
|
|
@@ -15665,10 +15731,10 @@ utils_default.forEach([
|
|
|
15665
15731
|
}));
|
|
15666
15732
|
};
|
|
15667
15733
|
}
|
|
15668
|
-
Axios.prototype[method] = generateHTTPMethod();
|
|
15669
|
-
Axios.prototype[method + "Form"] = generateHTTPMethod(true);
|
|
15734
|
+
Axios$1.prototype[method] = generateHTTPMethod();
|
|
15735
|
+
Axios$1.prototype[method + "Form"] = generateHTTPMethod(true);
|
|
15670
15736
|
});
|
|
15671
|
-
var Axios_default = Axios;
|
|
15737
|
+
var Axios_default = Axios$1;
|
|
15672
15738
|
|
|
15673
15739
|
//#endregion
|
|
15674
15740
|
//#region ../agent-provider/node_modules/axios/lib/cancel/CancelToken.js
|
|
@@ -15679,7 +15745,7 @@ var Axios_default = Axios;
|
|
|
15679
15745
|
*
|
|
15680
15746
|
* @returns {CancelToken}
|
|
15681
15747
|
*/
|
|
15682
|
-
var CancelToken = class CancelToken {
|
|
15748
|
+
var CancelToken$1 = class CancelToken$1 {
|
|
15683
15749
|
constructor(executor) {
|
|
15684
15750
|
if (typeof executor !== "function") throw new TypeError("executor must be a function.");
|
|
15685
15751
|
let resolvePromise;
|
|
@@ -15751,14 +15817,14 @@ var CancelToken = class CancelToken {
|
|
|
15751
15817
|
static source() {
|
|
15752
15818
|
let cancel;
|
|
15753
15819
|
return {
|
|
15754
|
-
token: new CancelToken(function executor(c) {
|
|
15820
|
+
token: new CancelToken$1(function executor(c) {
|
|
15755
15821
|
cancel = c;
|
|
15756
15822
|
}),
|
|
15757
15823
|
cancel
|
|
15758
15824
|
};
|
|
15759
15825
|
}
|
|
15760
15826
|
};
|
|
15761
|
-
var CancelToken_default = CancelToken;
|
|
15827
|
+
var CancelToken_default = CancelToken$1;
|
|
15762
15828
|
|
|
15763
15829
|
//#endregion
|
|
15764
15830
|
//#region ../agent-provider/node_modules/axios/lib/helpers/spread.js
|
|
@@ -15783,7 +15849,7 @@ var CancelToken_default = CancelToken;
|
|
|
15783
15849
|
*
|
|
15784
15850
|
* @returns {Function}
|
|
15785
15851
|
*/
|
|
15786
|
-
function spread(callback) {
|
|
15852
|
+
function spread$1(callback) {
|
|
15787
15853
|
return function wrap(arr) {
|
|
15788
15854
|
return callback.apply(null, arr);
|
|
15789
15855
|
};
|
|
@@ -15798,13 +15864,13 @@ function spread(callback) {
|
|
|
15798
15864
|
*
|
|
15799
15865
|
* @returns {boolean} True if the payload is an error thrown by Axios, otherwise false
|
|
15800
15866
|
*/
|
|
15801
|
-
function isAxiosError(payload) {
|
|
15867
|
+
function isAxiosError$1(payload) {
|
|
15802
15868
|
return utils_default.isObject(payload) && payload.isAxiosError === true;
|
|
15803
15869
|
}
|
|
15804
15870
|
|
|
15805
15871
|
//#endregion
|
|
15806
15872
|
//#region ../agent-provider/node_modules/axios/lib/helpers/HttpStatusCode.js
|
|
15807
|
-
const HttpStatusCode = {
|
|
15873
|
+
const HttpStatusCode$1 = {
|
|
15808
15874
|
Continue: 100,
|
|
15809
15875
|
SwitchingProtocols: 101,
|
|
15810
15876
|
Processing: 102,
|
|
@@ -15869,10 +15935,10 @@ const HttpStatusCode = {
|
|
|
15869
15935
|
NotExtended: 510,
|
|
15870
15936
|
NetworkAuthenticationRequired: 511
|
|
15871
15937
|
};
|
|
15872
|
-
Object.entries(HttpStatusCode).forEach(([key, value]) => {
|
|
15873
|
-
HttpStatusCode[value] = key;
|
|
15938
|
+
Object.entries(HttpStatusCode$1).forEach(([key, value]) => {
|
|
15939
|
+
HttpStatusCode$1[value] = key;
|
|
15874
15940
|
});
|
|
15875
|
-
var HttpStatusCode_default = HttpStatusCode;
|
|
15941
|
+
var HttpStatusCode_default = HttpStatusCode$1;
|
|
15876
15942
|
|
|
15877
15943
|
//#endregion
|
|
15878
15944
|
//#region ../agent-provider/node_modules/axios/lib/axios.js
|
|
@@ -15889,7 +15955,7 @@ function createInstance(defaultConfig) {
|
|
|
15889
15955
|
utils_default.extend(instance, Axios_default.prototype, context, { allOwnKeys: true });
|
|
15890
15956
|
utils_default.extend(instance, context, null, { allOwnKeys: true });
|
|
15891
15957
|
instance.create = function create(instanceConfig) {
|
|
15892
|
-
return createInstance(mergeConfig(defaultConfig, instanceConfig));
|
|
15958
|
+
return createInstance(mergeConfig$1(defaultConfig, instanceConfig));
|
|
15893
15959
|
};
|
|
15894
15960
|
return instance;
|
|
15895
15961
|
}
|
|
@@ -15897,17 +15963,17 @@ const axios = createInstance(defaults_default);
|
|
|
15897
15963
|
axios.Axios = Axios_default;
|
|
15898
15964
|
axios.CanceledError = CanceledError_default;
|
|
15899
15965
|
axios.CancelToken = CancelToken_default;
|
|
15900
|
-
axios.isCancel = isCancel;
|
|
15901
|
-
axios.VERSION = VERSION;
|
|
15966
|
+
axios.isCancel = isCancel$1;
|
|
15967
|
+
axios.VERSION = VERSION$1;
|
|
15902
15968
|
axios.toFormData = toFormData_default;
|
|
15903
15969
|
axios.AxiosError = AxiosError_default;
|
|
15904
15970
|
axios.Cancel = axios.CanceledError;
|
|
15905
15971
|
axios.all = function all(promises) {
|
|
15906
15972
|
return Promise.all(promises);
|
|
15907
15973
|
};
|
|
15908
|
-
axios.spread = spread;
|
|
15909
|
-
axios.isAxiosError = isAxiosError;
|
|
15910
|
-
axios.mergeConfig = mergeConfig;
|
|
15974
|
+
axios.spread = spread$1;
|
|
15975
|
+
axios.isAxiosError = isAxiosError$1;
|
|
15976
|
+
axios.mergeConfig = mergeConfig$1;
|
|
15911
15977
|
axios.AxiosHeaders = AxiosHeaders_default;
|
|
15912
15978
|
axios.formToJSON = (thing) => formDataToJSON_default(utils_default.isHTMLForm(thing) ? new FormData(thing) : thing);
|
|
15913
15979
|
axios.getAdapter = adapters_default.getAdapter;
|
|
@@ -15915,6 +15981,10 @@ axios.HttpStatusCode = HttpStatusCode_default;
|
|
|
15915
15981
|
axios.default = axios;
|
|
15916
15982
|
var axios_default = axios;
|
|
15917
15983
|
|
|
15984
|
+
//#endregion
|
|
15985
|
+
//#region ../agent-provider/node_modules/axios/index.js
|
|
15986
|
+
const { Axios, AxiosError, CanceledError, isCancel, CancelToken, VERSION, all, Cancel, isAxiosError, spread, toFormData, AxiosHeaders, HttpStatusCode, formToJSON, getAdapter, mergeConfig } = axios_default;
|
|
15987
|
+
|
|
15918
15988
|
//#endregion
|
|
15919
15989
|
//#region ../agent-provider/src/http/http-service.ts
|
|
15920
15990
|
/**
|
|
@@ -15923,7 +15993,7 @@ var axios_default = axios;
|
|
|
15923
15993
|
* 特性:
|
|
15924
15994
|
* - 单例模式,全局唯一实例,延迟初始化(首次使用时自动创建)
|
|
15925
15995
|
* - 支持拦截器注册(其他模块可注入 header)
|
|
15926
|
-
* - 统一 401
|
|
15996
|
+
* - 统一 401 处理(支持自动刷新 token 并重试)
|
|
15927
15997
|
* - 自动携带凭证(withCredentials)
|
|
15928
15998
|
* - 类型安全
|
|
15929
15999
|
*
|
|
@@ -15963,6 +16033,8 @@ var HttpService = class HttpService {
|
|
|
15963
16033
|
*/
|
|
15964
16034
|
constructor(config = {}) {
|
|
15965
16035
|
this.unauthorizedCallbacks = /* @__PURE__ */ new Set();
|
|
16036
|
+
this.isRefreshing = false;
|
|
16037
|
+
this.refreshSubscribers = [];
|
|
15966
16038
|
this.config = config;
|
|
15967
16039
|
this.axiosInstance = axios_default.create({
|
|
15968
16040
|
baseURL: config.baseURL?.replace(/\/$/, "") || "",
|
|
@@ -16003,18 +16075,54 @@ var HttpService = class HttpService {
|
|
|
16003
16075
|
}, (error) => Promise.reject(error));
|
|
16004
16076
|
}
|
|
16005
16077
|
/**
|
|
16006
|
-
* 注册默认响应拦截器(处理 401
|
|
16078
|
+
* 注册默认响应拦截器(处理 401,支持自动重试)
|
|
16007
16079
|
*/
|
|
16008
16080
|
registerDefaultResponseInterceptor() {
|
|
16009
|
-
this.axiosInstance.interceptors.response.use((response) => response, (error) => {
|
|
16010
|
-
|
|
16011
|
-
|
|
16012
|
-
|
|
16081
|
+
this.axiosInstance.interceptors.response.use((response) => response, async (error) => {
|
|
16082
|
+
const originalRequest = error.config;
|
|
16083
|
+
if (error.response?.status === 401 && originalRequest && !originalRequest._retry) {
|
|
16084
|
+
if (originalRequest.url?.includes("/console/accounts")) {
|
|
16085
|
+
console.warn("[HttpService] Unauthorized 401 on refresh endpoint, not retrying");
|
|
16086
|
+
return Promise.reject(error);
|
|
16087
|
+
}
|
|
16088
|
+
console.warn("[HttpService] Unauthorized 401, attempting token refresh and retry");
|
|
16089
|
+
originalRequest._retry = true;
|
|
16090
|
+
if (this.isRefreshing) return new Promise((resolve, reject) => {
|
|
16091
|
+
this.refreshSubscribers.push((success) => {
|
|
16092
|
+
if (success) this.axiosInstance.request(originalRequest).then(resolve).catch(reject);
|
|
16093
|
+
else reject(error);
|
|
16094
|
+
});
|
|
16095
|
+
});
|
|
16096
|
+
this.isRefreshing = true;
|
|
16097
|
+
try {
|
|
16098
|
+
await this.triggerUnauthorizedCallbacks();
|
|
16099
|
+
this.onRefreshSuccess();
|
|
16100
|
+
return this.axiosInstance.request(originalRequest);
|
|
16101
|
+
} catch (refreshError) {
|
|
16102
|
+
this.onRefreshFailure();
|
|
16103
|
+
return Promise.reject(error);
|
|
16104
|
+
} finally {
|
|
16105
|
+
this.isRefreshing = false;
|
|
16106
|
+
}
|
|
16013
16107
|
}
|
|
16014
16108
|
return Promise.reject(error);
|
|
16015
16109
|
});
|
|
16016
16110
|
}
|
|
16017
16111
|
/**
|
|
16112
|
+
* token 刷新成功,通知所有等待的请求
|
|
16113
|
+
*/
|
|
16114
|
+
onRefreshSuccess() {
|
|
16115
|
+
this.refreshSubscribers.forEach((callback) => callback(true));
|
|
16116
|
+
this.refreshSubscribers = [];
|
|
16117
|
+
}
|
|
16118
|
+
/**
|
|
16119
|
+
* token 刷新失败,通知所有等待的请求
|
|
16120
|
+
*/
|
|
16121
|
+
onRefreshFailure() {
|
|
16122
|
+
this.refreshSubscribers.forEach((callback) => callback(false));
|
|
16123
|
+
this.refreshSubscribers = [];
|
|
16124
|
+
}
|
|
16125
|
+
/**
|
|
16018
16126
|
* 注册请求拦截器
|
|
16019
16127
|
* @param onFulfilled 请求成功拦截器
|
|
16020
16128
|
* @param onRejected 请求失败拦截器
|
|
@@ -16091,16 +16199,18 @@ var HttpService = class HttpService {
|
|
|
16091
16199
|
this.unauthorizedCallbacks.delete(callback);
|
|
16092
16200
|
}
|
|
16093
16201
|
/**
|
|
16094
|
-
* 触发所有 401
|
|
16202
|
+
* 触发所有 401 回调并等待完成
|
|
16203
|
+
* @returns Promise,等待所有回调完成
|
|
16204
|
+
* @throws 如果任何回调失败,则抛出错误
|
|
16095
16205
|
*/
|
|
16096
|
-
triggerUnauthorizedCallbacks() {
|
|
16097
|
-
this.unauthorizedCallbacks
|
|
16098
|
-
|
|
16099
|
-
|
|
16100
|
-
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
}
|
|
16206
|
+
async triggerUnauthorizedCallbacks() {
|
|
16207
|
+
const callbacks = Array.from(this.unauthorizedCallbacks);
|
|
16208
|
+
const failedResults = (await Promise.allSettled(callbacks.map((callback) => callback()))).filter((r) => r.status === "rejected");
|
|
16209
|
+
if (failedResults.length > 0) {
|
|
16210
|
+
const errors = failedResults.map((r) => r.reason);
|
|
16211
|
+
console.error("[HttpService] Some unauthorized callbacks failed:", errors);
|
|
16212
|
+
throw errors[0];
|
|
16213
|
+
}
|
|
16104
16214
|
}
|
|
16105
16215
|
/**
|
|
16106
16216
|
* 更新 authToken
|
|
@@ -16212,6 +16322,7 @@ var AccountService = class {
|
|
|
16212
16322
|
this.initPromise = null;
|
|
16213
16323
|
this.initResolve = null;
|
|
16214
16324
|
this.requestInterceptorId = null;
|
|
16325
|
+
this.crossTabBroadcaster = null;
|
|
16215
16326
|
this.initPromise = new Promise((resolve) => {
|
|
16216
16327
|
this.initResolve = resolve;
|
|
16217
16328
|
});
|
|
@@ -16260,15 +16371,34 @@ var AccountService = class {
|
|
|
16260
16371
|
this.initialized = true;
|
|
16261
16372
|
this.initResolve?.(account);
|
|
16262
16373
|
}
|
|
16263
|
-
if (!wasInitialized || prev?.uid !== account?.uid)
|
|
16374
|
+
if (!wasInitialized || prev?.uid !== account?.uid) {
|
|
16375
|
+
this.notifyListeners();
|
|
16376
|
+
if (account && this.crossTabBroadcaster) this.crossTabBroadcaster.broadcastLogin();
|
|
16377
|
+
}
|
|
16264
16378
|
}
|
|
16265
16379
|
/**
|
|
16266
16380
|
* 清除账号(登出)
|
|
16381
|
+
* 先广播登出消息,再清除本地账号
|
|
16267
16382
|
*/
|
|
16268
16383
|
clearAccount() {
|
|
16384
|
+
if (this.crossTabBroadcaster) this.crossTabBroadcaster.broadcastLogout();
|
|
16385
|
+
this.setAccount(null);
|
|
16386
|
+
}
|
|
16387
|
+
/**
|
|
16388
|
+
* 静默清除账号(不广播)
|
|
16389
|
+
* 用于收到其他标签页 logout 消息时,避免循环广播
|
|
16390
|
+
*/
|
|
16391
|
+
clearAccountSilently() {
|
|
16269
16392
|
this.setAccount(null);
|
|
16270
16393
|
}
|
|
16271
16394
|
/**
|
|
16395
|
+
* 设置跨标签页认证同步广播器
|
|
16396
|
+
* 应在应用初始化时由上层(如 agent-ui)调用
|
|
16397
|
+
*/
|
|
16398
|
+
setCrossTabBroadcaster(broadcaster) {
|
|
16399
|
+
this.crossTabBroadcaster = broadcaster;
|
|
16400
|
+
}
|
|
16401
|
+
/**
|
|
16272
16402
|
* 订阅账号变化
|
|
16273
16403
|
* @param callback 变化时的回调函数
|
|
16274
16404
|
* @returns 取消订阅函数
|
|
@@ -16333,6 +16463,114 @@ var AccountService = class {
|
|
|
16333
16463
|
* 导出单例实例
|
|
16334
16464
|
*/
|
|
16335
16465
|
const accountService = new AccountService();
|
|
16466
|
+
/**
|
|
16467
|
+
* 暴露给全局,供 Agent Manager 直接调用 setAccount 刷新 Widget 状态
|
|
16468
|
+
* 这是为了解决 IDE 环境中 IPC 事件无法直接触发 Widget 账号刷新的问题
|
|
16469
|
+
*/
|
|
16470
|
+
if (typeof window !== "undefined") window.__genieAccountService = accountService;
|
|
16471
|
+
|
|
16472
|
+
//#endregion
|
|
16473
|
+
//#region ../agent-provider/src/common/utils/lru-cache.ts
|
|
16474
|
+
/**
|
|
16475
|
+
* LRU (Least Recently Used) Cache
|
|
16476
|
+
* 当缓存达到容量上限时,自动淘汰最久未使用的数据
|
|
16477
|
+
*
|
|
16478
|
+
* @template K - Key 类型
|
|
16479
|
+
* @template V - Value 类型
|
|
16480
|
+
*/
|
|
16481
|
+
var LRUCache = class {
|
|
16482
|
+
/**
|
|
16483
|
+
* 创建 LRU 缓存实例
|
|
16484
|
+
* @param capacity - 缓存容量上限
|
|
16485
|
+
*/
|
|
16486
|
+
constructor(capacity) {
|
|
16487
|
+
if (capacity <= 0) throw new Error("Cache capacity must be greater than 0");
|
|
16488
|
+
this.capacity = capacity;
|
|
16489
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
16490
|
+
}
|
|
16491
|
+
/**
|
|
16492
|
+
* 获取缓存值
|
|
16493
|
+
* @param key - 键
|
|
16494
|
+
* @returns 值,如果不存在返回 undefined
|
|
16495
|
+
*/
|
|
16496
|
+
get(key) {
|
|
16497
|
+
if (!this.cache.has(key)) return;
|
|
16498
|
+
const value = this.cache.get(key);
|
|
16499
|
+
this.cache.delete(key);
|
|
16500
|
+
this.cache.set(key, value);
|
|
16501
|
+
return value;
|
|
16502
|
+
}
|
|
16503
|
+
/**
|
|
16504
|
+
* 设置缓存值
|
|
16505
|
+
* @param key - 键
|
|
16506
|
+
* @param value - 值
|
|
16507
|
+
*/
|
|
16508
|
+
set(key, value) {
|
|
16509
|
+
if (this.cache.has(key)) this.cache.delete(key);
|
|
16510
|
+
else if (this.cache.size >= this.capacity) {
|
|
16511
|
+
const firstKey = this.cache.keys().next().value;
|
|
16512
|
+
this.cache.delete(firstKey);
|
|
16513
|
+
}
|
|
16514
|
+
this.cache.set(key, value);
|
|
16515
|
+
}
|
|
16516
|
+
/**
|
|
16517
|
+
* 检查 key 是否存在
|
|
16518
|
+
* @param key - 键
|
|
16519
|
+
* @returns 是否存在
|
|
16520
|
+
*/
|
|
16521
|
+
has(key) {
|
|
16522
|
+
return this.cache.has(key);
|
|
16523
|
+
}
|
|
16524
|
+
/**
|
|
16525
|
+
* 删除指定 key
|
|
16526
|
+
* @param key - 键
|
|
16527
|
+
* @returns 是否删除成功
|
|
16528
|
+
*/
|
|
16529
|
+
delete(key) {
|
|
16530
|
+
return this.cache.delete(key);
|
|
16531
|
+
}
|
|
16532
|
+
/**
|
|
16533
|
+
* 清空缓存
|
|
16534
|
+
*/
|
|
16535
|
+
clear() {
|
|
16536
|
+
this.cache.clear();
|
|
16537
|
+
}
|
|
16538
|
+
/**
|
|
16539
|
+
* 获取当前缓存大小
|
|
16540
|
+
* @returns 当前缓存的元素数量
|
|
16541
|
+
*/
|
|
16542
|
+
get size() {
|
|
16543
|
+
return this.cache.size;
|
|
16544
|
+
}
|
|
16545
|
+
/**
|
|
16546
|
+
* 获取缓存容量
|
|
16547
|
+
* @returns 缓存容量上限
|
|
16548
|
+
*/
|
|
16549
|
+
get maxSize() {
|
|
16550
|
+
return this.capacity;
|
|
16551
|
+
}
|
|
16552
|
+
/**
|
|
16553
|
+
* 获取所有 key
|
|
16554
|
+
* @returns key 数组
|
|
16555
|
+
*/
|
|
16556
|
+
keys() {
|
|
16557
|
+
return Array.from(this.cache.keys());
|
|
16558
|
+
}
|
|
16559
|
+
/**
|
|
16560
|
+
* 获取所有 value
|
|
16561
|
+
* @returns value 数组
|
|
16562
|
+
*/
|
|
16563
|
+
values() {
|
|
16564
|
+
return Array.from(this.cache.values());
|
|
16565
|
+
}
|
|
16566
|
+
/**
|
|
16567
|
+
* 遍历缓存
|
|
16568
|
+
* @param callback - 回调函数
|
|
16569
|
+
*/
|
|
16570
|
+
forEach(callback) {
|
|
16571
|
+
this.cache.forEach((value, key) => callback(value, key));
|
|
16572
|
+
}
|
|
16573
|
+
};
|
|
16336
16574
|
|
|
16337
16575
|
//#endregion
|
|
16338
16576
|
//#region ../agent-provider/src/common/utils/concurrency.ts
|
|
@@ -16435,20 +16673,32 @@ var CosUploadService = class {
|
|
|
16435
16673
|
* 上传单个文件到 COS
|
|
16436
16674
|
*
|
|
16437
16675
|
* @param file - 要上传的文件
|
|
16676
|
+
* @param abortSignal - 可选的 AbortSignal,用于取消上传
|
|
16438
16677
|
* @returns 上传结果,包含访问 URL 或错误信息
|
|
16439
16678
|
*/
|
|
16440
|
-
async uploadFile(file) {
|
|
16679
|
+
async uploadFile(file, abortSignal) {
|
|
16441
16680
|
const filename = file.name;
|
|
16442
16681
|
this.logger?.info(`[CosUploadService] Uploading file: ${filename}`);
|
|
16443
16682
|
try {
|
|
16683
|
+
if (abortSignal?.aborted) return {
|
|
16684
|
+
success: false,
|
|
16685
|
+
error: "Upload cancelled",
|
|
16686
|
+
aborted: true
|
|
16687
|
+
};
|
|
16444
16688
|
const objectKey = this.generateObjectKey(filename);
|
|
16445
16689
|
this.logger?.debug(`[CosUploadService] Generated objectKey: ${objectKey}`);
|
|
16446
16690
|
const presignedItem = (await this.getPresignedUrls([objectKey])).items[0];
|
|
16447
16691
|
if (!presignedItem) throw new Error("No presigned URL item returned");
|
|
16692
|
+
if (abortSignal?.aborted) return {
|
|
16693
|
+
success: false,
|
|
16694
|
+
error: "Upload cancelled",
|
|
16695
|
+
aborted: true
|
|
16696
|
+
};
|
|
16448
16697
|
const uploadResponse = await fetch(presignedItem.upload_url, {
|
|
16449
16698
|
method: "PUT",
|
|
16450
16699
|
body: file,
|
|
16451
|
-
headers: { "Content-Type": file.type || "application/octet-stream" }
|
|
16700
|
+
headers: { "Content-Type": file.type || "application/octet-stream" },
|
|
16701
|
+
signal: abortSignal
|
|
16452
16702
|
});
|
|
16453
16703
|
if (!uploadResponse.ok) {
|
|
16454
16704
|
const errorText = await uploadResponse.text().catch(() => uploadResponse.statusText);
|
|
@@ -16462,6 +16712,11 @@ var CosUploadService = class {
|
|
|
16462
16712
|
objectKey
|
|
16463
16713
|
};
|
|
16464
16714
|
} catch (error) {
|
|
16715
|
+
if (error instanceof Error && error.name === "AbortError") return {
|
|
16716
|
+
success: false,
|
|
16717
|
+
error: "Upload cancelled",
|
|
16718
|
+
aborted: true
|
|
16719
|
+
};
|
|
16465
16720
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
16466
16721
|
this.logger?.error(`[CosUploadService] Upload failed: ${filename}`, error);
|
|
16467
16722
|
return {
|
|
@@ -16476,14 +16731,25 @@ var CosUploadService = class {
|
|
|
16476
16731
|
* 使用并发控制,限制同时上传的文件数量
|
|
16477
16732
|
*
|
|
16478
16733
|
* @param files - 要上传的文件数组
|
|
16734
|
+
* @param abortSignal - 可选的 AbortSignal,用于取消上传
|
|
16479
16735
|
* @returns 所有文件的上传结果
|
|
16480
16736
|
*/
|
|
16481
|
-
async uploadFiles(files) {
|
|
16737
|
+
async uploadFiles(files, abortSignal) {
|
|
16482
16738
|
if (files.length === 0) return {
|
|
16483
16739
|
success: true,
|
|
16484
16740
|
urls: [],
|
|
16485
16741
|
results: []
|
|
16486
16742
|
};
|
|
16743
|
+
if (abortSignal?.aborted) return {
|
|
16744
|
+
success: false,
|
|
16745
|
+
error: "Upload cancelled",
|
|
16746
|
+
aborted: true,
|
|
16747
|
+
results: files.map(() => ({
|
|
16748
|
+
success: false,
|
|
16749
|
+
error: "Upload cancelled",
|
|
16750
|
+
aborted: true
|
|
16751
|
+
}))
|
|
16752
|
+
};
|
|
16487
16753
|
this.logger?.info(`[CosUploadService] Uploading ${files.length} file(s) with concurrency ${this.uploadConcurrency}`);
|
|
16488
16754
|
try {
|
|
16489
16755
|
const fileInfos = files.map((file) => ({
|
|
@@ -16495,6 +16761,12 @@ var CosUploadService = class {
|
|
|
16495
16761
|
this.logger?.debug(`[CosUploadService] Got ${presignedResponse.items.length} presigned URLs`);
|
|
16496
16762
|
if (presignedResponse.items.length !== fileInfos.length) throw new Error(`Expected ${fileInfos.length} presigned URLs, got ${presignedResponse.items.length}`);
|
|
16497
16763
|
const results = (await runWithConcurrencySettled(fileInfos.map(({ file }, index) => async () => {
|
|
16764
|
+
if (abortSignal?.aborted) return {
|
|
16765
|
+
success: false,
|
|
16766
|
+
error: "Upload cancelled",
|
|
16767
|
+
aborted: true,
|
|
16768
|
+
objectKey: fileInfos[index].objectKey
|
|
16769
|
+
};
|
|
16498
16770
|
const presignedItem = presignedResponse.items[index];
|
|
16499
16771
|
if (!presignedItem) return {
|
|
16500
16772
|
success: false,
|
|
@@ -16505,7 +16777,8 @@ var CosUploadService = class {
|
|
|
16505
16777
|
const uploadResponse = await fetch(presignedItem.upload_url, {
|
|
16506
16778
|
method: "PUT",
|
|
16507
16779
|
body: file,
|
|
16508
|
-
headers: { "Content-Type": file.type || "application/octet-stream" }
|
|
16780
|
+
headers: { "Content-Type": file.type || "application/octet-stream" },
|
|
16781
|
+
signal: abortSignal
|
|
16509
16782
|
});
|
|
16510
16783
|
if (!uploadResponse.ok) {
|
|
16511
16784
|
const errorText = await uploadResponse.text().catch(() => uploadResponse.statusText);
|
|
@@ -16522,6 +16795,12 @@ var CosUploadService = class {
|
|
|
16522
16795
|
objectKey: presignedItem.object_key
|
|
16523
16796
|
};
|
|
16524
16797
|
} catch (error) {
|
|
16798
|
+
if (error instanceof Error && error.name === "AbortError") return {
|
|
16799
|
+
success: false,
|
|
16800
|
+
error: "Upload cancelled",
|
|
16801
|
+
aborted: true,
|
|
16802
|
+
objectKey: presignedItem.object_key
|
|
16803
|
+
};
|
|
16525
16804
|
return {
|
|
16526
16805
|
success: false,
|
|
16527
16806
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
@@ -16575,35 +16854,35 @@ var CosUploadService = class {
|
|
|
16575
16854
|
* E2B Filesystem Implementation
|
|
16576
16855
|
*
|
|
16577
16856
|
* Provides FilesResource implementation using E2B Sandbox SDK.
|
|
16578
|
-
*
|
|
16857
|
+
* Supports optional auto-reconnect on auth failure (401/403).
|
|
16579
16858
|
*
|
|
16580
16859
|
* @see https://e2b.dev/docs/filesystem/read-write
|
|
16581
16860
|
* @see https://e2b.dev/docs/filesystem/watch
|
|
16582
16861
|
*/
|
|
16583
16862
|
/**
|
|
16584
|
-
* E2B Filesystem
|
|
16863
|
+
* E2B Filesystem
|
|
16585
16864
|
*
|
|
16586
|
-
* Wraps E2B Sandbox SDK's filesystem operations to implement FilesResource
|
|
16865
|
+
* Wraps E2B Sandbox SDK's filesystem operations to implement FilesResource.
|
|
16866
|
+
* When `reconnectFn` is provided, automatically reconnects on auth errors.
|
|
16587
16867
|
*
|
|
16588
16868
|
* @example
|
|
16589
16869
|
* ```typescript
|
|
16590
|
-
*
|
|
16591
|
-
*
|
|
16592
|
-
* apiKey: 'e2b_xxx'
|
|
16593
|
-
* });
|
|
16594
|
-
*
|
|
16595
|
-
* // Read/write files
|
|
16596
|
-
* await fs.write('/test.txt', 'Hello World');
|
|
16597
|
-
* const content = await fs.read('/test.txt');
|
|
16870
|
+
* // Basic usage (no auto-reconnect)
|
|
16871
|
+
* const fs = await E2BFilesystem.connect({ sandboxId: '...' });
|
|
16598
16872
|
*
|
|
16599
|
-
* //
|
|
16600
|
-
* const
|
|
16601
|
-
*
|
|
16602
|
-
* });
|
|
16873
|
+
* // With auto-reconnect on token expiry
|
|
16874
|
+
* const fs = await E2BFilesystem.connect({ sandboxId: '...' });
|
|
16875
|
+
* fs.setReconnectFn(async () => fetchFreshConnectionInfo());
|
|
16603
16876
|
* ```
|
|
16604
16877
|
*/
|
|
16605
16878
|
var E2BFilesystem = class E2BFilesystem {
|
|
16879
|
+
static {
|
|
16880
|
+
this.MIN_RECONNECT_INTERVAL_MS = 10 * 1e3;
|
|
16881
|
+
}
|
|
16606
16882
|
constructor(sandbox) {
|
|
16883
|
+
this.isReconnecting = false;
|
|
16884
|
+
this.reconnectSubscribers = [];
|
|
16885
|
+
this.lastReconnectAt = 0;
|
|
16607
16886
|
this.sandbox = sandbox;
|
|
16608
16887
|
}
|
|
16609
16888
|
/**
|
|
@@ -16619,38 +16898,111 @@ var E2BFilesystem = class E2BFilesystem {
|
|
|
16619
16898
|
}));
|
|
16620
16899
|
}
|
|
16621
16900
|
/**
|
|
16901
|
+
* Set reconnect callback. When set, auth errors trigger automatic reconnect + retry.
|
|
16902
|
+
*/
|
|
16903
|
+
setReconnectFn(fn) {
|
|
16904
|
+
this.reconnectFn = fn;
|
|
16905
|
+
}
|
|
16906
|
+
/**
|
|
16622
16907
|
* Get the underlying E2B Sandbox instance
|
|
16623
16908
|
*/
|
|
16624
16909
|
getSandbox() {
|
|
16625
16910
|
return this.sandbox;
|
|
16626
16911
|
}
|
|
16912
|
+
isAuthError(error) {
|
|
16913
|
+
if (!error || typeof error !== "object") return false;
|
|
16914
|
+
const err = error;
|
|
16915
|
+
if (err.status === 401 || err.status === 403) return true;
|
|
16916
|
+
if (err.statusCode === 401 || err.statusCode === 403) return true;
|
|
16917
|
+
if (err.response && typeof err.response === "object") {
|
|
16918
|
+
const resp = err.response;
|
|
16919
|
+
if (resp.status === 401 || resp.status === 403) return true;
|
|
16920
|
+
}
|
|
16921
|
+
if (typeof err.message === "string") {
|
|
16922
|
+
const msg = err.message.toLowerCase();
|
|
16923
|
+
if (msg.includes("unauthorized") || msg.includes("token expired") || msg.includes("authentication")) return true;
|
|
16924
|
+
}
|
|
16925
|
+
return false;
|
|
16926
|
+
}
|
|
16927
|
+
canAttemptReconnect() {
|
|
16928
|
+
return Date.now() - this.lastReconnectAt >= E2BFilesystem.MIN_RECONNECT_INTERVAL_MS;
|
|
16929
|
+
}
|
|
16930
|
+
/**
|
|
16931
|
+
* Reconnect with fresh credentials.
|
|
16932
|
+
* Only one reconnect in-flight at a time; concurrent callers share the result.
|
|
16933
|
+
*/
|
|
16934
|
+
async reconnect() {
|
|
16935
|
+
if (this.isReconnecting) return new Promise((resolve, reject) => {
|
|
16936
|
+
this.reconnectSubscribers.push((success) => {
|
|
16937
|
+
if (success) resolve();
|
|
16938
|
+
else reject(/* @__PURE__ */ new Error("E2B sandbox reconnect failed"));
|
|
16939
|
+
});
|
|
16940
|
+
});
|
|
16941
|
+
this.isReconnecting = true;
|
|
16942
|
+
this.lastReconnectAt = Date.now();
|
|
16943
|
+
try {
|
|
16944
|
+
const info = await this.reconnectFn();
|
|
16945
|
+
this.sandbox = await e2b.Sandbox.connect(info.sandboxId, {
|
|
16946
|
+
domain: info.domain,
|
|
16947
|
+
apiUrl: info.apiUrl,
|
|
16948
|
+
requestTimeoutMs: info.requestTimeoutMs,
|
|
16949
|
+
debug: info.debug,
|
|
16950
|
+
headers: info.headers
|
|
16951
|
+
});
|
|
16952
|
+
this.reconnectSubscribers.forEach((cb) => cb(true));
|
|
16953
|
+
this.reconnectSubscribers = [];
|
|
16954
|
+
} catch (error) {
|
|
16955
|
+
this.reconnectSubscribers.forEach((cb) => cb(false));
|
|
16956
|
+
this.reconnectSubscribers = [];
|
|
16957
|
+
throw error;
|
|
16958
|
+
} finally {
|
|
16959
|
+
this.isReconnecting = false;
|
|
16960
|
+
}
|
|
16961
|
+
}
|
|
16962
|
+
/**
|
|
16963
|
+
* Execute an operation. If reconnectFn is set and an auth error occurs,
|
|
16964
|
+
* reconnect and retry once.
|
|
16965
|
+
*/
|
|
16966
|
+
async exec(operation) {
|
|
16967
|
+
try {
|
|
16968
|
+
return await operation(this.sandbox.files);
|
|
16969
|
+
} catch (error) {
|
|
16970
|
+
if (this.reconnectFn && this.isAuthError(error) && this.canAttemptReconnect()) {
|
|
16971
|
+
await this.reconnect();
|
|
16972
|
+
return operation(this.sandbox.files);
|
|
16973
|
+
}
|
|
16974
|
+
throw error;
|
|
16975
|
+
}
|
|
16976
|
+
}
|
|
16627
16977
|
read(path, opts) {
|
|
16628
|
-
return this.
|
|
16978
|
+
return this.exec((f) => f.read(path, opts));
|
|
16629
16979
|
}
|
|
16630
16980
|
write(pathOrFiles, dataOrOpts, opts) {
|
|
16631
|
-
|
|
16632
|
-
|
|
16981
|
+
return this.exec((f) => {
|
|
16982
|
+
if (Array.isArray(pathOrFiles)) return f.write(pathOrFiles, dataOrOpts);
|
|
16983
|
+
return f.write(pathOrFiles, dataOrOpts, opts);
|
|
16984
|
+
});
|
|
16633
16985
|
}
|
|
16634
16986
|
async list(path, opts) {
|
|
16635
|
-
return this.
|
|
16987
|
+
return this.exec((f) => f.list(path, opts));
|
|
16636
16988
|
}
|
|
16637
16989
|
async exists(path, opts) {
|
|
16638
|
-
return this.
|
|
16990
|
+
return this.exec((f) => f.exists(path, opts));
|
|
16639
16991
|
}
|
|
16640
16992
|
async makeDir(path, opts) {
|
|
16641
|
-
return this.
|
|
16993
|
+
return this.exec((f) => f.makeDir(path, opts));
|
|
16642
16994
|
}
|
|
16643
16995
|
async remove(path, opts) {
|
|
16644
|
-
return this.
|
|
16996
|
+
return this.exec((f) => f.remove(path, opts));
|
|
16645
16997
|
}
|
|
16646
16998
|
async rename(oldPath, newPath, opts) {
|
|
16647
|
-
return this.
|
|
16999
|
+
return this.exec((f) => f.rename(oldPath, newPath, opts));
|
|
16648
17000
|
}
|
|
16649
17001
|
async getInfo(path, opts) {
|
|
16650
|
-
return this.
|
|
17002
|
+
return this.exec((f) => f.getInfo(path, opts));
|
|
16651
17003
|
}
|
|
16652
17004
|
async watchDir(path, onEvent, opts) {
|
|
16653
|
-
return this.
|
|
17005
|
+
return this.exec((f) => f.watchDir(path, onEvent, opts));
|
|
16654
17006
|
}
|
|
16655
17007
|
};
|
|
16656
17008
|
|
|
@@ -16802,8 +17154,11 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
16802
17154
|
this.filesystemCache = /* @__PURE__ */ new Map();
|
|
16803
17155
|
this.connectionCache = /* @__PURE__ */ new Map();
|
|
16804
17156
|
this.eventListeners = /* @__PURE__ */ new Map();
|
|
17157
|
+
this.productConfigCache = null;
|
|
16805
17158
|
this.options = options;
|
|
16806
17159
|
this.logger = options.logger;
|
|
17160
|
+
this.marketplaceCache = new LRUCache(200);
|
|
17161
|
+
this.pluginCache = new LRUCache(2e3);
|
|
16807
17162
|
if (options.endpoint) httpService.setBaseURL(options.endpoint);
|
|
16808
17163
|
if (options.authToken) httpService.setAuthToken(options.authToken);
|
|
16809
17164
|
if (options.headers && Object.keys(options.headers).length > 0) this.requestInterceptorId = httpService.registerRequestInterceptor((config) => {
|
|
@@ -16854,7 +17209,14 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
16854
17209
|
const cached = this.filesystemCache.get(agentId);
|
|
16855
17210
|
if (cached) return cached;
|
|
16856
17211
|
const info = await this.getSandboxInfo(agentId);
|
|
16857
|
-
const
|
|
17212
|
+
const e2bFilesystem = await E2BFilesystem.connect(info);
|
|
17213
|
+
e2bFilesystem.setReconnectFn(async () => {
|
|
17214
|
+
this.logger?.debug(`Reconnecting E2B sandbox for agent: ${agentId}`);
|
|
17215
|
+
const newInfo = await this.getSandboxInfo(agentId);
|
|
17216
|
+
this.logger?.debug(`E2B sandbox reconnected for agent: ${agentId}`);
|
|
17217
|
+
return newInfo;
|
|
17218
|
+
});
|
|
17219
|
+
const filesystem = createAgentFilesystem(e2bFilesystem);
|
|
16858
17220
|
this.filesystemCache.set(agentId, filesystem);
|
|
16859
17221
|
this.logger?.debug(`Created filesystem for agent: ${agentId}`);
|
|
16860
17222
|
return filesystem;
|
|
@@ -16922,15 +17284,9 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
16922
17284
|
const url = this.buildGetUrl("/console/as/conversations/", params);
|
|
16923
17285
|
const apiResponse = await httpService.get(url);
|
|
16924
17286
|
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
17287
|
return {
|
|
16932
|
-
agents,
|
|
16933
|
-
pagination
|
|
17288
|
+
agents: apiResponse.data.conversations.map((a) => this.toAgentState(a)),
|
|
17289
|
+
pagination: apiResponse.data.pagination
|
|
16934
17290
|
};
|
|
16935
17291
|
} catch (error) {
|
|
16936
17292
|
this.logger?.error("Failed to list agents:", error);
|
|
@@ -16940,13 +17296,21 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
16940
17296
|
/**
|
|
16941
17297
|
* Create a new conversation
|
|
16942
17298
|
* POST {endpoint}/console/as/conversations
|
|
17299
|
+
* @param params - Session params containing cwd and optional configuration
|
|
16943
17300
|
*/
|
|
16944
|
-
async create() {
|
|
17301
|
+
async create(params) {
|
|
16945
17302
|
try {
|
|
16946
|
-
const
|
|
16947
|
-
|
|
16948
|
-
|
|
16949
|
-
});
|
|
17303
|
+
const { options = {} } = params;
|
|
17304
|
+
const codebuddyMeta = options._meta?.["codebuddy.ai"];
|
|
17305
|
+
const tagsObj = options.tags || codebuddyMeta?.tags;
|
|
17306
|
+
const tagsArray = tagsObj ? Object.entries(tagsObj).map(([key, value]) => `${key}:${value}`) : void 0;
|
|
17307
|
+
const createPayload = {
|
|
17308
|
+
prompt: (options.prompt || "").slice(0, 100),
|
|
17309
|
+
model: options.model || "deepseek-r1",
|
|
17310
|
+
...tagsArray && tagsArray.length > 0 ? { tags: tagsArray } : {}
|
|
17311
|
+
};
|
|
17312
|
+
console.log("[CloudAgentProvider] Creating conversation with payload:", createPayload);
|
|
17313
|
+
const apiResponse = await httpService.post("/console/as/conversations/", createPayload);
|
|
16950
17314
|
if (!apiResponse.data) throw new Error("No data in API response");
|
|
16951
17315
|
this.logger?.info(`Created conversation: ${apiResponse.data.id}`);
|
|
16952
17316
|
return apiResponse.data.id;
|
|
@@ -16996,7 +17360,14 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
16996
17360
|
} catch (error) {
|
|
16997
17361
|
this.logger?.debug(`Failed to fetch conversation details for ${agentId}:`, error);
|
|
16998
17362
|
}
|
|
16999
|
-
|
|
17363
|
+
const existingConnection = this.connectionCache.get(endpoint);
|
|
17364
|
+
if (existingConnection) {
|
|
17365
|
+
this.connectionCache.delete(endpoint);
|
|
17366
|
+
existingConnection.removeAllListeners();
|
|
17367
|
+
existingConnection.disconnect().catch((err) => {
|
|
17368
|
+
this.logger?.debug("Failed to disconnect old connection:", err);
|
|
17369
|
+
});
|
|
17370
|
+
}
|
|
17000
17371
|
const clientCapabilities = {
|
|
17001
17372
|
...this.options.clientCapabilities,
|
|
17002
17373
|
_meta: {
|
|
@@ -17116,6 +17487,35 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17116
17487
|
}
|
|
17117
17488
|
}
|
|
17118
17489
|
/**
|
|
17490
|
+
* Update conversation status by ID
|
|
17491
|
+
* POST {endpoint}/console/as/conversations/{agentId}
|
|
17492
|
+
*
|
|
17493
|
+
* @param agentId - Conversation ID to update
|
|
17494
|
+
* @param status - New status for the conversation
|
|
17495
|
+
* @returns PatchConversationResponse containing the updated conversation ID
|
|
17496
|
+
*
|
|
17497
|
+
* @example
|
|
17498
|
+
* ```typescript
|
|
17499
|
+
* const result = await provider.updateStatus('agent-123', 'completed');
|
|
17500
|
+
* console.log('Updated conversation status:', result.id);
|
|
17501
|
+
* ```
|
|
17502
|
+
*/
|
|
17503
|
+
async updateStatus(agentId, status) {
|
|
17504
|
+
try {
|
|
17505
|
+
const body = { status };
|
|
17506
|
+
const apiResponse = await httpService.post(`/console/as/conversations/${agentId}`, body);
|
|
17507
|
+
if (!apiResponse.data) {
|
|
17508
|
+
this.logger?.info(`Updated conversation status: ${agentId} to "${status}"`);
|
|
17509
|
+
return { id: agentId };
|
|
17510
|
+
}
|
|
17511
|
+
this.logger?.info(`Updated conversation status: ${apiResponse.data.id} to "${status}"`);
|
|
17512
|
+
return apiResponse.data;
|
|
17513
|
+
} catch (error) {
|
|
17514
|
+
this.logger?.error(`Failed to update conversation status ${agentId}:`, error);
|
|
17515
|
+
throw error;
|
|
17516
|
+
}
|
|
17517
|
+
}
|
|
17518
|
+
/**
|
|
17119
17519
|
* Get available models from product configuration
|
|
17120
17520
|
*
|
|
17121
17521
|
* GET {endpoint}/console/enterprises/{personal|enterpriseId}/models?repos[]={repo}
|
|
@@ -17146,9 +17546,13 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17146
17546
|
this.logger?.warn("[CloudAgentProvider] No data in config response, returning empty models");
|
|
17147
17547
|
return [];
|
|
17148
17548
|
}
|
|
17149
|
-
|
|
17150
|
-
|
|
17151
|
-
|
|
17549
|
+
this.productConfigCache = apiResponse.data;
|
|
17550
|
+
const productConfig = apiResponse.data;
|
|
17551
|
+
const allModels = productConfig.models ?? [];
|
|
17552
|
+
const cliModelIds = (productConfig.agents ?? []).find((agent) => agent.name === "cli")?.models ?? [];
|
|
17553
|
+
const filteredModels = cliModelIds.length > 0 ? allModels.filter((model) => cliModelIds.includes(model.id)) : allModels;
|
|
17554
|
+
this.logger?.info(`[CloudAgentProvider] Retrieved ${filteredModels.length} models for cli agent (total: ${allModels.length})`);
|
|
17555
|
+
return filteredModels.map((model) => ({
|
|
17152
17556
|
id: model.id,
|
|
17153
17557
|
name: model.name ?? model.id,
|
|
17154
17558
|
description: model.description,
|
|
@@ -17170,6 +17574,43 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17170
17574
|
}
|
|
17171
17575
|
}
|
|
17172
17576
|
/**
|
|
17577
|
+
* 获取产品部署类型(从缓存)
|
|
17578
|
+
* 需要先调用 getModels() 初始化缓存
|
|
17579
|
+
*
|
|
17580
|
+
* @returns 部署类型:'SaaS' | 'Cloud-Hosted' | 'Self-Hosted',默认为 'SaaS'
|
|
17581
|
+
*/
|
|
17582
|
+
getDeploymentType() {
|
|
17583
|
+
return this.productConfigCache?.deploymentType ?? "SaaS";
|
|
17584
|
+
}
|
|
17585
|
+
/**
|
|
17586
|
+
* 获取 Credit 购买引导配置(从缓存)
|
|
17587
|
+
* 需要先调用 getModels() 初始化缓存
|
|
17588
|
+
*
|
|
17589
|
+
* @returns Credit 购买引导配置,key 为错误码。如果后端未返回,则使用默认配置
|
|
17590
|
+
*/
|
|
17591
|
+
getCreditPurchaseActions() {
|
|
17592
|
+
return this.productConfigCache?.config?.creditPurchaseActions ?? {
|
|
17593
|
+
"14018": {
|
|
17594
|
+
labelZh: "获取 Credits",
|
|
17595
|
+
labelEn: "Get credits",
|
|
17596
|
+
url: "https://www.codebuddy.cn/profile/plan",
|
|
17597
|
+
showButton: true
|
|
17598
|
+
},
|
|
17599
|
+
"6004": {
|
|
17600
|
+
labelZh: "升级专业版",
|
|
17601
|
+
labelEn: "Upgrade to Pro",
|
|
17602
|
+
url: "https://www.codebuddy.cn/profile/plan",
|
|
17603
|
+
showButton: true
|
|
17604
|
+
},
|
|
17605
|
+
"6005": {
|
|
17606
|
+
labelZh: "升级专业版",
|
|
17607
|
+
labelEn: "Upgrade to Pro",
|
|
17608
|
+
url: "https://www.codebuddy.cn/profile/plan",
|
|
17609
|
+
showButton: true
|
|
17610
|
+
}
|
|
17611
|
+
};
|
|
17612
|
+
}
|
|
17613
|
+
/**
|
|
17173
17614
|
* Generate a unique request ID
|
|
17174
17615
|
*/
|
|
17175
17616
|
generateRequestId() {
|
|
@@ -17252,7 +17693,7 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17252
17693
|
/**
|
|
17253
17694
|
* Upload files to cloud storage via COS presigned URL
|
|
17254
17695
|
*
|
|
17255
|
-
* @param params - files array (File objects in browser)
|
|
17696
|
+
* @param params - files array (File objects in browser), optional abortSignal
|
|
17256
17697
|
* @returns Response with corresponding cloud URLs
|
|
17257
17698
|
*/
|
|
17258
17699
|
async uploadFile(params) {
|
|
@@ -17262,12 +17703,13 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17262
17703
|
success: false,
|
|
17263
17704
|
error: "No valid File objects provided"
|
|
17264
17705
|
};
|
|
17265
|
-
const result = await this.cosUploadService.uploadFiles(files);
|
|
17706
|
+
const result = await this.cosUploadService.uploadFiles(files, params.abortSignal);
|
|
17266
17707
|
return {
|
|
17267
17708
|
success: result.success,
|
|
17268
17709
|
urls: result.urls,
|
|
17269
17710
|
expireSeconds: result.expireSeconds,
|
|
17270
|
-
error: result.error
|
|
17711
|
+
error: result.error,
|
|
17712
|
+
aborted: result.aborted
|
|
17271
17713
|
};
|
|
17272
17714
|
}
|
|
17273
17715
|
/**
|
|
@@ -17309,20 +17751,22 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17309
17751
|
}
|
|
17310
17752
|
/**
|
|
17311
17753
|
* 获取支持的场景列表
|
|
17312
|
-
* API 端点: GET /
|
|
17754
|
+
* API 端点: GET /v2/as/support/scenes (不鉴权)
|
|
17313
17755
|
* 用于 Welcome 页面的 QuickActions 快捷操作
|
|
17314
17756
|
*
|
|
17757
|
+
* @param locale - 可选,语言环境(如 'zh-CN', 'en-US'),用于获取对应语言的场景数据
|
|
17315
17758
|
* @returns Promise<SupportScene[]> 支持的场景列表
|
|
17316
17759
|
*/
|
|
17317
|
-
async getSupportScenes() {
|
|
17760
|
+
async getSupportScenes(locale) {
|
|
17318
17761
|
try {
|
|
17319
|
-
const
|
|
17762
|
+
const url = this.buildGetUrl("/v2/as/support/scenes", locale ? { locale } : void 0);
|
|
17763
|
+
const apiResponse = await httpService.get(url);
|
|
17320
17764
|
if (!apiResponse.data) {
|
|
17321
17765
|
this.logger?.warn("[CloudAgentProvider] No data in support scenes response");
|
|
17322
17766
|
return [];
|
|
17323
17767
|
}
|
|
17324
17768
|
const scenes = apiResponse.data.scenes || [];
|
|
17325
|
-
this.logger?.info(`[CloudAgentProvider] Retrieved ${scenes.length} support scenes`);
|
|
17769
|
+
this.logger?.info(`[CloudAgentProvider] Retrieved ${scenes.length} support scenes${locale ? ` for locale: ${locale}` : ""}`);
|
|
17326
17770
|
return scenes;
|
|
17327
17771
|
} catch (error) {
|
|
17328
17772
|
this.logger?.error("[CloudAgentProvider] Failed to get support scenes:", error);
|
|
@@ -17338,7 +17782,8 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17338
17782
|
type: "cloud",
|
|
17339
17783
|
status,
|
|
17340
17784
|
createdAt: data.createdAt ? new Date(data.createdAt) : void 0,
|
|
17341
|
-
capabilities: this.options.clientCapabilities
|
|
17785
|
+
capabilities: this.options.clientCapabilities,
|
|
17786
|
+
isUserDefinedTitle: data.isUserDefinedTitle
|
|
17342
17787
|
};
|
|
17343
17788
|
}
|
|
17344
17789
|
/**
|
|
@@ -17354,57 +17799,500 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17354
17799
|
const queryString = searchParams.toString();
|
|
17355
17800
|
return queryString ? `${path}?${queryString}` : path;
|
|
17356
17801
|
}
|
|
17357
|
-
};
|
|
17358
|
-
|
|
17359
|
-
//#endregion
|
|
17360
|
-
//#region ../agent-provider/src/common/providers/local-agent-provider/local-connection.ts
|
|
17361
|
-
/**
|
|
17362
|
-
* Local Agent Connection
|
|
17363
|
-
* Wraps AcpJsonRpcClient to implement AgentConnection interface
|
|
17364
|
-
*
|
|
17365
|
-
* Uses IWidgetChannel for IPC communication with ExtensionHost
|
|
17366
|
-
* Migrated from ipc-agent-provider for unified local agent access
|
|
17367
|
-
*/
|
|
17368
|
-
|
|
17369
|
-
//#endregion
|
|
17370
|
-
//#region ../agent-provider/src/common/client/session.ts
|
|
17371
|
-
/**
|
|
17372
|
-
* ActiveSessionImpl - Implements the ActiveSession interface
|
|
17373
|
-
*
|
|
17374
|
-
* This class wraps an AgentConnection and provides the session-centric API.
|
|
17375
|
-
* It is created by SessionManager when creating or loading sessions.
|
|
17376
|
-
*
|
|
17377
|
-
* @example
|
|
17378
|
-
* ```typescript
|
|
17379
|
-
* // Created by client.sessions.new() or client.sessions.load()
|
|
17380
|
-
* const session = await client.sessions.new({ cwd: '/workspace' });
|
|
17381
|
-
*
|
|
17382
|
-
* // Access agent state
|
|
17383
|
-
* console.log(session.agentState.status);
|
|
17384
|
-
*
|
|
17385
|
-
* // Send prompt
|
|
17386
|
-
* const response = await session.prompts.send({ content: 'Hello!' });
|
|
17387
|
-
*
|
|
17388
|
-
* // Cleanup
|
|
17389
|
-
* session.disconnect();
|
|
17390
|
-
* ```
|
|
17391
|
-
*/
|
|
17392
|
-
var ActiveSessionImpl = class {
|
|
17393
17802
|
/**
|
|
17394
|
-
*
|
|
17395
|
-
*
|
|
17396
|
-
* @param sessionId - Session ID
|
|
17397
|
-
* @param agentId - Agent ID
|
|
17398
|
-
* @param connection - Already connected AgentConnection
|
|
17399
|
-
* @param options - Additional options
|
|
17803
|
+
* 获取已安装插件列表
|
|
17804
|
+
* GET /console/as/user/plugins/installed
|
|
17400
17805
|
*/
|
|
17401
|
-
|
|
17402
|
-
|
|
17403
|
-
|
|
17404
|
-
|
|
17405
|
-
|
|
17406
|
-
|
|
17407
|
-
|
|
17806
|
+
async getInstalledPlugins(forceRefresh) {
|
|
17807
|
+
try {
|
|
17808
|
+
const result = ((await httpService.get("/console/as/user/plugins/installed")).data?.plugins || []).map((p) => ({
|
|
17809
|
+
name: p.plugin_name,
|
|
17810
|
+
marketplaceName: p.marketplace_name,
|
|
17811
|
+
status: p.enabled ? "enabled" : "disabled",
|
|
17812
|
+
description: p.description,
|
|
17813
|
+
version: p.version,
|
|
17814
|
+
installScope: p.scope === "local" ? "project" : p.scope,
|
|
17815
|
+
installedScopes: [p.scope],
|
|
17816
|
+
installId: p.id
|
|
17817
|
+
}));
|
|
17818
|
+
result.forEach((plugin) => {
|
|
17819
|
+
this.pluginCache.set(plugin.name, plugin);
|
|
17820
|
+
});
|
|
17821
|
+
return result;
|
|
17822
|
+
} catch (error) {
|
|
17823
|
+
this.logger?.error("[CloudAgentProvider] getInstalledPlugins failed:", error);
|
|
17824
|
+
throw error;
|
|
17825
|
+
}
|
|
17826
|
+
}
|
|
17827
|
+
/**
|
|
17828
|
+
* 安装插件
|
|
17829
|
+
* POST /console/as/user/plugins/install
|
|
17830
|
+
*
|
|
17831
|
+
* @param pluginNames - 插件名称数组
|
|
17832
|
+
* @param marketplaceNameOrId - 市场名称或 ID
|
|
17833
|
+
*/
|
|
17834
|
+
async installPlugins(pluginNames, marketplaceNameOrId, installScope, marketplaceSource, workspacePath) {
|
|
17835
|
+
try {
|
|
17836
|
+
const marketplaceId = await this.findMarketplaceId(marketplaceNameOrId);
|
|
17837
|
+
if (!marketplaceId) return {
|
|
17838
|
+
success: false,
|
|
17839
|
+
error: `Marketplace not found: ${marketplaceNameOrId}`
|
|
17840
|
+
};
|
|
17841
|
+
const failed = (await Promise.allSettled(pluginNames.map((pluginName) => httpService.post("/console/as/user/plugins/install", {
|
|
17842
|
+
plugin_name: pluginName,
|
|
17843
|
+
marketplace_id: marketplaceId,
|
|
17844
|
+
version: "latest"
|
|
17845
|
+
})))).filter((r) => r.status === "rejected");
|
|
17846
|
+
if (failed.length > 0) {
|
|
17847
|
+
const errors = failed.map((r) => r.reason?.message || "Unknown error");
|
|
17848
|
+
return {
|
|
17849
|
+
success: false,
|
|
17850
|
+
error: `安装失败 ${failed.length} 个插件: ${errors.join(", ")}`
|
|
17851
|
+
};
|
|
17852
|
+
}
|
|
17853
|
+
return { success: true };
|
|
17854
|
+
} catch (error) {
|
|
17855
|
+
return {
|
|
17856
|
+
success: false,
|
|
17857
|
+
error: this.extractErrorMessage(error)
|
|
17858
|
+
};
|
|
17859
|
+
}
|
|
17860
|
+
}
|
|
17861
|
+
/**
|
|
17862
|
+
* 卸载插件
|
|
17863
|
+
* POST /console/as/user/plugins/installed/:id/uninstall
|
|
17864
|
+
*
|
|
17865
|
+
* 完整链路:
|
|
17866
|
+
* CloudAgentProvider.uninstallPlugin()
|
|
17867
|
+
* -> HTTP POST /console/as/user/plugins/installed/:id/uninstall
|
|
17868
|
+
* -> agentserver: PluginInstallService.Uninstall()
|
|
17869
|
+
* -> 软删除 DB + 异步同步到活跃沙箱
|
|
17870
|
+
*
|
|
17871
|
+
* @param pluginName - 插件名称
|
|
17872
|
+
* @param marketplaceName - 市场名称(用于标识唯一插件)
|
|
17873
|
+
* @param scope - 卸载范围 ('user' | 'project' | 'project-local')
|
|
17874
|
+
*/
|
|
17875
|
+
async uninstallPlugin(pluginName, marketplaceName, scope) {
|
|
17876
|
+
try {
|
|
17877
|
+
const installId = await this.findPluginInstallId(pluginName);
|
|
17878
|
+
if (!installId) return {
|
|
17879
|
+
success: false,
|
|
17880
|
+
error: `Plugin not found or not installed: ${pluginName}`
|
|
17881
|
+
};
|
|
17882
|
+
await httpService.post(`/console/as/user/plugins/installed/${installId}/uninstall`);
|
|
17883
|
+
return { success: true };
|
|
17884
|
+
} catch (error) {
|
|
17885
|
+
return {
|
|
17886
|
+
success: false,
|
|
17887
|
+
error: this.extractErrorMessage(error)
|
|
17888
|
+
};
|
|
17889
|
+
}
|
|
17890
|
+
}
|
|
17891
|
+
/**
|
|
17892
|
+
* 获取插件市场列表
|
|
17893
|
+
* GET /console/as/marketplace/sources
|
|
17894
|
+
*/
|
|
17895
|
+
async getPluginMarketplaces(forceRefresh) {
|
|
17896
|
+
try {
|
|
17897
|
+
const result = ((await httpService.get("/console/as/marketplace/sources")).data?.sources || []).map((src) => ({
|
|
17898
|
+
id: src.id,
|
|
17899
|
+
name: src.name,
|
|
17900
|
+
type: this.mapSourceType(src.source_type),
|
|
17901
|
+
source: { url: src.url },
|
|
17902
|
+
description: src.name,
|
|
17903
|
+
isBuiltin: src.is_default
|
|
17904
|
+
}));
|
|
17905
|
+
result.forEach((m) => {
|
|
17906
|
+
const marketplaceInfo = {
|
|
17907
|
+
id: m.id,
|
|
17908
|
+
name: m.name
|
|
17909
|
+
};
|
|
17910
|
+
this.marketplaceCache.set(m.name, marketplaceInfo);
|
|
17911
|
+
this.marketplaceCache.set(m.id, marketplaceInfo);
|
|
17912
|
+
});
|
|
17913
|
+
return result;
|
|
17914
|
+
} catch (error) {
|
|
17915
|
+
this.logger?.error("[CloudAgentProvider] getPluginMarketplaces failed:", error);
|
|
17916
|
+
throw error;
|
|
17917
|
+
}
|
|
17918
|
+
}
|
|
17919
|
+
/**
|
|
17920
|
+
* 获取市场下的插件列表
|
|
17921
|
+
* - 有 searchText: GET /console/as/marketplace/plugins/search (跨所有市场搜索)
|
|
17922
|
+
* - 无 searchText: GET /console/as/marketplace/plugins (指定市场)
|
|
17923
|
+
*
|
|
17924
|
+
* @param marketplaceNameOrId - 市场名称或 ID(优先使用 ID,如果是名称则从缓存查询 ID)
|
|
17925
|
+
* @param forceRefresh - 是否强制刷新
|
|
17926
|
+
* @param searchText - 搜索关键字(如果提供,则跨所有市场搜索)
|
|
17927
|
+
*/
|
|
17928
|
+
async getMarketplacePlugins(marketplaceNameOrId, forceRefresh, searchText) {
|
|
17929
|
+
try {
|
|
17930
|
+
if (searchText) return ((await httpService.get("/console/as/marketplace/plugins/search", { params: {
|
|
17931
|
+
q: searchText,
|
|
17932
|
+
page: 1,
|
|
17933
|
+
page_size: 100
|
|
17934
|
+
} })).data?.plugins || []).map((p) => this.mapPluginData(p));
|
|
17935
|
+
const sourceId = await this.findMarketplaceId(marketplaceNameOrId);
|
|
17936
|
+
if (!sourceId) {
|
|
17937
|
+
this.logger?.warn(`[CloudAgentProvider] Marketplace not found: ${marketplaceNameOrId}`);
|
|
17938
|
+
return [];
|
|
17939
|
+
}
|
|
17940
|
+
const params = {
|
|
17941
|
+
source_id: sourceId,
|
|
17942
|
+
page: 1,
|
|
17943
|
+
page_size: 100
|
|
17944
|
+
};
|
|
17945
|
+
return ((await httpService.get("/console/as/marketplace/plugins", { params })).data?.plugins || []).map((p) => this.mapPluginData(p));
|
|
17946
|
+
} catch (error) {
|
|
17947
|
+
this.logger?.error("[CloudAgentProvider] getMarketplacePlugins failed:", error);
|
|
17948
|
+
throw error;
|
|
17949
|
+
}
|
|
17950
|
+
}
|
|
17951
|
+
/**
|
|
17952
|
+
* 获取插件详情
|
|
17953
|
+
* GET /console/as/marketplace/plugins/:name/detail
|
|
17954
|
+
*
|
|
17955
|
+
* @param pluginName - 插件名称
|
|
17956
|
+
* @param marketplaceNameOrId - 市场名称或 ID(优先使用 ID,如果是名称则从缓存查询 ID)
|
|
17957
|
+
*/
|
|
17958
|
+
async getPluginDetail(pluginName, marketplaceNameOrId) {
|
|
17959
|
+
try {
|
|
17960
|
+
const sourceId = await this.findMarketplaceId(marketplaceNameOrId);
|
|
17961
|
+
if (!sourceId) {
|
|
17962
|
+
this.logger?.warn(`[CloudAgentProvider] Marketplace not found: ${marketplaceNameOrId}`);
|
|
17963
|
+
return null;
|
|
17964
|
+
}
|
|
17965
|
+
const p = (await httpService.get(`/console/as/marketplace/plugins/${pluginName}/detail`, { params: { source_id: sourceId } })).data?.plugin;
|
|
17966
|
+
if (!p) return null;
|
|
17967
|
+
const capabilities = p.capabilities ? this.parseCapabilities(p.capabilities) : {};
|
|
17968
|
+
const tags = p.tags ? JSON.parse(p.tags) : [];
|
|
17969
|
+
return {
|
|
17970
|
+
name: p.name,
|
|
17971
|
+
marketplaceName: p.marketplace_name,
|
|
17972
|
+
description: p.description,
|
|
17973
|
+
version: p.version,
|
|
17974
|
+
iconUrl: p.icon_url,
|
|
17975
|
+
tags,
|
|
17976
|
+
installed: p.installed,
|
|
17977
|
+
status: p.enabled ? "enabled" : p.installed ? "disabled" : "not-installed",
|
|
17978
|
+
readme: p.readme,
|
|
17979
|
+
author: p.author,
|
|
17980
|
+
homepage: p.homepage,
|
|
17981
|
+
repositoryUrl: p.repository_url,
|
|
17982
|
+
license: p.license,
|
|
17983
|
+
...capabilities
|
|
17984
|
+
};
|
|
17985
|
+
} catch (error) {
|
|
17986
|
+
this.logger?.error("[CloudAgentProvider] getPluginDetail failed:", error);
|
|
17987
|
+
throw error;
|
|
17988
|
+
}
|
|
17989
|
+
}
|
|
17990
|
+
/**
|
|
17991
|
+
* 添加插件市场
|
|
17992
|
+
* POST /console/as/marketplace/sources
|
|
17993
|
+
*/
|
|
17994
|
+
async addPluginMarketplace(sourceUrl, name) {
|
|
17995
|
+
try {
|
|
17996
|
+
const body = {
|
|
17997
|
+
source_type: sourceUrl.startsWith("http") ? "url" : "github",
|
|
17998
|
+
url: sourceUrl,
|
|
17999
|
+
name: name || sourceUrl
|
|
18000
|
+
};
|
|
18001
|
+
const sourceData = (await httpService.post("/console/as/marketplace/sources", body)).data?.source;
|
|
18002
|
+
if (!sourceData) throw new Error("Invalid response from server");
|
|
18003
|
+
const marketplaceInfo = {
|
|
18004
|
+
id: sourceData.id,
|
|
18005
|
+
name: sourceData.name
|
|
18006
|
+
};
|
|
18007
|
+
this.marketplaceCache.set(sourceData.name, marketplaceInfo);
|
|
18008
|
+
this.marketplaceCache.set(sourceData.id, marketplaceInfo);
|
|
18009
|
+
return {
|
|
18010
|
+
success: true,
|
|
18011
|
+
marketplace: {
|
|
18012
|
+
id: sourceData.id,
|
|
18013
|
+
name: sourceData.name,
|
|
18014
|
+
type: this.mapSourceType(sourceData.source_type),
|
|
18015
|
+
source: { url: sourceData.url },
|
|
18016
|
+
isBuiltin: sourceData.is_default
|
|
18017
|
+
}
|
|
18018
|
+
};
|
|
18019
|
+
} catch (error) {
|
|
18020
|
+
return {
|
|
18021
|
+
success: false,
|
|
18022
|
+
error: this.extractErrorMessage(error)
|
|
18023
|
+
};
|
|
18024
|
+
}
|
|
18025
|
+
}
|
|
18026
|
+
/**
|
|
18027
|
+
* 删除插件市场
|
|
18028
|
+
* POST /console/as/marketplace/sources/:id/delete
|
|
18029
|
+
*/
|
|
18030
|
+
async removePluginMarketplace(marketplaceNameOrId) {
|
|
18031
|
+
try {
|
|
18032
|
+
const marketplaceId = await this.findMarketplaceId(marketplaceNameOrId);
|
|
18033
|
+
if (!marketplaceId) return {
|
|
18034
|
+
success: false,
|
|
18035
|
+
error: `Marketplace not found: ${marketplaceNameOrId}`
|
|
18036
|
+
};
|
|
18037
|
+
await httpService.post(`/console/as/marketplace/sources/${marketplaceId}/delete`, {});
|
|
18038
|
+
return { success: true };
|
|
18039
|
+
} catch (error) {
|
|
18040
|
+
return {
|
|
18041
|
+
success: false,
|
|
18042
|
+
error: this.extractErrorMessage(error)
|
|
18043
|
+
};
|
|
18044
|
+
}
|
|
18045
|
+
}
|
|
18046
|
+
/**
|
|
18047
|
+
* 刷新插件市场
|
|
18048
|
+
* POST /console/as/marketplace/sources/:id/check-updates
|
|
18049
|
+
*/
|
|
18050
|
+
async refreshPluginMarketplace(marketplaceNameOrId) {
|
|
18051
|
+
try {
|
|
18052
|
+
const marketplaceId = await this.findMarketplaceId(marketplaceNameOrId);
|
|
18053
|
+
if (!marketplaceId) return {
|
|
18054
|
+
success: false,
|
|
18055
|
+
error: `Marketplace not found: ${marketplaceNameOrId}`
|
|
18056
|
+
};
|
|
18057
|
+
return {
|
|
18058
|
+
success: true,
|
|
18059
|
+
plugins: (await httpService.post(`/console/as/marketplace/sources/${marketplaceId}/check-updates`, {})).data?.updated_plugins || []
|
|
18060
|
+
};
|
|
18061
|
+
} catch (error) {
|
|
18062
|
+
return {
|
|
18063
|
+
success: false,
|
|
18064
|
+
error: this.extractErrorMessage(error)
|
|
18065
|
+
};
|
|
18066
|
+
}
|
|
18067
|
+
}
|
|
18068
|
+
/**
|
|
18069
|
+
* 批量切换插件启用/禁用状态
|
|
18070
|
+
* POST /console/as/user/plugins/installed/:id/toggle
|
|
18071
|
+
*/
|
|
18072
|
+
async batchTogglePlugins(request) {
|
|
18073
|
+
try {
|
|
18074
|
+
const results = await Promise.allSettled(request.items.map(async (item) => {
|
|
18075
|
+
const installId = await this.findPluginInstallId(item.pluginName);
|
|
18076
|
+
if (!installId) throw new Error(`Plugin not found or not installed: ${item.pluginName}`);
|
|
18077
|
+
const enabled = item.operation === "enable";
|
|
18078
|
+
await httpService.post(`/console/as/user/plugins/installed/${installId}/toggle`, { enabled });
|
|
18079
|
+
return item;
|
|
18080
|
+
}));
|
|
18081
|
+
const succeededPlugins = [];
|
|
18082
|
+
const failedPlugins = [];
|
|
18083
|
+
results.forEach((r, i) => {
|
|
18084
|
+
const item = request.items[i];
|
|
18085
|
+
if (r.status === "fulfilled") succeededPlugins.push(item);
|
|
18086
|
+
else failedPlugins.push({
|
|
18087
|
+
...item,
|
|
18088
|
+
error: r.reason?.message || "Unknown error"
|
|
18089
|
+
});
|
|
18090
|
+
});
|
|
18091
|
+
return {
|
|
18092
|
+
success: failedPlugins.length === 0,
|
|
18093
|
+
succeededPlugins,
|
|
18094
|
+
failedPlugins
|
|
18095
|
+
};
|
|
18096
|
+
} catch (error) {
|
|
18097
|
+
return {
|
|
18098
|
+
success: false,
|
|
18099
|
+
succeededPlugins: [],
|
|
18100
|
+
failedPlugins: request.items.map((item) => ({
|
|
18101
|
+
...item,
|
|
18102
|
+
error: this.extractErrorMessage(error)
|
|
18103
|
+
}))
|
|
18104
|
+
};
|
|
18105
|
+
}
|
|
18106
|
+
}
|
|
18107
|
+
/**
|
|
18108
|
+
* 将后端插件数据映射为前端格式
|
|
18109
|
+
*/
|
|
18110
|
+
mapPluginData(p) {
|
|
18111
|
+
const capabilities = p.capabilities ? this.parseCapabilities(p.capabilities) : {};
|
|
18112
|
+
let tags = [];
|
|
18113
|
+
if (p.tags) {
|
|
18114
|
+
if (Array.isArray(p.tags)) tags = p.tags;
|
|
18115
|
+
else if (typeof p.tags === "string") try {
|
|
18116
|
+
const parsed = JSON.parse(p.tags);
|
|
18117
|
+
tags = Array.isArray(parsed) ? parsed : [parsed];
|
|
18118
|
+
} catch {
|
|
18119
|
+
tags = p.tags.split(",").map((t) => t.trim()).filter((t) => t);
|
|
18120
|
+
}
|
|
18121
|
+
}
|
|
18122
|
+
return {
|
|
18123
|
+
name: p.name,
|
|
18124
|
+
marketplaceName: p.marketplace_name,
|
|
18125
|
+
description: p.description,
|
|
18126
|
+
version: p.version,
|
|
18127
|
+
iconUrl: p.icon_url,
|
|
18128
|
+
tags,
|
|
18129
|
+
installed: p.installed,
|
|
18130
|
+
status: p.enabled ? "enabled" : p.installed ? "disabled" : "not-installed",
|
|
18131
|
+
installedScopes: p.installed ? [p.installed_scope] : [],
|
|
18132
|
+
...capabilities
|
|
18133
|
+
};
|
|
18134
|
+
}
|
|
18135
|
+
/**
|
|
18136
|
+
* 从缓存中查找插件的 install_id
|
|
18137
|
+
* 如果缓存未命中,则调用 API 获取并缓存
|
|
18138
|
+
*
|
|
18139
|
+
* @param pluginName - 插件名称
|
|
18140
|
+
* @returns install_id 或 null
|
|
18141
|
+
*/
|
|
18142
|
+
async findPluginInstallId(pluginName) {
|
|
18143
|
+
const cached = this.pluginCache.get(pluginName);
|
|
18144
|
+
if (cached) return cached.installId;
|
|
18145
|
+
await this.getInstalledPlugins();
|
|
18146
|
+
return this.pluginCache.get(pluginName)?.installId || null;
|
|
18147
|
+
}
|
|
18148
|
+
/**
|
|
18149
|
+
* 从缓存中查找 marketplace ID
|
|
18150
|
+
* 如果缓存未命中,则调用 API 获取并缓存
|
|
18151
|
+
*/
|
|
18152
|
+
async findMarketplaceId(nameOrId) {
|
|
18153
|
+
const cached = this.marketplaceCache.get(nameOrId);
|
|
18154
|
+
if (cached) return cached.id;
|
|
18155
|
+
await this.getPluginMarketplaces();
|
|
18156
|
+
return this.marketplaceCache.get(nameOrId)?.id || null;
|
|
18157
|
+
}
|
|
18158
|
+
/**
|
|
18159
|
+
* 提取 API 错误信息
|
|
18160
|
+
* 从 AxiosError 中提取详细的错误信息,包括 HTTP 状态码、错误码和错误消息
|
|
18161
|
+
*/
|
|
18162
|
+
extractErrorMessage(error) {
|
|
18163
|
+
if (error instanceof AxiosError) {
|
|
18164
|
+
const status = error.response?.status;
|
|
18165
|
+
const apiResponse = error.response?.data;
|
|
18166
|
+
const parts = [];
|
|
18167
|
+
if (status) parts.push(`HTTP ${status}`);
|
|
18168
|
+
if (apiResponse?.code) parts.push(`Code ${apiResponse.code}`);
|
|
18169
|
+
if (apiResponse?.msg) parts.push(apiResponse.msg);
|
|
18170
|
+
else if (error.message) parts.push(error.message);
|
|
18171
|
+
const errorMessage = parts.join(" - ");
|
|
18172
|
+
this.logger?.error("[CloudAgentProvider] API Error:", {
|
|
18173
|
+
status,
|
|
18174
|
+
code: apiResponse?.code,
|
|
18175
|
+
msg: apiResponse?.msg,
|
|
18176
|
+
requestId: apiResponse?.requestId,
|
|
18177
|
+
url: error.config?.url,
|
|
18178
|
+
method: error.config?.method
|
|
18179
|
+
});
|
|
18180
|
+
return errorMessage;
|
|
18181
|
+
}
|
|
18182
|
+
if (error instanceof Error) return error.message;
|
|
18183
|
+
return "Unknown error";
|
|
18184
|
+
}
|
|
18185
|
+
/**
|
|
18186
|
+
* 映射后端 source_type 到前端类型
|
|
18187
|
+
*/
|
|
18188
|
+
mapSourceType(sourceType) {
|
|
18189
|
+
switch (sourceType) {
|
|
18190
|
+
case "github": return "github";
|
|
18191
|
+
case "official": return "custom";
|
|
18192
|
+
default: return "custom";
|
|
18193
|
+
}
|
|
18194
|
+
}
|
|
18195
|
+
/**
|
|
18196
|
+
* 解析 capabilities JSON 字符串
|
|
18197
|
+
*/
|
|
18198
|
+
parseCapabilities(capabilitiesStr) {
|
|
18199
|
+
try {
|
|
18200
|
+
const cap = JSON.parse(capabilitiesStr);
|
|
18201
|
+
return {
|
|
18202
|
+
commands: cap.commands,
|
|
18203
|
+
skills: cap.skills,
|
|
18204
|
+
mcpServers: cap.mcp,
|
|
18205
|
+
agents: cap.agents,
|
|
18206
|
+
hooks: cap.hooks,
|
|
18207
|
+
rules: cap.rules
|
|
18208
|
+
};
|
|
18209
|
+
} catch {
|
|
18210
|
+
return {};
|
|
18211
|
+
}
|
|
18212
|
+
}
|
|
18213
|
+
/**
|
|
18214
|
+
* 上报 telemetry 事件(Cloud 模式)
|
|
18215
|
+
* 通过 HTTP POST 发送到 /v2/report
|
|
18216
|
+
* 注入用户信息和浏览器环境等公共字段
|
|
18217
|
+
*/
|
|
18218
|
+
async reportTelemetry(eventName, payload) {
|
|
18219
|
+
try {
|
|
18220
|
+
const account = accountService.getAccount();
|
|
18221
|
+
const commonFields = {};
|
|
18222
|
+
if (account) {
|
|
18223
|
+
commonFields.userId = account.uid;
|
|
18224
|
+
commonFields.userNickname = account.nickname;
|
|
18225
|
+
if (account.enterpriseId) commonFields.enterpriseId = account.enterpriseId;
|
|
18226
|
+
if (account.enterpriseUserName) commonFields.username = account.enterpriseUserName;
|
|
18227
|
+
}
|
|
18228
|
+
if (typeof navigator !== "undefined") {
|
|
18229
|
+
commonFields.userAgent = navigator.userAgent;
|
|
18230
|
+
commonFields.os = navigator.platform;
|
|
18231
|
+
}
|
|
18232
|
+
const events = [{
|
|
18233
|
+
eventCode: eventName,
|
|
18234
|
+
timestamp: Date.now(),
|
|
18235
|
+
reportDelay: 0,
|
|
18236
|
+
...commonFields,
|
|
18237
|
+
...payload
|
|
18238
|
+
}];
|
|
18239
|
+
await httpService.post("/v2/report", events);
|
|
18240
|
+
} catch (error) {
|
|
18241
|
+
this.logger?.warn("reportTelemetry() failed:", error);
|
|
18242
|
+
}
|
|
18243
|
+
}
|
|
18244
|
+
};
|
|
18245
|
+
|
|
18246
|
+
//#endregion
|
|
18247
|
+
//#region ../agent-provider/src/common/providers/local-agent-provider/local-connection.ts
|
|
18248
|
+
/**
|
|
18249
|
+
* Local Agent Connection
|
|
18250
|
+
* Wraps AcpJsonRpcClient to implement AgentConnection interface
|
|
18251
|
+
*
|
|
18252
|
+
* Uses IWidgetChannel for IPC communication with ExtensionHost
|
|
18253
|
+
* Migrated from ipc-agent-provider for unified local agent access
|
|
18254
|
+
*/
|
|
18255
|
+
|
|
18256
|
+
//#endregion
|
|
18257
|
+
//#region ../agent-provider/src/common/client/session.ts
|
|
18258
|
+
/**
|
|
18259
|
+
* ActiveSessionImpl - Implements the ActiveSession interface
|
|
18260
|
+
*
|
|
18261
|
+
* This class wraps an AgentConnection and provides the session-centric API.
|
|
18262
|
+
* It is created by SessionManager when creating or loading sessions.
|
|
18263
|
+
*
|
|
18264
|
+
* @example
|
|
18265
|
+
* ```typescript
|
|
18266
|
+
* // Created by client.sessions.new() or client.sessions.load()
|
|
18267
|
+
* const session = await client.sessions.new({ cwd: '/workspace' });
|
|
18268
|
+
*
|
|
18269
|
+
* // Access agent state
|
|
18270
|
+
* console.log(session.agentState.status);
|
|
18271
|
+
*
|
|
18272
|
+
* // Send prompt
|
|
18273
|
+
* const response = await session.prompts.send({ content: 'Hello!' });
|
|
18274
|
+
*
|
|
18275
|
+
* // Cleanup
|
|
18276
|
+
* session.disconnect();
|
|
18277
|
+
* ```
|
|
18278
|
+
*/
|
|
18279
|
+
var ActiveSessionImpl = class {
|
|
18280
|
+
/**
|
|
18281
|
+
* Create an ActiveSessionImpl instance
|
|
18282
|
+
*
|
|
18283
|
+
* @param sessionId - Session ID
|
|
18284
|
+
* @param agentId - Agent ID
|
|
18285
|
+
* @param connection - Already connected AgentConnection
|
|
18286
|
+
* @param options - Additional options
|
|
18287
|
+
*/
|
|
18288
|
+
constructor(sessionId, agentId, connection, options = {}) {
|
|
18289
|
+
this._availableCommands = [];
|
|
18290
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
18291
|
+
this.onceListeners = /* @__PURE__ */ new Map();
|
|
18292
|
+
this.connectionListeners = [];
|
|
18293
|
+
this._id = sessionId;
|
|
18294
|
+
this._agentId = agentId;
|
|
18295
|
+
this.connection = connection;
|
|
17408
18296
|
this.logger = options.logger;
|
|
17409
18297
|
this._getFilesystem = options.getFilesystem;
|
|
17410
18298
|
this._connectionInfo = options.connectionInfo;
|
|
@@ -17427,6 +18315,18 @@ var ActiveSessionImpl = class {
|
|
|
17427
18315
|
return this._agentId;
|
|
17428
18316
|
}
|
|
17429
18317
|
/**
|
|
18318
|
+
* Actual workspace path (set from newSession response _meta)
|
|
18319
|
+
*/
|
|
18320
|
+
get cwd() {
|
|
18321
|
+
return this._cwd;
|
|
18322
|
+
}
|
|
18323
|
+
/**
|
|
18324
|
+
* Set actual workspace path (called by SessionManager after createSession)
|
|
18325
|
+
*/
|
|
18326
|
+
setCwd(cwd) {
|
|
18327
|
+
this._cwd = cwd;
|
|
18328
|
+
}
|
|
18329
|
+
/**
|
|
17430
18330
|
* Agent state (live connection state)
|
|
17431
18331
|
* Returns LocalAgentState or CloudAgentState based on transport type
|
|
17432
18332
|
*/
|
|
@@ -17643,8 +18543,8 @@ var ActiveSessionImpl = class {
|
|
|
17643
18543
|
* await session.setMode('architect');
|
|
17644
18544
|
* ```
|
|
17645
18545
|
*/
|
|
17646
|
-
async setMode(modeId) {
|
|
17647
|
-
if (this._availableModes) {
|
|
18546
|
+
async setMode(modeId, skipAvailableChecker) {
|
|
18547
|
+
if (this._availableModes && !skipAvailableChecker) {
|
|
17648
18548
|
if (!this._availableModes.some((m) => m.id === modeId)) {
|
|
17649
18549
|
const availableIds = this._availableModes.map((m) => m.id).join(", ");
|
|
17650
18550
|
throw new Error(`Invalid modeId: "${modeId}". Available modes: ${availableIds}`);
|
|
@@ -17667,6 +18567,7 @@ var ActiveSessionImpl = class {
|
|
|
17667
18567
|
* ```
|
|
17668
18568
|
*/
|
|
17669
18569
|
async setSessionModel(modelId) {
|
|
18570
|
+
this._currentModelId = modelId;
|
|
17670
18571
|
await this.getConnectionOrThrow().setSessionModel(this._id, modelId);
|
|
17671
18572
|
}
|
|
17672
18573
|
/**
|
|
@@ -17744,11 +18645,23 @@ var ActiveSessionImpl = class {
|
|
|
17744
18645
|
* Disconnect from the session/agent
|
|
17745
18646
|
*/
|
|
17746
18647
|
disconnect() {
|
|
18648
|
+
this.removeConnectionListeners();
|
|
17747
18649
|
this.connection.disconnect();
|
|
17748
18650
|
this.removeAllListeners();
|
|
17749
18651
|
this.logger?.info(`Session ${this._id}: Disconnected`);
|
|
17750
18652
|
}
|
|
17751
18653
|
/**
|
|
18654
|
+
* Detach the session from connection events without disconnecting the connection.
|
|
18655
|
+
* This should be called when the session is being replaced but the connection is shared.
|
|
18656
|
+
* Unlike disconnect(), this only removes event listeners without closing the connection.
|
|
18657
|
+
*/
|
|
18658
|
+
detach() {
|
|
18659
|
+
this.logger?.info(`Session ${this._id}: Detaching from connection events`);
|
|
18660
|
+
this.removeConnectionListeners();
|
|
18661
|
+
this.removeAllListeners();
|
|
18662
|
+
this.logger?.info(`Session ${this._id}: Detached successfully`);
|
|
18663
|
+
}
|
|
18664
|
+
/**
|
|
17752
18665
|
* Symbol.dispose for 'using' keyword support
|
|
17753
18666
|
* Automatically disconnects and cleans up when session goes out of scope
|
|
17754
18667
|
*
|
|
@@ -17767,60 +18680,85 @@ var ActiveSessionImpl = class {
|
|
|
17767
18680
|
if (!this.connection.isInitialized) throw new Error(`Session ${this._id}: Connection not initialized.`);
|
|
17768
18681
|
return this.connection;
|
|
17769
18682
|
}
|
|
18683
|
+
/**
|
|
18684
|
+
* 在 connection 上注册 listener 并保存引用,便于 disconnect 时移除
|
|
18685
|
+
*/
|
|
18686
|
+
addConnectionListener(connection, event, listener) {
|
|
18687
|
+
connection.on(event, listener);
|
|
18688
|
+
this.connectionListeners.push({
|
|
18689
|
+
event,
|
|
18690
|
+
listener
|
|
18691
|
+
});
|
|
18692
|
+
}
|
|
18693
|
+
/**
|
|
18694
|
+
* 从 connection 上移除所有本 session 注册的 listener
|
|
18695
|
+
*/
|
|
18696
|
+
removeConnectionListeners() {
|
|
18697
|
+
for (const { event, listener } of this.connectionListeners) this.connection.off(event, listener);
|
|
18698
|
+
this.connectionListeners = [];
|
|
18699
|
+
}
|
|
17770
18700
|
setupConnectionEvents(connection) {
|
|
17771
|
-
|
|
18701
|
+
this.addConnectionListener(connection, "connected", () => {
|
|
17772
18702
|
this.emit("connected", void 0);
|
|
17773
18703
|
});
|
|
17774
|
-
|
|
18704
|
+
this.addConnectionListener(connection, "disconnected", () => {
|
|
17775
18705
|
this.emit("disconnected", void 0);
|
|
17776
18706
|
});
|
|
17777
|
-
|
|
18707
|
+
this.addConnectionListener(connection, "error", (error) => {
|
|
17778
18708
|
this.emit("error", error);
|
|
17779
18709
|
});
|
|
17780
|
-
|
|
18710
|
+
this.addConnectionListener(connection, "sessionUpdate", (update) => {
|
|
18711
|
+
const notificationSessionId = update?.sessionId;
|
|
18712
|
+
if (notificationSessionId && notificationSessionId !== this._id) {
|
|
18713
|
+
console.log(`[RT-DEBUG][AgentMgr:Session] sessionUpdate SKIPPED: notifSessionId mismatch, notif=${notificationSessionId?.substring(0, 8)}, my=${this._id?.substring(0, 8)}`);
|
|
18714
|
+
return;
|
|
18715
|
+
}
|
|
17781
18716
|
this.emit("sessionUpdate", update);
|
|
17782
18717
|
});
|
|
17783
|
-
|
|
17784
|
-
|
|
17785
|
-
artifactUri: artifact.uri,
|
|
17786
|
-
artifactType: artifact.type
|
|
17787
|
-
});
|
|
18718
|
+
this.addConnectionListener(connection, "artifactCreated", (artifact) => {
|
|
18719
|
+
if (!this.shouldForwardArtifact(artifact)) return;
|
|
17788
18720
|
this.emit("artifactCreated", artifact);
|
|
17789
18721
|
});
|
|
17790
|
-
|
|
17791
|
-
|
|
17792
|
-
artifactUri: artifact.uri,
|
|
17793
|
-
artifactType: artifact.type
|
|
17794
|
-
});
|
|
18722
|
+
this.addConnectionListener(connection, "artifactUpdated", (artifact) => {
|
|
18723
|
+
if (!this.shouldForwardArtifact(artifact)) return;
|
|
17795
18724
|
this.emit("artifactUpdated", artifact);
|
|
17796
18725
|
});
|
|
17797
|
-
|
|
17798
|
-
|
|
18726
|
+
this.addConnectionListener(connection, "artifactDeleted", (artifact) => {
|
|
18727
|
+
if (!this.shouldForwardArtifact(artifact)) return;
|
|
17799
18728
|
this.emit("artifactDeleted", artifact);
|
|
17800
18729
|
});
|
|
17801
|
-
|
|
18730
|
+
this.addConnectionListener(connection, "permissionRequest", (request) => {
|
|
17802
18731
|
this.emit("permissionRequest", request);
|
|
17803
18732
|
});
|
|
17804
|
-
|
|
18733
|
+
this.addConnectionListener(connection, "questionRequest", (request) => {
|
|
17805
18734
|
this.emit("questionRequest", request);
|
|
17806
18735
|
});
|
|
17807
|
-
|
|
18736
|
+
this.addConnectionListener(connection, "questionCancelled", () => {
|
|
17808
18737
|
this.prompts.cancel();
|
|
17809
18738
|
});
|
|
17810
|
-
|
|
18739
|
+
this.addConnectionListener(connection, "usageUpdate", (usage) => {
|
|
17811
18740
|
this.emit("usageUpdate", usage);
|
|
17812
18741
|
});
|
|
17813
|
-
|
|
18742
|
+
this.addConnectionListener(connection, "checkpointCreated", (checkpoint) => {
|
|
18743
|
+
const originSessionId = checkpoint.__sessionId;
|
|
18744
|
+
if (originSessionId && originSessionId !== this._id) return;
|
|
17814
18745
|
this.emit("checkpointCreated", checkpoint);
|
|
17815
18746
|
});
|
|
17816
|
-
|
|
18747
|
+
this.addConnectionListener(connection, "checkpointUpdated", (checkpoint) => {
|
|
18748
|
+
const originSessionId = checkpoint.__sessionId;
|
|
18749
|
+
if (originSessionId && originSessionId !== this._id) return;
|
|
17817
18750
|
this.emit("checkpointUpdated", checkpoint);
|
|
17818
18751
|
});
|
|
17819
|
-
|
|
17820
|
-
|
|
17821
|
-
|
|
17822
|
-
|
|
17823
|
-
|
|
18752
|
+
this.addConnectionListener(connection, "command", (command) => {
|
|
18753
|
+
const originSessionId = command.__sessionId;
|
|
18754
|
+
if (originSessionId && originSessionId !== this._id) {
|
|
18755
|
+
console.log("[Session] Command not forwarded:", {
|
|
18756
|
+
command,
|
|
18757
|
+
originSessionId,
|
|
18758
|
+
sessionId: this._id
|
|
18759
|
+
});
|
|
18760
|
+
return;
|
|
18761
|
+
}
|
|
17824
18762
|
this.emit("command", command);
|
|
17825
18763
|
});
|
|
17826
18764
|
}
|
|
@@ -17830,19 +18768,20 @@ var ActiveSessionImpl = class {
|
|
|
17830
18768
|
_meta: response._meta ?? void 0
|
|
17831
18769
|
};
|
|
17832
18770
|
}
|
|
18771
|
+
/**
|
|
18772
|
+
* 判断 artifact 是否应该转发给当前 session
|
|
18773
|
+
* 所有类型的 artifact 都按 __sessionId 严格隔离
|
|
18774
|
+
*/
|
|
18775
|
+
shouldForwardArtifact(artifact) {
|
|
18776
|
+
const originSessionId = artifact.__sessionId;
|
|
18777
|
+
if (!originSessionId || originSessionId !== this._id) return false;
|
|
18778
|
+
return true;
|
|
18779
|
+
}
|
|
17833
18780
|
};
|
|
17834
18781
|
|
|
17835
18782
|
//#endregion
|
|
17836
18783
|
//#region ../agent-provider/src/common/client/session-manager.ts
|
|
17837
18784
|
/**
|
|
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
18785
|
* SessionManager - Session lifecycle management
|
|
17847
18786
|
*
|
|
17848
18787
|
* This class manages the relationship between sessions and agents.
|
|
@@ -17892,7 +18831,8 @@ var SessionManager = class {
|
|
|
17892
18831
|
createdAt: agent.createdAt,
|
|
17893
18832
|
lastActivityAt: agent.updatedAt,
|
|
17894
18833
|
cwd: agent.type === "local" ? agent.cwd : void 0,
|
|
17895
|
-
isPlayground: agent.isPlayground
|
|
18834
|
+
isPlayground: agent.isPlayground,
|
|
18835
|
+
isUserDefinedTitle: agent.isUserDefinedTitle
|
|
17896
18836
|
}));
|
|
17897
18837
|
console.log("[SessionManager] Returning sessions:", {
|
|
17898
18838
|
count: sessions.length,
|
|
@@ -17919,13 +18859,26 @@ var SessionManager = class {
|
|
|
17919
18859
|
if (this.provider.create) {
|
|
17920
18860
|
agentId = await this.provider.create(params);
|
|
17921
18861
|
this.logger?.debug(`Created new agent: ${agentId}`);
|
|
18862
|
+
if (params.options?.onSessionPrepared) {
|
|
18863
|
+
const initialPrompt = params.options?.prompt;
|
|
18864
|
+
const initialTitle = initialPrompt?.slice(0, 50) || "";
|
|
18865
|
+
params.options.onSessionPrepared({
|
|
18866
|
+
id: agentId,
|
|
18867
|
+
agentId,
|
|
18868
|
+
name: initialTitle + (initialPrompt && initialPrompt.length > 50 ? "..." : ""),
|
|
18869
|
+
status: "connecting",
|
|
18870
|
+
cwd: params.cwd || "",
|
|
18871
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
18872
|
+
});
|
|
18873
|
+
this.logger?.debug(`Called onSessionPrepared for: ${agentId}`);
|
|
18874
|
+
}
|
|
17922
18875
|
} else throw new Error("Provider does not support creating agents. Use sessions.load() with an existing sessionId.");
|
|
17923
18876
|
const connection = await this.provider.connect(agentId);
|
|
17924
18877
|
this.logger?.debug(`Connected to agent: ${agentId}`);
|
|
17925
18878
|
const response = await connection.createSession({
|
|
17926
|
-
_meta: params._meta,
|
|
18879
|
+
_meta: params.options?._meta,
|
|
17927
18880
|
cwd: params.cwd,
|
|
17928
|
-
mcpServers: params.mcpServers
|
|
18881
|
+
mcpServers: params.options?.mcpServers
|
|
17929
18882
|
});
|
|
17930
18883
|
if (this.provider.registerSession) {
|
|
17931
18884
|
this.provider.registerSession(response.sessionId, agentId);
|
|
@@ -17938,14 +18891,10 @@ var SessionManager = class {
|
|
|
17938
18891
|
connectionInfo
|
|
17939
18892
|
});
|
|
17940
18893
|
session.setModes(response.modes?.availableModes, response.modes?.currentModeId);
|
|
17941
|
-
|
|
17942
|
-
|
|
17943
|
-
|
|
17944
|
-
|
|
17945
|
-
description: m.description ?? void 0
|
|
17946
|
-
}));
|
|
17947
|
-
session.setModels(localModels, response.models?.currentModelId);
|
|
17948
|
-
}
|
|
18894
|
+
const availableModels = this.extractAvailableModels(response);
|
|
18895
|
+
if (availableModels) session.setModels(availableModels, response.models?.currentModelId);
|
|
18896
|
+
const responseCwd = response._meta?.["codebuddy.ai"]?.cwd;
|
|
18897
|
+
if (responseCwd) session.setCwd(responseCwd);
|
|
17949
18898
|
this.logger?.info(`Session created: ${response.sessionId}`);
|
|
17950
18899
|
return session;
|
|
17951
18900
|
}
|
|
@@ -17981,17 +18930,31 @@ var SessionManager = class {
|
|
|
17981
18930
|
mcpServers: params.mcpServers
|
|
17982
18931
|
});
|
|
17983
18932
|
session.setModes(response.modes?.availableModes, response.modes?.currentModeId);
|
|
17984
|
-
|
|
17985
|
-
|
|
17986
|
-
id: m.modelId,
|
|
17987
|
-
name: m.name,
|
|
17988
|
-
description: m.description ?? void 0
|
|
17989
|
-
}));
|
|
17990
|
-
session.setModels(localModels, response.models?.currentModelId);
|
|
17991
|
-
}
|
|
18933
|
+
const availableModels = this.extractAvailableModels(response);
|
|
18934
|
+
if (availableModels) session.setModels(availableModels, response.models?.currentModelId);
|
|
17992
18935
|
this.logger?.info(`Session loaded: ${params.sessionId}`);
|
|
17993
18936
|
return session;
|
|
17994
18937
|
}
|
|
18938
|
+
/**
|
|
18939
|
+
* 从 ACP response 中提取可用模型列表
|
|
18940
|
+
*
|
|
18941
|
+
* 优先级:
|
|
18942
|
+
* 1. response.models._meta?.['codebuddy.ai']?.availableModels - 包含完整的模型信息(字段名为 'id')
|
|
18943
|
+
* 2. response.models?.availableModels - 只包含基本信息(字段名为 'modelId')
|
|
18944
|
+
* 3. undefined - 都没有时返回 undefined
|
|
18945
|
+
*
|
|
18946
|
+
* @param response - ACP 响应对象
|
|
18947
|
+
* @returns ModelInfo[] | undefined
|
|
18948
|
+
*/
|
|
18949
|
+
extractAvailableModels(response) {
|
|
18950
|
+
const metaModels = (response.models?._meta?.["codebuddy.ai"])?.availableModels;
|
|
18951
|
+
if (metaModels && Array.isArray(metaModels) && metaModels.length > 0) return metaModels;
|
|
18952
|
+
const availableModels = response.models?.availableModels;
|
|
18953
|
+
if (availableModels && Array.isArray(availableModels) && availableModels.length > 0) return availableModels.map((model) => ({
|
|
18954
|
+
...model,
|
|
18955
|
+
...model._meta?.["codebuddy.ai"] || {}
|
|
18956
|
+
}));
|
|
18957
|
+
}
|
|
17995
18958
|
};
|
|
17996
18959
|
|
|
17997
18960
|
//#endregion
|
|
@@ -18098,6 +19061,26 @@ var AgentClient = class {
|
|
|
18098
19061
|
throw error;
|
|
18099
19062
|
}
|
|
18100
19063
|
},
|
|
19064
|
+
updateStatus: async (sessionId, status) => {
|
|
19065
|
+
this.logger?.debug("AgentClient.sessions.updateStatus called", {
|
|
19066
|
+
sessionId,
|
|
19067
|
+
status
|
|
19068
|
+
});
|
|
19069
|
+
try {
|
|
19070
|
+
if (this.provider.updateStatus) {
|
|
19071
|
+
const result = await this.provider.updateStatus(sessionId, status);
|
|
19072
|
+
this.logger?.info("Session status updated successfully", {
|
|
19073
|
+
sessionId,
|
|
19074
|
+
status
|
|
19075
|
+
});
|
|
19076
|
+
return result;
|
|
19077
|
+
}
|
|
19078
|
+
throw new Error("Provider does not support updateStatus method");
|
|
19079
|
+
} catch (error) {
|
|
19080
|
+
this.logger?.error("Failed to update session status", error);
|
|
19081
|
+
throw error;
|
|
19082
|
+
}
|
|
19083
|
+
},
|
|
18101
19084
|
move: async (sessionId) => {
|
|
18102
19085
|
this.logger?.debug("AgentClient.sessions.move called", { sessionId });
|
|
18103
19086
|
try {
|
|
@@ -18145,6 +19128,100 @@ var AgentClient = class {
|
|
|
18145
19128
|
return [];
|
|
18146
19129
|
}
|
|
18147
19130
|
},
|
|
19131
|
+
getAutomationSnapshot: async () => {
|
|
19132
|
+
try {
|
|
19133
|
+
if (this.provider?.getAutomationSnapshot) return await this.provider.getAutomationSnapshot();
|
|
19134
|
+
this.logger?.warn("Provider does not support getAutomationSnapshot");
|
|
19135
|
+
} catch (error) {
|
|
19136
|
+
this.logger?.error("Failed to get automation snapshot", error);
|
|
19137
|
+
}
|
|
19138
|
+
return {
|
|
19139
|
+
automations: [],
|
|
19140
|
+
inbox: [],
|
|
19141
|
+
runtimeState: {},
|
|
19142
|
+
updatedAt: Date.now()
|
|
19143
|
+
};
|
|
19144
|
+
},
|
|
19145
|
+
updateAutomation: async (payload) => {
|
|
19146
|
+
try {
|
|
19147
|
+
if (this.provider?.updateAutomation) return await this.provider.updateAutomation(payload);
|
|
19148
|
+
this.logger?.warn("Provider does not support updateAutomation");
|
|
19149
|
+
} catch (error) {
|
|
19150
|
+
this.logger?.error("Failed to update automation", error);
|
|
19151
|
+
return {
|
|
19152
|
+
success: false,
|
|
19153
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
19154
|
+
};
|
|
19155
|
+
}
|
|
19156
|
+
return {
|
|
19157
|
+
success: false,
|
|
19158
|
+
message: "Provider does not support updateAutomation"
|
|
19159
|
+
};
|
|
19160
|
+
},
|
|
19161
|
+
deleteAutomation: async (id) => {
|
|
19162
|
+
try {
|
|
19163
|
+
if (this.provider?.deleteAutomation) return await this.provider.deleteAutomation(id);
|
|
19164
|
+
this.logger?.warn("Provider does not support deleteAutomation");
|
|
19165
|
+
} catch (error) {
|
|
19166
|
+
this.logger?.error("Failed to delete automation", error);
|
|
19167
|
+
return {
|
|
19168
|
+
success: false,
|
|
19169
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
19170
|
+
};
|
|
19171
|
+
}
|
|
19172
|
+
return {
|
|
19173
|
+
success: false,
|
|
19174
|
+
message: "Provider does not support deleteAutomation"
|
|
19175
|
+
};
|
|
19176
|
+
},
|
|
19177
|
+
archiveAutomationInboxItem: async (itemId) => {
|
|
19178
|
+
try {
|
|
19179
|
+
if (this.provider?.archiveAutomationInboxItem) return await this.provider.archiveAutomationInboxItem(itemId);
|
|
19180
|
+
this.logger?.warn("Provider does not support archiveAutomationInboxItem");
|
|
19181
|
+
} catch (error) {
|
|
19182
|
+
this.logger?.error("Failed to archive automation inbox item", error);
|
|
19183
|
+
return {
|
|
19184
|
+
success: false,
|
|
19185
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
19186
|
+
};
|
|
19187
|
+
}
|
|
19188
|
+
return {
|
|
19189
|
+
success: false,
|
|
19190
|
+
message: "Provider does not support archiveAutomationInboxItem"
|
|
19191
|
+
};
|
|
19192
|
+
},
|
|
19193
|
+
deleteAutomationInboxItem: async (itemId) => {
|
|
19194
|
+
try {
|
|
19195
|
+
if (this.provider?.deleteAutomationInboxItem) return await this.provider.deleteAutomationInboxItem(itemId);
|
|
19196
|
+
this.logger?.warn("Provider does not support deleteAutomationInboxItem");
|
|
19197
|
+
} catch (error) {
|
|
19198
|
+
this.logger?.error("Failed to delete automation inbox item", error);
|
|
19199
|
+
return {
|
|
19200
|
+
success: false,
|
|
19201
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
19202
|
+
};
|
|
19203
|
+
}
|
|
19204
|
+
return {
|
|
19205
|
+
success: false,
|
|
19206
|
+
message: "Provider does not support deleteAutomationInboxItem"
|
|
19207
|
+
};
|
|
19208
|
+
},
|
|
19209
|
+
testAutomation: async (id) => {
|
|
19210
|
+
try {
|
|
19211
|
+
if (this.provider?.testAutomation) return await this.provider.testAutomation(id);
|
|
19212
|
+
this.logger?.warn("Provider does not support testAutomation");
|
|
19213
|
+
} catch (error) {
|
|
19214
|
+
this.logger?.error("Failed to test automation", error);
|
|
19215
|
+
return {
|
|
19216
|
+
success: false,
|
|
19217
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
19218
|
+
};
|
|
19219
|
+
}
|
|
19220
|
+
return {
|
|
19221
|
+
success: false,
|
|
19222
|
+
message: "Provider does not support testAutomation"
|
|
19223
|
+
};
|
|
19224
|
+
},
|
|
18148
19225
|
on: (event, handler) => {
|
|
18149
19226
|
if (this.provider.on) this.provider.on(event, handler);
|
|
18150
19227
|
else this.logger?.warn(`Provider does not support event registration: ${String(event)}`);
|
|
@@ -18264,6 +19341,189 @@ var AgentClient = class {
|
|
|
18264
19341
|
};
|
|
18265
19342
|
}
|
|
18266
19343
|
},
|
|
19344
|
+
getSubagentList: async (params) => {
|
|
19345
|
+
try {
|
|
19346
|
+
if (this.provider && this.provider.getSubagentList) {
|
|
19347
|
+
const result = await this.provider.getSubagentList(params);
|
|
19348
|
+
this.logger?.info("Subagent list retrieved", {
|
|
19349
|
+
resultCount: result.results.length,
|
|
19350
|
+
hasError: !!result.error
|
|
19351
|
+
});
|
|
19352
|
+
return result;
|
|
19353
|
+
}
|
|
19354
|
+
return {
|
|
19355
|
+
results: [],
|
|
19356
|
+
error: "Provider does not support getSubagentList"
|
|
19357
|
+
};
|
|
19358
|
+
} catch (error) {
|
|
19359
|
+
this.logger?.error("Failed to get subagent list", error);
|
|
19360
|
+
return {
|
|
19361
|
+
results: [],
|
|
19362
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19363
|
+
};
|
|
19364
|
+
}
|
|
19365
|
+
},
|
|
19366
|
+
getSkillList: async (params) => {
|
|
19367
|
+
try {
|
|
19368
|
+
if (this.provider && this.provider.getSkillList) {
|
|
19369
|
+
const result = await this.provider.getSkillList(params);
|
|
19370
|
+
this.logger?.info("Skill list retrieved", {
|
|
19371
|
+
resultCount: result.results.length,
|
|
19372
|
+
hasError: !!result.error
|
|
19373
|
+
});
|
|
19374
|
+
return result;
|
|
19375
|
+
}
|
|
19376
|
+
return {
|
|
19377
|
+
results: [],
|
|
19378
|
+
error: "Provider does not support getSkillList"
|
|
19379
|
+
};
|
|
19380
|
+
} catch (error) {
|
|
19381
|
+
this.logger?.error("Failed to get skill list", error);
|
|
19382
|
+
return {
|
|
19383
|
+
results: [],
|
|
19384
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19385
|
+
};
|
|
19386
|
+
}
|
|
19387
|
+
},
|
|
19388
|
+
importSkill: async (params) => {
|
|
19389
|
+
try {
|
|
19390
|
+
if (this.provider && this.provider.importSkill) {
|
|
19391
|
+
const result = await this.provider.importSkill(params);
|
|
19392
|
+
this.logger?.info("Import skill completed", {
|
|
19393
|
+
success: result.success,
|
|
19394
|
+
hasError: !!result.error
|
|
19395
|
+
});
|
|
19396
|
+
return result;
|
|
19397
|
+
}
|
|
19398
|
+
return {
|
|
19399
|
+
success: false,
|
|
19400
|
+
error: "Provider does not support importSkill"
|
|
19401
|
+
};
|
|
19402
|
+
} catch (error) {
|
|
19403
|
+
this.logger?.error("Failed to import skill", error);
|
|
19404
|
+
return {
|
|
19405
|
+
success: false,
|
|
19406
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19407
|
+
};
|
|
19408
|
+
}
|
|
19409
|
+
},
|
|
19410
|
+
toggleSkill: async (params) => {
|
|
19411
|
+
try {
|
|
19412
|
+
if (this.provider && this.provider.toggleSkill) {
|
|
19413
|
+
const result = await this.provider.toggleSkill(params);
|
|
19414
|
+
this.logger?.info("Toggle skill completed", {
|
|
19415
|
+
success: result.success,
|
|
19416
|
+
hasError: !!result.error
|
|
19417
|
+
});
|
|
19418
|
+
return result;
|
|
19419
|
+
}
|
|
19420
|
+
return {
|
|
19421
|
+
success: false,
|
|
19422
|
+
error: "Provider does not support toggleSkill"
|
|
19423
|
+
};
|
|
19424
|
+
} catch (error) {
|
|
19425
|
+
this.logger?.error("Failed to toggle skill", error);
|
|
19426
|
+
return {
|
|
19427
|
+
success: false,
|
|
19428
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19429
|
+
};
|
|
19430
|
+
}
|
|
19431
|
+
},
|
|
19432
|
+
deleteSkill: async (params) => {
|
|
19433
|
+
try {
|
|
19434
|
+
if (this.provider && this.provider.deleteSkill) {
|
|
19435
|
+
const result = await this.provider.deleteSkill(params);
|
|
19436
|
+
this.logger?.info("Delete skill completed", {
|
|
19437
|
+
success: result.success,
|
|
19438
|
+
hasError: !!result.error
|
|
19439
|
+
});
|
|
19440
|
+
return result;
|
|
19441
|
+
}
|
|
19442
|
+
return {
|
|
19443
|
+
success: false,
|
|
19444
|
+
error: "Provider does not support deleteSkill"
|
|
19445
|
+
};
|
|
19446
|
+
} catch (error) {
|
|
19447
|
+
this.logger?.error("Failed to delete skill", error);
|
|
19448
|
+
return {
|
|
19449
|
+
success: false,
|
|
19450
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19451
|
+
};
|
|
19452
|
+
}
|
|
19453
|
+
},
|
|
19454
|
+
getSkillContent: async (params) => {
|
|
19455
|
+
try {
|
|
19456
|
+
if (this.provider && this.provider.getSkillContent) {
|
|
19457
|
+
const result = await this.provider.getSkillContent(params);
|
|
19458
|
+
this.logger?.info("Get skill content completed", { hasError: !!result.error });
|
|
19459
|
+
return result;
|
|
19460
|
+
}
|
|
19461
|
+
return {
|
|
19462
|
+
content: "",
|
|
19463
|
+
error: "Provider does not support getSkillContent"
|
|
19464
|
+
};
|
|
19465
|
+
} catch (error) {
|
|
19466
|
+
this.logger?.error("Failed to get skill content", error);
|
|
19467
|
+
return {
|
|
19468
|
+
content: "",
|
|
19469
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19470
|
+
};
|
|
19471
|
+
}
|
|
19472
|
+
},
|
|
19473
|
+
getMarketplaceSkills: async () => {
|
|
19474
|
+
try {
|
|
19475
|
+
if (this.provider && this.provider.getMarketplaceSkills) {
|
|
19476
|
+
const result = await this.provider.getMarketplaceSkills();
|
|
19477
|
+
this.logger?.info("Marketplace skills retrieved", {
|
|
19478
|
+
resultCount: result.results.length,
|
|
19479
|
+
hasError: !!result.error
|
|
19480
|
+
});
|
|
19481
|
+
return result;
|
|
19482
|
+
}
|
|
19483
|
+
return {
|
|
19484
|
+
results: [],
|
|
19485
|
+
error: "Provider does not support getMarketplaceSkills"
|
|
19486
|
+
};
|
|
19487
|
+
} catch (error) {
|
|
19488
|
+
this.logger?.error("Failed to get marketplace skills", error);
|
|
19489
|
+
return {
|
|
19490
|
+
results: [],
|
|
19491
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19492
|
+
};
|
|
19493
|
+
}
|
|
19494
|
+
},
|
|
19495
|
+
getMarketplaceSkillContent: async (params) => {
|
|
19496
|
+
try {
|
|
19497
|
+
if (this.provider && this.provider.getMarketplaceSkillContent) return await this.provider.getMarketplaceSkillContent(params);
|
|
19498
|
+
return {
|
|
19499
|
+
content: "",
|
|
19500
|
+
error: "Provider does not support getMarketplaceSkillContent"
|
|
19501
|
+
};
|
|
19502
|
+
} catch (error) {
|
|
19503
|
+
this.logger?.error("Failed to get marketplace skill content", error);
|
|
19504
|
+
return {
|
|
19505
|
+
content: "",
|
|
19506
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19507
|
+
};
|
|
19508
|
+
}
|
|
19509
|
+
},
|
|
19510
|
+
installMarketplaceSkill: async (params) => {
|
|
19511
|
+
try {
|
|
19512
|
+
if (this.provider && this.provider.installMarketplaceSkill) return await this.provider.installMarketplaceSkill(params);
|
|
19513
|
+
return {
|
|
19514
|
+
success: false,
|
|
19515
|
+
skillName: params.skillName,
|
|
19516
|
+
errorMessage: "Provider does not support installMarketplaceSkill"
|
|
19517
|
+
};
|
|
19518
|
+
} catch (error) {
|
|
19519
|
+
this.logger?.error("Failed to install marketplace skill", error);
|
|
19520
|
+
return {
|
|
19521
|
+
success: false,
|
|
19522
|
+
skillName: params.skillName,
|
|
19523
|
+
errorMessage: error instanceof Error ? error.message : "Unknown error"
|
|
19524
|
+
};
|
|
19525
|
+
}
|
|
19526
|
+
},
|
|
18267
19527
|
batchTogglePlugins: async (request) => {
|
|
18268
19528
|
try {
|
|
18269
19529
|
if (this.provider && this.provider.batchTogglePlugins) {
|
|
@@ -18304,41 +19564,233 @@ var AgentClient = class {
|
|
|
18304
19564
|
this.logger?.warn("Provider does not support getInstalledPlugins");
|
|
18305
19565
|
return [];
|
|
18306
19566
|
} catch (error) {
|
|
18307
|
-
this.logger?.error("Failed to get installed plugins", error);
|
|
18308
|
-
return [];
|
|
19567
|
+
this.logger?.error("Failed to get installed plugins", error);
|
|
19568
|
+
return [];
|
|
19569
|
+
}
|
|
19570
|
+
},
|
|
19571
|
+
installPlugins: async (pluginNames, marketplaceName, installScope, marketplaceSource, workspacePath) => {
|
|
19572
|
+
try {
|
|
19573
|
+
if (this.provider && "installPlugins" in this.provider && typeof this.provider.installPlugins === "function") {
|
|
19574
|
+
const result = await this.provider.installPlugins(pluginNames, marketplaceName, installScope, marketplaceSource, workspacePath);
|
|
19575
|
+
this.logger?.info("Install plugins", {
|
|
19576
|
+
pluginNames,
|
|
19577
|
+
marketplaceName,
|
|
19578
|
+
success: result.success
|
|
19579
|
+
});
|
|
19580
|
+
return result;
|
|
19581
|
+
}
|
|
19582
|
+
this.logger?.warn("Provider does not support installPlugins");
|
|
19583
|
+
return {
|
|
19584
|
+
success: false,
|
|
19585
|
+
error: "Provider does not support installPlugins"
|
|
19586
|
+
};
|
|
19587
|
+
} catch (error) {
|
|
19588
|
+
this.logger?.error("Failed to install plugins", error);
|
|
19589
|
+
return {
|
|
19590
|
+
success: false,
|
|
19591
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19592
|
+
};
|
|
19593
|
+
}
|
|
19594
|
+
},
|
|
19595
|
+
uninstallPlugin: async (pluginName, marketplaceName, scope) => {
|
|
19596
|
+
try {
|
|
19597
|
+
if (this.provider && "uninstallPlugin" in this.provider && typeof this.provider.uninstallPlugin === "function") {
|
|
19598
|
+
const result = await this.provider.uninstallPlugin(pluginName, marketplaceName, scope);
|
|
19599
|
+
this.logger?.info("Uninstall plugin", {
|
|
19600
|
+
pluginName,
|
|
19601
|
+
marketplaceName,
|
|
19602
|
+
scope,
|
|
19603
|
+
success: result.success
|
|
19604
|
+
});
|
|
19605
|
+
return result;
|
|
19606
|
+
}
|
|
19607
|
+
this.logger?.warn("Provider does not support uninstallPlugin");
|
|
19608
|
+
return {
|
|
19609
|
+
success: false,
|
|
19610
|
+
error: "Provider does not support uninstallPlugin"
|
|
19611
|
+
};
|
|
19612
|
+
} catch (error) {
|
|
19613
|
+
this.logger?.error("Failed to uninstall plugin", error);
|
|
19614
|
+
return {
|
|
19615
|
+
success: false,
|
|
19616
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19617
|
+
};
|
|
19618
|
+
}
|
|
19619
|
+
},
|
|
19620
|
+
updatePlugin: async (pluginName, marketplaceName) => {
|
|
19621
|
+
try {
|
|
19622
|
+
if (this.provider && "updatePlugin" in this.provider && typeof this.provider.updatePlugin === "function") {
|
|
19623
|
+
const result = await this.provider.updatePlugin(pluginName, marketplaceName);
|
|
19624
|
+
this.logger?.info("Update plugin", {
|
|
19625
|
+
pluginName,
|
|
19626
|
+
marketplaceName,
|
|
19627
|
+
success: result.success
|
|
19628
|
+
});
|
|
19629
|
+
return result;
|
|
19630
|
+
}
|
|
19631
|
+
this.logger?.warn("Provider does not support updatePlugin");
|
|
19632
|
+
return {
|
|
19633
|
+
success: false,
|
|
19634
|
+
error: "Provider does not support updatePlugin"
|
|
19635
|
+
};
|
|
19636
|
+
} catch (error) {
|
|
19637
|
+
this.logger?.error("Failed to update plugin", error);
|
|
19638
|
+
return {
|
|
19639
|
+
success: false,
|
|
19640
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19641
|
+
};
|
|
19642
|
+
}
|
|
19643
|
+
},
|
|
19644
|
+
getPluginMarketplaces: async (forceRefresh) => {
|
|
19645
|
+
try {
|
|
19646
|
+
if (this.provider && "getPluginMarketplaces" in this.provider && typeof this.provider.getPluginMarketplaces === "function") {
|
|
19647
|
+
const result = await this.provider.getPluginMarketplaces(forceRefresh);
|
|
19648
|
+
this.logger?.info("Got plugin marketplaces", { count: result?.length ?? 0 });
|
|
19649
|
+
return result;
|
|
19650
|
+
}
|
|
19651
|
+
this.logger?.warn("Provider does not support getPluginMarketplaces");
|
|
19652
|
+
return [];
|
|
19653
|
+
} catch (error) {
|
|
19654
|
+
this.logger?.error("Failed to get plugin marketplaces", error);
|
|
19655
|
+
return [];
|
|
19656
|
+
}
|
|
19657
|
+
},
|
|
19658
|
+
getMarketplacePlugins: async (marketplaceName, forceRefresh, searchText) => {
|
|
19659
|
+
try {
|
|
19660
|
+
if (this.provider && "getMarketplacePlugins" in this.provider && typeof this.provider.getMarketplacePlugins === "function") {
|
|
19661
|
+
const result = await this.provider.getMarketplacePlugins(marketplaceName, forceRefresh, searchText);
|
|
19662
|
+
this.logger?.info("Got marketplace plugins", {
|
|
19663
|
+
marketplaceName,
|
|
19664
|
+
count: result?.length ?? 0
|
|
19665
|
+
});
|
|
19666
|
+
return result;
|
|
19667
|
+
}
|
|
19668
|
+
this.logger?.warn("Provider does not support getMarketplacePlugins");
|
|
19669
|
+
return [];
|
|
19670
|
+
} catch (error) {
|
|
19671
|
+
this.logger?.error("Failed to get marketplace plugins", error);
|
|
19672
|
+
return [];
|
|
19673
|
+
}
|
|
19674
|
+
},
|
|
19675
|
+
getPluginDetail: async (pluginName, marketplaceName) => {
|
|
19676
|
+
try {
|
|
19677
|
+
if (this.provider && "getPluginDetail" in this.provider && typeof this.provider.getPluginDetail === "function") {
|
|
19678
|
+
const result = await this.provider.getPluginDetail(pluginName, marketplaceName);
|
|
19679
|
+
this.logger?.info("Got plugin detail", {
|
|
19680
|
+
pluginName,
|
|
19681
|
+
marketplaceName
|
|
19682
|
+
});
|
|
19683
|
+
return result;
|
|
19684
|
+
}
|
|
19685
|
+
this.logger?.warn("Provider does not support getPluginDetail");
|
|
19686
|
+
return null;
|
|
19687
|
+
} catch (error) {
|
|
19688
|
+
this.logger?.error("Failed to get plugin detail", error);
|
|
19689
|
+
return null;
|
|
19690
|
+
}
|
|
19691
|
+
},
|
|
19692
|
+
addPluginMarketplace: async (source, name) => {
|
|
19693
|
+
try {
|
|
19694
|
+
if (this.provider && "addPluginMarketplace" in this.provider && typeof this.provider.addPluginMarketplace === "function") {
|
|
19695
|
+
const result = await this.provider.addPluginMarketplace(source, name);
|
|
19696
|
+
this.logger?.info("Add plugin marketplace", {
|
|
19697
|
+
source,
|
|
19698
|
+
name,
|
|
19699
|
+
success: result.success
|
|
19700
|
+
});
|
|
19701
|
+
return result;
|
|
19702
|
+
}
|
|
19703
|
+
this.logger?.warn("Provider does not support addPluginMarketplace");
|
|
19704
|
+
return {
|
|
19705
|
+
success: false,
|
|
19706
|
+
error: "Provider does not support addPluginMarketplace"
|
|
19707
|
+
};
|
|
19708
|
+
} catch (error) {
|
|
19709
|
+
this.logger?.error("Failed to add plugin marketplace", error);
|
|
19710
|
+
return {
|
|
19711
|
+
success: false,
|
|
19712
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19713
|
+
};
|
|
19714
|
+
}
|
|
19715
|
+
},
|
|
19716
|
+
removePluginMarketplace: async (marketplaceName) => {
|
|
19717
|
+
try {
|
|
19718
|
+
if (this.provider && "removePluginMarketplace" in this.provider && typeof this.provider.removePluginMarketplace === "function") {
|
|
19719
|
+
const result = await this.provider.removePluginMarketplace(marketplaceName);
|
|
19720
|
+
this.logger?.info("Remove plugin marketplace", {
|
|
19721
|
+
marketplaceName,
|
|
19722
|
+
success: result.success
|
|
19723
|
+
});
|
|
19724
|
+
return result;
|
|
19725
|
+
}
|
|
19726
|
+
this.logger?.warn("Provider does not support removePluginMarketplace");
|
|
19727
|
+
return {
|
|
19728
|
+
success: false,
|
|
19729
|
+
error: "Provider does not support removePluginMarketplace"
|
|
19730
|
+
};
|
|
19731
|
+
} catch (error) {
|
|
19732
|
+
this.logger?.error("Failed to remove plugin marketplace", error);
|
|
19733
|
+
return {
|
|
19734
|
+
success: false,
|
|
19735
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19736
|
+
};
|
|
18309
19737
|
}
|
|
18310
19738
|
},
|
|
18311
|
-
|
|
19739
|
+
refreshPluginMarketplace: async (marketplaceName) => {
|
|
18312
19740
|
try {
|
|
18313
|
-
if (this.provider && "
|
|
18314
|
-
const result = await this.provider.
|
|
18315
|
-
this.logger?.info("
|
|
18316
|
-
pluginNames,
|
|
19741
|
+
if (this.provider && "refreshPluginMarketplace" in this.provider && typeof this.provider.refreshPluginMarketplace === "function") {
|
|
19742
|
+
const result = await this.provider.refreshPluginMarketplace(marketplaceName);
|
|
19743
|
+
this.logger?.info("Refresh plugin marketplace", {
|
|
18317
19744
|
marketplaceName,
|
|
18318
19745
|
success: result.success
|
|
18319
19746
|
});
|
|
18320
19747
|
return result;
|
|
18321
19748
|
}
|
|
18322
|
-
this.logger?.warn("Provider does not support
|
|
19749
|
+
this.logger?.warn("Provider does not support refreshPluginMarketplace");
|
|
18323
19750
|
return {
|
|
18324
19751
|
success: false,
|
|
18325
|
-
error: "Provider does not support
|
|
19752
|
+
error: "Provider does not support refreshPluginMarketplace"
|
|
18326
19753
|
};
|
|
18327
19754
|
} catch (error) {
|
|
18328
|
-
this.logger?.error("Failed to
|
|
19755
|
+
this.logger?.error("Failed to refresh plugin marketplace", error);
|
|
18329
19756
|
return {
|
|
18330
19757
|
success: false,
|
|
18331
19758
|
error: error instanceof Error ? error.message : "Unknown error"
|
|
18332
19759
|
};
|
|
18333
19760
|
}
|
|
18334
19761
|
},
|
|
18335
|
-
|
|
19762
|
+
openFolderInNewWindow: async (folderPath) => {
|
|
19763
|
+
try {
|
|
19764
|
+
if (this.provider && "openFolderInNewWindow" in this.provider && typeof this.provider.openFolderInNewWindow === "function") {
|
|
19765
|
+
await this.provider.openFolderInNewWindow(folderPath);
|
|
19766
|
+
this.logger?.info("Opened folder in new window", { folderPath });
|
|
19767
|
+
} else {
|
|
19768
|
+
this.logger?.warn("Provider does not support openFolderInNewWindow");
|
|
19769
|
+
throw new Error("Provider does not support openFolderInNewWindow");
|
|
19770
|
+
}
|
|
19771
|
+
} catch (error) {
|
|
19772
|
+
this.logger?.error("Failed to open folder in new window", error);
|
|
19773
|
+
throw error;
|
|
19774
|
+
}
|
|
19775
|
+
},
|
|
19776
|
+
openFolder: async (folderPath) => {
|
|
18336
19777
|
try {
|
|
18337
|
-
if (this.provider && "
|
|
18338
|
-
const result = await this.provider.
|
|
18339
|
-
this.logger?.info("
|
|
19778
|
+
if (this.provider && "openFolder" in this.provider && typeof this.provider.openFolder === "function") {
|
|
19779
|
+
const result = await this.provider.openFolder(folderPath);
|
|
19780
|
+
this.logger?.info("Opened folder in system file manager", { folderPath });
|
|
18340
19781
|
return result;
|
|
19782
|
+
} else {
|
|
19783
|
+
this.logger?.warn("Provider does not support openFolder");
|
|
19784
|
+
throw new Error("Provider does not support openFolder");
|
|
18341
19785
|
}
|
|
19786
|
+
} catch (error) {
|
|
19787
|
+
this.logger?.error("Failed to open folder", error);
|
|
19788
|
+
throw error;
|
|
19789
|
+
}
|
|
19790
|
+
},
|
|
19791
|
+
getSupportScenes: async (locale) => {
|
|
19792
|
+
try {
|
|
19793
|
+
if (this.provider && "getSupportScenes" in this.provider && typeof this.provider.getSupportScenes === "function") return await this.provider.getSupportScenes(locale);
|
|
18342
19794
|
this.logger?.warn("Provider does not support getSupportScenes");
|
|
18343
19795
|
return [];
|
|
18344
19796
|
} catch (error) {
|
|
@@ -18346,6 +19798,193 @@ var AgentClient = class {
|
|
|
18346
19798
|
return [];
|
|
18347
19799
|
}
|
|
18348
19800
|
},
|
|
19801
|
+
getProductScenes: async (locale) => {
|
|
19802
|
+
try {
|
|
19803
|
+
if (this.provider?.getProductScenes) {
|
|
19804
|
+
const result = await this.provider.getProductScenes(locale);
|
|
19805
|
+
this.logger?.info("Got product scenes", { count: result?.length ?? 0 });
|
|
19806
|
+
return result;
|
|
19807
|
+
}
|
|
19808
|
+
this.logger?.warn("Provider does not support getProductScenes");
|
|
19809
|
+
return [];
|
|
19810
|
+
} catch (error) {
|
|
19811
|
+
this.logger?.error("Failed to get product scenes", error);
|
|
19812
|
+
return [];
|
|
19813
|
+
}
|
|
19814
|
+
},
|
|
19815
|
+
getAvailableCommands: async (params) => {
|
|
19816
|
+
try {
|
|
19817
|
+
if (this.provider && "getAvailableCommands" in this.provider && typeof this.provider.getAvailableCommands === "function") {
|
|
19818
|
+
const result = await this.provider.getAvailableCommands(params);
|
|
19819
|
+
this.logger?.info("Got available commands from provider", {
|
|
19820
|
+
sessionId: params?.sessionId ?? "(default)",
|
|
19821
|
+
count: result?.length ?? 0
|
|
19822
|
+
});
|
|
19823
|
+
return result;
|
|
19824
|
+
}
|
|
19825
|
+
this.logger?.warn("Provider does not support getAvailableCommands", { params });
|
|
19826
|
+
return [];
|
|
19827
|
+
} catch (error) {
|
|
19828
|
+
this.logger?.error("Failed to get available commands", error);
|
|
19829
|
+
return [];
|
|
19830
|
+
}
|
|
19831
|
+
},
|
|
19832
|
+
reportTelemetry: async (eventName, payload) => {
|
|
19833
|
+
try {
|
|
19834
|
+
if (this.provider?.reportTelemetry) await this.provider.reportTelemetry(eventName, payload);
|
|
19835
|
+
else this.logger?.warn("Provider does not support reportTelemetry");
|
|
19836
|
+
} catch (error) {
|
|
19837
|
+
this.logger?.error("Failed to report telemetry", error);
|
|
19838
|
+
}
|
|
19839
|
+
},
|
|
19840
|
+
getProductConfiguration: async () => {
|
|
19841
|
+
try {
|
|
19842
|
+
if (this.provider?.getProductConfiguration) return await this.provider.getProductConfiguration();
|
|
19843
|
+
this.logger?.warn("Provider does not support getProductConfiguration");
|
|
19844
|
+
return {};
|
|
19845
|
+
} catch (error) {
|
|
19846
|
+
this.logger?.error("Failed to get product configuration", error);
|
|
19847
|
+
return {};
|
|
19848
|
+
}
|
|
19849
|
+
},
|
|
19850
|
+
getUserInfo: async () => {
|
|
19851
|
+
this.logger?.info("[AgentClient.sessions] getUserInfo() called");
|
|
19852
|
+
try {
|
|
19853
|
+
if (this.provider?.getUserInfo) {
|
|
19854
|
+
const result = await this.provider.getUserInfo();
|
|
19855
|
+
this.logger?.info("[AgentClient.sessions] getUserInfo() result:", JSON.stringify(result));
|
|
19856
|
+
return result;
|
|
19857
|
+
}
|
|
19858
|
+
this.logger?.warn("Provider does not support getUserInfo");
|
|
19859
|
+
return {};
|
|
19860
|
+
} catch (error) {
|
|
19861
|
+
this.logger?.error("Failed to get user info", error);
|
|
19862
|
+
return {};
|
|
19863
|
+
}
|
|
19864
|
+
},
|
|
19865
|
+
respondToSampling: async (sessionId, response) => {
|
|
19866
|
+
try {
|
|
19867
|
+
if (this.provider?.respondToSampling) {
|
|
19868
|
+
await this.provider.respondToSampling(sessionId, response);
|
|
19869
|
+
this.logger?.info("Responded to sampling request", {
|
|
19870
|
+
sessionId,
|
|
19871
|
+
requestId: response.id,
|
|
19872
|
+
approved: response.approved
|
|
19873
|
+
});
|
|
19874
|
+
} else this.logger?.warn("Provider does not support respondToSampling");
|
|
19875
|
+
} catch (error) {
|
|
19876
|
+
this.logger?.error("Failed to respond to sampling request", error);
|
|
19877
|
+
throw error;
|
|
19878
|
+
}
|
|
19879
|
+
},
|
|
19880
|
+
respondToRoots: async (sessionId, response) => {
|
|
19881
|
+
try {
|
|
19882
|
+
if (this.provider?.respondToRoots) {
|
|
19883
|
+
await this.provider.respondToRoots(sessionId, response);
|
|
19884
|
+
this.logger?.info("Responded to roots request", {
|
|
19885
|
+
sessionId,
|
|
19886
|
+
requestId: response.id,
|
|
19887
|
+
approved: response.approved
|
|
19888
|
+
});
|
|
19889
|
+
} else this.logger?.warn("Provider does not support respondToRoots");
|
|
19890
|
+
} catch (error) {
|
|
19891
|
+
this.logger?.error("Failed to respond to roots request", error);
|
|
19892
|
+
throw error;
|
|
19893
|
+
}
|
|
19894
|
+
},
|
|
19895
|
+
subscribeSamplingRequests: (serverName, callback) => {
|
|
19896
|
+
if (this.provider?.subscribeSamplingRequests) {
|
|
19897
|
+
this.logger?.info("Subscribing to sampling requests", { serverName });
|
|
19898
|
+
return this.provider.subscribeSamplingRequests(serverName, callback);
|
|
19899
|
+
}
|
|
19900
|
+
this.logger?.warn("Provider does not support subscribeSamplingRequests");
|
|
19901
|
+
return () => {};
|
|
19902
|
+
},
|
|
19903
|
+
subscribeRootsRequests: (serverName, callback) => {
|
|
19904
|
+
if (this.provider?.subscribeRootsRequests) {
|
|
19905
|
+
this.logger?.info("Subscribing to roots requests", { serverName });
|
|
19906
|
+
return this.provider.subscribeRootsRequests(serverName, callback);
|
|
19907
|
+
}
|
|
19908
|
+
this.logger?.warn("Provider does not support subscribeRootsRequests");
|
|
19909
|
+
return () => {};
|
|
19910
|
+
},
|
|
19911
|
+
getMcpServers: async () => {
|
|
19912
|
+
if (this.provider?.getMcpServers) {
|
|
19913
|
+
this.logger?.info("Getting MCP servers list");
|
|
19914
|
+
return this.provider.getMcpServers();
|
|
19915
|
+
}
|
|
19916
|
+
this.logger?.warn("Provider does not support getMcpServers");
|
|
19917
|
+
return [];
|
|
19918
|
+
},
|
|
19919
|
+
toggleMcpServer: async (serverName, enabled) => {
|
|
19920
|
+
if (this.provider?.toggleMcpServer) {
|
|
19921
|
+
this.logger?.info("Toggling MCP server", {
|
|
19922
|
+
serverName,
|
|
19923
|
+
enabled
|
|
19924
|
+
});
|
|
19925
|
+
await this.provider.toggleMcpServer(serverName, enabled);
|
|
19926
|
+
} else {
|
|
19927
|
+
this.logger?.warn("Provider does not support toggleMcpServer");
|
|
19928
|
+
throw new Error("toggleMcpServer not supported by provider");
|
|
19929
|
+
}
|
|
19930
|
+
},
|
|
19931
|
+
reconnectMcpServer: async (serverName, forceHttpCallback) => {
|
|
19932
|
+
if (this.provider?.reconnectMcpServer) {
|
|
19933
|
+
this.logger?.info("Reconnecting MCP server", {
|
|
19934
|
+
serverName,
|
|
19935
|
+
forceHttpCallback
|
|
19936
|
+
});
|
|
19937
|
+
await this.provider.reconnectMcpServer(serverName, forceHttpCallback);
|
|
19938
|
+
} else {
|
|
19939
|
+
this.logger?.warn("Provider does not support reconnectMcpServer");
|
|
19940
|
+
throw new Error("reconnectMcpServer not supported by provider");
|
|
19941
|
+
}
|
|
19942
|
+
},
|
|
19943
|
+
deleteMcpServer: async (serverName) => {
|
|
19944
|
+
if (this.provider?.deleteMcpServer) {
|
|
19945
|
+
this.logger?.info("Deleting MCP server", { serverName });
|
|
19946
|
+
await this.provider.deleteMcpServer(serverName);
|
|
19947
|
+
} else {
|
|
19948
|
+
this.logger?.warn("Provider does not support deleteMcpServer");
|
|
19949
|
+
throw new Error("deleteMcpServer not supported by provider");
|
|
19950
|
+
}
|
|
19951
|
+
},
|
|
19952
|
+
openMcpConfig: async () => {
|
|
19953
|
+
if (this.provider?.openMcpConfig) {
|
|
19954
|
+
this.logger?.info("Opening MCP config");
|
|
19955
|
+
await this.provider.openMcpConfig();
|
|
19956
|
+
} else {
|
|
19957
|
+
this.logger?.warn("Provider does not support openMcpConfig");
|
|
19958
|
+
throw new Error("openMcpConfig not supported by provider");
|
|
19959
|
+
}
|
|
19960
|
+
},
|
|
19961
|
+
getMcpConfigContent: async () => {
|
|
19962
|
+
if (this.provider?.getMcpConfigContent) {
|
|
19963
|
+
this.logger?.info("Getting MCP config content");
|
|
19964
|
+
return await this.provider.getMcpConfigContent();
|
|
19965
|
+
} else {
|
|
19966
|
+
this.logger?.warn("Provider does not support getMcpConfigContent");
|
|
19967
|
+
throw new Error("getMcpConfigContent not supported by provider");
|
|
19968
|
+
}
|
|
19969
|
+
},
|
|
19970
|
+
saveMcpConfigContent: async (content) => {
|
|
19971
|
+
if (this.provider?.saveMcpConfigContent) {
|
|
19972
|
+
this.logger?.info("Saving MCP config content");
|
|
19973
|
+
await this.provider.saveMcpConfigContent(content);
|
|
19974
|
+
} else {
|
|
19975
|
+
this.logger?.warn("Provider does not support saveMcpConfigContent");
|
|
19976
|
+
throw new Error("saveMcpConfigContent not supported by provider");
|
|
19977
|
+
}
|
|
19978
|
+
},
|
|
19979
|
+
clipboardReadText: async () => {
|
|
19980
|
+
if (this.provider?.clipboardReadText) {
|
|
19981
|
+
this.logger?.info("Reading clipboard text");
|
|
19982
|
+
return await this.provider.clipboardReadText();
|
|
19983
|
+
} else {
|
|
19984
|
+
this.logger?.warn("Provider does not support clipboardReadText");
|
|
19985
|
+
throw new Error("clipboardReadText not supported by provider");
|
|
19986
|
+
}
|
|
19987
|
+
},
|
|
18349
19988
|
models: this.createModelsResource()
|
|
18350
19989
|
};
|
|
18351
19990
|
}
|
|
@@ -18412,6 +20051,154 @@ let AccountStatus = /* @__PURE__ */ function(AccountStatus) {
|
|
|
18412
20051
|
return AccountStatus;
|
|
18413
20052
|
}({});
|
|
18414
20053
|
|
|
20054
|
+
//#endregion
|
|
20055
|
+
//#region ../agent-provider/src/backend/service/oauth-repository-service.ts
|
|
20056
|
+
/**
|
|
20057
|
+
* OAuth Repository Service
|
|
20058
|
+
*
|
|
20059
|
+
* 封装 OAuth 连接器相关的仓库和分支操作
|
|
20060
|
+
*/
|
|
20061
|
+
/**
|
|
20062
|
+
* OAuth Repository Service
|
|
20063
|
+
*
|
|
20064
|
+
* 提供仓库和分支的查询操作
|
|
20065
|
+
*/
|
|
20066
|
+
var OAuthRepositoryService = class {
|
|
20067
|
+
/**
|
|
20068
|
+
* 获取仓库分支列表
|
|
20069
|
+
* API 端点: GET /console/as/connector/oauth/{name}/branches
|
|
20070
|
+
*
|
|
20071
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
20072
|
+
* @param params 平台特定的查询参数
|
|
20073
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
20074
|
+
* @param perPage 每页数量,最大100
|
|
20075
|
+
* @returns Promise<OauthBranch[]> 分支列表
|
|
20076
|
+
*
|
|
20077
|
+
* @example
|
|
20078
|
+
* ```typescript
|
|
20079
|
+
* // GitHub
|
|
20080
|
+
* const branches = await service.getBranches('github', {
|
|
20081
|
+
* owner: 'CodeBuddy-Official-Account',
|
|
20082
|
+
* repo: 'CodeBuddyIDE'
|
|
20083
|
+
* });
|
|
20084
|
+
*
|
|
20085
|
+
* // Gongfeng
|
|
20086
|
+
* const branches = await service.getBranches('gongfeng', {
|
|
20087
|
+
* project_id: '1611499'
|
|
20088
|
+
* });
|
|
20089
|
+
*
|
|
20090
|
+
* // CNB
|
|
20091
|
+
* const branches = await service.getBranches('cnb', {
|
|
20092
|
+
* repo: 'genie/genie-ide'
|
|
20093
|
+
* });
|
|
20094
|
+
* ```
|
|
20095
|
+
*/
|
|
20096
|
+
async getBranches(connector, params, page = 0, perPage = 100) {
|
|
20097
|
+
try {
|
|
20098
|
+
const url = `/console/as/connector/oauth/${connector}/branches?${this.buildBranchQueryParams(connector, params, page, perPage).toString()}`;
|
|
20099
|
+
console.log(`[OAuthRepositoryService] GET ${url}`);
|
|
20100
|
+
const apiResponse = await httpService.get(url);
|
|
20101
|
+
if (!apiResponse.data) {
|
|
20102
|
+
console.warn(`[OAuthRepositoryService] No data in branches response for ${connector}`);
|
|
20103
|
+
return [];
|
|
20104
|
+
}
|
|
20105
|
+
const branches = apiResponse.data.branches || [];
|
|
20106
|
+
console.log(`[OAuthRepositoryService] Retrieved ${branches.length} branches from ${connector}`);
|
|
20107
|
+
return branches;
|
|
20108
|
+
} catch (error) {
|
|
20109
|
+
console.error(`[OAuthRepositoryService] Failed to get branches from ${connector}:`, error);
|
|
20110
|
+
throw error;
|
|
20111
|
+
}
|
|
20112
|
+
}
|
|
20113
|
+
/**
|
|
20114
|
+
* 获取仓库列表
|
|
20115
|
+
* API 端点: GET /console/as/connector/oauth/{name}/repos
|
|
20116
|
+
*
|
|
20117
|
+
* Note: 由于工蜂原生支持的 Search 能力会匹配 path/name/description 部分,
|
|
20118
|
+
* 且不支持定制,不满足产品要求(只按 name 匹配),因此前端拉取全量数据后做筛选。
|
|
20119
|
+
*
|
|
20120
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
20121
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
20122
|
+
* - GitHub 只支持全量数据,必须传 0
|
|
20123
|
+
* - 工蜂和 CNB 依据前端逻辑而定
|
|
20124
|
+
* @param perPage 每页数量,最大100
|
|
20125
|
+
* @returns Promise<ListReposResponse> 仓库列表响应
|
|
20126
|
+
*
|
|
20127
|
+
* @example
|
|
20128
|
+
* ```typescript
|
|
20129
|
+
* // GitHub - 必须传 page=0 获取全量数据
|
|
20130
|
+
* const response = await service.getRepositories('github', 0, 100);
|
|
20131
|
+
* // response.github_repos 是 map: installation_id => repo[]
|
|
20132
|
+
*
|
|
20133
|
+
* // Gongfeng
|
|
20134
|
+
* const response = await service.getRepositories('gongfeng', 0, 100);
|
|
20135
|
+
* // response.gongfeng_repos 是数组
|
|
20136
|
+
*
|
|
20137
|
+
* // CNB
|
|
20138
|
+
* const response = await service.getRepositories('cnb', 0, 100);
|
|
20139
|
+
* // response.cnb_repos 是数组
|
|
20140
|
+
* ```
|
|
20141
|
+
*/
|
|
20142
|
+
async getRepositories(connector, page = 0, perPage = 100) {
|
|
20143
|
+
try {
|
|
20144
|
+
const queryParams = new URLSearchParams();
|
|
20145
|
+
queryParams.append("page", String(page));
|
|
20146
|
+
queryParams.append("per_page", String(Math.min(perPage, 100)));
|
|
20147
|
+
const url = `/console/as/connector/oauth/${connector}/repos?${queryParams.toString()}`;
|
|
20148
|
+
console.log(`[OAuthRepositoryService] GET ${url}`);
|
|
20149
|
+
const apiResponse = await httpService.get(url);
|
|
20150
|
+
if (!apiResponse.data) {
|
|
20151
|
+
console.warn(`[OAuthRepositoryService] No data in repos response for ${connector}`);
|
|
20152
|
+
return {};
|
|
20153
|
+
}
|
|
20154
|
+
const response = apiResponse.data;
|
|
20155
|
+
this.logRepositoryCounts(response);
|
|
20156
|
+
return response;
|
|
20157
|
+
} catch (error) {
|
|
20158
|
+
console.error(`[OAuthRepositoryService] Failed to get repos from ${connector}:`, error);
|
|
20159
|
+
throw error;
|
|
20160
|
+
}
|
|
20161
|
+
}
|
|
20162
|
+
/**
|
|
20163
|
+
* 构建分支查询参数
|
|
20164
|
+
*/
|
|
20165
|
+
buildBranchQueryParams(connector, params, page, perPage) {
|
|
20166
|
+
const queryParams = new URLSearchParams();
|
|
20167
|
+
queryParams.append("page", String(page));
|
|
20168
|
+
queryParams.append("per_page", String(Math.min(perPage, 100)));
|
|
20169
|
+
if (connector === "github") {
|
|
20170
|
+
const githubParams = params;
|
|
20171
|
+
if (!githubParams.owner || !githubParams.repo) throw new Error("GitHub requires owner and repo parameters");
|
|
20172
|
+
queryParams.append("owner", githubParams.owner);
|
|
20173
|
+
queryParams.append("repo", githubParams.repo);
|
|
20174
|
+
} else if (connector === "gongfeng") {
|
|
20175
|
+
const gongfengParams = params;
|
|
20176
|
+
if (!gongfengParams.project_id) throw new Error("Gongfeng requires project_id parameter");
|
|
20177
|
+
queryParams.append("project_id", gongfengParams.project_id);
|
|
20178
|
+
} else if (connector === "cnb") {
|
|
20179
|
+
const cnbParams = params;
|
|
20180
|
+
if (!cnbParams.repo) throw new Error("CNB requires repo parameter");
|
|
20181
|
+
queryParams.append("repo", cnbParams.repo);
|
|
20182
|
+
} else throw new Error(`Unknown connector: ${connector}`);
|
|
20183
|
+
return queryParams;
|
|
20184
|
+
}
|
|
20185
|
+
/**
|
|
20186
|
+
* 记录仓库数量日志
|
|
20187
|
+
*/
|
|
20188
|
+
logRepositoryCounts(response) {
|
|
20189
|
+
if (response.github_repos) {
|
|
20190
|
+
const totalCount = Object.values(response.github_repos).reduce((sum, repos) => sum + repos.length, 0);
|
|
20191
|
+
console.log(`[OAuthRepositoryService] Retrieved ${totalCount} GitHub repos across ${Object.keys(response.github_repos).length} installations`);
|
|
20192
|
+
}
|
|
20193
|
+
if (response.gongfeng_repos) console.log(`[OAuthRepositoryService] Retrieved ${response.gongfeng_repos.length} Gongfeng repos`);
|
|
20194
|
+
if (response.cnb_repos) console.log(`[OAuthRepositoryService] Retrieved ${response.cnb_repos.length} CNB repos`);
|
|
20195
|
+
}
|
|
20196
|
+
};
|
|
20197
|
+
/**
|
|
20198
|
+
* OAuth Repository Service 单例实例
|
|
20199
|
+
*/
|
|
20200
|
+
const oauthRepositoryService = new OAuthRepositoryService();
|
|
20201
|
+
|
|
18415
20202
|
//#endregion
|
|
18416
20203
|
//#region ../agent-provider/src/backend/backend-provider.ts
|
|
18417
20204
|
/**
|
|
@@ -18420,28 +20207,17 @@ let AccountStatus = /* @__PURE__ */ function(AccountStatus) {
|
|
|
18420
20207
|
* 封装与后端 API 的 HTTP 通信
|
|
18421
20208
|
*/
|
|
18422
20209
|
/**
|
|
18423
|
-
*
|
|
18424
|
-
*
|
|
20210
|
+
* 判断当前账号是否是 SSO 账号
|
|
20211
|
+
* 通过 account.accountType === 'sso' 来判断,这种不行,因为未登录之前account 为空
|
|
18425
20212
|
*/
|
|
18426
|
-
const isSSODomain = () => {
|
|
18427
|
-
const { hostname } = window.location;
|
|
18428
|
-
return hostname.includes(".sso.copilot") || hostname.includes("sso.codebuddy.cn") || hostname.includes(".sso.copilot-staging") || hostname.includes(".staging-sso.codebuddy.cn");
|
|
18429
|
-
};
|
|
18430
20213
|
/**
|
|
18431
|
-
*
|
|
18432
|
-
* - SSO
|
|
18433
|
-
* - 非 SSO
|
|
20214
|
+
* 根据路径获取完整 URL
|
|
20215
|
+
* - SSO 账号需要跳转到对应的预发/生产域名
|
|
20216
|
+
* - 非 SSO 账号直接使用当前域名
|
|
20217
|
+
* @param path 路径,如 '/login'、'/logout'、'/home' 等
|
|
20218
|
+
* @returns 完整的 URL 地址
|
|
18434
20219
|
*/
|
|
18435
|
-
const
|
|
18436
|
-
const { hostname, protocol } = window.location;
|
|
18437
|
-
if (isSSODomain()) {
|
|
18438
|
-
const isCodebuddy = hostname.includes("codebuddy.cn");
|
|
18439
|
-
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`;
|
|
18442
|
-
}
|
|
18443
|
-
return `${window.location.origin}/login`;
|
|
18444
|
-
};
|
|
20220
|
+
const getFullUrl = (path) => `${window.location.origin}${path}`;
|
|
18445
20221
|
/** 获取当前域名的账号选择页面 URL */
|
|
18446
20222
|
const getSelectAccountUrl = () => `${window.location.origin}/login/select`;
|
|
18447
20223
|
/** localStorage 中存储选中账号 ID 的 key */
|
|
@@ -18478,12 +20254,30 @@ var BackendProvider = class {
|
|
|
18478
20254
|
constructor(config) {
|
|
18479
20255
|
httpService.setBaseURL(config.baseUrl);
|
|
18480
20256
|
if (config.authToken) httpService.setAuthToken(config.authToken);
|
|
18481
|
-
httpService.onUnauthorized(() =>
|
|
18482
|
-
|
|
18483
|
-
|
|
18484
|
-
|
|
20257
|
+
httpService.onUnauthorized(() => this.handleUnauthorized());
|
|
20258
|
+
}
|
|
20259
|
+
/**
|
|
20260
|
+
* 处理 401 未授权错误
|
|
20261
|
+
* 先尝试刷新 token,失败后再执行登出流程
|
|
20262
|
+
*
|
|
20263
|
+
* @throws 如果 token 刷新失败,抛出错误通知 HttpService 不要重试
|
|
20264
|
+
*/
|
|
20265
|
+
async handleUnauthorized() {
|
|
20266
|
+
console.log("[BackendProvider] User unauthorized (401), attempting token refresh first");
|
|
20267
|
+
try {
|
|
20268
|
+
if (await this.refreshToken()) {
|
|
20269
|
+
console.log("[BackendProvider] Token refresh successful after 401, user still logged in");
|
|
20270
|
+
return;
|
|
20271
|
+
}
|
|
20272
|
+
throw new Error("Token refresh returned null");
|
|
20273
|
+
} catch (error) {
|
|
20274
|
+
console.error("[BackendProvider] Token refresh failed after 401:", error);
|
|
20275
|
+
console.log("[BackendProvider] Token refresh failed, triggering logout");
|
|
20276
|
+
this.logout().catch((logoutError) => {
|
|
20277
|
+
console.error("[BackendProvider] Logout failed in 401 handler:", logoutError);
|
|
18485
20278
|
});
|
|
18486
|
-
|
|
20279
|
+
throw error;
|
|
20280
|
+
}
|
|
18487
20281
|
}
|
|
18488
20282
|
/**
|
|
18489
20283
|
* 获取当前账号信息
|
|
@@ -18528,7 +20322,7 @@ var BackendProvider = class {
|
|
|
18528
20322
|
return account;
|
|
18529
20323
|
}
|
|
18530
20324
|
const redirectUrl = encodeURIComponent(window.location.href);
|
|
18531
|
-
window.location.href = `${getSelectAccountUrl()}?platform=
|
|
20325
|
+
window.location.href = `${getSelectAccountUrl()}?platform=agents&state=0&redirect_uri=${redirectUrl}`;
|
|
18532
20326
|
accountService.setAccount(null);
|
|
18533
20327
|
return null;
|
|
18534
20328
|
} catch (error) {
|
|
@@ -18551,7 +20345,8 @@ var BackendProvider = class {
|
|
|
18551
20345
|
activeStatus: connector.active_status,
|
|
18552
20346
|
displayName: connector.display_name,
|
|
18553
20347
|
oauthClientId: connector.oauth_client_id,
|
|
18554
|
-
oauthRedirectUrl: connector.oauth_redirect_url
|
|
20348
|
+
oauthRedirectUrl: connector.oauth_redirect_url,
|
|
20349
|
+
oauthAppName: connector.oauth_app_name
|
|
18555
20350
|
})) };
|
|
18556
20351
|
}
|
|
18557
20352
|
throw result;
|
|
@@ -18633,7 +20428,8 @@ var BackendProvider = class {
|
|
|
18633
20428
|
connectStatus: connector.connect_status,
|
|
18634
20429
|
displayName: connector.display_name,
|
|
18635
20430
|
oauthClientId: connector.oauth_client_id,
|
|
18636
|
-
oauthRedirectUrl: connector.oauth_redirect_url
|
|
20431
|
+
oauthRedirectUrl: connector.oauth_redirect_url,
|
|
20432
|
+
oauthAppName: connector.oauth_app_name
|
|
18637
20433
|
})) };
|
|
18638
20434
|
}
|
|
18639
20435
|
throw result;
|
|
@@ -18745,10 +20541,11 @@ var BackendProvider = class {
|
|
|
18745
20541
|
if (!time) return 0;
|
|
18746
20542
|
return new Date(time).getTime();
|
|
18747
20543
|
};
|
|
18748
|
-
const dailyCredits = [CommodityCode.free
|
|
20544
|
+
const dailyCredits = [CommodityCode.free];
|
|
18749
20545
|
const planResources = resources.map((r) => {
|
|
18750
20546
|
const isDaily = dailyCredits.includes(r.PackageCode);
|
|
18751
20547
|
const endTime = isDaily ? r.CycleEndTime : r.DeductionEndTime;
|
|
20548
|
+
const refreshAt = parseTime(r.CycleEndTime) + 1e3;
|
|
18752
20549
|
return {
|
|
18753
20550
|
id: r.ResourceId,
|
|
18754
20551
|
name: isDaily ? "plan.addonCredits" : getPackageName(r.PackageCode),
|
|
@@ -18758,7 +20555,7 @@ var BackendProvider = class {
|
|
|
18758
20555
|
used: Math.max(0, Number(r.CycleCapacitySizePrecise) - Number(r.CycleCapacityRemainPrecise)) || 0,
|
|
18759
20556
|
left: Number(r.CycleCapacityRemainPrecise) || 0,
|
|
18760
20557
|
expireAt: parseTime(endTime),
|
|
18761
|
-
refreshAt: isDaily ? void 0 :
|
|
20558
|
+
refreshAt: isDaily ? void 0 : refreshAt
|
|
18762
20559
|
};
|
|
18763
20560
|
}).sort((a, b) => {
|
|
18764
20561
|
const getPriority = (code) => {
|
|
@@ -18766,10 +20563,11 @@ var BackendProvider = class {
|
|
|
18766
20563
|
CommodityCode.proMon,
|
|
18767
20564
|
CommodityCode.proMonPlus,
|
|
18768
20565
|
CommodityCode.proYear,
|
|
20566
|
+
CommodityCode.freeMon,
|
|
18769
20567
|
CommodityCode.extra
|
|
18770
20568
|
].includes(code)) return 1;
|
|
18771
20569
|
if ([CommodityCode.gift, CommodityCode.activity].includes(code)) return 2;
|
|
18772
|
-
if ([CommodityCode.free
|
|
20570
|
+
if ([CommodityCode.free].includes(code)) return 3;
|
|
18773
20571
|
return 4;
|
|
18774
20572
|
};
|
|
18775
20573
|
return getPriority(a.packageCode) - getPriority(b.packageCode);
|
|
@@ -18890,38 +20688,69 @@ var BackendProvider = class {
|
|
|
18890
20688
|
*/
|
|
18891
20689
|
async login() {
|
|
18892
20690
|
const redirectUrl = encodeURIComponent(window.location.href);
|
|
18893
|
-
window.location.href = `${
|
|
20691
|
+
window.location.href = `${getFullUrl("/login")}?platform=agents&state=0&redirect_uri=${redirectUrl}`;
|
|
18894
20692
|
}
|
|
18895
20693
|
/**
|
|
18896
20694
|
* 登出账号
|
|
18897
|
-
*
|
|
20695
|
+
*
|
|
20696
|
+
* 策略:
|
|
20697
|
+
* - IOA 企业:用 iframe 走 SSO/SAML SLO 登出链路(涉及跨域重定向),通过轮询 iframe URL 变化检测完成
|
|
20698
|
+
* - 非 IOA 企业:直接用 httpService 请求 /console/logout,速度快
|
|
18898
20699
|
*/
|
|
18899
20700
|
async logout() {
|
|
18900
|
-
const
|
|
20701
|
+
const account = accountService.getAccount();
|
|
20702
|
+
if (account?.enterpriseId && ["esoikz80kd8g", "etahzsqej0n4"].includes(account.enterpriseId)) await this.logoutViaIframe();
|
|
20703
|
+
else await this.logoutViaHttp();
|
|
20704
|
+
localStorage.removeItem(SELECTED_ACCOUNT_KEY);
|
|
20705
|
+
accountService.clearAccount();
|
|
20706
|
+
}
|
|
20707
|
+
/**
|
|
20708
|
+
* IOA 企业登出:通过 iframe 走 SSO/SAML SLO 登出链路
|
|
20709
|
+
* 轮询 iframe URL 变化检测完成,兜底超时 5 秒
|
|
20710
|
+
*/
|
|
20711
|
+
async logoutViaIframe() {
|
|
20712
|
+
const logoutUrl = `${httpService.getAxiosInstance().defaults.baseURL}/console/logout`;
|
|
18901
20713
|
try {
|
|
18902
20714
|
await new Promise((resolve) => {
|
|
18903
20715
|
const iframe = document.createElement("iframe");
|
|
18904
20716
|
iframe.style.cssText = "position:fixed;top:-9999px;left:-9999px;width:1px;height:1px;border:none;";
|
|
18905
|
-
iframe.src =
|
|
18906
|
-
|
|
18907
|
-
|
|
18908
|
-
|
|
18909
|
-
|
|
18910
|
-
|
|
20717
|
+
iframe.src = logoutUrl;
|
|
20718
|
+
let pollTimer;
|
|
20719
|
+
let settled = false;
|
|
20720
|
+
const done = () => {
|
|
20721
|
+
if (settled) return;
|
|
20722
|
+
settled = true;
|
|
20723
|
+
clearInterval(pollTimer);
|
|
18911
20724
|
clearTimeout(timeout);
|
|
18912
20725
|
if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
|
|
18913
|
-
};
|
|
18914
|
-
iframe.onerror = () => {
|
|
18915
|
-
cleanup();
|
|
18916
20726
|
resolve();
|
|
18917
20727
|
};
|
|
20728
|
+
let wasRedirecting = false;
|
|
20729
|
+
pollTimer = setInterval(() => {
|
|
20730
|
+
try {
|
|
20731
|
+
const href = iframe.contentWindow?.location?.href;
|
|
20732
|
+
if (wasRedirecting && href) done();
|
|
20733
|
+
} catch {
|
|
20734
|
+
wasRedirecting = true;
|
|
20735
|
+
}
|
|
20736
|
+
}, 100);
|
|
20737
|
+
const timeout = setTimeout(done, 5e3);
|
|
20738
|
+
iframe.onerror = done;
|
|
18918
20739
|
document.body.appendChild(iframe);
|
|
18919
20740
|
});
|
|
18920
20741
|
} catch (error) {
|
|
18921
|
-
console.error("[BackendProvider] logout failed:", error);
|
|
20742
|
+
console.error("[BackendProvider] logout via iframe failed:", error);
|
|
20743
|
+
}
|
|
20744
|
+
}
|
|
20745
|
+
/**
|
|
20746
|
+
* 非 IOA 企业登出:直接 HTTP 请求 /console/logout
|
|
20747
|
+
*/
|
|
20748
|
+
async logoutViaHttp() {
|
|
20749
|
+
try {
|
|
20750
|
+
await httpService.get("/console/logout");
|
|
20751
|
+
} catch (error) {
|
|
20752
|
+
console.error("[BackendProvider] logout via http failed:", error);
|
|
18922
20753
|
}
|
|
18923
|
-
localStorage.removeItem(SELECTED_ACCOUNT_KEY);
|
|
18924
|
-
accountService.clearAccount();
|
|
18925
20754
|
}
|
|
18926
20755
|
/**
|
|
18927
20756
|
* 批量切换插件状态
|
|
@@ -18953,6 +20782,101 @@ var BackendProvider = class {
|
|
|
18953
20782
|
return null;
|
|
18954
20783
|
}
|
|
18955
20784
|
}
|
|
20785
|
+
/**
|
|
20786
|
+
* 刷新 Token
|
|
20787
|
+
* 通过调用 getAccount 刷新 cookie,适用于 Cloud 场景下页面切换回来时刷新登录态
|
|
20788
|
+
* @returns Promise<Account | null> 刷新后的账号信息
|
|
20789
|
+
*/
|
|
20790
|
+
async refreshToken() {
|
|
20791
|
+
console.log("[BackendProvider] Refreshing token...");
|
|
20792
|
+
try {
|
|
20793
|
+
const account = await this.getAccount();
|
|
20794
|
+
console.log("[BackendProvider] Token refreshed, account:", account?.uid);
|
|
20795
|
+
return account;
|
|
20796
|
+
} catch (error) {
|
|
20797
|
+
console.error("[BackendProvider] refreshToken failed:", error);
|
|
20798
|
+
return null;
|
|
20799
|
+
}
|
|
20800
|
+
}
|
|
20801
|
+
/**
|
|
20802
|
+
* 获取仓库分支列表
|
|
20803
|
+
* API 端点: GET /console/as/connector/oauth/{name}/branches
|
|
20804
|
+
*
|
|
20805
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
20806
|
+
* @param params 平台特定的查询参数
|
|
20807
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
20808
|
+
* @param perPage 每页数量,最大100
|
|
20809
|
+
* @returns Promise<OauthBranch[]> 分支列表
|
|
20810
|
+
*/
|
|
20811
|
+
async getBranches(connector, params, page = 0, perPage = 100) {
|
|
20812
|
+
return oauthRepositoryService.getBranches(connector, params, page, perPage);
|
|
20813
|
+
}
|
|
20814
|
+
/**
|
|
20815
|
+
* 获取仓库列表
|
|
20816
|
+
* API 端点: GET /console/as/connector/oauth/{name}/repos
|
|
20817
|
+
*
|
|
20818
|
+
* Note: 由于工蜂原生支持的 Search 能力会匹配 path/name/description 部分,
|
|
20819
|
+
* 且不支持定制,不满足产品要求(只按 name 匹配),因此前端拉取全量数据后做筛选。
|
|
20820
|
+
*
|
|
20821
|
+
* @param connector 连接器名称 ('github' | 'gongfeng' | 'cnb')
|
|
20822
|
+
* @param page 页码,从1开始,0表示不分页获取全部
|
|
20823
|
+
* - GitHub 只支持全量数据,必须传 0
|
|
20824
|
+
* - 工蜂和 CNB 依据前端逻辑而定
|
|
20825
|
+
* @param perPage 每页数量,最大100
|
|
20826
|
+
* @returns Promise<ListReposResponse> 仓库列表响应
|
|
20827
|
+
*/
|
|
20828
|
+
async getRepositories(connector, page = 0, perPage = 100) {
|
|
20829
|
+
return oauthRepositoryService.getRepositories(connector, page, perPage);
|
|
20830
|
+
}
|
|
20831
|
+
/**
|
|
20832
|
+
* 保存待发送的输入内容到后端
|
|
20833
|
+
* API 端点: POST /api/v1/code-id
|
|
20834
|
+
*/
|
|
20835
|
+
async savePendingInput(code) {
|
|
20836
|
+
try {
|
|
20837
|
+
const result = await httpService.post("/api/v1/code-id", { code });
|
|
20838
|
+
return result?.codeId || result?.data?.codeId || null;
|
|
20839
|
+
} catch (e) {
|
|
20840
|
+
console.warn("[BackendProvider] savePendingInput failed:", e);
|
|
20841
|
+
return null;
|
|
20842
|
+
}
|
|
20843
|
+
}
|
|
20844
|
+
/**
|
|
20845
|
+
* 从后端加载待发送的输入内容
|
|
20846
|
+
* API 端点: GET /api/v1/code?id=xxx
|
|
20847
|
+
*/
|
|
20848
|
+
async loadPendingInput(codeId) {
|
|
20849
|
+
try {
|
|
20850
|
+
const result = await httpService.get(`/api/v1/code?id=${encodeURIComponent(codeId)}`);
|
|
20851
|
+
return result?.code || result?.data?.code || null;
|
|
20852
|
+
} catch (e) {
|
|
20853
|
+
console.warn("[BackendProvider] loadPendingInput failed:", e);
|
|
20854
|
+
return null;
|
|
20855
|
+
}
|
|
20856
|
+
}
|
|
20857
|
+
/**
|
|
20858
|
+
* 获取每日签到状态
|
|
20859
|
+
* API 端点: POST /billing/meter/checkin-status
|
|
20860
|
+
*/
|
|
20861
|
+
async getCheckinStatus() {
|
|
20862
|
+
try {
|
|
20863
|
+
const result = await httpService.post("/billing/meter/checkin-status", {});
|
|
20864
|
+
if (result?.code === 0 && result?.data) return result.data;
|
|
20865
|
+
return null;
|
|
20866
|
+
} catch (error) {
|
|
20867
|
+
console.error("[BackendProvider] getCheckinStatus failed:", error);
|
|
20868
|
+
return null;
|
|
20869
|
+
}
|
|
20870
|
+
}
|
|
20871
|
+
/**
|
|
20872
|
+
* 执行每日签到
|
|
20873
|
+
* API 端点: POST /billing/meter/daily-checkin
|
|
20874
|
+
*/
|
|
20875
|
+
async claimDailyCheckin() {
|
|
20876
|
+
const result = await httpService.post("/billing/meter/daily-checkin", {});
|
|
20877
|
+
if (result?.code === 0 && result?.data) return result.data;
|
|
20878
|
+
throw new Error(result?.msg || "Checkin failed");
|
|
20879
|
+
}
|
|
18956
20880
|
};
|
|
18957
20881
|
/**
|
|
18958
20882
|
* 创建 BackendProvider 实例
|
|
@@ -18992,8 +20916,12 @@ const BACKEND_REQUEST_TYPES = {
|
|
|
18992
20916
|
GET_FILE: "backend:get-file",
|
|
18993
20917
|
RELOAD_WINDOW: "backend:reload-window",
|
|
18994
20918
|
CLOSE_AGENT_MANAGER: "backend:close-agent-manager",
|
|
20919
|
+
OPEN_EXTERNAL: "backend:open-external",
|
|
18995
20920
|
BATCH_TOGGLE_PLUGINS: "backend:batch-toggle-plugins",
|
|
18996
|
-
GET_SUPPORT_SCENES: "backend:get-support-scenes"
|
|
20921
|
+
GET_SUPPORT_SCENES: "backend:get-support-scenes",
|
|
20922
|
+
GET_ACCOUNT_USAGE: "backend:get-account-usage",
|
|
20923
|
+
GET_CHECKIN_STATUS: "backend:get-checkin-status",
|
|
20924
|
+
CLAIM_DAILY_CHECKIN: "backend:claim-daily-checkin"
|
|
18997
20925
|
};
|
|
18998
20926
|
/**
|
|
18999
20927
|
* 生成唯一请求 ID
|
|
@@ -19040,12 +20968,14 @@ var IPCBackendProvider = class {
|
|
|
19040
20968
|
*/
|
|
19041
20969
|
async getAccount() {
|
|
19042
20970
|
this.log("Getting account via IPC");
|
|
20971
|
+
const startTime = performance.now();
|
|
19043
20972
|
try {
|
|
19044
20973
|
const account = await this.sendBackendRequest(BACKEND_REQUEST_TYPES.GET_ACCOUNT);
|
|
20974
|
+
this.log(`getAccount IPC completed in ${(performance.now() - startTime).toFixed(0)}ms`);
|
|
19045
20975
|
accountService.setAccount(account);
|
|
19046
20976
|
return account;
|
|
19047
20977
|
} catch (error) {
|
|
19048
|
-
this.log(
|
|
20978
|
+
this.log(`getAccount IPC failed after ${(performance.now() - startTime).toFixed(0)}ms:`, error);
|
|
19049
20979
|
accountService.setAccount(null);
|
|
19050
20980
|
return null;
|
|
19051
20981
|
}
|
|
@@ -19287,6 +21217,20 @@ var IPCBackendProvider = class {
|
|
|
19287
21217
|
}
|
|
19288
21218
|
}
|
|
19289
21219
|
/**
|
|
21220
|
+
* 在外部浏览器中打开链接
|
|
21221
|
+
* IDE 环境: 通过 IPC 通知 IDE 使用 vscode.env.openExternal 打开 URL
|
|
21222
|
+
* @param url 要打开的 URL
|
|
21223
|
+
*/
|
|
21224
|
+
async openExternal(url) {
|
|
21225
|
+
this.log("Opening external URL via IPC:", url);
|
|
21226
|
+
try {
|
|
21227
|
+
await this.sendBackendRequest(BACKEND_REQUEST_TYPES.OPEN_EXTERNAL, { url });
|
|
21228
|
+
} catch (error) {
|
|
21229
|
+
this.log("Open external request failed:", error);
|
|
21230
|
+
throw error;
|
|
21231
|
+
}
|
|
21232
|
+
}
|
|
21233
|
+
/**
|
|
19290
21234
|
* 批量切换插件状态
|
|
19291
21235
|
* IDE 环境: 通过 IPC 调用 Extension Host 的 PluginService
|
|
19292
21236
|
*/
|
|
@@ -19320,6 +21264,51 @@ var IPCBackendProvider = class {
|
|
|
19320
21264
|
}
|
|
19321
21265
|
}
|
|
19322
21266
|
/**
|
|
21267
|
+
* 获取账号用量信息(积分/Credits)
|
|
21268
|
+
* IDE 环境: 通过 IPC 实时获取用量信息,每次打开菜单时调用
|
|
21269
|
+
*
|
|
21270
|
+
* 调用链:
|
|
21271
|
+
* 1. agent-ui: IPCBackendProvider.getAccountUsage()
|
|
21272
|
+
* 2. Agent Manager renderer: BackendService.getAccountUsage()
|
|
21273
|
+
* 3. Main Process: codebuddy:getAccountUsage IPC handler
|
|
21274
|
+
* 4. 返回 { usageLeft, usageTotal, editionType, refreshAt } 等字段
|
|
21275
|
+
*/
|
|
21276
|
+
async getAccountUsage() {
|
|
21277
|
+
this.log("Getting account usage via IPC");
|
|
21278
|
+
try {
|
|
21279
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.GET_ACCOUNT_USAGE);
|
|
21280
|
+
} catch (error) {
|
|
21281
|
+
this.log("Get account usage failed:", error);
|
|
21282
|
+
return null;
|
|
21283
|
+
}
|
|
21284
|
+
}
|
|
21285
|
+
/**
|
|
21286
|
+
* 获取每日签到状态
|
|
21287
|
+
* IDE 环境: 通过 IPC 获取签到状态
|
|
21288
|
+
*/
|
|
21289
|
+
async getCheckinStatus() {
|
|
21290
|
+
this.log("Getting checkin status via IPC");
|
|
21291
|
+
try {
|
|
21292
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.GET_CHECKIN_STATUS);
|
|
21293
|
+
} catch (error) {
|
|
21294
|
+
this.log("Get checkin status failed:", error);
|
|
21295
|
+
return null;
|
|
21296
|
+
}
|
|
21297
|
+
}
|
|
21298
|
+
/**
|
|
21299
|
+
* 执行每日签到
|
|
21300
|
+
* IDE 环境: 通过 IPC 执行签到
|
|
21301
|
+
*/
|
|
21302
|
+
async claimDailyCheckin() {
|
|
21303
|
+
this.log("Claiming daily checkin via IPC");
|
|
21304
|
+
try {
|
|
21305
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.CLAIM_DAILY_CHECKIN);
|
|
21306
|
+
} catch (error) {
|
|
21307
|
+
this.log("Claim daily checkin failed:", error);
|
|
21308
|
+
throw error;
|
|
21309
|
+
}
|
|
21310
|
+
}
|
|
21311
|
+
/**
|
|
19323
21312
|
* 调试日志
|
|
19324
21313
|
*/
|
|
19325
21314
|
log(...args) {
|