DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Tab Status Dot — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
T

@pxy/dsh-tab-status-dot

Tab Status Dot

DeepSeek Harness 网页客户端插件:实时浏览器标签页图标状态点——会话在你离开期间完成时显示浅绿色,会话等待你选择时显示浅蓝色,两种状态同时存在时显示两个点;支持识别隐藏标签页,并在重新加载后保留提醒。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:linksdeact-sys/dsh-tab-status-dot#fca57c9ea5b423c780ef689ee95eff8b831fc20d
README兼容性版本

兼容性与来源证明

Tab Status Dot 以 @pxy/dsh-tab-status-dot 发布,当前版本为 0.1.4。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/9/12

版本

0.1.4stable
2026/9/12

相关插件

正在加载相关插件…

最新版
0.1.4
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
github
GitHub
★ 0
周下载
0
最近提交
2026/9/12
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 ui-customization 分类下经过校验的插件。

Whale Widgetdsh-whale-widgetDSH Web 界面右下角的 DeepSeek 余额小鲸鱼挂件:余额/今日已用/峰谷定价、自定义泡泡点击序列(文本/余额/今日/峰谷/图片/随机语句与并列加权选择)、逐行样式与字体、悬浮快捷编辑、音效与每轮消耗、自定义角色/动图/音效、吸附与翻转自定义Deepseek Idesigndeepseek-idesign作为原生 DeepSeek Harness 对话视图的 iPolloWork Design Studio 及其精选设计模板。Deepseek Ipptdeepseek-ipptiPolloWork PPT Studio 及其精选幻灯片模板,作为原生 DeepSeek Harness 对话视图。Genui@changfenhuang/dsh-genuiGenUI for DeepSeek Harness:通过 ```dsh-ui``` 代码围栏在助手回复中内嵌渲染交互式 UI 组件——布局、图表、绘图、表单、测验、mermaid、3D 场景,以及回传模型的操作事件循环。随附教授代码围栏的主机插件

README

dsh-tab-status-dot

A tiny browser-side plugin for the DeepSeek Harness Web GUI (dsh web) that shows a status dot as the browser-tab favicon, telling you at a glance whether any conversation has finished while you were away, or is waiting for you to make a choice.

No page-title text is modified — the indicator lives entirely in the tab icon (favicon), where size and colour are fully controllable.

New to this? Read the beginner-friendly Getting started (中文版) — step-by-step for Windows, Linux and macOS, no coding required.

states

States

FaviconMeaningReturns to neutral when
Neutral dotDefault / a task is currently running—
Light-green dot≥1 session finished running while you were not looking (tab in background, or viewing another session)You open that session; if it was already the open session, staying on the page ≈1 s counts as read. Every unfinished "viewed" item must be handled before the dot returns to neutral
Light-blue dotA session is waiting for your choice (question / approval / plan review) — not answered yetOnly after you actually answer/choose and the run resumes; merely viewing does not clear it
Two light dots (green + blue)Both conditions above exist at the same timeGreen clears by viewing; blue clears by answering

Rules

  • A session finishing while you are looking at the page and at that session does not light up (you saw the result).
  • A session finishing while the tab is hidden/backgrounded lights up green even if it is the currently open session — you were not actually watching it.
  • Running again, or deleting the session, removes its stale reminder.
  • Unviewed completions persist in localStorage, so a page reload does not lose them.

Why it exists

The runtime's built-in model treats "session selected" as "viewed" — so a task finishing in the open session while the tab was hidden never produced a reminder. This plugin redefines "you were not looking" as session not selected or page hidden, which matches how people actually use the app (start a task → switch away → come back).

How it works

  • Registered as a dual-face cordis plugin (dsh.client, platform: web): the host half (lib/index.js) is an empty apply, the browser half (exports["./client"] → lib/client.js) is a classic-script module-loader bundle.
  • Subscribes to the sessions service (ctx.get("sessions").list), an observable snapshot carrying per-session running, completed and the open-session current id.
  • Pending operator choices come from the runtime's own source: on DSH 0.1.5-rc.1+ that is uiSession.pendingInteractions (an observable Map<SessionId, interaction>); on older versions the per-summary pendingInteraction field is scanned instead. Both paths are supported.
  • Completeness signals: the runtime's own completed flag plus our own running→idle edge detection plus a "page was hidden since last visible observation" flag — so reminders are armed even when the browser throttles background timers and the transition is only observed after you return.
  • Background resilience: browsers suspend requestAnimationFrame (and some event delivery) for hidden tabs, so the plugin also
    • polls the cheap cached snapshot every second,
    • paints through a short-timeout fallback as well as rAF,
    • refreshes immediately on visibilitychange / window focus.
  • Rendering is coalesced & change-checked: at most one DOM write per frame, raw-string favicon comparison (never the normalized .href read-back), no writes when nothing changed.
  • Takes over the favicon (<link rel=icon>) so browsers do not pick a competing brand icon; the original icon is restored on unload.

Compatibility

DSHStatus
0.1.5-rc.1 (current)Supported — sessions from @deepseek-ai/dsh-api-session-controller, pending from uiSession.pendingInteractions.
≤ 0.1.0-rc.xSupported — sessions from the then-current runtime, pending scanned from the session summary.

The plugin deliberately declares no package-name inject edges (dsh.client.inject), only the service name it needs (exports.inject = ["sessions"]). Package names move between DSH releases (the sessions runtime itself moved in 0.1.5-rc.1), and an edge naming a package that no longer exists silently prevents the row from ever materializing — which is exactly how the indicator went dark. Waiting on the service name is stable across versions.

After installing or updating the plugin, restart dsh web (and reopen the URL it prints). The client module registry caches package metadata per specifier until restart, so a page refresh alone will not pick up a changed package.json.

Requirements

  • DeepSeek Harness with a web profile (see the runtime's profile/plugin conventions), any modern browser.

Installation

How plugin deployment works in DeepSeek Harness

Every DSH surface is a profile directory ($DSH_HOME/profiles/<name>, e.g. ~/.dsh/profiles/web). A plugin only has to satisfy two things:

  1. the package is resolvable from the profile — i.e. it lives in <profile>/node_modules/<package-name> (pnpm installs there, but a plain copy works just as well);
  2. the profile registers a loader row for it — either the package's own bundle patch (see below) or one insert entry in <profile>/cordis.patch.yml naming the package.

After that the instance composes the row and serves the client bundle. Current DSH caches package metadata until the process restarts, so restart dsh web after installing or changing package.json and open the (authenticated) URL it prints; only lib/client.js content changes need just a page refresh.

This package is an official-form plugin (and a bundle)

Per the DSH documentation, every capability is a plugin row in a cordis.yml, and a package can ship a bundle patch layer that adds its own row:

dsh: {
  bundle: { patch: "./cordis.patch.yml" },   // this package's row lives here
  client: { platform: "web" }                // dual-face client plugin (./client export)
}

That gives two equivalent activation routes — use exactly one:

RouteHowNeeds
A. Bundle (official CLI route)dsh plugin --profile web add github:linksdeact-sys/dsh-tab-status-dot, then add "@pxy/dsh-tab-status-dot" to dsh.profile.bundles in <profile>/package.jsonpnpm (the dsh plugin command forwards to it)
B. Scripts / manual copyinstall.ps1 / install.sh (or a plain copy into node_modules) + the insert row in <profile>/cordis.patch.ymlnothing

Why not a dynamic Cordis plugin? DSH also offers runtime plugins defined through the cordis_* tools, but the official authoring guide forbids them from touching the page directly ("Do not manipulate document.body, window, or hard-coded product DOM selectors"). A tab-favicon indicator inherently needs exactly that, so it must be a packaged client bundle like this one.

Verified installers. CI exercises them on four real environments — ubuntu-latest (where sh is dash), macos-latest (BSD userland), Alpine/BusyBox sh, and windows-latest (Windows PowerShell 5.1). Each job installs into a profile shaped exactly like the shipped template (comment header + bare [], no trailing newline), validates the resulting YAML with js-yaml, and checks the idempotent, append-to-existing-entries and uninstall paths. A separate job validates these package conventions (test/bundle.test.mjs), so a metadata regression cannot silently disable the plugin again.

Method 1 — install script (recommended)

# Windows (PowerShell)
git clone https://github.com/linksdeact-sys/dsh-tab-status-dot.git
cd dsh-tab-status-dot
powershell -ExecutionPolicy Bypass -File .\install.ps1
# macOS / Linux
git clone https://github.com/linksdeact-sys/dsh-tab-status-dot.git
cd dsh-tab-status-dot
./install.sh

The script copies the package into the web profile, appends the registration block to cordis.patch.yml (idempotent, keeps a .bak backup), and prints the next steps. Options: -Profile <name> / --profile <name>, -DshHome <path> / --dsh-home <path>, --uninstall.

Method 2 — package manager (dsh plugin)

If pnpm is available, the official route installs straight from GitHub into the profile:

dsh plugin --profile web add github:linksdeact-sys/dsh-tab-status-dot

…then register the row by appending this to ~/.dsh/profiles/web/cordis.patch.yml:

# >>> dsh-tab-status-dot >>>
- insert:
    - id: tab-status-dot
      name: '@pxy/dsh-tab-status-dot'
# <<< dsh-tab-status-dot <<<

Method 3 — manual copy

Download the release zip (or copy from a clone) so the profile ends up with:

<profile>/node_modules/@pxy/dsh-tab-status-dot/
├── package.json
└── lib/
    ├── index.js
    └── client.js

and add the same insert block shown in Method 2 to <profile>/cordis.patch.yml.

Verify

  1. Refresh the Harness page — hard refresh (Ctrl+F5) if the old bundle was cached.
  2. The tab icon shows a neutral dot. Start a task and switch to another page: when it finishes while you are away the dot turns light green; a question/approval waiting for you turns it light blue.
  3. Optional server-side check: GET http://127.0.0.1:3080/plugins/@pxy/dsh-tab-status-dot/client.js returns 200.

Uninstall

powershell -ExecutionPolicy Bypass -File .\install.ps1 -Uninstall   # Windows
./install.sh --uninstall                                           # macOS / Linux

or delete <profile>/node_modules/@pxy/dsh-tab-status-dot and the insert block by hand.

Troubleshooting

SymptomFix
Nothing appears after refreshMake sure cordis.patch.yml holds the insert row with the exact package name, then hard-refresh; if your instance does not hot-reload patches, restart dsh web once.
GET /plugins/.../client.js returns 404The row is not registered in the running instance (patch layer not applied), or the package is not in the profile's node_modules.
dsh plugin … add failspnpm is missing/unavailable — use Method 1 or 3; neither needs a package manager.
Page looks broken after installingRemove the row from cordis.patch.yml (or run the uninstaller) and refresh: the plugin unloads completely, including its favicon override.

See INSTALL.md for the original step-by-step notes and operational details.

Development

├── package.json          # dsh.client declaration (platform=web, injects client-runtime)
├── lib/
│   ├── index.js          # host half: empty apply (pure client plugin convention)
│   └── client.js         # browser bundle: module-loader factory + state machine + renderer
└── test/
    ├── core.test.mjs         # pure-logic cases + node:vm sandbox smoke test (no CJS globals)
    └── browser.e2e.mjs       # real-browser E2E (Playwright) + browser/fixture.html kernel stub

Unit tests (no dependencies)

node test/core.test.mjs        # or: npm test

The harness evaluates client.js inside a node:vm sandbox that provides only browser-ish globals (window, document, localStorage) — the same conditions the DSH module loader creates — so a missing CommonJS-style wrapper (exports is not defined) or any load-time crash is caught before it ever reaches a real page.

Browser E2E (Playwright)

# Locally, reusing an installed Chrome/Edge (no browser download):
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm install --no-save --no-package-lock playwright
PW_CHANNEL=msedge node test/browser.e2e.mjs

# Or with Playwright's own Chromium:
npm install --no-save --no-package-lock playwright
npx playwright install --with-deps chromium
node test/browser.e2e.mjs      # or: npm run test:e2e

test/browser/fixture.html stands in for the DSH kernel: it captures the bundle's __ModuleLoader__ registration and exposes a controllable fake sessions service. The test then drives real conversation state and asserts the favicon the browser resolves: neutral → light green (finished while you were away) → cleared on open; green for a hidden-tab finish of the open session plus its ~1 s read-dwell auto-clear; light blue while a choice waits and its clearing on answer; two dots when both hold; the reminder restored after a page reload; and full cleanup on disposal. It also fails on any page or console error.

Edit lib/client.js → refresh the page to test live (the bundle is served no-cache).

Notes & limitations

  • Browser tab titles are plain text: a coloured dot there can only be an emoji, whose size/colour are fixed. That is why state colours live in the favicon and the page title is left untouched.
  • Reminders are per-browser (localStorage); two browser tabs of the same profile share storage with last-write-wins semantics.

License

MIT