Back to marketplace

dsh-thinking-notifier

UI & Experience

6-debug-6/dsh-thinking-notifier

A popup plugin that shows when DeepSeek has finished thinking or is requesting permission during split-screen, with always-on-top desktop notifications.

  • dsh-plugin
GitHub Stars
4GitHub
Views
1DSH Plugin Hub
Forks
0GitHub
Open issues
0GitHub Issues
Manifest version
1.2.0dsh-thinking-notifier
Latest push
Oct 7, 2026GitHub
License
MITJavaScript
Plugin type
HostRuns in the DSH Host

Verification and compatibility

This section shows evidence collected by the catalog. Undeclared information is labeled as unknown.

Static checked
01Exact source: github · dsh-thinking-notifier@1.2.002Validated: Aug 24, 202603Verified Harness: 0.1.0-rc.7
Current-version compatibility
Verified on the catalog Harness version
Declared Harness range
Not declared
Declared platforms
Not declared
Profiles
web
Build approval
Unknown
Permissions
Not declared
External services
Not declared
Telemetry
Unknown
No known risk flags found

This is not a security endorsement. Review source, permissions, and configuration before installing.

View evidence and scope

Verification covers only the named source, version, and Harness environment. It does not guarantee future compatibility.

  • github:6-debug-6/dsh-thinking-notifier#d97ab09f21568e22b47e02d036ef678212d2d137
  • The manifest and static structure passed checks; a runtime load check has not completed.

README

View source

dsh-thinking-notifier

A DeepSeek Harness (DSH) plugin that shows a small always-on-top desktop popup in the bottom-right corner of your screen. It mirrors the AI's thinking status in real time and alerts you when the AI requests permission, waits for a choice from you, or finishes thinking — even when you are working in other apps, browsers, or virtual desktops.

中文说明见 README.zh.md

Features

StatePopupSound
AI is thinkingDeepSeek-blue pulsing dot + AI 正在思考… + elapsed time. Auto-collapses to a 25 px slim right-edge tab after 5 s; hover or click the tab to expand it againnone
AI waits for your choiceViolet pulsing dot + AI 正在等待你的选择 + the question heading, the first question's option labels (选项:A / B, (可多选) for multi-select, (共 N 问) when several questions arrive at once) and how long it has been waiting. Stays expanded until you answersystem Question
AI requests permissionAmber pulsing dot + AI 请求权限 + session/tool name. Stays expanded until you decidesystem Exclamation
AI finished thinkingGreen dot + AI 已完成思考, auto-hides after 12 ssystem Asterisk
IdleHiddennone
  • DeepSeek-style dark card (#1E2235 / #4D6BFE).
  • Always-on-top frameless window, bottom-right, visible over any application.
  • Auto-collapses into a 25 px slim right-edge tab after 5 s while the AI is thinking, so it stays visible without blocking desktop controls.
  • Hover or click the edge tab to expand it manually; new turns, questions, permission requests, and completions expand it automatically.
  • Click the X button to dismiss the current popup; the next new turn, question, permission request, or completion will show it again.
  • Questions are shown with their options, which is enough to know what is being decided; the answer itself is still given in the DSH Web UI (the popup is read-only by design).
  • Multiple sessions are summarized automatically.
  • The popup process stays alive while DSH runs; it exits ~15 s after the status endpoint becomes unreachable.
  • No browser extension required; the popup is a native desktop window.

How it works

DSH process
  └─ lib/index.js (host plugin)
       ├─ listens to session/event: turn/start, turn/end, approval/asked, approval/decided, session/title
       ├─ rebuilds existing session state from ctx.sessions.list() at startup
       │    (a session whose log ends inside an open turn is treated as not running)
       ├─ wraps ctx.userQuestions.ask to observe ask_user_question
       │    (that state produces no session event, and a second UI provider cannot be registered)
       ├─ serves a local status JSON at http://127.0.0.1:7389/status
       └─ launches the desktop popup process
             ├─ Windows: desktop-popup.ps1 (PowerShell + WPF)
             └─ macOS/Linux: desktop-popup.py (Python 3 + tkinter)

Desktop popup
  ├─ polls /status every second
  ├─ renders the DeepSeek-style card (question/pending/running/done/idle)
  ├─ plays a system sound on question/pending/done transitions
  ├─ auto-collapses to the right edge while running; stays expanded while waiting for you
  └─ hides while idle, keeps running in the background

Status JSON

GET http://127.0.0.1:7389/status returns:

{
  "ok": true,
  "mode": "question",
  "statusText": "AI 正在等待你的选择",
  "sessionText": "Choose Mode",
  "detailText": "选项:样式 A / 样式 B(可多选)",
  "timeText": "已等待 00:12",
  "pendingKind": "question",
  "pendingTool": null,
  "runningSince": null,
  "doneAt": null,
  "questionCount": 1,
  "questionSince": 1791374946369,
  "appUrl": "http://127.0.0.1:3080",
  "now": 1791374946369
}

mode priority: pending (an approval is waiting) > question (a question is waiting) > running > done (shown for 12 s) > idle. pendingKind is approval or question. timeText is the thinking timer while running and the waiting time while question; detailText carries the first question's options.

Installation

From a local checkout

cd dsh-thinking-notifier
dsh plugin --profile web add .

# Restart DSH web so the host plugin is loaded
dsh web

From npm (once published)

dsh plugin --profile web add dsh-thinking-notifier
dsh web

Uninstall

dsh plugin --profile web remove dsh-thinking-notifier

Configuration

Environment variableDefaultDescription
DSH_THINKING_NOTIFIER_PORT7389Local status server port. If busy, the next 10 ports are tried.
DSH_THINKING_NOTIFIER_NO_POPUPunsetSet to 1 to run the status server without launching the desktop popup (headless, tests).

Requirements

  • DeepSeek Harness Web UI (dsh web)
  • Node.js ^22.19.0 || >=24.0.0
  • Windows: Windows 10/11 with PowerShell 5.1+ (built in)
  • macOS/Linux: Python 3 with tkinter

Verification status

Being explicit about what has actually been tested, so nobody is surprised:

AreaStatus
Thinking / done states, popup geometry, sounds, single instanceverified on Windows 10/11 (PowerShell 5.1 + WPF)
Question state (ask_user_question)verified end to end in a live DSH session (a real question drove the popup into the waiting state, and it cleared when the answer arrived), against the real ctx.userQuestions service in a cordis context, and by the smoke test
Permission alert (amber)verified only with the mock status service. On a Windows DSH install without a confining sandbox, an out-of-workspace write is not intercepted, so no approval is raised by the runtime; the request only appears when a tool call explicitly asks for a sandbox_permissions escalation or a pre-execute hook returns ask
desktop-popup.py (macOS/Linux)never run on real hardware — syntax-checked only
Popup process stacking after repeated dsh web restartsthe launcher kills stale popups for its own port before starting a new one; verified for a single restart cycle

Development

# status-machine smoke test (fake cordis context, no popup, port 17389)
npm test

# render the popup against a mock status service, on a spare port
node tools/mock-status.mjs question --port 17389
powershell -NoProfile -ExecutionPolicy Bypass -File desktop-popup.ps1 -Port 17389   # Windows
python3 desktop-popup.py --port 17389                                               # macOS/Linux

Use a spare port for popup experiments: the real popup on 7389 is left alone, because the plugin only cleans up popup processes belonging to its own port.

Project structure

dsh-thinking-notifier/
├── lib/
│   └── index.js          # host plugin: state machine + status service + popup launcher
├── desktop-popup.ps1     # Windows native popup (PowerShell + WPF)
├── desktop-popup.py      # macOS/Linux native popup (Python 3 + tkinter)
├── cordis.patch.yml      # DSH bundle patch for persistent mounting
├── test/
│   └── status-smoke.mjs  # status-machine smoke test
├── tools/
│   └── mock-status.mjs   # mock status service for offline popup testing
├── package.json          # npm package + dsh.bundle declaration
├── README.md             # English readme
├── README.zh.md          # Chinese readme
├── CHANGELOG.md
├── CONTRIBUTING.md
└── LICENSE

Troubleshooting

Debug logs are written to:

  • ~/.dsh/tn-plugin.log — host plugin lifecycle, popup launcher, question watcher.
  • ~/.dsh/tn-launcher.log — PID of the popup process created by the launcher.
  • ~/.dsh/tn-popup-debug.log — popup script lifecycle and polling errors.

If the popup does not appear after restarting dsh web, check those logs first. Note that popup launcher exit: code=0 in tn-plugin.log is expected: the plugin spawns a one-shot launcher which starts the real popup process and then exits.

License

MIT

Comments

0
Newest first