dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Single-session context anatomy for the DSH Web GUI: attribution, headroom planning, and a context x trajectory timeline — not another usage ledger.
Context anatomy for a single DeepSeek Harness session.
The GUI already shows you a context percentage and a trajectory view. Neither answers the question you actually have when a session gets expensive: what is eating the window, and how many turns do I have left?
dsh-context-lens adds a Context Lens panel that answers four things:
Not another usage ledger. The ecosystem already has a dozen token counters. This plugin is scoped to a single session's context anatomy, and it deliberately does not do billing reconciliation. See docs/COMPATIBILITY.md for the full scope boundary.
The panel opens from a Context action in the sidebar footer, and is also available as a dockable tab in the right sidebar. It reads:
used / window, with the remaining tokens and an
estimated number of turns left at the recent average growth rate.Every figure is either a value the harness computed or a labelled estimate. The panel never invents precision it does not have.
# From npm (prebuilt)
dsh plugin --profile web add dsh-context-lens
# From a tarball (prebuilt)
pnpm pack # the tarball takes the manifest version; read the name it prints
dsh plugin --profile web add ./dsh-context-lens-<version>.tgz
# Straight from GitHub (builds from source on install)
dsh plugin --profile web add github:yukitakasama/dsh-context-lens
A git install fetches sources, not built artifacts, so the package ships a
prepare script that builds lib/ from source. pnpm ≥ 10 refuses to run a git
dependency's prepare until you allow it, so the first install fails with
ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED. pnpm prints the exact key it wants —
copy that line verbatim into the profile's pnpm-workspace.yaml. It is not just
the package name; it carries the resolved commit, so the pin is built in:
allowBuilds:
dsh-context-lens@git+https://github.com/yukitakasama/dsh-context-lens.git#<resolved-sha>: true
Then re-run the install. Treat that allowance as permission to execute this package's code on your machine at install time. It is only required because the build is real — nothing prebuilt is committed to git.
Verified end to end on dsh 0.1.5-rc.1: with that key present, pnpm install
runs prepack, builds lib/, and the profile then resolves the
# == dsh-context-lens layer.
To pin a specific revision yourself:
dsh plugin --profile web add github:yukitakasama/dsh-context-lens#<sha>
Substitute your own account name if you forked the repository.
If you are working from a checkout, the browser half is a built artifact — a
change to src/client/** does nothing until you rebuild:
node scripts/build.mjs # writes lib/index.js and lib/client.js
node scripts/check.mjs # manifest + compliance assertions
node --test "tests/*.spec.mjs"
scripts/build.mjs is dependency-free and hand-reproduces the official
lazy-CJS bundle format, because the harness's clientBundle() preset is not
published for third-party packages.
lib/ is gitignored and the suite reads the built artifacts, so the build is
a prerequisite for the tests: host.spec.mjs imports the host half from
lib/, and the bundle, degradation and externals specs read lib/client.js.
On a fresh clone, node --test before node scripts/build.mjs cannot pass:
host.spec.mjs fails to load its imports at all, and every spec that reads
lib/client.js fails with it.
All tunables are validated Config fields, so an invalid value throws at load
time rather than being silently ignored:
| Key | Default | Range | Meaning |
|---|---|---|---|
sampleStride | 1 | 1–10000 | Log revisions to advance between samples. |
maxSamples | 2000 | 1–50000 | Sample cap per session; overflow is reported as truncated. |
cacheTtlMs | 15000 | 0–600000 | How long a read stays valid. |
paceWindow | 10 | 1–200 | Recent steps averaged for the capacity estimate. |
- insert:
- id: context-lens
name: dsh-context-lens
config:
sampleStride: 2
paceWindow: 20
Pure consumer. The plugin adds no session event, changes no agent-loop
code, and exposes nothing model-visible. It is a second reading of data the log
already carries.
The client never folds events. Every displayed value is a finished value the
host already computed, arriving through the official session projections —
contextPressure, contextBreakdown, tokenUsage, sessionStats.
One honest exception. The timeline needs a series, and the harness offers no
prerendered one. So the host half observes ctx.tokenMeter.measure() at step and
compaction boundaries and serves that over a read-only route. Two consequences
are stated rather than hidden:
coverage field, and the UI labels it.measure() is O(surface), so sampling is event-driven at boundaries only,
never per token delta, and capped.host projections ─┐
├─→ client view model (pure, tested) ─→ panel
host token meter ─┘
Verified against dsh 0.1.5-rc.1 and 0.1.5-rc.2 — the same build loads in
both, whose baseline module table, projection keys and slots are unchanged.
Declares no required service, which is deliberate: depending on webServer would strand the plugin
in PENDING in a TUI profile and stall the entire profile. Every optional
capability (sessions, sidebarRightTabs, settings, tokenMeter,
webServer) is probed with ctx.get, so a missing one disables exactly one
seat.
Full matrix, degradation tiers, and reproducible verification commands live in docs/COMPATIBILITY.md.
node scripts/build.mjs # build both halves into lib/ — do this first
node scripts/check.mjs # manifest + compliance assertions
node --test "tests/*.spec.mjs" # tests
Both commands print their own totals, which is why none is restated above: a
number written into prose is a number that drifts. The live figures are
asserted against the docs by tests/docs.spec.mjs.
scripts/check.mjs enforces the rules a type checker cannot: no default
export (it would silently drop inject), no literal colors, no bare runtime
import in the host half, and a host half that declares no service.
MIT — see LICENSE.