dsh-plugin
DayuanJiang/next-ai-draw-iodsh 的 draw.io 绘图插件:通过 next-ai-drawio MCP 服务器作图,点回复里的链接在右侧栏打开实时预览,可以手动修改图,AI 的每次修改都是可以恢复的版本。需 Node.js 18+,首次使用由 npx 下载 MCP 服务器。
归档会话管理、任务完成桌面通知、更新检查、模型路由(关键词规则 + 白名单门控 model_route)、多任务定时触发(心跳与定点任务),以及 DeepSeek 风格的消息滚动导航。
Unofficial community plugin. Not affiliated with DeepSeek. Code produced by AI.
Better DSH — a dual-half plugin (host + browser) that follows the DeepSeek Harness plugin conventions and adds a few handy tools to the dsh web GUI: archived-session management, system-level task notifications, an update checker, model routing, multi-task scheduled triggers (heartbeats & fixed-time), and a DeepSeek-style message scroll nav. Everything lives under Settings → Better DSH, ready to use right after install.
中文 · English
This plugin is listed on dsh-market — you can discover and install it right from the marketplace.
Published on npm — one terminal command installs it into your dsh profile:
dsh plugin --profile web add dsh-better
Restart DSH afterwards and the "Better DSH" entry appears in Settings.
Settings → Better DSH:
model_route tool lets the agent switch models mid-conversation (design ported from dsh-model-router, trimmed to what was needed);Every configuration change applies live — no restart needed.
A standard dual-half plugin: the host half runs inside the Node backend process and registers a set of loopback-only /api/dsh-better/* exact API routes; the browser half loads per page, injects the settings UI, and talks to the host over those routes.
Everything is resolved against the running dsh runtime at load time: dsh-better is loaded through a symlinked directory and cannot statically import "@deepseek-ai/*", so the host half resolves the host modules it needs with the running entry as the anchor — the same build artifacts as the running instance. Any missing piece disables just its own feature with a warning instead of breaking backend startup.
Three security fences: loopback peers only; a Host header check (anti DNS-rebinding); and POST bodies must declare application/json — a cross-site "simple request" cannot forge that header, and these routes never answer CORS preflights, so a forged page can't touch your archives.
.jsonl session log and removes the session from the workspace records and the archive set; a live session refuses deletion (session-live);domain/changed forwarding — every open page, no manual refresh.DSH_BETTER_REPO_ROOT → walk up from the running entry (argv[1]) and cwd to the nearest @deepseek-ai/dsh package.json (hits both source runs and packaged installs) → the pnpm global store next to the node executable → a conventional-path scan of <drive>:\.dsh\deepseek-harness. A path containing node_modules means "packaged install"; an apps/cli layout means "source build"; the drive scan and pnpm probing are Windows-only and silently skipped on unix;/releases/latest (that endpoint excludes prereleases — a 404 is expected when every upstream release is a prerelease) → the /releases list's first non-draft entry (one retry) → the github.com/<repo>/releases.atom feed (a different host — the independent path when api.github.com is down entirely; one retry). Per-request timeout of 9 seconds; successes cache for 5 minutes; if everything fails within 24 hours of a success, the stale value is shown with a "cached data (may be outdated)" badge — stale data beats a blank error;0.1.1-rc.2 < 0.1.1, numeric prerelease identifiers compare numerically); the comparator is exported separately for testing;cmd /d /s /c start gives the inner cmd a brand-new console — dodging the pitfall where detached: true equals DETACHED_PROCESS and a console program gets no console at all; macOS uses open -a Terminal; Linux tries x-terminal-emulator / gnome-terminal / konsole / xfce4-terminal in order, using a 250ms error-race to tell a "missing program" from a real launch, with late errors parked on a no-op listener so they can't take the backend down. The window is fully independent of the backend lifecycle, never managed or killed by it; you paste the commands yourself — the plugin never types for you.better-model-router (deliberately distinct from the original plugin, so the two can coexist);model_route tool (off by default): once enabled, the agent may switch the current session's model mid-conversation, strictly within combinations listed one by one in an allowlist, and every execution is re-validated live; with an empty allowlist no tool is registered; the chat stream shows a matching routing card;One page manages any number of tasks (capped at 20), each with its own name, switch, type, schedule, prompt, and target, sharing one delivery path. The scheduler runs entirely inside the dsh backend process — it keeps firing with the browser closed:
sessionController resume path and then injected — exactly equivalent to opening it in the web app and sending a message yourself; the accepted cost is that woken sessions stay resident;{time} placeholder (replaced with the delivery time) and fall back to a default patrol prompt when blank; messages carry a plugin source, the same delivery mechanism the official schedule reminders use;Three implementation notes:
better-scheduler ({ version: 2, tasks: […] }, capped at 20); saving uses a version-number optimistic lock and clearly reports conflicts when the config changed elsewhere; the host subscribes via scope.watch, so every task re-arms live after each save — no restart. Old single-task configs (separate heartbeat / fixed-time entries) migrate automatically into the task list on read — configured ones keep their original timers, never-configured installs migrate to an empty table;sessionController.resolveAgent (cold-resuming the standard way when a target is not in memory), then inject the user message via agent.followup; a main-workspace-root target matches live root sessions by cwd (capped at 5) and delivers to each. "Run once" on the page walks this very chain — an end-to-end rehearsal of the production delivery.The official build now ships its own (off by default since v0.4.1): dsh 0.1.2-alpha.1 includes a built-in turn navigator (the per-turn tick rail at the conversation's right edge). This feature became an optional enhancement — off by default, leaving the official navigator untouched; once enabled, the takeover is global: the official navigator stays hidden in every conversation, regardless of whether this feature's tick rail is currently on screen (in a session with fewer than two ticks or with messages not yet paged in, only this feature's rail stays dormant — the official one remains hidden); toggling off restores the official navigator everywhere, instantly. The toggle applies live — no page reload needed. Jumps default to the official mechanics (one instant position write, honored by the official scroll ledger — never dragged back by streaming output); an optional "Smooth scroll jumps" toggle in settings restores the pre-alpha.1 glide with its heartbeat guard (during active streaming it may occasionally need an extra beat to settle).
user / steering (mid-run interjection) chat node maps to one tick, aligned by a stable anchor key onto the rendered message row;ResizeObserver following layout changes; the currently-read position is computed synchronously on every scroll — deliberately no rAF, which freezes in backgrounded windows and would leave the active tick stale;nav element inside the official scroll container; the plugin's own rail carries a dedicated marker and can never be caught by its own rule;light-dark() to follow light/dark automatically; custom colors persist in browser-local localStorage and apply live.And something we're a little proud of: the UI follows dsh's original design language throughout — colors, radii, spacing and typography all come from the active theme's semantic tokens, with zero third-party styling. Whatever theme you switch to, it blends in like a built-in page.
Running into anything — install trouble, UI glitches, silent notifications, routing not kicking in… — or just have an idea? Please open an Issue; more reports are always welcome. The more specific the report (DSH version, OS, steps to reproduce), the faster the fix.
Until the official host reaches a stable release, this plugin supports exactly one host version: DSH 0.1.2-rc.1 (including post-rc.1 master builds that self-report this version). engines.dsh in package.json is pinned to this exact version, so dshmarket will flag every other host version as incompatible. The 0.1.3 alphas currently break core functionality (session history fails to display) — wait for the official stable release before upgrading the host.