feat(schedule): add fixed-rate reminders

This commit is contained in:
pku-xht
2026-08-06 20:37:08 +08:00
committed by Tianyi Cui
parent 1e6e92fb0a
commit ceb0bbd66d
19 changed files with 2173 additions and 528 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write examples/web-schedule/README.md
README.md: b5a2067bfd217baa268965caad63234136e811d5
README.zh.md: 69b9a244dca3cf0e47819b29028a8f70a96e8604
README.md: e7107751dcf2b6f47cae762dc4bf4dbc501d23f3
README.zh.md: 1afbdced1562fd2ea147a39c630cd7301fae6947

View File

@@ -1,19 +1,23 @@
# Session-local Schedule
# Durable Web Schedule
English | [中文](README.zh.md)
This overlay opts one `dsh web` process into Schedule reminders without changing the shipped default Web composition:
This overlay opts one `dsh web` process into durable Schedule reminders without changing the shipped default Web composition:
```sh
dsh web --patch examples/web-schedule/cordis.yml
```
The current overlay supports one-shot reminders created with a positive whole-number `after_seconds` or an absolute `at` target. The model manages them through `schedule_create`, `schedule_list`, and `schedule_delete`; every result identifies delivery as `session-local`.
The current overlay supports one-shot reminders created with a positive whole-number `after_seconds` or an absolute `at` target, plus fixed-rate `every_seconds` reminders at intervals of at least 300 seconds. The model manages them through `schedule_create`, `schedule_list`, and `schedule_delete`; every result identifies the delivery mode as `session-local`.
The browser attaches its IANA zone to each prompt. Time-context tells the model to interpret otherwise-unqualified dates and times in that request's browser zone. This assumption belongs to natural-language interpretation only: `schedule_create.at` must be either a strict RFC 3339 date-time with `Z` or a numeric offset, or `{ date, time, time_zone }` with an explicit `UTC` or IANA Area/Location zone. Schedule does not retain or infer a Session default zone. Daylight-saving gaps are rejected, overlaps choose the first instant, and successful records keep only the resulting UTC target.
An `at` target is either a strict RFC 3339 date-time with `Z` or a numeric offset, or a local `{ date, time, time_zone? }` value. The overlay loads time-context so the model sees the current date, local time, Session zone, and request-zone relationship before calling the tool. A local value may omit `time_zone` only when the current browser zone agrees with the immutable zone captured when that Session was created.
The original Session log owns each reminder. A live root Agent waits until it is fully idle, then queues a normal follow-up turn in that conversation. It never steers current work and adds no separate receipt or reminder card. Closing the process or leaving the Session cold stops its in-memory timer without deleting the record; reopening that same Session restores the wait and delivers an overdue reminder. Reading cold history never activates it, and a fork does not inherit its parent's reminders.
The browser samples its zone for each create or prompt operation. Resuming the Session from another zone does not overwrite the original default: an omitted local zone then returns `timezone_confirmation_required`, and the model asks which zone to use before retrying explicitly. Older headerless Sessions behave the same way with an unavailable default. Daylight-saving gaps are rejected and overlaps choose the first instant; successful records keep only the resulting UTC target.
Create and actual delete operations acknowledge success only after Session persistence confirms their event prefix. Schedule does not provide browser, operating-system, email, SMS, or other external notification. A durable dispatch records that the follow-up was queued; it does not acknowledge model success or user receipt.
The original Session log owns each reminder. A live root Agent waits, retries after it becomes idle, and records a durable dispatch receipt in the Web conversation. Closing the process or leaving the Session cold stops its in-memory timer without deleting the record; reopening that same Session restores the wait and delivers an overdue reminder. Merely reading cold history never activates it, and a fork does not inherit its parent's reminders.
Fixed-rate and cron rules are not supported by this version.
Fixed-rate reminders remain anchored to their first target. A late wake or restart skips the missed backlog and presents only each record's latest due occurrence, then advances to its first future target. All overdue fixed-rate records share one model follow-up when the 300-second recurring gate opens, while each keeps its own durable dispatch, next target, and Web receipt. One-shot reminders bypass that gate.
Create and actual delete operations acknowledge success only after Session persistence confirms their event prefix. A reminder receipt likewise appears only after its dispatch is durable. Schedule does not provide browser, operating-system, email, SMS, or other external notification, and the best-effort model follow-up is not a delivery acknowledgement.
Cron rules are not accepted by this layer.

View File

@@ -1,19 +1,23 @@
# 仅限 Session 内的 Schedule
# 持久 Web Schedule
[English](README.md) | 中文
此 overlay 让一个 `dsh web` 进程显式启用 Schedule 提醒,同时不改变交付的默认 Web 组合:
此 overlay 让一个 `dsh web` 进程显式启用持久 Schedule 提醒,同时不改变交付的默认 Web 组合:
```sh
dsh web --patch examples/web-schedule/cordis.yml
```
当前 overlay 支持使用正整数 `after_seconds` 或绝对时间 `at` 目标创建的一次性提醒。模型通过 `schedule_create``schedule_list``schedule_delete` 管理它们;每个结果都会把交付标为 `session-local`
当前 overlay 支持使用正整数 `after_seconds` 或绝对时间 `at` 目标创建的一次性提醒,也支持间隔至少为 300 秒的固定频率 `every_seconds` 提醒。模型通过 `schedule_create``schedule_list``schedule_delete` 管理它们;每个结果都会把交付模式标为 `session-local`
浏览器会为每条提示词附加其 IANA 时区。Time-context 会告诉模型,把未明确限定时区的日期和时间解释为该请求的浏览器时区。此假设仅用于自然语言解释:`schedule_create.at` 必须是带 `Z` 或数值偏移量且严格符合 RFC 3339 的日期时间,或是带显式 `UTC` 或 IANA Area/Location 时区的 `{ date, time, time_zone }`。Schedule 不保留或推断 Session 默认时区。夏令时缺口会被拒绝,重叠时段选择第一个时刻;成功创建的记录只保留所得的 UTC 目标
`at` 目标可以是带 `Z` 或数值偏移量且严格符合 RFC 3339 的日期时间,也可以是本地 `{ date, time, time_zone? }` 值。此 overlay 会加载时间上下文让模型在调用工具前看到当前日期、本地时间、Session 时区及其与请求时区的关系。只有当前浏览器时区与创建该 Session 时捕获且不可变的时区一致,本地值才可省略 `time_zone`
每条提醒由原 Session 日志拥有。live 根 Agent 会等待到完全 idle再在该对话中排入一个普通 follow-up 轮次。它绝不会中途引导当前工作,也不会添加独立回执或提醒卡片。关闭进程或让 Session 保持 cold 会停止内存 timer但不会删除记录重新打开同一个 Session 会恢复等待并交付逾期提醒。查看 cold 历史不会激活提醒fork 也不会继承父 Session 的提醒
浏览器会在每次创建或提示词操作时采样自身时区。从其他时区恢复 Session 不会覆盖原有的默认时区:此时若省略本地时区,就会返回 `timezone_confirmation_required`,模型会先询问应使用哪个时区,再显式指定该时区重试。没有标头的旧 Session 在默认时区不可用时也会采用相同行为。夏令时缺口会被拒绝,重叠时段则选择第一个时刻;成功创建的记录只保留所得的 UTC 目标
创建和实际删除操作只有在 Session persistence 确认对应事件前缀后才会确认成功。Schedule 不提供浏览器、操作系统、邮件、短信或其他外部通知。持久 dispatch 会记录 follow-up 已经入队;它不确认模型成功或用户已收到提醒。
每条提醒由原 Session 日志拥有。live 根 Agent 会等待,在恢复 idle 后重试,并在 Web 会话中记录持久 dispatch 回执。关闭进程或让 Session 保持 cold 会停止内存 timer但不会删除记录重新打开同一个 Session 会恢复等待并交付逾期提醒。仅查看 cold 历史不会激活提醒fork 也不会继承父 Session 的提醒。
此版本不支持固定速率规则或 cron 规则。
固定频率提醒始终锚定其首个目标。延迟唤醒或重启会跳过错过期间的积压,只呈现每条记录最近一次到期的 occurrence随后推进到该记录的第一个未来目标。300 秒周期性门控开放时,所有 overdue 固定频率记录共享一次模型 follow-up但每条记录仍保有自己的持久 dispatch、下一个目标和 Web 回执。一次性提醒会绕过该门控。
创建和实际删除操作只有在 Session persistence 确认对应事件前缀后才会确认成功。提醒回执同样只在 dispatch 持久化后出现。Schedule 不提供浏览器、操作系统、邮件、短信或其他外部通知best-effort 模型 follow-up 也不构成交付确认。
本层不接受 cron 规则。