@deepseek-ai/dsh-client-ui-schedule 0.2.1-rc.5 → 0.2.2-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.i18n.yaml +19 -19
  2. package/README.md +28 -36
  3. package/README.zh.md +26 -34
  4. package/lib/client.js +15570 -3670
  5. package/lib/types/client/ClockPicker.d.ts +3 -3
  6. package/lib/types/client/DeleteToast.d.ts +26 -11
  7. package/lib/types/client/DeliveryHistory.d.ts +12 -6
  8. package/lib/types/client/NewSessionLimit.d.ts +12 -0
  9. package/lib/types/client/RuleSelectRow.d.ts +22 -0
  10. package/lib/types/client/ScheduleCatalogAction.d.ts +9 -4
  11. package/lib/types/client/ScheduleEmptyIllustration.d.ts +12 -0
  12. package/lib/types/client/ScheduleTaskTab.d.ts +2 -1
  13. package/lib/types/client/TaskDetail.d.ts +71 -96
  14. package/lib/types/client/TaskEditorFields.d.ts +54 -0
  15. package/lib/types/client/TaskManagerPage.d.ts +18 -4
  16. package/lib/types/client/TaskMenu.d.ts +3 -2
  17. package/lib/types/client/TaskRuleControls.d.ts +50 -0
  18. package/lib/types/client/catalog-source.d.ts +5 -2
  19. package/lib/types/client/clear-ended.d.ts +33 -0
  20. package/lib/types/client/editor-store.d.ts +32 -0
  21. package/lib/types/client/editor-timing.d.ts +47 -0
  22. package/lib/types/client/frequency-locales.d.ts +386 -2
  23. package/lib/types/client/index.d.ts +4 -4
  24. package/lib/types/client/locales.d.ts +490 -10
  25. package/lib/types/client/relative-clock.d.ts +8 -2
  26. package/lib/types/client/schedule-format.d.ts +16 -5
  27. package/lib/types/client/session-link.d.ts +1 -22
  28. package/lib/types/client/session-schedule-state.d.ts +13 -29
  29. package/lib/types/client/task-cron.d.ts +0 -65
  30. package/lib/types/client/task-manager-locales.d.ts +1386 -51
  31. package/lib/types/client/task-record.d.ts +30 -0
  32. package/locale/de.json +6 -0
  33. package/locale/es.json +6 -0
  34. package/locale/fr.json +6 -0
  35. package/locale/ja.json +6 -0
  36. package/locale/pt.json +6 -0
  37. package/locale/ru.json +6 -0
  38. package/package.json +25 -22
  39. package/lib/types/client/task-timing.d.ts +0 -96
package/README.i18n.yaml CHANGED
@@ -3,38 +3,38 @@
3
3
  # After editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/client/ui-schedule/README.md
5
5
  /:
6
- en: 265778d19fe0dd76
7
- zh: 78b0a191a4bd4e4e
6
+ en: b4f472194d36189e
7
+ zh: 9dc81770c98be03b
8
8
  /deepseek-ai-dsh-client-ui-schedule:
9
9
  en: 862120984d5392eb
10
10
  zh: eb3e5d5a802da592
11
11
  /deepseek-ai-dsh-client-ui-schedule/summary:
12
- en: 8dfc371c14bb4415
13
- zh: 9b3545c1a7468a7a
12
+ en: 9a690c99b0562de5
13
+ zh: 77a7464316afb3ed
14
14
  /deepseek-ai-dsh-client-ui-schedule/table-of-contents:
15
15
  en: d152484eb41ac6b4
16
16
  zh: 405b30feaf48c087
17
17
  /deepseek-ai-dsh-client-ui-schedule/use-this-package:
18
- en: edba0e1573f3ce42
19
- zh: 77875b469d94cc62
18
+ en: 99626c29eb801b6f
19
+ zh: 9693d278f467ad90
20
20
  /deepseek-ai-dsh-client-ui-schedule/use-this-package/time-zone-data-source:
21
- en: 6bd6882dbbbefcb0
22
- zh: 03aa15f1a65d13dc
21
+ en: 4005b800e930f581
22
+ zh: ccb9318dad7f7e8f
23
23
  /deepseek-ai-dsh-client-ui-schedule/understand-the-implementation:
24
- en: 959145f9a08c3913
25
- zh: caae642a82d2acd3
24
+ en: 72598a09be42251d
25
+ zh: 4140b2eec82c7f1f
26
26
  /deepseek-ai-dsh-client-ui-schedule/further-exploration:
27
- en: 06e265120b05dbf5
28
- zh: 08ab1ef979b8ea40
27
+ en: 2fd968202916b197
28
+ zh: f1ab66194846562b
29
29
  /deepseek-ai-dsh-client-ui-schedule/model-experience:
30
- en: a8838aba5fd29fd8
31
- zh: b9f67d82c81dd030
30
+ en: 6f528a72fe45af1b
31
+ zh: 8272529f6e324315
32
32
  /deepseek-ai-dsh-client-ui-schedule/model-experience/kv-cache-effect:
33
- en: 4b81350950285d47
34
- zh: 6dc3d5cf7ca8a622
33
+ en: 52239e5688dfebe1
34
+ zh: 37343f5dbde010e8
35
35
  /deepseek-ai-dsh-client-ui-schedule/known-limitations-and-deferred-work:
36
- en: ce8cd6e03f4763ae
37
- zh: 65ad26aad74d83ca
36
+ en: 6ee939ce57fcea66
37
+ zh: 0e99fadf1fb7ac4d
38
38
  /deepseek-ai-dsh-client-ui-schedule/known-limitations-and-deferred-work/dev-note:
39
- en: e67f633dc6fe7773
39
+ en: 18a59ce211e19bbd
40
40
  zh: a4b126f9a4eaca6f
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Web task management across Sessions and a current-Session reminder catalog."
2
+ description: "Automation task management and Session reminder entries in the existing Web UI."
3
3
  kind: "package-reference"
4
4
  ---
5
5
 
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
9
9
 
10
10
  ## Summary
11
11
 
12
- Manage active and inactive tasks from the Automation tasks page and the right Sidebar task tab: search, filter, edit name, instruction, and run time, browse records, delete, or open the original conversation. Every surface names a task by its title. An open Session's header shows an icon-only reminder clock while active reminders exist and opens that task's detail; a `schedule_create` call renders a transcript card; an idle, unarchived Session row with active tasks shows a clock mark and hover list.
12
+ The Automation tasks page and right Sidebar task tab use the same editor for task rules, saved delivery records, deletion, and conversation navigation. Manual creation and target selection use the Host Schedule service; conversation cards, header clocks, and Session row marks retain their existing locations.
13
13
 
14
14
  ## Table of Contents
15
15
 
@@ -25,83 +25,75 @@ Manage active and inactive tasks from the Automation tasks page and the right Si
25
25
  <a id="use-this-package"></a>
26
26
  ## Use this package
27
27
 
28
- The shipped Web composition mounts `ui-schedule` with the Host Schedule service. The clock context that supplies the model's current time is preset-owned: `standard`, `cordis`, and `ptc` declare it, and `minimal` declares neither it nor the reminder tools. 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 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. When the strip cannot fit the tab list beside the labelled entry, the entry becomes an icon button with the same button style as More task actions, with the Session chat icon and a Linked session tooltip that also shows while the entry is disabled; the entry keeps focus when it switches layouts; the tab list scrolls without a visible scrollbar. 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.
28
+ Below 768px, the task list uses 20px horizontal insets, matching the Plugins page.
29
29
 
30
- The page header keeps the title at its natural width and moves New to another line when the two no longer fit together. The action label stays on one line.
30
+ The shipped Web composition mounts `ui-schedule` with Host Schedule. The Automation tasks sidebar entry opens the task list without selecting or activating a Session. New and the adjacent menu's Create in a session action both open a new conversation with a short task-creation prompt in the current UI language, ready for the user to complete and send. When a blank conversation is reused, the prompt is appended on a new line, preserving its text, inline references, and attachments. The same menu offers Create manually. Manual creation opens the same editor as an existing task, validates required fields, and saves a task without starting an Agent or sending the instruction. A failed request leaves the form and its values visible. The empty state shows a decorative document-and-clock illustration whose colors follow the theme.
31
31
 
32
- 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.
32
+ Enabled, Paused, Ended, and All filters combine with text search over the title, prompt, and linked Session id; the page starts on Enabled. The search-row menu clears all ended tasks after confirmation, preserving active and paused tasks. Selecting a task opens its editable Rules / Records page. Save is enabled only for valid, meaningful changes and sends only changed fields with `expectedUpdatedAt`, or `null` when no stored revision exists. The fields stay editable after saving. Unsaved drafts survive navigation between tasks and away from the page. A conflict retains the whole draft and disables Save. Review with my edits reapplies the changed field groups to the latest values for review before saving; Discard replaces the draft with the latest stored values. For a new task, Discard closes the editor. Late responses cannot change another task's detail. Coarse-pointer search, instruction, and timing fields use 16px text to prevent focus zoom on iOS Safari.
33
33
 
34
- Rules shows the rule in a Run time card whose rows edit a local draft: Repeat is a menu of Weekly, Monday to Friday, Every day, Every N hours, Every N minutes, Every N seconds, Once, and Custom (cron), a weekly rule adds a Weekday row, a fixed-rate choice edits only the interval quantity in the unit it names, a one-shot rule edits separate Date and Time rows, and Custom (cron) edits one Cron expression row holding a five-field expression, interpreted in the selected time zone. The card parses that expression in the browser and, under the row, shows a localized sentence describing it; an expression the Host would reject shows the localized validation message in place of that sentence and blocks Save. A stored weekly rule whose weekday set is exactly Monday through Friday selects the Monday to Friday choice. The Date row is a read-only trigger showing the staged date as `YYYY/MM/DD` and opening a month calendar with localized weekday headings, month navigation, and a marked today; the draft and the submitted text keep the ISO form; the Time row is a read-only trigger showing one 24-hour clock and opening three scrolling columns of hours, minutes, and seconds with the staged value marked and scrolled into view. A calendar or clock pick stages the draft under the same staged save as every other row, arrow keys walk the open column or grid, Enter stages the marked value, Escape closes the panel and returns focus to its row, and a disabled row cannot open one. Clock rows show whole seconds, an untouched row keeps a stored millisecond value for its submit, and editing a time submits whole-second precision. Time zone is a searchable, height-bounded menu. An unlabeled top block keeps the five most recently selected exact zones in browser-local storage; first use seeds the actual system zone and UTC rather than inferring a location from UI language. The system zone is marked, and the remaining inventory is ordered by current UTC offset and canonical IANA id. Each visible label puts `UTC±HH:MM` before the localized zone name; canonical ids stay internal but remain searchable. Zones that ICU renders with the same offset and localized name share one visible row; every grouped id remains searchable, and an already stored id remains selected instead of being rewritten. The inventory comes from `Intl.supportedValuesOf('timeZone')`, and names come from `Intl.DateTimeFormat(..., { timeZoneName: 'longGeneric' })`: both are browser ICU/CLDR data, not a scraped or product-maintained translation table. There is therefore no crawler or generated zone-name resource to refresh. A third-party locale supplies its ordinary `time.locale` value and automatically receives the corresponding ICU names; only the selector's surrounding UI copy needs translation. When the runtime cannot enumerate zones, a short identifier fallback is offered, and a stored zone outside the offered set is kept. Daily, Weekly, and Cron keep their stored rule and IANA zone, and each frequency line names the zone only when it differs from the host's system zone. A one-shot After/At seeds the date and time from the record's stored zone, or this device's zone when the record stores none, so the seeded clock names the stored instant; changing that zone keeps the entered clock values and changes the instant. A kind the card seeds on selection uses the committed occurrence's clock and the choice's zone, which is the record's stored zone or this device's zone, a seeded weekly rule starts from that occurrence's weekday in that zone, and a seeded cron rule states that occurrence's clock as a daily expression. Every accepts at least 60 whole seconds, independent of time zones. One Save submits the complete expected record with the staged change and preserves the id, original Session, latest receipt, and saved history; [Schedule](../../schedule/schedule/README.md#use-this-package) defines future-target selection, reanchoring, and unchanged-rule no-ops.
34
+ The destination menu offers a new conversation that the first delivery creates and later deliveries reuse, or a new conversation at every delivery. Manual creation defaults to reuse. A task already bound to a Session shows Current linked conversation as its destination, and editing it preserves that destination unless the user explicitly chooses a new one. The Linked workspace selector lists the framework Workspace catalog, shows each Workspace's directory under its name, and labels the first-use Workspace with its localized default name. A new destination starts in that Workspace, else in the first listed one. A stored task without a directory shows Ungrouped, because the Sessions it creates join no Workspace. For a reusable destination, the bottom conversation entry shows Pending creation until the first Session exists. A per-run destination instead shows Latest run conversation after its first delivery and hides the entry before that delivery; earlier conversations remain accessible from delivery records. Available links recheck membership and archive state before opening; missing or archived Sessions remain disabled.
35
35
 
36
- The rows are disabled while a save is in flight, while the catalog is loading, during a deletion, and for an inactive task. A save bar appears only while the local draft differs from the stored task: it shows Unsaved changes with Cancel and Save changes, and Save changes becomes Saving… while the save is in flight. Cancel restores the stored values. A catalog refresh becomes the shown values only while the draft has no unsaved edit, so an unsaved draft survives an authoritative refresh. A failed save keeps the draft and shows a localized message; after a conflict, retry against the refreshed record. If the task disappears from the catalog, Delete is disabled until the task returns. A successful update refreshes the authoritative catalog. A rejected or unconfirmed update is distinct from a catalog-read failure: Retry reloads the catalog without presenting the update as failed. If the update itself cannot be confirmed, check the task before retrying. Late responses after switching tasks or closing details do not replace the current view, and no failure rolls back a Host write already begun.
36
+ The repeat editor offers once, minute, hour, day, week, month, and custom rules. Date and clock controls reuse existing pickers. Guided presets produce RRULE; minute and hour intervals start from the current minute in the selected zone. The Custom choice and Customize input do not name either syntax; the input accepts a two-line RRULE or a five-field Cron expression with an explicit zone. RRULE retains the zone in `DTSTART`; Cron retains its expression and selected zone as Cron timing. Complex RRULE values remain verbatim. The shared time parser checks new or changed Custom text before enabling Save; invalid or empty input keeps the draft and explains which field to change. Invalid Custom text offers manual correction, another repeat option, or correction by the Agent. The Host performs the final validation on save. Stored After and At tasks show date and clock fields immediately; a repeated local time uses UTC when needed to retain the exact instant. Every, Daily, and Weekly tasks show the matching controls when their interval or wall-clock precision is representable. Other stored timings remain in Custom and keep their typed timing until replaced. Viewing a task or editing other fields preserves its timing and committed occurrence.
37
37
 
38
- Opening Records lazily requests the newest 20 saved records. Load older records adds another page in newest-first append order, independent of wall-clock rollback. The tab strip is the whole header of that view: the editable name and next-run line belong to Rules. Each Saved delivery record leads with a clock glyph and its occurrence time as the locale's month name and clock field pair in the task's zone, or the browser's zone for a one-shot record, and shows the actual saved prompt when present. A prompt longer than two lines shows its first two lines and an Expand toggle, which Collapse reverses; a collapsed prompt rechecks its length when the panel width changes. A legacy receipt without a prompt never substitutes the current instruction.
38
+ Pause and resume update lifecycle state. Unsaved changes hold pause, resume, Run now, and Delete until you save or discard them. The detail menu offers Run now and Delete. It offers no queued-message cancellation: one inbox message may contain deliveries from several tasks. While a delivery to a reused conversation is queued or running, the detail disables its fields, Save, pause and resume, Run now, and Delete, and states that the task is queued or running and is managed in its conversation, which the bottom conversation entry opens. The minimum delivery interval disables another immediate run until the interval ends, while pause and deletion remain available once execution is idle. When the interval is the only cause, the Run now row stays focusable, and its tooltip states that the minimum run interval has not passed and when Run now becomes available. An archived linked conversation of a task already bound to a Session also disables Run now, because the Host refuses that delivery. A run that the Host refuses with `schedule_execution_pending` shows a status notice instead of an error. Deletion requires confirmation, removes the task and its saved records, retains Sessions and already-delivered messages, and reports the result through the existing app-wide toast. The confirmation focuses Cancel first; when it closes, focus returns to the detail menu button. The detail keeps the task until the Host answers. An applied deletion closes the detail or its task tab; a failed deletion keeps the task open for another attempt.
39
39
 
40
- After the last saved page loads, a nonempty history with confirmed pruning shows a borderless notice at the bottom left of the detail panel. Its info button expands or collapses the current Host retention rules. Empty history, legacy unavailability without confirmed pruning, incomplete pagination, and failed reads show no cleanup notice.
40
+ The list, detail, header, and Session hover show the later of the scheduled occurrence and the Host delivery floor as the next run. Creation and editing show one short minimum-interval hint for per-run conversation targets, read from `schedule.deliveryLimits`; a failed read offers Retry. Scheduled and immediate runs share this limit.
41
41
 
42
- A successful empty history page is distinct from loading, query failure, a missing task, or an invalid cursor. Failed requests retain previously loaded records with a warning and Retry delivery records; an invalid cursor offers Refresh delivery records to reload the newest page. Changing the latest `messageId` refreshes the newest page without switching tabs. Responses superseded by a refresh or received after changing tasks, leaving Records, or closing details do not replace the current view.
42
+ Records lazily requests 20 saved deliveries, supports newest-first pagination, retains loaded records after failure, and ignores superseded or unmounted requests. Each record shows its occurrence and saved prompt, with Expand / Collapse for long prompts; legacy records without prompt text never substitute the current instruction. A receipt's actual destination has a conversation link when the Session is available. Confirmed pruning is stated only after the final saved page and offers the current retention explanation. These records acknowledge inbox delivery, not model execution success.
43
43
 
44
- The Automation tasks page requires confirmation before deleting a task. Deletion is hard: the Host removes the stored task row together with its saved delivery records, so the task stops future delivery, leaves `list` and `catalog`, and its delivery history is no longer readable. Deletion leaves the original Session and queued messages intact, and the list keeps the row visible only until an authoritative query confirms the removal. Every deletion path — the Tasks page detail, the Session task tab, and the header popover — reports its settled outcome into one store that the app-wide `shell.overlay` notice renders, so the outcome outlives the panel or tab that asked for it: the notice reads `Task deleted.` once the Host removed the row with its saved delivery records, and `Could not delete the task.` after a failure, which leaves the rule in place to retry. Confirming a deletion closes the detail or the tab it was confirmed from, and each notice is keyed by its own sequence so a later one restarts the banner instead of being folded into an earlier one. A query failure keeps the last known records and shows a separate Retry action; it never appears as an empty successful result. A one-shot remains stored as inactive after durable inbox delivery. Its details and original Session id remain available through the All or Inactive filter until explicit deletion. The latest delivery shows its occurrence time; the message id and delivery acknowledgment time are not shown. Neither inactive status nor that receipt means model execution completed.
45
-
46
- An open Session renders an icon-only clock button among its header's right-aligned utilities, immediately left of the overflow menu, only once it has something to open: the first read mounts nothing, a read that returns no active reminder leaves the header without the button, a refresh keeps the last known reminders visible, and a failed read keeps the button with its retry. That rule prevents the clock from appearing and disappearing around the first answer. Its accessible name states the reminder count when the read is ready and the generic reminder label otherwise. With exactly one active reminder, the button opens that task's detail in the right Sidebar directly. With any other count it opens a popover that lists overdue reminders first, then future reminders by target time, with stored title, frequency, browser-local target time, relative time, and a Delete button; the title is a button that opens that task's detail in the right Sidebar. The task tab names the shown task's stored title on its chip and carries the same rule, delivery records, name, instruction, and run-time editing, confirmed deletion, and original-Session link as the Automation tasks page; it never activates a Session. Daily frequency text retains the saved local time and zone, and every next-target instant is shown as a device-zone clock with its relative duration in parentheses; the rule's own zone appears only in that frequency text. Escape closes the popover and returns focus to the button; an outside pointer press dismisses it. Deleting the final reminder removes the button, and an already open popover stays expandable until then.
47
-
48
- The popover is body-portaled and targets 336px, sharing the trigger left edge when space permits and shifting left to retain a 16px viewport margin when the trigger is near the right edge; its width never exceeds the viewport width minus 32px, and it scrolls vertically when the list overflows. It exposes no task id, raw UTC value, or delivery details; each row carries only its detail opener and its Delete action.
49
-
50
- Calling `schedule_create` renders the created task in the transcript as a card with a clock icon, its stored title, its frequency, and an Open button that opens that task's right-Sidebar tab. The card first narrows the task out of the call's persisted result JSON and reads its `title` from that result; once a catalog read that succeeded after the card appeared resolves that task, the card follows the catalog for the current name and frequency, and shows its deleted state instead of a frequency when that read lacks the record. A result recorded before the stored field existed falls back to the instruction's first line. A running call, a failed creation, or a result carrying no complete task keeps the row, shows the raw result text when the result is a single non-empty text block, and offers no Open action. The card adds no Host field and no Session-log format change, so Sessions recorded before the card existed render it too.
51
-
52
- The Sidebar's Session rows mark scheduled Sessions: while a row is idle, unarchived, and its Session has at least one active task, the row shows a clock mark; an archived row keeps that cell blank, with its live status on the hover card only. A long hover on a Session with active tasks adds an automation section inside that row's existing hover card, whether or not the row is idle, listing up to two tasks with their icon, stored title, frequency, and next-run text, and an omission line when further tasks are hidden. A row with a higher-priority state — a pending interaction, live activity, or an unviewed completion — keeps its own dot and renders no mark, so the two never appear together. The mark and the hover section read the shared active and inactive Host task catalog and select their own Session's active tasks from it, so any number of visible rows costs one read; they never activate, retain, or unarchive a Session, and never read a Session log.
53
-
54
- -----
44
+ An open conversation's header clock remains hidden before the first successful read or while no active related tasks exist. One task opens its right Sidebar tab; several open the existing popover. Idle, unarchived Session rows with active related tasks retain their clock mark and hover list. `schedule_create` continues to render a Turn-level card with a task title, repeat description, and Open action. Persisted legacy and current tool results both render; an authoritative read newer than the card resolves later edits or deletion.
55
45
 
56
46
  ### Time-zone data source
57
47
 
58
- Time-zone inventory and localization are offline. `Intl` reads ICU/CLDR tables embedded in the browser runtime and never fetches or downloads zone data while DSH runs. There is no crawler to refresh; a third-party locale supplies `time.locale` and translates only the selector's own UI copy.
48
+ Time-zone enumeration and localized names use the browser's embedded ICU/CLDR data through `Intl`. There is no runtime download. The editor retains a stored alias even when enumeration omits it, and uses the system zone plus UTC when enumeration is unavailable.
59
49
 
60
50
  <a id="understand-the-implementation"></a>
61
51
  ## Understand the implementation
62
52
 
53
+ Task menus use the [standard menu geometry](../../../docs/ui-radius.md#nested-hover), including keyboard-highlighted rows. Portaled task menus and date/time pickers use `useAnchoredPosition` to follow their triggers during browser zoom, scrolling, and resizing, while preserving viewport margins and the desktop frame clearance. Task-menu labels and clock values ellipsize when the visual viewport is too narrow. Clock columns shrink within the panel and scroll vertically within its available height; task menus scroll vertically to reach every choice. The Session-header popover follows the same viewport constraints and stays hidden until its first position resolves.
54
+
63
55
  <details>
64
- <summary>Implementation internals — click to expand</summary>
56
+ <summary>Implementation details — click to expand</summary>
65
57
 
66
- The browser entry registers the `schedules` main panel and matching sidebar entry, the `schedule-catalog` entry among the Session header's right-aligned utilities at `order: -5` immediately left of the overflow menu, the `schedule_create` transcript card at the turn level through `ctx.uiConversation.events` and ui-chat's list seat `conversation.chat.turnTail`, so it renders after the turn's closing assistant text and stays visible when the tool-call group is collapsed, the root-scoped Session-row seats `sidebar.session.row.leading` and `sidebar.session.row.hover`, and the right-Sidebar page type `@deepseek-ai/dsh-client-ui-schedule/task` under the kind `scheduleTask`. The type registers in two stages: its definition into `ctx.sidebarRightTabs`, then its body and chip into the keyed `sidebar.right.pane.tab` and `sidebar.right.pane.tab.title` seats under the definition's id. Opening a task from the Session entry calls `ctx.sidebarRight.openTab` with that entry's Session id and the chosen task id, so the detail appears in the Sidebar for the Session the entry belongs to; the Automation tasks page keeps its own list and shares the same detail component. The global page, the tab, the row mark, and the row hover section read active and inactive tasks from one `schedule.catalog` source; the header entry keeps its own per-Session `schedule.list` read, which returns only that Session's active tasks. Every surface uses the same observable query lifecycle and refreshes after `schedule/changed` or connection resets. The transcript card narrows the created task from the call's persisted result JSON rather than a Host-added field; the call's own Tool-group cell stays with ui-tool's generic keyed tool view, and the card appears only for a call that produced a complete task. The reconciliation is causal, never clock-based: a catalog snapshot carries `readRequest` (the ordinal of the newest requested read) and `readSettled` (the ordinal of the read that produced its records); the Turn tail anchors `readRequest` when it mounts and requests one read, uses its retained records only once `readSettled` exceeds that anchor, and the source coalesces the requests of one commit into a single `list()`, sharing that read only with callers that have not already observed it. Comparing the browser's clock with the Host's would not establish that order. The shared delete callback and injected `onUpdateTiming` retain the selected record's original Session binding rather than using the currently open conversation. The detail holds the shown task's local draft, the authoritative values it compares that draft against, and any pending or failed save; the owner retains the task while a save is pending or failed and after a confirmed deletion, so a catalog refresh that drops the row can neither close the surfaced failure nor close the detail that states the deletion. Save submits one `schedule.update` request carrying the complete expected `ScheduleRecord` and the staged change; `onUpdateTiming` refreshes the catalog without turning a readback failure into a mutation failure.
58
+ While the Peer may read `schedule/catalog`, the plugin registers the existing `schedules` main panel, Session header utility, Turn tail card, Session row mark and hover entries, and `scheduleTask` right Sidebar tab. Slot injection supplies framework readers and action callbacks; components own selection, search, and paging state. Entry-declared stores retain each task draft and its CAS baseline across navigation within their root or Session scope; the main panel and Session tabs have independent drafts. Pristine forms follow the catalog. A dirty form retains all fields and its original revision. A newer catalog revision prevents saving until the user discards the draft or explicitly reapplies changed title, prompt, timing, and target groups to that revision. Reapplying does not write; the user reviews the resulting form and saves with the new CAS baseline. Untouched groups follow the newer record. Missing tasks retain editable local drafts while Host mutations stay disabled. Drafts are not persisted; a Client reload or disposal of the owning entry or Session scope drops them. The Host owns task storage and execution. Browsing catalogs does not activate a Session. Conflict feedback reuses the catalog notice style; its outlined review action wraps below the message in narrow panes.
67
59
 
68
- A restored task tab carries no navigation parameters, because the Sidebar persists a tab's layout record and not what its opener passed. The page type therefore keeps its own binding from the Session and the layout record's id to the Session and id of the task that record last showed, stored under one `dsh.schedule.task-tab.v1.<sessionId>` localStorage key per Session with one entry per tab id and never any task content. Its body and chip read the entry only for a record without navigation parameters, remove it once a read that succeeded after the tab appeared cannot resolve it, and report no missing task on a binding's behalf. Once such a read leaves the tab without a task identity, the body names that state instead of reporting a load that never finishes.
60
+ Edits to typed calendar timing use the shared recurrence evaluator to find the first valid future occurrence while preserving interval alignment across daylight-saving gaps. Successful edits use Schedule’s existing [current-format write path](../../schedule/schedule/README.md); a content-only edit retains the timing kind, precision, expression, and committed occurrence.
69
61
 
70
- Subscriptions exist only while the framework observes a source. The final unsubscribe releases event listeners and invalidates pending responses. Components receive framework-bound `useCatalog` hooks and explicit action callbacks. The mounted Records view reads `schedule.history` with the selected task's original Session binding; catalog and list responses omit full history. Components own disposable search, filtering, selection, confirmation, and history-page state. Reminder records remain Host-owned and do not come from historical Session projections or browser-local demo data.
62
+ The manager, task tabs, row marks, and conversation-header projections share one observable `schedule.catalog` source. Header and row views filter active records by involvement and delivery target. Mutations use task-id-based `schedule.create`, `schedule.edit`, and `schedule.run`; history uses task identity and cursor without a Session ownership parameter. A mutation acknowledgment triggers a fresh authoritative read; a failed read remains a catalog error rather than changing the acknowledged write into a failure.
71
63
 
72
- Task menus use the [standard menu geometry](../../../docs/ui-radius.md#nested-hover), including keyboard-highlighted rows. Created-task cards follow the [file-card family](../../../docs/ui-radius.md#radius-scale) for their radius and icon-tile material.
64
+ Sidebar layout records omit opener parameters. `TaskTabBindings` therefore persists task identity by Session and tab id in localStorage, without storing task content. Closed tab bindings are pruned. Observable catalog requests subscribe only while read, invalidate on Schedule changes and connection reset, and retire outstanding reads after the final subscriber leaves.
73
65
 
74
66
  </details>
75
67
 
76
68
  <a id="further-exploration"></a>
77
69
  ## Further Exploration
78
70
 
79
- - [Schedule](../../schedule/schedule/README.md) owns persistence, dispatch, and deletion semantics.
80
- - [Slots](../../../docs/subsystems/slots.md) documents injected hooks and panel contributions.
71
+ - [Schedule](../../schedule/schedule/README.md) owns persistence, destinations, lifecycle, and delivery semantics.
72
+ - [Slots](../../../docs/subsystems/slots.md) defines framework readers and panel contributions.
81
73
 
82
74
  <a id="model-experience"></a>
83
75
  ## Model Experience
84
76
 
85
- None, as this browser UI registers no model-facing tools or messages; Schedule owns reminder delivery.
77
+ None, as this browser package registers no model tools or automatic messages; the creation prompt stays an unsent draft.
86
78
 
87
79
  #### KV Cache effect
88
80
 
89
- None. Catalog presentation does not enter model requests.
81
+ None. Task-list content does not enter model requests.
90
82
 
91
83
  ## Known Limitations and Deferred Work
92
84
 
93
85
  <a id="known-limitations-and-deferred-work"></a>
94
86
 
95
- - Saved records describe inbox delivery, not model execution results. Tasks without saved history expose only their existing receipt until new deliveries append records; unsaved earlier records and prompt snapshots cannot be recovered. Previously physically deleted tasks are not restored.
96
- - Twenty-record pages bound the number of records requested, not prompt bytes or the storage a task retains. Delivery history is bounded by the Host plugin's configuration: `deliveryHistoryDays` (default 30) and `deliveryHistoryRecords` (default 200), pruned when an acknowledgment is appended, with the latest receipt always kept and a pruned older window reported as unavailable; see [Schedule limits](../../schedule/schedule/README.md#known-limitations-and-deferred-work).
97
- - Deletion does not cancel a reminder already queued for execution. The linked-Session control in the detail tab strip opens the original conversation through ordinary Session navigation and its recovery policy, not a message-specific jump.
98
- - Reminder creation remains with the Schedule tools. Name, instruction, and run-time edits are available only in the Rules view of an active task, in the Automation tasks page and in the task tab; pausing and immediate execution are not available, and the Run time card's Repeat menu accepts any choice, including one that changes the stored recurrence kind, in which case the target is recomputed from the new rule. The page's New action starts a Session instead of creating a task in place, and the Session-header popover itself has no run-time editor. The Time zone menu offers the runtime's IANA zone inventory, or a short curated list when the runtime cannot enumerate zones.
87
+ - Saved records describe inbox delivery, not execution results; absent historical prompts or physically deleted tasks cannot be reconstructed.
88
+ - The Host limits saved history by `deliveryHistoryDays` and `deliveryHistoryRecords`; page size limits record count, not prompt bytes.
89
+ - Conversation links open the Session through normal navigation, not a specific message. Deleting a task does not cancel messages already delivered.
90
+ - This UI provides no task-level authorization for model tools. Host Schedule owns access control and must enforce any per-Session restrictions.
99
91
 
100
92
  <a id="dev-note"></a>
101
93
  ### Dev Note
102
94
 
103
95
  <details>
104
- <summary>Working context for maintainers — click to expand</summary>
96
+ <summary>Maintenance context — click to expand</summary>
105
97
 
106
98
  None.
107
99
 
package/README.zh.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "跨会话的 Web 任务管理页面及当前会话的提醒列表。"
2
+ description: "基于现有 Web UI 的自动化任务管理和会话提醒入口。"
3
3
  kind: "package-reference"
4
4
  ---
5
5
 
@@ -9,7 +9,7 @@ kind: "package-reference"
9
9
 
10
10
  ## 概述
11
11
 
12
- 在「自动化任务」页面和右侧栏的任务页签中管理各个会话的活动和未运行定时任务:搜索、筛选、修改名称、指令和运行时间、浏览任务运行记录、删除任务,或打开原会话。每个界面都用任务已存储的标题命名任务。已打开会话在存在活动提醒时,页头显示仅图标的提醒时钟,点击在右侧栏打开该任务详情;`schedule_create` 调用把创建的任务渲染为会话卡片;侧栏中带活动任务的未归档空闲会话行显示时钟标记,其悬停卡片列出这些任务。
12
+ 自动化任务页和右侧栏任务页签使用同一编辑器处理任务规则、已保存的投递记录、删除及会话导航。手动创建和执行目标选择使用宿主的 Schedule 服务;会话卡片、页头时钟和会话行标记保留现有位置。
13
13
 
14
14
  ## 目录
15
15
 
@@ -25,77 +25,69 @@ kind: "package-reference"
25
25
  <a id="use-this-package"></a>
26
26
  ## 使用本包
27
27
 
28
- 随发行版交付的 Web 组合把 `ui-schedule` 与 Host Schedule 服务一起挂载。为模型提供当前时间的时钟上下文归 preset 所有:`standard`、`cordis` 与 `ptc` 声明它,`minimal` 既不声明它,也不声明提醒工具。侧栏的自动化任务入口打开全局页面,不选择或激活会话。页面页头的“新建”操作会打开一个新会话,提醒由模型在该会话中创建;页面本身没有创建表单。列表支持文本搜索和一行“全部/已开启/未运行”状态筛选;搜索匹配任务已存储的名称、指令和内部会话 id,不匹配解析出的会话标题,空状态在提示旁保留页头的“新建”操作。选择活动或未运行任务后,进入含“规则”和“任务运行记录”页签的第二层详情。每条列表行显示任务已存储的标题及其状态、频率和下次运行,不显示原会话名称;详情中的名称输入框显示任务已存储的标题。“规则”显示完整提醒、状态、活动任务的下一目标时间、原始重复规则和任务 id。每天的规则标签显示已保存的本地时间与精确的存储 IANA 时区,保留非零秒与毫秒,而不替换为浏览器时区。详情页签条内的“关联会话”入口按会话标题显示,取不到标题时回退显示会话 id。页签条放不下页签列表和带文字的入口时,入口收为与“更多任务操作”同样式的图标按钮,使用会话对话图标,悬停提示“关联会话”,入口禁用时也会显示;切换形态时保留焦点;页签列表可滚动但不显示滚动条。元数据加载后,它可打开可用且未归档的会话;会话或 Workspace 元数据尚未就绪、会话已归档、会话不在列表中或 Workspace 查询失败时,入口保持禁用并显示原因。点击时会重新检查可用性;浏览不会取消会话归档。仅此操作请求激活会话。删除位于详情顶部条带的“更多任务操作”菜单。
28
+ 宽度小于 768px 时,任务列表使用 20px 的左右内边距,与插件页一致。
29
29
 
30
- 页头按标题的自然宽度排布;标题和“新建”无法并排容纳时,将按钮移到下一行。操作文案保持单行。
30
+ 发布的 Web 组合将 `ui-schedule` 与宿主 Schedule 一起挂载。自动化任务侧栏入口打开任务列表,不选择或激活会话。“新建”和相邻菜单的“在会话中创建”都会进入新会话,按当前界面语言预填简短的任务创建提示,供用户补充并发送。若复用空白会话,提示会另起一行追加,保留原有文本、行内引用和附件。该菜单还提供“手动创建”。手动创建与已有任务打开同一编辑页,校验必填项并保存任务,不启动 Agent 或发送指令。请求失败时保留表单和已填内容。空态显示装饰性的文档与时钟插图,其颜色随主题变化。
31
31
 
32
- 从列表选择任务时默认打开“规则”;刷新同一任务会保留当前页签。活动任务的“规则”修改名称、指令和运行时间;这些修改保留在本地草稿中直到保存,未运行任务保持只读。不带修饰键的左右方向键循环切换页签,Home/End 选择第一个/最后一个页签,键盘焦点随选择移动。页签不会拦截这些键与 Alt、Ctrl、Meta 或 Shift 的组合。共用的会话入口位于详情页签条内,在“规则”页签可见;确认删除操作在两种页签下都可用。
32
+ “已开启”“已暂停”“已结束”“全部”筛选结合标题、指令和关联会话 id 搜索,默认显示已开启任务。搜索行菜单在确认后清除全部已结束任务,保留已开启和已暂停任务。选择任务直接打开可编辑的“规则 / 任务运行记录”页面。只有字段有效且有实际修改时才能保存;保存只发送变更字段及 `expectedUpdatedAt`,存储版本缺失时发送 `null`。保存后字段保持可编辑。切换任务或离开页面时保留未保存的草稿。冲突保留整份草稿并禁用保存。“保留修改并复核”将改过的字段组应用到最新值,供保存前复核;“放弃”用最新存储值替换草稿。对于新任务,“放弃”关闭编辑页。迟到响应不会改变其他任务详情。粗指针设备的搜索、指令和时间字段使用 16px 字号,避免 iOS Safari 聚焦时缩放。
33
33
 
34
- “规则”在“运行时间”卡片中以行编辑本地草稿:“重复”是含每周、周一至周五、每天、每 N 小时、每 N 分钟、每 N 秒、仅一次和自定义(cron)的菜单,每周规则增加“星期”行,固定速率选项只修改它所属单位的间隔数量,一次性规则用独立的“日期”和“时间”两行编辑目标,自定义(cron)用一行“Cron 表达式”编辑按所选时区解释的 5 字段表达式。卡片在浏览器中解析该表达式,并在该行下方显示描述它的本地化语句;Host 会拒绝的表达式改为显示本地化校验信息,并在解析通过前阻止保存。已存储的每周规则若星期集合恰好为周一至周五,则选中“周一至周五”选项。“日期”行是只读触发器,以 `YYYY/MM/DD` 显示暂存的日期并展开带本地化星期表头、月份切换和今天标记的月历;草稿与提交文本保持 ISO 形态;“时间”行是只读触发器,显示统一的 24 小时时钟,并展开时、分、秒三列可滚动列表,当前值高亮并在打开时滚动到可见。在月历或时钟上点选即按与其他行相同的分阶段保存写入草稿;方向键在打开的列或网格内移动,Enter 选定当前值,Escape 关闭面板并把焦点还给所在行,被禁用的行无法打开面板。时钟行显示到秒,未改动的行在提交时保留已存储的毫秒值,编辑时间时按整秒精度提交。“时区”使用高度受限的可搜索菜单。顶部无标题区域保留浏览器本地最近选过的 5 个准确时区;首次使用按真实系统时区和 UTC 初始化,而不根据界面语言猜测所在地。系统时区带有标记,其余清单按当前 UTC 偏移、再按规范 IANA 标识排序。可见文案把 `UTC±HH:MM` 放在本地化时区名称之前;IANA 标识仅在内部使用,但可用于搜索。ICU 显示成相同偏移和本地化名称的多个时区只占一行;所有被合并的标识仍可用于搜索,任务已保存的标识也会继续作为选中值,不会被改写。时区清单来自 `Intl.supportedValuesOf('timeZone')`,名称来自 `Intl.DateTimeFormat(..., { timeZoneName: 'longGeneric' })`:两者都是浏览器内置的 ICU/CLDR 数据,不是抓取或产品自维护的翻译表。因此没有需要刷新的爬虫或生成时区资源;第三方语言包只需提供常规的 `time.locale` 值,即可自动获得对应的 ICU 名称,仅需翻译选择器周边的 UI 文案。运行时无法枚举时改用简短的标识候选列表,已存储但不在其中的时区会保留。每天、每周和 cron 保留各自已存储的规则与时区,其频率行仅在时区与宿主系统时区不同时标出时区。一次性 After/At 以记录已存储的时区初始化日期和时间;记录未保存时区时取本设备时区,初始钟表值在该时区下仍表示同一瞬时;更改时区会保留输入的钟表值并改变时点。因选择种类而重新初始化的种类使用已提交发生时点的钟表值和该选项的时区,该时区取记录已存储的时区或本设备时区:每周的星期取自该发生时点在该时区下的星期,cron 则把该发生时点的钟表值写成每天执行的表达式。固定间隔至少为 60 整秒,不受时区影响。一次保存以分阶段的变更提交完整预期记录,并保留 id、原会话、最近一次回执及已保存历史;未来目标选择、重新确定起算时间和未变更规则的无写入语义见 [Schedule](../../schedule/schedule/README.zh.md#use-this-package)。
34
+ 执行位置下拉提供“新建对话并复用”和“每次新建对话”,手动创建默认前者。已经关联会话的任务,执行位置显示“当前关联对话”;编辑时保留原目标,只有用户主动选择新方式才会切换。“关联工作区”选择器列出框架工作区目录,在每个工作区名称下显示其路径,并以本地化默认名称标注首次使用时创建的工作区。新的执行位置默认使用该工作区;没有该工作区时使用列表中的第一个。没有目录的已有任务显示“未分组”,因为它创建的会话不加入任何工作区。复用目标的首次会话尚未存在时,详情底部入口显示“待创建”。每次新建的目标在首次投递后显示“最近运行对话”,首次投递前隐藏该入口;更早的对话仍可从任务运行记录进入。可用链接在打开前再次检查会话是否仍存在、是否归档;缺失或归档会话保持禁用。
35
35
 
36
- 行在保存进行中、目录加载中、删除期间以及任务未运行时禁用。仅当本地草稿与已存储任务不同时才出现保存栏:显示“有未保存的修改”及“取消”和“保存修改”,保存期间“保存修改”变为“保存中…”。“取消”恢复已存储的值。仅当草稿没有未保存修改时,目录刷新才会成为显示值,因此未保存的草稿会保留到权威刷新之后。保存失败保留草稿并显示本地化提示;冲突后针对刷新后的记录重试。任务从目录消失时,“删除”会禁用,直到任务重新出现。更新成功后刷新权威目录。更新被拒绝或无法确认与目录读取失败相互区分:“重试”重新加载目录,不将该更新显示为失败。若更新本身无法确认,应在重试前检查任务。切换任务或关闭详情后才到达的响应不会替换当前视图,任何失败都不会回滚宿主已开始的写入。
36
+ 重复编辑提供仅一次、每分钟、每小时、每天、每周、每月和自定义规则。日期和时间控件复用已有选择器。引导选项生成 RRULE;分钟和小时间隔从所选时区的当前分钟开始。自定义选项和自定义输入框不提示任何语法名称;输入框接受两行 RRULE 或带显式时区的五字段 Cron。RRULE 在 `DTSTART` 中保留时区;Cron 将表达式和所选时区保留为 Cron 时间类型。复杂 RRULE 保持原文。新的或已修改的自定义文本由共享时间解析器校验,校验通过后才能保存;无效或空输入保留草稿,并说明需要修改的字段。自定义文本无效时,提示手动修改规则、选择其他重复方式,或让智能体修改规则。宿主在保存时执行最终校验。已有 After、At 任务直接显示日期和时间控件;本地时间重复时,必要时使用 UTC 保留准确时点。Every、Daily、Weekly 任务在控件可表示其间隔或钟表时间精度时直接显示对应控件;其他时间规则仍在自定义中显示描述,并在替换前保留原类型。查看任务或编辑其他字段保留其时间规则及已提交发生时点。
37
37
 
38
- 打开“任务运行记录”时才请求最新的 20 条已保存记录。“加载更早的记录”按追加顺序从新到旧增加一页,不受实际时间回拨影响。该视图中页签条就是整个页头:名称输入框和“下次运行”行只属于“规则”。每条“已保存的任务运行记录”以时钟图标和任务时区下的本地月份名与时钟字段开头(一次性记录使用浏览器时区),并在存在时显示实际保存的提示文本。超过两行的提示文本只显示前两行并提供“展开”,展开后可“收起”;面板宽度变化时,收起状态的提示文本会重新判断是否超过两行。旧回执没有提示文本时,绝不以当前指令代替。
38
+ 暂停和恢复修改生命周期状态。有未保存修改时,先保存或放弃更改,才能暂停、恢复、立即执行或删除。详情菜单提供立即执行和删除,不提供取消排队消息:同一条收件箱消息可能包含多个任务的投递。投递到复用对话的投递排队或执行期间,详情禁用字段、保存、暂停与恢复、立即执行和删除,并说明此任务已排队或执行中,请在会话中管理任务;详情底部的会话入口打开该会话。最小投递间隔结束前禁用再次立即执行,执行空闲后仍可暂停或删除。仅因间隔禁用时,立即执行项仍可聚焦,其提示说明未满最小运行间隔,并给出可以立即执行的时间。已经关联会话的任务,其关联对话已归档时,同样禁用立即执行,因为宿主拒绝这次投递。宿主以 `schedule_execution_pending` 拒绝的立即执行显示为状态提示,而非错误。删除需要确认,移除任务及其已保存记录,保留会话和已经投递的消息,并通过现有应用级提示报告结果。确认对话框首先聚焦“取消”;对话框关闭后,焦点回到详情菜单按钮。宿主答复之前,详情保持显示该任务。删除生效后关闭详情或其任务页签;删除失败时保留任务,以便再次尝试。
39
39
 
40
- 最后一页加载完成后,非空且确认裁剪过的历史在详情面板左下角显示无分隔线的清理提示,信息图标可展开或收起当前宿主的保留规则。空历史、未确认裁剪的旧格式历史、尚未加载完的分页和读取失败均不显示清理提示。
40
+ 列表、详情、页头和会话悬浮内容的下次运行时间,取计划发生时间和宿主最早允许投递时间中较晚的一项。创建和编辑“每次新建对话”时,通过 `schedule.deliveryLimits` 读取宿主配置,以一句短提示显示最小间隔;读取失败可重试。定时与立即执行共用此限制。
41
41
 
42
- 历史查询成功的空页与加载中、查询失败、任务不存在或游标无效相互区分。请求失败时保留此前加载的记录,并显示警告和“重试加载任务运行记录”;游标无效时提供“刷新任务运行记录”,重新加载最新一页。最新 `messageId` 变化时刷新最新一页,不切换页签。被刷新取代的响应,以及切换任务、离开任务运行记录或关闭详情后才收到的响应,不会替换当前视图。
42
+ “任务运行记录”按需请求 20 条已保存投递,支持从新到旧分页,失败时保留已加载记录,并忽略被刷新替代或卸载后的请求。每条记录显示投递发生时间与已保存指令,长指令可展开、收起;缺少指令的旧记录不使用当前指令替代。回执的实际执行会话可用时提供入口。仅在最后一页且确认裁剪后显示清理提示,并提供当前保留规则说明。这些记录确认收件箱投递,不表示模型执行成功。
43
43
 
44
- 自动化任务页面要求确认后才能删除任务。删除是硬删除:Host 连同已保存的任务运行记录一起移除存储的任务行,该任务因此停止后续投递、离开 `list` 与 `catalog`,其投递历史不再可读。删除保留原会话和已入队消息;列表仅在权威查询确认移除之前保留该行。每条删除路径——自动化任务页的详情、会话的任务页签、以及页头弹层——都把最终结果写入同一个存储,由应用级 `shell.overlay` 提示渲染,因此提示的生命周期长于发起它的面板或页签:Host 连同已保存的运行记录移除该行后提示显示「任务已删除」,失败时显示「无法删除任务」,并保留规则以便重试。确认删除会关闭确认所在的面板或页签,每条提示按自身序号区分,后一条会重新开始横幅而不是并入前一条。查询失败保留最近已知记录,并显示独立的重试操作;不会呈现为查询成功的空结果。一次性任务在持久收件箱投递后仍以未运行状态保存。显式删除前,通过全部或未运行筛选仍可查看详情与原会话 id。最近一次投递显示其发生时间,不显示消息 id 和投递确认时间;未运行状态和该回执均不表示模型执行完成。
45
-
46
- 已打开的会话只有在确实有可打开的内容时,才在页头右侧功能位中、紧邻更多操作菜单左侧渲染一个仅图标时钟按钮:首次读取前不渲染任何内容,读取结果为没有活动提醒时页头不显示该按钮,刷新期间保留上一次已知的提醒,读取失败则保留按钮及其重试。该规则避免时钟在首次结果前后出现又消失。其无障碍名称在读取就绪时给出提醒数量,否则显示通用提醒标签。当该会话只有一个活动提醒时,按钮直接在右侧栏打开该任务的详情。其余数量都会打开弹层:先列出逾期提醒,再按目标时间列出未来提醒,显示已存储的标题、频率、浏览器本地目标时间、相对时间及删除按钮;标题本身是一个按钮,点击后在右侧栏打开该任务的详情。任务页签在标签上显示当前任务已存储的标题,并提供与自动化任务页面相同的规则、任务运行记录、名称、指令和运行时间修改、确认删除和原会话入口;它不会激活会话。每日频率文本保留保存的本地时间和时区;每个下一目标时点都显示为设备时区的钟点和括号内的相对时长;规则自身的时区只显示在该频率文本中。Escape 关闭弹层并将焦点返回按钮;点击外部将其关闭。删除最后一条提醒会移除按钮;在此之前,已经打开的弹层保持可展开状态。
47
-
48
- 弹层通过 portal 挂到 body,目标宽度为 336px;空间足够时与触发按钮左边缘对齐,触发器靠近视口右侧时向左避让并保留 16px 视口边距,宽度不超过视口宽度减 32px,列表溢出时纵向滚动。它不显示任务 id、原始 UTC 值或投递详情;每行只带自身的详情入口和删除操作。
49
-
50
- 调用 `schedule_create` 时,创建的任务会以卡片形式渲染在 transcript 中,包含时钟图标、已存储的标题、频率,以及打开该任务右侧栏页签的“打开”按钮。卡片先按该调用持久化的结果 JSON 收窄出任务,并从该结果读取 `title`;当一次在卡片出现之后成功结束的目录读取解析到该任务时,卡片改为跟随目录显示当前名称与频率,若该读取中不含该记录,则以“已删除”代替频率显示。在已存储字段存在之前录制的结果回退为指令首行。仍在运行的调用、创建失败,或结果中没有完整任务时,卡片保留该行,并在结果为单个非空文本块时显示原始结果文本,不提供“打开”操作。卡片不增加 Host 字段,也不改变 Session 日志格式,因此早于该卡片录制的 Session 也会渲染它。
51
-
52
- 侧栏的 Session 行会标记有定时任务的会话:当某行处于空闲状态、未归档且其会话至少有一个活动任务时,该行显示时钟标记;归档行该格留空,其实时状态只在悬浮卡片中显示。对存在活动任务的会话长按悬停时,无论该行是否空闲,都会在其已有的悬浮卡片内增加自动化区段,最多列出两个任务(图标、已存储的标题、频率与下次运行文本),还有更多任务被隐藏时显示遗漏行。处于更高优先级状态的行——有待处理交互、活动仍在进行,或有未查看的完成提醒——保留自身状态点且不渲染标记,两者不会同时出现。该标记和悬停区段读取共享的活动与未运行 Host 任务目录,并从中筛选本会话的活动任务;它们不会激活、保留或取消归档任何会话,也不读取 Session 日志。
53
-
54
- -----
44
+ 打开会话的页头时钟在首次读取成功之前或没有活动关联任务时保持隐藏。一个任务直接打开右侧栏页签;多个任务打开现有弹层。空闲、未归档且有活动关联任务的会话行保留时钟标记和悬浮列表。`schedule_create` 继续在轮次末尾渲染任务卡片,显示标题、重复描述和“打开”操作。持久化的旧工具结果与当前结果均可渲染;比卡片更新的权威读取同步后续修改或删除。
55
45
 
56
46
  ### 时区数据来源
57
47
 
58
- 时区清单与本地化完全离线。`Intl` 读取浏览器运行时内嵌的 ICU/CLDR 表,DSH 运行时不会获取或下载时区数据。没有需要刷新的爬虫;第三方语言包提供 `time.locale`,并仅翻译选择器自身的 UI 文案。
48
+ 时区清单和本地化名称通过 `Intl` 使用浏览器内嵌的 ICU/CLDR 数据,不在运行时下载。选择器保留清单未列出的已存储别名;无法枚举时使用系统时区和 UTC。
59
49
 
60
50
  <a id="understand-the-implementation"></a>
61
51
  ## 理解实现
62
52
 
53
+ 任务菜单使用[标准菜单几何](../../../docs/ui-radius.zh.md#nested-hover),包含键盘高亮行。使用 portal 的任务菜单和日期、时间选择器通过 `useAnchoredPosition`,在浏览器缩放、滚动和尺寸变化时跟随触发器,并保留视口边距和桌面标题栏避让。视觉视口过窄时,任务菜单文案和时间值以省略号截断。时间列随面板缩窄,并在可用高度内纵向滚动;任务菜单通过纵向滚动到达每个选项。会话页头弹层遵循同样的视口限制,并在首次定位完成前保持隐藏。
54
+
63
55
  <details>
64
56
  <summary>实现内部细节 — 点击展开</summary>
65
57
 
66
- 浏览器入口注册 `schedules` 主面板及对应的侧栏入口、Session 页头右侧功能位中位于 `order: -5` 且紧邻更多操作菜单左侧的 `schedule-catalog` 入口、经由 `ctx.uiConversation.events` 与 ui-chat 的 list seat `conversation.chat.turnTail` 在轮次层级注册的 `schedule_create` transcript 卡片(因此它渲染在该轮收尾的 assistant 文本之后,并在工具调用组折叠时仍然可见)、root 作用域的两个 Session 行 seat `sidebar.session.row.leading` 与 `sidebar.session.row.hover`,以及 kind 为 `scheduleTask` 的右侧栏页类型 `@deepseek-ai/dsh-client-ui-schedule/task`。该类型分两阶段注册:先把其定义注册进 `ctx.sidebarRightTabs`,再按该定义的 id 把正文与 chip 注册进带键 seat `sidebar.right.pane.tab` 与 `sidebar.right.pane.tab.title`。从 Session 入口打开任务时调用 `ctx.sidebarRight.openTab`,传入该入口的 Session id 与所选任务 id,详情因此出现在该入口所属 Session 的右侧栏中;自动化任务页面保留自己的列表并共用同一个详情组件。全局页面、任务页签、行标记与行悬停区段都从同一个 `schedule.catalog` 源读取活动与未运行任务;页头入口保留自己的按 Session `schedule.list` 读取,只返回该 Session 的活动任务。每个面都使用同一套可观察的查询生命周期,并在 `schedule/changed` 或连接重置后刷新。transcript 卡片从该调用持久化的结果 JSON 收窄出创建的任务,而不是依赖 Host 追加字段;该调用自身的工具调用组单元格由 ui-tool 的通用键控视图渲染,且卡片只对产生完整任务的调用出现。该对齐是因果判定而非时钟比较:目录快照带有 `readRequest`(最新被请求的读取序号)与 `readSettled`(产出当前记录的读取序号);Turn 尾部挂载时锚定 `readRequest` 并请求一次读取,仅在 `readSettled` 大于该锚点后才用其保留记录判定,且源把一次提交内的请求合并为单次 `list()`,只把该读取共享给尚未观察到它的调用者。比较浏览器时钟与 Host 时钟无法确立这一顺序。共用的删除回调与注入的 `onUpdateTiming` 保留所选记录的原 Session 绑定,而不使用当前打开的对话。详情保留当前任务的本地草稿、用于比较的权威值以及等待中或失败的保存;保存等待中或失败期间以及删除确认后,属主保留所显示的任务,使目录刷新在丢弃该行时既不能关闭已呈现的失败,也不能关闭陈述删除的详情。保存发出一次携带完整预期 `ScheduleRecord` 和分阶段变更的 `schedule.update` 请求;`onUpdateTiming` 刷新目录,而不把回读失败变成修改失败。
58
+ Peer 可读取 `schedule/catalog` 时,插件注册现有 `schedules` 主面板、会话页头功能位、轮次尾部卡片、会话行标记与悬浮内容,以及 `scheduleTask` 右侧栏页签。槽位注入提供框架读取器与操作回调;组件拥有选择、搜索和分页状态。入口声明的存储在根或会话作用域中按任务保留草稿和 CAS 基线,支持导航后恢复;主面板与会话页签的草稿相互独立。未修改的表单跟随目录更新。已修改的表单保留全部字段及原版本。目录出现新版本后,须放弃草稿,或由用户明确将改过的名称、内容、时间和目标字段组重新应用到该版本,才能保存。此操作不写入任务;用户复核结果后,以新版本作为 CAS 基线保存。未修改的字段组采用新记录的值。任务缺失时保留可编辑的本地草稿,宿主修改操作仍禁用。草稿不持久化;客户端重新加载,或所属入口、会话作用域销毁时,草稿随之释放。宿主拥有任务存储与执行。浏览目录不会激活会话。冲突反馈沿用目录提示样式;复核按钮采用描边样式,在窄面板中换到提示下方。
67
59
 
68
- 刷新恢复出的任务标签没有导航参数,因为 Sidebar 只持久化标签的布局记录,不持久化打开方传入的内容。因此该页面类型自行保存从 Session 加布局记录 id 到该记录最后显示任务的 Session 和 id 的关联:每个 Session 一个 `dsh.schedule.task-tab.v1.<sessionId>` localStorage 键,按 tab id 一条记录,且从不保存任务内容。正文和 chip 只对没有导航参数的记录读取该条目,在标签出现之后成功的一次读取无法解析时将其删除,且不代替关联声称任务缺失。这样的一次读取无法为该标签给出任务标识时,正文陈述该状态,而不呈现永不结束的加载。
60
+ 修改类型化日历时间时,通过共享重复规则求值器查找首个有效未来发生时点,并保留跨夏令时缺口的间隔对齐。成功编辑沿用 Schedule 的[当前格式写入路径](../../schedule/schedule/README.zh.md);仅修改内容时保留时间类型、精度、表达式及已提交发生时点。
69
61
 
70
- 仅在框架观察数据源期间订阅。最后一个订阅取消时释放事件监听,并使尚未完成的响应失效。组件接收框架绑定的 `useCatalog` hook 和明确的操作回调。已挂载的任务运行记录视图使用所选任务的原会话绑定读取 `schedule.history`;目录和列表响应不包含完整历史。组件拥有可丢弃的搜索、筛选、选择、确认和历史分页状态。提醒记录由 Host 拥有,不来自历史会话投影或浏览器本地演示数据。
62
+ 管理页、任务页签、行标记和会话页头投影共享一个可观察的 `schedule.catalog` 数据源。页头与会话行根据关联关系和执行目标筛选活动记录。修改使用基于任务 id 的 `schedule.create`、`schedule.edit` 和 `schedule.run`;历史使用任务标识和游标,不携带会话所有权参数。修改确认后发起新的权威读取;回读失败仍是目录错误,不将已经确认的写入改判为失败。
71
63
 
72
- 任务菜单使用[标准菜单几何](../../../docs/ui-radius.zh.md#nested-hover),包含键盘高亮行。已创建任务卡片的圆角和图标底框材质遵循[文件卡片家族](../../../docs/ui-radius.zh.md#radius-scale)。
64
+ 侧栏布局记录不保存打开参数,因此 `TaskTabBindings` 按会话和页签 id 在 localStorage 中保存任务标识,不保存任务内容,并清理已关闭页签的关联。可观察目录仅在被读取时订阅,在 Schedule 变更或连接重置时刷新,最后一个订阅退出后使未完成读取失效。
73
65
 
74
66
  </details>
75
67
 
76
68
  <a id="further-exploration"></a>
77
69
  ## 延伸阅读
78
70
 
79
- - [Schedule](../../schedule/schedule/README.zh.md) 拥有持久化、投递和删除语义。
80
- - [槽位](../../../docs/subsystems/slots.zh.md) 说明注入 hook 和面板贡献。
71
+ - [Schedule](../../schedule/schedule/README.zh.md) 拥有持久化、执行目标、生命周期和投递语义。
72
+ - [槽位](../../../docs/subsystems/slots.zh.md) 定义框架读取器和面板贡献。
81
73
 
82
74
  <a id="model-experience"></a>
83
75
  ## 模型体验
84
76
 
85
- 无,因为浏览器 UI 不注册面向模型的工具或消息;提醒投递由 Schedule 拥有。
77
+ 无:本浏览器包不注册模型工具或自动消息;创建提示保留为未发送的草稿。
86
78
 
87
79
  #### KV Cache 影响
88
80
 
89
- 无。列表展示不进入模型请求。
81
+ 无。任务列表内容不进入模型请求。
90
82
 
91
83
  ## 已知限制与后续工作
92
84
 
93
85
  <a id="known-limitations-and-deferred-work"></a>
94
86
 
95
- - 已保存的记录描述收件箱投递,不表示模型执行结果。没有已保存历史的任务仅呈现已有回执,直到新投递追加记录;未保存的更早记录和提示文本快照无法恢复。此前已物理删除的任务不会恢复。
96
- - 每页 20 条仅限制请求的记录数,不限制提示文本字节数或任务保留的存储。投递历史由 Host 插件的配置设界:`deliveryHistoryDays`(默认 30)与 `deliveryHistoryRecords`(默认 200),在追加确认时裁剪,最近一次回执始终保留,被裁剪的更早窗口报告为不可用;见 [Schedule 限制](../../schedule/schedule/README.zh.md#known-limitations-and-deferred-work)。
97
- - 删除不会取消已经排队执行的提醒。详情页签条内的关联会话入口使用普通会话导航及其恢复策略打开原对话,不直接跳转到特定消息。
98
- - 创建提醒仍通过 Schedule 工具完成。仅在活动任务的“规则”中可修改名称、指令和运行时间,自动化任务页面和任务页签均可;不提供暂停或立即执行,且“运行时间”卡片的“重复”菜单接受任意选择,包括改变已存储重复规则种类;此时按新规则重算目标。页面的“新建”操作会打开一个会话,而不是在页面内创建任务;会话页头的弹层本身不提供运行时间编辑器。“时区”菜单提供运行时的 IANA 时区清单,运行时无法枚举时改用简短的候选列表。
87
+ - 已保存记录描述收件箱投递,不表示执行结果;无法重建缺失的历史指令或已物理删除的任务。
88
+ - 宿主通过 `deliveryHistoryDays` 和 `deliveryHistoryRecords` 限制历史;分页大小限制记录数量,不限制指令字节数。
89
+ - 会话入口通过普通导航打开会话,不跳转到特定消息。删除任务不会取消已投递的消息。
90
+ - 此 UI 不为模型工具提供任务级授权。宿主 Schedule 拥有访问控制,任何按会话限制都必须由宿主执行。
99
91
 
100
92
  <a id="dev-note"></a>
101
93
  ### 开发备注