dshbase

插件目录 / Developer / dsh-elf

dsh-elf

已验证 · 实测可装 winditer

✓ 持续维护

查看 GitHub ↗ ← 返回插件目录

0Stars
0Forks
0未关闭 issue
—语言
2026-08-19最近推送
跨平台平台

功能简介

A temporary dialogue elf designed specifically for DSH

✅
我们的评价
可用 — 实测通过,早期项目

A temporary dialogue elf designed specifically for DSH 实测能干净安装、正常启动。早期项目,但功能可用。

「已验证」表示我们的自动化 CI 在干净 profile 里实际执行了 dsh plugin add 并启动成功——仅此而已。功能描述与版本兼容性均为作者声明。这不是安全审计,也不代表对第三方代码的背书。

README

dsh-elf logo

dsh-elf

English | 中文

License: MIT
Node
npm

A DeepSeek whale elf that lives on your DSH page. A translucent, slowly drifting whale (rendered from the official DeepSeek favicon path, tinted blue → purple → green) hovers at the edge of the viewport; click it to open a lightweight, draggable chat window that never touches your session history.

Screenshots

The whale elf hovering at the corner of the page The temporary chat window opened by clicking the elf

Features

  • Living elf — the whale slowly wanders around its anchor point (sin/cos drift plus a bob animation); drag it anywhere and the position persists across restarts
  • Instant chat — click to open, drag the title bar to move, — to minimize back to the elf
  • Zero-config by default — follows the session's default model (the harness's configured provider), no API key required
  • Custom endpoint mode — uncheck "follow session default" and plug in any OpenAI-compatible endpoint (DeepSeek / OpenAI / Moonshot / GLM / Qwen / custom base URL), streamed token-by-token directly from the browser
  • Real streaming — host-route chats poll the streaming response (~55 ms) so text appears as it is generated; custom endpoints use native SSE
  • Nice-to-haves — copy per message, one-click clear, model badge, light/dark theme, empty-state hint, drag clamping (you can't lose the elf off-screen)
  • Follows your language — the elf UI switches between 中文 / English automatically, matching the language setting in DSH; no reload needed

Requirements

  • DSH with a web or desktop profile
  • Node.js ^22.19.0 or >=24.0.0 (only needed to build from source)
  • pnpm is recommended when installing into a profile

Install

The bundle entry (id: elf) is self-declared by this package's cordis.patch.yml —
no manual patch file is needed.

From npm

dsh plugin --profile desktop add dsh-elf

Restart DSH (quit fully and reopen), then a fresh page shows the elf at the bottom-right.

From git

Installing the plugin directly from the repository (e.g. "dsh-elf": "github:winditer/dsh-elf" in a
profile's package.json) also works out of the box: the built client bundle is committed, so the
codeload tarball a git install downloads already contains dist/client.js and no build step is needed
on the consuming side. (This was not always true — the bundle used to be gitignored, which made the
plugin tree fail to load with client bundles not found; run pnpm run build before launch.)

From source (development)

git clone https://github.com/winditer/dsh-elf.git dsh-elf && cd dsh-elf
npm install
npm run build          # produces dist/client.js
dsh plugin --profile desktop add .    # links the workspace into the profile by package name

Or install by hand: in the target profile's package.json (e.g. ~/.dsh/profiles/desktop/package.json):

{
  "dependencies": {
    "dsh-elf": "link:/absolute/path/to/dsh-elf"
    // ...
  },
  "dsh": {
    "profile": {
      "bundles": [ /* ... */, "dsh-elf" ]
    }
  }
}

then pnpm install inside the profile directory and restart DSH.

Uninstall

Remove dsh-elf from the profile's dependencies and dsh.profile.bundles, then clean up the installed link (rm -rf <profile>/node_modules/dsh-elf or pnpm --filter dsh-elf remove --dir <profile>).

Usage

  • Drag the elf to park it anywhere (the drop position is persisted under dsh-elf:orb); click (without dragging) to open the chat window
  • Chat header: model badge · ⚙ configuration · — minimize · 清空 clear
  • Enter sends, Shift+Enter inserts a newline; hover a message and click 📋 to copy
  • Chats are temporary: they are never written to DSH sessions and disappear when the plugin stops or you clear them

Configuration

Open ⚙ in the chat header:

Setting Meaning
跟随会话默认 (follow) On: use the harness's session-default model automatically. Off: enable the fields below
提供方 (provider) Preset for the OpenAI-compatible base URL
API 地址 / API Key / 模型 Base URL, key, and model name for the custom route
reasoning Optional reasoning_effort (high / medium / low) for compatible models

Settings are saved in the browser's localStorage (dsh-elf:cfg) together with chat history, positions and window mode (dsh-elf:chat / dsh-elf:orb / dsh-elf:win / dsh-elf:mode).

Architecture

Two halves, one package:

  • Host half — lib/index.js (= src/host.js). Registers a JSON API at /dsh-elf/api through the harness webServer service; runs the session-default chat via llm.stream; chats live in an in-memory Map that is cleared when the plugin unloads.
  • Client half — src/client.js, bundled to dist/client.js (esbuild, wrapped in __ModuleLoader__.load({ id: "dsh-elf", … }); the id must equal the installed package name). Renders into the shell.overlay slot, talks to the host with fetch POSTs.

Host API

All endpoints are POST /dsh-elf/api/<method>; every response is { ok: true, value } or { ok: false, error }.

Method Body Returns
elf.sessionModel {} { available, provider?, model?, reasoningEffort? } — the session's default model
elf.chat.start { messages: [{ role, text }] } { ok, chatId } or { ok: false, error }
elf.chat.poll { chatId } { ok, done, text, error? } — accumulated text while streaming; done: true at the end
elf.chat.close { chatId } { ok }

Protocol details: only POST is accepted (405 otherwise); the body is JSON with a 1 MB cap (413); unknown methods return 404.

Security notes

  • Default route sends no credentials — it reuses the harness's configured provider.
  • The custom-mode API key stays in your browser (localStorage), never on disk or over the wire to anything but the endpoint you configured.
  • Chats are ephemeral and in-memory; nothing is written to DSH session history.

Development

npm run build   # esbuild: src/client.js → dist/client.js (__ModuleLoader__ bundle)
npm run check   # node --check on both halves
npm test        # node --test (host mount regression + client bundle guards)

Project layout

src/client.js      Client half (shell.overlay, plain browser timers, fetch → /dsh-elf/api)
src/host.js        Host half source (= lib/index.js, the Node entry)
lib/index.js       Package main — host half, loaded by the DSH host runtime
dist/client.js     Built client bundle (__ModuleLoader__ format, load id = dsh-elf)
cordis.patch.yml   Bundle entry declaration (insert: { id: elf, name: dsh-elf })
scripts/build.mjs  Build script (esbuild + bundle wrapper)
test/              node:test suites
assets/            Logo / whale artwork

Gotchas (learned the hard way)

  • Bundle id must equal the package name — arrive() throws bundle loaded without registering <id> otherwise. scripts/build.mjs hardcodes the correct id.

  • Profile bundles don't get the cordis timer service — that service is installed only for dynamic cordis-runner packages. Use plain browser setInterval/setTimeout (disposed in React effect cleanup), exactly like the sibling dshmarket bundle.

  • Prefer link: over file: when installing a workspace copy — file: copies files, so edits/rebuilds go stale.

  • Client changes go live on page refresh (bundle rev is content-hashed); host changes require a full DSH restart.

  • Fresh publishes can trip the profile's minimumReleaseAge policy — if the profile enforces pnpm's release-age supply-chain check, a version published less than ~24 h ago fails dsh plugin … add <pkg> with ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION. Add the exact name@version to minimumReleaseAgeExclude in the profile's pnpm-workspace.yaml (and keep the entry current when you release a new version):

    minimumReleaseAgeExclude:
      - [email protected]
    

License

MIT

安装

🧩 让 Agent 自动装(推荐)

装一次目录插件,之后本站所有插件都能让 DeepSeek Harness 自动找、自动装:

dsh plugin add dshbase-catalog

然后对 agent 说「帮我装 dsh-elf」,它会在目录里找到并自动安装。文档:dshbase-catalog · 已验证场景包。

该插件是 GitHub 源码(未发 npm)——直接从仓库装:

Web profile:

dsh plugin --profile web add github:winditer/dsh-elf

Headless(CLI)profile:

dsh plugin --profile headless add github:winditer/dsh-elf

实测报告

验证通过:从 GitHub 源码完成 L1 安装 + L2 加载 + L3 运行(dsh 0.1.0-rc.6)。

安全:尚未扫描——我们的每日静态扫描将很快覆盖它。

分享徽章

Developer 里更多

浏览全部 7819 个插件 →