aws-runtime-bridge 1.8.4 → 1.8.6
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/adapter/AcodeSdkAdapter.d.ts.map +1 -1
- package/dist/adapter/AcodeSdkAdapter.js +6 -98
- package/dist/adapter/AcodeSdkAdapter.test.js +2 -313
- package/dist/adapter/OpencodeSdkAdapter.js +1 -1
- package/dist/adapter/types.d.ts.map +1 -1
- package/dist/adapter/types.js +3 -7
- package/dist/config.d.ts +3 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -36
- package/dist/config.test.js +20 -24
- package/dist/routes/ai-sources.js +1 -5
- package/dist/routes/ai-sources.test.js +0 -21
- package/dist/routes/instance.test.js +70 -1
- package/dist/routes/runtime-binding.d.ts.map +1 -1
- package/dist/routes/runtime-binding.js +1 -36
- package/dist/routes/terminal.d.ts +0 -2
- package/dist/routes/terminal.d.ts.map +1 -1
- package/dist/routes/terminal.js +7 -109
- package/dist/routes/terminal.test.js +1 -118
- package/dist/services/mcp-launch-binding-queue.d.ts +0 -7
- package/dist/services/mcp-launch-binding-queue.d.ts.map +1 -1
- package/dist/services/mcp-launch-binding-queue.js +0 -25
- package/dist/services/session-output.d.ts +3 -7
- package/dist/services/session-output.d.ts.map +1 -1
- package/package/acode/dist/runtime.d.ts +0 -1
- package/package/acode/dist/runtime.d.ts.map +1 -1
- package/package/acode/dist/runtime.js +31 -265
- package/package/acode/dist/types.d.ts +1 -1
- package/package/acode/dist/types.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/config.d.ts +0 -4
- package/package/aws-client-agent-mcp/dist/config.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/config.js +0 -15
- package/package/aws-client-agent-mcp/dist/config.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts +0 -10
- package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.js +1 -79
- package/package/aws-client-agent-mcp/dist/http-client.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.test.js +265 -129
- package/package/aws-client-agent-mcp/dist/http-client.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import os from "node:os";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { describe, expect, it } from "vitest";
|
|
5
5
|
import { SDK_PROVIDER_DEFINITIONS } from "../adapter/SdkProviderSpi.js";
|
|
6
|
-
import { buildAcodeCommandOutputPath, buildClaudeCodeLaunchConfig, buildRuntimeEnv,
|
|
6
|
+
import { buildAcodeCommandOutputPath, buildClaudeCodeLaunchConfig, buildRuntimeEnv, buildToolResultTimelineActionInfo, countTerminalOutputLines, createTerminalOutputDecoder, decodeTerminalOutputChunk, evaluatePersistedSessionReuse, formatCommandInactivityTimeoutNotice, formatCommandOutputSpilloverNotice, formatTerminalPrompt, formatSdkOutputEvent, normalizeTerminalCommandInput, parseTerminalDirectoryChangeTarget, resolveSdkInputMessage, resolveTerminalOutputEncoding, resolveSdkProviderId, resolveSdkSessionDisplayStatus, resolveRuntimeStatusFromProviderEvent, resolveStatusChangeUsage, } from "./terminal.js";
|
|
7
7
|
describe("terminal route validation", () => {
|
|
8
8
|
it("requires agentId and workspacePath for start", () => {
|
|
9
9
|
const validateStartRequest = (body) => {
|
|
@@ -377,44 +377,6 @@ describe("SDK status usage forwarding", () => {
|
|
|
377
377
|
},
|
|
378
378
|
});
|
|
379
379
|
});
|
|
380
|
-
it("includes file paths and commands in tool status action details", () => {
|
|
381
|
-
expect(resolveRuntimeStatusFromProviderEvent({
|
|
382
|
-
type: "tool_use_start",
|
|
383
|
-
sessionId: "session-1",
|
|
384
|
-
timestamp: new Date(0).toISOString(),
|
|
385
|
-
data: {
|
|
386
|
-
toolName: "builtin/read_file",
|
|
387
|
-
toolInput: { path: "src/views/App.vue" },
|
|
388
|
-
toolUseId: "tool-read",
|
|
389
|
-
},
|
|
390
|
-
})).toEqual({
|
|
391
|
-
status: "tool_using",
|
|
392
|
-
actionInfo: {
|
|
393
|
-
actionType: "read_file",
|
|
394
|
-
actionLabel: "读取文件",
|
|
395
|
-
actionDetail: "src/views/App.vue",
|
|
396
|
-
actionId: "tool-read",
|
|
397
|
-
},
|
|
398
|
-
});
|
|
399
|
-
expect(resolveRuntimeStatusFromProviderEvent({
|
|
400
|
-
type: "tool_use_start",
|
|
401
|
-
sessionId: "session-1",
|
|
402
|
-
timestamp: new Date(0).toISOString(),
|
|
403
|
-
data: {
|
|
404
|
-
toolName: "bash",
|
|
405
|
-
toolInput: { command: "npm run test:agent-timeline-panel" },
|
|
406
|
-
toolUseId: "tool-bash",
|
|
407
|
-
},
|
|
408
|
-
})).toEqual({
|
|
409
|
-
status: "tool_using",
|
|
410
|
-
actionInfo: {
|
|
411
|
-
actionType: "bash",
|
|
412
|
-
actionLabel: "执行命令",
|
|
413
|
-
actionDetail: "npm run test:agent-timeline-panel",
|
|
414
|
-
actionId: "tool-bash",
|
|
415
|
-
},
|
|
416
|
-
});
|
|
417
|
-
});
|
|
418
380
|
});
|
|
419
381
|
describe("SDK output forwarding", () => {
|
|
420
382
|
it("formats assistant text provider events for the terminal output callback path", () => {
|
|
@@ -463,85 +425,6 @@ describe("SDK output forwarding", () => {
|
|
|
463
425
|
};
|
|
464
426
|
expect(formatSdkOutputEvent(requestEvent)).toBe("\r\n[ACode] 正在请求模型 test-model:inspect status\r\n");
|
|
465
427
|
});
|
|
466
|
-
it("builds ACode log metadata for output callbacks", () => {
|
|
467
|
-
const requestEvent = {
|
|
468
|
-
type: "ai_request",
|
|
469
|
-
sessionId: "session-1",
|
|
470
|
-
timestamp: new Date(0).toISOString(),
|
|
471
|
-
data: { model: "test-model", endpoint: "openai-compatible", toolCount: 2 },
|
|
472
|
-
};
|
|
473
|
-
const errorEvent = {
|
|
474
|
-
type: "error",
|
|
475
|
-
sessionId: "session-1",
|
|
476
|
-
timestamp: new Date(0).toISOString(),
|
|
477
|
-
data: { text: "provider failed" },
|
|
478
|
-
};
|
|
479
|
-
expect(buildSdkOutputMetadata(requestEvent)).toEqual({
|
|
480
|
-
sourceEventType: "ai_request",
|
|
481
|
-
logCategory: "acode",
|
|
482
|
-
logLevel: "info",
|
|
483
|
-
logMessage: "AI request started: test-model @ openai-compatible, tools=2",
|
|
484
|
-
});
|
|
485
|
-
expect(buildSdkOutputMetadata(errorEvent)).toEqual({
|
|
486
|
-
sourceEventType: "error",
|
|
487
|
-
logCategory: "acode",
|
|
488
|
-
logLevel: "error",
|
|
489
|
-
logMessage: "provider failed",
|
|
490
|
-
});
|
|
491
|
-
});
|
|
492
|
-
it("does not mark streaming text chunks as standalone ACode log rows", () => {
|
|
493
|
-
const metadata = buildSdkOutputMetadata({
|
|
494
|
-
type: "text_delta",
|
|
495
|
-
sessionId: "session-1",
|
|
496
|
-
data: { text: "word" },
|
|
497
|
-
});
|
|
498
|
-
expect(metadata).toEqual({
|
|
499
|
-
sourceEventType: "text_delta",
|
|
500
|
-
logCategory: "acode",
|
|
501
|
-
});
|
|
502
|
-
});
|
|
503
|
-
it("includes file paths and commands in ACode tool log metadata", () => {
|
|
504
|
-
const readEvent = {
|
|
505
|
-
type: "tool_use_start",
|
|
506
|
-
sessionId: "session-1",
|
|
507
|
-
timestamp: new Date(0).toISOString(),
|
|
508
|
-
data: {
|
|
509
|
-
toolName: "read_file",
|
|
510
|
-
toolInput: { path: "src/index.ts" },
|
|
511
|
-
},
|
|
512
|
-
};
|
|
513
|
-
const editEvent = {
|
|
514
|
-
type: "tool_use_start",
|
|
515
|
-
sessionId: "session-1",
|
|
516
|
-
timestamp: new Date(0).toISOString(),
|
|
517
|
-
data: {
|
|
518
|
-
toolName: "edit",
|
|
519
|
-
toolInput: { file_path: "src/app.ts" },
|
|
520
|
-
},
|
|
521
|
-
};
|
|
522
|
-
const writeEvent = {
|
|
523
|
-
type: "tool_use_end",
|
|
524
|
-
sessionId: "session-1",
|
|
525
|
-
timestamp: new Date(0).toISOString(),
|
|
526
|
-
data: {
|
|
527
|
-
toolName: "write_file",
|
|
528
|
-
toolInput: { path: "src/new-file.ts" },
|
|
529
|
-
},
|
|
530
|
-
};
|
|
531
|
-
const bashEvent = {
|
|
532
|
-
type: "tool_use_start",
|
|
533
|
-
sessionId: "session-1",
|
|
534
|
-
timestamp: new Date(0).toISOString(),
|
|
535
|
-
data: {
|
|
536
|
-
toolName: "bash",
|
|
537
|
-
toolInput: { command: "npm run build -- --mode production" },
|
|
538
|
-
},
|
|
539
|
-
};
|
|
540
|
-
expect(buildSdkOutputMetadata(readEvent).logMessage).toBe("开始读取文件: src/index.ts");
|
|
541
|
-
expect(buildSdkOutputMetadata(editEvent).logMessage).toBe("开始编辑文件: src/app.ts");
|
|
542
|
-
expect(buildSdkOutputMetadata(writeEvent).logMessage).toBe("完成写入文件: src/new-file.ts");
|
|
543
|
-
expect(buildSdkOutputMetadata(bashEvent).logMessage).toBe("开始执行命令: npm run build -- --mode production");
|
|
544
|
-
});
|
|
545
428
|
});
|
|
546
429
|
describe("SDK tool result timeline action info", () => {
|
|
547
430
|
it("keeps MCP tool results on MCP timeline events", () => {
|
|
@@ -32,11 +32,4 @@ export declare function enqueueMcpLaunchBinding(input: McpLaunchBindingInput): M
|
|
|
32
32
|
export declare function claimMcpLaunchBinding(request: McpLaunchBindingClaimRequest): ClaimedMcpLaunchBinding | null;
|
|
33
33
|
export declare function getMcpLaunchQueueSize(workspacePath: unknown): number;
|
|
34
34
|
export declare function clearMcpLaunchBindingQueues(): void;
|
|
35
|
-
/**
|
|
36
|
-
* 获取指定 agent 的最新 MCP session token。
|
|
37
|
-
* 供 MCP node 在 401 后向 bridge 查询最新 token 使用。
|
|
38
|
-
*/
|
|
39
|
-
export declare function getLatestAgentToken(agentId: string): {
|
|
40
|
-
runtimeAccessToken: string;
|
|
41
|
-
} | null;
|
|
42
35
|
//# sourceMappingURL=mcp-launch-binding-queue.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-launch-binding-queue.d.ts","sourceRoot":"","sources":["../../src/services/mcp-launch-binding-queue.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mcp-launch-binding-queue.d.ts","sourceRoot":"","sources":["../../src/services/mcp-launch-binding-queue.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC/D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,4BAA4B;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA2DD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,qBAAqB,GAAG,gBAAgB,GAAG,IAAI,CA+B7F;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,uBAAuB,GAAG,IAAI,CAkD3G;AAED,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,OAAO,GAAG,MAAM,CAOpE;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAElD"}
|
|
@@ -2,12 +2,6 @@ import path from "node:path";
|
|
|
2
2
|
import { schedulerBaseUrl as defaultSchedulerBaseUrl } from "../config.js";
|
|
3
3
|
import { getRuntimeAccessToken, loadRuntimeBinding, normalizeSchedulerBaseUrl } from "./runtime-binding.js";
|
|
4
4
|
const LAUNCH_BINDING_TTL_MS = 5 * 60 * 1000;
|
|
5
|
-
/**
|
|
6
|
-
* 每个 agent 最新的 MCP session token 缓存。
|
|
7
|
-
* key = agentId,value = { runtimeAccessToken, updatedAt }
|
|
8
|
-
* 当 /runtime/start 入队新 binding 时更新,供 MCP node 401 后刷新使用。
|
|
9
|
-
*/
|
|
10
|
-
const latestAgentTokens = new Map();
|
|
11
5
|
const launchBindings = [];
|
|
12
6
|
function normalizeWorkspacePath(workspacePath) {
|
|
13
7
|
const raw = String(workspacePath || "").trim();
|
|
@@ -82,14 +76,6 @@ export function enqueueMcpLaunchBinding(input) {
|
|
|
82
76
|
enqueuedAt: new Date().toISOString(),
|
|
83
77
|
};
|
|
84
78
|
launchBindings.push(binding);
|
|
85
|
-
// 缓存最新 token,供 MCP node 401 后刷新
|
|
86
|
-
const tokenValue = binding.runtimeAccessToken;
|
|
87
|
-
if (tokenValue) {
|
|
88
|
-
latestAgentTokens.set(agentId, {
|
|
89
|
-
runtimeAccessToken: tokenValue,
|
|
90
|
-
updatedAt: Date.now(),
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
79
|
return binding;
|
|
94
80
|
}
|
|
95
81
|
export function claimMcpLaunchBinding(request) {
|
|
@@ -145,14 +131,3 @@ export function getMcpLaunchQueueSize(workspacePath) {
|
|
|
145
131
|
export function clearMcpLaunchBindingQueues() {
|
|
146
132
|
launchBindings.splice(0, launchBindings.length);
|
|
147
133
|
}
|
|
148
|
-
/**
|
|
149
|
-
* 获取指定 agent 的最新 MCP session token。
|
|
150
|
-
* 供 MCP node 在 401 后向 bridge 查询最新 token 使用。
|
|
151
|
-
*/
|
|
152
|
-
export function getLatestAgentToken(agentId) {
|
|
153
|
-
const cached = latestAgentTokens.get(agentId);
|
|
154
|
-
if (!cached || !cached.runtimeAccessToken) {
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
157
|
-
return { runtimeAccessToken: cached.runtimeAccessToken };
|
|
158
|
-
}
|
|
@@ -15,12 +15,6 @@ interface RuntimeStatusActionInfo {
|
|
|
15
15
|
export interface RuntimeCallbackAuthOptions {
|
|
16
16
|
runtimeAccessToken?: string;
|
|
17
17
|
}
|
|
18
|
-
export interface RuntimeOutputMetadata {
|
|
19
|
-
sourceEventType?: string;
|
|
20
|
-
logLevel?: "info" | "warn" | "error";
|
|
21
|
-
logMessage?: string;
|
|
22
|
-
logCategory?: string;
|
|
23
|
-
}
|
|
24
18
|
/** 活跃会话存储 */
|
|
25
19
|
export declare const sessions: Map<string, Session>;
|
|
26
20
|
/**
|
|
@@ -43,7 +37,9 @@ export declare function sendStatus(agentId: string, sessionId: string | null, st
|
|
|
43
37
|
* @param sessionId - 会话 ID
|
|
44
38
|
* @param seq - 序列号
|
|
45
39
|
*/
|
|
46
|
-
export declare function sendOutput(agentId: string, output: string, sessionId: string, seq: number, metadata?:
|
|
40
|
+
export declare function sendOutput(agentId: string, output: string, sessionId: string, seq: number, metadata?: {
|
|
41
|
+
sourceEventType?: string;
|
|
42
|
+
}, authOptions?: RuntimeCallbackAuthOptions): Promise<void>;
|
|
47
43
|
/**
|
|
48
44
|
* 发送 AskUserQuestion 事件到调度器。
|
|
49
45
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-output.d.ts","sourceRoot":"","sources":["../../src/services/session-output.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,UAAU,uBAAuB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,0BAA0B;IACzC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;
|
|
1
|
+
{"version":3,"file":"session-output.d.ts","sourceRoot":"","sources":["../../src/services/session-output.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,UAAU,uBAAuB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,0BAA0B;IACzC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAmBD,aAAa;AACb,eAAO,MAAM,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAa,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,uBAAuB,EACpC,KAAK,CAAC,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,EACrD,WAAW,CAAC,EAAE,0BAA0B,GACvC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,CA0C7C;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE;IAAE,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,EACvC,WAAW,CAAC,EAAE,0BAA0B,GACvC,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAAE,EACpB,WAAW,CAAC,EAAE,0BAA0B,GACvC,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAgBzE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAa3D;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCzE"}
|
|
@@ -33,7 +33,6 @@ export declare class ACodeRuntime extends EventEmitter {
|
|
|
33
33
|
private requestChatCompletion;
|
|
34
34
|
private readChatCompletionStream;
|
|
35
35
|
private handleToolCalls;
|
|
36
|
-
private callMcpToolWithTimeout;
|
|
37
36
|
private appendSyntheticMultimodalUserMessage;
|
|
38
37
|
private appendToolFailureResult;
|
|
39
38
|
private connectMcpServers;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAiB3C,OAAO,KAAK,EAOV,kBAAkB,EAEnB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAiB3C,OAAO,KAAK,EAOV,kBAAkB,EAEnB,MAAM,YAAY,CAAC;AA44BpB,qBAAa,YAAa,SAAQ,YAAY;IAmChC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAlCnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IAEvC,OAAO,CAAC,KAAK,CAoBX;IAEF,OAAO,CAAC,eAAe,CAAgC;IAEvD,OAAO,CAAC,WAAW,CAAoC;IAEvD,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,sBAAsB,CAAS;gBAEV,MAAM,EAAE,kBAAkB;IAevD,OAAO,CAAC,cAAc;IAatB;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwF5B;;;;OAIG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAM9B,aAAa;IA2E3B,oDAAoD;IAC9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B,uCAAuC;IACjC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA8B3B,OAAO,CAAC,kBAAkB;YAaZ,YAAY;YA6DZ,qBAAqB;YAiHrB,wBAAwB;YA6ExB,eAAe;YAwJf,oCAAoC;IAkBlD,OAAO,CAAC,uBAAuB;YAuBjB,iBAAiB;IA2C/B,OAAO,CAAC,kBAAkB;YA2BZ,oBAAoB;CAiBnC"}
|
|
@@ -25,15 +25,9 @@ const DEFAULT_PROVIDER_REQUEST_TIMEOUT_MS = 60_000;
|
|
|
25
25
|
const DEFAULT_PROVIDER_REQUEST_RETRY_COUNT = 2;
|
|
26
26
|
const DEFAULT_PROVIDER_REQUEST_RETRY_DELAY_MS = 1000;
|
|
27
27
|
const DEFAULT_MCP_TOOL_CALL_TIMEOUT_MS = 60_000;
|
|
28
|
-
const DEFAULT_MCP_POLLING_TOOL_CALL_TIMEOUT_MS =
|
|
29
|
-
const MCP_SDK_MAX_SAFE_TIMEOUT_MS = 2_147_483_647;
|
|
28
|
+
const DEFAULT_MCP_POLLING_TOOL_CALL_TIMEOUT_MS = 30 * 60_000;
|
|
30
29
|
const DEFAULT_RUNTIME_SHUTDOWN_TIMEOUT_MS = 10_000;
|
|
31
30
|
const MAX_INLINE_IMAGE_BYTES = 10 * 1024 * 1024;
|
|
32
|
-
const MAX_REQUEST_BODY_BYTES = 800 * 1024;
|
|
33
|
-
const CONTEXT_COMPACTION_RECENT_MESSAGE_COUNT = 12;
|
|
34
|
-
const CONTEXT_COMPACTION_MAX_SUMMARY_CHARS = 6000;
|
|
35
|
-
const CONTEXT_COMPACTION_MAX_PREVIEW_CHARS = 500;
|
|
36
|
-
const CONTEXT_COMPACTION_SUMMARY_PREFIX = "ACode context compaction summary:";
|
|
37
31
|
async function withTimeout(operation, timeoutMs, label, onTimeout) {
|
|
38
32
|
if (timeoutMs <= 0) {
|
|
39
33
|
return await operation;
|
|
@@ -75,39 +69,6 @@ function normalizePositiveInteger(value, fallback) {
|
|
|
75
69
|
const numeric = normalizeNonNegativeInteger(value, fallback);
|
|
76
70
|
return numeric > 0 ? numeric : fallback;
|
|
77
71
|
}
|
|
78
|
-
/**
|
|
79
|
-
* Estimate the token count of the initial context (system prompt + tool definitions).
|
|
80
|
-
*
|
|
81
|
-
* Uses a blended character-based heuristic: approximately 1 token per 3 characters,
|
|
82
|
-
* which balances English (~4 chars/token) and CJK (~1.5–2 chars/token) content
|
|
83
|
-
* commonly found in system prompts and MCP tool descriptions.
|
|
84
|
-
*/
|
|
85
|
-
const ESTIMATED_CHARS_PER_TOKEN = 3;
|
|
86
|
-
function estimateTokensFromText(value) {
|
|
87
|
-
if (!value)
|
|
88
|
-
return 0;
|
|
89
|
-
return Math.ceil(value.length / ESTIMATED_CHARS_PER_TOKEN);
|
|
90
|
-
}
|
|
91
|
-
function estimateContextTokens(systemPrompt, exposedTools) {
|
|
92
|
-
let charCount = systemPrompt.length;
|
|
93
|
-
for (const tool of exposedTools) {
|
|
94
|
-
const toolName = tool.kind === "mcp" ? tool.toolName : tool.toolName;
|
|
95
|
-
charCount += toolName.length;
|
|
96
|
-
if (tool.kind === "mcp") {
|
|
97
|
-
if (tool.description) {
|
|
98
|
-
charCount += tool.description.length;
|
|
99
|
-
}
|
|
100
|
-
charCount += JSON.stringify(tool.inputSchema).length;
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
const builtIn = tool;
|
|
104
|
-
if (builtIn.inputSchema) {
|
|
105
|
-
charCount += JSON.stringify(builtIn.inputSchema).length;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return Math.ceil(charCount / ESTIMATED_CHARS_PER_TOKEN);
|
|
110
|
-
}
|
|
111
72
|
async function delay(ms) {
|
|
112
73
|
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
113
74
|
}
|
|
@@ -157,7 +118,7 @@ function resolveProviderConfig(config, acodeConfig) {
|
|
|
157
118
|
requestTimeoutMs: normalizeNonNegativeInteger(providerOptions?.requestTimeoutMs ?? providerOptions?.timeoutMs, DEFAULT_PROVIDER_REQUEST_TIMEOUT_MS),
|
|
158
119
|
requestRetryCount: normalizeNonNegativeInteger(providerOptions?.requestRetryCount, DEFAULT_PROVIDER_REQUEST_RETRY_COUNT),
|
|
159
120
|
mcpToolTimeoutMs: normalizePositiveInteger(providerOptions?.mcpToolTimeoutMs, DEFAULT_MCP_TOOL_CALL_TIMEOUT_MS),
|
|
160
|
-
mcpPollingToolTimeoutMs:
|
|
121
|
+
mcpPollingToolTimeoutMs: normalizePositiveInteger(providerOptions?.mcpPollingToolTimeoutMs, DEFAULT_MCP_POLLING_TOOL_CALL_TIMEOUT_MS),
|
|
161
122
|
supportsImageInput: modelSupportsImageInput(model, defaultProvider, providerOptions),
|
|
162
123
|
};
|
|
163
124
|
}
|
|
@@ -362,38 +323,6 @@ function contentPreview(content) {
|
|
|
362
323
|
.join(" ")
|
|
363
324
|
.trim();
|
|
364
325
|
}
|
|
365
|
-
function truncateText(value, maxChars) {
|
|
366
|
-
if (value.length <= maxChars) {
|
|
367
|
-
return value;
|
|
368
|
-
}
|
|
369
|
-
return `${value.slice(0, maxChars)}…`;
|
|
370
|
-
}
|
|
371
|
-
function summarizeToolCalls(toolCalls) {
|
|
372
|
-
if (!toolCalls || toolCalls.length === 0) {
|
|
373
|
-
return "";
|
|
374
|
-
}
|
|
375
|
-
return toolCalls
|
|
376
|
-
.map((toolCall) => {
|
|
377
|
-
const args = truncateText(toolCall.function.arguments.replace(/\s+/g, " ").trim(), 160);
|
|
378
|
-
return `${toolCall.function.name}(${args})`;
|
|
379
|
-
})
|
|
380
|
-
.join(", ");
|
|
381
|
-
}
|
|
382
|
-
function summarizeConversationMessage(message, index) {
|
|
383
|
-
const preview = truncateText(contentPreview(message.content).replace(/\s+/g, " ").trim(), CONTEXT_COMPACTION_MAX_PREVIEW_CHARS);
|
|
384
|
-
const toolCalls = summarizeToolCalls(message.tool_calls);
|
|
385
|
-
const parts = [`${index + 1}. ${message.role}`];
|
|
386
|
-
if (toolCalls) {
|
|
387
|
-
parts.push(`tool_calls=${toolCalls}`);
|
|
388
|
-
}
|
|
389
|
-
if (message.tool_call_id) {
|
|
390
|
-
parts.push(`tool_call_id=${message.tool_call_id}`);
|
|
391
|
-
}
|
|
392
|
-
if (preview) {
|
|
393
|
-
parts.push(`content=${preview}`);
|
|
394
|
-
}
|
|
395
|
-
return parts.join(" | ");
|
|
396
|
-
}
|
|
397
326
|
/**
|
|
398
327
|
* 解析 ACode 工具权限配置。
|
|
399
328
|
* 主流程:运行时配置优先 -> `.acode/config.json` 次之 -> 兼容旧式 allowedTools/deniedTools 字段。
|
|
@@ -543,105 +472,8 @@ function toToolResultText(result) {
|
|
|
543
472
|
function getErrorMessage(error) {
|
|
544
473
|
return error instanceof Error ? error.message : String(error);
|
|
545
474
|
}
|
|
546
|
-
function estimateMessageSizeBytes(message) {
|
|
547
|
-
let size = 16;
|
|
548
|
-
if (typeof message.content === "string") {
|
|
549
|
-
size += message.content.length * 2;
|
|
550
|
-
}
|
|
551
|
-
else if (Array.isArray(message.content)) {
|
|
552
|
-
for (const part of message.content) {
|
|
553
|
-
if (typeof part === "object" && part !== null) {
|
|
554
|
-
size += JSON.stringify(part).length;
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
if (message.tool_calls) {
|
|
559
|
-
size += JSON.stringify(message.tool_calls).length;
|
|
560
|
-
}
|
|
561
|
-
if (message.tool_call_id) {
|
|
562
|
-
size += message.tool_call_id.length;
|
|
563
|
-
}
|
|
564
|
-
return size;
|
|
565
|
-
}
|
|
566
|
-
function isContextCompactionSummaryMessage(message) {
|
|
567
|
-
return (message.role === "system" &&
|
|
568
|
-
typeof message.content === "string" &&
|
|
569
|
-
message.content.startsWith(CONTEXT_COMPACTION_SUMMARY_PREFIX));
|
|
570
|
-
}
|
|
571
|
-
function truncateConversationIfNeeded(conversation, maxBytes) {
|
|
572
|
-
let totalBytes = 0;
|
|
573
|
-
for (const message of conversation) {
|
|
574
|
-
totalBytes += estimateMessageSizeBytes(message);
|
|
575
|
-
}
|
|
576
|
-
if (totalBytes <= maxBytes) {
|
|
577
|
-
return 0;
|
|
578
|
-
}
|
|
579
|
-
return compactConversationForRequestLimit(conversation, maxBytes);
|
|
580
|
-
}
|
|
581
|
-
function compactConversationForRequestLimit(conversation, maxBytes) {
|
|
582
|
-
const baseSystemMessages = conversation.filter((m) => m.role === "system" && !isContextCompactionSummaryMessage(m));
|
|
583
|
-
const compactableMessages = conversation.filter((m) => m.role !== "system" || isContextCompactionSummaryMessage(m));
|
|
584
|
-
const keptMessages = [];
|
|
585
|
-
let keptBytes = baseSystemMessages.reduce((sum, m) => sum + estimateMessageSizeBytes(m), 0);
|
|
586
|
-
for (let i = compactableMessages.length - 1; i >= 0; i--) {
|
|
587
|
-
const messageSize = estimateMessageSizeBytes(compactableMessages[i]);
|
|
588
|
-
if (keptBytes + messageSize > maxBytes && keptMessages.length > 0) {
|
|
589
|
-
break;
|
|
590
|
-
}
|
|
591
|
-
keptBytes += messageSize;
|
|
592
|
-
keptMessages.unshift(compactableMessages[i]);
|
|
593
|
-
}
|
|
594
|
-
return compactConversationWithSummary(conversation, compactableMessages.length - keptMessages.length);
|
|
595
|
-
}
|
|
596
|
-
function compactConversationForContextOverflow(conversation) {
|
|
597
|
-
const compactableMessages = conversation.filter((m) => m.role !== "system" || isContextCompactionSummaryMessage(m));
|
|
598
|
-
const removableCount = Math.max(0, compactableMessages.length - CONTEXT_COMPACTION_RECENT_MESSAGE_COUNT);
|
|
599
|
-
return compactConversationWithSummary(conversation, removableCount);
|
|
600
|
-
}
|
|
601
|
-
function compactConversationWithSummary(conversation, requestedRemovedCount) {
|
|
602
|
-
const baseSystemMessages = conversation.filter((m) => m.role === "system" && !isContextCompactionSummaryMessage(m));
|
|
603
|
-
const compactableMessages = conversation.filter((m) => m.role !== "system" || isContextCompactionSummaryMessage(m));
|
|
604
|
-
const removedCount = Math.max(0, Math.min(requestedRemovedCount, compactableMessages.length));
|
|
605
|
-
if (removedCount === 0) {
|
|
606
|
-
return 0;
|
|
607
|
-
}
|
|
608
|
-
const removedMessages = compactableMessages.slice(0, removedCount);
|
|
609
|
-
const keptMessages = compactableMessages.slice(removedCount);
|
|
610
|
-
const summaryLines = removedMessages.map((message, index) => summarizeConversationMessage(message, index));
|
|
611
|
-
const summary = truncateText(summaryLines.join("\n"), CONTEXT_COMPACTION_MAX_SUMMARY_CHARS);
|
|
612
|
-
conversation.length = 0;
|
|
613
|
-
conversation.push(...baseSystemMessages);
|
|
614
|
-
conversation.push({
|
|
615
|
-
role: "system",
|
|
616
|
-
content: [
|
|
617
|
-
CONTEXT_COMPACTION_SUMMARY_PREFIX,
|
|
618
|
-
`${removedCount} earlier compactable conversation messages were summarized to keep the provider request within context limits.`,
|
|
619
|
-
"Preserve the user's goal, decisions, tool results, file paths, errors, and unresolved tasks from this summary. Recent messages below remain authoritative.",
|
|
620
|
-
summary,
|
|
621
|
-
].join("\n"),
|
|
622
|
-
});
|
|
623
|
-
conversation.push(...keptMessages);
|
|
624
|
-
return removedCount;
|
|
625
|
-
}
|
|
626
|
-
function isContextOverflowProviderRequestError(error) {
|
|
627
|
-
const message = getErrorMessage(error).toLowerCase();
|
|
628
|
-
return (message.includes("context_length_exceeded") ||
|
|
629
|
-
message.includes("context length") ||
|
|
630
|
-
message.includes("maximum context") ||
|
|
631
|
-
message.includes("max context") ||
|
|
632
|
-
message.includes("token limit") ||
|
|
633
|
-
message.includes("tokens exceed") ||
|
|
634
|
-
message.includes("too many tokens") ||
|
|
635
|
-
message.includes("input is too long") ||
|
|
636
|
-
message.includes("prompt is too long") ||
|
|
637
|
-
message.includes("request too large") ||
|
|
638
|
-
message.includes("413"));
|
|
639
|
-
}
|
|
640
475
|
function isRetryableProviderRequestError(error) {
|
|
641
476
|
const message = getErrorMessage(error).toLowerCase();
|
|
642
|
-
if (isContextOverflowProviderRequestError(error)) {
|
|
643
|
-
return false;
|
|
644
|
-
}
|
|
645
477
|
return (message.includes("fetch failed") ||
|
|
646
478
|
message.includes("timed out") ||
|
|
647
479
|
message.includes("econnreset") ||
|
|
@@ -652,14 +484,6 @@ function isRetryableProviderRequestError(error) {
|
|
|
652
484
|
message.includes("503") ||
|
|
653
485
|
message.includes("504"));
|
|
654
486
|
}
|
|
655
|
-
function isMcpRequestTimeoutError(error) {
|
|
656
|
-
if (typeof error !== "object" || error === null) {
|
|
657
|
-
return false;
|
|
658
|
-
}
|
|
659
|
-
const code = Reflect.get(error, "code");
|
|
660
|
-
const message = getErrorMessage(error).toLowerCase();
|
|
661
|
-
return code === -32001 || message.includes("request timed out");
|
|
662
|
-
}
|
|
663
487
|
function getErrorType(error) {
|
|
664
488
|
if (typeof error === "object" && error !== null) {
|
|
665
489
|
const code = Reflect.get(error, "code");
|
|
@@ -880,7 +704,6 @@ export class ACodeRuntime extends EventEmitter {
|
|
|
880
704
|
workingDirectory: this.config.workingDirectory,
|
|
881
705
|
model: provider.model,
|
|
882
706
|
commandCount: commands.length,
|
|
883
|
-
estimatedContextTokens: estimateContextTokens(systemPrompt, exposedTools),
|
|
884
707
|
});
|
|
885
708
|
this.emitAcodeEvent("mcp_status", {
|
|
886
709
|
configPath: this.config.configPath,
|
|
@@ -1059,17 +882,12 @@ export class ACodeRuntime extends EventEmitter {
|
|
|
1059
882
|
const toolCalls = Array.isArray(message?.tool_calls)
|
|
1060
883
|
? message.tool_calls
|
|
1061
884
|
: [];
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
inputTokens: rtInputTokens,
|
|
1069
|
-
outputTokens: rtOutputTokens,
|
|
1070
|
-
};
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
885
|
+
finalUsage = {
|
|
886
|
+
inputTokens: response.usage?.prompt_tokens ?? response.usage?.input_tokens ?? 0,
|
|
887
|
+
outputTokens: response.usage?.completion_tokens ??
|
|
888
|
+
response.usage?.output_tokens ??
|
|
889
|
+
0,
|
|
890
|
+
};
|
|
1073
891
|
this.state.conversation.push({
|
|
1074
892
|
role: "assistant",
|
|
1075
893
|
content: content || null,
|
|
@@ -1101,42 +919,26 @@ export class ACodeRuntime extends EventEmitter {
|
|
|
1101
919
|
if (!baseURL) {
|
|
1102
920
|
throw new Error("ACode provider baseURL is not configured");
|
|
1103
921
|
}
|
|
1104
|
-
const
|
|
1105
|
-
|
|
1106
|
-
this.
|
|
1107
|
-
|
|
1108
|
-
});
|
|
1109
|
-
}
|
|
1110
|
-
const allowedTools = this.state.exposedTools.filter((tool) => isToolAllowed(tool, this.state.permissions, commandAllowedTools));
|
|
1111
|
-
const buildBody = () => {
|
|
1112
|
-
const body = {
|
|
1113
|
-
model: provider.model,
|
|
1114
|
-
messages: this.state.conversation,
|
|
1115
|
-
stream: provider.stream,
|
|
1116
|
-
};
|
|
1117
|
-
if (allowedTools.length > 0) {
|
|
1118
|
-
body.tools = toOpenAiTools(allowedTools);
|
|
1119
|
-
body.tool_choice = "auto";
|
|
1120
|
-
}
|
|
1121
|
-
return body;
|
|
1122
|
-
};
|
|
1123
|
-
const emitAiRequest = (body) => {
|
|
1124
|
-
const requestBody = JSON.stringify(body, null, 2);
|
|
1125
|
-
this.emitAcodeEvent("ai_request", {
|
|
1126
|
-
model: provider.model,
|
|
1127
|
-
endpoint: summarizeProviderUrl(baseURL),
|
|
1128
|
-
stream: provider.stream,
|
|
1129
|
-
messageCount: this.state.conversation.length,
|
|
1130
|
-
toolCount: allowedTools.length,
|
|
1131
|
-
lastUserMessagePreview: summarizeLastUserMessage(this.state.conversation),
|
|
1132
|
-
estimatedContextTokens: estimateTokensFromText(requestBody),
|
|
1133
|
-
requestBody,
|
|
1134
|
-
});
|
|
922
|
+
const body = {
|
|
923
|
+
model: provider.model,
|
|
924
|
+
messages: this.state.conversation,
|
|
925
|
+
stream: provider.stream,
|
|
1135
926
|
};
|
|
1136
|
-
|
|
1137
|
-
|
|
927
|
+
const allowedTools = this.state.exposedTools.filter((tool) => isToolAllowed(tool, this.state.permissions, commandAllowedTools));
|
|
928
|
+
if (allowedTools.length > 0) {
|
|
929
|
+
body.tools = toOpenAiTools(allowedTools);
|
|
930
|
+
body.tool_choice = "auto";
|
|
931
|
+
}
|
|
932
|
+
this.emitAcodeEvent("ai_request", {
|
|
933
|
+
model: provider.model,
|
|
934
|
+
endpoint: summarizeProviderUrl(baseURL),
|
|
935
|
+
stream: provider.stream,
|
|
936
|
+
messageCount: this.state.conversation.length,
|
|
937
|
+
toolCount: allowedTools.length,
|
|
938
|
+
lastUserMessagePreview: summarizeLastUserMessage(this.state.conversation),
|
|
939
|
+
requestBody: JSON.stringify(body, null, 2),
|
|
940
|
+
});
|
|
1138
941
|
const maxAttempts = provider.requestRetryCount + 1;
|
|
1139
|
-
let contextOverflowCompacted = false;
|
|
1140
942
|
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
1141
943
|
this.abortController = new AbortController();
|
|
1142
944
|
let timedOut = false;
|
|
@@ -1177,23 +979,6 @@ export class ACodeRuntime extends EventEmitter {
|
|
|
1177
979
|
requestError =
|
|
1178
980
|
error instanceof Error ? error : new Error(String(error));
|
|
1179
981
|
}
|
|
1180
|
-
if (!contextOverflowCompacted &&
|
|
1181
|
-
!this.abortRequested &&
|
|
1182
|
-
!this.state.terminated &&
|
|
1183
|
-
isContextOverflowProviderRequestError(requestError)) {
|
|
1184
|
-
const compactedCount = compactConversationForContextOverflow(this.state.conversation);
|
|
1185
|
-
contextOverflowCompacted = true;
|
|
1186
|
-
if (compactedCount === 0) {
|
|
1187
|
-
throw requestError;
|
|
1188
|
-
}
|
|
1189
|
-
this.emitAcodeEvent("warning", {
|
|
1190
|
-
message: `ACode provider context limit exceeded; summarized ${compactedCount} older messages and rebuilt the request instead of retrying the same oversized payload`,
|
|
1191
|
-
});
|
|
1192
|
-
body = buildBody();
|
|
1193
|
-
emitAiRequest(body);
|
|
1194
|
-
attempt -= 1;
|
|
1195
|
-
continue;
|
|
1196
|
-
}
|
|
1197
982
|
const shouldRetry = attempt < maxAttempts &&
|
|
1198
983
|
!this.abortRequested &&
|
|
1199
984
|
!this.state.terminated &&
|
|
@@ -1364,11 +1149,13 @@ export class ACodeRuntime extends EventEmitter {
|
|
|
1364
1149
|
arguments: toolArguments,
|
|
1365
1150
|
argumentsPreview: summarizeToolArguments(toolArguments),
|
|
1366
1151
|
});
|
|
1367
|
-
const
|
|
1368
|
-
const toolTimeoutMs = isPollingTool
|
|
1152
|
+
const toolTimeoutMs = isMcpPollingToolName(tool.toolName)
|
|
1369
1153
|
? this.state.provider.mcpPollingToolTimeoutMs
|
|
1370
1154
|
: this.state.provider.mcpToolTimeoutMs;
|
|
1371
|
-
const result = await
|
|
1155
|
+
const result = await withTimeout(connection.client.callTool({
|
|
1156
|
+
name: tool.toolName,
|
|
1157
|
+
arguments: toolArguments,
|
|
1158
|
+
}, undefined, { timeout: toolTimeoutMs }), toolTimeoutMs, `ACode MCP tool ${tool.serverName}/${tool.toolName}`);
|
|
1372
1159
|
await this.hookBus.dispatch("PostToolUse", {
|
|
1373
1160
|
source: "mcp",
|
|
1374
1161
|
serverName: tool.serverName,
|
|
@@ -1395,27 +1182,6 @@ export class ACodeRuntime extends EventEmitter {
|
|
|
1395
1182
|
}
|
|
1396
1183
|
}
|
|
1397
1184
|
}
|
|
1398
|
-
async callMcpToolWithTimeout(connection, tool, toolArguments, timeoutMs, retrySdkTimeout) {
|
|
1399
|
-
const sdkTimeout = timeoutMs > 0 ? timeoutMs : MCP_SDK_MAX_SAFE_TIMEOUT_MS;
|
|
1400
|
-
while (true) {
|
|
1401
|
-
try {
|
|
1402
|
-
return await withTimeout(connection.client.callTool({
|
|
1403
|
-
name: tool.toolName,
|
|
1404
|
-
arguments: toolArguments,
|
|
1405
|
-
}, undefined, { timeout: sdkTimeout }), timeoutMs, `ACode MCP tool ${tool.serverName}/${tool.toolName}`);
|
|
1406
|
-
}
|
|
1407
|
-
catch (error) {
|
|
1408
|
-
if (!retrySdkTimeout ||
|
|
1409
|
-
timeoutMs > 0 ||
|
|
1410
|
-
!isMcpRequestTimeoutError(error)) {
|
|
1411
|
-
throw error;
|
|
1412
|
-
}
|
|
1413
|
-
this.emitAcodeEvent("warning", {
|
|
1414
|
-
message: `ACode MCP polling tool ${tool.serverName}/${tool.toolName} reached the MCP SDK timeout window and will continue polling.`,
|
|
1415
|
-
});
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1419
1185
|
async appendSyntheticMultimodalUserMessage(toolResultText) {
|
|
1420
1186
|
const parsedContent = parseAttachmentMessage(toolResultText);
|
|
1421
1187
|
if (!parsedContent.hasImages) {
|
|
@@ -45,7 +45,7 @@ export interface ACodeSkillMetadata {
|
|
|
45
45
|
description?: string;
|
|
46
46
|
directory: string;
|
|
47
47
|
}
|
|
48
|
-
export type ACodeEventType = "session_started" | "ai_request" | "thinking_delta" | "assistant_delta" | "command_status" | "mcp_status" | "skill_status" | "
|
|
48
|
+
export type ACodeEventType = "session_started" | "ai_request" | "thinking_delta" | "assistant_delta" | "command_status" | "mcp_status" | "skill_status" | "turn_complete" | "session_complete" | "error";
|
|
49
49
|
export interface ACodeEvent {
|
|
50
50
|
type: ACodeEventType;
|
|
51
51
|
sessionId: string;
|