Repository navigation
fix(agent): 任务启动时等待控制器就绪并尝试重连 - #430
AyanamiRei233 wants to merge 2 commits into
Conversation
并发连接场景下(preActions 触发的重置连接状态与重连请求并发), 刚 bind 的控制器可能仍处于异步连接中,甚至刚被并发的替换流程 销毁重建。原守门检查 inited() 是瞬时快照,快照失败立即报错会 让「连接成功」后启动的任务必然失败。 改为有限时间内轮询等待控制器连接就绪(250ms 轮询 / 10s 超时), 超时才报错。不改变并发语义与销毁逻辑,最小侵入。
实测反馈:纯等待不足以下架——tasker 引用与实例当前控制器脱节后 (并发替换流程销毁旧对象),inited() 永远不会自行变为 true, 10s 超时后仍失败。 守门检查升级为分层自愈: 1. 有限时间轮询等待异步连接完成; 2. 实例控制器已 connected 但 tasker 未 inited(绑定过期引用): 丢弃 tasker,用当前活控制器重建重绑; 3. 实例控制器未连接(已被并发替换销毁):重新走完整连接流程 (connect_controller_impl),完成后再重绑; 4. 超时报错并输出诊断日志(controller connected 状态、自愈路径)。 Tasker 创建逻辑(new + sink 挂载)抽出为 create_tasker_with_sinks, 供初始装配与自愈路径共用。
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ee7b591b5f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| waited_ms += POLL_INTERVAL_MS; | ||
| since_heal_ms += POLL_INTERVAL_MS; | ||
|
|
||
| if tasker.inited() { |
There was a problem hiding this comment.
Revalidate the tasker before accepting readiness
When a concurrent controller request replaces the instance while this loop is waiting, update_instance_controller removes the stored tasker, but the local clone here keeps the old controller/tasker alive. If that old connection finishes first, inited() becomes true and this unconditional break proceeds with the stale controller/tasker; agents and tasks are then posted through handles no longer stored in the instance, so status/stop calls can report no Tasker while work runs (and it may target the superseded controller). Revalidate that the local handles still belong to the current instance before breaking, otherwise rebuild from the current handles.
Useful? React with 👍 / 👎.
| let mut rebound = false; | ||
| let mut reconnected = false; | ||
| loop { | ||
| tokio::time::sleep(std::time::Duration::from_millis(POLL_INTERVAL_MS)).await; |
There was a problem hiding this comment.
Honor cancellation during the readiness wait
When Stop is requested while a slow controller is in this new wait, stop_task_impl sets completion.submission_cancelled(), but the loop never checks it and can keep sleeping and even invoke reconnect until the 20-second timeout; the only cancellation check is later, after optional Agent startup. The UI stop path waits only 8 seconds (taskStopService.ts), so it times out and leaves the instance marked running even though cancellation was accepted. Check the completion cancellation/stop state on every poll before healing.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
嘿——我发现了 7 个问题
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="src-tauri/src/commands/maa_agent.rs" line_range="761-766" />
<code_context>
+ let ctrl_alive = instance.controller.as_ref().is_some_and(|c| c.connected());
+ let config = instance.controller_config.clone();
+
+ let rebound_tasker = if ctrl_alive && !rebound {
+ warn!(
+ "[start_tasks] instance controller is connected but tasker not inited, \
+ rebuilding tasker binding"
+ );
+ rebound = true;
+ let res_now = instance
+ .resource
</code_context>
<issue_to_address>
**Tasks use a superseded controller**
When another connection replaces the instance controller while startup is waiting, the readiness check accepts the locally cloned tasker as soon as `tasker.inited()` is true without verifying it still matches the instance’s current controller. The one-time `rebound` flag also prevents rebinding after a further replacement, so task startup submits through a stale controller or times out despite a connected replacement.
Check that the local tasker and controller still match the instance before proceeding, and rebind whenever they do not.
Also at `src-tauri/src/commands/maa_agent.rs:738-744`.
</issue_to_address>
### Comment 2
<location path="src-tauri/src/commands/maa_agent.rs" line_range="767-771" />
<code_context>
+ rebuilding tasker binding"
+ );
+ rebound = true;
+ let res_now = instance
+ .resource
+ .as_ref()
+ .ok_or("Resource not loaded")?
+ .clone();
+ let ctrl_now = instance.controller.as_ref().unwrap().clone();
+ let t = create_tasker_with_sinks(&app, maa_state, &instance_id, instance)?;
</code_context>
<issue_to_address>
**Agents use a stale resource**
When the instance resource is replaced while startup is waiting and agent configs are provided, the recovery path binds the replacement tasker to `res_now` but leaves the outer `resource` snapshot unchanged. `start_single_agent` then registers agents with the old resource while tasks use the new one, so agents use stale data or fail to access task resources.
Update the resource snapshot used by `start_single_agent` to the same resource passed to the replacement tasker.
Also at `src-tauri/src/commands/maa_agent.rs:775`.
</issue_to_address>
### Comment 3
<location path="src-tauri/src/commands/maa_agent.rs" line_range="812" />
<code_context>
+ cfg,
+ on_event,
+ )
+ .await
+ {
+ Ok(_) => info!("[start_tasks] reconnect request accepted"),
</code_context>
<issue_to_address>
**Startup exceeds its timeout**
When the reconnect worker blocks on the connection gate or controller setup for longer than the remaining startup timeout, `start_tasks_impl` awaits `connect_controller_impl` inline, so it cannot reach the `WAIT_TIMEOUT_MS` check while the connection gate or controller operation is blocked. The task-start request therefore remains pending beyond its advertised limit.
Make the recovery connection wait respect the remaining startup timeout instead of awaiting it unboundedly.
</issue_to_address>
### Comment 4
<location path="src-tauri/src/commands/maa_agent.rs" line_range="760" />
<code_context>
}).await.map_err(|e| e.to_string())?
}
+/// 创建带回调 sink 的 Tasker(初始装配与连接自愈共用)
+///
</code_context>
<issue_to_address>
**Recovery overrides the latest connection**
When a different controller connection is requested after recovery snapshots the configuration but before it calls `connect_controller_impl`, the recovery path passes its captured `config` to `connect_controller_impl`, which starts a new request and can cancel the newer connection request. The instance reconnects to the old configuration instead of the user’s latest selection.
Verify the captured configuration or request is still current before starting recovery, so stale recovery cannot replace a newer connection.
Also at `src-tauri/src/commands/maa_agent.rs:798-812`.
</issue_to_address>
### Comment 5
<location path="src-tauri/src/commands/maa_agent.rs" line_range="734-735" />
<code_context>
+ let mut rebound = false;
+ let mut reconnected = false;
+ loop {
+ tokio::time::sleep(std::time::Duration::from_millis(POLL_INTERVAL_MS)).await;
+ waited_ms += POLL_INTERVAL_MS;
+ since_heal_ms += POLL_INTERVAL_MS;
+
</code_context>
<issue_to_address>
**Stopped starts keep waiting**
When a stop request arrives while the tasker is waiting for controller initialization, the readiness loop does not check whether the submission was cancelled, so it keeps waiting and can initiate a recovery connection after the stop request. The start permit remains held and the start call stays active until initialization or timeout.
Check for submission cancellation in the readiness loop and exit before reconnecting or starting agents.
Also at `src-tauri/src/commands/maa_agent.rs:795`.
</issue_to_address>
### Comment 6
<location path="src-tauri/src/commands/maa_agent.rs" line_range="758" />
<code_context>
+ if !Arc::ptr_eq(&instance.run_completion, &completion) {
+ return Err("INSTANCE_REPLACED".to_string());
+ }
+ let ctrl_alive = instance.controller.as_ref().is_some_and(|c| c.connected());
+ let config = instance.controller_config.clone();
+
</code_context>
<issue_to_address>
**Pending connections get restarted**
When the original controller action remains pending for at least four seconds, a controller whose connection action is still pending has `connected() == false`, so after four seconds `start_tasks_impl` treats it as dead and calls `connect_controller_impl` again. That starts a new request and calls `post_connection()` on the pooled pending controller, disrupting or duplicating a slow connection that the wait was meant to let finish.
Before reconnecting, distinguish a genuinely failed controller from one whose connection action is still pending or running, and continue waiting for the latter.
Also at `src-tauri/src/commands/maa_agent.rs:795-819`.
</issue_to_address>
### Comment 7
<location path="src-tauri/src/commands/maa_agent.rs" line_range="724-726" />
<code_context>
+ // 3. 实例控制器也未连接(可能已被并发替换流程销毁):重新走完整
+ // 连接流程(connect_controller_impl),完成后再按 2 重绑;
+ // 4. 超时才报错,并在日志中输出诊断信息。
if !tasker.inited() {
- error!("[start_tasks] Tasker not properly initialized");
- return Err("Tasker not properly initialized".to_string());
+ warn!("[start_tasks] Tasker not inited yet, waiting for controller connection...");
+ const WAIT_TIMEOUT_MS: u64 = 20_000;
+ const POLL_INTERVAL_MS: u64 = 250;
+ const HEAL_INTERVAL_MS: u64 = 2_000;
</code_context>
<issue_to_address>
**Direct task calls still fail**
When a caller starts a direct task while its controller connection is still completing asynchronously, the new wait-and-recovery behavior is only in `start_tasks_impl`; direct `run_task_impl` calls still return immediately when a newly bound tasker is not initialized. Callers using that API with a slow or asynchronously connecting controller continue to see task startup fail.
Apply an equivalent readiness/recovery strategy to `run_task_impl`, or route direct task starts through a shared tasker-readiness helper.
</issue_to_address>Original comment in English
Hey - I've found 7 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="src-tauri/src/commands/maa_agent.rs" line_range="761-766" />
<code_context>
+ let ctrl_alive = instance.controller.as_ref().is_some_and(|c| c.connected());
+ let config = instance.controller_config.clone();
+
+ let rebound_tasker = if ctrl_alive && !rebound {
+ warn!(
+ "[start_tasks] instance controller is connected but tasker not inited, \
+ rebuilding tasker binding"
+ );
+ rebound = true;
+ let res_now = instance
+ .resource
</code_context>
<issue_to_address>
**Tasks use a superseded controller**
When another connection replaces the instance controller while startup is waiting, the readiness check accepts the locally cloned tasker as soon as `tasker.inited()` is true without verifying it still matches the instance’s current controller. The one-time `rebound` flag also prevents rebinding after a further replacement, so task startup submits through a stale controller or times out despite a connected replacement.
Check that the local tasker and controller still match the instance before proceeding, and rebind whenever they do not.
Also at `src-tauri/src/commands/maa_agent.rs:738-744`.
</issue_to_address>
### Comment 2
<location path="src-tauri/src/commands/maa_agent.rs" line_range="767-771" />
<code_context>
+ rebuilding tasker binding"
+ );
+ rebound = true;
+ let res_now = instance
+ .resource
+ .as_ref()
+ .ok_or("Resource not loaded")?
+ .clone();
+ let ctrl_now = instance.controller.as_ref().unwrap().clone();
+ let t = create_tasker_with_sinks(&app, maa_state, &instance_id, instance)?;
</code_context>
<issue_to_address>
**Agents use a stale resource**
When the instance resource is replaced while startup is waiting and agent configs are provided, the recovery path binds the replacement tasker to `res_now` but leaves the outer `resource` snapshot unchanged. `start_single_agent` then registers agents with the old resource while tasks use the new one, so agents use stale data or fail to access task resources.
Update the resource snapshot used by `start_single_agent` to the same resource passed to the replacement tasker.
Also at `src-tauri/src/commands/maa_agent.rs:775`.
</issue_to_address>
### Comment 3
<location path="src-tauri/src/commands/maa_agent.rs" line_range="812" />
<code_context>
+ cfg,
+ on_event,
+ )
+ .await
+ {
+ Ok(_) => info!("[start_tasks] reconnect request accepted"),
</code_context>
<issue_to_address>
**Startup exceeds its timeout**
When the reconnect worker blocks on the connection gate or controller setup for longer than the remaining startup timeout, `start_tasks_impl` awaits `connect_controller_impl` inline, so it cannot reach the `WAIT_TIMEOUT_MS` check while the connection gate or controller operation is blocked. The task-start request therefore remains pending beyond its advertised limit.
Make the recovery connection wait respect the remaining startup timeout instead of awaiting it unboundedly.
</issue_to_address>
### Comment 4
<location path="src-tauri/src/commands/maa_agent.rs" line_range="760" />
<code_context>
}).await.map_err(|e| e.to_string())?
}
+/// 创建带回调 sink 的 Tasker(初始装配与连接自愈共用)
+///
</code_context>
<issue_to_address>
**Recovery overrides the latest connection**
When a different controller connection is requested after recovery snapshots the configuration but before it calls `connect_controller_impl`, the recovery path passes its captured `config` to `connect_controller_impl`, which starts a new request and can cancel the newer connection request. The instance reconnects to the old configuration instead of the user’s latest selection.
Verify the captured configuration or request is still current before starting recovery, so stale recovery cannot replace a newer connection.
Also at `src-tauri/src/commands/maa_agent.rs:798-812`.
</issue_to_address>
### Comment 5
<location path="src-tauri/src/commands/maa_agent.rs" line_range="734-735" />
<code_context>
+ let mut rebound = false;
+ let mut reconnected = false;
+ loop {
+ tokio::time::sleep(std::time::Duration::from_millis(POLL_INTERVAL_MS)).await;
+ waited_ms += POLL_INTERVAL_MS;
+ since_heal_ms += POLL_INTERVAL_MS;
+
</code_context>
<issue_to_address>
**Stopped starts keep waiting**
When a stop request arrives while the tasker is waiting for controller initialization, the readiness loop does not check whether the submission was cancelled, so it keeps waiting and can initiate a recovery connection after the stop request. The start permit remains held and the start call stays active until initialization or timeout.
Check for submission cancellation in the readiness loop and exit before reconnecting or starting agents.
Also at `src-tauri/src/commands/maa_agent.rs:795`.
</issue_to_address>
### Comment 6
<location path="src-tauri/src/commands/maa_agent.rs" line_range="758" />
<code_context>
+ if !Arc::ptr_eq(&instance.run_completion, &completion) {
+ return Err("INSTANCE_REPLACED".to_string());
+ }
+ let ctrl_alive = instance.controller.as_ref().is_some_and(|c| c.connected());
+ let config = instance.controller_config.clone();
+
</code_context>
<issue_to_address>
**Pending connections get restarted**
When the original controller action remains pending for at least four seconds, a controller whose connection action is still pending has `connected() == false`, so after four seconds `start_tasks_impl` treats it as dead and calls `connect_controller_impl` again. That starts a new request and calls `post_connection()` on the pooled pending controller, disrupting or duplicating a slow connection that the wait was meant to let finish.
Before reconnecting, distinguish a genuinely failed controller from one whose connection action is still pending or running, and continue waiting for the latter.
Also at `src-tauri/src/commands/maa_agent.rs:795-819`.
</issue_to_address>
### Comment 7
<location path="src-tauri/src/commands/maa_agent.rs" line_range="724-726" />
<code_context>
+ // 3. 实例控制器也未连接(可能已被并发替换流程销毁):重新走完整
+ // 连接流程(connect_controller_impl),完成后再按 2 重绑;
+ // 4. 超时才报错,并在日志中输出诊断信息。
if !tasker.inited() {
- error!("[start_tasks] Tasker not properly initialized");
- return Err("Tasker not properly initialized".to_string());
+ warn!("[start_tasks] Tasker not inited yet, waiting for controller connection...");
+ const WAIT_TIMEOUT_MS: u64 = 20_000;
+ const POLL_INTERVAL_MS: u64 = 250;
+ const HEAL_INTERVAL_MS: u64 = 2_000;
</code_context>
<issue_to_address>
**Direct task calls still fail**
When a caller starts a direct task while its controller connection is still completing asynchronously, the new wait-and-recovery behavior is only in `start_tasks_impl`; direct `run_task_impl` calls still return immediately when a newly bound tasker is not initialized. Callers using that API with a slow or asynchronously connecting controller continue to see task startup fail.
Apply an equivalent readiness/recovery strategy to `run_task_impl`, or route direct task starts through a shared tasker-readiness helper.
</issue_to_address>| if !Arc::ptr_eq(&instance.run_completion, &completion) { | ||
| return Err("INSTANCE_REPLACED".to_string()); | ||
| } | ||
| let ctrl_alive = instance.controller.as_ref().is_some_and(|c| c.connected()); |
There was a problem hiding this comment.
🟡 Medium · 待处理的连接会被重新启动
如果原始控制器操作至少持续待处理四秒,那么连接操作仍在等待中的控制器会有 connected() == false,因此四秒后 start_tasks_impl 会将其视为已失效,并再次调用 connect_controller_impl。这会启动新请求,并在连接池中仍处于待处理状态的控制器上调用 post_connection(),从而干扰或重复启动本来希望等待其完成的慢速连接。
重新连接前,请区分确实已失败的控制器与其连接操作仍处于待处理或运行状态的控制器;对于后者,应继续等待。
另请参阅 src-tauri/src/commands/maa_agent.rs:795-819。
提供给 AI 代理的提示
在 `src-tauri/src/commands/maa_agent.rs` 第 758 行:
**待处理的连接会被重新启动**
如果原始控制器操作至少持续待处理四秒,那么连接操作仍在等待中的控制器会有 `connected() == false`,因此四秒后 `start_tasks_impl` 会将其视为已失效,并再次调用 `connect_controller_impl`。这会启动新请求,并在连接池中仍处于待处理状态的控制器上调用 `post_connection()`,从而干扰或重复启动本来希望等待其完成的慢速连接。
重新连接前,请区分确实已失败的控制器与其连接操作仍处于待处理或运行状态的控制器;对于后者,应继续等待。
另请参阅 `src-tauri/src/commands/maa_agent.rs:795-819`。Original comment in English
🟡 Medium · Pending connections get restarted
When the original controller action remains pending for at least four seconds, a controller whose connection action is still pending has connected() == false, so after four seconds start_tasks_impl treats it as dead and calls connect_controller_impl again. That starts a new request and calls post_connection() on the pooled pending controller, disrupting or duplicating a slow connection that the wait was meant to let finish.
Before reconnecting, distinguish a genuinely failed controller from one whose connection action is still pending or running, and continue waiting for the latter.
Also at src-tauri/src/commands/maa_agent.rs:795-819.
Prompt for AI agents
In `src-tauri/src/commands/maa_agent.rs` at line 758:
**Pending connections get restarted**
When the original controller action remains pending for at least four seconds, a controller whose connection action is still pending has `connected() == false`, so after four seconds `start_tasks_impl` treats it as dead and calls `connect_controller_impl` again. That starts a new request and calls `post_connection()` on the pooled pending controller, disrupting or duplicating a slow connection that the wait was meant to let finish.
Before reconnecting, distinguish a genuinely failed controller from one whose connection action is still pending or running, and continue waiting for the latter.
Also at `src-tauri/src/commands/maa_agent.rs:795-819`.
MistEO
left a comment
There was a problem hiding this comment.
看过 ee7b591 的改动、相关调用链和附件日志。等待慢连接完成这个方向合理,但当前版本还不能合并,建议先解决以下问题。已有机器人评论中,旧 Tasker 和取消处理的问题,经核对确实成立。
-
[P1] 就绪检查没有确认 Tasker 仍属于当前控制器。 第 738–743 行只要本地
tasker.inited()为 true 就退出等待。并发连接会在update_instance_controller中替换控制器并清空instance.tasker,但这里的克隆仍持有旧句柄;旧连接随后成功,就会继续用旧 Tasker 提交任务。后面的run_completion比较只能识别实例重建,不能识别同一实例的控制器替换,停止/状态查询也无法管理这个已脱离实例的 Tasker。应校验连接请求身份及当前绑定,并在最终提交时保证一致;一次性的rebound标志也不足以应对再次替换。 -
[P2] 等待和恢复路径不响应停止。 第 733 行起的循环不检查
completion.submission_cancelled()/stop_in_progress。停止请求虽然已被后端接受,启动许可仍被占用,还可能继续重连、启动 Agent,直到后面的提交检查才退出。前端停止等待上限为 8 秒,这里却可等 20 秒甚至更久。请在每轮等待、重连前后和启动 Agent 前处理取消,并及时释放启动许可。 -
[P2]
connected() == false不能当作“控制器已死”,恢复也不能覆盖更新的连接请求。 第 795–812 行在 4 秒后就调用完整连接流程。原连接仍可能处于 PENDING/RUNNING;connect_controller_impl会创建新请求、取消旧请求的回调资格,并可能在池中同一个连接中的控制器上再次post_connection()。此外,解锁后用配置快照发起恢复,也可能取消期间用户发起的更新连接。请区分连接中与失败,并把恢复绑定到仍然有效的请求身份。 -
[P2] 声明的 20 秒不是实际超时上限。 第 812 行直接等待
connect_controller_impl,期间可能等待连接门控或原生控制器操作;waited_ms只累计 sleep 的 250ms,不计重连和其他操作耗时。请使用单调时钟的 deadline,并让重连等待也受剩余时间和取消约束。后台 blocking worker 的后续发布也需要请求身份保护,不能仅让外层等待超时。 -
[P2] 重绑后的 Resource 与 Agent 使用的 Resource 可能不一致。 第 767–785 行会用当前
res_now绑定新 Tasker,却只更新外层tasker/controller。如果等待期间执行了资源切换,后面的start_single_agent仍拿旧resource注册。Resource、Controller、Tasker 应作为同一份有效快照校验和更新。
关于根因,附件里“同一毫秒出现 create/post/destroy”还不足以证明新控制器被销毁:相关日志只记录 ctrl=true,没有原生句柄身份;项目锁定的 maa-framework 1.27.0 中,Controller/Tasker 都共享 Arc,Tasker 绑定还会保留 Controller 的克隆。当前代码也已有实例锁、按配置的连接门控和请求身份校验,不能直接归因为“没有同步锁”。建议补上句柄/请求身份、连接 action 状态和确切构建版本的日志,先确定销毁的是哪个对象,以及为什么前端已判定连接成功、启动时却仍未就绪。
验证范围:本次核对了源码、锁定版本的 Rust binding、MaaFramework 的初始化判定及附件日志,未在 Windows ↔ macOS AVD 链路做实机复现。当前六个平台/架构构建检查均通过;附件 v2-test-report.md 自报结果为 7/10 成功,另外 3 次仍然初始化失败,因此目前证据支持“有缓解效果”,尚不能证明问题已解决。建议补充慢连接期间替换控制器、停止、资源切换和超时场景的回归验证。
da0673c to
ee7b591
Compare
先说明发现问题的场景?可能比较难复现
在测试maa-end的时候,偶然发现,若模拟器的adb存在较大的延迟,如AVD,在开启前置任务的情况下,会稳定触发连接失败,经过一段时间的检查,怀疑是下面这个原因
在有前置任务的情况下,前置任务本身会尝试连接一次模拟器,然后执行完成前置任务并开启任务流程时会将此控制器销毁并新建一个控制器,对于大多数adb来说,这只需要几毫秒,故销毁-重建新控制器是可稳定触发的
因为这次我使用的adb的原因,销毁控制器后重建新控制器这个过程需要约300ms,此时就会出现一次并发竞态,新的控制器也会被销毁(这里注意到maa-end的日志里会提示等待3s,应该也是因为这个控制器交接的过程)
于是让大模型写了一个包含重连的版本,完成了编译和测试,对慢速adb有一定的恢复连接能力,并进行了有限的手动测试
复现:mac os AVD模拟器,通过网络桥接到windows,造成adb延迟较高,从而导致控制器出现异常被销毁
不过我认为即使这个需求比较猎奇,但是前置任务转交控制器给主任务这块没有同步锁确实是一个小问题,我让模型写的版本比较拉跨,不接受PR也希望我去写一个issue解决这个问题,例如写一个锁同步或者直接转交控制器对象,不再销毁重建等
下面包含了相关的日志等
mxu-tasker-bug-archive-2026-11-05.zip
写的比较乱,需要复现或者需要有什么疑问可以告诉我喵
AI 使用信息:
Sourcery 摘要
通过等待初始化完成并恢复过期连接,使任务启动能够更好地应对异步控制器切换和缓慢的 ADB 连接。
Bug 修复:
改进:
Original summary in English
Sourcery 摘要
通过等待 tasker 就绪并安全恢复过期连接,增强 agent 和 task 的启动能力,以应对控制器异步移交和 ADB 连接缓慢的情况。
错误修复:
增强功能:
测试:
Original summary in English
Summary by Sourcery
Make agent and task startup resilient to asynchronous controller handoff and slow ADB connections by waiting for tasker readiness and safely recovering stale connections.
Bug Fixes:
Enhancements:
Tests: