[Bug] ZCode 连接 WSL 定时任务无法触发
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 22
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
提交前确认 · Pre-submission checklist
- 我已搜索过现有 issue,确认这不是重复 / I searched existing issues and confirmed this isn't a duplicate.
- 我已阅读 CONTRIBUTING.md / I've read CONTRIBUTING.md.
问题类别 · Category
对话 / Agent 交互 · Agent chat
涉及的 Agent 框架 · Agent framework
ZCode Agent(自研)
严重程度 · Severity
阻塞使用 · Blocking (无法使用核心功能 / core function unusable)
复现频率 · Reproducibility
必现 · Always
问题描述 · Description
桌面版 ZCode 连接WSl的会话中创建定时任务,到达时间窗口后无动作。打开任务面板,手工点击“立即运行”,弹出“执行失败”的提示。
同样条件下,Windows 桌面侧会话正常。
复现步骤 · Steps to reproduce
- 打开ZCode, 连接本机WSL环境
- 打开任意WSL上的工作区
- 在该工作区新建会话,任意输入确认对话正常。
- 对话告知助手创建任意定时任务(周期性或一次性),任务可以是简单的发回一句问候语。
- 等待时间到达,观察执情况
期望表现 · Expected behavior
正常执行任务。
实际表现 · Actual behavior
无任何动作发生。
ZCode 版本 · ZCode version
ZCode Desktop 3.12.3
设备 / 系统 / 浏览器 · Device / OS / Browser
Windows 11
截图 / 录屏 / 日志 · Screenshots / Recordings / Logs
以下是 ZCode 会话内调查过程汇总的报告,由 glm-5.3-flash 生成
环境信息
| 项目 | 内容 |
|---|---|
| 客户端 | ZCode Desktop 3.12.3.7463(Windows 11,WSL2) |
| 工作区拓扑 | remote-WSL 工作区(workspace identity 形如 remote:wsl:<发行版>:<项目路径>;zcode-server 在 WSL 发行版内由桌面端拉起) |
现象摘要
- 在 remote-WSL 工作区的会话中创建的定时自动化(通过 agent 的
CronCreate工具或自动化面板),到达触发时间后不会执行。UI 上无任何错误:任务仍显示 active 及下次触发时间,但到点后静默无事发生(目标会话收不到任何消息)。 - 对这类任务点击「立即运行」→ UI 弹出笼统的「执行失败」,无具体错误信息。
- 对照组:同一时段在桌面端本地上下文创建的同样任务,能被正常调度、派发并成功执行。
三者同时出现,指向 remote-WSL 工作区的自动化注册/派发链路整体断裂,而非单个任务的问题。
复现步骤
- 连接一个 remote-WSL 工作区,打开其会话;
- 让 agent 调用
CronCreate创建一个短延迟一次性任务(如「2 分钟后发送一条消息」),或在自动化面板中创建; - 等待超过触发时间,观察绑定会话:没有任何新消息产生,UI 亦无失败提示;
- 在自动化面板对该任务点「立即运行」:弹出「执行失败」。
预期:任务到点被派发到绑定会话;「立即运行」应立即派发。
实际:定时触发静默失火;「立即运行」固定失败。
排查证据
以下证据来自对本次故障两端数据库状态与客户端/服务端 JS 产物(app.asar / zcode-server.cjs)的分析。
1. 双侧数据库分叉:任务注册进了「无人调度」的库
自动化状态存储有两份:
- WSL 侧:
~/.zcode/v2/tasks-index.sqlite(由 zcode-server 进程持有) - Windows 侧:
%USERPROFILE%\.zcode\v2\tasks-index.sqlite(由桌面客户端持有)
remote-WSL 工作区会话中通过 CronCreate 创建的任务,被写入 WSL 侧库:
automations表有记录,run_count = 0,dispatch_status = 'idle',dispatch_attempts = 0,last_error为空automation_runs表 0 行
而本地上下文创建的任务写入 Windows 侧库,其 automation_runs 中存在 trigger='schedule'、dispatch_status='dispatched'、outcome='succeeded' 的正常记录。
2. 调度循环只存在于客户端进程,且只轮询本地库
- 客户端包内实现了一个调度 worker(独立线程,每 20 秒 tick),tick 逻辑为:
claimDue()(认领到期自动化)+claimManualRuns()(认领手动运行)→ 逐个派发。 - WSL 侧 zcode-server 包内同样打包了
AutomationRepo(含claimDue),但claimDue在 server 内没有任何调用方——即远端库上没有任何调度循环在运行。 - 旁证:
lsof显示 WSL 库仅由 zcode-server 持有;客户端调度器无法看到写入该库的任务。
因此:remote 工作区创建的自动化永远不会被认领,无论 recurring 还是一次性。
3. 「立即运行」的失败点:dispatcher 未装配即抛错
server 侧 runAutomationNow RPC 的实现(两端产物一致):
async runAutomationNow(params) {
const dispatch = options?.onAutomationManualRunRequested;
if (!dispatch) {
throw new Error("Automation immediate dispatcher is unavailable.");
}
const claimed = await automationService.runNow(params.automationId, {...});
...
await dispatch(claimed);
return { status: "queued" };
}
onAutomationManualRunRequested仅在 desktop-local 宿主装配中传入了真实派发器实现;- remote(desktop-attached-remote)装配路径未注入该回调,
options?.onAutomationManualRunRequested为 undefined; - 于是 RPC 一进入就抛
"Automation immediate dispatcher is unavailable."; - 抛错发生在
automationService.runNow()(其内部会写automation_runs、置running=1/claimed_at)之前——这解释了库内零痕迹(automation_runs0 行、automation 行的updated_at不变),而 UI 只显示笼统的「执行失败」。
4. 失火任务的表象细节
过期的一次性任务的 next_run_at 会在读取时被惰性重算顺延(实际观察到 next_run_at 从 15:58:49 被顺延至 16:00:49,而 dispatch_attempts 始终为 0),永远不会补跑,也永远不会产生错误记录。UI 上任务看起来一切正常,只是"到点没动静"。
5. 失败/成功对照时间线
| 任务 | 创建侧 | 创建时间 | 触发时间 | 结果 |
|---|---|---|---|---|
| 任务 A(一次性,1 分钟延迟) | remote-WSL 工作区会话(CronCreate) | 15:57:49 | 15:58:49 | 从未派发;约 16:07 点「立即运行」→「执行失败」 |
| 任务 B(一次性,约 1 分钟延迟) | 客户端本地工作区会话创建 | 16:00:52 | ≈16:01:52 | 16:02:08 被认领派发,outcome='succeeded' |
根因推断
定时自动化的调度循环(tick → claimDue/claimManualRuns → 派发)只在桌面客户端进程内实现,且只轮询客户端本地的 tasks-index.sqlite;而 remote-WSL 工作区创建的自动化被登记到 WSL 侧 server 的库中。结果:
- 定时触发:远端库无人认领 → 静默失火;
- 立即运行:remote 装配缺少
onAutomationManualRunRequested派发器 → RPC 直接抛错; - 两条路径失败后都不产生任何用户可见的错误(定时无提示、立即运行只有笼统「执行失败」),故障只能靠"到点没反应"被发现。
影响
- remote-WSL 工作区创建的所有自动化(含 recurring 周期任务)100% 静默失火;
- 「立即运行」100% 失败且无有效错误信息;
- 无告警、无失败记录,用户难以察觉,对依赖自动化做定时巡检/提醒的场景属于静默失效,信任成本高。
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the desktop scheduler in app.asar and the remote server entry points in zcode-server.cjs, especially AutomationRepo.claimDue, runAutomationNow, and onAutomationManualRunRequested. Compare the remote-WSL and desktop-local assembly paths and the two tasks-index.sqlite databases. Done means scheduled and manual automations from remote-WSL sessions are dispatched successfully and leave the expected run records.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- sqlite
- Domain
- backend, databases, desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100