Merge pull request #5179 from deepseek-harness/feat/experimental-schedule-bundle

feat(schedule): ship the Schedule switch as an optional bundle
This commit is contained in:
Chinesezjc authored and GitHub committed 2026-09-25 15:57:37 +08:00
commit cfeb478e03
69 files changed
+623 -88

No files matched your search

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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
2026-09-24-web-default-schedule-composition.md: 3f27bb09ebc00d42c32563e17a1de82c8e525be1
2026-09-24-web-default-schedule-composition.zh.md: 9e0e1fb77ce89b579e1bc8b0d4d0a1b9f4e9fea5
@@ -1,6 +1,7 @@
# Agent Note: Schedule in the shipped Web composition
Status: implemented
Archived: 2026-09-25
English | [中文](2026-09-24-web-default-schedule-composition.zh.md)
@@ -1,6 +1,7 @@
# Agent Note: 默认 Web 组合中的 Schedule
Status: implemented
Archived: 2026-09-25
[English](2026-09-24-web-default-schedule-composition.md) | 中文
+3
View File
@@ -376,6 +376,9 @@
"architecture/2026-09-11-wasm-preview-font-and-image-budgets.i18n.yaml": "sha256:af027c7dae53a181e4d73fd2309f69e9ae3c48df0d3b1dfc53cae274aa60d69e",
"architecture/2026-09-11-wasm-preview-font-and-image-budgets.md": "sha256:44dd52839cdb67644c0dbcbc4beb6f36802628c4a8d17a0aad11db1f9be649ed",
"architecture/2026-09-11-wasm-preview-font-and-image-budgets.zh.md": "sha256:8285432ee1676be8b79a05953c4b6ac4a7ca5d8e701173b3a2b533608b584d0a",
"architecture/2026-09-24-web-default-schedule-composition.i18n.yaml": "sha256:8c3d5c614924d0e81f361a299427ac697aefc6189c41eb3f4151f5c42e371ca0",
"architecture/2026-09-24-web-default-schedule-composition.md": "sha256:3a139593ade13f95cbb67094c1eec66cb0a2c14bcc154512799803b2a7d22ab4",
"architecture/2026-09-24-web-default-schedule-composition.zh.md": "sha256:59908f7987058742d1226dc8a801d03c265c84d51172249ba51716b91f084f0c",
"bug-fix/2026-07-19-windows-atomic-write-dacl-preservation.i18n.yaml": "sha256:8be5b0afd8820c593e2ec254d35fb8c384267814104f6234bb9af824c5f974ba",
"bug-fix/2026-07-19-windows-atomic-write-dacl-preservation.md": "sha256:861e6130e893489271478def5f54f212a106a1580b744e6e40f56356f73c7e10",
"bug-fix/2026-07-19-windows-atomic-write-dacl-preservation.zh.md": "sha256:3549257e06f074591de580ebfaa71284c7c384fb0ffb1963c30258d7a7c26db7",
@@ -15,5 +15,5 @@
en: 21d7ec9a9ff3cbf2
zh: 93d03b8b3012aa7e
/agent-note-host-owned-scheduled-messages/consequences:
en: 0358aab730e4bf56
zh: 61e89e0374891f8a
en: a48f13f89a1944b1
zh: f8fa677122ce2e12
@@ -58,7 +58,7 @@ Session inbox persistence and the task put occur in separate persistence systems
**Keep the mock's hourly choice out of the stored vocabulary.** The approved mock lists 每小时整点 beside the daily, weekly and one-shot choices. Hourly and fixed-rate intervals are the same elapsed-time rule, so the card maps that menu slot onto the existing interval kind instead of adding a persisted kind. A dedicated hourly kind would need a new durable variant, its decoder, its target resolution, and its tool schema, all to express what an interval already expresses.
Task discovery and timers do not depend on loaded Sessions. The after, absolute-time, and fixed-rate selectors retain their semantics alongside Daily, Weekly, and Cron; reading existing saved tasks does not rewrite them. The Host must have its ordinary Session persistence and recovery services available, and the Web bundle mounts Schedule in its host row list. Explicit deletion stops future delivery and removes the task from `list` and `catalog` without deleting conversation messages; the removed row takes its saved receipts with it. History is pruned to the configured window and record cap when an acknowledgment is appended, loaded into Host memory, and rewritten with the task on each acknowledgment. Pagination limits the returned record count; the plugin configuration (`deliveryHistoryDays`, default 30, and `deliveryHistoryRecords`, default 200) limits storage growth. Earlier overwritten receipts and deliveries whose task write failed cannot be reconstructed. Pause and execution-history operations remain unsupported.
Task discovery and timers do not depend on loaded Sessions. The after, absolute-time, and fixed-rate selectors retain their semantics alongside Daily, Weekly, and Cron; reading existing saved tasks does not rewrite them. The Host must have its ordinary Session persistence and recovery services available, and enabling the optional experimental bundle `@deepseek-ai/dsh-experimental-schedule-bundle` mounts Schedule; the Web composition carries its row disabled. Explicit deletion stops future delivery and removes the task from `list` and `catalog` without deleting conversation messages; the removed row takes its saved receipts with it. History is pruned to the configured window and record cap when an acknowledgment is appended, loaded into Host memory, and rewritten with the task on each acknowledgment. Pagination limits the returned record count; the plugin configuration (`deliveryHistoryDays`, default 30, and `deliveryHistoryRecords`, default 200) limits storage growth. Earlier overwritten receipts and deliveries whose task write failed cannot be reconstructed. Pause and execution-history operations remain unsupported.
Required coverage includes startup from stored tasks, missing-status normalization, cold Session restoration, latest-only catch-up, inactive-task retention without repeat dispatch, real message receipts, deletion across restart, removal of a deleted task's saved deliveries, queue/persistence failures, and disposal. Wall-clock obligations include gaps and skipped dates, earlier-only overlaps, fractional seconds, UTC-range edges, committed-target and alias preservation, and post-restoration clock rollback. Weekly adds weekday normalization and validation, next-target selection across a gap and an overlap, and stored set preservation. Historical decoders must reject Daily, Weekly, and Cron while Host storage accepts them. Client coverage includes every recurring kind, exact rule time, zone, and weekday set, All/Enabled/Inactive status filters, retained inactive details and original-Session navigation, authoritative refresh after confirmed deletion and notification, empty lists, reconnect, and late responses. Presentation coverage includes the page's New action starting a Session, the transcript card's narrowing of persisted result JSON including an incomplete or replayed result, the header clock's direct open for exactly one task and its count label, the idle-only row mark with the hover-card two-task limit and omission line. History coverage includes legacy byte preservation, append and restart, immutable sent instructions, strict latest-receipt consistency, stable cursor pagination, binding checks, failed persistence, and late page replies during refresh or task changes. Cross-store crash duplication remains an explicit limitation rather than a completion claim.
@@ -58,7 +58,7 @@ Session 收件箱持久化和任务 put 发生在两个持久化系统中。收
**不把 mock 的「每小时整点」引入持久词表。** 设计稿把它与每天、每周、仅一次并列。每小时整点与固定间隔在语义上是同一种按经过时间计量的规则,因此详情里的该项直接映射到既有的间隔类型,而不是新增一个持久种类。若真要新增,需要新的持久变体、解码器、目标解析与工具 schema,而它表达的能力现有间隔已经覆盖。
任务发现和 timer 不依赖已加载的 Session。延迟、绝对时间和固定速率选择器在与 Daily、Weekly、Cron 并存时保留自身语义;读取已有任务不会重写它们。Host 必须提供普通 Session 持久化和恢复服务,Web bundle 在其宿主行列表中挂载 Schedule。显式删除会阻止后续投递,并将任务从 `list` 和 `catalog` 中移除,不删除对话消息;被移除的行会带走其已保存回执。历史在追加确认时按配置的窗口与条数上限裁剪,随后加载到 Host 内存,并在每次确认时随任务一起重写。分页限制返回记录数量,不限制存储增长或指令字节数。此前被覆盖的回执,以及任务写入失败的投递记录,无法重建。暂停和执行历史操作仍不受支持。
任务发现和 timer 不依赖已加载的 Session。延迟、绝对时间和固定速率选择器在与 Daily、Weekly、Cron 并存时保留自身语义;读取已有任务不会重写它们。Host 必须提供普通 Session 持久化和恢复服务,而挂载 Schedule 需要启用可选实验 bundle `@deepseek-ai/dsh-experimental-schedule-bundle`;Web 组合以禁用状态携带其条目。显式删除会阻止后续投递,并将任务从 `list` 和 `catalog` 中移除,不删除对话消息;被移除的行会带走其已保存回执。历史在追加确认时按配置的窗口与条数上限裁剪,随后加载到 Host 内存,并在每次确认时随任务一起重写。分页限制返回记录数量,不限制存储增长或指令字节数。此前被覆盖的回执,以及任务写入失败的投递记录,无法重建。暂停和执行历史操作仍不受支持。
必要覆盖范围包括从已存储任务启动、缺失状态规范化、冷 Session 恢复、仅补发最新发生时点、保留未运行任务且不重复投递、真实消息回执、重启后的删除结果、删除会移除已保存发送记录、排队或持久化失败,以及销毁。钟表规则的验证要求包括缺口和跳过的日期、仅选择较早时点的重叠、小数秒、UTC 范围边缘、已提交目标和别名保留,以及恢复后的时钟回拨。Weekly 另需覆盖星期集合的规范化与校验、跨缺口与重叠的下一目标选择,以及已存集合的保留。历史解码器必须拒绝 Daily、Weekly 与 Cron,而宿主存储接受它们。客户端覆盖范围包括每种重复规则、精确规则时间、时区和星期集合、全部/已开启/未运行状态筛选、保留未运行任务详情和原 Session 导航、确认删除和通知后的权威刷新、空列表、重新连接和晚到响应。呈现覆盖范围包括页面“新建”操作打开新会话、transcript 卡片从不完整或回放的结果 JSON 中收窄任务、页头时钟在恰好一个任务时直接打开并给出数量标签、仅空闲行标记及其悬浮卡片两个任务上限与遗漏行。历史覆盖范围包括旧文件字节保留、追加与重启、不可变的发送指令、最近回执一致性严格校验、稳定游标分页、绑定校验、持久化失败,以及刷新或切换任务期间晚到的分页响应。跨存储崩溃导致的重复投递仍是明确限制,不能被表述为完成保证。
@@ -9,11 +9,11 @@
en: 2ba6c43b20a3d347
zh: 5647179ddaa38ad9
/agent-note-ship-experimental-capabilities-as-optional-bundles/decision:
en: 1c5a43b3ce2d3056
zh: b59f549a12cf67d1
en: fdd54ede661f7a83
zh: a41ed1a872bb8ba3
/agent-note-ship-experimental-capabilities-as-optional-bundles/alternatives-considered:
en: a65d84004e48b3ef
zh: 17221f08e7a8a89b
/agent-note-ship-experimental-capabilities-as-optional-bundles/consequences:
en: d52ed0a248131a37
zh: 779b8d415281c5da
en: e7fb2a93a89ba9b6
zh: 37ed9f0a3ca44583
@@ -10,7 +10,7 @@ The Web plugin page offered two optional bundles, Agent Teams and voice input. A
## Decision
`OPTIONAL_BUNDLES` lists Agent Teams, voice input, and Auto review. Every optional bundle declares `icon` and exports `./locale/*.json` with `meta.title` and `meta.description`, so the Official group renders a localized title, description, and image; `verify-default-product-isolation` rejects an optional bundle without them. The Inspector's `cordis.patch.yml` names the package instead of a built-artifact path, so the same file is the bundle patch and the `--patch` overlay for a built Web launch.
`OPTIONAL_BUNDLES` lists Agent Teams, voice input, Auto review, and the Schedule bundle. Every optional bundle declares `icon` and exports `./locale/*.json` with `meta.title` and `meta.description`, so the Official group renders a localized title, description, and image; `verify-default-product-isolation` rejects an optional bundle without them. The Inspector's `cordis.patch.yml` names the package instead of a built-artifact path, so the same file is the bundle patch and the `--patch` overlay for a built Web launch.
An optional bundle is a runtime dependency of the installation, so its dependency graph is downloaded by every `dsh` install. The list therefore admits only packages whose graph is already in the installation's closure; Auto review adds nothing. The Inspector stays available through explicit installation and does not appear in the default plugin list. The browser-use and computer-use providers stay explicit compositions: Playwright MCP, Chrome DevTools MCP, and the native Cua Driver runtime binaries add about 85 MB and 21 packages to every install whether or not the bundle is enabled, and a shipped Cua Driver MCP switch would offer a capability whose executable the installation does not carry. Those provider packages keep locale display metadata for their component rows. Two more packages stay out for other reasons: `ptc-runtime-python` replaces the PTC runtime, and `workflow-ptc` rejects a non-TypeScript runtime at load while the Web presets carry `workflow-ptc` rows a bundle patch cannot reach; `browser-use-stagehand-native` requires a native model name and API key at schema validation with no configuration form on the page.
@@ -22,4 +22,4 @@ An optional bundle is a runtime dependency of the installation, so its dependenc
## Consequences
The Official group grows from two to three entries, each tagged experimental by its experimental name. The runtime dependency closure of the installation is unchanged. A browser-use or computer-use provider still needs its Service Definition and the provider in a profile patch or composition.
The Official group carries four optional-bundle entries, each tagged experimental by its experimental name. The runtime dependency closure of the installation is unchanged. A browser-use or computer-use provider still needs its Service Definition and the provider in a profile patch or composition.
@@ -10,7 +10,7 @@ Web 插件页只提供两个可选 bundle:Agent Teams 与语音输入。Auto r
## 决策
`OPTIONAL_BUNDLES` 列出 Agent Teams、语音输入与 Auto review。每个可选 bundle 都声明 `icon` 并导出带 `meta.title` 与 `meta.description` 的 `./locale/*.json`,官方分组因此能渲染本地化标题、描述和图片;`verify-default-product-isolation` 会拒绝缺少这些声明的可选 bundle。Inspector 的 `cordis.patch.yml` 直接写包名而非构建产物路径,所以同一文件既是 bundle patch,也是已构建 Web 启动的 `--patch` overlay。
`OPTIONAL_BUNDLES` 列出 Agent Teams、语音输入、Auto review 与 Schedule bundle。每个可选 bundle 都声明 `icon` 并导出带 `meta.title` 与 `meta.description` 的 `./locale/*.json`,官方分组因此能渲染本地化标题、描述和图片;`verify-default-product-isolation` 会拒绝缺少这些声明的可选 bundle。Inspector 的 `cordis.patch.yml` 直接写包名而非构建产物路径,所以同一文件既是 bundle patch,也是已构建 Web 启动的 `--patch` overlay。
可选 bundle 是安装的运行时依赖,其依赖图会随每次 `dsh` 安装一起下载。因此名单只接纳依赖图已在安装闭包内的包;Auto review 不增加任何依赖。Inspector 保留显式安装方式,不在默认插件列表中显示。浏览器操作与电脑操作提供方仍保持显式组合:Playwright MCP、Chrome DevTools MCP 与原生 Cua Driver 运行时二进制会让每次安装多出约 85 MB、21 个包,无论 bundle 是否启用;而随附的 Cua Driver MCP 开关会提供一个安装本身并不携带其可执行文件的能力。这些提供方包保留 locale 显示元数据,供组件行使用。另有两个包因其他原因不纳入:`ptc-runtime-python` 会替换 PTC 运行时,而 `workflow-ptc` 在加载时拒绝非 TypeScript 运行时,且 Web preset 内含 bundle patch 无法触及的 `workflow-ptc` 行;`browser-use-stagehand-native` 在 schema 校验时就要求原生模型名称与 API 密钥,而插件页没有对应的配置表单。
@@ -22,4 +22,4 @@ Web 插件页只提供两个可选 bundle:Agent Teams 与语音输入。Auto r
## 后果
官方分组从两项增至三项,每项都因实验包名而带实验性标签。安装的运行时依赖闭包保持不变。浏览器操作或电脑操作提供方仍需在 profile patch 或组合中同时挂载其 Service Definition 与提供方。
官方分组包含四个可选 bundle 条目,每项都因实验包名而带实验性标签。安装的运行时依赖闭包保持不变。浏览器操作或电脑操作提供方仍需在 profile patch 或组合中同时挂载其 Service Definition 与提供方。
@@ -0,0 +1,19 @@
# Bilingual-pair consistency record for 2026-09-24-schedule-opt-in-optional-bundle.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-09-24-schedule-opt-in-optional-bundle.md
/agent-note-schedule-as-an-opt-in-optional-bundle:
en: d234bf064c5990f1
zh: c54b941429b4658c
/agent-note-schedule-as-an-opt-in-optional-bundle/problem:
en: 2409ea3a006ea5d9
zh: dbcda58a4c6b5b9f
/agent-note-schedule-as-an-opt-in-optional-bundle/decision:
en: 5aa944749a231645
zh: c14651be6367ee13
/agent-note-schedule-as-an-opt-in-optional-bundle/alternatives-considered:
en: 1782c8ecdbe6bf87
zh: dd6997d067257562
/agent-note-schedule-as-an-opt-in-optional-bundle/consequences:
en: 8ea1d9aaf25f1702
zh: 32e721347ea55475
@@ -0,0 +1,34 @@
# Agent Note: Schedule as an opt-in optional bundle
Status: implemented
English | [中文](2026-09-24-schedule-opt-in-optional-bundle.zh.md)
> Supersedes [Schedule in the shipped Web composition](../../archived/architecture/2026-09-24-web-default-schedule-composition.md): the three rows now ship disabled, and switching them on is this bundle's job.
## Problem
`packages/bundle/web-app/cordis.patch.yml` inserts `time-context`, `schedule`, and `ui-schedule` with `disabled: true`, so the shipped Web composition exposes no Schedule surface: no `schedule_*` tools, no Session reminder catalog, no Automation tasks page, and no per-step clock reading. The rows have no switch on the product surface; a deployment that wants them edits a profile patch layer or passes a `--patch` overlay, and both are configuration files a person using the shipped Web profile cannot reach.
## Decision
The rows stay in the composition because an id-targeted patch overrides an existing row: a profile patch or a bundle sets a row's `disabled` to `false` without inserting it again.
`@deepseek-ai/dsh-experimental-schedule-bundle` (`packages/experimental/schedule-bundle/`) carries three id-targeted patches in its `cordis.patch.yml`, one per row, each setting `disabled: false`; it inserts no row. `OPTIONAL_BUNDLES` in `packages/boot/app-boot/src/profile.ts` names the package, and `apps/cli` declares it as a runtime dependency, so every installation ships it switched off. The [experimental-as-optional-bundles decision](2026-09-21-experimental-capabilities-as-optional-bundles.md) owns the `OPTIONAL_BUNDLES` conventions and the localized `icon` and `meta.title` / `meta.description` metadata the Web Plugins page renders in its Official group.
Enabling the bundle turns on `time-context` (a per-step clock reading with the sampled instant, the browser zone attached to the open request, and the elapsed time since the preceding model-visible message), `schedule` (durable reminders plus `schedule_create`, `schedule_list`, `schedule_update`, and `schedule_delete` on live root Agents), and `ui-schedule` (the Session reminder catalog and the Automation tasks page). The bundle switches `time-context` on with `schedule` because a reminder request states a wall-clock target: the sampled instant is what lets the model turn a request such as "tomorrow at nine" into an offset-bearing `at` value. The [Schedule subsystem](../../../../docs/subsystems/schedule.md) owns the durable records, delivery, and management operations; the [Web bundle](../../../../packages/bundle/web-app/README.md) owns the composition that carries the disabled rows. Disabling the bundle restores the shipped composition, and the Host stops scheduling while the `schedule` row stays disabled; stored task records remain in the Schedule domain.
## Alternatives considered
**Ship Schedule on by default.** Every Web session then pays four tool schemas in each request header and one durable user message per eligible step, and a conversation that never creates a reminder pays both costs. The arrangement also left the capability without an off switch on the product surface.
**Keep a `--patch` overlay file.** An overlay is a launch-time argument rather than a product-surface switch, so a person using the shipped Web profile cannot reach it. Re-declaring the rows through its `insert` list does not override them: `applyEntryPatches` appends that list without de-duplicating ids, and the Loader collapses the composed list to one entry per id with the last declaration winning, so the overlay replaces the Web bundle's rows instead of setting fields on them.
**Extract the three rows out of the Web composition into the bundle.** The bundle would insert the rows instead of overriding them, so a profile that also declares one of those ids would have two declarations for it, of which the Loader keeps only the last. The disabled rows are what an override-style switch targets.
## Consequences
- A default `dsh web` session carries no Schedule tool schemas, no Session reminder catalog, no Automation tasks page, and no per-step clock reading. An installation that wants them enables the optional bundle from the Plugins page or lists the package in a profile's `dsh.profile.bundles`.
- An enabled installation adds four tool schemas to every live root Agent and one durable clock message per eligible step; the reading is model-visible and durable, so it replays, compacts, and appears in exported Session logs like any other user message.
- A composition that does not carry the three Web rows reports one `patch: entry <id> not found` warning per patch and mounts nothing from this bundle, and its package declares no plugin dependency, so enabling it cannot mount a Host service twice.
- The switch is configuration-only: `src/index.ts` is an empty module, the patch carries the runtime content, and the package owns no mutable runtime state, so it publishes no invariant companion.
@@ -0,0 +1,34 @@
# Agent Note: Schedule 作为按需开启的可选 bundle
Status: implemented
[English](2026-09-24-schedule-opt-in-optional-bundle.md) | 中文
> 取代[默认 Web 组合中的 Schedule](../../archived/architecture/2026-09-24-web-default-schedule-composition.md):这三行现在默认禁用,打开它们是此 bundle 的职责。
## Problem
`packages/bundle/web-app/cordis.patch.yml` 以 `disabled: true` 插入 `time-context`、`schedule` 与 `ui-schedule`,因此随发行版交付的 Web 组合不提供任何定时能力:没有 `schedule_*` 工具、没有 Session 提醒目录、没有自动化任务页面,也没有逐步时钟读数。这些条目在产品界面上没有开关;想要它们的部署要改 profile patch 层或传 `--patch` overlay,而两者都是使用随发行版 Web profile 的人无法触及的配置文件。
## Decision
这三行仍留在组合中,因为按 id 定位的 patch 覆盖的是已存在的行:profile patch 或 bundle 把某行的 `disabled` 设为 `false`,无需再次插入它。
`@deepseek-ai/dsh-experimental-schedule-bundle`(`packages/experimental/schedule-bundle/`)在其 `cordis.patch.yml` 中携带三个按 id 定位的 patch,每行一个,各自把 `disabled` 设为 `false`;它不插入任何行。`packages/boot/app-boot/src/profile.ts` 的 `OPTIONAL_BUNDLES` 列出该包,`apps/cli` 将其声明为运行时依赖,因此每次安装都随包携带且默认关闭。[实验性能力作为可选 bundle 的决策](2026-09-21-experimental-capabilities-as-optional-bundles.zh.md)负责 `OPTIONAL_BUNDLES` 的约定,以及 Web 插件管理页在 Official 分组中渲染的本地化 `icon` 与 `meta.title` / `meta.description` 元数据。
启用该 bundle 会打开 `time-context`(每个步骤的时钟读数,包含采样瞬时、附加到当前开放请求的浏览器时区,以及自前一条模型可见消息以来的经过时长)、`schedule`(持久提醒,以及每个活跃根 Agent 上的 `schedule_create`、`schedule_list`、`schedule_update` 与 `schedule_delete`),以及 `ui-schedule`(Session 提醒目录与自动化任务页面)。该 bundle 把 `time-context` 与 `schedule` 一起打开,因为提醒请求给出的是挂钟时间目标:采样瞬时正是让模型把“明天九点”这类请求转换成带偏移量的 `at` 值的依据。持久记录、投递与管理操作由 [Schedule 子系统](../../../../docs/subsystems/schedule.zh.md)负责;承载这些禁用行的组合由 [Web bundle](../../../../packages/bundle/web-app/README.zh.md)负责。禁用该 bundle 会恢复随发行版交付的组合,`schedule` 行保持禁用期间 Host 不再调度;已存储的任务记录保留在 Schedule domain 中。
## Alternatives considered
**默认发布 Schedule。** 那样每个 Web 会话都要在每个请求头中带上四个工具 schema,并在每个符合条件的步骤追加一条持久 user 消息,从不创建提醒的对话也要承担这两项成本。这种安排还让该能力在产品界面上没有关闭开关。
**保留一个 `--patch` overlay 文件。** overlay 是启动时的参数,而不是产品界面上的开关,因此使用随发行版 `web` profile 的人无法触及它。通过它的 `insert` 列表重新声明这些条目并不能覆盖它们:`applyEntryPatches` 追加该列表时不对 id 去重,而 Loader 会把组合出的列表按 id 收敛为一个条目、最后一个声明生效,因此该 overlay 会替换 Web Bundle 的条目,而不是给它们设值。
**把这三行从 Web 组合中抽出、移入 bundle。** 这样 bundle 会插入这些行而不是覆盖它们;某个 profile 若也声明了这些 id,同一个 id 就会有两份声明,而 Loader 只保留最后一份。按需开关针对的正是这些禁用行。
## Consequences
- 默认的 `dsh web` 会话不带 Schedule 工具 schema、Session 提醒目录、自动化任务页面与逐步时钟读数。需要它们的安装可从插件管理页启用该可选 bundle,或把该包列进 profile 的 `dsh.profile.bundles`。
- 启用后的安装会给每个活跃根 Agent 增加四个工具 schema,并在每个符合条件的步骤追加一条持久时钟消息;该读数对模型可见且持久,因此它与其他 user 消息一样参与回放、压缩,并出现在导出的 Session 日志中。
- 在不携带这三行 Web 行的组合中,该 bundle 的每个补丁都会报告一条 `patch: entry <id> not found` 警告且不挂载任何东西;其包不声明插件依赖,因此启用它不会重复挂载同一个 Host 服务。
- 该开关只涉及配置:`src/index.ts` 是空模块,运行时内容由 patch 承载,包本身不拥有可变的运行时状态,因此不发布不变量伴随模块。
@@ -1,22 +0,0 @@
# Bilingual-pair consistency record for 2026-09-24-web-default-schedule-composition.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-09-24-web-default-schedule-composition.md
/agent-note-schedule-in-the-shipped-web-composition:
en: 39229d7ab6ed433b
zh: 54287471d371a11c
/agent-note-schedule-in-the-shipped-web-composition/problem:
en: 2871fd5ed881c007
zh: d03c78d402d186da
/agent-note-schedule-in-the-shipped-web-composition/decision:
en: bb19ad12b2ab0ffc
zh: 971f33e95474a36c
/agent-note-schedule-in-the-shipped-web-composition/recorded-sessions:
en: 5539a42052f4ddb7
zh: 98cc190ae63b4549
/agent-note-schedule-in-the-shipped-web-composition/alternatives-considered:
en: ca032a407c2ee8cb
zh: 748a4fcf2485a3da
/agent-note-schedule-in-the-shipped-web-composition/consequences:
en: 4f23bda8fda37987
zh: 9f7c4a3538bd2979
+1
View File
@@ -39,6 +39,7 @@
"@deepseek-ai/dsh-compaction-tool-result-pruner": "workspace:*",
"@deepseek-ai/dsh-cordis-client-runner": "workspace:*",
"@deepseek-ai/dsh-experimental-agent-team-profile": "workspace:*",
"@deepseek-ai/dsh-experimental-schedule-bundle": "workspace:*",
"@deepseek-ai/dsh-fs-local": "workspace:*",
"@deepseek-ai/dsh-goal": "workspace:*",
"@deepseek-ai/dsh-goal-round-driver": "workspace:*",
@@ -1,2 +0,0 @@
- id: schedule
disabled: false
@@ -8,7 +8,8 @@ import type { DailyScheduleRecord, ScheduleCatalogEntry } from '@deepseek-ai/dsh
import { expect, it } from 'vitest'
import { withDefaultWeb, webGet, webRequest } from './default-web-process.ts'
const patches = [fileURLToPath(new URL('./fixtures/schedule.patch.yml', import.meta.url))]
/** The optional Schedule bundle is the switch this built-Web scenario turns on. */
const patches = [fileURLToPath(new URL('../../../../../../packages/experimental/schedule-bundle/cordis.patch.yml', import.meta.url))]
const id = 'retained-remote-task' as DailyScheduleRecord['id']
const sessionId = 'unloaded-owner' as ScheduleCatalogEntry['sessionId']
+4 -2
View File
@@ -223,8 +223,10 @@ export function createAssembledRemote(options: AssembledRemoteOptions = {}): Ass
return ok(undefined)
})
mock.unary('session/list', () => ok({ items: structuredClone(sessions) }))
// The shipped Web composition mounts the Schedule client, whose catalog and
// per-Session list read empty here: these scenarios drive no reminder.
// The shipped bundle layers this graph composes carry the `ui-schedule` row
// disabled, so the Schedule client does not mount and no case here reads the
// catalog or the per-Session list. Both stay declared so an enabled
// composition reads empty lists instead of a missing-rule failure.
mock.unary('schedule/catalog', () => ok([]))
mock.unary('schedule/list', () => ok([]))
mock.unary('session/projections', (request: unknown) => {
@@ -3,7 +3,7 @@
- button "刷新"
- button "添加插件"
- heading "官方" [level=3]
- text: "7"
- text: "8"
- list:
- listitem:
- button "查看 智能体团队": 智能体团队
@@ -13,6 +13,10 @@
- button "查看 自动授权审查": 自动授权审查
- text: 实验性 提供自动审查权限模式,由模型在每次工具调用前判断是否授权。
- switch "启用 自动授权审查"
- listitem:
- button "查看 定时与时间上下文": 定时与时间上下文
- text: 实验性 启用持久提醒、自动化任务页面与逐步时钟上下文。
- switch "启用 定时与时间上下文"
- listitem:
- button "查看 语音输入": 语音输入
- text: 实验性 在本机使用 SenseVoice 转写录音;首次使用需安装依赖
@@ -3,7 +3,7 @@
- button "刷新"
- button "添加插件"
- heading "官方" [level=3]
- text: "7"
- text: "8"
- list:
- listitem:
- button "查看 智能体团队": 智能体团队
@@ -13,6 +13,10 @@
- button "查看 自动授权审查": 自动授权审查
- text: 实验性 提供自动审查权限模式,由模型在每次工具调用前判断是否授权。
- switch "启用 自动授权审查"
- listitem:
- button "查看 定时与时间上下文": 定时与时间上下文
- text: 实验性 启用持久提醒、自动化任务页面与逐步时钟上下文。
- switch "启用 定时与时间上下文"
- listitem:
- button "查看 语音输入": 语音输入
- text: 实验性 在本机使用 SenseVoice 转写录音;首次使用需安装依赖
@@ -3,7 +3,7 @@
- button "刷新"
- button "添加插件"
- heading "官方" [level=3]
- text: "7"
- text: "8"
- list:
- listitem:
- button "查看 智能体团队": 智能体团队
@@ -13,6 +13,10 @@
- button "查看 自动授权审查": 自动授权审查
- text: 实验性 提供自动审查权限模式,由模型在每次工具调用前判断是否授权。
- switch "启用 自动授权审查"
- listitem:
- button "查看 定时与时间上下文": 定时与时间上下文
- text: 实验性 启用持久提醒、自动化任务页面与逐步时钟上下文。
- switch "启用 定时与时间上下文"
- listitem:
- button "查看 语音输入": 语音输入
- text: 实验性 在本机使用 SenseVoice 转写录音;首次使用需安装依赖
+2 -5
View File
@@ -1,9 +1,6 @@
# Browser-zone assertions need a fresh reading after the non-browser preparation turn.
# The Schedule rows stay disabled in the shipped composition; the scenario enables them
# with the shipped `@deepseek-ai/dsh-experimental-schedule-bundle` patch.
- id: time-context
disabled: false
config:
refreshIntervalMs: 0
- id: schedule
disabled: false
- id: ui-schedule
disabled: false
+5 -2
View File
@@ -44,6 +44,9 @@ declare module '@deepseek-ai/dsh-llm' {
}
const MODE = webSnapshotMode()
/** The optional Schedule bundle is the switch these scenarios turn on. */
const SCHEDULE_BUNDLE = fileURLToPath(new URL('../../../packages/experimental/schedule-bundle/cordis.patch.yml', import.meta.url))
const TIME_CONTEXT_EVERY_STEP = fileURLToPath(new URL('./fixtures/time-context-every-step.patch.yml', import.meta.url))
const SNAPSHOT_DIR = fileURLToPath(new URL('./expected/schedule-after', import.meta.url))
const AFTER_EXPECTED = join(SNAPSHOT_DIR, 'conversation.expected.md')
const AT_EXPECTED = join(SNAPSHOT_DIR, 'at-conversation.expected.md')
@@ -272,7 +275,7 @@ describe.skipIf(MODE === 'record')('web e2e: conversational reminders', () => {
beforeAll(async () => {
scaffold = await launchWebScaffold({
extraOverlayPath: fileURLToPath(new URL('./fixtures/time-context-every-step.patch.yml', import.meta.url)),
extraOverlayPath: [SCHEDULE_BUNDLE, TIME_CONTEXT_EVERY_STEP],
})
scaffold.ctx.effect(
() => scaffold.ctx.llm.registerAdapter([AFTER_PROVIDER], afterAdapter),
@@ -710,7 +713,7 @@ describe.skipIf(MODE === 'record')('web e2e: active Schedule catalog', () => {
beforeAll(async () => {
const fixture = await readFile(CATALOG_FIXTURE, 'utf8')
scaffold = await launchWebScaffold({
extraOverlayPath: fileURLToPath(new URL('./fixtures/time-context-every-step.patch.yml', import.meta.url)),
extraOverlayPath: [SCHEDULE_BUNDLE, TIME_CONTEXT_EVERY_STEP],
})
await seedSession(scaffold, fixture, CATALOG_SESSION_ID, 'standard')
const records = foldScheduleEvents(fixture.trim().split('\n').slice(1).map(line => JSON.parse(line) as SessionEvent)).active
+1
View File
@@ -4424,6 +4424,7 @@ Imported as libraries by other packages; a `cordis.yml` cannot load them.
| `@deepseek-ai/dsh-deque` | — | [`packages/util/deque/src/index.ts`](../packages/util/deque/src/index.ts) |
| `@deepseek-ai/dsh-experimental-agent-team-profile` | — | [`packages/experimental/agent-team-profile/src/index.ts`](../packages/experimental/agent-team-profile/src/index.ts) |
| `@deepseek-ai/dsh-experimental-browser-use-runtime` | — | [`packages/experimental/browser-use-runtime/src/index.ts`](../packages/experimental/browser-use-runtime/src/index.ts) |
| `@deepseek-ai/dsh-experimental-schedule-bundle` | — | [`packages/experimental/schedule-bundle/src/index.ts`](../packages/experimental/schedule-bundle/src/index.ts) |
| `@deepseek-ai/dsh-experimental-voice-input-bundle` | — | [`packages/experimental/voice-input-bundle/src/index.ts`](../packages/experimental/voice-input-bundle/src/index.ts) |
| `@deepseek-ai/dsh-experimental-webworker-packer` | — | [`packages/experimental/webworker-packer/src/index.ts`](../packages/experimental/webworker-packer/src/index.ts) |
| `@deepseek-ai/dsh-experimental-webworker-runtime` | — | [`packages/experimental/webworker-runtime/src/index.ts`](../packages/experimental/webworker-runtime/src/index.ts) |
+1
View File
@@ -4426,6 +4426,7 @@ export interface Config {
| `@deepseek-ai/dsh-deque` | — | [`packages/util/deque/src/index.ts`](../packages/util/deque/src/index.ts) |
| `@deepseek-ai/dsh-experimental-agent-team-profile` | — | [`packages/experimental/agent-team-profile/src/index.ts`](../packages/experimental/agent-team-profile/src/index.ts) |
| `@deepseek-ai/dsh-experimental-browser-use-runtime` | — | [`packages/experimental/browser-use-runtime/src/index.ts`](../packages/experimental/browser-use-runtime/src/index.ts) |
| `@deepseek-ai/dsh-experimental-schedule-bundle` | — | [`packages/experimental/schedule-bundle/src/index.ts`](../packages/experimental/schedule-bundle/src/index.ts) |
| `@deepseek-ai/dsh-experimental-voice-input-bundle` | — | [`packages/experimental/voice-input-bundle/src/index.ts`](../packages/experimental/voice-input-bundle/src/index.ts) |
| `@deepseek-ai/dsh-experimental-webworker-packer` | — | [`packages/experimental/webworker-packer/src/index.ts`](../packages/experimental/webworker-packer/src/index.ts) |
| `@deepseek-ai/dsh-experimental-webworker-runtime` | — | [`packages/experimental/webworker-runtime/src/index.ts`](../packages/experimental/webworker-runtime/src/index.ts) |
+2
View File
@@ -258,6 +258,7 @@ flowchart TD
pkg_experimental_computer_use_cua_driver_native["experimental-computer-use-cua-driver-native"]
pkg_experimental_inspector["experimental-inspector"]
pkg_experimental_ptc_runtime_python["experimental-ptc-runtime-python"]
pkg_experimental_schedule_bundle["experimental-schedule-bundle"]
pkg_experimental_speech_to_text["experimental-speech-to-text"]
pkg_experimental_speech_to_text_sensevoice["experimental-speech-to-text-sensevoice"]
pkg_experimental_tool_agent_team["experimental-tool-agent-team"]
@@ -1452,6 +1453,7 @@ flowchart TD
| [`client-web`](../packages/client/web) | `client` | — |
| [`office-to-pdf`](../packages/document/office-to-pdf) | `document` | — |
| [`experimental-agent-team-profile`](../packages/experimental/agent-team-profile) | `experimental` | — |
| [`experimental-schedule-bundle`](../packages/experimental/schedule-bundle) | `experimental` | — |
| [`experimental-voice-input-bundle`](../packages/experimental/voice-input-bundle) | `experimental` | — |
| [`experimental-webworker-packer`](../packages/experimental/webworker-packer) | `experimental` | — |
| [`client-ui-cordis`](../packages/extensions/ui-cordis) | `extensions` | — |
+2
View File
@@ -260,6 +260,7 @@ flowchart TD
pkg_experimental_computer_use_cua_driver_native["experimental-computer-use-cua-driver-native"]
pkg_experimental_inspector["experimental-inspector"]
pkg_experimental_ptc_runtime_python["experimental-ptc-runtime-python"]
pkg_experimental_schedule_bundle["experimental-schedule-bundle"]
pkg_experimental_speech_to_text["experimental-speech-to-text"]
pkg_experimental_speech_to_text_sensevoice["experimental-speech-to-text-sensevoice"]
pkg_experimental_tool_agent_team["experimental-tool-agent-team"]
@@ -1454,6 +1455,7 @@ flowchart TD
| [`client-web`](../packages/client/web) | `client` | — |
| [`office-to-pdf`](../packages/document/office-to-pdf) | `document` | — |
| [`experimental-agent-team-profile`](../packages/experimental/agent-team-profile) | `experimental` | — |
| [`experimental-schedule-bundle`](../packages/experimental/schedule-bundle) | `experimental` | — |
| [`experimental-voice-input-bundle`](../packages/experimental/voice-input-bundle) | `experimental` | — |
| [`experimental-webworker-packer`](../packages/experimental/webworker-packer) | `experimental` | — |
| [`client-ui-cordis`](../packages/extensions/ui-cordis) | `extensions` | — |
+4 -4
View File
@@ -9,8 +9,8 @@
en: 41cd197b5c74bfa3
zh: 18ed11259036d726
/host-wide-schedule/absolute-time-input:
en: e730fda52ba2854f
zh: 01a6c682e327a133
en: 0876a14a60ba2160
zh: e7d4bd9099c14fb2
/host-wide-schedule/daily-wall-clock-input:
en: 2d249edc3dfccb8a
zh: 33fecda132b03b84
@@ -27,8 +27,8 @@
en: 0656173de50ee132
zh: 54176540371d0f28
/host-wide-schedule/web-catalog:
en: 39f24636dd788034
zh: ba3ff541fee5854a
en: 60c88b08abde9bb0
zh: 0a3644cfa86d014d
/host-wide-schedule/timing-edits:
en: ce5d2095a3ad2e82
zh: 167b3715f8eaffc1
+2 -2
View File
@@ -116,7 +116,7 @@ interface LocalAtInput {
type AtInput = string | LocalAtInput
```
The shipped Web bundle mounts time-context, which samples the browser's IANA zone for every prompt. Time-context tells the model to interpret otherwise-unqualified natural-language dates and times in that request-local zone when the open turn has one unambiguous browser zone; mixed or missing browser-zone records tell the model to ask. That guidance is not a durable Session default: the model must still pass an offset in the string form or `time_zone` in the local form, and Schedule never reads browser, Session, process, or model context.
The shipped Web composition carries the `time-context` row disabled; the optional experimental bundle `@deepseek-ai/dsh-experimental-schedule-bundle`, enabled from the Plugins page, mounts time-context, which samples the browser's IANA zone for every prompt. Time-context tells the model to interpret otherwise-unqualified natural-language dates and times in that request-local zone when the open turn has one unambiguous browser zone; mixed or missing browser-zone records tell the model to ask. That guidance is not a durable Session default: the model must still pass an offset in the string form or `time_zone` in the local form, and Schedule never reads browser, Session, process, or model context.
Schedule rejects invalid offsets and zones, offset-free strings, non-future targets, and local times inside daylight-saving gaps. A daylight-saving overlap chooses its first, earlier instant. Successful creation stores only canonical UTC `scheduledAt`, so replay never depends on ambient time-zone state.
@@ -339,7 +339,7 @@ type ScheduleCatalogEntry = ScheduleRecord & {
The Remote `schedule.list({ sessionId })`, model `schedule_list`, and Session-header catalog return only active tasks. A model view's derived timing `state` remains distinct from stored lifecycle `status`. Deletion uses `schedule.delete({ sessionId, id })` with the entry's original binding; a mismatched binding returns not found. Model tools supply the current Agent's Session, whereas the global user interface supplies the selected task's binding. The binding check alone does not establish caller authorization. The payload-free `schedule/changed` event invalidates client lists; reconnecting clients fetch current state again.
The Web bundle mounts `ui-schedule` with the Host capability. The [client package](../../packages/client/ui-schedule/README.md) owns the catalog, empty state, and deletion controls. The page separately filters all, active, and inactive tasks, retains inactive details and an original-Session control in the detail tab strip, and requires explicit confirmed deletion. Rules and Delivery records separate task settings from lazily paged saved receipts. Neither a receipt nor inactive status confirms model execution.
The shipped Web composition carries the `ui-schedule` row disabled; the optional experimental bundle `@deepseek-ai/dsh-experimental-schedule-bundle`, enabled from the Plugins page, mounts `ui-schedule` with the Host capability. The [client package](../../packages/client/ui-schedule/README.md) owns the catalog, empty state, and deletion controls. The page separately filters all, active, and inactive tasks, retains inactive details and an original-Session control in the detail tab strip, and requires explicit confirmed deletion. Rules and Delivery records separate task settings from lazily paged saved receipts. Neither a receipt nor inactive status confirms model execution.
## Timing edits
+2 -2
View File
@@ -116,7 +116,7 @@ interface LocalAtInput {
type AtInput = string | LocalAtInput
```
发布的 Web bundle 会挂载 time-context,它为每条提示词采样浏览器的 IANA 时区。当 open turn 只有一个无歧义的浏览器时区时,Time-context 会告诉模型按该请求本地时区解释未明确限定时区的自然语言日期和时间;浏览器时区记录混合或缺失时,则告诉模型询问用户。该指引不是持久 Session 默认值:模型仍必须在字符串形式中传入偏移量,或在本地形式中传入 `time_zone`;Schedule 绝不会读取浏览器、Session、进程或模型上下文。
随发行版交付的 Web 组合把 `time-context` 行保持禁用;在插件管理页启用可选实验性 bundle `@deepseek-ai/dsh-experimental-schedule-bundle` 会挂载 time-context,它为每条提示词采样浏览器的 IANA 时区。当 open turn 只有一个无歧义的浏览器时区时,Time-context 会告诉模型按该请求本地时区解释未明确限定时区的自然语言日期和时间;浏览器时区记录混合或缺失时,则告诉模型询问用户。该指引不是持久 Session 默认值:模型仍必须在字符串形式中传入偏移量,或在本地形式中传入 `time_zone`;Schedule 绝不会读取浏览器、Session、进程或模型上下文。
Schedule 会拒绝无效偏移量与时区、不带偏移量的字符串、非未来目标,以及落在夏令时缺口内的本地时间。遇到夏令时重叠时,会选择第一次出现的较早时点。创建成功后只存储规范化后的 UTC `scheduledAt`,因此回放绝不依赖环境时区状态。
@@ -339,7 +339,7 @@ type ScheduleCatalogEntry = ScheduleRecord & {
Remote 方法 `schedule.list({ sessionId })`、模型 `schedule_list` 和 Session 页头目录仅返回活动任务。模型视图派生的时间 `state` 与存储的生命周期 `status` 仍是不同概念。删除通过 `schedule.delete({ sessionId, id })` 使用条目的原始绑定;绑定不匹配时返回未找到。模型工具传入当前 Agent 的 Session,全局用户界面则传入所选任务的绑定。仅校验绑定并不构成调用者鉴权。无 payload 的 `schedule/changed` 事件通知客户端刷新列表;重新连接后,客户端再次获取当前状态。
Web bundle 将 `ui-schedule` 与宿主能力一起挂载。[客户端包](../../packages/client/ui-schedule/README.zh.md) 负责目录、空状态与删除控件。页面单独筛选全部、活动和未运行任务,保留未运行任务详情及详情页签条内的原 Session 入口,并要求显式确认删除。“规则”和“发送记录”将任务设置与按需分页加载的已保存回执分开。回执与未运行状态均不确认模型执行。
随发行版交付的 Web 组合把 `ui-schedule` 行保持禁用;在插件管理页启用可选实验性 bundle `@deepseek-ai/dsh-experimental-schedule-bundle` 会将它与宿主能力一起挂载。[客户端包](../../packages/client/ui-schedule/README.zh.md) 负责目录、空状态与删除控件。页面单独筛选全部、活动和未运行任务,保留未运行任务详情及详情页签条内的原 Session 入口,并要求显式确认删除。“规则”和“发送记录”将任务设置与按需分页加载的已保存回执分开。回执与未运行状态均不确认模型执行。
## 修改时间
+2 -2
View File
@@ -12,8 +12,8 @@
en: b3b2a6e0ce02bdee
zh: 2ddb168de79fd19c
/schedule-reminders/create-reminders:
en: 70ae56895847c453
zh: 19b38057c7462123
en: c76ee99f59529942
zh: be1d75c226231dd7
/schedule-reminders/inspect-and-delete-tasks:
en: a44fc1aabc2ab957
zh: 31f444d4c7fd5c7a
+1 -1
View File
@@ -17,7 +17,7 @@ Create reminders in a conversation, then inspect active and inactive tasks and e
<a id="create-reminders"></a>
## Create reminders
The shipped Web profile mounts Schedule with the clock context that gives the model the current time and the browser's zone. Configure a model provider before asking it to create reminders.
The shipped Web profile carries the `time-context`, `schedule`, and `ui-schedule` rows disabled. Open Plugins and enable `Scheduling and time context` in the Official group; the optional experimental bundle `@deepseek-ai/dsh-experimental-schedule-bundle` then mounts Schedule with the clock context that gives the model the current time and the browser's zone. Configure a model provider before asking it to create reminders.
Ask the model to create, list, edit, or delete reminders. It uses `schedule_create`, `schedule_list`, `schedule_update`, and `schedule_delete` (update changes one reminder in place and keeps its id and saved delivery records); the Automation tasks page's New action opens a New Session for a creation instead, with the request already written in its composer. Supported choices are a one-time delay in positive whole seconds, an absolute date and time, a fixed interval of at least one minute, a daily local time with an IANA time zone, a weekly local time with an IANA time zone and ISO weekdays from Monday 1 through Sunday 7, or a five-field cron expression with an explicit IANA time zone, stored in canonical form.
+1 -1
View File
@@ -17,7 +17,7 @@
<a id="create-reminders"></a>
## 创建提醒
发布的 Web profile 会挂载 Schedule 及其时钟上下文,后者把当前时间和浏览器时区交给模型。在请求模型创建提醒前,先配置模型 provider。
发布的 Web profile 把 `time-context`、`schedule` 与 `ui-schedule` 三行保持禁用。打开插件管理页,在 Official 分组中启用“定时与时间上下文”;可选实验性 bundle `@deepseek-ai/dsh-experimental-schedule-bundle` 随即挂载 Schedule 及其时钟上下文,后者把当前时间和浏览器时区交给模型。在请求模型创建提醒前,先配置模型 provider。
向模型提出创建、列出、修改或删除提醒的请求。模型使用 `schedule_create`、`schedule_list`、`schedule_update` 和 `schedule_delete`(更新原地修改一条提醒,保留其 id 与已保存的投递记录);「自动化任务」页面的「新建」操作则为创建打开一个新会话,其 composer 已写好该请求。支持正整数秒的一次性延迟、绝对日期时间、至少一分钟的固定间隔、带 IANA 时区的每日本地时间、带 IANA 时区和 ISO 星期(周一 1 至周日 7)的每周本地时间,以及带显式 IANA 时区的五字段 cron 表达式(表达式以规范化形式保存)。
+1
View File
@@ -214,6 +214,7 @@ export const OPTIONAL_BUNDLES: readonly string[] = [
'@deepseek-ai/dsh-experimental-agent-team-profile',
'@deepseek-ai/dsh-experimental-voice-input-bundle',
'@deepseek-ai/dsh-experimental-auto-review',
'@deepseek-ai/dsh-experimental-schedule-bundle',
]
const PROFILE_PATCH_TEMPLATE = `# Your patch layer for this dsh profile, applied after every bundle layer:
+2 -2
View File
@@ -21,8 +21,8 @@
en: b7ab01cfe9fed40f
zh: 23703ab7727c3ab5
/deepseek-ai-dsh-web-app/use-this-package/configuration:
en: 4f18797d9de48038
zh: 62387505417e4813
en: cea7ecccb2a03b79
zh: 0af72c22e46045d3
/deepseek-ai-dsh-web-app/use-this-package/lan-access-and-trusted-hosts:
en: 2522c806db384ddc
zh: 7e96f11194af9f9f
+1 -1
View File
@@ -51,7 +51,7 @@ Most users never set these; the command-line flags feed the four settings below
| `surfaceContext` | `true` | Give the agent GUI-orientation context and expose `DSH_WEB_URL` to its shell commands |
| `trustedHosts` | `[]` | Extra hosts allowed to reach the GUI from the network |
The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-web-app) is the exhaustive source for every accepted field and its JSDoc. The shipped composition disables `schedule`, `ui-schedule`, and `time-context` by default.
The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-web-app) is the exhaustive source for every accepted field and its JSDoc. The shipped composition disables `schedule`, `ui-schedule`, and `time-context` by default, and the optional experimental bundle `@deepseek-ai/dsh-experimental-schedule-bundle` switches those three rows on from the Plugins page.
### LAN access and trusted hosts
+1 -1
View File
@@ -51,7 +51,7 @@ dsh --profile web --no-open --port 8080
| `surfaceContext` | `true` | 给 agent 提供 GUI 定位上下文,并把 `DSH_WEB_URL` 暴露给其 shell 命令 |
| `trustedHosts` | `[]` | 允许从网络访问 GUI 的额外主机 |
生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-web-app)是每个受支持字段及其 JSDoc 的穷尽式真源。 随发行版交付的组合默认禁用 `schedule`、`ui-schedule` 和 `time-context`。
生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-web-app)是每个受支持字段及其 JSDoc 的穷尽式真源。 随发行版交付的组合默认禁用 `schedule`、`ui-schedule` 和 `time-context`,可选实验性 bundle `@deepseek-ai/dsh-experimental-schedule-bundle` 可在插件管理页把这三行打开。
### LAN 访问与可信主机
+2 -2
View File
@@ -15,8 +15,8 @@
en: d152484eb41ac6b4
zh: 405b30feaf48c087
/deepseek-ai-dsh-client-ui-schedule/use-this-package:
en: 3594ab6704cbd7b9
zh: 99a965f43187501b
en: bf8096e6e576ac07
zh: 1936c0a75dc5cd4b
/deepseek-ai-dsh-client-ui-schedule/use-this-package/time-zone-data-source:
en: 6bd6882dbbbefcb0
zh: 03aa15f1a65d13dc
+1 -1
View File
@@ -25,7 +25,7 @@ Manage active and inactive tasks from the Automation tasks page and the right Si
<a id="use-this-package"></a>
## Use this package
The shipped Web bundle mounts `ui-schedule` with the Host Schedule service and the clock context that supplies the model's current time. The Automation tasks sidebar entry opens a global page without selecting or activating a Session. The page header's New action starts a new Session, where the reminder is created by asking the model; the page itself has no creation form. Its task list supports text search and one All, Enabled, and Inactive status filter row; search matches the stored task name, the instruction, and the internal Session id, not a resolved Session title, and the empty state keeps the heading's New action beside the notice. Selecting an active or inactive task opens a second detail level with Rules and Delivery records tabs. Every list row shows the task's stored title with its status, frequency, and next run and never the original Session name; the detail's name control shows the stored title. Rules contains the complete reminder, status, next target for active tasks, original recurrence rule, and task id. Daily rule labels show the saved local time and exact stored IANA zone, preserving nonzero seconds and milliseconds rather than substituting the browser's zone. The Linked session entry in the detail tab strip names the linked Session by its catalog title, falling back to the Session id when no title is available. It opens an available, unarchived Session after metadata loads; pending Session or Workspace metadata, an archived Session, missing Session membership, or a Workspace query error keeps it disabled with an explanation. The click rechecks availability; browsing does not unarchive the Session. Only this action requests Session activation. Deletion is available from the More task actions menu in the detail's top strip, separate from navigation.
The shipped Web composition carries the `ui-schedule` row disabled; enable the optional experimental bundle `@deepseek-ai/dsh-experimental-schedule-bundle` from the Plugins page (Official group), or list it in a profile's `dsh.profile.bundles`, to mount `ui-schedule` with the Host Schedule service and the clock context that supplies the model's current time. The Automation tasks sidebar entry opens a global page without selecting or activating a Session. The page header's New action starts a new Session, where the reminder is created by asking the model; the page itself has no creation form. Its task list supports text search and one All, Enabled, and Inactive status filter row; search matches the stored task name, the instruction, and the internal Session id, not a resolved Session title, and the empty state keeps the heading's New action beside the notice. Selecting an active or inactive task opens a second detail level with Rules and Delivery records tabs. Every list row shows the task's stored title with its status, frequency, and next run and never the original Session name; the detail's name control shows the stored title. Rules contains the complete reminder, status, next target for active tasks, original recurrence rule, and task id. Daily rule labels show the saved local time and exact stored IANA zone, preserving nonzero seconds and milliseconds rather than substituting the browser's zone. The Linked session entry in the detail tab strip names the linked Session by its catalog title, falling back to the Session id when no title is available. It opens an available, unarchived Session after metadata loads; pending Session or Workspace metadata, an archived Session, missing Session membership, or a Workspace query error keeps it disabled with an explanation. The click rechecks availability; browsing does not unarchive the Session. Only this action requests Session activation. Deletion is available from the More task actions menu in the detail's top strip, separate from navigation.
Selecting a task from the list opens Rules; refreshing that task preserves the selected tab. Rules edits an active task's name, instruction, and run time; the edits stay in a local draft until saved, and inactive tasks remain read-only. Unmodified Left/Right arrows cycle the tabs, Home/End select the first/last tab, and keyboard focus follows the selection. The tabs do not consume these keys with Alt, Ctrl, Meta, or Shift. The linked-Session control in the detail tab strip stays available on the Rules tab, and confirmed deletion is available from either view.
+1 -1
View File
@@ -25,7 +25,7 @@ kind: "package-reference"
<a id="use-this-package"></a>
## 使用本包
发布的 Web bundle 将 `ui-schedule` 与 Host Schedule 服务、以及为模型提供当前时间的时钟上下文一起挂载。侧栏的自动化任务入口打开全局页面,不选择或激活会话。页面页头的“新建”操作会打开一个新会话,提醒由模型在该会话中创建;页面本身没有创建表单。列表支持文本搜索和一行“全部/已开启/未运行”状态筛选;搜索匹配任务已存储的名称、指令和内部会话 id,不匹配解析出的会话标题,空状态在提示旁保留页头的“新建”操作。选择活动或未运行任务后,进入含“规则”和“任务运行记录”页签的第二层详情。每条列表行显示任务已存储的标题及其状态、频率和下次运行,不显示原会话名称;详情中的名称输入框显示任务已存储的标题。“规则”显示完整提醒、状态、活动任务的下一目标时间、原始重复规则和任务 id。每天的规则标签显示已保存的本地时间与精确的存储 IANA 时区,保留非零秒与毫秒,而不替换为浏览器时区。详情页签条内的“关联会话”入口按会话标题显示,取不到标题时回退显示会话 id。元数据加载后,它可打开可用且未归档的会话;会话或 Workspace 元数据尚未就绪、会话已归档、会话不在列表中或 Workspace 查询失败时,入口保持禁用并显示原因。点击时会重新检查可用性;浏览不会取消会话归档。仅此操作请求激活会话。删除位于详情顶部条带的“更多任务操作”菜单。
随发行版交付的 Web 组合把 `ui-schedule` 行保持禁用;在插件管理页(Official 分组)启用可选实验性 bundle `@deepseek-ai/dsh-experimental-schedule-bundle`,或把它列进 profile 的 `dsh.profile.bundles`,即可将 `ui-schedule` 与 Host Schedule 服务、以及为模型提供当前时间的时钟上下文一起挂载。侧栏的自动化任务入口打开全局页面,不选择或激活会话。页面页头的“新建”操作会打开一个新会话,提醒由模型在该会话中创建;页面本身没有创建表单。列表支持文本搜索和一行“全部/已开启/未运行”状态筛选;搜索匹配任务已存储的名称、指令和内部会话 id,不匹配解析出的会话标题,空状态在提示旁保留页头的“新建”操作。选择活动或未运行任务后,进入含“规则”和“任务运行记录”页签的第二层详情。每条列表行显示任务已存储的标题及其状态、频率和下次运行,不显示原会话名称;详情中的名称输入框显示任务已存储的标题。“规则”显示完整提醒、状态、活动任务的下一目标时间、原始重复规则和任务 id。每天的规则标签显示已保存的本地时间与精确的存储 IANA 时区,保留非零秒与毫秒,而不替换为浏览器时区。详情页签条内的“关联会话”入口按会话标题显示,取不到标题时回退显示会话 id。元数据加载后,它可打开可用且未归档的会话;会话或 Workspace 元数据尚未就绪、会话已归档、会话不在列表中或 Workspace 查询失败时,入口保持禁用并显示原因。点击时会重新检查可用性;浏览不会取消会话归档。仅此操作请求激活会话。删除位于详情顶部条带的“更多任务操作”菜单。
从列表选择任务时默认打开“规则”;刷新同一任务会保留当前页签。活动任务的“规则”修改名称、指令和运行时间;这些修改保留在本地草稿中直到保存,未运行任务保持只读。不带修饰键的左右方向键循环切换页签,Home/End 选择第一个/最后一个页签,键盘焦点随选择移动。页签不会拦截这些键与 Alt、Ctrl、Meta 或 Shift 的组合。共用的会话入口位于详情页签条内,在“规则”页签可见;确认删除操作在两种页签下都可用。
+2 -2
View File
@@ -9,8 +9,8 @@
en: 05a169f23a64b7e4
zh: cf57e471b7f13509
/context-request-context-plugins/summary:
en: 4a48e859cbeca00f
zh: 312b8621ba74a3ec
en: c301d0f01494ac06
zh: 00e51efcde0d1267
/context-request-context-plugins/table-of-contents:
en: 1eb35b015a6c423f
zh: a8a3dceee2c9e943
+1 -1
View File
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
## Summary
The context group provides plugins that add model-visible context to each request without defining any tool: workspace instruction files become guidance, `@file` mentions offer path completion, other sessions can be referenced as bounded snapshots, and the model can see the current time and the agent's tmux location. Only `agent-instructions` (`dsh-base`) and `time-context` (`dsh-web-app`) ship by default; the rest are opt-in. Context is durable: injected instructions and references enter session history as user-role messages, so they persist, replay, and compact like other conversation content. This page maps the group; each package README owns the per-package contract.
The context group provides plugins that add model-visible context to each request without defining any tool: workspace instruction files become guidance, `@file` mentions offer path completion, other sessions can be referenced as bounded snapshots, and the model can see the current time and the agent's tmux location. Only `agent-instructions` (`dsh-base`) ships mounted by default; the rest are opt-in. Context is durable: injected instructions and references enter session history as user-role messages, so they persist, replay, and compact like other conversation content. This page maps the group; each package README owns the per-package contract.
## Table of Contents
+1 -1
View File
@@ -9,7 +9,7 @@ kind: "package-group"
## 概述
context 组提供不定义任何工具、为每次请求添加模型可见上下文的插件:工作区指令文件成为指引,`@file` 提及提供路径补全,其他会话可以作为有界快照被引用,模型还能看到当前时间与 agent(智能体)的 tmux 位置。默认只包含 `agent-instructions`(`dsh-base`)与 `time-context`(`dsh-web-app`);其余全部需主动启用。上下文是持久的:注入的指令与引用以用户角色消息的形式进入会话历史,因此与其他对话内容一样持久保留、可回放、可压缩。本页概述本组;包级约定由各包 README 负责。
context 组提供不定义任何工具、为每次请求添加模型可见上下文的插件:工作区指令文件成为指引,`@file` 提及提供路径补全,其他会话可以作为有界快照被引用,模型还能看到当前时间与 agent(智能体)的 tmux 位置。默认只挂载 `agent-instructions`(`dsh-base`);其余全部需主动启用。上下文是持久的:注入的指令与引用以用户角色消息的形式进入会话历史,因此与其他对话内容一样持久保留、可回放、可压缩。本页概述本组;包级约定由各包 README 负责。
## 目录
@@ -9,8 +9,8 @@
en: ec051915b3d81cda
zh: 3a0ef832e3a5e419
/deepseek-ai-dsh-time-context/summary:
en: e4e308b9fd3fcd56
zh: 9fb4d40ebe621d6a
en: 8160d6d20a8bc98c
zh: b7010a1edf57079b
/deepseek-ai-dsh-time-context/table-of-contents:
en: d152484eb41ac6b4
zh: 09388d293f9be9cb
+1 -1
View File
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
## Summary
`dsh-time-context` gives the model a clock: on eligible steps it appends a durable, source-attributed reading with the current time, the browser zone attached to the open request, and the elapsed time since the preceding model-visible message. It helps the model interpret otherwise-unqualified dates and times in the user's browser zone, and tells it to ask when current-turn browser zones are mixed or missing. The shipped Web bundle mounts it with Schedule. Readings default to a 10-minute minimum interval; `refreshIntervalMs: 0` injects at every eligible step.
`dsh-time-context` gives the model a clock: on eligible steps it appends a durable, source-attributed reading with the current time, the browser zone attached to the open request, and the elapsed time since the preceding model-visible message. It helps the model interpret otherwise-unqualified dates and times in the user's browser zone, and tells it to ask when current-turn browser zones are mixed or missing. The shipped Web composition carries its row disabled; the optional `@deepseek-ai/dsh-experimental-schedule-bundle` mounts it with Schedule from the Plugins page. Readings default to a 10-minute minimum interval; `refreshIntervalMs: 0` injects at every eligible step.
## Table of Contents
+1 -1
View File
@@ -9,7 +9,7 @@ kind: "package-reference"
## 概述
`dsh-time-context` 给模型一只时钟:在符合条件的步骤上,它追加一条持久、带来源的读数,包含当前时间、附加到当前开放请求的浏览器时区,以及自前一条模型可见消息以来的经过时长。它帮助模型按用户的浏览器时区解释未明确限定时区的日期与时间;时区来源混杂或缺失时,它告诉模型去询问。发布的 Web bundle 会随 Schedule 一起挂载它。读数默认采用 10 分钟的最小间隔;`refreshIntervalMs: 0` 会在每个符合条件的步骤注入。
`dsh-time-context` 给模型一只时钟:在符合条件的步骤上,它追加一条持久、带来源的读数,包含当前时间、附加到当前开放请求的浏览器时区,以及自前一条模型可见消息以来的经过时长。它帮助模型按用户的浏览器时区解释未明确限定时区的日期与时间;时区来源混杂或缺失时,它告诉模型去询问。随发行版交付的 Web 组合把该行保持禁用;可选的 `@deepseek-ai/dsh-experimental-schedule-bundle` 在插件管理页会随 Schedule 一起挂载它。读数默认采用 10 分钟的最小间隔;`refreshIntervalMs: 0` 会在每个符合条件的步骤注入。
## 目录
+4 -4
View File
@@ -9,14 +9,14 @@
en: 18bc48bb66b3e516
zh: 51f2340a5c921f36
/packages-experimental/summary:
en: 9341a408afcd5dfa
zh: 07541055b5f41ff8
en: 882aada84ecc5413
zh: daedbca3726e6ac2
/packages-experimental/table-of-contents:
en: 1eb35b015a6c423f
zh: a8a3dceee2c9e943
/packages-experimental/packages:
en: ad10945dac9dbb51
zh: 245b454406ce99f8
en: 74635f0629fe1e84
zh: 6119c5bbc6b807ac
/packages-experimental/related-documentation:
en: 31282a28dd828c81
zh: ebb1d3cacdc1bd6d
+2 -1
View File
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
## Summary
The experimental group contains prototype capabilities whose contracts can change and carry no support promise. All current packages publish under their `@deepseek-ai/dsh-experimental-*` names, including the opt-in Agent Teams composition, Auto review, Cua Driver providers, browser-use backends, cross-realm Inspector, CPython PTC backend, and browser-worker preview libraries. Released products outside this group must not depend on experimental packages. The dsh installation ships the Agent Teams, voice input, and Auto review packages as optional bundles switched on from the Web sidebar's Plugins page ([decision](../../.agents/notes/implemented/architecture/2026-09-21-experimental-capabilities-as-optional-bundles.md)); the other packages are libraries or explicit compositions.
The experimental group contains prototype capabilities whose contracts can change and carry no support promise. All current packages publish under their `@deepseek-ai/dsh-experimental-*` names, including the opt-in Agent Teams composition, Auto review, Cua Driver providers, browser-use backends, cross-realm Inspector, CPython PTC backend, and browser-worker preview libraries. Released products outside this group must not depend on experimental packages. The dsh installation ships the Agent Teams, voice input, Auto review, and Schedule packages as optional bundles switched on from the Web sidebar's Plugins page ([decision](../../.agents/notes/implemented/architecture/2026-09-21-experimental-capabilities-as-optional-bundles.md)); the other packages are libraries or explicit compositions.
## Table of Contents
@@ -33,6 +33,7 @@ The experimental group contains prototype capabilities whose contracts can chang
| [`agent-team`](agent-team/README.md) | Named teammates with durable messages and a shared task board | `ctx.agentTeams` |
| [`client-ui-agent-team`](client-ui-agent-team/README.md) | Team roster, task board, and teammate navigation for Web | — |
| [`auto-review`](auto-review/README.md) | Explicit Web layer for same-model review before each native or PTC inner tool call | — |
| [`schedule-bundle`](schedule-bundle/README.md) | Opt-in Schedule and time-context switch over the shipped Web composition | — |
| [`ptc-runtime-python`](ptc-runtime-python/README.md) | CPython subprocess backend for the PTC execution seam | `ctx.ptcRuntime` |
| [`computer-use-cua-driver-mcp`](computer-use-cua-driver-mcp/README.md) | Use an installed Cua Driver through MCP | `ctx.computerUse` |
| [`computer-use-cua-driver-native`](computer-use-cua-driver-native/README.md) | Embed the Cua Driver native npm runtime | `ctx.computerUse` |
+2 -1
View File
@@ -9,7 +9,7 @@ kind: "package-group"
## 概述
实验组包含约定可能变更且不提供支持承诺的原型能力。所有当前包都以 `@deepseek-ai/dsh-experimental-*` 名称发布,包括显式启用的 Agent Teams 组合、Auto review、Cua Driver 提供方、浏览器操作后端、跨 realm Inspector、CPython PTC 后端与浏览器 worker 预览库。组外已发布产品不得依赖实验性包。dsh 安装将 Agent Teams、语音输入与 Auto review 包作为可选 bundle 一起发布,可从 Web 侧边栏“插件”页启用([决策](../../.agents/notes/implemented/architecture/2026-09-21-experimental-capabilities-as-optional-bundles.zh.md));其余包是库或显式组合。
实验组包含约定可能变更且不提供支持承诺的原型能力。所有当前包都以 `@deepseek-ai/dsh-experimental-*` 名称发布,包括显式启用的 Agent Teams 组合、Auto review、Cua Driver 提供方、浏览器操作后端、跨 realm Inspector、CPython PTC 后端与浏览器 worker 预览库。组外已发布产品不得依赖实验性包。dsh 安装将 Agent Teams、语音输入、Auto review 与定时包作为可选 bundle 一起发布,可从 Web 侧边栏“插件”页启用([决策](../../.agents/notes/implemented/architecture/2026-09-21-experimental-capabilities-as-optional-bundles.zh.md));其余包是库或显式组合。
## 目录
@@ -33,6 +33,7 @@ kind: "package-group"
| [`agent-team`](agent-team/README.zh.md) | 具名 teammate,成员之间持久消息与共享任务板 | `ctx.agentTeams` |
| [`client-ui-agent-team`](client-ui-agent-team/README.zh.md) | Web Team roster、任务板与 teammate 导航 | — |
| [`auto-review`](auto-review/README.zh.md) | 显式 Web 层,在每个原生或 PTC inner 工具调用前使用同一模型审查 | — |
| [`schedule-bundle`](schedule-bundle/README.zh.md) | 在出厂 Web 组合上按需开启定时与时间上下文的开关 | — |
| [`ptc-runtime-python`](ptc-runtime-python/README.zh.md) | PTC 执行 seam 的 CPython 子进程后端 | `ctx.ptcRuntime` |
| [`computer-use-cua-driver-mcp`](computer-use-cua-driver-mcp/README.zh.md) | 通过 MCP 使用已安装的 Cua Driver | `ctx.computerUse` |
| [`computer-use-cua-driver-native`](computer-use-cua-driver-native/README.zh.md) | 嵌入 Cua Driver 原生 npm 运行时 | `ctx.computerUse` |
@@ -0,0 +1,46 @@
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/experimental/schedule-bundle/README.md
/:
en: 7504834d27adc717
zh: 464587026083c661
/deepseek-ai-dsh-experimental-schedule-bundle:
en: d7b8b6126df4e3c4
zh: 546d528efd4edbde
/deepseek-ai-dsh-experimental-schedule-bundle/summary:
en: 832752e963df6177
zh: 30d1d292230a17c1
/deepseek-ai-dsh-experimental-schedule-bundle/table-of-contents:
en: d152484eb41ac6b4
zh: 364c80ee00a374ff
/deepseek-ai-dsh-experimental-schedule-bundle/use-this-package:
en: d84cae0d3f3869c6
zh: c19c74c0671f3127
/deepseek-ai-dsh-experimental-schedule-bundle/understand-the-implementation:
en: b17882af7c7eaf2c
zh: bfc71d0152557af5
/deepseek-ai-dsh-experimental-schedule-bundle/further-exploration:
en: 99a29dddf9805540
zh: 13a6df3ee31abfc1
/deepseek-ai-dsh-experimental-schedule-bundle/model-experience:
en: 215e7ba838619b7b
zh: a311da3843709f90
/deepseek-ai-dsh-experimental-schedule-bundle/model-experience/reminder-tools-and-clock-readings:
en: c7fec3a37d945018
zh: 164346dc63d188dd
/deepseek-ai-dsh-experimental-schedule-bundle/model-experience/reminder-tools-and-clock-readings/what-the-model-sees:
en: fb1906621d02c594
zh: 394dc933ed63b349
/deepseek-ai-dsh-experimental-schedule-bundle/model-experience/reminder-tools-and-clock-readings/token-effect:
en: 7c44bfc062010b7b
zh: 15f431db31ad53eb
/deepseek-ai-dsh-experimental-schedule-bundle/model-experience/reminder-tools-and-clock-readings/kv-cache-effect:
en: 0b01d8c40b422f5b
zh: 57fede4db59a62b8
/deepseek-ai-dsh-experimental-schedule-bundle/known-limitations-and-deferred-work:
en: a4a2674fb3c5a101
zh: cb4c54ba37730708
/deepseek-ai-dsh-experimental-schedule-bundle/known-limitations-and-deferred-work/dev-note:
en: 0225ba087c5266f3
zh: 4e706f1b2b984e63
@@ -0,0 +1,94 @@
---
description: "Enable the shipped Schedule services, reminder catalog, and Automation tasks page from the plugin manager."
kind: "package-bundle"
---
# @deepseek-ai/dsh-experimental-schedule-bundle
English | [中文](README.zh.md)
## Summary
This optional bundle switches on the three Schedule rows that `@deepseek-ai/dsh-web-app` inserts with `disabled: true`: `time-context`, `schedule`, and `ui-schedule`. Its patch appends no row and declares no plugin dependency, so enabling it cannot mount a Host service twice. Shipped profiles leave it switched off.
## Table of Contents
- [Use this package](#use-this-package)
- [Understand the implementation](#understand-the-implementation)
- [Further Exploration](#further-exploration)
- [Model Experience](#model-experience)
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
- [Dev Note](#dev-note)
-----
<a id="use-this-package"></a>
## Use this package
Open Plugins in the Web sidebar and enable Scheduling and time context, marked by a clock icon. A live root Agent then receives `schedule_create`, `schedule_list`, `schedule_update`, and `schedule_delete`, the Session header shows its reminder catalog, the sidebar's Automation tasks entry opens the task-management page and the right Sidebar holds the selected task's detail, and each eligible step appends one clock reading with the current time, the browser zone attached to the open request, and the elapsed time since the preceding model-visible message. Disabling the bundle restores the shipped composition; stored tasks remain on disk.
-----
<a id="understand-the-implementation"></a>
## Understand the implementation
<details>
<summary>Maintainer details — click to expand</summary>
`cordis.patch.yml` carries three id-targeted patches, each setting `disabled: false` on a row the Web bundle already inserts. `OPTIONAL_BUNDLES` in `packages/boot/app-boot/src/profile.ts` names this package and `apps/cli` depends on it, so every installation ships it switched off and the plugin manager offers it in the Official group. Selecting it appends the bundle to the tail of the profile's `dsh.profile.bundles` list; bundle layers apply in list order, so the patches reach the rows only because that list places `@deepseek-ai/dsh-web-app` before this package. A hand-ordered list with this package first leaves the rows disabled while the Plugins page still shows the switch as on. No runtime invariant companion is published because this configuration-only package owns no mutable runtime state.
| File | Role |
|---|---|
| [`cordis.patch.yml`](cordis.patch.yml) | Three `disabled: false` patches over the shipped Web rows |
| [`locale/en.json`](locale/en.json), [`locale/zh.json`](locale/zh.json) | Plugin-manager title and description |
| [`icon.svg`](icon.svg) | Plugin-manager icon |
| [`src/index.ts`](src/index.ts) | Empty module entry; the patch is the runtime content |
</details>
-----
<a id="further-exploration"></a>
## Further Exploration
- [Schedule subsystem](../../../docs/subsystems/schedule.md) — durable tasks, occurrence resolution, and delivery.
- [Schedule service](../../schedule/schedule/README.md) — Host task storage, activation, and the record format.
- [Web bundle](../../bundle/web-app/README.md) — the composition that carries these rows.
-----
<a id="model-experience"></a>
## Model Experience
### Reminder tools and clock readings
#### What the model sees
A live root Agent gains `schedule_create`, `schedule_list`, `schedule_update`, and `schedule_delete`. `time-context` appends one durable user message per eligible step carrying the sampled instant, the browser zone attached to the open request, and the elapsed time since the preceding model-visible message.
#### Token effect
Selecting the bundle adds four Schedule tool schemas to every live root Agent request and one durable clock reading per eligible step; a conversation that never creates a reminder pays both.
#### KV Cache effect
The tool schemas change the request prefix once when the bundle mounts; each appended reading is new visible content after that prefix, so existing entries are not invalidated.
## Known Limitations and Deferred Work
<a id="known-limitations-and-deferred-work"></a>
- The switch targets rows `@deepseek-ai/dsh-web-app` inserts. In a profile without that bundle the three patches match no row: the loader reports one `patch: entry <id> not found` warning per row and mounts nothing from this bundle; such a profile mounts no Plugins page either.
- The bundle's detail page has no per-row switches. The Host reports the three overridden ids under `overrides`, and the Web client renders only the rows a bundle inserts, so opening this card shows "This plugin pack contains no components." The switch for the three rows is on the Official-group list row.
-----
<a id="dev-note"></a>
### Dev Note
<details>
<summary>Maintainer details — click to expand</summary>
None.
</details>
@@ -0,0 +1,94 @@
---
description: "从插件管理页启用出厂的定时服务、提醒目录与自动化任务页面。"
kind: "package-bundle"
---
# @deepseek-ai/dsh-experimental-schedule-bundle
[English](README.md) | 中文
## 概述
此可选 Bundle 打开 `@deepseek-ai/dsh-web-app` 以 `disabled: true` 插入的三个定时条目:`time-context`、`schedule` 与 `ui-schedule`。它的补丁不追加条目,也不声明插件依赖,因此启用它不会重复挂载同一个 Host 服务。随包配置默认禁用。
## 目录
- [使用此包](#use-this-package)
- [理解实现](#understand-the-implementation)
- [进一步探索](#further-exploration)
- [模型体验](#model-experience)
- [已知限制与后续工作](#known-limitations-and-deferred-work)
- [开发备注](#dev-note)
-----
<a id="use-this-package"></a>
## 使用此包
打开 Web 侧栏的插件管理页并启用带时钟图标的“定时与时间上下文”。此后,活跃的根智能体获得 `schedule_create`、`schedule_list`、`schedule_update` 与 `schedule_delete`,会话头部显示提醒目录,侧栏的自动化任务入口打开任务管理页面、右侧栏承载所选任务的详情,每个符合条件的步骤追加一条时钟读数,包含当前时间、打开请求所带的浏览器时区,以及距上一条模型可见消息的经过时间。禁用此 Bundle 会恢复随包组合;已存储的任务保留在磁盘上。
-----
<a id="understand-the-implementation"></a>
## 理解实现
<details>
<summary>维护者信息 — 点击展开</summary>
`cordis.patch.yml` 包含三个按 id 定位的补丁,各自把 Web Bundle 已插入条目的 `disabled` 设为 `false`。`packages/boot/app-boot/src/profile.ts` 的 `OPTIONAL_BUNDLES` 列出此包,`apps/cli` 依赖它,因此每次安装都随包携带且默认禁用,插件管理页在 Official 分组中提供它。选中后会把该 Bundle 追加到 profile 的 `dsh.profile.bundles` 列表末尾;Bundle 层按列表顺序应用,因此这些补丁能命中条目,只是因为该列表把 `@deepseek-ai/dsh-web-app` 排在此包之前。手写顺序把此包排在最前时,这些条目保持禁用,而插件管理页仍把该开关显示为已启用。此纯配置包不拥有可变的运行时状态,因此不发布不变量伴随模块。
| 文件 | 作用 |
|---|---|
| [`cordis.patch.yml`](cordis.patch.yml) | 针对出厂 Web 条目的三个 `disabled: false` 补丁 |
| [`locale/en.json`](locale/en.json)、[`locale/zh.json`](locale/zh.json) | 插件管理页的标题与描述 |
| [`icon.svg`](icon.svg) | 插件管理页图标 |
| [`src/index.ts`](src/index.ts) | 空的模块入口;补丁即运行时内容 |
</details>
-----
<a id="further-exploration"></a>
## 进一步探索
- [定时子系统](../../../docs/subsystems/schedule.zh.md) — 持久任务、发生时刻解析与投递。
- [定时服务](../../schedule/schedule/README.zh.md) — Host 任务存储、激活与记录格式。
- [Web Bundle](../../bundle/web-app/README.zh.md) — 携带这些条目的组合。
-----
<a id="model-experience"></a>
## 模型体验
### 提醒工具与时钟读数
#### 模型看到的内容
活跃的根智能体获得 `schedule_create`、`schedule_list`、`schedule_update` 与 `schedule_delete`。`time-context` 在每个符合条件的步骤追加一条持久用户消息,携带采样时刻、打开请求所带的浏览器时区,以及距上一条模型可见消息的经过时间。
#### Token 影响
启用该 bundle 会给每个活跃根 Agent 请求增加四个定时工具的 schema,并为每个符合条件的步骤增加一条持久时钟读数;即使对话从不创建提醒也会承担这两项开销。
#### KV 缓存影响
四个工具的 schema 在 bundle 挂载时改变一次请求前缀;每条追加的读数都是该前缀之后的新可见内容,因此不会使已有条目失效。
## 已知限制与后续工作
<a id="known-limitations-and-deferred-work"></a>
- 此开关针对 `@deepseek-ai/dsh-web-app` 插入的条目。在没有该 Bundle 的 profile 中,三个补丁匹配不到任何条目:加载器为每个条目报告一条 `patch: entry <id> not found` 警告,且不从该 Bundle 挂载任何东西;这样的 profile 也不挂载插件管理页。
- 该 Bundle 的详情页没有逐条目开关。Host 把被覆盖的三个 id 报告在 `overrides` 下,而 Web 客户端只渲染 Bundle 插入的条目,因此打开这张卡片会显示“这个插件包不包含任何组件。”。控制这三个条目的开关在 Official 分组列表行上。
-----
<a id="dev-note"></a>
### 开发备注
<details>
<summary>维护者信息 — 点击展开</summary>
无。
</details>
@@ -0,0 +1,12 @@
# Experimental Schedule switch over the shipped Web composition. `dsh-web-app`
# inserts the three rows with `disabled: true`; this layer flips them on and
# appends nothing, so enabling it cannot mount a Host service twice.
- id: time-context
disabled: false
- id: schedule
disabled: false
- id: ui-schedule
disabled: false
@@ -0,0 +1,11 @@
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="18" cy="18" r="11.5" fill="url(#a)" />
<path d="M18 11.8V18.6L22.6 22.4" stroke="#FFFFFF" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" />
<circle cx="18" cy="18.6" r="1.5" fill="#FFFFFF" />
<defs>
<linearGradient id="a" x1="18" y1="6.5" x2="18" y2="29.5" gradientUnits="userSpaceOnUse">
<stop stop-color="#7CB7FF" />
<stop offset="1" stop-color="#145AF3" />
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 550 B

@@ -0,0 +1,6 @@
{
"meta": {
"title": "Scheduling and time context",
"description": "Enable durable reminders, the Automation tasks page, and per-step clock context."
}
}
@@ -0,0 +1,6 @@
{
"meta": {
"title": "定时与时间上下文",
"description": "启用持久提醒、自动化任务页面与逐步时钟上下文。"
}
}
@@ -0,0 +1,48 @@
{
"name": "@deepseek-ai/dsh-experimental-schedule-bundle",
"description": "Optional bundle that switches the shipped Schedule, time-context, and reminder-catalog rows on",
"version": "0.1.7-rc.2",
"icon": "./icon.svg",
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
"directory": "packages/experimental/schedule-bundle"
},
"type": "module",
"main": "lib/index.js",
"types": "lib/types/index.d.ts",
"exports": {
".": {
"types": "./lib/types/index.d.ts",
"default": "./lib/index.js"
},
"./src/*": "./src/*",
"./package.json": "./package.json",
"./cordis.patch.yml": "./cordis.patch.yml",
"./locale/*.json": "./locale/*.json"
},
"files": [
"icon.svg",
"locale/*.json",
"lib/index.js",
"cordis.patch.yml",
"lib/types/**/*.d.ts"
],
"license": "MIT",
"peerDependencies": {
"@deepseek-ai/cordis": "workspace:~"
},
"devDependencies": {
"@deepseek-ai/cordis": "workspace:~",
"@deepseek-ai/cordis-plugin-include": "workspace:~",
"js-yaml": "^4.2.0"
},
"dsh": {
"bundle": {
"patch": "./cordis.patch.yml"
}
}
}
@@ -0,0 +1,2 @@
/** Experimental Schedule composition switch; the patched rows live in cordis.patch.yml. */
export {}
@@ -0,0 +1,56 @@
/** The experimental Schedule switch must flip exactly the three rows the Web bundle inserts. */
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { describe, expect, it } from 'vitest'
import * as yaml from 'js-yaml'
import { entryListSchema } from '@deepseek-ai/cordis-plugin-include'
const root = fileURLToPath(new URL('..', import.meta.url))
interface Manifest {
name?: string
icon?: string
private?: boolean
publishConfig?: { access?: string }
exports?: Record<string, unknown>
dependencies?: Record<string, string>
dsh?: { bundle?: { patch?: string } }
}
interface Patch {
id?: string
name?: string
disabled?: boolean
insert?: unknown[]
}
describe('experimental Schedule bundle', () => {
const manifest = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8')) as Manifest
it('publishes as an experimental bundle with plugin-manager display metadata', () => {
expect(manifest.name).toBe('@deepseek-ai/dsh-experimental-schedule-bundle')
expect(manifest.private).toBeUndefined()
expect(manifest.publishConfig?.access).toBe('public')
expect(manifest.icon).toBe('./icon.svg')
expect(manifest.dsh?.bundle?.patch).toBe('./cordis.patch.yml')
expect(manifest.exports?.['./locale/*.json']).toBe('./locale/*.json')
expect(manifest.exports?.['./cordis.patch.yml']).toBe('./cordis.patch.yml')
// The patch only overrides rows another layer inserts, so it depends on no plugin package.
expect(manifest.dependencies).toBeUndefined()
})
it('flips the three shipped rows on and appends none', () => {
const parsed = yaml.load(readFileSync(resolve(root, './cordis.patch.yml'), 'utf8'), { schema: entryListSchema })
expect(parsed).toEqual([
{ id: 'time-context', disabled: false },
{ id: 'schedule', disabled: false },
{ id: 'ui-schedule', disabled: false },
])
for (const patch of parsed as Patch[]) {
expect(patch.insert).toBeUndefined()
expect(patch.name).toBeUndefined()
}
})
})
@@ -0,0 +1,15 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "lib/types"
},
"include": [
"src"
],
"references": [
{
"path": "../../../vendor/cordis"
}
]
}
@@ -0,0 +1,3 @@
import { defineConfig } from 'tsdown'
export default defineConfig({ entry: ['lib/types/index.js'], outDir: 'lib', format: ['esm'], platform: 'node', target: 'es2024', fixedExtension: false, dts: false, clean: false })
+2 -2
View File
@@ -15,8 +15,8 @@
en: 23386452a66b2fbd
zh: 4a8d91b2f313fead
/deepseek-ai-dsh-schedule/use-this-package:
en: 401d9737620b86d9
zh: 0ebbc36e2fe157f3
en: db292f4e03cef41b
zh: 064cb553698d548c
/deepseek-ai-dsh-schedule/understand-the-implementation:
en: 676b7c508f37a1b7
zh: c5e8520b3350f0b0
+1 -1
View File
@@ -23,7 +23,7 @@ Schedule delivers one-shot, fixed-rate, daily, weekly, and cron wall-clock remin
<a id="use-this-package"></a>
## Use this package
The shipped Web bundle mounts the service alongside storage-domain and the Session controller. Its `Config` states `deliveryHistoryDays` (default 30) and `deliveryHistoryRecords` (default 200). Storage backend routing belongs to storage-domain; Session model and preset restoration belong to the Session controller. Schedule cannot be mounted alone in a headless or SDK-only composition: delivery requires the Host Web Session controller and a Session persistence backend, because a delivery commits only after the Session acknowledges `session/flush`.
The shipped Web composition carries the `schedule` row disabled; enable the optional experimental bundle `@deepseek-ai/dsh-experimental-schedule-bundle` from the Plugins page (Official group), or list it in a profile's `dsh.profile.bundles`, to mount the service alongside storage-domain and the Session controller. Its `Config` states `deliveryHistoryDays` (default 30) and `deliveryHistoryRecords` (default 200). Storage backend routing belongs to storage-domain; Session model and preset restoration belong to the Session controller. Schedule cannot be mounted alone in a headless or SDK-only composition: delivery requires the Host Web Session controller and a Session persistence backend, because a delivery commits only after the Session acknowledges `session/flush`.
The Agent receives `schedule_create`, `schedule_list`, `schedule_delete`, and `schedule_update`. Update replaces the name, instruction, or timing of one reminder in place and keeps its id and saved records; it is not offered for the relative `after` delay. Creation requires a non-empty prompt, a title, and exactly one of six selectors:
+1 -1
View File
@@ -23,7 +23,7 @@ Schedule 将一次性、固定周期、按每日、按每周以及 cron 本地
<a id="use-this-package"></a>
## 使用此包
发布的 Web bundle 将此服务与 storage-domain、Session controller 一起挂载。其 `Config` 声明 `deliveryHistoryDays`(默认 30)与 `deliveryHistoryRecords`(默认 200)。存储后端路由由 storage-domain 管理;会话模型与 preset 恢复由 Session controller 管理。Schedule 无法在 headless 或仅 SDK 的组合中单独挂载:投递需要 Host 的 Web Session controller 和 Session 持久化后端,因为只有在 Session 确认 `session/flush` 之后一次投递才会提交。
随发行版交付的 Web 组合把 `schedule` 行保持禁用;在插件管理页(Official 分组)启用可选实验性 bundle `@deepseek-ai/dsh-experimental-schedule-bundle`,或把它列进 profile 的 `dsh.profile.bundles`,即可将此服务与 storage-domain、Session controller 一起挂载。其 `Config` 声明 `deliveryHistoryDays`(默认 30)与 `deliveryHistoryRecords`(默认 200)。存储后端路由由 storage-domain 管理;会话模型与 preset 恢复由 Session controller 管理。Schedule 无法在 headless 或仅 SDK 的组合中单独挂载:投递需要 Host 的 Web Session controller 和 Session 持久化后端,因为只有在 Session 确认 `session/flush` 之后一次投递才会提交。
Agent 获得 `schedule_create`、`schedule_list`、`schedule_delete` 和 `schedule_update`。更新原地替换一条提醒的名称、指令或时间,保留其 id 与已保存记录;相对的 `after` 延迟不支持更新。创建时需要非空提示文本、标题,且必须只提供以下六个选择器之一:
+15
View File
@@ -247,6 +247,9 @@ importers:
'@deepseek-ai/dsh-experimental-auto-review':
specifier: workspace:*
version: link:../../packages/experimental/auto-review
'@deepseek-ai/dsh-experimental-schedule-bundle':
specifier: workspace:*
version: link:../../packages/experimental/schedule-bundle
'@deepseek-ai/dsh-experimental-voice-input-bundle':
specifier: workspace:*
version: link:../../packages/experimental/voice-input-bundle
@@ -7769,6 +7772,18 @@ importers:
specifier: workspace:*
version: link:../../util/values
packages/experimental/schedule-bundle:
devDependencies:
'@deepseek-ai/cordis':
specifier: workspace:~
version: link:../../../vendor/cordis
'@deepseek-ai/cordis-plugin-include':
specifier: workspace:~
version: link:../../../vendor/include
js-yaml:
specifier: ^4.2.0
version: 4.3.1
packages/experimental/speech-to-text:
dependencies:
'@deepseek-ai/dsh-brand':
+26 -1
View File
@@ -41,13 +41,38 @@ describe('optional bundles', () => {
it.each(OPTIONAL_BUNDLES)('%s composes over the Web profile without a skipped patch', (name) => {
const { patches } = bundle(name)
const warnings: string[] = []
const ids = new Set(composeEntries([...shipped, patches], message => warnings.push(message)).map(entry => entry.id))
const composed = composeEntries([...shipped, patches], message => warnings.push(message))
const ids = new Set(composed.map(entry => entry.id))
expect(warnings).toEqual([])
// Inserted rows carry stable ids at the profile root, so a later profile patch can configure or disable them.
for (const row of patches.flatMap(patch => patch.insert ?? [])) {
expect(typeof row.id).toBe('string')
expect(ids.has(row.id)).toBe(true)
}
// One top-level row per id: a duplicate declaration leaves the Loader with the last one, silently
// replacing the layer that declared the id first.
const topLevelIds = composed.flatMap(entry => typeof entry.id === 'string' ? [entry.id] : [])
expect(topLevelIds).toHaveLength(new Set(topLevelIds).size)
// An id-targeted patch reaches a row another layer inserted: the id resolves to exactly one top-level
// row, and the override keeps the package the shipped layer declared on it.
const shippedComposed = composeEntries([...shipped])
for (const patch of patches) {
if (patch.insert !== undefined || typeof patch.id !== 'string') continue
const matches = composed.filter(entry => entry.id === patch.id)
expect(matches).toHaveLength(1)
expect(matches[0]?.name).toBe(shippedComposed.find(entry => entry.id === patch.id)?.name)
}
})
it('composes the Schedule bundle over the three shipped Web rows', () => {
const { patches } = bundle('@deepseek-ai/dsh-experimental-schedule-bundle')
const composed = composeEntries([...shipped, patches])
expect(composed.filter(entry => entry.id === 'time-context' || entry.id === 'schedule' || entry.id === 'ui-schedule'))
.toMatchObject([
{ id: 'time-context', name: '@deepseek-ai/dsh-time-context', disabled: false },
{ id: 'schedule', name: '@deepseek-ai/dsh-schedule', disabled: false },
{ id: 'ui-schedule', name: '@deepseek-ai/dsh-client-ui-schedule', disabled: false },
])
})
it.each(OPTIONAL_BUNDLES)('%s resolves a title, description, and icon in both shipped languages', (name) => {
+1
View File
@@ -62,6 +62,7 @@ describe('release families', () => {
'@deepseek-ai/dsh-experimental-computer-use-cua-driver-native',
'@deepseek-ai/dsh-experimental-inspector',
'@deepseek-ai/dsh-experimental-ptc-runtime-python',
'@deepseek-ai/dsh-experimental-schedule-bundle',
'@deepseek-ai/dsh-experimental-speech-to-text-sensevoice',
'@deepseek-ai/dsh-experimental-speech-to-text',
'@deepseek-ai/dsh-experimental-tool-agent-team',
+1
View File
@@ -319,6 +319,7 @@
"@deepseek-ai/dsh-experimental-inspector": ["./packages/experimental/inspector/src"],
"@deepseek-ai/dsh-experimental-inspector/client": ["./packages/experimental/inspector/src/client/index.ts"],
"@deepseek-ai/dsh-experimental-ptc-runtime-python": ["./packages/experimental/ptc-runtime-python/src"],
"@deepseek-ai/dsh-experimental-schedule-bundle": ["./packages/experimental/schedule-bundle/src/index.ts"],
"@deepseek-ai/dsh-util-crypto": ["./packages/util/crypto/src"],
"@deepseek-ai/dsh-util-values": ["./packages/util/values/src"],
"@deepseek-ai/dsh-util-code-language": ["./packages/util/code-language/src"],
+1
View File
@@ -357,6 +357,7 @@
{ "path": "./packages/terminal/tool-terminal" },
{ "path": "./packages/ptc-runtime/ptc-runtime" },
{ "path": "./packages/experimental/ptc-runtime-python" },
{ "path": "./packages/experimental/schedule-bundle" },
{ "path": "./packages/ptc-runtime/ptc-runtime-node" },
{ "path": "./packages/llm/llm-deepseek" },
{ "path": "./packages/llm/llm-deepseek-api-key" },