deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
English | 中文
Persistent browser plugin for the DeepSeek Harness 3D whale desktop pet.
The plugin registers one additive whale-pet entry in shell.overlay. It renders the procedural whale directly with the bundled three@0.147.0; it does not use a CDN, an iframe, a host RPC, or a workspace-absolute path.
requestAnimationFrame loop.Ctrl/Cmd + Alt + W — toggle the pet's visibility from anywhere;
the shortcut works even when the pet is hidden.localStorage (guarded against private mode), and
the recap tracks the days you have spent together.The right-click "和鲸鲸聊天…" entry opens an inline input bubble next to
the pet (Enter to send, Esc/outside click to close; 200-character input, no
transcript UI), and the pet replies in its speech bubble. Replies stream in
when the host supports SSE (Accept: text/event-stream); the same bubble
grows as tokens arrive instead of popping a new one per delta. The bubble
carries a model selector and a reasoning
effort selector: the model list comes from the DSH LLM service
(GET /api/whale-pet/models), and models that expose multiple reasoning
levels (e.g. deepseek-reasoner low/high) show an effort dropdown. Choices
persist to localStorage (dsh.whale-pet.chat-prefs.v1) and ride along with
every request.
Architecture: the browser pet never talks to an upstream LLM directly — the
host-side entry of this package registers the /api/whale-pet prefix on the
web server, and the client calls the same-origin POST /api/whale-pet/chat
endpoint. The API key stays on the server.
Backend selection: when the dsh ctx.llm service is available the proxy
uses it (DSH-configured providers, credentials, retries and reasoning
efforts); otherwise it falls back to the direct OpenAI-compatible upstream,
whose key resolves per request:
config.apiKey (patch entry config: field)DSH_WHALE_API_KEY (fallback DEEPSEEK_API_KEY)DEEPSEEK_API_KEY) — the pet works with the
same key the agent already uses, zero extra configurationOther configuration (direct mode only): DSH_WHALE_API_BASE (default
https://api.deepseek.com, OpenAI-compatible upstream origin) and
DSH_WHALE_API_MODEL (default deepseek-chat).
Memory: the pet keeps long-term facts about you plus a bounded recent
conversation under the dsh.whale-pet.memory.v1 localStorage key (same guarded
storage channel as the rest of the pet state). The right-click "鲸鲸记得什么…"
panel lists those facts, lets you delete one, or type a new one. The chat box
itself stays history-free. Facts arrive three ways: the model may still emit a
[记住] <fact> line, the coordinator also extracts first-person statements
from the user ("我叫… / 我喜欢… / 记住:…"), and the panel can add a fact
directly. The 60-character cap applies only to the spoken bubble, not the
[记住] line. Marker lines are stripped before the bubble is shown.
While a request is in flight the pet holds the thinking mood (an external
override the session observer respects) and reacts with an error mood and sweat
drops if the proxy is unreachable or unconfigured (no key → HTTP 503).
The pet can answer "进度如何了": when asked, the pet actively probes the
current progress and appends a compact read-only snapshot to its own
system prompt, so it truthfully reports long-task progress. The probe has
three layers — the live projection state (running tools, turn duration, node
count, goal/plan phase), a fine-grained summary from the host event log
(current step, latest activity like "运行 bash:npm test", latest result
summary), and the jobs registry's real state (running task labels,
elapsed time, output tail like "进度 45%"; served at
GET /api/whale-pet/progress?session=<id>). It only reads — it never
writes to the DSH conversation, so long chats are not disturbed.
While the agent is busy, a plain click on the pet bubbles a playful but factual progress line ("正在鼓捣终端(bash),已经 3 分钟" / "正在深度思考…"; a running background job wins: "正在后台跑 npm run build(已 5 分钟)") without typing.
The pet's own context stays bounded: up to 24 memory facts (80 chars
each) + the last 8 turns (240 chars each) + the progress block, worst case
≈ 4.4 KB (~1.3k tokens). When a turn overflows the 8-turn window, evicted
old turns are not dropped — they are compacted into a capped summary
(summary, 400 chars) so long conversations keep a coarse digest of what
was discussed.
When the user asks the pet for something that needs real execution
(writing code, running commands, research, fixing bugs…), the pet does not
fake an answer: it replies with a [TASK] <description> marker. Only that
marker dispatches work — a casual reply that merely contains execution verbs
stays a direct answer. The client then calls POST /api/whale-pet/task, and
the host dispatches a real subagent conversation through ctx.subagents
(the same machinery as the agent's
subagent tool: its own session, tools and results). The child appears in
the DSH subagent view so the user can open it directly; when it finishes the
pet summarizes the outcome in its bubble (on 1-min timeout it reports the child
session id). The parent is the active agent (currentInitiator); when idle,
a fresh agent is created as the parent identity.
Debug: GET /api/whale-pet/health reports { ok, configured }.
The plugin observes the current DSH session through ctx.sessions and drives
the pet's mood from the conversation snapshot and the goal/plan
projections. The bridge retries until the sessions service is available and
absorbs history-window lag after binding, so old errors never trigger a
reaction.
| Session state | Pet reaction |
|---|---|
| Assistant tokens or tool calls are running | working/thinking: faster swimming, input-area gaze, periodic bubbles |
| One turn runs longer than 20s | focused: a slight dive posture |
| Tool fails (non-zero exit code or error node) | error: pouring sweat drops, a trembling body, a pulsing red "!" mark and wide eyes for 3s |
| Long turn (≥15s), goal completion, or plan exit | celebrating: a 360° elliptical lap with continuous yaw and screen-space depth, while hearts stream every 650ms |
| You are composing a reply in the chat input | listening: gazes at the input area, shows a floating "?", and recaps "在呢,我听着~" on click |
Session is blocked on you (pendingInteraction: approval / question / plan-review) |
awaiting: same gaze and "?" as listening; click recaps "有个审批等你拍板" / "有个问题等你回答" / "有个计划等你过目". Wins over working because the turn often stays marked running. |
| Forceful or prolonged drag release | dizzy: freezes pointer interaction, rolls belly-up, weakly wobbles, and shows a depth-aware elliptical star orbit for about 4s |
| Hover or drag while sleeping | Wakes immediately and resets the idle clock |
| No activity for 60s | sleeping: closed eyes, slow breathing, z-z-z |
| First idle/sleep of a local calendar day | one unsolicited greeting ("今天也在~" / "又见面啦,第 N 天"); at most once a day |
| A compaction node lands after the bind settle window | one "记忆被压扁了一点,我还在~" bubble; never an LLM daemon |
Debug attributes on the pet element:
data-whale-activity — current mood (idle, thinking, working, focused, celebrating, error, dizzy, sleeping, listening, awaiting)data-whale-bridge — session bridge state (off, waiting, bound)The repository ships prebuilt runtime artifacts in lib/, so a downloaded
copy needs no pnpm workspace and no build step. Requires Node.js 22+ on the
machine running dsh.
Download the repository (GitHub ZIP or git clone).
Run the profile installer:
node install-profile.mjs web
This copies the package to $DSH_HOME/profiles/web/plugins/ui-whale-pet,
adds it to the profile manifest and node_modules, and appends the
ui-whale-pet Cordis row to $DSH_HOME/profiles/web/cordis.patch.yml.
Use another profile name as the argument to install there.
Configure the chat proxy API key (see LLM chat and memory) or the pet chat reports an unconfigured error.
Restart dsh web and hard-refresh the browser.
The repository builds standalone (no pnpm workspace, no dsh checkout):
npm install # dev toolchain: typescript, esbuild, vitest, three…
npm run build # tsc declarations + esbuild host/client bundles → lib/
npm test # vitest suite (175 tests)
node install-profile.mjs web
The build is self-contained: host bundles inline everything (only type-only
imports), so the cordis loader needs no node_modules next to the plugin, and
the client bundle keeps the DSH __ModuleLoader__.load browser format with
react/react/jsx-runtime external.
src/client/activity.ts — pure mood/effect vocabulary and the view snapshot type.src/client/motion.ts — pure frame-rate-independent screen-space motion, including the celebration loop path and corner snapping.src/client/persistence.ts — guarded localStorage state (name, position, hidden, snap preference, first-run date).src/client/runtime/scheduler.ts — the single requestAnimationFrame clock.src/client/runtime/whale-pet-controller.ts — owns the DOM listeners, scheduler, and per-frame rendering; composes the Three.js scene from src/client/whale.src/client/runtime/whale-pet-service.ts — observable runtime service (ctx.whalePet) with activity, transient effects, recap history and persisted state.src/client/runtime/session-observer.ts — subscribes to the current session snapshot (with a low-frequency polling fallback) and maps session state to moods/effects and user typing.src/client/whale/config.ts — shared geometry/animation constants and SVG contours.src/client/whale/geometry.ts — pure SVG/contour helpers and BufferGeometry builders.src/client/whale/materials.ts — material factories, including the blue/white body-mask shader.src/client/whale/animation.ts — frame pose animation (swim, tail, fins, eyes, float, error/sleep reactions).src/client/whale/scene.ts — createWhaleScene factory composing config, geometry, materials and animation into a WhaleScene handle.src/client/WhalePet.tsx — thin view consuming the service snapshot through useSyncExternalStore; owns the DOM focus listeners for typing detection, the context menu and the chat bubble (model/effort selectors).src/client/memory.ts — long-term memory store (facts + recent turns) with the [记住] extraction protocol, persisted through the guarded storage channel.src/client/llm.ts — browser transport for the same-origin chat proxy (/api/whale-pet/chat, /api/whale-pet/models), injectable for headless tests.src/client/runtime/whale-pet-chat.ts — chat coordinator: thinking override, reply bubble, memory persistence, error reactions, chat preferences.src/chat-proxy.ts — pure host-side proxy logic: backend interface, direct upstream forwarding, HTTP handler for /health, /models, /chat.src/llm-backend.ts — dsh-llm backend: model catalog with reasoning efforts, streaming completion via ctx.llm.src/index.ts — host entry: mounts the /api/whale-pet prefix on ctx.webServer, picks the backend (dsh llm service first, direct upstream fallback).The original whale model and visual reference come from the Bilibili video BV17Buf69EVV. Thanks to the original creator for publishing the model demonstration and design reference.
This plugin ports and packages the model for the DeepSeek Harness interaction and lifecycle system. This acknowledgement does not grant additional rights to the original model or video; downstream users remain responsible for complying with the original creator's terms.
The overlay registration, DOM listeners, animation frame, WebGL renderer, geometries, materials, and textures all unwind with the owning Cordis fiber. The host chat-proxy route unwinds with its fiber too; the API key never enters the browser.
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。