aws-runtime-bridge 1.9.50 → 1.9.51
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 +17 -3
- package/dist/routes/file-diff-rollback.d.ts +17 -3
- package/dist/routes/file-diff-rollback.d.ts.map +1 -1
- package/dist/routes/file-diff-rollback.js +52 -29
- package/package/acode/dist/runtime.d.ts +36 -0
- package/package/acode/dist/runtime.d.ts.map +1 -1
- package/package/acode/dist/runtime.js +82 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AcodeSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/AcodeSdkAdapter.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"AcodeSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/AcodeSdkAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1801,13 +1801,27 @@ export class AcodeSdkAdapter extends EventEmitter {
|
|
|
1801
1801
|
currentEntry.watchdogLastDataFlowTime = now;
|
|
1802
1802
|
return;
|
|
1803
1803
|
}
|
|
1804
|
-
//
|
|
1805
|
-
|
|
1804
|
+
// ★ 看门狗只在 thinking 状态工作:检测 ai_request 发出后 provider 流挂死。
|
|
1805
|
+
// tool_using 状态下完全不触发看门狗——每个工具都有自己的超时机制:
|
|
1806
|
+
// - MCP 普通工具:60s(DEFAULT_MCP_TOOL_CALL_TIMEOUT_MS)
|
|
1807
|
+
// - 内置文件工具/Bash:fallbackTimeoutMs / 自带 timeout_ms
|
|
1808
|
+
// - ask_user_question:question_request 事件取消看门狗,依赖用户回答
|
|
1809
|
+
// - await_sub_agents:无超时,依赖子 agent 自己的 runtime 看门狗
|
|
1810
|
+
// 若在 tool_using 触发看门狗,abort() 即使能中断工具,也会打断 agent 正在进行的
|
|
1811
|
+
// 合法长时间操作(如等待子 agent 完成),违反"看门狗不应影响 agent 动作"原则。
|
|
1812
|
+
// 同时重置计时基准,避免 tool_using 期间累积时间带到下一次 thinking 误触发。
|
|
1813
|
+
if (status === "tool_using") {
|
|
1814
|
+
currentEntry.watchdogLastDataFlowTime = now;
|
|
1815
|
+
currentEntry.watchdogSubmitStartTime = now;
|
|
1816
|
+
return;
|
|
1817
|
+
}
|
|
1818
|
+
// 其他非 thinking 状态(compacting/error 等)不计时
|
|
1819
|
+
if (status !== "thinking") {
|
|
1806
1820
|
return;
|
|
1807
1821
|
}
|
|
1808
1822
|
const submitElapsed = now - (currentEntry.watchdogSubmitStartTime || now);
|
|
1809
1823
|
const dataFlowElapsed = now - (currentEntry.watchdogLastDataFlowTime || now);
|
|
1810
|
-
// 数据流超时(40s 无流式数据)—
|
|
1824
|
+
// 数据流超时(40s 无流式数据)— 仅 thinking 状态触发,比 submit 超时(120s)更短,优先触发
|
|
1811
1825
|
if (dataFlowElapsed >= ACODE_DATA_FLOW_STREAM_WATCHDOG_MS) {
|
|
1812
1826
|
console.warn(`[ACode] CRITICAL: Data flow watchdog triggered after ${Math.round(dataFlowElapsed / 1000)}s ` +
|
|
1813
1827
|
`(source: ${source}, session: ${sessionId}, status: ${status}). ` +
|
|
@@ -9,12 +9,14 @@
|
|
|
9
9
|
* - CREATE:检查文件是否存在,准备删除
|
|
10
10
|
* - UPDATE:读取 diff patch,读取当前文件内容,在内存中应用反向 patch 验证是否成功
|
|
11
11
|
* - DELETE:读取删除前的完整内容,准备重建
|
|
12
|
-
* 2.
|
|
13
|
-
*
|
|
12
|
+
* 2. 原子执行:预检全部通过后,批量写入文件系统;任一预检失败则返回 previewFailed=true,
|
|
13
|
+
* 由调用方(前端)弹出"跳过不通过项 / 文件全量覆盖"二选一对话框。
|
|
14
|
+
* skipFailed=true 时仅执行通过项(partial);否则不写盘。
|
|
14
15
|
*
|
|
15
16
|
* 反向操作映射:
|
|
16
17
|
* CREATE → DELETE(删除创建的文件)
|
|
17
|
-
* UPDATE → 应用反向 diff patch
|
|
18
|
+
* UPDATE → 应用反向 diff patch(精确撤销修改的部分,保留用户后续改动);
|
|
19
|
+
* 若补丁无法精确应用(上下文不匹配=冲突),报为预检失败,不静默整文件覆盖
|
|
18
20
|
* DELETE → 重新创建被删除的文件(根据 cacheKey 从 bridge 本地缓存读取)
|
|
19
21
|
*/
|
|
20
22
|
export declare const fileDiffRollbackRouter: import("express-serve-static-core").Router;
|
|
@@ -31,6 +33,13 @@ export interface ReverseOperation {
|
|
|
31
33
|
export interface DiffRollbackRequest {
|
|
32
34
|
workspacePath: string;
|
|
33
35
|
operations: ReverseOperation[];
|
|
36
|
+
/**
|
|
37
|
+
* 预检部分失败时的处理策略。
|
|
38
|
+
* - 缺省/ false:任一预检失败则直接返回 previewFailed,不写盘(由调用方决定后续动作)。
|
|
39
|
+
* - true:仅执行通过预检的操作(preview.plan 中的项),跳过失败项,
|
|
40
|
+
* 返回 partial:true,让调用方可以"跳过不通过项"而非整工作区快照覆盖。
|
|
41
|
+
*/
|
|
42
|
+
skipFailed?: boolean;
|
|
34
43
|
}
|
|
35
44
|
/** 单条操作的执行状态 */
|
|
36
45
|
export interface OperationDetail {
|
|
@@ -50,6 +59,11 @@ export interface DiffRollbackResult {
|
|
|
50
59
|
errors: string[];
|
|
51
60
|
/** 当 ok=false 且未执行写盘时为 true */
|
|
52
61
|
previewFailed?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* 部分执行标志:skipFailed=true 且仅有部分操作通过预检时,
|
|
64
|
+
* 已对通过项执行写盘、跳过失败项,返回 partial:true。
|
|
65
|
+
*/
|
|
66
|
+
partial?: boolean;
|
|
53
67
|
/** 每条操作的详细状态 */
|
|
54
68
|
details: OperationDetail[];
|
|
55
69
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-diff-rollback.d.ts","sourceRoot":"","sources":["../../src/routes/file-diff-rollback.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"file-diff-rollback.d.ts","sourceRoot":"","sources":["../../src/routes/file-diff-rollback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAWH,eAAO,MAAM,sBAAsB,4CAAW,CAAC;AAE/C,MAAM,WAAW,gBAAgB;IAC/B,aAAa;IACb,iBAAiB,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAClD,mBAAmB;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,sBAAsB;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,gBAAgB;AAChB,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa;IACb,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC/E,gBAAgB;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,+BAA+B;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gBAAgB;IAChB,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B"}
|
|
@@ -9,12 +9,14 @@
|
|
|
9
9
|
* - CREATE:检查文件是否存在,准备删除
|
|
10
10
|
* - UPDATE:读取 diff patch,读取当前文件内容,在内存中应用反向 patch 验证是否成功
|
|
11
11
|
* - DELETE:读取删除前的完整内容,准备重建
|
|
12
|
-
* 2.
|
|
13
|
-
*
|
|
12
|
+
* 2. 原子执行:预检全部通过后,批量写入文件系统;任一预检失败则返回 previewFailed=true,
|
|
13
|
+
* 由调用方(前端)弹出"跳过不通过项 / 文件全量覆盖"二选一对话框。
|
|
14
|
+
* skipFailed=true 时仅执行通过项(partial);否则不写盘。
|
|
14
15
|
*
|
|
15
16
|
* 反向操作映射:
|
|
16
17
|
* CREATE → DELETE(删除创建的文件)
|
|
17
|
-
* UPDATE → 应用反向 diff patch
|
|
18
|
+
* UPDATE → 应用反向 diff patch(精确撤销修改的部分,保留用户后续改动);
|
|
19
|
+
* 若补丁无法精确应用(上下文不匹配=冲突),报为预检失败,不静默整文件覆盖
|
|
18
20
|
* DELETE → 重新创建被删除的文件(根据 cacheKey 从 bridge 本地缓存读取)
|
|
19
21
|
*/
|
|
20
22
|
import { promises as fs } from 'node:fs';
|
|
@@ -93,40 +95,42 @@ async function previewRollback(workspacePath, operations) {
|
|
|
93
95
|
details.push({ relativePath, originalOperation: 'UPDATE', status: 'preview_failed', reason });
|
|
94
96
|
break;
|
|
95
97
|
}
|
|
96
|
-
// 尝试用 diff patch
|
|
98
|
+
// 尝试用 diff patch 精确回滚。
|
|
99
|
+
// 关键设计:applyPatch 失败时不再静默回退到 beforeContent(那会丢弃用户/其他任务
|
|
100
|
+
// 对该文件的所有改动),而是报为 preview_failed,让前端弹出
|
|
101
|
+
// "跳过不通过项 / 文件全量覆盖" 二选一对话框。
|
|
97
102
|
const patch = await readDiffFromCache(normalizedWorkspace, op.cacheKey);
|
|
103
|
+
if (patch === null) {
|
|
104
|
+
const reason = `本地缓存中找不到 diff 补丁 (cacheKey=${op.cacheKey}),无法精确回滚`;
|
|
105
|
+
errors.push(`UPDATE rollback failed: ${reason} for ${relativePath}`);
|
|
106
|
+
details.push({ relativePath, originalOperation: 'UPDATE', status: 'preview_failed', reason });
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
98
109
|
let rollbackContent = null;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (result !== false) {
|
|
106
|
-
rollbackContent = result;
|
|
107
|
-
rollbackMethod = '反向 diff 补丁';
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
log.warn(`Diff patch failed for ${relativePath}, falling back to beforeContent`);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
catch (err) {
|
|
114
|
-
log.warn(`Diff patch error for ${relativePath}: ${err.message}, falling back to beforeContent`);
|
|
110
|
+
try {
|
|
111
|
+
const parsed = Diff.parsePatch(patch);
|
|
112
|
+
const reversed = Diff.reversePatch(parsed);
|
|
113
|
+
const result = Diff.applyPatch(currentContent, reversed);
|
|
114
|
+
if (result !== false) {
|
|
115
|
+
rollbackContent = result;
|
|
115
116
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (beforeContent === null) {
|
|
121
|
-
const reason = `diff 补丁应用失败且本地缓存中找不到 beforeContent (cacheKey=${op.cacheKey})`;
|
|
117
|
+
else {
|
|
118
|
+
// 反向 diff 补丁无法精确应用(上下文不匹配),
|
|
119
|
+
// 说明文件已被其他任务或用户修改了 AI 改动的同一区域,存在冲突。
|
|
120
|
+
const reason = `反向 diff 补丁无法精确应用:文件当前内容与 AI 变更后的预期上下文不匹配,可能已被其他任务或用户修改了相同区域,存在冲突`;
|
|
122
121
|
errors.push(`UPDATE rollback failed: ${reason} for ${relativePath}`);
|
|
123
122
|
details.push({ relativePath, originalOperation: 'UPDATE', status: 'preview_failed', reason });
|
|
124
123
|
break;
|
|
125
124
|
}
|
|
126
|
-
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
const reason = `反向 diff 补丁应用异常: ${err.message}`;
|
|
128
|
+
errors.push(`UPDATE rollback failed: ${reason} for ${relativePath}`);
|
|
129
|
+
details.push({ relativePath, originalOperation: 'UPDATE', status: 'preview_failed', reason });
|
|
130
|
+
break;
|
|
127
131
|
}
|
|
128
132
|
plan.push({ type: 'WRITE', fullPath, relativePath, originalOperation: 'UPDATE', content: rollbackContent });
|
|
129
|
-
details.push({ relativePath, originalOperation: 'UPDATE', status: 'preview_passed', action:
|
|
133
|
+
details.push({ relativePath, originalOperation: 'UPDATE', status: 'preview_passed', action: '应用反向 diff 补丁' });
|
|
130
134
|
// 更新内存状态:文件内容已回滚
|
|
131
135
|
fileContentMap.set(relativePath, rollbackContent);
|
|
132
136
|
break;
|
|
@@ -243,7 +247,7 @@ fileDiffRollbackRouter.post('/file-diff-rollback/preview', validateToken, async
|
|
|
243
247
|
* 无论成功失败,都返回每条操作的详细状态。
|
|
244
248
|
*/
|
|
245
249
|
fileDiffRollbackRouter.post('/file-diff-rollback/execute', validateToken, async (req, res) => {
|
|
246
|
-
const { workspacePath, operations } = req.body;
|
|
250
|
+
const { workspacePath, operations, skipFailed } = req.body;
|
|
247
251
|
if (!workspacePath || !Array.isArray(operations)) {
|
|
248
252
|
res.status(400).json({ error: 'workspacePath and operations (array) are required' });
|
|
249
253
|
return;
|
|
@@ -251,6 +255,25 @@ fileDiffRollbackRouter.post('/file-diff-rollback/execute', validateToken, async
|
|
|
251
255
|
// ── 第一步:内存预检 ──
|
|
252
256
|
const preview = await previewRollback(workspacePath, operations);
|
|
253
257
|
if (!preview.ok) {
|
|
258
|
+
// 策略:仅执行通过预检的项(跳过失败项)。
|
|
259
|
+
// preview.plan 只装通过项,且链式预演中失败项不会污染 fileContentMap,
|
|
260
|
+
// 因此通过项预计算出的目标内容天然保留了失败项的改动 —— 直接执行 plan 即等价于"跳过不通过项"。
|
|
261
|
+
if (skipFailed && preview.plan.length > 0) {
|
|
262
|
+
const execResult = await executePlan(preview.plan, preview.details);
|
|
263
|
+
const failedCount = preview.details.filter((d) => d.status === 'preview_failed').length;
|
|
264
|
+
log.warn(`Diff rollback partial execute: passed=${execResult.restored}, skippedFailed=${failedCount}, ioSkipped=${execResult.skipped}`);
|
|
265
|
+
const result = {
|
|
266
|
+
ok: execResult.errors.length === 0,
|
|
267
|
+
restored: execResult.restored,
|
|
268
|
+
skipped: execResult.skipped + failedCount,
|
|
269
|
+
errors: execResult.errors,
|
|
270
|
+
previewFailed: false,
|
|
271
|
+
partial: true,
|
|
272
|
+
details: execResult.details,
|
|
273
|
+
};
|
|
274
|
+
res.json(result);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
254
277
|
const result = {
|
|
255
278
|
ok: false,
|
|
256
279
|
restored: 0,
|
|
@@ -40,6 +40,20 @@ export declare class ACodeRuntime extends EventEmitter {
|
|
|
40
40
|
private submitQueue;
|
|
41
41
|
private activeTurn;
|
|
42
42
|
private abortRequested;
|
|
43
|
+
/**
|
|
44
|
+
* 当前正在 await_sub_agents 工具中阻塞等待的子 agent subId 集合。
|
|
45
|
+
*
|
|
46
|
+
* 用于让 abort()/stop() 能中断 awaitSubAgents 的阻塞:
|
|
47
|
+
* - awaitSubAgents 调用前把 subIds 加入此 set,finally 中移除
|
|
48
|
+
* - abort()/stop() 时对此 set 中每个 subId 调用 manager.abort(subId)
|
|
49
|
+
* - manager.abort 会 settle completionPromise(resolve with error)
|
|
50
|
+
* - 从而让 await completionPromise 解除阻塞,execute() 正常返回,
|
|
51
|
+
* executeSubmit 不再永久 pending,submitQueue 链恢复,后续 submit 可执行。
|
|
52
|
+
*
|
|
53
|
+
* 没有此机制时:abort() 只能中断 fetch 流,对 await completionPromise 无效,
|
|
54
|
+
* 导致 executeSubmit 永久阻塞 → submitQueue 死锁 → 后续 sendMessage 全部排队 → agent 无反应。
|
|
55
|
+
*/
|
|
56
|
+
private pendingAwaitedSubIds;
|
|
43
57
|
private sessionCompleteEmitted;
|
|
44
58
|
private contextVersion;
|
|
45
59
|
private readonly stopWaiters;
|
|
@@ -174,6 +188,28 @@ export declare class ACodeRuntime extends EventEmitter {
|
|
|
174
188
|
* 在 abort()/stop() 中调用,确保用户点停止或会话终止时 execute 不会永久阻塞。
|
|
175
189
|
*/
|
|
176
190
|
private rejectAllQuestionWaiters;
|
|
191
|
+
/**
|
|
192
|
+
* 取消当前正在 await_sub_agents 工具中阻塞等待的子 agent。
|
|
193
|
+
*
|
|
194
|
+
* 核心作用:让 abort()/stop() 能解除 awaitSubAgents 的阻塞,避免 submitQueue 死锁。
|
|
195
|
+
*
|
|
196
|
+
* 工作原理:
|
|
197
|
+
* 1. 遍历 pendingAwaitedSubIds(awaitSubAgents 工具执行期间记录的 subIds)
|
|
198
|
+
* 2. 对每个 subId 调用 manager.abort(subId)
|
|
199
|
+
* 3. manager.abort 会 settle completionPromise(resolve with error="aborted")
|
|
200
|
+
* 4. awaitSubAgents 中 await completionPromise 解除阻塞,execute() 正常返回
|
|
201
|
+
* 5. executeSubmit 完成,submit() Promise resolve,submitQueue 链恢复
|
|
202
|
+
* 6. 后续 sendMessage / auto-poll 的 submit 能正常排队执行
|
|
203
|
+
*
|
|
204
|
+
* 场景:看门狗触发 abort() 或用户点击停止时,agent 正卡在 await_sub_agents
|
|
205
|
+
* 等待子 agent 完成。若不取消子 agent,completionPromise 永不 settle,
|
|
206
|
+
* executeSubmit 永久 pending,submitQueue 死锁,agent 彻底无反应。
|
|
207
|
+
*
|
|
208
|
+
* 注意:此方法 fire-and-forget,不 await manager.abort 完成。
|
|
209
|
+
* manager.abort 内部会同步 settle completionPromise(通过 completionResolve),
|
|
210
|
+
* 解除 awaitSubAgents 阻塞无需等待 abort I/O 完成。
|
|
211
|
+
*/
|
|
212
|
+
private cancelPendingAwaitedSubAgents;
|
|
177
213
|
/** 终止 ACode 会话并发出 session_complete。 */
|
|
178
214
|
stop(): Promise<void>;
|
|
179
215
|
private resolveCommandDirs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAInE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAC;AAE/E,OAAO,EAIL,KAAK,UAAU,EAChB,MAAM,0BAA0B,CAAC;AA+BlC,OAAO,KAAK,EAOV,kBAAkB,EAGnB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,KAAK,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,UAAU,CAAC;CACzB;AAiyCD,qBAAa,YAAa,SAAQ,YAAY;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -1018,6 +1018,20 @@ export class ACodeRuntime extends EventEmitter {
|
|
|
1018
1018
|
this.submitQueue = Promise.resolve();
|
|
1019
1019
|
this.activeTurn = false;
|
|
1020
1020
|
this.abortRequested = false;
|
|
1021
|
+
/**
|
|
1022
|
+
* 当前正在 await_sub_agents 工具中阻塞等待的子 agent subId 集合。
|
|
1023
|
+
*
|
|
1024
|
+
* 用于让 abort()/stop() 能中断 awaitSubAgents 的阻塞:
|
|
1025
|
+
* - awaitSubAgents 调用前把 subIds 加入此 set,finally 中移除
|
|
1026
|
+
* - abort()/stop() 时对此 set 中每个 subId 调用 manager.abort(subId)
|
|
1027
|
+
* - manager.abort 会 settle completionPromise(resolve with error)
|
|
1028
|
+
* - 从而让 await completionPromise 解除阻塞,execute() 正常返回,
|
|
1029
|
+
* executeSubmit 不再永久 pending,submitQueue 链恢复,后续 submit 可执行。
|
|
1030
|
+
*
|
|
1031
|
+
* 没有此机制时:abort() 只能中断 fetch 流,对 await completionPromise 无效,
|
|
1032
|
+
* 导致 executeSubmit 永久阻塞 → submitQueue 死锁 → 后续 sendMessage 全部排队 → agent 无反应。
|
|
1033
|
+
*/
|
|
1034
|
+
this.pendingAwaitedSubIds = new Set();
|
|
1021
1035
|
this.sessionCompleteEmitted = false;
|
|
1022
1036
|
this.contextVersion = 0;
|
|
1023
1037
|
this.stopWaiters = new Set();
|
|
@@ -1704,6 +1718,15 @@ export class ACodeRuntime extends EventEmitter {
|
|
|
1704
1718
|
this.abortController = null;
|
|
1705
1719
|
// ask_user_question 等待用户回答期间被 abort,需 reject 所有 waiter
|
|
1706
1720
|
this.rejectAllQuestionWaiters("aborted");
|
|
1721
|
+
// ★ 取消正在 await_sub_agents 中阻塞等待的子 agent,让 completionPromise settle,
|
|
1722
|
+
// 解除 execute() 阻塞,避免 submitQueue 永久死锁导致 agent 无反应。
|
|
1723
|
+
this.cancelPendingAwaitedSubAgents();
|
|
1724
|
+
// ★ 触发 stopWaiters,中断正在执行的 MCP 工具调用(callTool)。
|
|
1725
|
+
// MCP callTool 不监听 abortController.signal,只通过 stopWaiter.promise 被中断。
|
|
1726
|
+
// 若不触发,MCP 工具超过 120s 后看门狗触发 abort,但 callTool 仍 pending,
|
|
1727
|
+
// executeSubmit 永久阻塞 → submitQueue 死锁 → agent 无反应。
|
|
1728
|
+
// stopWaiters 是一次性的(触发后清空),不影响后续轮次的新 stopWaiter。
|
|
1729
|
+
this.notifyRuntimeStop();
|
|
1707
1730
|
}
|
|
1708
1731
|
/**
|
|
1709
1732
|
* 构造 ask_user_question 工具的依赖注入。
|
|
@@ -1811,7 +1834,26 @@ export class ACodeRuntime extends EventEmitter {
|
|
|
1811
1834
|
};
|
|
1812
1835
|
},
|
|
1813
1836
|
// 阻塞等待指定子 agent 数组完成
|
|
1814
|
-
|
|
1837
|
+
// ★ 记录正在等待的 subIds 到 pendingAwaitedSubIds,让 abort()/stop() 能中断此阻塞:
|
|
1838
|
+
// manager.abort(subId) 会 settle completionPromise,使 await completionPromise 解除阻塞,
|
|
1839
|
+
// execute() 正常返回,executeSubmit 不再永久 pending,submitQueue 链恢复。
|
|
1840
|
+
awaitSubAgents: async (subIds, timeoutMs) => {
|
|
1841
|
+
// 记录当前等待的 subIds(用于 abort/stop 时中断)
|
|
1842
|
+
const tracking = new Set();
|
|
1843
|
+
for (const id of subIds) {
|
|
1844
|
+
this.pendingAwaitedSubIds.add(id);
|
|
1845
|
+
tracking.add(id);
|
|
1846
|
+
}
|
|
1847
|
+
try {
|
|
1848
|
+
return await manager.awaitCompletion(subIds, timeoutMs);
|
|
1849
|
+
}
|
|
1850
|
+
finally {
|
|
1851
|
+
// 清理跟踪记录(无论成功/失败/中断都需清理)
|
|
1852
|
+
for (const id of tracking) {
|
|
1853
|
+
this.pendingAwaitedSubIds.delete(id);
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
},
|
|
1815
1857
|
// 终止某子 agent
|
|
1816
1858
|
abortSubAgent: (subId) => manager.abort(subId),
|
|
1817
1859
|
};
|
|
@@ -1846,6 +1888,42 @@ export class ACodeRuntime extends EventEmitter {
|
|
|
1846
1888
|
}
|
|
1847
1889
|
this.questionWaiters.clear();
|
|
1848
1890
|
}
|
|
1891
|
+
/**
|
|
1892
|
+
* 取消当前正在 await_sub_agents 工具中阻塞等待的子 agent。
|
|
1893
|
+
*
|
|
1894
|
+
* 核心作用:让 abort()/stop() 能解除 awaitSubAgents 的阻塞,避免 submitQueue 死锁。
|
|
1895
|
+
*
|
|
1896
|
+
* 工作原理:
|
|
1897
|
+
* 1. 遍历 pendingAwaitedSubIds(awaitSubAgents 工具执行期间记录的 subIds)
|
|
1898
|
+
* 2. 对每个 subId 调用 manager.abort(subId)
|
|
1899
|
+
* 3. manager.abort 会 settle completionPromise(resolve with error="aborted")
|
|
1900
|
+
* 4. awaitSubAgents 中 await completionPromise 解除阻塞,execute() 正常返回
|
|
1901
|
+
* 5. executeSubmit 完成,submit() Promise resolve,submitQueue 链恢复
|
|
1902
|
+
* 6. 后续 sendMessage / auto-poll 的 submit 能正常排队执行
|
|
1903
|
+
*
|
|
1904
|
+
* 场景:看门狗触发 abort() 或用户点击停止时,agent 正卡在 await_sub_agents
|
|
1905
|
+
* 等待子 agent 完成。若不取消子 agent,completionPromise 永不 settle,
|
|
1906
|
+
* executeSubmit 永久 pending,submitQueue 死锁,agent 彻底无反应。
|
|
1907
|
+
*
|
|
1908
|
+
* 注意:此方法 fire-and-forget,不 await manager.abort 完成。
|
|
1909
|
+
* manager.abort 内部会同步 settle completionPromise(通过 completionResolve),
|
|
1910
|
+
* 解除 awaitSubAgents 阻塞无需等待 abort I/O 完成。
|
|
1911
|
+
*/
|
|
1912
|
+
cancelPendingAwaitedSubAgents() {
|
|
1913
|
+
if (this.pendingAwaitedSubIds.size === 0)
|
|
1914
|
+
return;
|
|
1915
|
+
const manager = this.config.subAgentManager;
|
|
1916
|
+
if (!manager)
|
|
1917
|
+
return;
|
|
1918
|
+
const subIds = Array.from(this.pendingAwaitedSubIds);
|
|
1919
|
+
runtimeDebugLog(`[ACodeRuntime] ⛔ Cancelling ${subIds.length} pending awaited sub-agent(s): ${subIds.join(", ")}`);
|
|
1920
|
+
// fire-and-forget:manager.abort 内部同步 settle completionPromise 即可解除阻塞
|
|
1921
|
+
for (const subId of subIds) {
|
|
1922
|
+
void manager.abort(subId).catch((err) => {
|
|
1923
|
+
runtimeDebugLog(`[ACodeRuntime] ⚠️ manager.abort(${subId}) threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
1924
|
+
});
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1849
1927
|
/** 终止 ACode 会话并发出 session_complete。 */
|
|
1850
1928
|
async stop() {
|
|
1851
1929
|
if (this.state.terminated) {
|
|
@@ -1858,6 +1936,9 @@ export class ACodeRuntime extends EventEmitter {
|
|
|
1858
1936
|
this.abortController = null;
|
|
1859
1937
|
// ask_user_question 等待用户回答期间被 stop,需 reject 所有 waiter
|
|
1860
1938
|
this.rejectAllQuestionWaiters("session terminated");
|
|
1939
|
+
// ★ 取消正在 await_sub_agents 中阻塞等待的子 agent,让 completionPromise settle,
|
|
1940
|
+
// 解除 execute() 阻塞,避免 submitQueue 永久死锁。
|
|
1941
|
+
this.cancelPendingAwaitedSubAgents();
|
|
1861
1942
|
await runBestEffort("ACode active turn shutdown", this.submitQueue, (message) => {
|
|
1862
1943
|
this.emitAcodeEvent("error", { message });
|
|
1863
1944
|
});
|