Problem / 问题
定时任务页目前只有「任务」和「运行记录」两个平铺列表,能创建和触发任务,但看不出「一次运行到底跑成什么样」,也不方便按任务回查;同时定时任务产生的会话又混进了主界面的会话列表。具体是这几处(基于当前 main 的 apps/desktop/src/pages/ScheduledPage.tsx 与 apps/desktop/electron/main/ipc/scheduled-ipc.ts):
运行记录是全局平铺列表,不能按任务查看。 desktop 侧固定 host.call("scheduled.listRuns", { limit: 100 }),虽然 host 的 scheduled.listRuns 已经支持 taskId 过滤(crates/host-core/src/rpc/scheduled_rpc.rs),但渲染层没有传,也没有任何筛选入口。任务一多,某条记录属于哪个任务要靠肉眼比对标题。
没有运行时长。 task_runs.ended_at 已经落库(scheduled.rs::finish_run),界面只显示 startedAt,所以看不出一次运行跑了 3 秒还是 3 分钟,也看不出是否卡住。
失败与正常运行在视觉上几乎一样。 状态徽章是 tone={run.status === "completed" ? "success" : "neutral"},error / aborted 和 running 共用 neutral;失败只多一行通用文案加错误码。
查看结果必须离开页面。 「打开会话」执行 selectSession(...) + setPage("chat"),会切到对话页并替换当前对话上下文。只是想确认一次夜间任务的结果,代价是一次上下文跳转。
任务列表没有「上次运行结果」。 只能切到运行记录页自己找;「运行中」状态靠全量 runs 扫描。
刷新是整轮轮询。 每 10 秒重新拉 tasks + runs + projects,没有按需读取单任务历史。
定时任务的会话混进了主界面的项目会话列表。 scheduled.run 会创建一个真实会话(scheduled_rpc.rs 里用任务标题作 title、用任务工作区或当前工作区作 project_path),因此它会像普通对话一样出现在侧栏的项目分组下(以及会话搜索里)。而 sessions 表只有 source(转写权威:desktop / native),没有任何「这是定时任务产出」的标记,session.list 也不做过滤,用户只能靠标题猜。绑定项目 + 每天执行的任务会持续往项目分组里堆会话,把用户自己的对话挤下去。
Proposed change / 期望改动
把定时任务页改成任务列表 + 任务详情 的主从结构,让运行结果在页内可读,同时把定时任务会话从主界面会话列表里收回来:
┌─ 任务 ─────────────┬─ 详情:每日依赖检查 ─────────────┐
│ ● 每日依赖检查 │ 概览:指令 / 周期 / 权限 / 模型 / 项目 │
│ 上次 02:00 成功 ✓ │ ───────────────────────────── │
│ 下次 02:00 (18h) │ 运行历史(仅本任务,可翻页) │
│ ○ 夜间测试 失败 ✗ │ 02:00 ✓ 42s · 自动 · [查看内容] │
│ ○ PR 巡查 运行中… │ 昨天 02:00 ✗ 1m12s · PROVIDER_… │
│ │ ───────────────────────────── │
│ │ 运行内容:页内读取该次运行的转写 │
└─────────────────────┴───────────────────────────────┘
任务行 :补「上次运行:状态 + 时间 + 时长」、下次执行倒计时、运行中标记。
任务详情 :概览(指令、周期、权限、模型、项目)/ 运行历史(该任务)/ 运行内容(页内读转写)。
运行历史行 :成功 / 失败 / 中断使用不同色彩;显示开始时间、时长 、触发方式、错误码与可读原因、结果摘要(首段输出预览)。
页内读取转写 :点开某条运行,在页面内的抽屉/详情面板读取它 session_id 的会话内容(有界读取,复用现有会话读取与转写渲染),停留在定时任务页 ;「在对话中打开」保留为次级动作,供需要继续追问的场景。
主界面不再显示定时任务会话 :侧栏的项目分组、会话列表与会话搜索都不再列出定时任务产生的会话,它们的转写只从定时任务页按运行记录进入。「在对话中打开」是显式动作,需要继续追问时才把那次会话带到对话页。这样主列表只保留用户自己发起的对话,运行产出回到它所属的任务下面。
删除任务后的历史要有去处 :现在 task_runs.task_id 是 ON DELETE CASCADE,而 task_runs.session_id 是 ON DELETE SET NULL,所以删除任务会删掉运行记录、但会话仍然留在库里。如果再把它从主列表隐藏,这些会话就完全没有任何入口了。需要在下面几种处理里选一种:随任务一并删除运行会话;或在定时任务页保留一个「已删除任务的历史」入口;或让失去归属的会话重新出现在主列表。
失败可见性 :失败运行使用错误色徽章,任务行给出最近一次失败提示;失败通知可后续单独讨论。
空状态 :按 docs/spec/04-ux/10-workbuddy-benchmark-ux.md §3.3 已经提出的方向,给 4–6 个开发场景模板(夜间测试、依赖更新摘要、PR 巡查、changelog 草稿)。
建议分阶段,便于小 PR 合入:
阶段 1(无 schema 改动) :任务详情 + 按任务过滤的运行历史 + 页内读转写 + 时长显示 + 失败色彩与原因 + 主界面排除定时任务会话 + 保留「在对话中打开」。改动面:ScheduledPage(可拆子组件)、侧栏会话列表与搜索的过滤、scheduled-ipc.ts 透传 taskId、i18n、组件规范。页内读取和主列表隐藏建议放在同一步 :只有页内能读到转写,才可以放心把会话从主列表拿掉。
阶段 2 :任务行显示上次运行结果 / 下次执行倒计时 / 运行中标记;运行历史「加载更多」(需要 host list_runs 增加 offset 或 cursor)。
阶段 3(可选,需要迁移) :task_runs 增加 trigger(manual / automatic)用于区分手动与自动触发;以及失败通知策略。
数据与契约影响:
阶段 1 不需要数据库迁移 :task_runs 已有 ended_at、session_id、error_code。
判断「这个会话属于定时任务」最小实现可以由 task_runs.session_id 反查得出,再在会话摘要上带回一个标记(例如 scheduledRun: true),由渲染层过滤侧栏与搜索;是否把它落库成 sessions 的新字段(例如 origin)可以再定,若落库则需要迁移。
需要把 taskId 从 desktop IPC 透传到 host RPC(现有 RPC 已支持 task_id,只是 desktop 侧没传)。
如果选择在 host 侧过滤,session.list 与会话搜索查询都要一起改,避免只改一处导致侧栏排除了、搜索还能搜到。
页内读转写使用现有 session.get 有界读取,不新增读取通道。
Alternatives / 其他方案
只做「运行记录按任务分组」 ,不做页内读转写:改动最小,但确认一次运行结果仍然要跳去对话页。
保留全局运行记录页,另加任务详情抽屉 :状态与路由更简单,但「全局历史」和「任务详情」两个入口容易信息分叉。
不隐藏定时任务会话,只在侧栏给出可见来源标记 ,并把它们从项目分组移到一个独立的「定时任务」分组:改动小、不丢入口,但主列表仍然会变长,也没有解决「想按任务回看」的问题。
新增独立的「自动化」页面 :对现有信息架构改动最大,暂不建议。
页内读取也可以只做「结果摘要 + 首段输出」,不做完整转写渲染;如果担心在定时任务页重复实现转写阅读体验,可以先用摘要再评估。
Additional context / 补充信息
相关实现:apps/desktop/src/pages/ScheduledPage.tsx、apps/desktop/electron/main/ipc/scheduled-ipc.ts、crates/host-core/src/rpc/scheduled_rpc.rs、crates/host-core/src/scheduled.rs、crates/host-core/src/sessions.rs。
相关规范:docs/spec/03-runtime/04-data-storage.md §4.11(scheduled_tasks + task_runs)、docs/spec/04-ux/01-ui-ia.md §3.3(Scheduled)与侧栏会话分组部分。
历史:[Feature] 建议完善定时任务的自动执行与管理 #694 已经实现了「运行记录」与结果会话入口,本提案是在其基础上补齐按任务查看 、页内读取 ,以及定时任务会话不再混进主界面会话列表 。§3.3 现在写的是 “a conversation link opens the real transcript”,如果采纳页内读取,这句话需要同步更新为「页内可读 + 在对话中打开作为次级动作」;侧栏分组与数据存储章节也要写明定时任务会话的归属与生命周期。
如果方向认可,我可以按上面的阶段划分提 PR;阶段 1 的改动面比较小,也容易 review。实现范围、阶段划分或取舍需要调整的话,也请直接说。
Problem / 问题
定时任务页目前只有「任务」和「运行记录」两个平铺列表,能创建和触发任务,但看不出「一次运行到底跑成什么样」,也不方便按任务回查;同时定时任务产生的会话又混进了主界面的会话列表。具体是这几处(基于当前
main的apps/desktop/src/pages/ScheduledPage.tsx与apps/desktop/electron/main/ipc/scheduled-ipc.ts):host.call("scheduled.listRuns", { limit: 100 }),虽然 host 的scheduled.listRuns已经支持taskId过滤(crates/host-core/src/rpc/scheduled_rpc.rs),但渲染层没有传,也没有任何筛选入口。任务一多,某条记录属于哪个任务要靠肉眼比对标题。task_runs.ended_at已经落库(scheduled.rs::finish_run),界面只显示startedAt,所以看不出一次运行跑了 3 秒还是 3 分钟,也看不出是否卡住。tone={run.status === "completed" ? "success" : "neutral"},error/aborted和running共用 neutral;失败只多一行通用文案加错误码。selectSession(...)+setPage("chat"),会切到对话页并替换当前对话上下文。只是想确认一次夜间任务的结果,代价是一次上下文跳转。runs扫描。scheduled.run会创建一个真实会话(scheduled_rpc.rs里用任务标题作 title、用任务工作区或当前工作区作project_path),因此它会像普通对话一样出现在侧栏的项目分组下(以及会话搜索里)。而sessions表只有source(转写权威:desktop / native),没有任何「这是定时任务产出」的标记,session.list也不做过滤,用户只能靠标题猜。绑定项目 + 每天执行的任务会持续往项目分组里堆会话,把用户自己的对话挤下去。Proposed change / 期望改动
把定时任务页改成任务列表 + 任务详情的主从结构,让运行结果在页内可读,同时把定时任务会话从主界面会话列表里收回来:
session_id的会话内容(有界读取,复用现有会话读取与转写渲染),停留在定时任务页;「在对话中打开」保留为次级动作,供需要继续追问的场景。task_runs.task_id是ON DELETE CASCADE,而task_runs.session_id是ON DELETE SET NULL,所以删除任务会删掉运行记录、但会话仍然留在库里。如果再把它从主列表隐藏,这些会话就完全没有任何入口了。需要在下面几种处理里选一种:随任务一并删除运行会话;或在定时任务页保留一个「已删除任务的历史」入口;或让失去归属的会话重新出现在主列表。docs/spec/04-ux/10-workbuddy-benchmark-ux.md§3.3 已经提出的方向,给 4–6 个开发场景模板(夜间测试、依赖更新摘要、PR 巡查、changelog 草稿)。建议分阶段,便于小 PR 合入:
ScheduledPage(可拆子组件)、侧栏会话列表与搜索的过滤、scheduled-ipc.ts透传taskId、i18n、组件规范。页内读取和主列表隐藏建议放在同一步:只有页内能读到转写,才可以放心把会话从主列表拿掉。list_runs增加 offset 或 cursor)。task_runs增加trigger(manual / automatic)用于区分手动与自动触发;以及失败通知策略。数据与契约影响:
task_runs已有ended_at、session_id、error_code。task_runs.session_id反查得出,再在会话摘要上带回一个标记(例如scheduledRun: true),由渲染层过滤侧栏与搜索;是否把它落库成sessions的新字段(例如origin)可以再定,若落库则需要迁移。taskId从 desktop IPC 透传到 host RPC(现有 RPC 已支持task_id,只是 desktop 侧没传)。session.list与会话搜索查询都要一起改,避免只改一处导致侧栏排除了、搜索还能搜到。session.get有界读取,不新增读取通道。Alternatives / 其他方案
Additional context / 补充信息
apps/desktop/src/pages/ScheduledPage.tsx、apps/desktop/electron/main/ipc/scheduled-ipc.ts、crates/host-core/src/rpc/scheduled_rpc.rs、crates/host-core/src/scheduled.rs、crates/host-core/src/sessions.rs。docs/spec/03-runtime/04-data-storage.md§4.11(scheduled_tasks+task_runs)、docs/spec/04-ux/01-ui-ia.md§3.3(Scheduled)与侧栏会话分组部分。