@tencent-ai/cloud-agent-sdk 0.2.13 → 0.2.14-next.17885cf.20260323
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/e2b-filesystem-4-LU6-jg.cjs +168 -0
- package/dist/e2b-filesystem-4-LU6-jg.cjs.map +1 -0
- package/dist/e2b-filesystem-BNmEfpoW.mjs +162 -0
- package/dist/e2b-filesystem-BNmEfpoW.mjs.map +1 -0
- package/dist/e2b-filesystem-B_WoA22S.cjs +252 -0
- package/dist/e2b-filesystem-B_WoA22S.cjs.map +1 -0
- package/dist/e2b-filesystem-Cac-bpRR.cjs +3 -0
- package/dist/e2b-filesystem-DM_jsT05.mjs +234 -0
- package/dist/e2b-filesystem-DM_jsT05.mjs.map +1 -0
- package/dist/e2b-filesystem-DWj9UkV8.mjs +3 -0
- package/dist/e2b-filesystem-DcVVT_tP.cjs +4 -0
- package/dist/e2b-filesystem-UheQECjB.mjs +3 -0
- package/dist/index.cjs +2345 -384
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2131 -131
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2131 -131
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2331 -372
- package/dist/index.mjs.map +1 -1
- package/dist/legacy/index.cjs +24204 -0
- package/dist/legacy/index.cjs.map +1 -0
- package/dist/legacy/index.d.cts +6590 -0
- package/dist/legacy/index.d.cts.map +1 -0
- package/dist/legacy/index.d.mts +6590 -0
- package/dist/legacy/index.d.mts.map +1 -0
- package/dist/legacy/index.mjs +13480 -0
- package/dist/legacy/index.mjs.map +1 -0
- package/dist/tencent-ai-cloud-agent-sdk-0.2.14-next.17885cf.20260323.tgz +0 -0
- package/package.json +44 -7
- package/dist/tencent-ai-cloud-agent-sdk-0.2.13.tgz +0 -0
package/dist/index.cjs
CHANGED
|
@@ -39,6 +39,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
39
39
|
}) : target, mod));
|
|
40
40
|
|
|
41
41
|
//#endregion
|
|
42
|
+
const require_e2b_filesystem = require('./e2b-filesystem-4-LU6-jg.cjs');
|
|
42
43
|
let zod = require("zod");
|
|
43
44
|
let _agentclientprotocol_sdk = require("@agentclientprotocol/sdk");
|
|
44
45
|
require("@bufbuild/protobuf");
|
|
@@ -59,7 +60,6 @@ crypto = __toESM(crypto);
|
|
|
59
60
|
let zlib = require("zlib");
|
|
60
61
|
zlib = __toESM(zlib);
|
|
61
62
|
let events = require("events");
|
|
62
|
-
let e2b = require("e2b");
|
|
63
63
|
|
|
64
64
|
//#region ../agent-provider/src/common/_legacy/tool-schemas.ts
|
|
65
65
|
/**
|
|
@@ -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");
|
|
@@ -1182,6 +1182,10 @@ var ArtifactManager = class {
|
|
|
1182
1182
|
*/
|
|
1183
1183
|
const DEFAULT_INITIALIZE_TIMEOUT = 3e4;
|
|
1184
1184
|
/**
|
|
1185
|
+
* Default timeout for session/new operation (waiting for sessionId via SSE)
|
|
1186
|
+
*/
|
|
1187
|
+
const DEFAULT_SESSION_TIMEOUT = 3e4;
|
|
1188
|
+
/**
|
|
1185
1189
|
* Default timeout for permission requests
|
|
1186
1190
|
*/
|
|
1187
1191
|
const DEFAULT_PERMISSION_TIMEOUT = 3e5;
|
|
@@ -1237,8 +1241,14 @@ var InitializationError = class extends ACPClientError {
|
|
|
1237
1241
|
* Error thrown for session-related failures
|
|
1238
1242
|
*/
|
|
1239
1243
|
var SessionError = class extends ACPClientError {
|
|
1240
|
-
constructor(message, sessionId, cause) {
|
|
1241
|
-
|
|
1244
|
+
constructor(message, sessionId, agentIdOrCause, cause) {
|
|
1245
|
+
if (agentIdOrCause instanceof Error) {
|
|
1246
|
+
super(message, "SESSION_ERROR", agentIdOrCause);
|
|
1247
|
+
this.agentId = void 0;
|
|
1248
|
+
} else {
|
|
1249
|
+
super(message, "SESSION_ERROR", cause);
|
|
1250
|
+
this.agentId = agentIdOrCause;
|
|
1251
|
+
}
|
|
1242
1252
|
this.name = "SessionError";
|
|
1243
1253
|
this.sessionId = sessionId;
|
|
1244
1254
|
}
|
|
@@ -1913,6 +1923,9 @@ var StreamableHttpClient = class {
|
|
|
1913
1923
|
headers: this.options.headers,
|
|
1914
1924
|
reconnect: this.options.reconnect,
|
|
1915
1925
|
fetch: this.options.fetch,
|
|
1926
|
+
heartbeatTimeout: this.options.heartbeatTimeout,
|
|
1927
|
+
postTimeout: this.options.postTimeout,
|
|
1928
|
+
connectionTimeout: this.options.connectionTimeout,
|
|
1916
1929
|
onConnect: (connectionId) => {
|
|
1917
1930
|
this.options.logger?.debug(`Transport connected: ${connectionId}`);
|
|
1918
1931
|
},
|
|
@@ -1987,10 +2000,6 @@ var StreamableHttpClient = class {
|
|
|
1987
2000
|
},
|
|
1988
2001
|
requestPermission: async (params) => this.handleRequestPermission(params),
|
|
1989
2002
|
extNotification: async (method, params) => {
|
|
1990
|
-
console.log("[ACP-Client] extNotification callback invoked:", {
|
|
1991
|
-
method,
|
|
1992
|
-
paramsKeys: Object.keys(params)
|
|
1993
|
-
});
|
|
1994
2003
|
await this.handleExtNotification(method, params);
|
|
1995
2004
|
},
|
|
1996
2005
|
extMethod: async (method, params) => this.handleExtMethod(method, params)
|
|
@@ -1998,19 +2007,47 @@ var StreamableHttpClient = class {
|
|
|
1998
2007
|
}
|
|
1999
2008
|
/**
|
|
2000
2009
|
* Create a new session
|
|
2010
|
+
*
|
|
2011
|
+
* Retries on transient network errors (e.g., proxy connection reset)
|
|
2012
|
+
* since session/new is idempotent and safe to retry.
|
|
2013
|
+
*
|
|
2014
|
+
* A timeout (`options.sessionTimeout`, default 30 s) guards against the
|
|
2015
|
+
* SSE response never arriving — the POST returns 202 immediately and the
|
|
2016
|
+
* sessionId comes back via GET SSE, which can hang indefinitely.
|
|
2017
|
+
* On timeout a `SessionError` is thrown.
|
|
2001
2018
|
*/
|
|
2002
2019
|
async createSession(cwd) {
|
|
2003
2020
|
this.ensureInitialized("createSession");
|
|
2004
|
-
|
|
2005
|
-
|
|
2021
|
+
const maxRetries = 2;
|
|
2022
|
+
const timeout = this.options.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT;
|
|
2023
|
+
let lastError;
|
|
2024
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) try {
|
|
2025
|
+
const sessionPromise = this.connection.newSession({
|
|
2006
2026
|
cwd,
|
|
2007
2027
|
mcpServers: []
|
|
2008
2028
|
});
|
|
2029
|
+
let response;
|
|
2030
|
+
if (timeout > 0) {
|
|
2031
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
2032
|
+
setTimeout(() => {
|
|
2033
|
+
reject(new SessionError(`session/new timed out after ${timeout}ms`));
|
|
2034
|
+
}, timeout);
|
|
2035
|
+
});
|
|
2036
|
+
response = await Promise.race([sessionPromise, timeoutPromise]);
|
|
2037
|
+
} else response = await sessionPromise;
|
|
2009
2038
|
this.options.logger?.info(`Session created: ${response.sessionId}`);
|
|
2010
2039
|
return response;
|
|
2011
2040
|
} catch (err) {
|
|
2012
|
-
|
|
2041
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
2042
|
+
if (attempt < maxRetries && isRetryableNetworkError(err)) {
|
|
2043
|
+
const delay = 500 * Math.pow(2, attempt);
|
|
2044
|
+
this.options.logger?.warn(`session/new network error, retrying in ${delay}ms (attempt ${attempt + 1}/${maxRetries}): ${lastError.message}`);
|
|
2045
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
2046
|
+
continue;
|
|
2047
|
+
}
|
|
2048
|
+
throw new SessionError(`Failed to create session: ${lastError.message}`, void 0, lastError);
|
|
2013
2049
|
}
|
|
2050
|
+
throw new SessionError(`Failed to create session: ${lastError?.message}`, void 0, lastError);
|
|
2014
2051
|
}
|
|
2015
2052
|
/**
|
|
2016
2053
|
* Load an existing session
|
|
@@ -2234,6 +2271,18 @@ var StreamableHttpClient = class {
|
|
|
2234
2271
|
if (this.state !== "initialized") throw new InvalidStateError(operation, this.state, ["initialized"]);
|
|
2235
2272
|
}
|
|
2236
2273
|
};
|
|
2274
|
+
/**
|
|
2275
|
+
* Check if an error is a retryable network-level error.
|
|
2276
|
+
* Only network failures (TypeError from fetch) are retried, NOT HTTP errors (4xx/5xx).
|
|
2277
|
+
*/
|
|
2278
|
+
function isRetryableNetworkError(error) {
|
|
2279
|
+
if (error instanceof TypeError) return true;
|
|
2280
|
+
if (error instanceof Error) {
|
|
2281
|
+
const msg = error.message.toLowerCase();
|
|
2282
|
+
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");
|
|
2283
|
+
}
|
|
2284
|
+
return false;
|
|
2285
|
+
}
|
|
2237
2286
|
|
|
2238
2287
|
//#endregion
|
|
2239
2288
|
//#region ../agent-provider/src/common/providers/cloud-agent-provider/cloud-connection.ts
|
|
@@ -2269,7 +2318,7 @@ var CloudAgentConnection = class {
|
|
|
2269
2318
|
fetch: config.fetch,
|
|
2270
2319
|
clientCapabilities: config.clientCapabilities,
|
|
2271
2320
|
onSessionUpdate: (update) => {
|
|
2272
|
-
if (!this._isStreaming) this.emit("sessionUpdate", update);
|
|
2321
|
+
if (!this._isStreaming && this.isOwnSessionNotification(update)) this.emit("sessionUpdate", update);
|
|
2273
2322
|
},
|
|
2274
2323
|
onArtifact: (artifact, event) => {
|
|
2275
2324
|
console.log("[CloudConnection] onArtifact callback:", {
|
|
@@ -2283,10 +2332,41 @@ var CloudAgentConnection = class {
|
|
|
2283
2332
|
},
|
|
2284
2333
|
onUsageUpdate: (usage) => {
|
|
2285
2334
|
this.emit("usageUpdate", usage);
|
|
2335
|
+
},
|
|
2336
|
+
onExtNotification: (method, params) => {
|
|
2337
|
+
console.log("[CloudConnection] Received extNotification:", {
|
|
2338
|
+
method,
|
|
2339
|
+
paramsKeys: Object.keys(params)
|
|
2340
|
+
});
|
|
2341
|
+
if (method === ExtensionMethod.COMMAND) {
|
|
2342
|
+
const action = params.action;
|
|
2343
|
+
const commandParams = params.params;
|
|
2344
|
+
console.log("[CloudConnection] Emitting command event:", {
|
|
2345
|
+
action,
|
|
2346
|
+
paramsKeys: commandParams ? Object.keys(commandParams) : []
|
|
2347
|
+
});
|
|
2348
|
+
this.emit("command", {
|
|
2349
|
+
action,
|
|
2350
|
+
params: commandParams
|
|
2351
|
+
});
|
|
2352
|
+
}
|
|
2286
2353
|
}
|
|
2287
2354
|
});
|
|
2288
2355
|
this.setupEventForwarding();
|
|
2289
2356
|
}
|
|
2357
|
+
/**
|
|
2358
|
+
* Check whether a notification belongs to this connection's own session.
|
|
2359
|
+
*
|
|
2360
|
+
* CloudConnection.createSession() overrides sessionId to agentId, so the
|
|
2361
|
+
* rest of the client stack uses agentId as the canonical session
|
|
2362
|
+
* identifier. Notifications whose sessionId differs from agentId
|
|
2363
|
+
* originate from sub-agent sessions running inside the same sandbox and
|
|
2364
|
+
* should be silently ignored at this layer — the adapter layer handles
|
|
2365
|
+
* sub-agent messages independently via parentToolUseId in _meta.
|
|
2366
|
+
*/
|
|
2367
|
+
isOwnSessionNotification(notification) {
|
|
2368
|
+
return notification.sessionId === this.agentId;
|
|
2369
|
+
}
|
|
2290
2370
|
setupEventForwarding() {
|
|
2291
2371
|
this.client.on("connecting", () => {
|
|
2292
2372
|
this.emit("connecting", void 0);
|
|
@@ -2447,6 +2527,7 @@ var CloudAgentConnection = class {
|
|
|
2447
2527
|
let resolveUpdate = null;
|
|
2448
2528
|
let done = false;
|
|
2449
2529
|
const listener = (update) => {
|
|
2530
|
+
if (!this.isOwnSessionNotification(update)) return;
|
|
2450
2531
|
if (resolveUpdate) {
|
|
2451
2532
|
resolveUpdate(update);
|
|
2452
2533
|
resolveUpdate = null;
|
|
@@ -2529,6 +2610,16 @@ var CloudAgentConnection = class {
|
|
|
2529
2610
|
get sessionConnectionInfo() {
|
|
2530
2611
|
return this._sessionConnectionInfo;
|
|
2531
2612
|
}
|
|
2613
|
+
async reportTelemetry(eventName, payload) {
|
|
2614
|
+
try {
|
|
2615
|
+
await this.client.extMethod("reportTelemetry", {
|
|
2616
|
+
eventName,
|
|
2617
|
+
payload
|
|
2618
|
+
});
|
|
2619
|
+
} catch (error) {
|
|
2620
|
+
console.warn("[CloudAgentConnection] reportTelemetry failed:", error);
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2532
2623
|
async extMethod(method, params) {
|
|
2533
2624
|
return this.client.extMethod(method, params);
|
|
2534
2625
|
}
|
|
@@ -3131,7 +3222,7 @@ var utils_default = {
|
|
|
3131
3222
|
*
|
|
3132
3223
|
* @returns {Error} The created error.
|
|
3133
3224
|
*/
|
|
3134
|
-
function AxiosError(message, code, config, request, response) {
|
|
3225
|
+
function AxiosError$1(message, code, config, request, response) {
|
|
3135
3226
|
Error.call(this);
|
|
3136
3227
|
if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
|
|
3137
3228
|
else this.stack = (/* @__PURE__ */ new Error()).stack;
|
|
@@ -3145,7 +3236,7 @@ function AxiosError(message, code, config, request, response) {
|
|
|
3145
3236
|
this.status = response.status ? response.status : null;
|
|
3146
3237
|
}
|
|
3147
3238
|
}
|
|
3148
|
-
utils_default.inherits(AxiosError, Error, { toJSON: function toJSON() {
|
|
3239
|
+
utils_default.inherits(AxiosError$1, Error, { toJSON: function toJSON() {
|
|
3149
3240
|
return {
|
|
3150
3241
|
message: this.message,
|
|
3151
3242
|
name: this.name,
|
|
@@ -3160,7 +3251,7 @@ utils_default.inherits(AxiosError, Error, { toJSON: function toJSON() {
|
|
|
3160
3251
|
status: this.status
|
|
3161
3252
|
};
|
|
3162
3253
|
} });
|
|
3163
|
-
const prototype$1 = AxiosError.prototype;
|
|
3254
|
+
const prototype$1 = AxiosError$1.prototype;
|
|
3164
3255
|
const descriptors = {};
|
|
3165
3256
|
[
|
|
3166
3257
|
"ERR_BAD_OPTION_VALUE",
|
|
@@ -3178,22 +3269,22 @@ const descriptors = {};
|
|
|
3178
3269
|
].forEach((code) => {
|
|
3179
3270
|
descriptors[code] = { value: code };
|
|
3180
3271
|
});
|
|
3181
|
-
Object.defineProperties(AxiosError, descriptors);
|
|
3272
|
+
Object.defineProperties(AxiosError$1, descriptors);
|
|
3182
3273
|
Object.defineProperty(prototype$1, "isAxiosError", { value: true });
|
|
3183
|
-
AxiosError.from = (error, code, config, request, response, customProps) => {
|
|
3274
|
+
AxiosError$1.from = (error, code, config, request, response, customProps) => {
|
|
3184
3275
|
const axiosError = Object.create(prototype$1);
|
|
3185
3276
|
utils_default.toFlatObject(error, axiosError, function filter(obj) {
|
|
3186
3277
|
return obj !== Error.prototype;
|
|
3187
3278
|
}, (prop) => {
|
|
3188
3279
|
return prop !== "isAxiosError";
|
|
3189
3280
|
});
|
|
3190
|
-
AxiosError.call(axiosError, error.message, code, config, request, response);
|
|
3281
|
+
AxiosError$1.call(axiosError, error.message, code, config, request, response);
|
|
3191
3282
|
axiosError.cause = error;
|
|
3192
3283
|
axiosError.name = error.name;
|
|
3193
3284
|
customProps && Object.assign(axiosError, customProps);
|
|
3194
3285
|
return axiosError;
|
|
3195
3286
|
};
|
|
3196
|
-
var AxiosError_default = AxiosError;
|
|
3287
|
+
var AxiosError_default = AxiosError$1;
|
|
3197
3288
|
|
|
3198
3289
|
//#endregion
|
|
3199
3290
|
//#region ../../node_modules/delayed-stream/lib/delayed_stream.js
|
|
@@ -11920,7 +12011,7 @@ const predicates = utils_default.toFlatObject(utils_default, {}, null, function
|
|
|
11920
12011
|
*
|
|
11921
12012
|
* @returns
|
|
11922
12013
|
*/
|
|
11923
|
-
function toFormData(obj, formData, options) {
|
|
12014
|
+
function toFormData$1(obj, formData, options) {
|
|
11924
12015
|
if (!utils_default.isObject(obj)) throw new TypeError("target must be an object");
|
|
11925
12016
|
formData = formData || new (FormData_default || FormData)();
|
|
11926
12017
|
options = utils_default.toFlatObject(options, {
|
|
@@ -11991,7 +12082,7 @@ function toFormData(obj, formData, options) {
|
|
|
11991
12082
|
build(obj);
|
|
11992
12083
|
return formData;
|
|
11993
12084
|
}
|
|
11994
|
-
var toFormData_default = toFormData;
|
|
12085
|
+
var toFormData_default = toFormData$1;
|
|
11995
12086
|
|
|
11996
12087
|
//#endregion
|
|
11997
12088
|
//#region ../agent-provider/node_modules/axios/lib/helpers/AxiosURLSearchParams.js
|
|
@@ -12515,7 +12606,7 @@ function buildAccessors(obj, header) {
|
|
|
12515
12606
|
});
|
|
12516
12607
|
});
|
|
12517
12608
|
}
|
|
12518
|
-
var AxiosHeaders = class {
|
|
12609
|
+
var AxiosHeaders$1 = class {
|
|
12519
12610
|
constructor(headers) {
|
|
12520
12611
|
headers && this.set(headers);
|
|
12521
12612
|
}
|
|
@@ -12653,7 +12744,7 @@ var AxiosHeaders = class {
|
|
|
12653
12744
|
return this;
|
|
12654
12745
|
}
|
|
12655
12746
|
};
|
|
12656
|
-
AxiosHeaders.accessor([
|
|
12747
|
+
AxiosHeaders$1.accessor([
|
|
12657
12748
|
"Content-Type",
|
|
12658
12749
|
"Content-Length",
|
|
12659
12750
|
"Accept",
|
|
@@ -12661,7 +12752,7 @@ AxiosHeaders.accessor([
|
|
|
12661
12752
|
"User-Agent",
|
|
12662
12753
|
"Authorization"
|
|
12663
12754
|
]);
|
|
12664
|
-
utils_default.reduceDescriptors(AxiosHeaders.prototype, ({ value }, key) => {
|
|
12755
|
+
utils_default.reduceDescriptors(AxiosHeaders$1.prototype, ({ value }, key) => {
|
|
12665
12756
|
let mapped = key[0].toUpperCase() + key.slice(1);
|
|
12666
12757
|
return {
|
|
12667
12758
|
get: () => value,
|
|
@@ -12670,8 +12761,8 @@ utils_default.reduceDescriptors(AxiosHeaders.prototype, ({ value }, key) => {
|
|
|
12670
12761
|
}
|
|
12671
12762
|
};
|
|
12672
12763
|
});
|
|
12673
|
-
utils_default.freezeMethods(AxiosHeaders);
|
|
12674
|
-
var AxiosHeaders_default = AxiosHeaders;
|
|
12764
|
+
utils_default.freezeMethods(AxiosHeaders$1);
|
|
12765
|
+
var AxiosHeaders_default = AxiosHeaders$1;
|
|
12675
12766
|
|
|
12676
12767
|
//#endregion
|
|
12677
12768
|
//#region ../agent-provider/node_modules/axios/lib/core/transformData.js
|
|
@@ -12697,7 +12788,7 @@ function transformData(fns, response) {
|
|
|
12697
12788
|
|
|
12698
12789
|
//#endregion
|
|
12699
12790
|
//#region ../agent-provider/node_modules/axios/lib/cancel/isCancel.js
|
|
12700
|
-
function isCancel(value) {
|
|
12791
|
+
function isCancel$1(value) {
|
|
12701
12792
|
return !!(value && value.__CANCEL__);
|
|
12702
12793
|
}
|
|
12703
12794
|
|
|
@@ -12712,12 +12803,12 @@ function isCancel(value) {
|
|
|
12712
12803
|
*
|
|
12713
12804
|
* @returns {CanceledError} The created error.
|
|
12714
12805
|
*/
|
|
12715
|
-
function CanceledError(message, config, request) {
|
|
12806
|
+
function CanceledError$1(message, config, request) {
|
|
12716
12807
|
AxiosError_default.call(this, message == null ? "canceled" : message, AxiosError_default.ERR_CANCELED, config, request);
|
|
12717
12808
|
this.name = "CanceledError";
|
|
12718
12809
|
}
|
|
12719
|
-
utils_default.inherits(CanceledError, AxiosError_default, { __CANCEL__: true });
|
|
12720
|
-
var CanceledError_default = CanceledError;
|
|
12810
|
+
utils_default.inherits(CanceledError$1, AxiosError_default, { __CANCEL__: true });
|
|
12811
|
+
var CanceledError_default = CanceledError$1;
|
|
12721
12812
|
|
|
12722
12813
|
//#endregion
|
|
12723
12814
|
//#region ../agent-provider/node_modules/axios/lib/core/settle.js
|
|
@@ -14119,7 +14210,9 @@ var require_follow_redirects = /* @__PURE__ */ __commonJSMin(((exports, module)
|
|
|
14119
14210
|
|
|
14120
14211
|
//#endregion
|
|
14121
14212
|
//#region ../agent-provider/node_modules/axios/lib/env/data.js
|
|
14122
|
-
|
|
14213
|
+
var import_follow_redirects = /* @__PURE__ */ __toESM(require_follow_redirects(), 1);
|
|
14214
|
+
var import_proxy_from_env = /* @__PURE__ */ __toESM(require_proxy_from_env(), 1);
|
|
14215
|
+
const VERSION$1 = "1.10.0";
|
|
14123
14216
|
|
|
14124
14217
|
//#endregion
|
|
14125
14218
|
//#region ../agent-provider/node_modules/axios/lib/helpers/parseProtocol.js
|
|
@@ -14482,8 +14575,6 @@ const asyncDecorator = (fn) => (...args) => utils_default.asap(() => fn(...args)
|
|
|
14482
14575
|
|
|
14483
14576
|
//#endregion
|
|
14484
14577
|
//#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
14578
|
const zlibOptions = {
|
|
14488
14579
|
flush: zlib.default.constants.Z_SYNC_FLUSH,
|
|
14489
14580
|
finishFlush: zlib.default.constants.Z_SYNC_FLUSH
|
|
@@ -14649,7 +14740,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
14649
14740
|
}
|
|
14650
14741
|
if (supportedProtocols.indexOf(protocol) === -1) return reject(new AxiosError_default("Unsupported protocol " + protocol, AxiosError_default.ERR_BAD_REQUEST, config));
|
|
14651
14742
|
const headers = AxiosHeaders_default.from(config.headers).normalize();
|
|
14652
|
-
headers.set("User-Agent", "axios/" + VERSION, false);
|
|
14743
|
+
headers.set("User-Agent", "axios/" + VERSION$1, false);
|
|
14653
14744
|
const { onUploadProgress, onDownloadProgress } = config;
|
|
14654
14745
|
const maxRate = config.maxRate;
|
|
14655
14746
|
let maxUploadRate = void 0;
|
|
@@ -14659,7 +14750,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) {
|
|
|
14659
14750
|
data = formDataToStream_default(data, (formHeaders) => {
|
|
14660
14751
|
headers.set(formHeaders);
|
|
14661
14752
|
}, {
|
|
14662
|
-
tag: `axios-${VERSION}-boundary`,
|
|
14753
|
+
tag: `axios-${VERSION$1}-boundary`,
|
|
14663
14754
|
boundary: userBoundary && userBoundary[1] || void 0
|
|
14664
14755
|
});
|
|
14665
14756
|
} else if (utils_default.isFormData(data) && utils_default.isFunction(data.getHeaders)) {
|
|
@@ -14924,7 +15015,7 @@ const headersToObject = (thing) => thing instanceof AxiosHeaders_default ? { ...
|
|
|
14924
15015
|
*
|
|
14925
15016
|
* @returns {Object} New object resulting from merging config2 to config1
|
|
14926
15017
|
*/
|
|
14927
|
-
function mergeConfig(config1, config2) {
|
|
15018
|
+
function mergeConfig$1(config1, config2) {
|
|
14928
15019
|
config2 = config2 || {};
|
|
14929
15020
|
const config = {};
|
|
14930
15021
|
function getMergedValue(target, source, prop, caseless) {
|
|
@@ -14990,7 +15081,7 @@ function mergeConfig(config1, config2) {
|
|
|
14990
15081
|
//#endregion
|
|
14991
15082
|
//#region ../agent-provider/node_modules/axios/lib/helpers/resolveConfig.js
|
|
14992
15083
|
var resolveConfig_default = (config) => {
|
|
14993
|
-
const newConfig = mergeConfig({}, config);
|
|
15084
|
+
const newConfig = mergeConfig$1({}, config);
|
|
14994
15085
|
let { data, withXSRFToken, xsrfHeaderName, xsrfCookieName, headers, auth } = newConfig;
|
|
14995
15086
|
newConfig.headers = headers = AxiosHeaders_default.from(headers);
|
|
14996
15087
|
newConfig.url = buildURL(buildFullPath(newConfig.baseURL, newConfig.url, newConfig.allowAbsoluteUrls), config.params, config.paramsSerializer);
|
|
@@ -15421,7 +15512,7 @@ function dispatchRequest(config) {
|
|
|
15421
15512
|
response.headers = AxiosHeaders_default.from(response.headers);
|
|
15422
15513
|
return response;
|
|
15423
15514
|
}, function onAdapterRejection(reason) {
|
|
15424
|
-
if (!isCancel(reason)) {
|
|
15515
|
+
if (!isCancel$1(reason)) {
|
|
15425
15516
|
throwIfCancellationRequested(config);
|
|
15426
15517
|
if (reason && reason.response) {
|
|
15427
15518
|
reason.response.data = transformData.call(config, config.transformResponse, reason.response);
|
|
@@ -15459,7 +15550,7 @@ const deprecatedWarnings = {};
|
|
|
15459
15550
|
*/
|
|
15460
15551
|
validators$1.transitional = function transitional(validator, version, message) {
|
|
15461
15552
|
function formatMessage(opt, desc) {
|
|
15462
|
-
return "[Axios v" + VERSION + "] Transitional option '" + opt + "'" + desc + (message ? ". " + message : "");
|
|
15553
|
+
return "[Axios v" + VERSION$1 + "] Transitional option '" + opt + "'" + desc + (message ? ". " + message : "");
|
|
15463
15554
|
}
|
|
15464
15555
|
return (value, opt, opts) => {
|
|
15465
15556
|
if (validator === false) throw new AxiosError_default(formatMessage(opt, " has been removed" + (version ? " in " + version : "")), AxiosError_default.ERR_DEPRECATED);
|
|
@@ -15516,7 +15607,7 @@ const validators = validator_default.validators;
|
|
|
15516
15607
|
*
|
|
15517
15608
|
* @return {Axios} A new instance of Axios
|
|
15518
15609
|
*/
|
|
15519
|
-
var Axios = class {
|
|
15610
|
+
var Axios$1 = class {
|
|
15520
15611
|
constructor(instanceConfig) {
|
|
15521
15612
|
this.defaults = instanceConfig || {};
|
|
15522
15613
|
this.interceptors = {
|
|
@@ -15553,7 +15644,7 @@ var Axios = class {
|
|
|
15553
15644
|
config = config || {};
|
|
15554
15645
|
config.url = configOrUrl;
|
|
15555
15646
|
} else config = configOrUrl || {};
|
|
15556
|
-
config = mergeConfig(this.defaults, config);
|
|
15647
|
+
config = mergeConfig$1(this.defaults, config);
|
|
15557
15648
|
const { transitional, paramsSerializer, headers } = config;
|
|
15558
15649
|
if (transitional !== void 0) validator_default.assertOptions(transitional, {
|
|
15559
15650
|
silentJSONParsing: validators.transitional(validators.boolean),
|
|
@@ -15632,7 +15723,7 @@ var Axios = class {
|
|
|
15632
15723
|
return promise;
|
|
15633
15724
|
}
|
|
15634
15725
|
getUri(config) {
|
|
15635
|
-
config = mergeConfig(this.defaults, config);
|
|
15726
|
+
config = mergeConfig$1(this.defaults, config);
|
|
15636
15727
|
return buildURL(buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls), config.params, config.paramsSerializer);
|
|
15637
15728
|
}
|
|
15638
15729
|
};
|
|
@@ -15642,8 +15733,8 @@ utils_default.forEach([
|
|
|
15642
15733
|
"head",
|
|
15643
15734
|
"options"
|
|
15644
15735
|
], function forEachMethodNoData(method) {
|
|
15645
|
-
Axios.prototype[method] = function(url, config) {
|
|
15646
|
-
return this.request(mergeConfig(config || {}, {
|
|
15736
|
+
Axios$1.prototype[method] = function(url, config) {
|
|
15737
|
+
return this.request(mergeConfig$1(config || {}, {
|
|
15647
15738
|
method,
|
|
15648
15739
|
url,
|
|
15649
15740
|
data: (config || {}).data
|
|
@@ -15657,7 +15748,7 @@ utils_default.forEach([
|
|
|
15657
15748
|
], function forEachMethodWithData(method) {
|
|
15658
15749
|
function generateHTTPMethod(isForm) {
|
|
15659
15750
|
return function httpMethod(url, data, config) {
|
|
15660
|
-
return this.request(mergeConfig(config || {}, {
|
|
15751
|
+
return this.request(mergeConfig$1(config || {}, {
|
|
15661
15752
|
method,
|
|
15662
15753
|
headers: isForm ? { "Content-Type": "multipart/form-data" } : {},
|
|
15663
15754
|
url,
|
|
@@ -15665,10 +15756,10 @@ utils_default.forEach([
|
|
|
15665
15756
|
}));
|
|
15666
15757
|
};
|
|
15667
15758
|
}
|
|
15668
|
-
Axios.prototype[method] = generateHTTPMethod();
|
|
15669
|
-
Axios.prototype[method + "Form"] = generateHTTPMethod(true);
|
|
15759
|
+
Axios$1.prototype[method] = generateHTTPMethod();
|
|
15760
|
+
Axios$1.prototype[method + "Form"] = generateHTTPMethod(true);
|
|
15670
15761
|
});
|
|
15671
|
-
var Axios_default = Axios;
|
|
15762
|
+
var Axios_default = Axios$1;
|
|
15672
15763
|
|
|
15673
15764
|
//#endregion
|
|
15674
15765
|
//#region ../agent-provider/node_modules/axios/lib/cancel/CancelToken.js
|
|
@@ -15679,7 +15770,7 @@ var Axios_default = Axios;
|
|
|
15679
15770
|
*
|
|
15680
15771
|
* @returns {CancelToken}
|
|
15681
15772
|
*/
|
|
15682
|
-
var CancelToken = class CancelToken {
|
|
15773
|
+
var CancelToken$1 = class CancelToken$1 {
|
|
15683
15774
|
constructor(executor) {
|
|
15684
15775
|
if (typeof executor !== "function") throw new TypeError("executor must be a function.");
|
|
15685
15776
|
let resolvePromise;
|
|
@@ -15751,14 +15842,14 @@ var CancelToken = class CancelToken {
|
|
|
15751
15842
|
static source() {
|
|
15752
15843
|
let cancel;
|
|
15753
15844
|
return {
|
|
15754
|
-
token: new CancelToken(function executor(c) {
|
|
15845
|
+
token: new CancelToken$1(function executor(c) {
|
|
15755
15846
|
cancel = c;
|
|
15756
15847
|
}),
|
|
15757
15848
|
cancel
|
|
15758
15849
|
};
|
|
15759
15850
|
}
|
|
15760
15851
|
};
|
|
15761
|
-
var CancelToken_default = CancelToken;
|
|
15852
|
+
var CancelToken_default = CancelToken$1;
|
|
15762
15853
|
|
|
15763
15854
|
//#endregion
|
|
15764
15855
|
//#region ../agent-provider/node_modules/axios/lib/helpers/spread.js
|
|
@@ -15783,7 +15874,7 @@ var CancelToken_default = CancelToken;
|
|
|
15783
15874
|
*
|
|
15784
15875
|
* @returns {Function}
|
|
15785
15876
|
*/
|
|
15786
|
-
function spread(callback) {
|
|
15877
|
+
function spread$1(callback) {
|
|
15787
15878
|
return function wrap(arr) {
|
|
15788
15879
|
return callback.apply(null, arr);
|
|
15789
15880
|
};
|
|
@@ -15798,13 +15889,13 @@ function spread(callback) {
|
|
|
15798
15889
|
*
|
|
15799
15890
|
* @returns {boolean} True if the payload is an error thrown by Axios, otherwise false
|
|
15800
15891
|
*/
|
|
15801
|
-
function isAxiosError(payload) {
|
|
15892
|
+
function isAxiosError$1(payload) {
|
|
15802
15893
|
return utils_default.isObject(payload) && payload.isAxiosError === true;
|
|
15803
15894
|
}
|
|
15804
15895
|
|
|
15805
15896
|
//#endregion
|
|
15806
15897
|
//#region ../agent-provider/node_modules/axios/lib/helpers/HttpStatusCode.js
|
|
15807
|
-
const HttpStatusCode = {
|
|
15898
|
+
const HttpStatusCode$1 = {
|
|
15808
15899
|
Continue: 100,
|
|
15809
15900
|
SwitchingProtocols: 101,
|
|
15810
15901
|
Processing: 102,
|
|
@@ -15869,10 +15960,10 @@ const HttpStatusCode = {
|
|
|
15869
15960
|
NotExtended: 510,
|
|
15870
15961
|
NetworkAuthenticationRequired: 511
|
|
15871
15962
|
};
|
|
15872
|
-
Object.entries(HttpStatusCode).forEach(([key, value]) => {
|
|
15873
|
-
HttpStatusCode[value] = key;
|
|
15963
|
+
Object.entries(HttpStatusCode$1).forEach(([key, value]) => {
|
|
15964
|
+
HttpStatusCode$1[value] = key;
|
|
15874
15965
|
});
|
|
15875
|
-
var HttpStatusCode_default = HttpStatusCode;
|
|
15966
|
+
var HttpStatusCode_default = HttpStatusCode$1;
|
|
15876
15967
|
|
|
15877
15968
|
//#endregion
|
|
15878
15969
|
//#region ../agent-provider/node_modules/axios/lib/axios.js
|
|
@@ -15889,7 +15980,7 @@ function createInstance(defaultConfig) {
|
|
|
15889
15980
|
utils_default.extend(instance, Axios_default.prototype, context, { allOwnKeys: true });
|
|
15890
15981
|
utils_default.extend(instance, context, null, { allOwnKeys: true });
|
|
15891
15982
|
instance.create = function create(instanceConfig) {
|
|
15892
|
-
return createInstance(mergeConfig(defaultConfig, instanceConfig));
|
|
15983
|
+
return createInstance(mergeConfig$1(defaultConfig, instanceConfig));
|
|
15893
15984
|
};
|
|
15894
15985
|
return instance;
|
|
15895
15986
|
}
|
|
@@ -15897,17 +15988,17 @@ const axios = createInstance(defaults_default);
|
|
|
15897
15988
|
axios.Axios = Axios_default;
|
|
15898
15989
|
axios.CanceledError = CanceledError_default;
|
|
15899
15990
|
axios.CancelToken = CancelToken_default;
|
|
15900
|
-
axios.isCancel = isCancel;
|
|
15901
|
-
axios.VERSION = VERSION;
|
|
15991
|
+
axios.isCancel = isCancel$1;
|
|
15992
|
+
axios.VERSION = VERSION$1;
|
|
15902
15993
|
axios.toFormData = toFormData_default;
|
|
15903
15994
|
axios.AxiosError = AxiosError_default;
|
|
15904
15995
|
axios.Cancel = axios.CanceledError;
|
|
15905
15996
|
axios.all = function all(promises) {
|
|
15906
15997
|
return Promise.all(promises);
|
|
15907
15998
|
};
|
|
15908
|
-
axios.spread = spread;
|
|
15909
|
-
axios.isAxiosError = isAxiosError;
|
|
15910
|
-
axios.mergeConfig = mergeConfig;
|
|
15999
|
+
axios.spread = spread$1;
|
|
16000
|
+
axios.isAxiosError = isAxiosError$1;
|
|
16001
|
+
axios.mergeConfig = mergeConfig$1;
|
|
15911
16002
|
axios.AxiosHeaders = AxiosHeaders_default;
|
|
15912
16003
|
axios.formToJSON = (thing) => formDataToJSON_default(utils_default.isHTMLForm(thing) ? new FormData(thing) : thing);
|
|
15913
16004
|
axios.getAdapter = adapters_default.getAdapter;
|
|
@@ -15915,6 +16006,10 @@ axios.HttpStatusCode = HttpStatusCode_default;
|
|
|
15915
16006
|
axios.default = axios;
|
|
15916
16007
|
var axios_default = axios;
|
|
15917
16008
|
|
|
16009
|
+
//#endregion
|
|
16010
|
+
//#region ../agent-provider/node_modules/axios/index.js
|
|
16011
|
+
const { Axios, AxiosError, CanceledError, isCancel, CancelToken, VERSION, all, Cancel, isAxiosError, spread, toFormData, AxiosHeaders, HttpStatusCode, formToJSON, getAdapter, mergeConfig } = axios_default;
|
|
16012
|
+
|
|
15918
16013
|
//#endregion
|
|
15919
16014
|
//#region ../agent-provider/src/http/http-service.ts
|
|
15920
16015
|
/**
|
|
@@ -15923,7 +16018,7 @@ var axios_default = axios;
|
|
|
15923
16018
|
* 特性:
|
|
15924
16019
|
* - 单例模式,全局唯一实例,延迟初始化(首次使用时自动创建)
|
|
15925
16020
|
* - 支持拦截器注册(其他模块可注入 header)
|
|
15926
|
-
* - 统一 401
|
|
16021
|
+
* - 统一 401 处理(支持自动刷新 token 并重试)
|
|
15927
16022
|
* - 自动携带凭证(withCredentials)
|
|
15928
16023
|
* - 类型安全
|
|
15929
16024
|
*
|
|
@@ -15963,6 +16058,8 @@ var HttpService = class HttpService {
|
|
|
15963
16058
|
*/
|
|
15964
16059
|
constructor(config = {}) {
|
|
15965
16060
|
this.unauthorizedCallbacks = /* @__PURE__ */ new Set();
|
|
16061
|
+
this.isRefreshing = false;
|
|
16062
|
+
this.refreshSubscribers = [];
|
|
15966
16063
|
this.config = config;
|
|
15967
16064
|
this.axiosInstance = axios_default.create({
|
|
15968
16065
|
baseURL: config.baseURL?.replace(/\/$/, "") || "",
|
|
@@ -16003,18 +16100,54 @@ var HttpService = class HttpService {
|
|
|
16003
16100
|
}, (error) => Promise.reject(error));
|
|
16004
16101
|
}
|
|
16005
16102
|
/**
|
|
16006
|
-
* 注册默认响应拦截器(处理 401
|
|
16103
|
+
* 注册默认响应拦截器(处理 401,支持自动重试)
|
|
16007
16104
|
*/
|
|
16008
16105
|
registerDefaultResponseInterceptor() {
|
|
16009
|
-
this.axiosInstance.interceptors.response.use((response) => response, (error) => {
|
|
16010
|
-
|
|
16011
|
-
|
|
16012
|
-
|
|
16106
|
+
this.axiosInstance.interceptors.response.use((response) => response, async (error) => {
|
|
16107
|
+
const originalRequest = error.config;
|
|
16108
|
+
if (error.response?.status === 401 && originalRequest && !originalRequest._retry) {
|
|
16109
|
+
if (originalRequest.url?.includes("/console/accounts")) {
|
|
16110
|
+
console.warn("[HttpService] Unauthorized 401 on refresh endpoint, not retrying");
|
|
16111
|
+
return Promise.reject(error);
|
|
16112
|
+
}
|
|
16113
|
+
console.warn("[HttpService] Unauthorized 401, attempting token refresh and retry");
|
|
16114
|
+
originalRequest._retry = true;
|
|
16115
|
+
if (this.isRefreshing) return new Promise((resolve, reject) => {
|
|
16116
|
+
this.refreshSubscribers.push((success) => {
|
|
16117
|
+
if (success) this.axiosInstance.request(originalRequest).then(resolve).catch(reject);
|
|
16118
|
+
else reject(error);
|
|
16119
|
+
});
|
|
16120
|
+
});
|
|
16121
|
+
this.isRefreshing = true;
|
|
16122
|
+
try {
|
|
16123
|
+
await this.triggerUnauthorizedCallbacks();
|
|
16124
|
+
this.onRefreshSuccess();
|
|
16125
|
+
return this.axiosInstance.request(originalRequest);
|
|
16126
|
+
} catch (refreshError) {
|
|
16127
|
+
this.onRefreshFailure();
|
|
16128
|
+
return Promise.reject(error);
|
|
16129
|
+
} finally {
|
|
16130
|
+
this.isRefreshing = false;
|
|
16131
|
+
}
|
|
16013
16132
|
}
|
|
16014
16133
|
return Promise.reject(error);
|
|
16015
16134
|
});
|
|
16016
16135
|
}
|
|
16017
16136
|
/**
|
|
16137
|
+
* token 刷新成功,通知所有等待的请求
|
|
16138
|
+
*/
|
|
16139
|
+
onRefreshSuccess() {
|
|
16140
|
+
this.refreshSubscribers.forEach((callback) => callback(true));
|
|
16141
|
+
this.refreshSubscribers = [];
|
|
16142
|
+
}
|
|
16143
|
+
/**
|
|
16144
|
+
* token 刷新失败,通知所有等待的请求
|
|
16145
|
+
*/
|
|
16146
|
+
onRefreshFailure() {
|
|
16147
|
+
this.refreshSubscribers.forEach((callback) => callback(false));
|
|
16148
|
+
this.refreshSubscribers = [];
|
|
16149
|
+
}
|
|
16150
|
+
/**
|
|
16018
16151
|
* 注册请求拦截器
|
|
16019
16152
|
* @param onFulfilled 请求成功拦截器
|
|
16020
16153
|
* @param onRejected 请求失败拦截器
|
|
@@ -16091,16 +16224,18 @@ var HttpService = class HttpService {
|
|
|
16091
16224
|
this.unauthorizedCallbacks.delete(callback);
|
|
16092
16225
|
}
|
|
16093
16226
|
/**
|
|
16094
|
-
* 触发所有 401
|
|
16227
|
+
* 触发所有 401 回调并等待完成
|
|
16228
|
+
* @returns Promise,等待所有回调完成
|
|
16229
|
+
* @throws 如果任何回调失败,则抛出错误
|
|
16095
16230
|
*/
|
|
16096
|
-
triggerUnauthorizedCallbacks() {
|
|
16097
|
-
this.unauthorizedCallbacks
|
|
16098
|
-
|
|
16099
|
-
|
|
16100
|
-
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
}
|
|
16231
|
+
async triggerUnauthorizedCallbacks() {
|
|
16232
|
+
const callbacks = Array.from(this.unauthorizedCallbacks);
|
|
16233
|
+
const failedResults = (await Promise.allSettled(callbacks.map((callback) => callback()))).filter((r) => r.status === "rejected");
|
|
16234
|
+
if (failedResults.length > 0) {
|
|
16235
|
+
const errors = failedResults.map((r) => r.reason);
|
|
16236
|
+
console.error("[HttpService] Some unauthorized callbacks failed:", errors);
|
|
16237
|
+
throw errors[0];
|
|
16238
|
+
}
|
|
16104
16239
|
}
|
|
16105
16240
|
/**
|
|
16106
16241
|
* 更新 authToken
|
|
@@ -16166,6 +16301,14 @@ var HttpService = class HttpService {
|
|
|
16166
16301
|
return (await this.axiosInstance.put(url, data, config)).data;
|
|
16167
16302
|
}
|
|
16168
16303
|
/**
|
|
16304
|
+
* 通用请求方法
|
|
16305
|
+
* @param config axios 请求配置
|
|
16306
|
+
* @returns 原始 AxiosResponse
|
|
16307
|
+
*/
|
|
16308
|
+
async request(config) {
|
|
16309
|
+
return this.axiosInstance.request(config);
|
|
16310
|
+
}
|
|
16311
|
+
/**
|
|
16169
16312
|
* 获取原始 axios 实例(用于高级场景)
|
|
16170
16313
|
*/
|
|
16171
16314
|
getAxiosInstance() {
|
|
@@ -16359,6 +16502,109 @@ const accountService = new AccountService();
|
|
|
16359
16502
|
*/
|
|
16360
16503
|
if (typeof window !== "undefined") window.__genieAccountService = accountService;
|
|
16361
16504
|
|
|
16505
|
+
//#endregion
|
|
16506
|
+
//#region ../agent-provider/src/common/utils/lru-cache.ts
|
|
16507
|
+
/**
|
|
16508
|
+
* LRU (Least Recently Used) Cache
|
|
16509
|
+
* 当缓存达到容量上限时,自动淘汰最久未使用的数据
|
|
16510
|
+
*
|
|
16511
|
+
* @template K - Key 类型
|
|
16512
|
+
* @template V - Value 类型
|
|
16513
|
+
*/
|
|
16514
|
+
var LRUCache = class {
|
|
16515
|
+
/**
|
|
16516
|
+
* 创建 LRU 缓存实例
|
|
16517
|
+
* @param capacity - 缓存容量上限
|
|
16518
|
+
*/
|
|
16519
|
+
constructor(capacity) {
|
|
16520
|
+
if (capacity <= 0) throw new Error("Cache capacity must be greater than 0");
|
|
16521
|
+
this.capacity = capacity;
|
|
16522
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
16523
|
+
}
|
|
16524
|
+
/**
|
|
16525
|
+
* 获取缓存值
|
|
16526
|
+
* @param key - 键
|
|
16527
|
+
* @returns 值,如果不存在返回 undefined
|
|
16528
|
+
*/
|
|
16529
|
+
get(key) {
|
|
16530
|
+
if (!this.cache.has(key)) return;
|
|
16531
|
+
const value = this.cache.get(key);
|
|
16532
|
+
this.cache.delete(key);
|
|
16533
|
+
this.cache.set(key, value);
|
|
16534
|
+
return value;
|
|
16535
|
+
}
|
|
16536
|
+
/**
|
|
16537
|
+
* 设置缓存值
|
|
16538
|
+
* @param key - 键
|
|
16539
|
+
* @param value - 值
|
|
16540
|
+
*/
|
|
16541
|
+
set(key, value) {
|
|
16542
|
+
if (this.cache.has(key)) this.cache.delete(key);
|
|
16543
|
+
else if (this.cache.size >= this.capacity) {
|
|
16544
|
+
const firstKey = this.cache.keys().next().value;
|
|
16545
|
+
this.cache.delete(firstKey);
|
|
16546
|
+
}
|
|
16547
|
+
this.cache.set(key, value);
|
|
16548
|
+
}
|
|
16549
|
+
/**
|
|
16550
|
+
* 检查 key 是否存在
|
|
16551
|
+
* @param key - 键
|
|
16552
|
+
* @returns 是否存在
|
|
16553
|
+
*/
|
|
16554
|
+
has(key) {
|
|
16555
|
+
return this.cache.has(key);
|
|
16556
|
+
}
|
|
16557
|
+
/**
|
|
16558
|
+
* 删除指定 key
|
|
16559
|
+
* @param key - 键
|
|
16560
|
+
* @returns 是否删除成功
|
|
16561
|
+
*/
|
|
16562
|
+
delete(key) {
|
|
16563
|
+
return this.cache.delete(key);
|
|
16564
|
+
}
|
|
16565
|
+
/**
|
|
16566
|
+
* 清空缓存
|
|
16567
|
+
*/
|
|
16568
|
+
clear() {
|
|
16569
|
+
this.cache.clear();
|
|
16570
|
+
}
|
|
16571
|
+
/**
|
|
16572
|
+
* 获取当前缓存大小
|
|
16573
|
+
* @returns 当前缓存的元素数量
|
|
16574
|
+
*/
|
|
16575
|
+
get size() {
|
|
16576
|
+
return this.cache.size;
|
|
16577
|
+
}
|
|
16578
|
+
/**
|
|
16579
|
+
* 获取缓存容量
|
|
16580
|
+
* @returns 缓存容量上限
|
|
16581
|
+
*/
|
|
16582
|
+
get maxSize() {
|
|
16583
|
+
return this.capacity;
|
|
16584
|
+
}
|
|
16585
|
+
/**
|
|
16586
|
+
* 获取所有 key
|
|
16587
|
+
* @returns key 数组
|
|
16588
|
+
*/
|
|
16589
|
+
keys() {
|
|
16590
|
+
return Array.from(this.cache.keys());
|
|
16591
|
+
}
|
|
16592
|
+
/**
|
|
16593
|
+
* 获取所有 value
|
|
16594
|
+
* @returns value 数组
|
|
16595
|
+
*/
|
|
16596
|
+
values() {
|
|
16597
|
+
return Array.from(this.cache.values());
|
|
16598
|
+
}
|
|
16599
|
+
/**
|
|
16600
|
+
* 遍历缓存
|
|
16601
|
+
* @param callback - 回调函数
|
|
16602
|
+
*/
|
|
16603
|
+
forEach(callback) {
|
|
16604
|
+
this.cache.forEach((value, key) => callback(value, key));
|
|
16605
|
+
}
|
|
16606
|
+
};
|
|
16607
|
+
|
|
16362
16608
|
//#endregion
|
|
16363
16609
|
//#region ../agent-provider/src/common/utils/concurrency.ts
|
|
16364
16610
|
/**
|
|
@@ -16460,20 +16706,32 @@ var CosUploadService = class {
|
|
|
16460
16706
|
* 上传单个文件到 COS
|
|
16461
16707
|
*
|
|
16462
16708
|
* @param file - 要上传的文件
|
|
16709
|
+
* @param abortSignal - 可选的 AbortSignal,用于取消上传
|
|
16463
16710
|
* @returns 上传结果,包含访问 URL 或错误信息
|
|
16464
16711
|
*/
|
|
16465
|
-
async uploadFile(file) {
|
|
16712
|
+
async uploadFile(file, abortSignal) {
|
|
16466
16713
|
const filename = file.name;
|
|
16467
16714
|
this.logger?.info(`[CosUploadService] Uploading file: ${filename}`);
|
|
16468
16715
|
try {
|
|
16716
|
+
if (abortSignal?.aborted) return {
|
|
16717
|
+
success: false,
|
|
16718
|
+
error: "Upload cancelled",
|
|
16719
|
+
aborted: true
|
|
16720
|
+
};
|
|
16469
16721
|
const objectKey = this.generateObjectKey(filename);
|
|
16470
16722
|
this.logger?.debug(`[CosUploadService] Generated objectKey: ${objectKey}`);
|
|
16471
16723
|
const presignedItem = (await this.getPresignedUrls([objectKey])).items[0];
|
|
16472
16724
|
if (!presignedItem) throw new Error("No presigned URL item returned");
|
|
16725
|
+
if (abortSignal?.aborted) return {
|
|
16726
|
+
success: false,
|
|
16727
|
+
error: "Upload cancelled",
|
|
16728
|
+
aborted: true
|
|
16729
|
+
};
|
|
16473
16730
|
const uploadResponse = await fetch(presignedItem.upload_url, {
|
|
16474
16731
|
method: "PUT",
|
|
16475
16732
|
body: file,
|
|
16476
|
-
headers: { "Content-Type": file.type || "application/octet-stream" }
|
|
16733
|
+
headers: { "Content-Type": file.type || "application/octet-stream" },
|
|
16734
|
+
signal: abortSignal
|
|
16477
16735
|
});
|
|
16478
16736
|
if (!uploadResponse.ok) {
|
|
16479
16737
|
const errorText = await uploadResponse.text().catch(() => uploadResponse.statusText);
|
|
@@ -16487,6 +16745,11 @@ var CosUploadService = class {
|
|
|
16487
16745
|
objectKey
|
|
16488
16746
|
};
|
|
16489
16747
|
} catch (error) {
|
|
16748
|
+
if (error instanceof Error && error.name === "AbortError") return {
|
|
16749
|
+
success: false,
|
|
16750
|
+
error: "Upload cancelled",
|
|
16751
|
+
aborted: true
|
|
16752
|
+
};
|
|
16490
16753
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
16491
16754
|
this.logger?.error(`[CosUploadService] Upload failed: ${filename}`, error);
|
|
16492
16755
|
return {
|
|
@@ -16501,14 +16764,25 @@ var CosUploadService = class {
|
|
|
16501
16764
|
* 使用并发控制,限制同时上传的文件数量
|
|
16502
16765
|
*
|
|
16503
16766
|
* @param files - 要上传的文件数组
|
|
16767
|
+
* @param abortSignal - 可选的 AbortSignal,用于取消上传
|
|
16504
16768
|
* @returns 所有文件的上传结果
|
|
16505
16769
|
*/
|
|
16506
|
-
async uploadFiles(files) {
|
|
16770
|
+
async uploadFiles(files, abortSignal) {
|
|
16507
16771
|
if (files.length === 0) return {
|
|
16508
16772
|
success: true,
|
|
16509
16773
|
urls: [],
|
|
16510
16774
|
results: []
|
|
16511
16775
|
};
|
|
16776
|
+
if (abortSignal?.aborted) return {
|
|
16777
|
+
success: false,
|
|
16778
|
+
error: "Upload cancelled",
|
|
16779
|
+
aborted: true,
|
|
16780
|
+
results: files.map(() => ({
|
|
16781
|
+
success: false,
|
|
16782
|
+
error: "Upload cancelled",
|
|
16783
|
+
aborted: true
|
|
16784
|
+
}))
|
|
16785
|
+
};
|
|
16512
16786
|
this.logger?.info(`[CosUploadService] Uploading ${files.length} file(s) with concurrency ${this.uploadConcurrency}`);
|
|
16513
16787
|
try {
|
|
16514
16788
|
const fileInfos = files.map((file) => ({
|
|
@@ -16520,6 +16794,12 @@ var CosUploadService = class {
|
|
|
16520
16794
|
this.logger?.debug(`[CosUploadService] Got ${presignedResponse.items.length} presigned URLs`);
|
|
16521
16795
|
if (presignedResponse.items.length !== fileInfos.length) throw new Error(`Expected ${fileInfos.length} presigned URLs, got ${presignedResponse.items.length}`);
|
|
16522
16796
|
const results = (await runWithConcurrencySettled(fileInfos.map(({ file }, index) => async () => {
|
|
16797
|
+
if (abortSignal?.aborted) return {
|
|
16798
|
+
success: false,
|
|
16799
|
+
error: "Upload cancelled",
|
|
16800
|
+
aborted: true,
|
|
16801
|
+
objectKey: fileInfos[index].objectKey
|
|
16802
|
+
};
|
|
16523
16803
|
const presignedItem = presignedResponse.items[index];
|
|
16524
16804
|
if (!presignedItem) return {
|
|
16525
16805
|
success: false,
|
|
@@ -16530,7 +16810,8 @@ var CosUploadService = class {
|
|
|
16530
16810
|
const uploadResponse = await fetch(presignedItem.upload_url, {
|
|
16531
16811
|
method: "PUT",
|
|
16532
16812
|
body: file,
|
|
16533
|
-
headers: { "Content-Type": file.type || "application/octet-stream" }
|
|
16813
|
+
headers: { "Content-Type": file.type || "application/octet-stream" },
|
|
16814
|
+
signal: abortSignal
|
|
16534
16815
|
});
|
|
16535
16816
|
if (!uploadResponse.ok) {
|
|
16536
16817
|
const errorText = await uploadResponse.text().catch(() => uploadResponse.statusText);
|
|
@@ -16547,6 +16828,12 @@ var CosUploadService = class {
|
|
|
16547
16828
|
objectKey: presignedItem.object_key
|
|
16548
16829
|
};
|
|
16549
16830
|
} catch (error) {
|
|
16831
|
+
if (error instanceof Error && error.name === "AbortError") return {
|
|
16832
|
+
success: false,
|
|
16833
|
+
error: "Upload cancelled",
|
|
16834
|
+
aborted: true,
|
|
16835
|
+
objectKey: presignedItem.object_key
|
|
16836
|
+
};
|
|
16550
16837
|
return {
|
|
16551
16838
|
success: false,
|
|
16552
16839
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
@@ -16594,91 +16881,6 @@ var CosUploadService = class {
|
|
|
16594
16881
|
}
|
|
16595
16882
|
};
|
|
16596
16883
|
|
|
16597
|
-
//#endregion
|
|
16598
|
-
//#region ../agent-provider/src/common/providers/cloud-agent-provider/e2b-filesystem.ts
|
|
16599
|
-
/**
|
|
16600
|
-
* E2B Filesystem Implementation
|
|
16601
|
-
*
|
|
16602
|
-
* Provides FilesResource implementation using E2B Sandbox SDK.
|
|
16603
|
-
* Directly uses e2b SDK types.
|
|
16604
|
-
*
|
|
16605
|
-
* @see https://e2b.dev/docs/filesystem/read-write
|
|
16606
|
-
* @see https://e2b.dev/docs/filesystem/watch
|
|
16607
|
-
*/
|
|
16608
|
-
/**
|
|
16609
|
-
* E2B Filesystem Implementation
|
|
16610
|
-
*
|
|
16611
|
-
* Wraps E2B Sandbox SDK's filesystem operations to implement FilesResource interface.
|
|
16612
|
-
*
|
|
16613
|
-
* @example
|
|
16614
|
-
* ```typescript
|
|
16615
|
-
* const fs = await E2BFilesystem.connect({
|
|
16616
|
-
* sandboxId: 'sandbox-123',
|
|
16617
|
-
* apiKey: 'e2b_xxx'
|
|
16618
|
-
* });
|
|
16619
|
-
*
|
|
16620
|
-
* // Read/write files
|
|
16621
|
-
* await fs.write('/test.txt', 'Hello World');
|
|
16622
|
-
* const content = await fs.read('/test.txt');
|
|
16623
|
-
*
|
|
16624
|
-
* // Watch for changes
|
|
16625
|
-
* const handle = await fs.watchDir('/workspace', (event) => {
|
|
16626
|
-
* console.log('File changed:', event);
|
|
16627
|
-
* });
|
|
16628
|
-
* ```
|
|
16629
|
-
*/
|
|
16630
|
-
var E2BFilesystem = class E2BFilesystem {
|
|
16631
|
-
constructor(sandbox) {
|
|
16632
|
-
this.sandbox = sandbox;
|
|
16633
|
-
}
|
|
16634
|
-
/**
|
|
16635
|
-
* Connect to an E2B Sandbox and create filesystem instance
|
|
16636
|
-
*/
|
|
16637
|
-
static async connect(info) {
|
|
16638
|
-
return new E2BFilesystem(await e2b.Sandbox.connect(info.sandboxId, {
|
|
16639
|
-
domain: info.domain,
|
|
16640
|
-
apiUrl: info.apiUrl,
|
|
16641
|
-
requestTimeoutMs: info.requestTimeoutMs,
|
|
16642
|
-
debug: info.debug,
|
|
16643
|
-
headers: info.headers
|
|
16644
|
-
}));
|
|
16645
|
-
}
|
|
16646
|
-
/**
|
|
16647
|
-
* Get the underlying E2B Sandbox instance
|
|
16648
|
-
*/
|
|
16649
|
-
getSandbox() {
|
|
16650
|
-
return this.sandbox;
|
|
16651
|
-
}
|
|
16652
|
-
read(path, opts) {
|
|
16653
|
-
return this.sandbox.files.read(path, opts);
|
|
16654
|
-
}
|
|
16655
|
-
write(pathOrFiles, dataOrOpts, opts) {
|
|
16656
|
-
if (Array.isArray(pathOrFiles)) return this.sandbox.files.write(pathOrFiles, dataOrOpts);
|
|
16657
|
-
return this.sandbox.files.write(pathOrFiles, dataOrOpts, opts);
|
|
16658
|
-
}
|
|
16659
|
-
async list(path, opts) {
|
|
16660
|
-
return this.sandbox.files.list(path, opts);
|
|
16661
|
-
}
|
|
16662
|
-
async exists(path, opts) {
|
|
16663
|
-
return this.sandbox.files.exists(path, opts);
|
|
16664
|
-
}
|
|
16665
|
-
async makeDir(path, opts) {
|
|
16666
|
-
return this.sandbox.files.makeDir(path, opts);
|
|
16667
|
-
}
|
|
16668
|
-
async remove(path, opts) {
|
|
16669
|
-
return this.sandbox.files.remove(path, opts);
|
|
16670
|
-
}
|
|
16671
|
-
async rename(oldPath, newPath, opts) {
|
|
16672
|
-
return this.sandbox.files.rename(oldPath, newPath, opts);
|
|
16673
|
-
}
|
|
16674
|
-
async getInfo(path, opts) {
|
|
16675
|
-
return this.sandbox.files.getInfo(path, opts);
|
|
16676
|
-
}
|
|
16677
|
-
async watchDir(path, onEvent, opts) {
|
|
16678
|
-
return this.sandbox.files.watchDir(path, onEvent, opts);
|
|
16679
|
-
}
|
|
16680
|
-
};
|
|
16681
|
-
|
|
16682
16884
|
//#endregion
|
|
16683
16885
|
//#region ../agent-provider/src/common/providers/cloud-agent-provider/cloud-provider.ts
|
|
16684
16886
|
/**
|
|
@@ -16827,8 +17029,11 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
16827
17029
|
this.filesystemCache = /* @__PURE__ */ new Map();
|
|
16828
17030
|
this.connectionCache = /* @__PURE__ */ new Map();
|
|
16829
17031
|
this.eventListeners = /* @__PURE__ */ new Map();
|
|
17032
|
+
this.productConfigCache = null;
|
|
16830
17033
|
this.options = options;
|
|
16831
17034
|
this.logger = options.logger;
|
|
17035
|
+
this.marketplaceCache = new LRUCache(200);
|
|
17036
|
+
this.pluginCache = new LRUCache(2e3);
|
|
16832
17037
|
if (options.endpoint) httpService.setBaseURL(options.endpoint);
|
|
16833
17038
|
if (options.authToken) httpService.setAuthToken(options.authToken);
|
|
16834
17039
|
if (options.headers && Object.keys(options.headers).length > 0) this.requestInterceptorId = httpService.registerRequestInterceptor((config) => {
|
|
@@ -16879,7 +17084,19 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
16879
17084
|
const cached = this.filesystemCache.get(agentId);
|
|
16880
17085
|
if (cached) return cached;
|
|
16881
17086
|
const info = await this.getSandboxInfo(agentId);
|
|
16882
|
-
|
|
17087
|
+
let e2bFilesystem;
|
|
17088
|
+
if (this.options.filesystemFactory) e2bFilesystem = await this.options.filesystemFactory(info);
|
|
17089
|
+
else {
|
|
17090
|
+
const { E2BFilesystem } = await Promise.resolve().then(() => require("./e2b-filesystem-Cac-bpRR.cjs"));
|
|
17091
|
+
e2bFilesystem = await E2BFilesystem.connect(info);
|
|
17092
|
+
}
|
|
17093
|
+
if (e2bFilesystem.setReconnectFn) e2bFilesystem.setReconnectFn(async () => {
|
|
17094
|
+
this.logger?.debug(`Reconnecting E2B sandbox for agent: ${agentId}`);
|
|
17095
|
+
const newInfo = await this.getSandboxInfo(agentId);
|
|
17096
|
+
this.logger?.debug(`E2B sandbox reconnected for agent: ${agentId}`);
|
|
17097
|
+
return newInfo;
|
|
17098
|
+
});
|
|
17099
|
+
const filesystem = createAgentFilesystem(e2bFilesystem);
|
|
16883
17100
|
this.filesystemCache.set(agentId, filesystem);
|
|
16884
17101
|
this.logger?.debug(`Created filesystem for agent: ${agentId}`);
|
|
16885
17102
|
return filesystem;
|
|
@@ -16947,15 +17164,9 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
16947
17164
|
const url = this.buildGetUrl("/console/as/conversations/", params);
|
|
16948
17165
|
const apiResponse = await httpService.get(url);
|
|
16949
17166
|
if (!apiResponse.data) throw new Error("No data in API response");
|
|
16950
|
-
const agents = apiResponse.data.conversations.map((a) => this.toAgentState(a));
|
|
16951
|
-
const pagination = apiResponse.data.pagination;
|
|
16952
|
-
console.log("[CloudAgentProvider] API response:", {
|
|
16953
|
-
agentsCount: agents.length,
|
|
16954
|
-
pagination
|
|
16955
|
-
});
|
|
16956
17167
|
return {
|
|
16957
|
-
agents,
|
|
16958
|
-
pagination
|
|
17168
|
+
agents: apiResponse.data.conversations.map((a) => this.toAgentState(a)),
|
|
17169
|
+
pagination: apiResponse.data.pagination
|
|
16959
17170
|
};
|
|
16960
17171
|
} catch (error) {
|
|
16961
17172
|
this.logger?.error("Failed to list agents:", error);
|
|
@@ -16965,15 +17176,17 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
16965
17176
|
/**
|
|
16966
17177
|
* Create a new conversation
|
|
16967
17178
|
* POST {endpoint}/console/as/conversations
|
|
16968
|
-
* @param params -
|
|
17179
|
+
* @param params - Session params containing cwd and optional configuration
|
|
16969
17180
|
*/
|
|
16970
17181
|
async create(params) {
|
|
16971
17182
|
try {
|
|
16972
|
-
const
|
|
17183
|
+
const { options = {} } = params;
|
|
17184
|
+
const codebuddyMeta = options._meta?.["codebuddy.ai"];
|
|
17185
|
+
const tagsObj = options.tags || codebuddyMeta?.tags;
|
|
16973
17186
|
const tagsArray = tagsObj ? Object.entries(tagsObj).map(([key, value]) => `${key}:${value}`) : void 0;
|
|
16974
17187
|
const createPayload = {
|
|
16975
|
-
prompt: "",
|
|
16976
|
-
model: "deepseek-r1",
|
|
17188
|
+
prompt: (options.prompt || "").slice(0, 100),
|
|
17189
|
+
model: options.model || "deepseek-r1",
|
|
16977
17190
|
...tagsArray && tagsArray.length > 0 ? { tags: tagsArray } : {}
|
|
16978
17191
|
};
|
|
16979
17192
|
console.log("[CloudAgentProvider] Creating conversation with payload:", createPayload);
|
|
@@ -17027,7 +17240,14 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17027
17240
|
} catch (error) {
|
|
17028
17241
|
this.logger?.debug(`Failed to fetch conversation details for ${agentId}:`, error);
|
|
17029
17242
|
}
|
|
17030
|
-
|
|
17243
|
+
const existingConnection = this.connectionCache.get(endpoint);
|
|
17244
|
+
if (existingConnection) {
|
|
17245
|
+
this.connectionCache.delete(endpoint);
|
|
17246
|
+
existingConnection.removeAllListeners();
|
|
17247
|
+
existingConnection.disconnect().catch((err) => {
|
|
17248
|
+
this.logger?.debug("Failed to disconnect old connection:", err);
|
|
17249
|
+
});
|
|
17250
|
+
}
|
|
17031
17251
|
const clientCapabilities = {
|
|
17032
17252
|
...this.options.clientCapabilities,
|
|
17033
17253
|
_meta: {
|
|
@@ -17147,6 +17367,35 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17147
17367
|
}
|
|
17148
17368
|
}
|
|
17149
17369
|
/**
|
|
17370
|
+
* Update conversation status by ID
|
|
17371
|
+
* POST {endpoint}/console/as/conversations/{agentId}
|
|
17372
|
+
*
|
|
17373
|
+
* @param agentId - Conversation ID to update
|
|
17374
|
+
* @param status - New status for the conversation
|
|
17375
|
+
* @returns PatchConversationResponse containing the updated conversation ID
|
|
17376
|
+
*
|
|
17377
|
+
* @example
|
|
17378
|
+
* ```typescript
|
|
17379
|
+
* const result = await provider.updateStatus('agent-123', 'completed');
|
|
17380
|
+
* console.log('Updated conversation status:', result.id);
|
|
17381
|
+
* ```
|
|
17382
|
+
*/
|
|
17383
|
+
async updateStatus(agentId, status) {
|
|
17384
|
+
try {
|
|
17385
|
+
const body = { status };
|
|
17386
|
+
const apiResponse = await httpService.post(`/console/as/conversations/${agentId}`, body);
|
|
17387
|
+
if (!apiResponse.data) {
|
|
17388
|
+
this.logger?.info(`Updated conversation status: ${agentId} to "${status}"`);
|
|
17389
|
+
return { id: agentId };
|
|
17390
|
+
}
|
|
17391
|
+
this.logger?.info(`Updated conversation status: ${apiResponse.data.id} to "${status}"`);
|
|
17392
|
+
return apiResponse.data;
|
|
17393
|
+
} catch (error) {
|
|
17394
|
+
this.logger?.error(`Failed to update conversation status ${agentId}:`, error);
|
|
17395
|
+
throw error;
|
|
17396
|
+
}
|
|
17397
|
+
}
|
|
17398
|
+
/**
|
|
17150
17399
|
* Get available models from product configuration
|
|
17151
17400
|
*
|
|
17152
17401
|
* GET {endpoint}/console/enterprises/{personal|enterpriseId}/models?repos[]={repo}
|
|
@@ -17177,9 +17426,13 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17177
17426
|
this.logger?.warn("[CloudAgentProvider] No data in config response, returning empty models");
|
|
17178
17427
|
return [];
|
|
17179
17428
|
}
|
|
17180
|
-
|
|
17181
|
-
|
|
17182
|
-
|
|
17429
|
+
this.productConfigCache = apiResponse.data;
|
|
17430
|
+
const productConfig = apiResponse.data;
|
|
17431
|
+
const allModels = productConfig.models ?? [];
|
|
17432
|
+
const cliModelIds = (productConfig.agents ?? []).find((agent) => agent.name === "cli")?.models ?? [];
|
|
17433
|
+
const filteredModels = cliModelIds.length > 0 ? allModels.filter((model) => cliModelIds.includes(model.id)) : allModels;
|
|
17434
|
+
this.logger?.info(`[CloudAgentProvider] Retrieved ${filteredModels.length} models for cli agent (total: ${allModels.length})`);
|
|
17435
|
+
return filteredModels.map((model) => ({
|
|
17183
17436
|
id: model.id,
|
|
17184
17437
|
name: model.name ?? model.id,
|
|
17185
17438
|
description: model.description,
|
|
@@ -17201,6 +17454,43 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17201
17454
|
}
|
|
17202
17455
|
}
|
|
17203
17456
|
/**
|
|
17457
|
+
* 获取产品部署类型(从缓存)
|
|
17458
|
+
* 需要先调用 getModels() 初始化缓存
|
|
17459
|
+
*
|
|
17460
|
+
* @returns 部署类型:'SaaS' | 'Cloud-Hosted' | 'Self-Hosted',默认为 'SaaS'
|
|
17461
|
+
*/
|
|
17462
|
+
getDeploymentType() {
|
|
17463
|
+
return this.productConfigCache?.deploymentType ?? "SaaS";
|
|
17464
|
+
}
|
|
17465
|
+
/**
|
|
17466
|
+
* 获取 Credit 购买引导配置(从缓存)
|
|
17467
|
+
* 需要先调用 getModels() 初始化缓存
|
|
17468
|
+
*
|
|
17469
|
+
* @returns Credit 购买引导配置,key 为错误码。如果后端未返回,则使用默认配置
|
|
17470
|
+
*/
|
|
17471
|
+
getCreditPurchaseActions() {
|
|
17472
|
+
return this.productConfigCache?.config?.creditPurchaseActions ?? {
|
|
17473
|
+
"14018": {
|
|
17474
|
+
labelZh: "获取 Credits",
|
|
17475
|
+
labelEn: "Get credits",
|
|
17476
|
+
url: "https://www.codebuddy.cn/profile/plan",
|
|
17477
|
+
showButton: true
|
|
17478
|
+
},
|
|
17479
|
+
"6004": {
|
|
17480
|
+
labelZh: "升级专业版",
|
|
17481
|
+
labelEn: "Upgrade to Pro",
|
|
17482
|
+
url: "https://www.codebuddy.cn/profile/plan",
|
|
17483
|
+
showButton: true
|
|
17484
|
+
},
|
|
17485
|
+
"6005": {
|
|
17486
|
+
labelZh: "升级专业版",
|
|
17487
|
+
labelEn: "Upgrade to Pro",
|
|
17488
|
+
url: "https://www.codebuddy.cn/profile/plan",
|
|
17489
|
+
showButton: true
|
|
17490
|
+
}
|
|
17491
|
+
};
|
|
17492
|
+
}
|
|
17493
|
+
/**
|
|
17204
17494
|
* Generate a unique request ID
|
|
17205
17495
|
*/
|
|
17206
17496
|
generateRequestId() {
|
|
@@ -17283,7 +17573,7 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17283
17573
|
/**
|
|
17284
17574
|
* Upload files to cloud storage via COS presigned URL
|
|
17285
17575
|
*
|
|
17286
|
-
* @param params - files array (File objects in browser)
|
|
17576
|
+
* @param params - files array (File objects in browser), optional abortSignal
|
|
17287
17577
|
* @returns Response with corresponding cloud URLs
|
|
17288
17578
|
*/
|
|
17289
17579
|
async uploadFile(params) {
|
|
@@ -17293,12 +17583,13 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17293
17583
|
success: false,
|
|
17294
17584
|
error: "No valid File objects provided"
|
|
17295
17585
|
};
|
|
17296
|
-
const result = await this.cosUploadService.uploadFiles(files);
|
|
17586
|
+
const result = await this.cosUploadService.uploadFiles(files, params.abortSignal);
|
|
17297
17587
|
return {
|
|
17298
17588
|
success: result.success,
|
|
17299
17589
|
urls: result.urls,
|
|
17300
17590
|
expireSeconds: result.expireSeconds,
|
|
17301
|
-
error: result.error
|
|
17591
|
+
error: result.error,
|
|
17592
|
+
aborted: result.aborted
|
|
17302
17593
|
};
|
|
17303
17594
|
}
|
|
17304
17595
|
/**
|
|
@@ -17340,20 +17631,22 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17340
17631
|
}
|
|
17341
17632
|
/**
|
|
17342
17633
|
* 获取支持的场景列表
|
|
17343
|
-
* API 端点: GET /
|
|
17634
|
+
* API 端点: GET /v2/as/support/scenes (不鉴权)
|
|
17344
17635
|
* 用于 Welcome 页面的 QuickActions 快捷操作
|
|
17345
17636
|
*
|
|
17637
|
+
* @param locale - 可选,语言环境(如 'zh-CN', 'en-US'),用于获取对应语言的场景数据
|
|
17346
17638
|
* @returns Promise<SupportScene[]> 支持的场景列表
|
|
17347
17639
|
*/
|
|
17348
|
-
async getSupportScenes() {
|
|
17640
|
+
async getSupportScenes(locale) {
|
|
17349
17641
|
try {
|
|
17350
|
-
const
|
|
17642
|
+
const url = this.buildGetUrl("/v2/as/support/scenes", locale ? { locale } : void 0);
|
|
17643
|
+
const apiResponse = await httpService.get(url);
|
|
17351
17644
|
if (!apiResponse.data) {
|
|
17352
17645
|
this.logger?.warn("[CloudAgentProvider] No data in support scenes response");
|
|
17353
17646
|
return [];
|
|
17354
17647
|
}
|
|
17355
17648
|
const scenes = apiResponse.data.scenes || [];
|
|
17356
|
-
this.logger?.info(`[CloudAgentProvider] Retrieved ${scenes.length} support scenes`);
|
|
17649
|
+
this.logger?.info(`[CloudAgentProvider] Retrieved ${scenes.length} support scenes${locale ? ` for locale: ${locale}` : ""}`);
|
|
17357
17650
|
return scenes;
|
|
17358
17651
|
} catch (error) {
|
|
17359
17652
|
this.logger?.error("[CloudAgentProvider] Failed to get support scenes:", error);
|
|
@@ -17369,7 +17662,9 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17369
17662
|
type: "cloud",
|
|
17370
17663
|
status,
|
|
17371
17664
|
createdAt: data.createdAt ? new Date(data.createdAt) : void 0,
|
|
17372
|
-
|
|
17665
|
+
updatedAt: data.updatedAt ? new Date(data.updatedAt) : void 0,
|
|
17666
|
+
capabilities: this.options.clientCapabilities,
|
|
17667
|
+
isUserDefinedTitle: data.isUserDefinedTitle
|
|
17373
17668
|
};
|
|
17374
17669
|
}
|
|
17375
17670
|
/**
|
|
@@ -17385,57 +17680,500 @@ var CloudAgentProvider = class CloudAgentProvider {
|
|
|
17385
17680
|
const queryString = searchParams.toString();
|
|
17386
17681
|
return queryString ? `${path}?${queryString}` : path;
|
|
17387
17682
|
}
|
|
17388
|
-
};
|
|
17389
|
-
|
|
17390
|
-
//#endregion
|
|
17391
|
-
//#region ../agent-provider/src/common/providers/local-agent-provider/local-connection.ts
|
|
17392
|
-
/**
|
|
17393
|
-
* Local Agent Connection
|
|
17394
|
-
* Wraps AcpJsonRpcClient to implement AgentConnection interface
|
|
17395
|
-
*
|
|
17396
|
-
* Uses IWidgetChannel for IPC communication with ExtensionHost
|
|
17397
|
-
* Migrated from ipc-agent-provider for unified local agent access
|
|
17398
|
-
*/
|
|
17399
|
-
|
|
17400
|
-
//#endregion
|
|
17401
|
-
//#region ../agent-provider/src/common/client/session.ts
|
|
17402
|
-
/**
|
|
17403
|
-
* ActiveSessionImpl - Implements the ActiveSession interface
|
|
17404
|
-
*
|
|
17405
|
-
* This class wraps an AgentConnection and provides the session-centric API.
|
|
17406
|
-
* It is created by SessionManager when creating or loading sessions.
|
|
17407
|
-
*
|
|
17408
|
-
* @example
|
|
17409
|
-
* ```typescript
|
|
17410
|
-
* // Created by client.sessions.new() or client.sessions.load()
|
|
17411
|
-
* const session = await client.sessions.new({ cwd: '/workspace' });
|
|
17412
|
-
*
|
|
17413
|
-
* // Access agent state
|
|
17414
|
-
* console.log(session.agentState.status);
|
|
17415
|
-
*
|
|
17416
|
-
* // Send prompt
|
|
17417
|
-
* const response = await session.prompts.send({ content: 'Hello!' });
|
|
17418
|
-
*
|
|
17419
|
-
* // Cleanup
|
|
17420
|
-
* session.disconnect();
|
|
17421
|
-
* ```
|
|
17422
|
-
*/
|
|
17423
|
-
var ActiveSessionImpl = class {
|
|
17424
17683
|
/**
|
|
17425
|
-
*
|
|
17426
|
-
*
|
|
17427
|
-
* @param sessionId - Session ID
|
|
17428
|
-
* @param agentId - Agent ID
|
|
17429
|
-
* @param connection - Already connected AgentConnection
|
|
17430
|
-
* @param options - Additional options
|
|
17684
|
+
* 获取已安装插件列表
|
|
17685
|
+
* GET /console/as/user/plugins/installed
|
|
17431
17686
|
*/
|
|
17432
|
-
|
|
17433
|
-
|
|
17434
|
-
|
|
17435
|
-
|
|
17436
|
-
|
|
17437
|
-
|
|
17438
|
-
|
|
17687
|
+
async getInstalledPlugins(forceRefresh) {
|
|
17688
|
+
try {
|
|
17689
|
+
const result = ((await httpService.get("/console/as/user/plugins/installed")).data?.plugins || []).map((p) => ({
|
|
17690
|
+
name: p.plugin_name,
|
|
17691
|
+
marketplaceName: p.marketplace_name,
|
|
17692
|
+
status: p.enabled ? "enabled" : "disabled",
|
|
17693
|
+
description: p.description,
|
|
17694
|
+
version: p.version,
|
|
17695
|
+
installScope: p.scope === "local" ? "project" : p.scope,
|
|
17696
|
+
installedScopes: [p.scope],
|
|
17697
|
+
installId: p.id
|
|
17698
|
+
}));
|
|
17699
|
+
result.forEach((plugin) => {
|
|
17700
|
+
this.pluginCache.set(plugin.name, plugin);
|
|
17701
|
+
});
|
|
17702
|
+
return result;
|
|
17703
|
+
} catch (error) {
|
|
17704
|
+
this.logger?.error("[CloudAgentProvider] getInstalledPlugins failed:", error);
|
|
17705
|
+
throw error;
|
|
17706
|
+
}
|
|
17707
|
+
}
|
|
17708
|
+
/**
|
|
17709
|
+
* 安装插件
|
|
17710
|
+
* POST /console/as/user/plugins/install
|
|
17711
|
+
*
|
|
17712
|
+
* @param pluginNames - 插件名称数组
|
|
17713
|
+
* @param marketplaceNameOrId - 市场名称或 ID
|
|
17714
|
+
*/
|
|
17715
|
+
async installPlugins(pluginNames, marketplaceNameOrId, installScope, marketplaceSource, workspacePath) {
|
|
17716
|
+
try {
|
|
17717
|
+
const marketplaceId = await this.findMarketplaceId(marketplaceNameOrId);
|
|
17718
|
+
if (!marketplaceId) return {
|
|
17719
|
+
success: false,
|
|
17720
|
+
error: `Marketplace not found: ${marketplaceNameOrId}`
|
|
17721
|
+
};
|
|
17722
|
+
const failed = (await Promise.allSettled(pluginNames.map((pluginName) => httpService.post("/console/as/user/plugins/install", {
|
|
17723
|
+
plugin_name: pluginName,
|
|
17724
|
+
marketplace_id: marketplaceId,
|
|
17725
|
+
version: "latest"
|
|
17726
|
+
})))).filter((r) => r.status === "rejected");
|
|
17727
|
+
if (failed.length > 0) {
|
|
17728
|
+
const errors = failed.map((r) => r.reason?.message || "Unknown error");
|
|
17729
|
+
return {
|
|
17730
|
+
success: false,
|
|
17731
|
+
error: `安装失败 ${failed.length} 个插件: ${errors.join(", ")}`
|
|
17732
|
+
};
|
|
17733
|
+
}
|
|
17734
|
+
return { success: true };
|
|
17735
|
+
} catch (error) {
|
|
17736
|
+
return {
|
|
17737
|
+
success: false,
|
|
17738
|
+
error: this.extractErrorMessage(error)
|
|
17739
|
+
};
|
|
17740
|
+
}
|
|
17741
|
+
}
|
|
17742
|
+
/**
|
|
17743
|
+
* 卸载插件
|
|
17744
|
+
* POST /console/as/user/plugins/installed/:id/uninstall
|
|
17745
|
+
*
|
|
17746
|
+
* 完整链路:
|
|
17747
|
+
* CloudAgentProvider.uninstallPlugin()
|
|
17748
|
+
* -> HTTP POST /console/as/user/plugins/installed/:id/uninstall
|
|
17749
|
+
* -> agentserver: PluginInstallService.Uninstall()
|
|
17750
|
+
* -> 软删除 DB + 异步同步到活跃沙箱
|
|
17751
|
+
*
|
|
17752
|
+
* @param pluginName - 插件名称
|
|
17753
|
+
* @param marketplaceName - 市场名称(用于标识唯一插件)
|
|
17754
|
+
* @param scope - 卸载范围 ('user' | 'project' | 'project-local')
|
|
17755
|
+
*/
|
|
17756
|
+
async uninstallPlugin(pluginName, marketplaceName, scope) {
|
|
17757
|
+
try {
|
|
17758
|
+
const installId = await this.findPluginInstallId(pluginName);
|
|
17759
|
+
if (!installId) return {
|
|
17760
|
+
success: false,
|
|
17761
|
+
error: `Plugin not found or not installed: ${pluginName}`
|
|
17762
|
+
};
|
|
17763
|
+
await httpService.post(`/console/as/user/plugins/installed/${installId}/uninstall`);
|
|
17764
|
+
return { success: true };
|
|
17765
|
+
} catch (error) {
|
|
17766
|
+
return {
|
|
17767
|
+
success: false,
|
|
17768
|
+
error: this.extractErrorMessage(error)
|
|
17769
|
+
};
|
|
17770
|
+
}
|
|
17771
|
+
}
|
|
17772
|
+
/**
|
|
17773
|
+
* 获取插件市场列表
|
|
17774
|
+
* GET /console/as/marketplace/sources
|
|
17775
|
+
*/
|
|
17776
|
+
async getPluginMarketplaces(forceRefresh) {
|
|
17777
|
+
try {
|
|
17778
|
+
const result = ((await httpService.get("/console/as/marketplace/sources")).data?.sources || []).map((src) => ({
|
|
17779
|
+
id: src.id,
|
|
17780
|
+
name: src.name,
|
|
17781
|
+
type: this.mapSourceType(src.source_type),
|
|
17782
|
+
source: { url: src.url },
|
|
17783
|
+
description: src.name,
|
|
17784
|
+
isBuiltin: src.is_default
|
|
17785
|
+
}));
|
|
17786
|
+
result.forEach((m) => {
|
|
17787
|
+
const marketplaceInfo = {
|
|
17788
|
+
id: m.id,
|
|
17789
|
+
name: m.name
|
|
17790
|
+
};
|
|
17791
|
+
this.marketplaceCache.set(m.name, marketplaceInfo);
|
|
17792
|
+
this.marketplaceCache.set(m.id, marketplaceInfo);
|
|
17793
|
+
});
|
|
17794
|
+
return result;
|
|
17795
|
+
} catch (error) {
|
|
17796
|
+
this.logger?.error("[CloudAgentProvider] getPluginMarketplaces failed:", error);
|
|
17797
|
+
throw error;
|
|
17798
|
+
}
|
|
17799
|
+
}
|
|
17800
|
+
/**
|
|
17801
|
+
* 获取市场下的插件列表
|
|
17802
|
+
* - 有 searchText: GET /console/as/marketplace/plugins/search (跨所有市场搜索)
|
|
17803
|
+
* - 无 searchText: GET /console/as/marketplace/plugins (指定市场)
|
|
17804
|
+
*
|
|
17805
|
+
* @param marketplaceNameOrId - 市场名称或 ID(优先使用 ID,如果是名称则从缓存查询 ID)
|
|
17806
|
+
* @param forceRefresh - 是否强制刷新
|
|
17807
|
+
* @param searchText - 搜索关键字(如果提供,则跨所有市场搜索)
|
|
17808
|
+
*/
|
|
17809
|
+
async getMarketplacePlugins(marketplaceNameOrId, forceRefresh, searchText) {
|
|
17810
|
+
try {
|
|
17811
|
+
if (searchText) return ((await httpService.get("/console/as/marketplace/plugins/search", { params: {
|
|
17812
|
+
q: searchText,
|
|
17813
|
+
page: 1,
|
|
17814
|
+
page_size: 100
|
|
17815
|
+
} })).data?.plugins || []).map((p) => this.mapPluginData(p));
|
|
17816
|
+
const sourceId = await this.findMarketplaceId(marketplaceNameOrId);
|
|
17817
|
+
if (!sourceId) {
|
|
17818
|
+
this.logger?.warn(`[CloudAgentProvider] Marketplace not found: ${marketplaceNameOrId}`);
|
|
17819
|
+
return [];
|
|
17820
|
+
}
|
|
17821
|
+
const params = {
|
|
17822
|
+
source_id: sourceId,
|
|
17823
|
+
page: 1,
|
|
17824
|
+
page_size: 100
|
|
17825
|
+
};
|
|
17826
|
+
return ((await httpService.get("/console/as/marketplace/plugins", { params })).data?.plugins || []).map((p) => this.mapPluginData(p));
|
|
17827
|
+
} catch (error) {
|
|
17828
|
+
this.logger?.error("[CloudAgentProvider] getMarketplacePlugins failed:", error);
|
|
17829
|
+
throw error;
|
|
17830
|
+
}
|
|
17831
|
+
}
|
|
17832
|
+
/**
|
|
17833
|
+
* 获取插件详情
|
|
17834
|
+
* GET /console/as/marketplace/plugins/:name/detail
|
|
17835
|
+
*
|
|
17836
|
+
* @param pluginName - 插件名称
|
|
17837
|
+
* @param marketplaceNameOrId - 市场名称或 ID(优先使用 ID,如果是名称则从缓存查询 ID)
|
|
17838
|
+
*/
|
|
17839
|
+
async getPluginDetail(pluginName, marketplaceNameOrId) {
|
|
17840
|
+
try {
|
|
17841
|
+
const sourceId = await this.findMarketplaceId(marketplaceNameOrId);
|
|
17842
|
+
if (!sourceId) {
|
|
17843
|
+
this.logger?.warn(`[CloudAgentProvider] Marketplace not found: ${marketplaceNameOrId}`);
|
|
17844
|
+
return null;
|
|
17845
|
+
}
|
|
17846
|
+
const p = (await httpService.get(`/console/as/marketplace/plugins/${pluginName}/detail`, { params: { source_id: sourceId } })).data?.plugin;
|
|
17847
|
+
if (!p) return null;
|
|
17848
|
+
const capabilities = p.capabilities ? this.parseCapabilities(p.capabilities) : {};
|
|
17849
|
+
const tags = p.tags ? JSON.parse(p.tags) : [];
|
|
17850
|
+
return {
|
|
17851
|
+
name: p.name,
|
|
17852
|
+
marketplaceName: p.marketplace_name,
|
|
17853
|
+
description: p.description,
|
|
17854
|
+
version: p.version,
|
|
17855
|
+
iconUrl: p.icon_url,
|
|
17856
|
+
tags,
|
|
17857
|
+
installed: p.installed,
|
|
17858
|
+
status: p.enabled ? "enabled" : p.installed ? "disabled" : "not-installed",
|
|
17859
|
+
readme: p.readme,
|
|
17860
|
+
author: p.author,
|
|
17861
|
+
homepage: p.homepage,
|
|
17862
|
+
repositoryUrl: p.repository_url,
|
|
17863
|
+
license: p.license,
|
|
17864
|
+
...capabilities
|
|
17865
|
+
};
|
|
17866
|
+
} catch (error) {
|
|
17867
|
+
this.logger?.error("[CloudAgentProvider] getPluginDetail failed:", error);
|
|
17868
|
+
throw error;
|
|
17869
|
+
}
|
|
17870
|
+
}
|
|
17871
|
+
/**
|
|
17872
|
+
* 添加插件市场
|
|
17873
|
+
* POST /console/as/marketplace/sources
|
|
17874
|
+
*/
|
|
17875
|
+
async addPluginMarketplace(sourceUrl, name) {
|
|
17876
|
+
try {
|
|
17877
|
+
const body = {
|
|
17878
|
+
source_type: sourceUrl.startsWith("http") ? "url" : "github",
|
|
17879
|
+
url: sourceUrl,
|
|
17880
|
+
name: name || sourceUrl
|
|
17881
|
+
};
|
|
17882
|
+
const sourceData = (await httpService.post("/console/as/marketplace/sources", body)).data?.source;
|
|
17883
|
+
if (!sourceData) throw new Error("Invalid response from server");
|
|
17884
|
+
const marketplaceInfo = {
|
|
17885
|
+
id: sourceData.id,
|
|
17886
|
+
name: sourceData.name
|
|
17887
|
+
};
|
|
17888
|
+
this.marketplaceCache.set(sourceData.name, marketplaceInfo);
|
|
17889
|
+
this.marketplaceCache.set(sourceData.id, marketplaceInfo);
|
|
17890
|
+
return {
|
|
17891
|
+
success: true,
|
|
17892
|
+
marketplace: {
|
|
17893
|
+
id: sourceData.id,
|
|
17894
|
+
name: sourceData.name,
|
|
17895
|
+
type: this.mapSourceType(sourceData.source_type),
|
|
17896
|
+
source: { url: sourceData.url },
|
|
17897
|
+
isBuiltin: sourceData.is_default
|
|
17898
|
+
}
|
|
17899
|
+
};
|
|
17900
|
+
} catch (error) {
|
|
17901
|
+
return {
|
|
17902
|
+
success: false,
|
|
17903
|
+
error: this.extractErrorMessage(error)
|
|
17904
|
+
};
|
|
17905
|
+
}
|
|
17906
|
+
}
|
|
17907
|
+
/**
|
|
17908
|
+
* 删除插件市场
|
|
17909
|
+
* POST /console/as/marketplace/sources/:id/delete
|
|
17910
|
+
*/
|
|
17911
|
+
async removePluginMarketplace(marketplaceNameOrId) {
|
|
17912
|
+
try {
|
|
17913
|
+
const marketplaceId = await this.findMarketplaceId(marketplaceNameOrId);
|
|
17914
|
+
if (!marketplaceId) return {
|
|
17915
|
+
success: false,
|
|
17916
|
+
error: `Marketplace not found: ${marketplaceNameOrId}`
|
|
17917
|
+
};
|
|
17918
|
+
await httpService.post(`/console/as/marketplace/sources/${marketplaceId}/delete`, {});
|
|
17919
|
+
return { success: true };
|
|
17920
|
+
} catch (error) {
|
|
17921
|
+
return {
|
|
17922
|
+
success: false,
|
|
17923
|
+
error: this.extractErrorMessage(error)
|
|
17924
|
+
};
|
|
17925
|
+
}
|
|
17926
|
+
}
|
|
17927
|
+
/**
|
|
17928
|
+
* 刷新插件市场
|
|
17929
|
+
* POST /console/as/marketplace/sources/:id/check-updates
|
|
17930
|
+
*/
|
|
17931
|
+
async refreshPluginMarketplace(marketplaceNameOrId) {
|
|
17932
|
+
try {
|
|
17933
|
+
const marketplaceId = await this.findMarketplaceId(marketplaceNameOrId);
|
|
17934
|
+
if (!marketplaceId) return {
|
|
17935
|
+
success: false,
|
|
17936
|
+
error: `Marketplace not found: ${marketplaceNameOrId}`
|
|
17937
|
+
};
|
|
17938
|
+
return {
|
|
17939
|
+
success: true,
|
|
17940
|
+
plugins: (await httpService.post(`/console/as/marketplace/sources/${marketplaceId}/check-updates`, {})).data?.updated_plugins || []
|
|
17941
|
+
};
|
|
17942
|
+
} catch (error) {
|
|
17943
|
+
return {
|
|
17944
|
+
success: false,
|
|
17945
|
+
error: this.extractErrorMessage(error)
|
|
17946
|
+
};
|
|
17947
|
+
}
|
|
17948
|
+
}
|
|
17949
|
+
/**
|
|
17950
|
+
* 批量切换插件启用/禁用状态
|
|
17951
|
+
* POST /console/as/user/plugins/installed/:id/toggle
|
|
17952
|
+
*/
|
|
17953
|
+
async batchTogglePlugins(request) {
|
|
17954
|
+
try {
|
|
17955
|
+
const results = await Promise.allSettled(request.items.map(async (item) => {
|
|
17956
|
+
const installId = await this.findPluginInstallId(item.pluginName);
|
|
17957
|
+
if (!installId) throw new Error(`Plugin not found or not installed: ${item.pluginName}`);
|
|
17958
|
+
const enabled = item.operation === "enable";
|
|
17959
|
+
await httpService.post(`/console/as/user/plugins/installed/${installId}/toggle`, { enabled });
|
|
17960
|
+
return item;
|
|
17961
|
+
}));
|
|
17962
|
+
const succeededPlugins = [];
|
|
17963
|
+
const failedPlugins = [];
|
|
17964
|
+
results.forEach((r, i) => {
|
|
17965
|
+
const item = request.items[i];
|
|
17966
|
+
if (r.status === "fulfilled") succeededPlugins.push(item);
|
|
17967
|
+
else failedPlugins.push({
|
|
17968
|
+
...item,
|
|
17969
|
+
error: r.reason?.message || "Unknown error"
|
|
17970
|
+
});
|
|
17971
|
+
});
|
|
17972
|
+
return {
|
|
17973
|
+
success: failedPlugins.length === 0,
|
|
17974
|
+
succeededPlugins,
|
|
17975
|
+
failedPlugins
|
|
17976
|
+
};
|
|
17977
|
+
} catch (error) {
|
|
17978
|
+
return {
|
|
17979
|
+
success: false,
|
|
17980
|
+
succeededPlugins: [],
|
|
17981
|
+
failedPlugins: request.items.map((item) => ({
|
|
17982
|
+
...item,
|
|
17983
|
+
error: this.extractErrorMessage(error)
|
|
17984
|
+
}))
|
|
17985
|
+
};
|
|
17986
|
+
}
|
|
17987
|
+
}
|
|
17988
|
+
/**
|
|
17989
|
+
* 将后端插件数据映射为前端格式
|
|
17990
|
+
*/
|
|
17991
|
+
mapPluginData(p) {
|
|
17992
|
+
const capabilities = p.capabilities ? this.parseCapabilities(p.capabilities) : {};
|
|
17993
|
+
let tags = [];
|
|
17994
|
+
if (p.tags) {
|
|
17995
|
+
if (Array.isArray(p.tags)) tags = p.tags;
|
|
17996
|
+
else if (typeof p.tags === "string") try {
|
|
17997
|
+
const parsed = JSON.parse(p.tags);
|
|
17998
|
+
tags = Array.isArray(parsed) ? parsed : [parsed];
|
|
17999
|
+
} catch {
|
|
18000
|
+
tags = p.tags.split(",").map((t) => t.trim()).filter((t) => t);
|
|
18001
|
+
}
|
|
18002
|
+
}
|
|
18003
|
+
return {
|
|
18004
|
+
name: p.name,
|
|
18005
|
+
marketplaceName: p.marketplace_name,
|
|
18006
|
+
description: p.description,
|
|
18007
|
+
version: p.version,
|
|
18008
|
+
iconUrl: p.icon_url,
|
|
18009
|
+
tags,
|
|
18010
|
+
installed: p.installed,
|
|
18011
|
+
status: p.enabled ? "enabled" : p.installed ? "disabled" : "not-installed",
|
|
18012
|
+
installedScopes: p.installed ? [p.installed_scope] : [],
|
|
18013
|
+
...capabilities
|
|
18014
|
+
};
|
|
18015
|
+
}
|
|
18016
|
+
/**
|
|
18017
|
+
* 从缓存中查找插件的 install_id
|
|
18018
|
+
* 如果缓存未命中,则调用 API 获取并缓存
|
|
18019
|
+
*
|
|
18020
|
+
* @param pluginName - 插件名称
|
|
18021
|
+
* @returns install_id 或 null
|
|
18022
|
+
*/
|
|
18023
|
+
async findPluginInstallId(pluginName) {
|
|
18024
|
+
const cached = this.pluginCache.get(pluginName);
|
|
18025
|
+
if (cached) return cached.installId;
|
|
18026
|
+
await this.getInstalledPlugins();
|
|
18027
|
+
return this.pluginCache.get(pluginName)?.installId || null;
|
|
18028
|
+
}
|
|
18029
|
+
/**
|
|
18030
|
+
* 从缓存中查找 marketplace ID
|
|
18031
|
+
* 如果缓存未命中,则调用 API 获取并缓存
|
|
18032
|
+
*/
|
|
18033
|
+
async findMarketplaceId(nameOrId) {
|
|
18034
|
+
const cached = this.marketplaceCache.get(nameOrId);
|
|
18035
|
+
if (cached) return cached.id;
|
|
18036
|
+
await this.getPluginMarketplaces();
|
|
18037
|
+
return this.marketplaceCache.get(nameOrId)?.id || null;
|
|
18038
|
+
}
|
|
18039
|
+
/**
|
|
18040
|
+
* 提取 API 错误信息
|
|
18041
|
+
* 从 AxiosError 中提取详细的错误信息,包括 HTTP 状态码、错误码和错误消息
|
|
18042
|
+
*/
|
|
18043
|
+
extractErrorMessage(error) {
|
|
18044
|
+
if (error instanceof AxiosError) {
|
|
18045
|
+
const status = error.response?.status;
|
|
18046
|
+
const apiResponse = error.response?.data;
|
|
18047
|
+
const parts = [];
|
|
18048
|
+
if (status) parts.push(`HTTP ${status}`);
|
|
18049
|
+
if (apiResponse?.code) parts.push(`Code ${apiResponse.code}`);
|
|
18050
|
+
if (apiResponse?.msg) parts.push(apiResponse.msg);
|
|
18051
|
+
else if (error.message) parts.push(error.message);
|
|
18052
|
+
const errorMessage = parts.join(" - ");
|
|
18053
|
+
this.logger?.error("[CloudAgentProvider] API Error:", {
|
|
18054
|
+
status,
|
|
18055
|
+
code: apiResponse?.code,
|
|
18056
|
+
msg: apiResponse?.msg,
|
|
18057
|
+
requestId: apiResponse?.requestId,
|
|
18058
|
+
url: error.config?.url,
|
|
18059
|
+
method: error.config?.method
|
|
18060
|
+
});
|
|
18061
|
+
return errorMessage;
|
|
18062
|
+
}
|
|
18063
|
+
if (error instanceof Error) return error.message;
|
|
18064
|
+
return "Unknown error";
|
|
18065
|
+
}
|
|
18066
|
+
/**
|
|
18067
|
+
* 映射后端 source_type 到前端类型
|
|
18068
|
+
*/
|
|
18069
|
+
mapSourceType(sourceType) {
|
|
18070
|
+
switch (sourceType) {
|
|
18071
|
+
case "github": return "github";
|
|
18072
|
+
case "official": return "custom";
|
|
18073
|
+
default: return "custom";
|
|
18074
|
+
}
|
|
18075
|
+
}
|
|
18076
|
+
/**
|
|
18077
|
+
* 解析 capabilities JSON 字符串
|
|
18078
|
+
*/
|
|
18079
|
+
parseCapabilities(capabilitiesStr) {
|
|
18080
|
+
try {
|
|
18081
|
+
const cap = JSON.parse(capabilitiesStr);
|
|
18082
|
+
return {
|
|
18083
|
+
commands: cap.commands,
|
|
18084
|
+
skills: cap.skills,
|
|
18085
|
+
mcpServers: cap.mcp,
|
|
18086
|
+
agents: cap.agents,
|
|
18087
|
+
hooks: cap.hooks,
|
|
18088
|
+
rules: cap.rules
|
|
18089
|
+
};
|
|
18090
|
+
} catch {
|
|
18091
|
+
return {};
|
|
18092
|
+
}
|
|
18093
|
+
}
|
|
18094
|
+
/**
|
|
18095
|
+
* 上报 telemetry 事件(Cloud 模式)
|
|
18096
|
+
* 通过 HTTP POST 发送到 /v2/report
|
|
18097
|
+
* 注入用户信息和浏览器环境等公共字段
|
|
18098
|
+
*/
|
|
18099
|
+
async reportTelemetry(eventName, payload) {
|
|
18100
|
+
try {
|
|
18101
|
+
const account = accountService.getAccount();
|
|
18102
|
+
const commonFields = {};
|
|
18103
|
+
if (account) {
|
|
18104
|
+
commonFields.userId = account.uid;
|
|
18105
|
+
commonFields.userNickname = account.nickname;
|
|
18106
|
+
if (account.enterpriseId) commonFields.enterpriseId = account.enterpriseId;
|
|
18107
|
+
if (account.enterpriseUserName) commonFields.username = account.enterpriseUserName;
|
|
18108
|
+
}
|
|
18109
|
+
if (typeof navigator !== "undefined") {
|
|
18110
|
+
commonFields.userAgent = navigator.userAgent;
|
|
18111
|
+
commonFields.os = navigator.platform;
|
|
18112
|
+
}
|
|
18113
|
+
const events = [{
|
|
18114
|
+
eventCode: eventName,
|
|
18115
|
+
timestamp: Date.now(),
|
|
18116
|
+
reportDelay: 0,
|
|
18117
|
+
...commonFields,
|
|
18118
|
+
...payload
|
|
18119
|
+
}];
|
|
18120
|
+
await httpService.post("/v2/report", events);
|
|
18121
|
+
} catch (error) {
|
|
18122
|
+
this.logger?.warn("reportTelemetry() failed:", error);
|
|
18123
|
+
}
|
|
18124
|
+
}
|
|
18125
|
+
};
|
|
18126
|
+
|
|
18127
|
+
//#endregion
|
|
18128
|
+
//#region ../agent-provider/src/common/providers/local-agent-provider/local-connection.ts
|
|
18129
|
+
/**
|
|
18130
|
+
* Local Agent Connection
|
|
18131
|
+
* Wraps AcpJsonRpcClient to implement AgentConnection interface
|
|
18132
|
+
*
|
|
18133
|
+
* Uses IWidgetChannel for IPC communication with ExtensionHost
|
|
18134
|
+
* Migrated from ipc-agent-provider for unified local agent access
|
|
18135
|
+
*/
|
|
18136
|
+
|
|
18137
|
+
//#endregion
|
|
18138
|
+
//#region ../agent-provider/src/common/client/session.ts
|
|
18139
|
+
/**
|
|
18140
|
+
* ActiveSessionImpl - Implements the ActiveSession interface
|
|
18141
|
+
*
|
|
18142
|
+
* This class wraps an AgentConnection and provides the session-centric API.
|
|
18143
|
+
* It is created by SessionManager when creating or loading sessions.
|
|
18144
|
+
*
|
|
18145
|
+
* @example
|
|
18146
|
+
* ```typescript
|
|
18147
|
+
* // Created by client.sessions.new() or client.sessions.load()
|
|
18148
|
+
* const session = await client.sessions.new({ cwd: '/workspace' });
|
|
18149
|
+
*
|
|
18150
|
+
* // Access agent state
|
|
18151
|
+
* console.log(session.agentState.status);
|
|
18152
|
+
*
|
|
18153
|
+
* // Send prompt
|
|
18154
|
+
* const response = await session.prompts.send({ content: 'Hello!' });
|
|
18155
|
+
*
|
|
18156
|
+
* // Cleanup
|
|
18157
|
+
* session.disconnect();
|
|
18158
|
+
* ```
|
|
18159
|
+
*/
|
|
18160
|
+
var ActiveSessionImpl = class {
|
|
18161
|
+
/**
|
|
18162
|
+
* Create an ActiveSessionImpl instance
|
|
18163
|
+
*
|
|
18164
|
+
* @param sessionId - Session ID
|
|
18165
|
+
* @param agentId - Agent ID
|
|
18166
|
+
* @param connection - Already connected AgentConnection
|
|
18167
|
+
* @param options - Additional options
|
|
18168
|
+
*/
|
|
18169
|
+
constructor(sessionId, agentId, connection, options = {}) {
|
|
18170
|
+
this._availableCommands = [];
|
|
18171
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
18172
|
+
this.onceListeners = /* @__PURE__ */ new Map();
|
|
18173
|
+
this.connectionListeners = [];
|
|
18174
|
+
this._id = sessionId;
|
|
18175
|
+
this._agentId = agentId;
|
|
18176
|
+
this.connection = connection;
|
|
17439
18177
|
this.logger = options.logger;
|
|
17440
18178
|
this._getFilesystem = options.getFilesystem;
|
|
17441
18179
|
this._connectionInfo = options.connectionInfo;
|
|
@@ -17458,6 +18196,18 @@ var ActiveSessionImpl = class {
|
|
|
17458
18196
|
return this._agentId;
|
|
17459
18197
|
}
|
|
17460
18198
|
/**
|
|
18199
|
+
* Actual workspace path (set from newSession response _meta)
|
|
18200
|
+
*/
|
|
18201
|
+
get cwd() {
|
|
18202
|
+
return this._cwd;
|
|
18203
|
+
}
|
|
18204
|
+
/**
|
|
18205
|
+
* Set actual workspace path (called by SessionManager after createSession)
|
|
18206
|
+
*/
|
|
18207
|
+
setCwd(cwd) {
|
|
18208
|
+
this._cwd = cwd;
|
|
18209
|
+
}
|
|
18210
|
+
/**
|
|
17461
18211
|
* Agent state (live connection state)
|
|
17462
18212
|
* Returns LocalAgentState or CloudAgentState based on transport type
|
|
17463
18213
|
*/
|
|
@@ -17651,10 +18401,10 @@ var ActiveSessionImpl = class {
|
|
|
17651
18401
|
return this.connection.cancelQuestion(toolCallId, reason);
|
|
17652
18402
|
}
|
|
17653
18403
|
/**
|
|
17654
|
-
* Callback for tool operations (skip
|
|
18404
|
+
* Callback for tool operations (approve / skip / cancel)
|
|
17655
18405
|
* @param toolCallId Tool call ID
|
|
17656
18406
|
* @param toolName Tool name
|
|
17657
|
-
* @param action Action to perform ('skip'
|
|
18407
|
+
* @param action Action to perform ('approve' / 'skip' / 'cancel')
|
|
17658
18408
|
*/
|
|
17659
18409
|
async toolCallback(toolCallId, toolName, action) {
|
|
17660
18410
|
return await this.getConnectionOrThrow().toolCallback(this._id, toolCallId, toolName, action);
|
|
@@ -17698,6 +18448,7 @@ var ActiveSessionImpl = class {
|
|
|
17698
18448
|
* ```
|
|
17699
18449
|
*/
|
|
17700
18450
|
async setSessionModel(modelId) {
|
|
18451
|
+
this._currentModelId = modelId;
|
|
17701
18452
|
await this.getConnectionOrThrow().setSessionModel(this._id, modelId);
|
|
17702
18453
|
}
|
|
17703
18454
|
/**
|
|
@@ -17775,11 +18526,23 @@ var ActiveSessionImpl = class {
|
|
|
17775
18526
|
* Disconnect from the session/agent
|
|
17776
18527
|
*/
|
|
17777
18528
|
disconnect() {
|
|
18529
|
+
this.removeConnectionListeners();
|
|
17778
18530
|
this.connection.disconnect();
|
|
17779
18531
|
this.removeAllListeners();
|
|
17780
18532
|
this.logger?.info(`Session ${this._id}: Disconnected`);
|
|
17781
18533
|
}
|
|
17782
18534
|
/**
|
|
18535
|
+
* Detach the session from connection events without disconnecting the connection.
|
|
18536
|
+
* This should be called when the session is being replaced but the connection is shared.
|
|
18537
|
+
* Unlike disconnect(), this only removes event listeners without closing the connection.
|
|
18538
|
+
*/
|
|
18539
|
+
detach() {
|
|
18540
|
+
this.logger?.info(`Session ${this._id}: Detaching from connection events`);
|
|
18541
|
+
this.removeConnectionListeners();
|
|
18542
|
+
this.removeAllListeners();
|
|
18543
|
+
this.logger?.info(`Session ${this._id}: Detached successfully`);
|
|
18544
|
+
}
|
|
18545
|
+
/**
|
|
17783
18546
|
* Symbol.dispose for 'using' keyword support
|
|
17784
18547
|
* Automatically disconnects and cleans up when session goes out of scope
|
|
17785
18548
|
*
|
|
@@ -17798,60 +18561,85 @@ var ActiveSessionImpl = class {
|
|
|
17798
18561
|
if (!this.connection.isInitialized) throw new Error(`Session ${this._id}: Connection not initialized.`);
|
|
17799
18562
|
return this.connection;
|
|
17800
18563
|
}
|
|
18564
|
+
/**
|
|
18565
|
+
* 在 connection 上注册 listener 并保存引用,便于 disconnect 时移除
|
|
18566
|
+
*/
|
|
18567
|
+
addConnectionListener(connection, event, listener) {
|
|
18568
|
+
connection.on(event, listener);
|
|
18569
|
+
this.connectionListeners.push({
|
|
18570
|
+
event,
|
|
18571
|
+
listener
|
|
18572
|
+
});
|
|
18573
|
+
}
|
|
18574
|
+
/**
|
|
18575
|
+
* 从 connection 上移除所有本 session 注册的 listener
|
|
18576
|
+
*/
|
|
18577
|
+
removeConnectionListeners() {
|
|
18578
|
+
for (const { event, listener } of this.connectionListeners) this.connection.off(event, listener);
|
|
18579
|
+
this.connectionListeners = [];
|
|
18580
|
+
}
|
|
17801
18581
|
setupConnectionEvents(connection) {
|
|
17802
|
-
|
|
18582
|
+
this.addConnectionListener(connection, "connected", () => {
|
|
17803
18583
|
this.emit("connected", void 0);
|
|
17804
18584
|
});
|
|
17805
|
-
|
|
18585
|
+
this.addConnectionListener(connection, "disconnected", () => {
|
|
17806
18586
|
this.emit("disconnected", void 0);
|
|
17807
18587
|
});
|
|
17808
|
-
|
|
18588
|
+
this.addConnectionListener(connection, "error", (error) => {
|
|
17809
18589
|
this.emit("error", error);
|
|
17810
18590
|
});
|
|
17811
|
-
|
|
18591
|
+
this.addConnectionListener(connection, "sessionUpdate", (update) => {
|
|
18592
|
+
const notificationSessionId = update?.sessionId;
|
|
18593
|
+
if (notificationSessionId && notificationSessionId !== this._id) {
|
|
18594
|
+
console.log(`[RT-DEBUG][AgentMgr:Session] sessionUpdate SKIPPED: notifSessionId mismatch, notif=${notificationSessionId?.substring(0, 8)}, my=${this._id?.substring(0, 8)}`);
|
|
18595
|
+
return;
|
|
18596
|
+
}
|
|
17812
18597
|
this.emit("sessionUpdate", update);
|
|
17813
18598
|
});
|
|
17814
|
-
|
|
17815
|
-
|
|
17816
|
-
artifactUri: artifact.uri,
|
|
17817
|
-
artifactType: artifact.type
|
|
17818
|
-
});
|
|
18599
|
+
this.addConnectionListener(connection, "artifactCreated", (artifact) => {
|
|
18600
|
+
if (!this.shouldForwardArtifact(artifact)) return;
|
|
17819
18601
|
this.emit("artifactCreated", artifact);
|
|
17820
18602
|
});
|
|
17821
|
-
|
|
17822
|
-
|
|
17823
|
-
artifactUri: artifact.uri,
|
|
17824
|
-
artifactType: artifact.type
|
|
17825
|
-
});
|
|
18603
|
+
this.addConnectionListener(connection, "artifactUpdated", (artifact) => {
|
|
18604
|
+
if (!this.shouldForwardArtifact(artifact)) return;
|
|
17826
18605
|
this.emit("artifactUpdated", artifact);
|
|
17827
18606
|
});
|
|
17828
|
-
|
|
17829
|
-
|
|
18607
|
+
this.addConnectionListener(connection, "artifactDeleted", (artifact) => {
|
|
18608
|
+
if (!this.shouldForwardArtifact(artifact)) return;
|
|
17830
18609
|
this.emit("artifactDeleted", artifact);
|
|
17831
18610
|
});
|
|
17832
|
-
|
|
18611
|
+
this.addConnectionListener(connection, "permissionRequest", (request) => {
|
|
17833
18612
|
this.emit("permissionRequest", request);
|
|
17834
18613
|
});
|
|
17835
|
-
|
|
18614
|
+
this.addConnectionListener(connection, "questionRequest", (request) => {
|
|
17836
18615
|
this.emit("questionRequest", request);
|
|
17837
18616
|
});
|
|
17838
|
-
|
|
18617
|
+
this.addConnectionListener(connection, "questionCancelled", () => {
|
|
17839
18618
|
this.prompts.cancel();
|
|
17840
18619
|
});
|
|
17841
|
-
|
|
18620
|
+
this.addConnectionListener(connection, "usageUpdate", (usage) => {
|
|
17842
18621
|
this.emit("usageUpdate", usage);
|
|
17843
18622
|
});
|
|
17844
|
-
|
|
18623
|
+
this.addConnectionListener(connection, "checkpointCreated", (checkpoint) => {
|
|
18624
|
+
const originSessionId = checkpoint.__sessionId;
|
|
18625
|
+
if (originSessionId && originSessionId !== this._id) return;
|
|
17845
18626
|
this.emit("checkpointCreated", checkpoint);
|
|
17846
18627
|
});
|
|
17847
|
-
|
|
18628
|
+
this.addConnectionListener(connection, "checkpointUpdated", (checkpoint) => {
|
|
18629
|
+
const originSessionId = checkpoint.__sessionId;
|
|
18630
|
+
if (originSessionId && originSessionId !== this._id) return;
|
|
17848
18631
|
this.emit("checkpointUpdated", checkpoint);
|
|
17849
18632
|
});
|
|
17850
|
-
|
|
17851
|
-
|
|
17852
|
-
|
|
17853
|
-
|
|
17854
|
-
|
|
18633
|
+
this.addConnectionListener(connection, "command", (command) => {
|
|
18634
|
+
const originSessionId = command.__sessionId;
|
|
18635
|
+
if (originSessionId && originSessionId !== this._id) {
|
|
18636
|
+
console.log("[Session] Command not forwarded:", {
|
|
18637
|
+
command,
|
|
18638
|
+
originSessionId,
|
|
18639
|
+
sessionId: this._id
|
|
18640
|
+
});
|
|
18641
|
+
return;
|
|
18642
|
+
}
|
|
17855
18643
|
this.emit("command", command);
|
|
17856
18644
|
});
|
|
17857
18645
|
}
|
|
@@ -17861,6 +18649,15 @@ var ActiveSessionImpl = class {
|
|
|
17861
18649
|
_meta: response._meta ?? void 0
|
|
17862
18650
|
};
|
|
17863
18651
|
}
|
|
18652
|
+
/**
|
|
18653
|
+
* 判断 artifact 是否应该转发给当前 session
|
|
18654
|
+
* 所有类型的 artifact 都按 __sessionId 严格隔离
|
|
18655
|
+
*/
|
|
18656
|
+
shouldForwardArtifact(artifact) {
|
|
18657
|
+
const originSessionId = artifact.__sessionId;
|
|
18658
|
+
if (!originSessionId || originSessionId !== this._id) return false;
|
|
18659
|
+
return true;
|
|
18660
|
+
}
|
|
17864
18661
|
};
|
|
17865
18662
|
|
|
17866
18663
|
//#endregion
|
|
@@ -17893,6 +18690,7 @@ var ActiveSessionImpl = class {
|
|
|
17893
18690
|
*/
|
|
17894
18691
|
var SessionManager = class {
|
|
17895
18692
|
constructor(options) {
|
|
18693
|
+
this.pendingConnections = /* @__PURE__ */ new Map();
|
|
17896
18694
|
this.provider = options.provider;
|
|
17897
18695
|
this.logger = options.logger;
|
|
17898
18696
|
}
|
|
@@ -17913,9 +18711,11 @@ var SessionManager = class {
|
|
|
17913
18711
|
name: agent.name,
|
|
17914
18712
|
status: agent.status,
|
|
17915
18713
|
createdAt: agent.createdAt,
|
|
18714
|
+
updatedAt: agent.updatedAt,
|
|
17916
18715
|
lastActivityAt: agent.updatedAt,
|
|
17917
18716
|
cwd: agent.type === "local" ? agent.cwd : void 0,
|
|
17918
|
-
isPlayground: agent.isPlayground
|
|
18717
|
+
isPlayground: agent.isPlayground,
|
|
18718
|
+
isUserDefinedTitle: agent.isUserDefinedTitle
|
|
17919
18719
|
}));
|
|
17920
18720
|
console.log("[SessionManager] Returning sessions:", {
|
|
17921
18721
|
count: sessions.length,
|
|
@@ -17942,27 +18742,107 @@ var SessionManager = class {
|
|
|
17942
18742
|
if (this.provider.create) {
|
|
17943
18743
|
agentId = await this.provider.create(params);
|
|
17944
18744
|
this.logger?.debug(`Created new agent: ${agentId}`);
|
|
18745
|
+
if (params.options?.onSessionPrepared) {
|
|
18746
|
+
const initialPrompt = params.options?.prompt;
|
|
18747
|
+
const initialTitle = initialPrompt?.slice(0, 50) || "";
|
|
18748
|
+
params.options.onSessionPrepared({
|
|
18749
|
+
id: agentId,
|
|
18750
|
+
agentId,
|
|
18751
|
+
name: initialTitle + (initialPrompt && initialPrompt.length > 50 ? "..." : ""),
|
|
18752
|
+
status: "connecting",
|
|
18753
|
+
cwd: params.cwd || "",
|
|
18754
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
18755
|
+
});
|
|
18756
|
+
this.logger?.debug(`Called onSessionPrepared for: ${agentId}`);
|
|
18757
|
+
}
|
|
17945
18758
|
} else throw new Error("Provider does not support creating agents. Use sessions.load() with an existing sessionId.");
|
|
17946
18759
|
const connection = await this.provider.connect(agentId);
|
|
17947
18760
|
this.logger?.debug(`Connected to agent: ${agentId}`);
|
|
17948
|
-
|
|
17949
|
-
|
|
17950
|
-
|
|
17951
|
-
|
|
17952
|
-
|
|
17953
|
-
|
|
17954
|
-
|
|
17955
|
-
|
|
18761
|
+
let response;
|
|
18762
|
+
try {
|
|
18763
|
+
response = await connection.createSession({
|
|
18764
|
+
_meta: params.options?._meta,
|
|
18765
|
+
cwd: params.cwd,
|
|
18766
|
+
mcpServers: params.options?.mcpServers
|
|
18767
|
+
});
|
|
18768
|
+
} catch (err) {
|
|
18769
|
+
this.pendingConnections.set(agentId, connection);
|
|
18770
|
+
this.logger?.debug(`Cached pending connection for agent: ${agentId}`);
|
|
18771
|
+
if (err instanceof SessionError) throw new SessionError(err.message, err.sessionId, agentId, err.cause instanceof Error ? err.cause : void 0);
|
|
18772
|
+
const cause = err instanceof Error ? err : new Error(String(err));
|
|
18773
|
+
throw new SessionError(`Failed to create session: ${cause.message}`, void 0, agentId, cause);
|
|
17956
18774
|
}
|
|
17957
|
-
|
|
17958
|
-
|
|
17959
|
-
|
|
18775
|
+
return this.buildActiveSession(response, agentId, connection, params);
|
|
18776
|
+
}
|
|
18777
|
+
/**
|
|
18778
|
+
* Retry creating a session after initial session/new request failed.
|
|
18779
|
+
*
|
|
18780
|
+
* Use this when `sessions.create()` fails at the `session/new` step
|
|
18781
|
+
* (after agent creation and connection establishment succeeded).
|
|
18782
|
+
* The caller retrieves `agentId` from the thrown `SessionError.agentId`,
|
|
18783
|
+
* then calls this method to re-attempt only the `session/new` request
|
|
18784
|
+
* while reusing the already-initialized connection (no re-connect).
|
|
18785
|
+
*
|
|
18786
|
+
* @experimental This API is subject to change
|
|
18787
|
+
*
|
|
18788
|
+
* @param agentId - Agent ID from the failed SessionError
|
|
18789
|
+
* @param params - Original create session params (cwd, mcpServers, etc.)
|
|
18790
|
+
* @returns ActiveSession on success
|
|
18791
|
+
* @throws SessionError if session/new fails again
|
|
18792
|
+
*
|
|
18793
|
+
* @example
|
|
18794
|
+
* ```typescript
|
|
18795
|
+
* try {
|
|
18796
|
+
* const session = await client.sessions.create({ cwd: '/workspace' });
|
|
18797
|
+
* } catch (err) {
|
|
18798
|
+
* if (err instanceof SessionError && err.agentId) {
|
|
18799
|
+
* // Retry with custom logic
|
|
18800
|
+
* for (let i = 0; i < 3; i++) {
|
|
18801
|
+
* try {
|
|
18802
|
+
* const session = await client.sessions.retryNewSession(err.agentId, { cwd: '/workspace' });
|
|
18803
|
+
* break; // success
|
|
18804
|
+
* } catch (retryErr) {
|
|
18805
|
+
* await new Promise(r => setTimeout(r, 1000 * (i + 1)));
|
|
18806
|
+
* }
|
|
18807
|
+
* }
|
|
18808
|
+
* }
|
|
18809
|
+
* }
|
|
18810
|
+
* ```
|
|
18811
|
+
*/
|
|
18812
|
+
async retryNewSession(agentId, params) {
|
|
18813
|
+
this.logger?.info(`Retrying session/new for agent: ${agentId}`);
|
|
18814
|
+
const connection = this.pendingConnections.get(agentId);
|
|
18815
|
+
if (!connection) throw new SessionError(`No pending connection found for agent: ${agentId}. retryNewSession() can only be called after a failed sessions.create().`, void 0, agentId);
|
|
18816
|
+
this.logger?.debug(`Reusing cached connection for agent: ${agentId}`);
|
|
18817
|
+
const response = await connection.createSession({
|
|
18818
|
+
_meta: params.options?._meta,
|
|
18819
|
+
cwd: params.cwd,
|
|
18820
|
+
mcpServers: params.options?.mcpServers
|
|
18821
|
+
});
|
|
18822
|
+
this.pendingConnections.delete(agentId);
|
|
18823
|
+
this.logger?.debug(`Cleared pending connection for agent: ${agentId}`);
|
|
18824
|
+
return this.buildActiveSession(response, agentId, connection, params);
|
|
18825
|
+
}
|
|
18826
|
+
/**
|
|
18827
|
+
* Build an ActiveSession from a NewSessionResponse.
|
|
18828
|
+
* Shared by createSession() and retryNewSession().
|
|
18829
|
+
*/
|
|
18830
|
+
buildActiveSession(response, agentId, connection, params) {
|
|
18831
|
+
if (this.provider.registerSession) {
|
|
18832
|
+
this.provider.registerSession(response.sessionId, agentId);
|
|
18833
|
+
this.logger?.debug(`Registered session mapping: ${response.sessionId} → ${agentId}`);
|
|
18834
|
+
}
|
|
18835
|
+
const connectionInfo = connection.sessionConnectionInfo;
|
|
18836
|
+
const session = new ActiveSessionImpl(response.sessionId, agentId, connection, {
|
|
18837
|
+
logger: this.logger,
|
|
17960
18838
|
getFilesystem: this.provider.filesystem ? () => this.provider.filesystem.getFilesystem(response.sessionId) : void 0,
|
|
17961
18839
|
connectionInfo
|
|
17962
18840
|
});
|
|
17963
18841
|
session.setModes(response.modes?.availableModes, response.modes?.currentModeId);
|
|
17964
18842
|
const availableModels = this.extractAvailableModels(response);
|
|
17965
18843
|
if (availableModels) session.setModels(availableModels, response.models?.currentModelId);
|
|
18844
|
+
const responseCwd = response._meta?.["codebuddy.ai"]?.cwd;
|
|
18845
|
+
if (responseCwd) session.setCwd(responseCwd);
|
|
17966
18846
|
this.logger?.info(`Session created: ${response.sessionId}`);
|
|
17967
18847
|
return session;
|
|
17968
18848
|
}
|
|
@@ -18091,6 +18971,7 @@ var AgentClient = class {
|
|
|
18091
18971
|
return {
|
|
18092
18972
|
list: async (options) => this.sessionManager.listSessions(options),
|
|
18093
18973
|
create: async (params) => this.sessionManager.createSession(params),
|
|
18974
|
+
retryNewSession: async (agentId, params) => this.sessionManager.retryNewSession(agentId, params),
|
|
18094
18975
|
load: async (params) => {
|
|
18095
18976
|
console.log("[AgentClient] sessions.load called:", params.sessionId);
|
|
18096
18977
|
return this.sessionManager.loadSession(params);
|
|
@@ -18129,6 +19010,26 @@ var AgentClient = class {
|
|
|
18129
19010
|
throw error;
|
|
18130
19011
|
}
|
|
18131
19012
|
},
|
|
19013
|
+
updateStatus: async (sessionId, status) => {
|
|
19014
|
+
this.logger?.debug("AgentClient.sessions.updateStatus called", {
|
|
19015
|
+
sessionId,
|
|
19016
|
+
status
|
|
19017
|
+
});
|
|
19018
|
+
try {
|
|
19019
|
+
if (this.provider.updateStatus) {
|
|
19020
|
+
const result = await this.provider.updateStatus(sessionId, status);
|
|
19021
|
+
this.logger?.info("Session status updated successfully", {
|
|
19022
|
+
sessionId,
|
|
19023
|
+
status
|
|
19024
|
+
});
|
|
19025
|
+
return result;
|
|
19026
|
+
}
|
|
19027
|
+
throw new Error("Provider does not support updateStatus method");
|
|
19028
|
+
} catch (error) {
|
|
19029
|
+
this.logger?.error("Failed to update session status", error);
|
|
19030
|
+
throw error;
|
|
19031
|
+
}
|
|
19032
|
+
},
|
|
18132
19033
|
move: async (sessionId) => {
|
|
18133
19034
|
this.logger?.debug("AgentClient.sessions.move called", { sessionId });
|
|
18134
19035
|
try {
|
|
@@ -18161,6 +19062,16 @@ var AgentClient = class {
|
|
|
18161
19062
|
};
|
|
18162
19063
|
}
|
|
18163
19064
|
},
|
|
19065
|
+
requestYieldAfterCurrentStep: async (sessionId) => {
|
|
19066
|
+
try {
|
|
19067
|
+
if (this.provider?.requestYieldAfterCurrentStep) return await this.provider.requestYieldAfterCurrentStep(sessionId);
|
|
19068
|
+
this.logger?.warn("Provider does not support requestYieldAfterCurrentStep");
|
|
19069
|
+
return false;
|
|
19070
|
+
} catch (error) {
|
|
19071
|
+
this.logger?.error("Failed to request yield after current step", error);
|
|
19072
|
+
return false;
|
|
19073
|
+
}
|
|
19074
|
+
},
|
|
18164
19075
|
getCurrentWorkspaces: async (filter) => {
|
|
18165
19076
|
this.logger?.debug("AgentClient.sessions.getCurrentWorkspaces called", filter);
|
|
18166
19077
|
try {
|
|
@@ -18176,6 +19087,100 @@ var AgentClient = class {
|
|
|
18176
19087
|
return [];
|
|
18177
19088
|
}
|
|
18178
19089
|
},
|
|
19090
|
+
getAutomationSnapshot: async () => {
|
|
19091
|
+
try {
|
|
19092
|
+
if (this.provider?.getAutomationSnapshot) return await this.provider.getAutomationSnapshot();
|
|
19093
|
+
this.logger?.warn("Provider does not support getAutomationSnapshot");
|
|
19094
|
+
} catch (error) {
|
|
19095
|
+
this.logger?.error("Failed to get automation snapshot", error);
|
|
19096
|
+
}
|
|
19097
|
+
return {
|
|
19098
|
+
automations: [],
|
|
19099
|
+
inbox: [],
|
|
19100
|
+
runtimeState: {},
|
|
19101
|
+
updatedAt: Date.now()
|
|
19102
|
+
};
|
|
19103
|
+
},
|
|
19104
|
+
updateAutomation: async (payload) => {
|
|
19105
|
+
try {
|
|
19106
|
+
if (this.provider?.updateAutomation) return await this.provider.updateAutomation(payload);
|
|
19107
|
+
this.logger?.warn("Provider does not support updateAutomation");
|
|
19108
|
+
} catch (error) {
|
|
19109
|
+
this.logger?.error("Failed to update automation", error);
|
|
19110
|
+
return {
|
|
19111
|
+
success: false,
|
|
19112
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
19113
|
+
};
|
|
19114
|
+
}
|
|
19115
|
+
return {
|
|
19116
|
+
success: false,
|
|
19117
|
+
message: "Provider does not support updateAutomation"
|
|
19118
|
+
};
|
|
19119
|
+
},
|
|
19120
|
+
deleteAutomation: async (id) => {
|
|
19121
|
+
try {
|
|
19122
|
+
if (this.provider?.deleteAutomation) return await this.provider.deleteAutomation(id);
|
|
19123
|
+
this.logger?.warn("Provider does not support deleteAutomation");
|
|
19124
|
+
} catch (error) {
|
|
19125
|
+
this.logger?.error("Failed to delete automation", error);
|
|
19126
|
+
return {
|
|
19127
|
+
success: false,
|
|
19128
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
19129
|
+
};
|
|
19130
|
+
}
|
|
19131
|
+
return {
|
|
19132
|
+
success: false,
|
|
19133
|
+
message: "Provider does not support deleteAutomation"
|
|
19134
|
+
};
|
|
19135
|
+
},
|
|
19136
|
+
archiveAutomationInboxItem: async (itemId) => {
|
|
19137
|
+
try {
|
|
19138
|
+
if (this.provider?.archiveAutomationInboxItem) return await this.provider.archiveAutomationInboxItem(itemId);
|
|
19139
|
+
this.logger?.warn("Provider does not support archiveAutomationInboxItem");
|
|
19140
|
+
} catch (error) {
|
|
19141
|
+
this.logger?.error("Failed to archive automation inbox item", error);
|
|
19142
|
+
return {
|
|
19143
|
+
success: false,
|
|
19144
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
19145
|
+
};
|
|
19146
|
+
}
|
|
19147
|
+
return {
|
|
19148
|
+
success: false,
|
|
19149
|
+
message: "Provider does not support archiveAutomationInboxItem"
|
|
19150
|
+
};
|
|
19151
|
+
},
|
|
19152
|
+
deleteAutomationInboxItem: async (itemId) => {
|
|
19153
|
+
try {
|
|
19154
|
+
if (this.provider?.deleteAutomationInboxItem) return await this.provider.deleteAutomationInboxItem(itemId);
|
|
19155
|
+
this.logger?.warn("Provider does not support deleteAutomationInboxItem");
|
|
19156
|
+
} catch (error) {
|
|
19157
|
+
this.logger?.error("Failed to delete automation inbox item", error);
|
|
19158
|
+
return {
|
|
19159
|
+
success: false,
|
|
19160
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
19161
|
+
};
|
|
19162
|
+
}
|
|
19163
|
+
return {
|
|
19164
|
+
success: false,
|
|
19165
|
+
message: "Provider does not support deleteAutomationInboxItem"
|
|
19166
|
+
};
|
|
19167
|
+
},
|
|
19168
|
+
testAutomation: async (id) => {
|
|
19169
|
+
try {
|
|
19170
|
+
if (this.provider?.testAutomation) return await this.provider.testAutomation(id);
|
|
19171
|
+
this.logger?.warn("Provider does not support testAutomation");
|
|
19172
|
+
} catch (error) {
|
|
19173
|
+
this.logger?.error("Failed to test automation", error);
|
|
19174
|
+
return {
|
|
19175
|
+
success: false,
|
|
19176
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
19177
|
+
};
|
|
19178
|
+
}
|
|
19179
|
+
return {
|
|
19180
|
+
success: false,
|
|
19181
|
+
message: "Provider does not support testAutomation"
|
|
19182
|
+
};
|
|
19183
|
+
},
|
|
18179
19184
|
on: (event, handler) => {
|
|
18180
19185
|
if (this.provider.on) this.provider.on(event, handler);
|
|
18181
19186
|
else this.logger?.warn(`Provider does not support event registration: ${String(event)}`);
|
|
@@ -18317,6 +19322,167 @@ var AgentClient = class {
|
|
|
18317
19322
|
};
|
|
18318
19323
|
}
|
|
18319
19324
|
},
|
|
19325
|
+
getSkillList: async (params) => {
|
|
19326
|
+
try {
|
|
19327
|
+
if (this.provider && this.provider.getSkillList) {
|
|
19328
|
+
const result = await this.provider.getSkillList(params);
|
|
19329
|
+
this.logger?.info("Skill list retrieved", {
|
|
19330
|
+
resultCount: result.results.length,
|
|
19331
|
+
hasError: !!result.error
|
|
19332
|
+
});
|
|
19333
|
+
return result;
|
|
19334
|
+
}
|
|
19335
|
+
return {
|
|
19336
|
+
results: [],
|
|
19337
|
+
error: "Provider does not support getSkillList"
|
|
19338
|
+
};
|
|
19339
|
+
} catch (error) {
|
|
19340
|
+
this.logger?.error("Failed to get skill list", error);
|
|
19341
|
+
return {
|
|
19342
|
+
results: [],
|
|
19343
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19344
|
+
};
|
|
19345
|
+
}
|
|
19346
|
+
},
|
|
19347
|
+
importSkill: async (params) => {
|
|
19348
|
+
try {
|
|
19349
|
+
if (this.provider && this.provider.importSkill) {
|
|
19350
|
+
const result = await this.provider.importSkill(params);
|
|
19351
|
+
this.logger?.info("Import skill completed", {
|
|
19352
|
+
success: result.success,
|
|
19353
|
+
hasError: !!result.error
|
|
19354
|
+
});
|
|
19355
|
+
return result;
|
|
19356
|
+
}
|
|
19357
|
+
return {
|
|
19358
|
+
success: false,
|
|
19359
|
+
error: "Provider does not support importSkill"
|
|
19360
|
+
};
|
|
19361
|
+
} catch (error) {
|
|
19362
|
+
this.logger?.error("Failed to import skill", error);
|
|
19363
|
+
return {
|
|
19364
|
+
success: false,
|
|
19365
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19366
|
+
};
|
|
19367
|
+
}
|
|
19368
|
+
},
|
|
19369
|
+
toggleSkill: async (params) => {
|
|
19370
|
+
try {
|
|
19371
|
+
if (this.provider && this.provider.toggleSkill) {
|
|
19372
|
+
const result = await this.provider.toggleSkill(params);
|
|
19373
|
+
this.logger?.info("Toggle skill completed", {
|
|
19374
|
+
success: result.success,
|
|
19375
|
+
hasError: !!result.error
|
|
19376
|
+
});
|
|
19377
|
+
return result;
|
|
19378
|
+
}
|
|
19379
|
+
return {
|
|
19380
|
+
success: false,
|
|
19381
|
+
error: "Provider does not support toggleSkill"
|
|
19382
|
+
};
|
|
19383
|
+
} catch (error) {
|
|
19384
|
+
this.logger?.error("Failed to toggle skill", error);
|
|
19385
|
+
return {
|
|
19386
|
+
success: false,
|
|
19387
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19388
|
+
};
|
|
19389
|
+
}
|
|
19390
|
+
},
|
|
19391
|
+
deleteSkill: async (params) => {
|
|
19392
|
+
try {
|
|
19393
|
+
if (this.provider && this.provider.deleteSkill) {
|
|
19394
|
+
const result = await this.provider.deleteSkill(params);
|
|
19395
|
+
this.logger?.info("Delete skill completed", {
|
|
19396
|
+
success: result.success,
|
|
19397
|
+
hasError: !!result.error
|
|
19398
|
+
});
|
|
19399
|
+
return result;
|
|
19400
|
+
}
|
|
19401
|
+
return {
|
|
19402
|
+
success: false,
|
|
19403
|
+
error: "Provider does not support deleteSkill"
|
|
19404
|
+
};
|
|
19405
|
+
} catch (error) {
|
|
19406
|
+
this.logger?.error("Failed to delete skill", error);
|
|
19407
|
+
return {
|
|
19408
|
+
success: false,
|
|
19409
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19410
|
+
};
|
|
19411
|
+
}
|
|
19412
|
+
},
|
|
19413
|
+
getSkillContent: async (params) => {
|
|
19414
|
+
try {
|
|
19415
|
+
if (this.provider && this.provider.getSkillContent) {
|
|
19416
|
+
const result = await this.provider.getSkillContent(params);
|
|
19417
|
+
this.logger?.info("Get skill content completed", { hasError: !!result.error });
|
|
19418
|
+
return result;
|
|
19419
|
+
}
|
|
19420
|
+
return {
|
|
19421
|
+
content: "",
|
|
19422
|
+
error: "Provider does not support getSkillContent"
|
|
19423
|
+
};
|
|
19424
|
+
} catch (error) {
|
|
19425
|
+
this.logger?.error("Failed to get skill content", error);
|
|
19426
|
+
return {
|
|
19427
|
+
content: "",
|
|
19428
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19429
|
+
};
|
|
19430
|
+
}
|
|
19431
|
+
},
|
|
19432
|
+
getMarketplaceSkills: async () => {
|
|
19433
|
+
try {
|
|
19434
|
+
if (this.provider && this.provider.getMarketplaceSkills) {
|
|
19435
|
+
const result = await this.provider.getMarketplaceSkills();
|
|
19436
|
+
this.logger?.info("Marketplace skills retrieved", {
|
|
19437
|
+
resultCount: result.results.length,
|
|
19438
|
+
hasError: !!result.error
|
|
19439
|
+
});
|
|
19440
|
+
return result;
|
|
19441
|
+
}
|
|
19442
|
+
return {
|
|
19443
|
+
results: [],
|
|
19444
|
+
error: "Provider does not support getMarketplaceSkills"
|
|
19445
|
+
};
|
|
19446
|
+
} catch (error) {
|
|
19447
|
+
this.logger?.error("Failed to get marketplace skills", error);
|
|
19448
|
+
return {
|
|
19449
|
+
results: [],
|
|
19450
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19451
|
+
};
|
|
19452
|
+
}
|
|
19453
|
+
},
|
|
19454
|
+
getMarketplaceSkillContent: async (params) => {
|
|
19455
|
+
try {
|
|
19456
|
+
if (this.provider && this.provider.getMarketplaceSkillContent) return await this.provider.getMarketplaceSkillContent(params);
|
|
19457
|
+
return {
|
|
19458
|
+
content: "",
|
|
19459
|
+
error: "Provider does not support getMarketplaceSkillContent"
|
|
19460
|
+
};
|
|
19461
|
+
} catch (error) {
|
|
19462
|
+
this.logger?.error("Failed to get marketplace skill content", error);
|
|
19463
|
+
return {
|
|
19464
|
+
content: "",
|
|
19465
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19466
|
+
};
|
|
19467
|
+
}
|
|
19468
|
+
},
|
|
19469
|
+
installMarketplaceSkill: async (params) => {
|
|
19470
|
+
try {
|
|
19471
|
+
if (this.provider && this.provider.installMarketplaceSkill) return await this.provider.installMarketplaceSkill(params);
|
|
19472
|
+
return {
|
|
19473
|
+
success: false,
|
|
19474
|
+
skillName: params.skillName,
|
|
19475
|
+
errorMessage: "Provider does not support installMarketplaceSkill"
|
|
19476
|
+
};
|
|
19477
|
+
} catch (error) {
|
|
19478
|
+
this.logger?.error("Failed to install marketplace skill", error);
|
|
19479
|
+
return {
|
|
19480
|
+
success: false,
|
|
19481
|
+
skillName: params.skillName,
|
|
19482
|
+
errorMessage: error instanceof Error ? error.message : "Unknown error"
|
|
19483
|
+
};
|
|
19484
|
+
}
|
|
19485
|
+
},
|
|
18320
19486
|
batchTogglePlugins: async (request) => {
|
|
18321
19487
|
try {
|
|
18322
19488
|
if (this.provider && this.provider.batchTogglePlugins) {
|
|
@@ -18361,10 +19527,10 @@ var AgentClient = class {
|
|
|
18361
19527
|
return [];
|
|
18362
19528
|
}
|
|
18363
19529
|
},
|
|
18364
|
-
installPlugins: async (pluginNames, marketplaceName, installScope, marketplaceSource) => {
|
|
19530
|
+
installPlugins: async (pluginNames, marketplaceName, installScope, marketplaceSource, workspacePath) => {
|
|
18365
19531
|
try {
|
|
18366
19532
|
if (this.provider && "installPlugins" in this.provider && typeof this.provider.installPlugins === "function") {
|
|
18367
|
-
const result = await this.provider.installPlugins(pluginNames, marketplaceName, installScope, marketplaceSource);
|
|
19533
|
+
const result = await this.provider.installPlugins(pluginNames, marketplaceName, installScope, marketplaceSource, workspacePath);
|
|
18368
19534
|
this.logger?.info("Install plugins", {
|
|
18369
19535
|
pluginNames,
|
|
18370
19536
|
marketplaceName,
|
|
@@ -18385,37 +19551,399 @@ var AgentClient = class {
|
|
|
18385
19551
|
};
|
|
18386
19552
|
}
|
|
18387
19553
|
},
|
|
18388
|
-
|
|
19554
|
+
uninstallPlugin: async (pluginName, marketplaceName, scope) => {
|
|
19555
|
+
try {
|
|
19556
|
+
if (this.provider && "uninstallPlugin" in this.provider && typeof this.provider.uninstallPlugin === "function") {
|
|
19557
|
+
const result = await this.provider.uninstallPlugin(pluginName, marketplaceName, scope);
|
|
19558
|
+
this.logger?.info("Uninstall plugin", {
|
|
19559
|
+
pluginName,
|
|
19560
|
+
marketplaceName,
|
|
19561
|
+
scope,
|
|
19562
|
+
success: result.success
|
|
19563
|
+
});
|
|
19564
|
+
return result;
|
|
19565
|
+
}
|
|
19566
|
+
this.logger?.warn("Provider does not support uninstallPlugin");
|
|
19567
|
+
return {
|
|
19568
|
+
success: false,
|
|
19569
|
+
error: "Provider does not support uninstallPlugin"
|
|
19570
|
+
};
|
|
19571
|
+
} catch (error) {
|
|
19572
|
+
this.logger?.error("Failed to uninstall plugin", error);
|
|
19573
|
+
return {
|
|
19574
|
+
success: false,
|
|
19575
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19576
|
+
};
|
|
19577
|
+
}
|
|
19578
|
+
},
|
|
19579
|
+
updatePlugin: async (pluginName, marketplaceName) => {
|
|
18389
19580
|
try {
|
|
18390
|
-
if (this.provider && "
|
|
18391
|
-
const result = await this.provider.
|
|
18392
|
-
this.logger?.info("
|
|
19581
|
+
if (this.provider && "updatePlugin" in this.provider && typeof this.provider.updatePlugin === "function") {
|
|
19582
|
+
const result = await this.provider.updatePlugin(pluginName, marketplaceName);
|
|
19583
|
+
this.logger?.info("Update plugin", {
|
|
19584
|
+
pluginName,
|
|
19585
|
+
marketplaceName,
|
|
19586
|
+
success: result.success
|
|
19587
|
+
});
|
|
18393
19588
|
return result;
|
|
18394
19589
|
}
|
|
19590
|
+
this.logger?.warn("Provider does not support updatePlugin");
|
|
19591
|
+
return {
|
|
19592
|
+
success: false,
|
|
19593
|
+
error: "Provider does not support updatePlugin"
|
|
19594
|
+
};
|
|
19595
|
+
} catch (error) {
|
|
19596
|
+
this.logger?.error("Failed to update plugin", error);
|
|
19597
|
+
return {
|
|
19598
|
+
success: false,
|
|
19599
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19600
|
+
};
|
|
19601
|
+
}
|
|
19602
|
+
},
|
|
19603
|
+
getPluginMarketplaces: async (forceRefresh) => {
|
|
19604
|
+
try {
|
|
19605
|
+
if (this.provider && "getPluginMarketplaces" in this.provider && typeof this.provider.getPluginMarketplaces === "function") {
|
|
19606
|
+
const result = await this.provider.getPluginMarketplaces(forceRefresh);
|
|
19607
|
+
this.logger?.info("Got plugin marketplaces", { count: result?.length ?? 0 });
|
|
19608
|
+
return result;
|
|
19609
|
+
}
|
|
19610
|
+
this.logger?.warn("Provider does not support getPluginMarketplaces");
|
|
19611
|
+
return [];
|
|
19612
|
+
} catch (error) {
|
|
19613
|
+
this.logger?.error("Failed to get plugin marketplaces", error);
|
|
19614
|
+
return [];
|
|
19615
|
+
}
|
|
19616
|
+
},
|
|
19617
|
+
getMarketplacePlugins: async (marketplaceName, forceRefresh, searchText) => {
|
|
19618
|
+
try {
|
|
19619
|
+
if (this.provider && "getMarketplacePlugins" in this.provider && typeof this.provider.getMarketplacePlugins === "function") {
|
|
19620
|
+
const result = await this.provider.getMarketplacePlugins(marketplaceName, forceRefresh, searchText);
|
|
19621
|
+
this.logger?.info("Got marketplace plugins", {
|
|
19622
|
+
marketplaceName,
|
|
19623
|
+
count: result?.length ?? 0
|
|
19624
|
+
});
|
|
19625
|
+
return result;
|
|
19626
|
+
}
|
|
19627
|
+
this.logger?.warn("Provider does not support getMarketplacePlugins");
|
|
19628
|
+
return [];
|
|
19629
|
+
} catch (error) {
|
|
19630
|
+
this.logger?.error("Failed to get marketplace plugins", error);
|
|
19631
|
+
return [];
|
|
19632
|
+
}
|
|
19633
|
+
},
|
|
19634
|
+
getPluginDetail: async (pluginName, marketplaceName) => {
|
|
19635
|
+
try {
|
|
19636
|
+
if (this.provider && "getPluginDetail" in this.provider && typeof this.provider.getPluginDetail === "function") {
|
|
19637
|
+
const result = await this.provider.getPluginDetail(pluginName, marketplaceName);
|
|
19638
|
+
this.logger?.info("Got plugin detail", {
|
|
19639
|
+
pluginName,
|
|
19640
|
+
marketplaceName
|
|
19641
|
+
});
|
|
19642
|
+
return result;
|
|
19643
|
+
}
|
|
19644
|
+
this.logger?.warn("Provider does not support getPluginDetail");
|
|
19645
|
+
return null;
|
|
19646
|
+
} catch (error) {
|
|
19647
|
+
this.logger?.error("Failed to get plugin detail", error);
|
|
19648
|
+
return null;
|
|
19649
|
+
}
|
|
19650
|
+
},
|
|
19651
|
+
addPluginMarketplace: async (source, name) => {
|
|
19652
|
+
try {
|
|
19653
|
+
if (this.provider && "addPluginMarketplace" in this.provider && typeof this.provider.addPluginMarketplace === "function") {
|
|
19654
|
+
const result = await this.provider.addPluginMarketplace(source, name);
|
|
19655
|
+
this.logger?.info("Add plugin marketplace", {
|
|
19656
|
+
source,
|
|
19657
|
+
name,
|
|
19658
|
+
success: result.success
|
|
19659
|
+
});
|
|
19660
|
+
return result;
|
|
19661
|
+
}
|
|
19662
|
+
this.logger?.warn("Provider does not support addPluginMarketplace");
|
|
19663
|
+
return {
|
|
19664
|
+
success: false,
|
|
19665
|
+
error: "Provider does not support addPluginMarketplace"
|
|
19666
|
+
};
|
|
19667
|
+
} catch (error) {
|
|
19668
|
+
this.logger?.error("Failed to add plugin marketplace", error);
|
|
19669
|
+
return {
|
|
19670
|
+
success: false,
|
|
19671
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19672
|
+
};
|
|
19673
|
+
}
|
|
19674
|
+
},
|
|
19675
|
+
removePluginMarketplace: async (marketplaceName) => {
|
|
19676
|
+
try {
|
|
19677
|
+
if (this.provider && "removePluginMarketplace" in this.provider && typeof this.provider.removePluginMarketplace === "function") {
|
|
19678
|
+
const result = await this.provider.removePluginMarketplace(marketplaceName);
|
|
19679
|
+
this.logger?.info("Remove plugin marketplace", {
|
|
19680
|
+
marketplaceName,
|
|
19681
|
+
success: result.success
|
|
19682
|
+
});
|
|
19683
|
+
return result;
|
|
19684
|
+
}
|
|
19685
|
+
this.logger?.warn("Provider does not support removePluginMarketplace");
|
|
19686
|
+
return {
|
|
19687
|
+
success: false,
|
|
19688
|
+
error: "Provider does not support removePluginMarketplace"
|
|
19689
|
+
};
|
|
19690
|
+
} catch (error) {
|
|
19691
|
+
this.logger?.error("Failed to remove plugin marketplace", error);
|
|
19692
|
+
return {
|
|
19693
|
+
success: false,
|
|
19694
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19695
|
+
};
|
|
19696
|
+
}
|
|
19697
|
+
},
|
|
19698
|
+
refreshPluginMarketplace: async (marketplaceName) => {
|
|
19699
|
+
try {
|
|
19700
|
+
if (this.provider && "refreshPluginMarketplace" in this.provider && typeof this.provider.refreshPluginMarketplace === "function") {
|
|
19701
|
+
const result = await this.provider.refreshPluginMarketplace(marketplaceName);
|
|
19702
|
+
this.logger?.info("Refresh plugin marketplace", {
|
|
19703
|
+
marketplaceName,
|
|
19704
|
+
success: result.success
|
|
19705
|
+
});
|
|
19706
|
+
return result;
|
|
19707
|
+
}
|
|
19708
|
+
this.logger?.warn("Provider does not support refreshPluginMarketplace");
|
|
19709
|
+
return {
|
|
19710
|
+
success: false,
|
|
19711
|
+
error: "Provider does not support refreshPluginMarketplace"
|
|
19712
|
+
};
|
|
19713
|
+
} catch (error) {
|
|
19714
|
+
this.logger?.error("Failed to refresh plugin marketplace", error);
|
|
19715
|
+
return {
|
|
19716
|
+
success: false,
|
|
19717
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19718
|
+
};
|
|
19719
|
+
}
|
|
19720
|
+
},
|
|
19721
|
+
openFolderInNewWindow: async (folderPath) => {
|
|
19722
|
+
try {
|
|
19723
|
+
if (this.provider && "openFolderInNewWindow" in this.provider && typeof this.provider.openFolderInNewWindow === "function") {
|
|
19724
|
+
await this.provider.openFolderInNewWindow(folderPath);
|
|
19725
|
+
this.logger?.info("Opened folder in new window", { folderPath });
|
|
19726
|
+
} else {
|
|
19727
|
+
this.logger?.warn("Provider does not support openFolderInNewWindow");
|
|
19728
|
+
throw new Error("Provider does not support openFolderInNewWindow");
|
|
19729
|
+
}
|
|
19730
|
+
} catch (error) {
|
|
19731
|
+
this.logger?.error("Failed to open folder in new window", error);
|
|
19732
|
+
throw error;
|
|
19733
|
+
}
|
|
19734
|
+
},
|
|
19735
|
+
openFolder: async (folderPath) => {
|
|
19736
|
+
try {
|
|
19737
|
+
if (this.provider && "openFolder" in this.provider && typeof this.provider.openFolder === "function") {
|
|
19738
|
+
const result = await this.provider.openFolder(folderPath);
|
|
19739
|
+
this.logger?.info("Opened folder in system file manager", { folderPath });
|
|
19740
|
+
return result;
|
|
19741
|
+
} else {
|
|
19742
|
+
this.logger?.warn("Provider does not support openFolder");
|
|
19743
|
+
throw new Error("Provider does not support openFolder");
|
|
19744
|
+
}
|
|
19745
|
+
} catch (error) {
|
|
19746
|
+
this.logger?.error("Failed to open folder", error);
|
|
19747
|
+
throw error;
|
|
19748
|
+
}
|
|
19749
|
+
},
|
|
19750
|
+
getSupportScenes: async (locale) => {
|
|
19751
|
+
try {
|
|
19752
|
+
if (this.provider && "getSupportScenes" in this.provider && typeof this.provider.getSupportScenes === "function") return await this.provider.getSupportScenes(locale);
|
|
18395
19753
|
this.logger?.warn("Provider does not support getSupportScenes");
|
|
18396
19754
|
return [];
|
|
18397
19755
|
} catch (error) {
|
|
18398
|
-
this.logger?.error("Failed to get support scenes", error);
|
|
19756
|
+
this.logger?.error("Failed to get support scenes", error);
|
|
19757
|
+
return [];
|
|
19758
|
+
}
|
|
19759
|
+
},
|
|
19760
|
+
getProductScenes: async (locale) => {
|
|
19761
|
+
try {
|
|
19762
|
+
if (this.provider?.getProductScenes) {
|
|
19763
|
+
const result = await this.provider.getProductScenes(locale);
|
|
19764
|
+
this.logger?.info("Got product scenes", { count: result?.length ?? 0 });
|
|
19765
|
+
return result;
|
|
19766
|
+
}
|
|
19767
|
+
this.logger?.warn("Provider does not support getProductScenes");
|
|
19768
|
+
return [];
|
|
19769
|
+
} catch (error) {
|
|
19770
|
+
this.logger?.error("Failed to get product scenes", error);
|
|
18399
19771
|
return [];
|
|
18400
19772
|
}
|
|
18401
19773
|
},
|
|
18402
|
-
getAvailableCommands: async (
|
|
19774
|
+
getAvailableCommands: async (params) => {
|
|
18403
19775
|
try {
|
|
18404
19776
|
if (this.provider && "getAvailableCommands" in this.provider && typeof this.provider.getAvailableCommands === "function") {
|
|
18405
|
-
const result = await this.provider.getAvailableCommands(
|
|
19777
|
+
const result = await this.provider.getAvailableCommands(params);
|
|
18406
19778
|
this.logger?.info("Got available commands from provider", {
|
|
18407
|
-
sessionId: sessionId ?? "(default)",
|
|
19779
|
+
sessionId: params?.sessionId ?? "(default)",
|
|
18408
19780
|
count: result?.length ?? 0
|
|
18409
19781
|
});
|
|
18410
19782
|
return result;
|
|
18411
19783
|
}
|
|
18412
|
-
this.logger?.warn("Provider does not support getAvailableCommands", {
|
|
19784
|
+
this.logger?.warn("Provider does not support getAvailableCommands", { params });
|
|
18413
19785
|
return [];
|
|
18414
19786
|
} catch (error) {
|
|
18415
19787
|
this.logger?.error("Failed to get available commands", error);
|
|
18416
19788
|
return [];
|
|
18417
19789
|
}
|
|
18418
19790
|
},
|
|
19791
|
+
reportTelemetry: async (eventName, payload) => {
|
|
19792
|
+
try {
|
|
19793
|
+
if (this.provider?.reportTelemetry) await this.provider.reportTelemetry(eventName, payload);
|
|
19794
|
+
else this.logger?.warn("Provider does not support reportTelemetry");
|
|
19795
|
+
} catch (error) {
|
|
19796
|
+
this.logger?.error("Failed to report telemetry", error);
|
|
19797
|
+
}
|
|
19798
|
+
},
|
|
19799
|
+
getProductConfiguration: async () => {
|
|
19800
|
+
try {
|
|
19801
|
+
if (this.provider?.getProductConfiguration) return await this.provider.getProductConfiguration();
|
|
19802
|
+
this.logger?.warn("Provider does not support getProductConfiguration");
|
|
19803
|
+
return {};
|
|
19804
|
+
} catch (error) {
|
|
19805
|
+
this.logger?.error("Failed to get product configuration", error);
|
|
19806
|
+
return {};
|
|
19807
|
+
}
|
|
19808
|
+
},
|
|
19809
|
+
getUserInfo: async () => {
|
|
19810
|
+
this.logger?.info("[AgentClient.sessions] getUserInfo() called");
|
|
19811
|
+
try {
|
|
19812
|
+
if (this.provider?.getUserInfo) {
|
|
19813
|
+
const result = await this.provider.getUserInfo();
|
|
19814
|
+
this.logger?.info("[AgentClient.sessions] getUserInfo() result:", JSON.stringify(result));
|
|
19815
|
+
return result;
|
|
19816
|
+
}
|
|
19817
|
+
this.logger?.warn("Provider does not support getUserInfo");
|
|
19818
|
+
return {};
|
|
19819
|
+
} catch (error) {
|
|
19820
|
+
this.logger?.error("Failed to get user info", error);
|
|
19821
|
+
return {};
|
|
19822
|
+
}
|
|
19823
|
+
},
|
|
19824
|
+
respondToSampling: async (sessionId, response) => {
|
|
19825
|
+
try {
|
|
19826
|
+
if (this.provider?.respondToSampling) {
|
|
19827
|
+
await this.provider.respondToSampling(sessionId, response);
|
|
19828
|
+
this.logger?.info("Responded to sampling request", {
|
|
19829
|
+
sessionId,
|
|
19830
|
+
requestId: response.id,
|
|
19831
|
+
approved: response.approved
|
|
19832
|
+
});
|
|
19833
|
+
} else this.logger?.warn("Provider does not support respondToSampling");
|
|
19834
|
+
} catch (error) {
|
|
19835
|
+
this.logger?.error("Failed to respond to sampling request", error);
|
|
19836
|
+
throw error;
|
|
19837
|
+
}
|
|
19838
|
+
},
|
|
19839
|
+
respondToRoots: async (sessionId, response) => {
|
|
19840
|
+
try {
|
|
19841
|
+
if (this.provider?.respondToRoots) {
|
|
19842
|
+
await this.provider.respondToRoots(sessionId, response);
|
|
19843
|
+
this.logger?.info("Responded to roots request", {
|
|
19844
|
+
sessionId,
|
|
19845
|
+
requestId: response.id,
|
|
19846
|
+
approved: response.approved
|
|
19847
|
+
});
|
|
19848
|
+
} else this.logger?.warn("Provider does not support respondToRoots");
|
|
19849
|
+
} catch (error) {
|
|
19850
|
+
this.logger?.error("Failed to respond to roots request", error);
|
|
19851
|
+
throw error;
|
|
19852
|
+
}
|
|
19853
|
+
},
|
|
19854
|
+
subscribeSamplingRequests: (serverName, callback) => {
|
|
19855
|
+
if (this.provider?.subscribeSamplingRequests) {
|
|
19856
|
+
this.logger?.info("Subscribing to sampling requests", { serverName });
|
|
19857
|
+
return this.provider.subscribeSamplingRequests(serverName, callback);
|
|
19858
|
+
}
|
|
19859
|
+
this.logger?.warn("Provider does not support subscribeSamplingRequests");
|
|
19860
|
+
return () => {};
|
|
19861
|
+
},
|
|
19862
|
+
subscribeRootsRequests: (serverName, callback) => {
|
|
19863
|
+
if (this.provider?.subscribeRootsRequests) {
|
|
19864
|
+
this.logger?.info("Subscribing to roots requests", { serverName });
|
|
19865
|
+
return this.provider.subscribeRootsRequests(serverName, callback);
|
|
19866
|
+
}
|
|
19867
|
+
this.logger?.warn("Provider does not support subscribeRootsRequests");
|
|
19868
|
+
return () => {};
|
|
19869
|
+
},
|
|
19870
|
+
getMcpServers: async () => {
|
|
19871
|
+
if (this.provider?.getMcpServers) {
|
|
19872
|
+
this.logger?.info("Getting MCP servers list");
|
|
19873
|
+
return this.provider.getMcpServers();
|
|
19874
|
+
}
|
|
19875
|
+
this.logger?.warn("Provider does not support getMcpServers");
|
|
19876
|
+
return [];
|
|
19877
|
+
},
|
|
19878
|
+
toggleMcpServer: async (serverName, enabled) => {
|
|
19879
|
+
if (this.provider?.toggleMcpServer) {
|
|
19880
|
+
this.logger?.info("Toggling MCP server", {
|
|
19881
|
+
serverName,
|
|
19882
|
+
enabled
|
|
19883
|
+
});
|
|
19884
|
+
await this.provider.toggleMcpServer(serverName, enabled);
|
|
19885
|
+
} else {
|
|
19886
|
+
this.logger?.warn("Provider does not support toggleMcpServer");
|
|
19887
|
+
throw new Error("toggleMcpServer not supported by provider");
|
|
19888
|
+
}
|
|
19889
|
+
},
|
|
19890
|
+
reconnectMcpServer: async (serverName, forceHttpCallback) => {
|
|
19891
|
+
if (this.provider?.reconnectMcpServer) {
|
|
19892
|
+
this.logger?.info("Reconnecting MCP server", {
|
|
19893
|
+
serverName,
|
|
19894
|
+
forceHttpCallback
|
|
19895
|
+
});
|
|
19896
|
+
await this.provider.reconnectMcpServer(serverName, forceHttpCallback);
|
|
19897
|
+
} else {
|
|
19898
|
+
this.logger?.warn("Provider does not support reconnectMcpServer");
|
|
19899
|
+
throw new Error("reconnectMcpServer not supported by provider");
|
|
19900
|
+
}
|
|
19901
|
+
},
|
|
19902
|
+
deleteMcpServer: async (serverName) => {
|
|
19903
|
+
if (this.provider?.deleteMcpServer) {
|
|
19904
|
+
this.logger?.info("Deleting MCP server", { serverName });
|
|
19905
|
+
await this.provider.deleteMcpServer(serverName);
|
|
19906
|
+
} else {
|
|
19907
|
+
this.logger?.warn("Provider does not support deleteMcpServer");
|
|
19908
|
+
throw new Error("deleteMcpServer not supported by provider");
|
|
19909
|
+
}
|
|
19910
|
+
},
|
|
19911
|
+
openMcpConfig: async () => {
|
|
19912
|
+
if (this.provider?.openMcpConfig) {
|
|
19913
|
+
this.logger?.info("Opening MCP config");
|
|
19914
|
+
await this.provider.openMcpConfig();
|
|
19915
|
+
} else {
|
|
19916
|
+
this.logger?.warn("Provider does not support openMcpConfig");
|
|
19917
|
+
throw new Error("openMcpConfig not supported by provider");
|
|
19918
|
+
}
|
|
19919
|
+
},
|
|
19920
|
+
getMcpConfigContent: async () => {
|
|
19921
|
+
if (this.provider?.getMcpConfigContent) {
|
|
19922
|
+
this.logger?.info("Getting MCP config content");
|
|
19923
|
+
return await this.provider.getMcpConfigContent();
|
|
19924
|
+
} else {
|
|
19925
|
+
this.logger?.warn("Provider does not support getMcpConfigContent");
|
|
19926
|
+
throw new Error("getMcpConfigContent not supported by provider");
|
|
19927
|
+
}
|
|
19928
|
+
},
|
|
19929
|
+
saveMcpConfigContent: async (content) => {
|
|
19930
|
+
if (this.provider?.saveMcpConfigContent) {
|
|
19931
|
+
this.logger?.info("Saving MCP config content");
|
|
19932
|
+
await this.provider.saveMcpConfigContent(content);
|
|
19933
|
+
} else {
|
|
19934
|
+
this.logger?.warn("Provider does not support saveMcpConfigContent");
|
|
19935
|
+
throw new Error("saveMcpConfigContent not supported by provider");
|
|
19936
|
+
}
|
|
19937
|
+
},
|
|
19938
|
+
clipboardReadText: async () => {
|
|
19939
|
+
if (this.provider?.clipboardReadText) {
|
|
19940
|
+
this.logger?.info("Reading clipboard text");
|
|
19941
|
+
return await this.provider.clipboardReadText();
|
|
19942
|
+
} else {
|
|
19943
|
+
this.logger?.warn("Provider does not support clipboardReadText");
|
|
19944
|
+
throw new Error("clipboardReadText not supported by provider");
|
|
19945
|
+
}
|
|
19946
|
+
},
|
|
18419
19947
|
models: this.createModelsResource()
|
|
18420
19948
|
};
|
|
18421
19949
|
}
|
|
@@ -18641,10 +20169,6 @@ const oauthRepositoryService = new OAuthRepositoryService();
|
|
|
18641
20169
|
* 判断当前账号是否是 SSO 账号
|
|
18642
20170
|
* 通过 account.accountType === 'sso' 来判断,这种不行,因为未登录之前account 为空
|
|
18643
20171
|
*/
|
|
18644
|
-
const isSSODomain = () => {
|
|
18645
|
-
const { hostname } = window.location;
|
|
18646
|
-
return hostname.includes(".sso.copilot") || hostname.includes("sso.codebuddy.cn") || hostname.includes(".sso.copilot-staging") || hostname.includes(".staging-sso.codebuddy.cn");
|
|
18647
|
-
};
|
|
18648
20172
|
/**
|
|
18649
20173
|
* 根据路径获取完整 URL
|
|
18650
20174
|
* - SSO 账号需要跳转到对应的预发/生产域名
|
|
@@ -18652,16 +20176,7 @@ const isSSODomain = () => {
|
|
|
18652
20176
|
* @param path 路径,如 '/login'、'/logout'、'/home' 等
|
|
18653
20177
|
* @returns 完整的 URL 地址
|
|
18654
20178
|
*/
|
|
18655
|
-
const getFullUrl = (path) => {
|
|
18656
|
-
const { hostname, protocol } = window.location;
|
|
18657
|
-
if (isSSODomain()) {
|
|
18658
|
-
const isCodebuddy = hostname.includes("codebuddy.cn");
|
|
18659
|
-
const isStaging = hostname.includes("staging");
|
|
18660
|
-
if (isCodebuddy) return isStaging ? `${protocol}//staging.codebuddy.cn${path}` : `${protocol}//www.codebuddy.cn${path}`;
|
|
18661
|
-
else return isStaging ? `${protocol}//staging-copilot.tencent.com${path}` : `${protocol}//copilot.tencent.com${path}`;
|
|
18662
|
-
}
|
|
18663
|
-
return `${window.location.origin}${path}`;
|
|
18664
|
-
};
|
|
20179
|
+
const getFullUrl = (path) => `${window.location.origin}${path}`;
|
|
18665
20180
|
/** 获取当前域名的账号选择页面 URL */
|
|
18666
20181
|
const getSelectAccountUrl = () => `${window.location.origin}/login/select`;
|
|
18667
20182
|
/** localStorage 中存储选中账号 ID 的 key */
|
|
@@ -18694,16 +20209,34 @@ const getPackageName = (packageCode) => CommodityCodeText[packageCode] || "";
|
|
|
18694
20209
|
* 注意:getAgents 和 getModels 方法已废弃并移除,
|
|
18695
20210
|
* 请使用 IAgentAdapter 中的对应方法
|
|
18696
20211
|
*/
|
|
18697
|
-
var BackendProvider = class {
|
|
20212
|
+
var BackendProvider = class BackendProvider {
|
|
18698
20213
|
constructor(config) {
|
|
18699
20214
|
httpService.setBaseURL(config.baseUrl);
|
|
18700
20215
|
if (config.authToken) httpService.setAuthToken(config.authToken);
|
|
18701
|
-
httpService.onUnauthorized(() =>
|
|
18702
|
-
|
|
18703
|
-
|
|
18704
|
-
|
|
20216
|
+
httpService.onUnauthorized(() => this.handleUnauthorized());
|
|
20217
|
+
}
|
|
20218
|
+
/**
|
|
20219
|
+
* 处理 401 未授权错误
|
|
20220
|
+
* 先尝试刷新 token,失败后再执行登出流程
|
|
20221
|
+
*
|
|
20222
|
+
* @throws 如果 token 刷新失败,抛出错误通知 HttpService 不要重试
|
|
20223
|
+
*/
|
|
20224
|
+
async handleUnauthorized() {
|
|
20225
|
+
console.log("[BackendProvider] User unauthorized (401), attempting token refresh first");
|
|
20226
|
+
try {
|
|
20227
|
+
if (await this.refreshToken()) {
|
|
20228
|
+
console.log("[BackendProvider] Token refresh successful after 401, user still logged in");
|
|
20229
|
+
return;
|
|
20230
|
+
}
|
|
20231
|
+
throw new Error("Token refresh returned null");
|
|
20232
|
+
} catch (error) {
|
|
20233
|
+
console.error("[BackendProvider] Token refresh failed after 401:", error);
|
|
20234
|
+
console.log("[BackendProvider] Token refresh failed, triggering logout");
|
|
20235
|
+
this.logout().catch((logoutError) => {
|
|
20236
|
+
console.error("[BackendProvider] Logout failed in 401 handler:", logoutError);
|
|
18705
20237
|
});
|
|
18706
|
-
|
|
20238
|
+
throw error;
|
|
20239
|
+
}
|
|
18707
20240
|
}
|
|
18708
20241
|
/**
|
|
18709
20242
|
* 获取当前账号信息
|
|
@@ -18967,10 +20500,11 @@ var BackendProvider = class {
|
|
|
18967
20500
|
if (!time) return 0;
|
|
18968
20501
|
return new Date(time).getTime();
|
|
18969
20502
|
};
|
|
18970
|
-
const dailyCredits = [CommodityCode.free
|
|
20503
|
+
const dailyCredits = [CommodityCode.free];
|
|
18971
20504
|
const planResources = resources.map((r) => {
|
|
18972
20505
|
const isDaily = dailyCredits.includes(r.PackageCode);
|
|
18973
20506
|
const endTime = isDaily ? r.CycleEndTime : r.DeductionEndTime;
|
|
20507
|
+
const refreshAt = parseTime(r.CycleEndTime) + 1e3;
|
|
18974
20508
|
return {
|
|
18975
20509
|
id: r.ResourceId,
|
|
18976
20510
|
name: isDaily ? "plan.addonCredits" : getPackageName(r.PackageCode),
|
|
@@ -18980,7 +20514,7 @@ var BackendProvider = class {
|
|
|
18980
20514
|
used: Math.max(0, Number(r.CycleCapacitySizePrecise) - Number(r.CycleCapacityRemainPrecise)) || 0,
|
|
18981
20515
|
left: Number(r.CycleCapacityRemainPrecise) || 0,
|
|
18982
20516
|
expireAt: parseTime(endTime),
|
|
18983
|
-
refreshAt: isDaily ? void 0 :
|
|
20517
|
+
refreshAt: isDaily ? void 0 : refreshAt
|
|
18984
20518
|
};
|
|
18985
20519
|
}).sort((a, b) => {
|
|
18986
20520
|
const getPriority = (code) => {
|
|
@@ -18988,10 +20522,11 @@ var BackendProvider = class {
|
|
|
18988
20522
|
CommodityCode.proMon,
|
|
18989
20523
|
CommodityCode.proMonPlus,
|
|
18990
20524
|
CommodityCode.proYear,
|
|
20525
|
+
CommodityCode.freeMon,
|
|
18991
20526
|
CommodityCode.extra
|
|
18992
20527
|
].includes(code)) return 1;
|
|
18993
20528
|
if ([CommodityCode.gift, CommodityCode.activity].includes(code)) return 2;
|
|
18994
|
-
if ([CommodityCode.free
|
|
20529
|
+
if ([CommodityCode.free].includes(code)) return 3;
|
|
18995
20530
|
return 4;
|
|
18996
20531
|
};
|
|
18997
20532
|
return getPriority(a.packageCode) - getPriority(b.packageCode);
|
|
@@ -19116,34 +20651,65 @@ var BackendProvider = class {
|
|
|
19116
20651
|
}
|
|
19117
20652
|
/**
|
|
19118
20653
|
* 登出账号
|
|
19119
|
-
*
|
|
20654
|
+
*
|
|
20655
|
+
* 策略:
|
|
20656
|
+
* - IOA 企业:用 iframe 走 SSO/SAML SLO 登出链路(涉及跨域重定向),通过轮询 iframe URL 变化检测完成
|
|
20657
|
+
* - 非 IOA 企业:直接用 httpService 请求 /console/logout,速度快
|
|
19120
20658
|
*/
|
|
19121
20659
|
async logout() {
|
|
19122
|
-
const
|
|
20660
|
+
const account = accountService.getAccount();
|
|
20661
|
+
if (account?.enterpriseId && ["esoikz80kd8g", "etahzsqej0n4"].includes(account.enterpriseId)) await this.logoutViaIframe();
|
|
20662
|
+
else await this.logoutViaHttp();
|
|
20663
|
+
localStorage.removeItem(SELECTED_ACCOUNT_KEY);
|
|
20664
|
+
accountService.clearAccount();
|
|
20665
|
+
}
|
|
20666
|
+
/**
|
|
20667
|
+
* IOA 企业登出:通过 iframe 走 SSO/SAML SLO 登出链路
|
|
20668
|
+
* 轮询 iframe URL 变化检测完成,兜底超时 5 秒
|
|
20669
|
+
*/
|
|
20670
|
+
async logoutViaIframe() {
|
|
20671
|
+
const logoutUrl = `${httpService.getAxiosInstance().defaults.baseURL}/console/logout`;
|
|
19123
20672
|
try {
|
|
19124
20673
|
await new Promise((resolve) => {
|
|
19125
20674
|
const iframe = document.createElement("iframe");
|
|
19126
20675
|
iframe.style.cssText = "position:fixed;top:-9999px;left:-9999px;width:1px;height:1px;border:none;";
|
|
19127
|
-
iframe.src =
|
|
19128
|
-
|
|
19129
|
-
|
|
19130
|
-
|
|
19131
|
-
|
|
19132
|
-
|
|
20676
|
+
iframe.src = logoutUrl;
|
|
20677
|
+
let pollTimer;
|
|
20678
|
+
let settled = false;
|
|
20679
|
+
const done = () => {
|
|
20680
|
+
if (settled) return;
|
|
20681
|
+
settled = true;
|
|
20682
|
+
clearInterval(pollTimer);
|
|
19133
20683
|
clearTimeout(timeout);
|
|
19134
20684
|
if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
|
|
19135
|
-
};
|
|
19136
|
-
iframe.onerror = () => {
|
|
19137
|
-
cleanup();
|
|
19138
20685
|
resolve();
|
|
19139
20686
|
};
|
|
20687
|
+
let wasRedirecting = false;
|
|
20688
|
+
pollTimer = setInterval(() => {
|
|
20689
|
+
try {
|
|
20690
|
+
const href = iframe.contentWindow?.location?.href;
|
|
20691
|
+
if (wasRedirecting && href) done();
|
|
20692
|
+
} catch {
|
|
20693
|
+
wasRedirecting = true;
|
|
20694
|
+
}
|
|
20695
|
+
}, 100);
|
|
20696
|
+
const timeout = setTimeout(done, 5e3);
|
|
20697
|
+
iframe.onerror = done;
|
|
19140
20698
|
document.body.appendChild(iframe);
|
|
19141
20699
|
});
|
|
19142
20700
|
} catch (error) {
|
|
19143
|
-
console.error("[BackendProvider] logout failed:", error);
|
|
20701
|
+
console.error("[BackendProvider] logout via iframe failed:", error);
|
|
20702
|
+
}
|
|
20703
|
+
}
|
|
20704
|
+
/**
|
|
20705
|
+
* 非 IOA 企业登出:直接 HTTP 请求 /console/logout
|
|
20706
|
+
*/
|
|
20707
|
+
async logoutViaHttp() {
|
|
20708
|
+
try {
|
|
20709
|
+
await httpService.get("/console/logout");
|
|
20710
|
+
} catch (error) {
|
|
20711
|
+
console.error("[BackendProvider] logout via http failed:", error);
|
|
19144
20712
|
}
|
|
19145
|
-
localStorage.removeItem(SELECTED_ACCOUNT_KEY);
|
|
19146
|
-
accountService.clearAccount();
|
|
19147
20713
|
}
|
|
19148
20714
|
/**
|
|
19149
20715
|
* 批量切换插件状态
|
|
@@ -19221,6 +20787,132 @@ var BackendProvider = class {
|
|
|
19221
20787
|
async getRepositories(connector, page = 0, perPage = 100) {
|
|
19222
20788
|
return oauthRepositoryService.getRepositories(connector, page, perPage);
|
|
19223
20789
|
}
|
|
20790
|
+
/**
|
|
20791
|
+
* 保存待发送的输入内容到后端
|
|
20792
|
+
* API 端点: POST /api/v1/code-id
|
|
20793
|
+
*/
|
|
20794
|
+
async savePendingInput(code) {
|
|
20795
|
+
try {
|
|
20796
|
+
const result = await httpService.post("/api/v1/code-id", { code });
|
|
20797
|
+
return result?.codeId || result?.data?.codeId || null;
|
|
20798
|
+
} catch (e) {
|
|
20799
|
+
console.warn("[BackendProvider] savePendingInput failed:", e);
|
|
20800
|
+
return null;
|
|
20801
|
+
}
|
|
20802
|
+
}
|
|
20803
|
+
/**
|
|
20804
|
+
* 从后端加载待发送的输入内容
|
|
20805
|
+
* API 端点: GET /api/v1/code?id=xxx
|
|
20806
|
+
*/
|
|
20807
|
+
async loadPendingInput(codeId) {
|
|
20808
|
+
try {
|
|
20809
|
+
const result = await httpService.get(`/api/v1/code?id=${encodeURIComponent(codeId)}`);
|
|
20810
|
+
return result?.code || result?.data?.code || null;
|
|
20811
|
+
} catch (e) {
|
|
20812
|
+
console.warn("[BackendProvider] loadPendingInput failed:", e);
|
|
20813
|
+
return null;
|
|
20814
|
+
}
|
|
20815
|
+
}
|
|
20816
|
+
/**
|
|
20817
|
+
* 获取每日签到状态
|
|
20818
|
+
* API 端点: POST /billing/meter/checkin-status
|
|
20819
|
+
*/
|
|
20820
|
+
async getCheckinStatus() {
|
|
20821
|
+
try {
|
|
20822
|
+
const result = await httpService.post("/billing/meter/checkin-status", {});
|
|
20823
|
+
if (result?.code === 0 && result?.data) return result.data;
|
|
20824
|
+
return null;
|
|
20825
|
+
} catch (error) {
|
|
20826
|
+
console.error("[BackendProvider] getCheckinStatus failed:", error);
|
|
20827
|
+
return null;
|
|
20828
|
+
}
|
|
20829
|
+
}
|
|
20830
|
+
/**
|
|
20831
|
+
* 执行每日签到
|
|
20832
|
+
* API 端点: POST /billing/meter/daily-checkin
|
|
20833
|
+
*/
|
|
20834
|
+
async claimDailyCheckin() {
|
|
20835
|
+
const result = await httpService.post("/billing/meter/daily-checkin", {});
|
|
20836
|
+
if (result?.code === 0 && result?.data) return result.data;
|
|
20837
|
+
throw new Error(result?.msg || "Checkin failed");
|
|
20838
|
+
}
|
|
20839
|
+
static {
|
|
20840
|
+
this.SKILLHUB_BASE_URL = "https://lightmake.site";
|
|
20841
|
+
}
|
|
20842
|
+
static {
|
|
20843
|
+
this.SKILLHUB_FETCH_TIMEOUT = 1e4;
|
|
20844
|
+
}
|
|
20845
|
+
async skillHubFetch(url, init) {
|
|
20846
|
+
const controller = new AbortController();
|
|
20847
|
+
const timer = setTimeout(() => controller.abort(), BackendProvider.SKILLHUB_FETCH_TIMEOUT);
|
|
20848
|
+
try {
|
|
20849
|
+
return await fetch(url, {
|
|
20850
|
+
...init,
|
|
20851
|
+
signal: controller.signal
|
|
20852
|
+
});
|
|
20853
|
+
} finally {
|
|
20854
|
+
clearTimeout(timer);
|
|
20855
|
+
}
|
|
20856
|
+
}
|
|
20857
|
+
async getSkillHubList(params = {}) {
|
|
20858
|
+
const qs = new URLSearchParams();
|
|
20859
|
+
if (params.page) qs.set("page", String(params.page));
|
|
20860
|
+
if (params.pageSize) qs.set("pageSize", String(params.pageSize));
|
|
20861
|
+
if (params.sortBy) qs.set("sortBy", params.sortBy);
|
|
20862
|
+
if (params.order) qs.set("order", params.order);
|
|
20863
|
+
if (params.keyword) qs.set("keyword", params.keyword);
|
|
20864
|
+
if (params.category) qs.set("category", params.category);
|
|
20865
|
+
const res = await this.skillHubFetch(`${BackendProvider.SKILLHUB_BASE_URL}/api/skills?${qs.toString()}`);
|
|
20866
|
+
if (!res.ok) throw new Error(`SkillHub list: ${res.status}`);
|
|
20867
|
+
return res.json();
|
|
20868
|
+
}
|
|
20869
|
+
async getSkillHubCategories() {
|
|
20870
|
+
const res = await this.skillHubFetch(`${BackendProvider.SKILLHUB_BASE_URL}/api/v1/categories`);
|
|
20871
|
+
if (!res.ok) throw new Error(`SkillHub categories: ${res.status}`);
|
|
20872
|
+
return res.json();
|
|
20873
|
+
}
|
|
20874
|
+
async getSkillHubSearch(q, limit = 20) {
|
|
20875
|
+
const qs = new URLSearchParams({
|
|
20876
|
+
q,
|
|
20877
|
+
limit: String(limit)
|
|
20878
|
+
});
|
|
20879
|
+
const res = await this.skillHubFetch(`${BackendProvider.SKILLHUB_BASE_URL}/api/v1/search?${qs.toString()}`);
|
|
20880
|
+
if (!res.ok) throw new Error(`SkillHub search: ${res.status}`);
|
|
20881
|
+
return res.json();
|
|
20882
|
+
}
|
|
20883
|
+
async getSkillHubDetail(slug) {
|
|
20884
|
+
const res = await this.skillHubFetch(`${BackendProvider.SKILLHUB_BASE_URL}/api/v1/skills/${encodeURIComponent(slug)}`);
|
|
20885
|
+
if (!res.ok) throw new Error(`SkillHub detail: ${res.status}`);
|
|
20886
|
+
return res.json();
|
|
20887
|
+
}
|
|
20888
|
+
async getSkillHubExists(slugs) {
|
|
20889
|
+
const res = await this.skillHubFetch(`${BackendProvider.SKILLHUB_BASE_URL}/api/v1/skills/exists`, {
|
|
20890
|
+
method: "POST",
|
|
20891
|
+
headers: { "Content-Type": "application/json" },
|
|
20892
|
+
body: JSON.stringify({ slugs })
|
|
20893
|
+
});
|
|
20894
|
+
if (!res.ok) throw new Error(`SkillHub exists: ${res.status}`);
|
|
20895
|
+
return res.json();
|
|
20896
|
+
}
|
|
20897
|
+
async reportSkillHubStats(slug, inc) {
|
|
20898
|
+
try {
|
|
20899
|
+
await this.skillHubFetch(`${BackendProvider.SKILLHUB_BASE_URL}/api/v1/skills/${encodeURIComponent(slug)}/stats/inc`, {
|
|
20900
|
+
method: "POST",
|
|
20901
|
+
headers: { "Content-Type": "application/json" },
|
|
20902
|
+
body: JSON.stringify(inc)
|
|
20903
|
+
});
|
|
20904
|
+
} catch {}
|
|
20905
|
+
}
|
|
20906
|
+
async installSkillHubSkill(_slug, _version, _name) {
|
|
20907
|
+
return {
|
|
20908
|
+
success: false,
|
|
20909
|
+
skillName: _slug,
|
|
20910
|
+
errorMessage: "SkillHub install requires IDE mode (no IPC channel available)"
|
|
20911
|
+
};
|
|
20912
|
+
}
|
|
20913
|
+
async getSkillHubInstalledMetas() {
|
|
20914
|
+
return [];
|
|
20915
|
+
}
|
|
19224
20916
|
};
|
|
19225
20917
|
/**
|
|
19226
20918
|
* 创建 BackendProvider 实例
|
|
@@ -19259,10 +20951,26 @@ const BACKEND_REQUEST_TYPES = {
|
|
|
19259
20951
|
REVOKE_ALL: "backend:revoke-all",
|
|
19260
20952
|
GET_FILE: "backend:get-file",
|
|
19261
20953
|
RELOAD_WINDOW: "backend:reload-window",
|
|
20954
|
+
SAVE_LOCALE: "backend:save-locale",
|
|
19262
20955
|
CLOSE_AGENT_MANAGER: "backend:close-agent-manager",
|
|
19263
20956
|
OPEN_EXTERNAL: "backend:open-external",
|
|
20957
|
+
OPEN_LOCAL_FILE: "backend:open-local-file",
|
|
20958
|
+
GET_LOCAL_CUSTOM_MODELS: "backend:get-local-custom-models",
|
|
20959
|
+
SAVE_LOCAL_CUSTOM_MODEL: "backend:save-local-custom-model",
|
|
20960
|
+
DELETE_LOCAL_CUSTOM_MODEL: "backend:delete-local-custom-model",
|
|
19264
20961
|
BATCH_TOGGLE_PLUGINS: "backend:batch-toggle-plugins",
|
|
19265
|
-
GET_SUPPORT_SCENES: "backend:get-support-scenes"
|
|
20962
|
+
GET_SUPPORT_SCENES: "backend:get-support-scenes",
|
|
20963
|
+
GET_ACCOUNT_USAGE: "backend:get-account-usage",
|
|
20964
|
+
GET_CHECKIN_STATUS: "backend:get-checkin-status",
|
|
20965
|
+
CLAIM_DAILY_CHECKIN: "backend:claim-daily-checkin",
|
|
20966
|
+
GET_ACTIVITY_BANNER: "backend:get-activity-banner",
|
|
20967
|
+
SKILLHUB_LIST: "backend:skillhub-list",
|
|
20968
|
+
SKILLHUB_CATEGORIES: "backend:skillhub-categories",
|
|
20969
|
+
SKILLHUB_SEARCH: "backend:skillhub-search",
|
|
20970
|
+
SKILLHUB_DETAIL: "backend:skillhub-detail",
|
|
20971
|
+
SKILLHUB_DOWNLOAD_URL: "backend:skillhub-download-url",
|
|
20972
|
+
SKILLHUB_EXISTS: "backend:skillhub-exists",
|
|
20973
|
+
SKILLHUB_REPORT_STATS: "backend:skillhub-report-stats"
|
|
19266
20974
|
};
|
|
19267
20975
|
/**
|
|
19268
20976
|
* 生成唯一请求 ID
|
|
@@ -19281,6 +20989,25 @@ var IPCBackendProvider = class {
|
|
|
19281
20989
|
this.debug = config.debug ?? false;
|
|
19282
20990
|
this.timeoutMs = config.timeoutMs ?? 3e4;
|
|
19283
20991
|
this.log("Initialized with IWidgetChannel");
|
|
20992
|
+
this.setupSessionChangeListener();
|
|
20993
|
+
}
|
|
20994
|
+
/**
|
|
20995
|
+
* 设置会话变化监听器
|
|
20996
|
+
* 监听来自 Extension Host (BackendBridgeService) 推送的 auth:session-changed 事件
|
|
20997
|
+
* 并更新本地 accountService
|
|
20998
|
+
*/
|
|
20999
|
+
setupSessionChangeListener() {
|
|
21000
|
+
this.log("Setting up session change listener");
|
|
21001
|
+
this.channel.on("auth:session-changed", (data) => {
|
|
21002
|
+
this.log("Received auth:session-changed event from Extension Host:", data);
|
|
21003
|
+
const account = data?.account || null;
|
|
21004
|
+
accountService.setAccount(account);
|
|
21005
|
+
this.log("Updated accountService with new session", {
|
|
21006
|
+
hasAccount: !!account,
|
|
21007
|
+
accountNickname: account?.nickname
|
|
21008
|
+
});
|
|
21009
|
+
});
|
|
21010
|
+
this.log("Session change listener setup complete");
|
|
19284
21011
|
}
|
|
19285
21012
|
/**
|
|
19286
21013
|
* 发送统一格式的后端请求
|
|
@@ -19309,12 +21036,14 @@ var IPCBackendProvider = class {
|
|
|
19309
21036
|
*/
|
|
19310
21037
|
async getAccount() {
|
|
19311
21038
|
this.log("Getting account via IPC");
|
|
21039
|
+
const startTime = performance.now();
|
|
19312
21040
|
try {
|
|
19313
21041
|
const account = await this.sendBackendRequest(BACKEND_REQUEST_TYPES.GET_ACCOUNT);
|
|
21042
|
+
this.log(`getAccount IPC completed in ${(performance.now() - startTime).toFixed(0)}ms`);
|
|
19314
21043
|
accountService.setAccount(account);
|
|
19315
21044
|
return account;
|
|
19316
21045
|
} catch (error) {
|
|
19317
|
-
this.log(
|
|
21046
|
+
this.log(`getAccount IPC failed after ${(performance.now() - startTime).toFixed(0)}ms:`, error);
|
|
19318
21047
|
accountService.setAccount(null);
|
|
19319
21048
|
return null;
|
|
19320
21049
|
}
|
|
@@ -19543,6 +21272,20 @@ var IPCBackendProvider = class {
|
|
|
19543
21272
|
}
|
|
19544
21273
|
}
|
|
19545
21274
|
/**
|
|
21275
|
+
* Save locale to argv.json without restarting the app.
|
|
21276
|
+
* The change takes effect on next manual restart.
|
|
21277
|
+
* @param params locale to save
|
|
21278
|
+
*/
|
|
21279
|
+
async saveLocale(params) {
|
|
21280
|
+
this.log("Saving locale to argv.json via IPC", params);
|
|
21281
|
+
try {
|
|
21282
|
+
await this.sendBackendRequest(BACKEND_REQUEST_TYPES.SAVE_LOCALE, params);
|
|
21283
|
+
} catch (error) {
|
|
21284
|
+
this.log("Save locale request failed:", error);
|
|
21285
|
+
throw error;
|
|
21286
|
+
}
|
|
21287
|
+
}
|
|
21288
|
+
/**
|
|
19546
21289
|
* 关闭 Agent Manager 面板
|
|
19547
21290
|
* IDE 环境: 通过 IPC 通知 IDE 关闭 Agent Manager(用于返回 IDE)
|
|
19548
21291
|
*/
|
|
@@ -19570,6 +21313,41 @@ var IPCBackendProvider = class {
|
|
|
19570
21313
|
}
|
|
19571
21314
|
}
|
|
19572
21315
|
/**
|
|
21316
|
+
* 打开本地文件
|
|
21317
|
+
* IDE 环境: 通过 IPC 通知 IDE 打开本地配置文件
|
|
21318
|
+
* @param filePath 要打开的文件路径
|
|
21319
|
+
*/
|
|
21320
|
+
async openLocalFile(filePath) {
|
|
21321
|
+
this.log("Opening local file via IPC:", filePath);
|
|
21322
|
+
try {
|
|
21323
|
+
if (!await this.sendBackendRequest(BACKEND_REQUEST_TYPES.OPEN_LOCAL_FILE, { filePath })) throw new Error(`Failed to open local file: ${filePath}`);
|
|
21324
|
+
} catch (error) {
|
|
21325
|
+
this.log("Open local file request failed:", error);
|
|
21326
|
+
throw error;
|
|
21327
|
+
}
|
|
21328
|
+
}
|
|
21329
|
+
/**
|
|
21330
|
+
* 获取用户级本地自定义模型
|
|
21331
|
+
*/
|
|
21332
|
+
async getLocalCustomModels() {
|
|
21333
|
+
this.log("Getting local custom models via IPC");
|
|
21334
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.GET_LOCAL_CUSTOM_MODELS);
|
|
21335
|
+
}
|
|
21336
|
+
/**
|
|
21337
|
+
* 保存用户级本地自定义模型
|
|
21338
|
+
*/
|
|
21339
|
+
async saveLocalCustomModel(request) {
|
|
21340
|
+
this.log("Saving local custom model via IPC:", request);
|
|
21341
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.SAVE_LOCAL_CUSTOM_MODEL, request);
|
|
21342
|
+
}
|
|
21343
|
+
/**
|
|
21344
|
+
* 删除用户级本地自定义模型
|
|
21345
|
+
*/
|
|
21346
|
+
async deleteLocalCustomModel(id) {
|
|
21347
|
+
this.log("Deleting local custom model via IPC:", id);
|
|
21348
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.DELETE_LOCAL_CUSTOM_MODEL, { id });
|
|
21349
|
+
}
|
|
21350
|
+
/**
|
|
19573
21351
|
* 批量切换插件状态
|
|
19574
21352
|
* IDE 环境: 通过 IPC 调用 Extension Host 的 PluginService
|
|
19575
21353
|
*/
|
|
@@ -19603,6 +21381,187 @@ var IPCBackendProvider = class {
|
|
|
19603
21381
|
}
|
|
19604
21382
|
}
|
|
19605
21383
|
/**
|
|
21384
|
+
* 获取账号用量信息(积分/Credits)
|
|
21385
|
+
* IDE 环境: 通过 IPC 实时获取用量信息,每次打开菜单时调用
|
|
21386
|
+
*
|
|
21387
|
+
* 调用链:
|
|
21388
|
+
* 1. agent-ui: IPCBackendProvider.getAccountUsage()
|
|
21389
|
+
* 2. Agent Manager renderer: BackendService.getAccountUsage()
|
|
21390
|
+
* 3. Main Process: codebuddy:getAccountUsage IPC handler
|
|
21391
|
+
* 4. 返回 { usageLeft, usageTotal, editionType, refreshAt } 等字段
|
|
21392
|
+
*/
|
|
21393
|
+
async getAccountUsage() {
|
|
21394
|
+
this.log("Getting account usage via IPC");
|
|
21395
|
+
try {
|
|
21396
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.GET_ACCOUNT_USAGE);
|
|
21397
|
+
} catch (error) {
|
|
21398
|
+
this.log("Get account usage failed:", error);
|
|
21399
|
+
return null;
|
|
21400
|
+
}
|
|
21401
|
+
}
|
|
21402
|
+
/**
|
|
21403
|
+
* 获取每日签到状态
|
|
21404
|
+
* IDE 环境: 通过 IPC 获取签到状态
|
|
21405
|
+
*/
|
|
21406
|
+
async getCheckinStatus() {
|
|
21407
|
+
this.log("Getting checkin status via IPC");
|
|
21408
|
+
try {
|
|
21409
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.GET_CHECKIN_STATUS);
|
|
21410
|
+
} catch (error) {
|
|
21411
|
+
this.log("Get checkin status failed:", error);
|
|
21412
|
+
return null;
|
|
21413
|
+
}
|
|
21414
|
+
}
|
|
21415
|
+
/**
|
|
21416
|
+
* 执行每日签到
|
|
21417
|
+
* IDE 环境: 通过 IPC 执行签到
|
|
21418
|
+
*/
|
|
21419
|
+
async claimDailyCheckin() {
|
|
21420
|
+
this.log("Claiming daily checkin via IPC");
|
|
21421
|
+
try {
|
|
21422
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.CLAIM_DAILY_CHECKIN);
|
|
21423
|
+
} catch (error) {
|
|
21424
|
+
this.log("Claim daily checkin failed:", error);
|
|
21425
|
+
throw error;
|
|
21426
|
+
}
|
|
21427
|
+
}
|
|
21428
|
+
/**
|
|
21429
|
+
* 获取活动 Banner
|
|
21430
|
+
* IDE 环境: 通过 IPC 获取活动 Banner
|
|
21431
|
+
*/
|
|
21432
|
+
async getActivityBanner() {
|
|
21433
|
+
this.log("Getting activity banner via IPC");
|
|
21434
|
+
try {
|
|
21435
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.GET_ACTIVITY_BANNER);
|
|
21436
|
+
} catch (error) {
|
|
21437
|
+
this.log("Get activity banner failed:", error);
|
|
21438
|
+
return null;
|
|
21439
|
+
}
|
|
21440
|
+
}
|
|
21441
|
+
/**
|
|
21442
|
+
* 获取 SkillHub 技能列表
|
|
21443
|
+
* IDE 环境: 通过 IPC 获取技能列表
|
|
21444
|
+
*/
|
|
21445
|
+
async getSkillHubList(params) {
|
|
21446
|
+
this.log("Getting SkillHub list via IPC", params);
|
|
21447
|
+
try {
|
|
21448
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.SKILLHUB_LIST, params);
|
|
21449
|
+
} catch (error) {
|
|
21450
|
+
this.log("Get SkillHub list failed:", error);
|
|
21451
|
+
throw error;
|
|
21452
|
+
}
|
|
21453
|
+
}
|
|
21454
|
+
/**
|
|
21455
|
+
* 获取 SkillHub 分类列表
|
|
21456
|
+
* IDE 环境: 通过 IPC 获取分类列表
|
|
21457
|
+
*/
|
|
21458
|
+
async getSkillHubCategories() {
|
|
21459
|
+
this.log("Getting SkillHub categories via IPC");
|
|
21460
|
+
try {
|
|
21461
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.SKILLHUB_CATEGORIES);
|
|
21462
|
+
} catch (error) {
|
|
21463
|
+
this.log("Get SkillHub categories failed:", error);
|
|
21464
|
+
throw error;
|
|
21465
|
+
}
|
|
21466
|
+
}
|
|
21467
|
+
/**
|
|
21468
|
+
* 搜索 SkillHub 技能
|
|
21469
|
+
* IDE 环境: 通过 IPC 搜索技能
|
|
21470
|
+
*/
|
|
21471
|
+
async getSkillHubSearch(q, limit = 20) {
|
|
21472
|
+
this.log("Searching SkillHub via IPC", {
|
|
21473
|
+
q,
|
|
21474
|
+
limit
|
|
21475
|
+
});
|
|
21476
|
+
try {
|
|
21477
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.SKILLHUB_SEARCH, {
|
|
21478
|
+
q,
|
|
21479
|
+
limit
|
|
21480
|
+
});
|
|
21481
|
+
} catch (error) {
|
|
21482
|
+
this.log("SkillHub search failed:", error);
|
|
21483
|
+
throw error;
|
|
21484
|
+
}
|
|
21485
|
+
}
|
|
21486
|
+
/**
|
|
21487
|
+
* 获取 SkillHub 技能详情
|
|
21488
|
+
* IDE 环境: 通过 IPC 获取技能详情
|
|
21489
|
+
*/
|
|
21490
|
+
async getSkillHubDetail(slug) {
|
|
21491
|
+
this.log("Getting SkillHub detail via IPC", { slug });
|
|
21492
|
+
try {
|
|
21493
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.SKILLHUB_DETAIL, { slug });
|
|
21494
|
+
} catch (error) {
|
|
21495
|
+
this.log("Get SkillHub detail failed:", error);
|
|
21496
|
+
throw error;
|
|
21497
|
+
}
|
|
21498
|
+
}
|
|
21499
|
+
/**
|
|
21500
|
+
* 批量检查 SkillHub 技能是否存在
|
|
21501
|
+
* IDE 环境: 通过 IPC 检查技能是否存在
|
|
21502
|
+
*/
|
|
21503
|
+
async getSkillHubExists(slugs) {
|
|
21504
|
+
this.log("Checking SkillHub exists via IPC", { slugs });
|
|
21505
|
+
try {
|
|
21506
|
+
return await this.sendBackendRequest(BACKEND_REQUEST_TYPES.SKILLHUB_EXISTS, { slugs });
|
|
21507
|
+
} catch (error) {
|
|
21508
|
+
this.log("SkillHub exists check failed:", error);
|
|
21509
|
+
throw error;
|
|
21510
|
+
}
|
|
21511
|
+
}
|
|
21512
|
+
/**
|
|
21513
|
+
* 上报 SkillHub 技能统计
|
|
21514
|
+
* IDE 环境: 通过 IPC 上报统计
|
|
21515
|
+
*/
|
|
21516
|
+
async reportSkillHubStats(slug, inc) {
|
|
21517
|
+
this.log("Reporting SkillHub stats via IPC", {
|
|
21518
|
+
slug,
|
|
21519
|
+
inc
|
|
21520
|
+
});
|
|
21521
|
+
try {
|
|
21522
|
+
await this.sendBackendRequest(BACKEND_REQUEST_TYPES.SKILLHUB_REPORT_STATS, {
|
|
21523
|
+
slug,
|
|
21524
|
+
inc
|
|
21525
|
+
});
|
|
21526
|
+
} catch (error) {
|
|
21527
|
+
this.log("Report SkillHub stats failed:", error);
|
|
21528
|
+
}
|
|
21529
|
+
}
|
|
21530
|
+
/**
|
|
21531
|
+
* 安装 SkillHub 技能
|
|
21532
|
+
* IDE 环境: 通过 IPC 安装技能(下载 zip → 解压到本地)
|
|
21533
|
+
*/
|
|
21534
|
+
async installSkillHubSkill(slug, version, name) {
|
|
21535
|
+
this.log("Installing SkillHub skill via IPC", {
|
|
21536
|
+
slug,
|
|
21537
|
+
version,
|
|
21538
|
+
name
|
|
21539
|
+
});
|
|
21540
|
+
try {
|
|
21541
|
+
return await this.sendBackendRequest("backend:skillhub-install", {
|
|
21542
|
+
slug,
|
|
21543
|
+
version,
|
|
21544
|
+
name
|
|
21545
|
+
});
|
|
21546
|
+
} catch (error) {
|
|
21547
|
+
this.log("Install SkillHub skill failed:", error);
|
|
21548
|
+
throw error;
|
|
21549
|
+
}
|
|
21550
|
+
}
|
|
21551
|
+
/**
|
|
21552
|
+
* 获取本地已安装的 SkillHub 技能元信息
|
|
21553
|
+
* IDE 环境: 通过 IPC 获取元信息
|
|
21554
|
+
*/
|
|
21555
|
+
async getSkillHubInstalledMetas() {
|
|
21556
|
+
this.log("Getting SkillHub installed metas via IPC");
|
|
21557
|
+
try {
|
|
21558
|
+
return await this.sendBackendRequest("backend:skillhub-installed-metas");
|
|
21559
|
+
} catch (error) {
|
|
21560
|
+
this.log("Get SkillHub installed metas failed:", error);
|
|
21561
|
+
return [];
|
|
21562
|
+
}
|
|
21563
|
+
}
|
|
21564
|
+
/**
|
|
19606
21565
|
* 调试日志
|
|
19607
21566
|
*/
|
|
19608
21567
|
log(...args) {
|
|
@@ -19622,10 +21581,12 @@ exports.AgentClient = AgentClient;
|
|
|
19622
21581
|
exports.BackendProvider = BackendProvider;
|
|
19623
21582
|
exports.CloudAgentConnection = CloudAgentConnection;
|
|
19624
21583
|
exports.CloudAgentProvider = CloudAgentProvider;
|
|
19625
|
-
exports.E2BFilesystem = E2BFilesystem;
|
|
21584
|
+
exports.E2BFilesystem = require_e2b_filesystem.E2BFilesystem;
|
|
19626
21585
|
exports.HttpService = HttpService;
|
|
19627
21586
|
exports.IPCBackendProvider = IPCBackendProvider;
|
|
21587
|
+
exports.SessionError = SessionError;
|
|
19628
21588
|
exports.SessionManager = SessionManager;
|
|
21589
|
+
exports.__toESM = __toESM;
|
|
19629
21590
|
exports.createBackendProvider = createBackendProvider;
|
|
19630
21591
|
exports.createIPCBackendProvider = createIPCBackendProvider;
|
|
19631
21592
|
exports.httpService = httpService;
|