zai-org / zai-org/feedback

[Bug] ZCode 连接 WSL 定时任务无法触发

Open
#690 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

priority: P2 status: 待评估 type: Bug
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
  1. 打开ZCode, 连接本机WSL环境
  2. 打开任意WSL上的工作区
  3. 在该工作区新建会话,任意输入确认对话正常。
  4. 对话告知助手创建任意定时任务(周期性或一次性),任务可以是简单的发回一句问候语。
  5. 等待时间到达,观察执情况
期望表现 · 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 发行版内由桌面端拉起)

现象摘要

  1. remote-WSL 工作区的会话中创建的定时自动化(通过 agent 的 CronCreate 工具或自动化面板),到达触发时间后不会执行。UI 上无任何错误:任务仍显示 active 及下次触发时间,但到点后静默无事发生(目标会话收不到任何消息)。
  2. 对这类任务点击「立即运行」→ UI 弹出笼统的「执行失败」,无具体错误信息。
  3. 对照组:同一时段在桌面端本地上下文创建的同样任务,能被正常调度、派发并成功执行。

三者同时出现,指向 remote-WSL 工作区的自动化注册/派发链路整体断裂,而非单个任务的问题。

复现步骤

  1. 连接一个 remote-WSL 工作区,打开其会话;
  2. 让 agent 调用 CronCreate 创建一个短延迟一次性任务(如「2 分钟后发送一条消息」),或在自动化面板中创建;
  3. 等待超过触发时间,观察绑定会话:没有任何新消息产生,UI 亦无失败提示;
  4. 在自动化面板对该任务点「立即运行」:弹出「执行失败」。

预期:任务到点被派发到绑定会话;「立即运行」应立即派发。
实际:定时触发静默失火;「立即运行」固定失败。

排查证据

以下证据来自对本次故障两端数据库状态与客户端/服务端 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 = 0dispatch_status = 'idle'dispatch_attempts = 0last_error 为空
  • automation_runs0 行

而本地上下文创建的任务写入 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_runs 0 行、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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.