deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
A local tool for the DeepSeek Harness web GUI that browses the GitHub
dsh-plugin topic: every repo's
name, README, and statistics (stars, forks, open issues, language,
license, last update, topics), with a Sync button to refresh the data, an
in-memory search, top-tag filtering, and sorting (stars / last
update / created, ascending or descending).
It is a client plugin
(dsh.client dual-face package) that mounts one entry into the sidebar's
footer action list (sidebar.footer.action): a Plugin Explorer trigger
beside Settings that opens the tool's modal.
http://127.0.0.1:3080) and refresh the page.topic:dsh-plugin agent topic:python),
so a scoped sync fetches exactly that matching subset instead of GitHub's
1000-result cap truncating the whole topic, and the fetched subset replaces
the cached snapshot. The status line shows the GitHub query of the last
sync.dsh, dsh-plugin, dsh-plugins,
deepseek, deepseek-harness, ai-agent, ai-agents — are
excluded); click one to filter to repos carrying that tag (click again or
use Clear tag to remove the filter). The tag filter combines with
search.dsh plugin add <pkg>, pnpm add <pkg>, npm install <pkg>, or
yarn add <pkg> — only the package name is detected, never a command
line). If no install instruction can be found in the README (or the repo
has no README at all), the button is disabled and reads Cannot install
directly in grey. The README is fetched lazily, so for repos never
expanded the button starts as plain Install; clicking it probes the
README first and flips to the disabled grey state when it turns out to
carry no install command. Once a repo's package is installed in the
profile, the button switches to a danger-tinted Uninstall that removes
it again (dsh plugin --profile web remove <package>). The installed
state is authoritative — the host reads the profile's actual dependencies
and the list refreshes on modal open and after every successful
install/uninstall (a failed install never flips the button). Both actions
require an acknowledgement prompt; only the package name crosses the wire
— never a command line — and the host validates it against npm naming
rules before spawning the CLI. If pnpm 10+/11 blocks dependency build
scripts (ERR_PNPM_IGNORED_BUILDS), the host flips the exact packages
pnpm listed to true in the profile's pnpm-workspace.yaml
allowBuilds map and retries the install once.Data persists in localStorage under dsh-plugin-explorer:repos:v1 and
dsh-plugin-explorer:readmes:v1, so the list survives restarts and works
offline. The readme cache is size-bounded (oldest entries evicted).
The line under the toolbar summarizes the current view: repo counts, when the
snapshot was synced, the topic total, the active tag, the GitHub query of the
last sync, a hint when creation dates are missing, the active sort
(· sorted: Stars ↓), and a build tag (e.g. · b13) identifying the exact
bundle the browser runs. If the build tag is missing or older than the
latest, the browser is on a stale bundle — refresh the page.
api.github.com straight from the browser (CORS is
permissive); no token is required for public data. If you hit limits often,
set a GITHUB_TOKEN? No — the browser cannot read your env; the tool is
intentionally anonymous.src/
index.ts node half: default-exported PluginInstallerGateway
(a Typert Remote service; source-mode dispatch)
installer.ts host: install/uninstall/installed remotes that drive
the dsh CLI, plus pnpm build-script approval (js-yaml)
types.ts wire types (InstallRequest/InstallResult) shared by
both halves
client/
index.ts browser half: inject ['slots', 'remote', 'typert'],
mounts the installer Remote lazily, registers
RepoExplorer into 'sidebar.footer.action'
RepoExplorer.tsx trigger + modal: sync, search, tags, sort, README
expand, install/uninstall prompts
RepoExplorer.module.css
install-remote.ts hand-written Typert Remote descriptors + type merges
install-guide.ts README install-command detection
github.ts GitHub REST client + localStorage cache + helpers
The browser bundle (lib/client.js) is emitted by tsdown in the shell's
closure-factory format: window.__ModuleLoader__.load({ id, factory }) with
the frozen platform module table as externals (react, @deepseek-ai/cordis,
@deepseek-ai/dsh-client-ui-primitives, ...), CSS Modules compiled by
lightningcss and injected as <style data-plugin> tags.
The installer is a Typert Remote gateway (pluginInstaller): the browser
mounts hand-written descriptors (add, uninstall, installed) and the api
gateway dispatches to the host service through its @Remote markers. The
wire contract mirrors the host method signatures exactly — one request
parameter per action — and the install endpoint is named add because the
client namespace service reserves install and remove for its own members
(mounting a colliding name throws). Only a validated npm package name crosses
the wire; the CLI is spawned with an argument array, never a shell.
The tool is mounted through the web profile's user patch layer (no changes
to the DeepSeek Harness checkout):
# ~/.dsh/profiles/web/cordis.patch.yml
- insert:
- id: dsh-plugin-explorer
name: dsh-plugin-explorer
plus a symlink so the profile can resolve the package:
ln -s /Users/boxiao/Documents/dev/dhs-plugin-explorer \
/Users/boxiao/.dsh/profiles/node_modules/dsh-plugin-explorer
New rows are read at GUI boot (config hot-reload is off in the web profile),
so a restart of the dsh web process was required once. After that,
rebuilds of lib/client.js hot-reload through the client-plugin HMR chain
(the host polls the bundle and broadcasts rebuilt over SSE; no refresh
needed). Host-half changes (the installer gateway) load only at boot, so they
require a GUI restart.
pnpm install # registry dev deps only; dsh types resolve through a
# node_modules/@deepseek-ai -> ~/.dsh/profiles/node_modules/@deepseek-ai
# symlink (the exact package versions the GUI runs)
pnpm run typecheck # tsc --noEmit against the real dsh .d.ts artifacts
pnpm run build # tsc -p tsconfig.host.json (host half: decorators are
# lowered to plain JS) then tsdown: lib/index.js +
# lib/client.js (+ .map)
pnpm run watch # tsdown --watch (browser half only); bundle rewrites
# trigger client HMR. Host-half source edits need a
# `tsc -p tsconfig.host.json` run first, then a GUI restart.
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。