English · Chinese
dsh-todo-list — a To Do List plugin for DeepSeek Harness (DSH)
A deployment-level DeepSeek Harness (DSH) To Do List plugin: it recognizes key items from conversations — natural chat, imported notifications, announcements, and email content — turns them into dated to-dos, and manages them from the To Do List entry in the left sidebar. The plugin mounts as a bundle into a profile (dsh plugin add one-click install) without modifying DSH source. No approval or configuration needed; data and the entry survive restarts.
Feature Overview
- Understand-notification skill: a packaged skill (
understand-notification, ships inskills/and registers through a dedicatedtodo-skillsprovider) that teaches the model to extract actionable items from notifications, announcements, emails and conversations into a structured JSON with the 5W1H shape (who / what / when / where / why / how) plus urgency/importance — pure extraction rules, no tool calls inside the skill. Extraction follows an explicit granularity rule: actions merge into one entry when the owner is the same (or unstated), the due date is the same, and the actions form a "first … then … finally …" chain delivering one result (details go intowhat); actions split when the owner differs, the due date differs, or the deliverables are independent. Titles stay as short as possible;whatcarries the full detail; unmentioned 5W1H fields are left empty rather than invented. - Extract to-dos with preview & confirm: the model parses the text per the skill and calls
todo_previewto stage candidates; a multi-select popup appears, and items are written only after you confirm — nothing is added without your approval. - Seven model tools:
todo_preview/todo_add/todo_list/todo_complete/todo_remove/todo_update/todo_todayfor staged-preview and direct CRUD inside a session. - REST API:
/api/todowith list, batch-add, update, delete and clear-completed endpoints, plus/api/todo/pending(list / stage / clear) andPOST /api/todo/pending/confirmfor the preview-confirm flow. - Sidebar panel: a To Do List entry plus Pending/Done tabs; click an item for details (due date, days left, urgency/importance, 5W1H elements, notes). Both the detail popup and the preview popup are draggable by their headers.
- Settings page: language (Chinese / English), panel opacity and width, persisted automatically; the preview popup shares the same opacity setting.
- Reliable persistence: local JSON with atomic writes and legacy-data migration; nothing is lost on restart.
Installation
Prerequisites: a working DSH web profile (usually at $DSH_HOME/profiles/web, with DSH_HOME defaulting to ~/.dsh) and an available dsh command.
Recommended: dsh plugin add
dsh plugin --profile web add dsh-todo-list
This runs pnpm add dsh-todo-list inside the profile directory; because the package declares dsh.bundle.patch, dsh plugin automatically appends it to the profile's bundle layer (dsh.profile.bundles) — no manual edits to package.json or cordis.patch.yml. Restart dsh web after installing.
Alternative: local file: install
A file: install needs the project source (this repository), not the npm package — the npm tarball only ships the compiled lib/, the packaged skills/ and cordis.patch.yml, with no src/ or TypeScript toolchain to build from. Get the source first:
git clone https://github.com/perry-ai/dsh-todo-list.git # or download the zip from GitHub
Then build the output and declare the dependency:
# 1. Build the project in the source directory ($SRC)
cd "$SRC"
pnpm install # the prepare script compiles src/ → lib/
# 2. Declare the dependency: edit $PROFILE/package.json, add to dependencies
# "dsh-todo-list": "file:<path to $SRC>"
# 3. Join the composition: edit $PROFILE/cordis.patch.yml, append
# - insert:
# - id: dsh-todo-list
# name: 'dsh-todo-list'
# 4. Install and restart
cd "$PROFILE"
pnpm install
A file: dependency is installed by copy (not linked); pnpm may skip copying when it detects no content change — use pnpm install --force in that case. The plugin is ready after restarting dsh web.
Quick Start
Add to-dos directly in a DSH conversation using natural language, e.g.:
Please note two items for me: send the draft quarterly business analysis report to management by August 26 — it's important; also submit last month's expense claim in early September, no rush.
The model automatically calls todo_add, parsing the text into to-dos (title / 5W1H elements / due date / urgency / importance), e.g.:
Added 2 to-dos:
[ ] 2026-08-26 Draft the quarterly business analysis report and send it to management (urgent, important, top priority) (7 day(s) left) — important
[ ] 2026-09-01 Submit last month's expense claim (13 day(s) left)
Now: 2 pending, 0 done
Note: model tool output is currently rendered in Chinese; the English above is an illustration.
Then you can:
- call
todo_todayso the model converts relative dates ("tomorrow", "next Monday", "end of month") into concrete dates; - use
todo_listto view the list, andtodo_complete/todo_remove/todo_updateto maintain it (title, due date, urgency, importance, notes, 5W1H fields, etc.); - or open the To Do List entry in the left sidebar: switch between Pending/Done, click an item for details (due date, days left, urgency/importance, 5W1H elements, notes), and open settings to switch the language or adjust opacity/width;
- or use the REST API directly:
GET http://127.0.0.1:3080/api/todoto list,POST /api/todoto batch-add.
Storage & migration
- The list lives at
$DSH_HOME/storages/dsh-todo-list/todos.jsonwith the shape{ version, todos, nextId }(store version 3: the 5W1H fields were added in v2, and the formeracceptancefield was merged intowhatin v3; older files load fine — missing 5W1H fields are backfilled as empty strings and legacyacceptancevalues are merged intowhatwith a "完成标准:" prefix on read). - Every change first writes
<file>.tmpand then atomically renames it, avoiding half-written files. - On first load, if the legacy
<cwd>/todos.jsonfrom the old dynamic plugin exists, it is migrated to the new location; the original file is kept. - Reads go through an in-memory snapshot that is refreshed after every write.
Features
- Model tools: the Host registers 7 global tools —
todo_preview/todo_add/todo_list/todo_complete/todo_remove/todo_update/todo_today.todo_addturns multiple items from a piece of text into to-dos in one call, each with aYYYY-MM-DDdue date;todo_previewstages the parsed candidates for the confirm popup instead of writing them directly. - Understand-notification skill: the packaged
understand-notificationskill defines the extraction rules (granularity: merge same-owner + same-due-date actions that form a "first…then…finally…" chain delivering one result into a single entry with details inwhat, split when owner or due date differs or deliverables are independent; resolve due dates — explicit or relative to the current date, inferred ones marked in notes; fill the 5W1H fields who / what / when / where / why / how, leaving unmentioned ones empty and never inventing content; keep titles short andwhatdetailed — completion criteria also go intowhat, not a separate field; judge urgency/importance, notes) and the exact JSON output shape; it carries no tool-call instructions — the bridge totodo_previewlives in the tool description. The skill is discovered from the package'sskills/directory via thetodo-skillsprovider (independent of the hostfilesystemprovider). - Fields & priority: every to-do carries a title (the display main field, kept as short as possible), the 5W1H elements — who (owner), what (action detail, required and detailed — merged sub-steps and completion criteria live here), when (due date), where (place/channel), why (reason), how (steps) — plus urgency, importance and notes. The priority is derived automatically from urgency + importance — both high → urgent, shown as the badge URG in the list, either high → high, both medium → medium, either low → low. Missing 5W1H fields default to empty strings (never invented); legacy data is backfilled on load, with the former separate
acceptancefield merged intowhat. - REST API:
GET /api/todo(list),POST /api/todo(batch add),PATCH /api/todo/:id(update),DELETE /api/todo/:id(delete),POST /api/todo/clear-completed(clear completed); preview flow:GET/POST/DELETE /api/todo/pending(list / stage / clear candidates) andPOST /api/todo/pending/confirm(write the checked candidates). - Sidebar entry: a To Do List entry at the bottom of the sidebar — icon + label + pending-count badge in the wide bar, a round icon when collapsed to a rail. Clicking opens a panel with Pending/Done tabs; the pending tab shows a pending-count badge.
- Detail popup: click any row to float a detail popup to the right of the panel — due date, days left, color-coded urgency/importance, the 5W1H elements (who / what / where / why / how, shown when present) and notes; the clicked row is highlighted. The popup is draggable by its header.
- Preview-confirm popup: when the model calls
todo_preview, a popup (registered in theshell.overlayslot) shows the candidates with multi-select checkboxes; confirming writes the checked items via/api/todo/pending/confirm, cancelling clears them. Its visual language — background, opacity, rows, colors — matches the detail popup exactly, so both look identical side by side. Draggable by its header too. - Settings page: the gear button opens settings to adjust the panel opacity (0.01–0.1) and width (150–350 px) with a slider plus a live numeric display, persisted to localStorage; the detail and preview popups share the same opacity value.
- Persistence: the list is stored at
$DSH_HOME/storages/dsh-todo-list/todos.json, written via temp file + atomic rename so a crash never leaves a half-written file. - Theme adaptation: the panel uses a translucent DeepSeek-brand blue and automatically adapts to DSH web's dark/light theme (based on
body[data-ds-dark-theme]); the sidebar footer stacking fix is built into the client styles, no platform source changes needed. - Internationalization: every UI string is defined in zh/en dictionaries; the plugin starts in the DSH language and offers a language switcher (Chinese / English) in its settings page.
Architecture
src/index.tsmounts the/api/todoprefix routes through thewebServerservice, registers the 7 model tools through the optionaltoolsservice, and registers the packaged-skill provider through the optionalskillsservice.src/skill-provider.tsscans the packagedskills/directory (<name>/SKILL.mdor<name>.md), parses minimal frontmatter (name / description / whenToUse), and exposes them as a filesystem-style skill provider — zero extra runtime dependencies, and no conflict with the hostfilesystemprovider (unique provider nametodo-skills, scans only its own directory).src/types.tsdeclares domain types and shared constants;src/services.tsdeclares the structured subset contracts (types only, zero runtime) of the DSH/Cordis services this plugin consumes.src/store.tshandles persistence: in-memory snapshot + atomic rename writes, migrating old dynamic-plugin data on first load.src/domain.tscentralizes validation (title, date format), days-left math, priority derivation (derivePriority), item projection and CRUD, plus candidate staging for the preview flow (stageCandidates/pendingSnapshot/confirmPending/clearPending).src/api.tsdispatches REST routes; request bodies are JSON, capped at 1 MiB (413 when exceeded, 400 for invalid JSON). Besides CRUD it serves/api/todo/pending(GET list / POST stage / DELETE clear) andPOST /api/todo/pending/confirm.src/tools.tsdefines the JSON Schemas and text rendering of the 7todo_*tools (todo_previewstages candidates without writing).src/client.tsis the browser half: it self-registers as a single file viawindow.__ModuleLoader__, injects styles, and mounts the sidebar entry, detail popup, settings page and the preview-confirm popup (registered in theshell.overlayslot), reading and mutating data through/api/todo. The detail and preview popups share the same opacity setting and are draggable by their headers.
Build
Requires Node 22.19+ / 24+ (same as DSH) and the TypeScript toolchain:
pnpm install # installs devDependencies and triggers the prepare build into lib/
pnpm build # manual build: tsc -p tsconfig.json, src → lib
pnpm typecheck # type-check only: tsc --noEmit
lib/ is build output and is not committed (see .gitignore); pnpm install regenerates it from src/ via the prepare script, so run pnpm install once in this project before a file: install. The published package ships .d.ts declarations, so TypeScript consumers get types out of the box.
Manual verification
- Mount the plugin and restart
dsh web; confirm the To Do List entry appears at the bottom of the sidebar. - In a session, call
todo_todayto get today's date, thentodo_addto batch-add items. - Call
todo_list; confirm every item returns a title, due date and days left. - Open the sidebar panel and switch between Pending/Done; confirm the pending-count badge and that completed items show no due badge.
- Click an item to open the detail popup; confirm due date, days left, color-coded urgency/importance, 5W1H elements and notes; the clicked row is highlighted.
- Open the settings page and adjust opacity and width; confirm changes apply immediately and persist.
- Request
GET /api/todoand confirm{"todos":[...]}; PATCH an item as done, list again, and confirm the done state and pending count change. - Restart the Harness and confirm the to-dos are still there.
Known limitations
- No cross-process file lock: with several Hosts running against the same
$DSH_HOME, each process keeps its own in-memory snapshot and writes may overwrite each other. - To-dos are not shown inside the conversation; they are managed only via the sidebar entry and the
todo_*tools. - Priority cannot be set manually; it is always derived from urgency and importance.
- The sidebar footer fix depends on the CSS class
[class*="footerActions"]; renaming it in the platform would break the layout. - Relative dates (tomorrow / next Monday, etc.) are converted to concrete dates only after the model calls
todo_todayfirst. - Preview candidates are held in memory: they are discarded on a process restart, and a new
todo_previewcall replaces the whole pending set. Nothing is written until you confirm in the popup.
还没有评论,来写第一条。