working-activity

649Stars231Forks1Issues51Watchers

Real-time status bar plugin for DeepSeek Harness: collapses session events into playful thought text, showing currently running tools and elapsed time, delivered to both TUI prompts and web clients.

Language
TypeScript
License
MIT
Branch
main
deepseek-harnessdsh-pluginpi-coding-agentpi-pluginstatuslineworking-line

Install

$ dsh plugin --profile web add github:ccch1mneyyy/working-activity

Run the command above in your terminal to install this plugin via the dsh CLI. You can switch Profile in the top-right corner. New to dsh? Read the beginner tutorial

One-Line Pitch

The DeepSeek Harness real-time "working status line" plugin compresses model conversation events into user-friendly progress text—playful short phrases during thinking, "action + file/command + elapsed time" when running tools, and a wrap-up summary—delivered simultaneously to the TUI prompt and above the input area in the Web client.

Core Features

  • Folds conversation events (turn/start / assistant/chunk / tool/call / tool/result / turn/end) and agent/status into five-stage status (idle/waiting/thinking/tool/done), refreshing at 500ms ticks
  • Auto-maps tool names to playful verbs (翻翻文档/改改/跑个命令/搜搜东西/派个小弟 etc.), automatically extracting and truncating parameter details from path/command/query/url
  • Thinking text pool: ~95 Chinese colloquial short sentences + deadpan English (lol/hm/ok), rotating every ~4 seconds; late-night text mixed in during local time 00:00–06:00; thinking too long automatically tiered (30s / 1min / 5min)
  • TUI side: registers ${activity} template value in ctx.tuiPrompt, displayed via theme.leftPrompt
  • Web side: mounted as a slot plugin to conversation.input.dock, rendering a status line with stage-colored breathing dot + tool count badge above the composer
  • Optional injection of "⏵ Model Narration" convention into system prompt: lets the model write "⏵ What are you doing" at the first line of its response, the status line extracts this line in real-time, and filters it from the chat body
  • Wrap-up summary: 搞定 ✓ · N tools · Xs thinking Ys execution, the last cell briefly pins the most recent tool's snippet

Technical Implementation

  • Language: TypeScript (ESM, "type": "module"), Node-side tsc compiles to lib/, Web-side uses tsdown to output closure-factory bundle to lib/client.js
  • Key Dependencies: @deepseek-ai/cordis@^4.0.1, @deepseek-ai/dsh-session@^0.1.0-rc.6, @deepseek-ai/dsh-agent@^0.1.0-rc.6, @deepseek-ai/schemastery@^3.18.1
  • Architecture Pattern: Cordis host plugin (name: 'working-activity') + Web slot plugin (registered to conversation.input.dock, order 15) + invariant companion plugin (./invariant, uses dsh-invariants service to validate activity/status shape); self-mounting implemented via dsh.bundle.patch → cordis.patch.yml's - insert:
  • Entry Files: packages/activity/working-activity/src/index.ts (host plugin apply(ctx, config)) → src/status.ts (pure state machine ActivityTracker, clock-injected) → src/client/index.ts (Web slot apply(ctx), registers WorkingLine) → src/invariant.ts (validation companion)

Use Cases

DSH users want to see what the model is doing during long tasks—whether it's still thinking, stuck in thought, or running npm install—instead of just staring at a spinner. At a glance see elapsed time and the file/command being operated on during long tool execution; at wrap-up see the breakdown of thinking vs. execution time for peace of mind. Most straightforward with dsh-cc terminal's status bar or official Web client, also supports custom any consumer subscribing to activity/status events.

Prerequisites & Compatibility

DependencyMinimum VersionDescription
DeepSeek Harness0.1.0-rc.6+Locked by multiple @deepseek-ai/dsh-*@^0.1.0-rc.6 in peerDependencies
Node.js^22.19.0 || >=24.0.0Declared in engines.node; CI uses Node 24
pnpm10+ (11+ recommended)dsh plugin add forwards to pnpm; pnpm 9 transitive dependency resolution issues cause module resolution failures
PlatformmacOS / Windows / LinuxCross-platform, pure JS/TS implementation, no native modules
Native ModulesNoneNo node-gyp build dependencies
Web Additional RequirementOfficial rc.6 source repo with patches/webui-working-activity.patch appliedWeb side needs this runtime patch to wire activity/status into ConversationSnapshot; installs without it but status line stays empty
Required CredentialsNoneStatus line purely local derivation, no API key reading, no network requests

Installation

dsh plugin --profile web add github:ccch1mneyyy/working-activity

The install command itself only fills in the GitHub shortlink when publishing the repo root npm package. The actual package name dsh-working-activity is fixed (depended on by dsh-cc-tui), please confirm package.json#repository points to this repo before publishing.

Configuration Options

All tunable parameters are centralized in the Config Schema (packages/activity/working-activity/src:36), override by id at the profile user patch layer:

ConfigTypeDescriptionDefault
phrasesbooleanPlayful text pool switch; after disabling renders plain functional labels (思考中 · 总1m23s)true
publishbooleanAppends activity/status session events for Web / dsh-cc consumption. Default off: after enabling, sessions with status lines cannot be resumed (session.append() doesn't support ignorable)false
tickMsnumberStatus line render tick interval (ms), range 100–5000500
publishIntervalMsnumberMinimum interval between two publishes when status line is stable (ms), range 500–30000; dsh-cc recommends 5002000
detailLimitnumberMaximum display length for tool details (path/command/search pattern character count), range 8–12040
customActionsobjectExact tool name mapping to action text pool, e.g. {"my_deploy":["部署一下","上线中"]} (case-insensitive){}
narratebooleanInjects "⏵ Model Narration" convention into system prompt; after disabling only derived from eventstrue

FAQ

Q: I installed the Web side following the official dsh README, but the working status line doesn't appear above the composer.

A: This package's slot plugin only contributes registration to conversation.input.dock. To make Web actually render it, a runtime patch is needed to wire activity/status events into the ConversationSnapshot.activity field. Run git apply <this-repo>/patches/webui-working-activity.patch in your official rc.6 source repo root (already verified via git apply --check). Before the patch is merged, Web side won't error, it's just the WorkingLine component always returns null.

Q: I can't see ${activity} displayed in TUI, what should I do?

A: If ${activity} isn't added to the template, the template renderer omits it. Need to add it to dsh-tui's theme.leftPrompt in the profile user patch layer ($DSH_HOME/profiles/<profile>/cordis.patch.yml): '${cwd}${git/worktree}${activity}${model}${token_meter/cache_hit_rate}${context}'. Also confirm the profile has both dsh-tui and this plugin packages installed.

Q: After enabling publish: true, historical session resume fails. Why?

A: The current DSH version's session.append() cannot mark events as ignorable, the resume read path rejects unknown non-ignorable event types. After enabling publish, any session that rendered a status line gets an activity/status, the entire log resume errors. Only enable when host supports ignorable append AND your consumer is a log-replay-based UI; normal Web UI uses the conversation.input.dock slot with real-time events, doesn't need publish.

Q: I have my own tool (like an internal deploy tool), want the status line to show "部署一下 staging".

A: Configure the action pool for exact tool name in customActions: {"my_deploy":["部署一下","上线中"]}. Matching is case-insensitive exact match by tool name; if not matched, falls back to built-in mappings like "翻翻文档/改改/跑个命令/派个小弟"; unrecognized tools fallback to "干活/调用/整一下".

Q: The status line seconds tick too slowly, not responsive enough for long tools.

A: Set publishIntervalMs to 500 (default 2000), letting "stable lines" also republish every 0.5s—the elapsed time number then ticks continuously. Modify the config for the corresponding id in the profile user patch layer: { id: working-activity, config: { publishIntervalMs: 500 } }, don't insert another line with the same id (causes dual instances).

Q: Does uninstalling the plugin modify DSH core? Will I lose sessions?

A: No. This plugin is pure mounting, doesn't modify any DeepSeek Harness source code; uninstallation restores immediately. Session logs remain at original paths in the profile's sessions directory. activity/status events don't affect other event types—it's just that its existence causes resume failures during periods when publish is enabled (see above).

Q: Works on macOS / Windows / Linux? Need extra system dependencies?

A: Cross-platform usable, no native modules, no node-gyp dependencies. pnpm install && pnpm run build works on all three systems. Note on Windows: the dsh plugin forwarded pnpm command goes through cmd, don't call directly from Git Bash.

Ease of Use

Beginner — dsh plugin add one command installs and works out of the box; status line visible on TUI side with default config, Web side needs one additional git apply. Common tuning only involves publishIntervalMs one parameter.

Known Issues & Limitations

  • publish defaults off: After enabling, sessions that rendered status lines cannot be resumed (session.append() doesn't support ignorable; src/index.ts:38-46 / registration.ts:9-13).
  • Single active status line: Plugin maintains one status line per session; TUI slot displays the most recently active session, only seeing the latest line when multiple sessions run in parallel (README.md:118).
  • No tool progress percentage: DSH has no tool progress events, long tools only show elapsed time, no "remaining ~11s" like the pi version (README.md:120).
  • No animation frames: TUI slot renders static text fragments; pi version's moon/comet/braille animation presets need to wait for prompt slot contract to support frame callbacks before implementation (README.md:121).
  • Web side needs runtime patch: ConversationSnapshot.activity field is wired into official rc.6 runtime via patches/webui-working-activity.patch; if official merges that field into the release line, the patch retires, host remains compatible after upgrade (src/client/activity.ts:8-15).
  • Web dual entry: Input area WorkingLine and chat area TurnStatus render the same snapshot; dock entry covers all stages, the old patch's turn-level label no longer exists separately (README.md:122 / docs/dsh-working-activity.md:205-206).
  • narration is injection convention not protocol: Model narration's "⏵ What are you doing" depends on model complying with the system prompt segment appended at before_agent_start; models that don't support that convention or don't output it won't see this line (src/index.ts:93-94 / src/status.ts:472-480).
  • DSH prompt facet not differentiated: Plugin injecting narration convention into system prompt adds a small amount of tokens; fixed and small (single text segment), no impact on cache stability, but resent every round (README.md:103-105).