Files
ycode/docs/定时任务模块拆解-2026-10-17.md
T

172 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 定时任务模块拆解(2026-10-17)
> 开发执行入口:[三模块开发计划](三模块开发计划-2026-10-17.md)。新增公共执行服务抽取、时钟/持久化策略、首批分工和验证门槛;下文保留原版事实与未知边界,工程基线不等于原版规则已证实。
当前状态:完成首版页面、表单、频率模型、执行关系与实施批次拆解。本文只使用已保存的 WorkBuddy 5.8.3 REA Evidence 和当前 YCode 源码事实;没有启动原版或 YCode,没有构建、测试、导航或创建任务。
本轮目标是把“定时任务”从单个占位入口拆成可实现的本地闭环。页面复刻、任务定义、运行记录、调度器、会话执行和系统恢复必须分别建模,不能用 UI 计时器或 Toast 冒充调度成功。
## 证据边界
| 范围 | Evidence / 工件 | 已确认 | 限制 |
| --- | --- | --- | --- |
| 定时任务页 | `ev_386df7d869a651cc6c083205fb10c4264ec8356901bc0b031cab63d64d65c8d5`;`.tmp/rea-todo20-scheduled-page.json`、`rea-todo20-scheduled-page.png` | 1336×902 深色页面、导航、空态、模板卡、工具栏和布局 | 固定账号、主题、窗口与空数据状态 |
| 新建表单 | `ev_be404f0454dfd7496f91ff79a7f43bb61a54ad587933baee0d1cf77c4db915c5`;`.tmp/rea-todo20-scheduled-create.json`、`rea-todo20-scheduled-create.png` | 标题、名称、提示词、工作空间、权限、重复、时间、有效期、企业微信和按钮 | 仅空白表单静止态;没有提交、切换频率或打开弹层 |
| 静态实现 | `ev_625e3664a4da2b25291494bd5b985d16b09d1654d5f8170d8af6325d2019c159` | `automation-qDy4JNlv.js`、`automation-C36RYsTC.css`、路由和同次页面资源 | 来源覆盖部分;不代表原版全部脚本、服务端和状态 |
`app.asar` SHA-256 为 `3e50fcb5b060deba4f1ea9a8c293cf955bf12d7e52d971985de914350afd9077`。
`automation-qDy4JNlv.js` SHA-256 为 `687f7b062b0df0f353dafd1f17b00cb939685da5a12c8d3ce865b920b94d6710`,131,537 字节。`automation-C36RYsTC.css` SHA-256 为 `28c6dc5e1a8d83d7b955d00a604723898a296f0ece4a3bbe4d6db26fc3bbbda5`,56,516 字节。
证据可复核位置:两份运行态归档的 `normalized_result.scripts.items` / `styles.items`;只读导出在 `.tmp/todo20-scheduled-source/`。频率锚点为 `getScheduleMode`、`toIntervalRrule`、`toPeriodicRrule`、`ScheduleControls`、`ValidityField`;关闭约束为 `AutomationEditorSurface` 的 `closeOnOverlayClick:false` / `closeOnEscape:false`;权限确认为 `shouldConfirmAutomationFullAccess`、`AutomationFullAccessConfirmModal`、`requestSaveDraft`;页签与记录为 `AutomationToolbar`、`AutomationWorkspacePage`、`RecordsTab`、`RecordRow`、`AutomationRecordsFilterBar`。路由辅助源 `automation-D9XYSeN0.js` 以及中文文案 `zh-cn-C7BTHfrQ.js` 同为既有REA捕获正文的导出;本轮没有直接读取原版包。
## 原版页面结构
侧栏“定时任务”是独立一级入口,选中时使用该页导航态。主区在 Windows 原生标题栏之下从 `y=30` 开始,宽约 `1051.7`,高 `872`。
顶部工具栏高 `64`,左右内边距 `24`,标题为“定时任务”,右侧是“新建”分体按钮。静态实现还暴露“手动新建、从任务新建、从模版新建”入口;当前运行证据只显示主按钮与下拉箭头。
静态实现包含“定时任务 / 运行记录”两个页签,以及来源筛选、关键词搜索、批量管理和状态筛选;运行记录页包含状态、来源、任务筛选。当前运行截图只覆盖空列表,尚未逐一运行这些分支。
空态包含插画、“暂无定时任务”和“试试这些常用任务”。固定证据显示 12 张模板卡:每日 AI 新闻推送、每日 5 个英语单词、每日儿童睡前故事、每周工作周报、经典电影推荐、历史上的今天、每日一个为什么、父母联系提醒、体检预约提醒、面试准备提醒、会议前准备、可爱萌宠手机壁纸。
模板卡为三列,实测单卡约 `326.56×82`,圆角 `16`,内边距 `16px 20px`,列间约 `12`、行间约 `12`。静态点击处理会生成预填的自动化草稿;本轮未运行模板点击流程。
## 新建/编辑表单
固定弹窗宽 `768`、高约 `470.4`,内容面板圆角 `16`,遮罩为 `rgba(0,0,0,.8)`。静态组件配置禁止遮罩点击和 Escape 直接关闭,提供右上角按钮或“取消”;这些关闭行为尚未运行态验证。
标题为“新建定时任务”或“编辑定时任务”。底部“取消 / 确定”位于右对齐页脚,页脚内边距 `24`、按钮间距 `12`。
名称输入框实测约 `721.94×38.41`,圆角 `8`,占位“输入任务名称”。提示词使用富文本编辑器,实测区域约 `721.94×180.48`,占位“添加提示词”,最大 100,000 字符。
提示词编辑器接入共用输入能力,包括模型、专家、连接器、工作空间、权限和可选技能。执行配置至少包含:
- `cwd` / `workspaceScope`
- `modelId`、`modelThinking`、`reasoningEffort`、`contextWindow`
- `expertId`、`expertMarketplace`
- `connectorIds[]`、`skills[]`
- `permissionMode`
- `pushToWecomBot`、`wecomBotSource`
默认权限为 `fullAccess`。静态提交分支包含首次创建或从较低权限切换到完全访问时的确认弹窗,说明文件、终端和互联网能力,并要求确认后保存;该分支尚未运行态验证。
调度行实测为三个等宽字段,约 `230.4×38.4`,字段间距 `16`:重复、时间、有效期。单次任务隐藏有效期字段。
名称或提示词为空、提示词超过上限时“确定”禁用。提交时还会校验名称必填、提示词必填和提示词长度。
## 七类频率及规则
运行态默认显示“重复:每天,时间:当前时间后约 5 分钟”。静态实现确认七类分支:
| 频率 | 模型规则 | UI 行为 |
| --- | --- | --- |
| 间隔 | `FREQ=HOURLY;INTERVAL=N`,可选工作日限制 | 显示“每隔 N 小时”;静态解析也兼容 `FREQ=MINUTELY`,但 UI 会换算成小时 |
| 单次 | `type=once` + ISO `scheduledAt` | 选择日期和时间;必须晚于当前时间,隐藏有效期 |
| 每天 | `FREQ=DAILY;BYHOUR;BYMINUTE` | 每日同一时刻 |
| 每周 | `FREQ=WEEKLY;BYDAY=...;BYHOUR;BYMINUTE` | 多选周一至周日;全选显示“每天”,工作日显示“工作日”,周末显示“周末” |
| 双周 | `FREQ=WEEKLY;INTERVAL=2;BYDAY=...` | 每两周的所选星期 |
| 每月 | `FREQ=MONTHLY;BYMONTHDAY=...;BYHOUR;BYMINUTE` | 支持一个或多个月内日期,静态上限为 31 日 |
| 每年 | `FREQ=YEARLY;BYMONTH;BYMONTHDAY=...;BYHOUR;BYMINUTE` | 选择月份、日期和时间 |
有效期使用 `validFrom`、`validUntil`;二者为空时显示“长期有效”,支持起始、截止或起止区间。日历不允许早于当天,清空后恢复长期有效。
云任务只开放间隔、单次、每天三类分支。YCode 当前范围先做本地任务,不把这条云端限制冒充本地限制。
## 列表、生命周期和运行记录
本节为上述REA静态证据的客户端分支观察,未创建原版任务,也未验证服务端实际执行和状态变化。
任务定义状态至少为 `ACTIVE`、`PAUSED`,单次任务过期后呈现 `EXPIRED` 语义。操作包括编辑、手动运行、暂停、开启、删除、归档和批量删除。
运行记录使用独立列表,列为任务名称、状态、运行时间、耗时、任务类型和操作。状态筛选至少包含全部、运行中、成功、失败;记录可归档、取消归档和删除。
来源至少包含本地、项目、云端。项目任务只允许回到项目查看/管理;云端和移动端记录可能存在只读状态。YCode 首轮只实现本地,项目和云端保留明确未接态。
手动运行不是普通按钮反馈。静态实现等待任务产生真实 `sessionId`,成功后打开对应会话;运行中重复触发会被拒绝,删除运行中的任务也会被拒绝。
## 当前 YCode 现状
`src/renderer/src/components/Sidebar.tsx` 已有定时任务图标映射,但没有定时任务业务页面。
`src/renderer/src/App.tsx` 当前主路由仍是 `chat | capabilities | projects`,没有可达的 `scheduled` 页面。
`src/renderer/src/components/SourceHome.tsx` 有“定时任务”快捷动作,`src/renderer/src/mock.ts` 仍把定时任务标为 `implemented:false`。
`src/renderer/src/components/GeneralSettingsPanel.tsx:336` 只保留禁用态的“定时任务产物通知”,没有通知执行链路。
当前没有自动化定义、运行记录、RRULE 解析、持久化仓库、IPC、主进程调度器、重启恢复或真实会话触发实现。
## 建议数据契约
以下是 YCode 本地实现设计,不是对原版服务端结构的断言:
```text
AutomationDefinition 1 ── 0..n AutomationRun
AutomationRun 0..1 Session
AutomationDefinition 0..1 Workspace / Project
```
`AutomationDefinition`:`id`、`name`、`prompt`、`status`、`schedule`、`execution`、`origin`、可选 `workspaceId/projectId`、`createdAt`、`updatedAt`、可选 `archivedAt`。
`AutomationSchedule`:`type:'once'|'recurring'`、可选 `scheduledAt`、可选 `rrule`、`validFrom?`、`validUntil?`,并建议增加明确 IANA `timeZone`。
`AutomationExecution`:目录/空间、模型与思考配置、上下文窗口、专家、连接器、技能、权限、通知目标和模板来源。
`AutomationRun`:`id`、`automationId`、`trigger:'scheduled'|'manual'|'retry'`、计划时间、排队时间、开始/结束时间、`status`、`sessionId`、工作目录、名称快照、失败摘要、归档时间。
定义和记录必须原子落盘。提交保存时冻结任务名称、提示词、调度与执行配置;修改任务只影响后续运行,不篡改历史记录。
## 本地调度与执行关系
主进程是调度权威。渲染进程只负责表单、列表和倒计时展示,不能依赖页面存活触发任务。
持久化后维护最小触发时间堆或有序索引。启动、系统恢复、时区变化和配置更新时重新计算下一触发点。
到期后先原子创建 `queued` 运行记录并领取任务,再调用现有会话创建、OMP/模型执行和产物链路。一次运行创建或恢复一个会话,会话保存 `automationId`、`runId` 标签。
运行事件继续复用现有 chat 事件总线并广播到所有窗口。运行记录状态由主进程写入;会话失败、用户取消、应用退出和迟到事件都要落到明确终态。
同一自动化默认禁止重叠运行。全局并发需要上限;重复 timer、窗口重启和系统唤醒后的旧任务必须用运行 ID 与唯一约束去重。
错过触发、休眠恢复、失败重试、最大重试次数和退避目前均未从原版证实。YCode 可以先定义本地策略,但必须在 UI 和文档中标注为本地设计。
## 分批实施与验收
### 批次 A:契约与持久化
建立 shared 类型、RRULE 纯函数、仓库文件、错误码和迁移策略。覆盖创建、更新、暂停、归档、非法输入、原子写、损坏文件保护和重启恢复。
### 批次 B:页面与表单
接入侧栏路由、任务/记录双页签、空态、12 个恢复模板、新建/编辑弹窗、权限确认和深浅主题。先复刻已观察静止态,再补频率和时间弹层。
### 批次 C:调度引擎
在主进程实现下一触发计算、持久化队列、单实例领取、系统恢复后的重算、取消和过期。测试必须使用可控时钟,禁止按真实小时等待。
### 批次 D:会话执行闭环
把一次运行接到真实本地模型与工作区,创建独立会话并持续写入运行记录。验收至少覆盖成功、模型错误、用户取消、工作目录失效、应用退出重开和跨窗口同步。
### 批次 E:列表操作与记录
完成启停、手动运行、编辑、删除、归档、批量删除、运行记录筛选、打开会话和只读来源。失败路径必须有真实错误反馈,不以 Toast 代替状态。
### 批次 F:逐状态 1:1
用同视口、同主题、同字体和同数据比对列表、模板、表单、频率弹层、记录表、空态、错误态、Hover/Focus 与过渡。每个状态保留 REA Evidence ID 和本地截图。
## 待补 REA 证据
- 重复、时间、有效期三个弹层的完整 DOM、计算样式、键盘和边界翻转。
- 每周、双周、每月、每年选择器的实际交互及“工作日/周末”切换。
- 企业微信未连接、URL 重绑定、成功推送和失败提示。
- 任务卡 Hover、运行中、暂停、过期、失败、归档及批量管理状态。
- 运行记录的空、加载、分页、失败详情、归档和删除确认。
- 名称长度上限、精确错误文案、日期跨度限制和编辑单次任务的边界条件。
- 时区来源、夏令时重复/跳过时间、错过触发、休眠恢复、并发和重试策略。
- 原生服务端接口、持久化格式、通知服务、项目任务和云端/移动端只读语义。
这些未知项不能用当前 YCode 行为反推为原版事实。完成既有证据覆盖的本地闭环后,才进入完整 1:1 验收。