Repository navigation
Releases: mpinaev/dsh-context-governor
Releases · mpinaev/dsh-context-governor
Release list
v0.3.5
- New compact button in the composer, next to handoff. It runs the built-in
/compactthroughctx.remote.commands.execute(sessionId, '/compact', []),
so the user gets exactly the harness command — the same durable
command/run/command/donerecords and the same result node as typing it —
not a private reimplementation and not a second compaction path. The host half
needs no change: the command is already registered in DSH.remote.commands
is a separate Cordis service (theremoteservice only associates it), so the
button is mounted by a childctx.inject(['remote', 'remote.commands'])
plugin; the chip and handoff still load when that service is absent. - The button is honest about what it is doing. It disables itself and shows
compacting…while the request is in flight, confirms success in the UI
language, and on a failure shows the host's own reason (busy, cancelled,
changed history, no useful summary) in the tooltip. A host without the command
or without the command channel says so instead of pretending it worked. - This is the one place where tokens can be spent, and only on a click: the
plugin still makes no model calls of its own, but/compactasks the harness
summarizer to write the summary. All three READMEs now say this next to the
"no tokens" promise instead of leaving it as a silent exception. - The smoke suite clicks the real component against a stub Remote: it pins the
/compactline, the session id, the empty attachment list, the busy state,
the localized success, the "nothing to compact" answer, a refused remote
call and a handler error result (132 checks).
v0.3.4
- DSH 0.2.1-rc.3 support declared — that is the newest release (published
2026-10-23). No host- or client-facing code change was needed: every contract
the plugin touches is unchanged between0.2.1-rc.1and0.2.1-rc.3— the
session/eventpayload, thetokenUsage/contextPressureprojections, the
session query surface,credentials.resolveand both balance shapes,
webServer.register, the model catalog (llm.resolveModelInfo), the two
client slots (conversation.session.header.utilities,
conversation.input.right) anduiWorkspace.startSession. The compaction
formula indsh-compaction-basicis byte-for-byte identical to rc.1
(min(thresholdRatio * window, window - reserve - headroom), headroom 65536),
so the threshold and the bands stay right. - What rc.2 and rc.3 did change does not reach the plugin: V4.1-Flash-1017 and
DeepSeek Search/Fetch extend the model and tool set (the window still comes
from the catalog), the new "More" plugin menus add slots but do not move the
two the plugin uses, and the API-key model-list sync is the same account path
the plugin already reads. - Verified live on rc.3, not just on paper: the status route returns the token
projections and the catalog window, the handoff route returns a document, the
balance arrives from the stored API key, both client slots exist in the
client contract, anddsh --profile web --dump-configkeeps
id: context-governorenabled. - The compatibility tables in all three READMEs name
0.2.1-rc.3, and the smoke
suite now pins the declared range (^0.1.7-rc.2 || ^0.2.0-rc.1) instead of
only checking that some range exists, so an accidental narrowing fails before
a release.
v0.3.3
- The handoff document now covers the whole session instead of its tail. It used
to take the last user message as the task and the last assistant message as
the state, so a long session read as "what happened at the end" with no path
to it. The host now walks the model surface in order: the first task, then
every user request with the last assistant answer to it (the session arc),
then the current state and the touched files. - Injected harness messages are not requests. AGENTS.md, the runtime-context
snapshot, the skill catalog and the time snapshot arrive asuser/message
events whosesource.kindis notuser; before, they became arc steps and the
answer to the previous turn stuck to them. Now only real user messages — or
messages from an older host without a source — start a step. - Several messages of one turn fold into one step: a user who sends text and then
an image is one request, and the image is marked[изображение]/[image]/
[图片]. Touched files are reduced to one form (relative to cwd), so a file no
longer appears twice under two different paths. - A very long session keeps its beginning and its end (24 steps) and says how
many middle requests were skipped, instead of dumping everything. - The smoke suite covers the arc: first task versus last, the middle, numbering,
en/zh localization, injected-message filtering, image steps, same-turn merging
and the long-session gap marker.
v0.3.2
- The balance is no longer short by the granted wallet on the platform-account
path. The account service returns topped-up wallets invalueand granted
ones inbonusWallets; the plugin summed onlyvalueand reported it as the
total, so a $29.53 grant next to a $19.26 top-up read "$19.26, granted
$29.53, topped up $0" — smaller than the real balance and internally absurd.
The total is now topped-up plus granted in the primary wallet's currency
($48.79 in that example), with the two parts still shown separately. - Wallets in another currency are surfaced instead of discarded. DeepSeek keeps
yuan and dollar wallets side by side, and the DSH account panel shows them as
"$29.53 + ¥1.45"; the plugin used to drop everything but the first currency.
The status payload now carries anotherslist (also filled from the extra
balance_infosof/user/balance), and the chip, the panel row and the
tooltip append it as "+ ¥1.45". Yuan and dollars are still never added to one
another. - The smoke suite pins the account arithmetic against the real wallet shape
(topped-up 19.26 + granted 29.53 + CNY 1.45 -> 48.79 USD + ¥1.45) and the
multi-currency/user/balanceresponse; all three READMEs document the suffix
and the assertion count.
v0.3.1
- DSH 0.2.1 support declared. The 0.2.1 line needs no code change: every host
contract the plugin touches is unchanged there —session/eventwith
request/contextandrequest/header(same payload fields, same
contextWindowandconfig.maxTokens), thetokenUsage/contextPressure
projections (onChanged,stateOf), the session query surface (readSurface,
filterEvents),credentials.resolve, the account balance shapes
(credential-stored,value/bonusWallets),webServer.register, the
model catalog (llm.resolveModelInfo) and both client slots
(conversation.session.header.utilities,conversation.input.right) — and
uiWorkspace.startSessiononly gained an optional argument. The compaction
formula indsh-compaction-basicis byte-for-byte identical between
0.2.0-rc.2and0.2.1-rc.1, so the threshold and the bands stay right. - The compatibility range now lives in
engines.dsh. DSH 0.2.1 checks that field
and ignorespeerDependenciesonce it is present, so this is the declaration
that actually decides; the peers stay so package managers and older hosts keep
reading a range. The same range still matches0.2.1-rc.1because the host
compares prereleases included, which is what the plugin quietly relied on
before. - On Web, DSH 0.2.1 resolves a stored credential before the environment. The
balance follows with no code change — it resolves the key through
credentials.resolve('DEEPSEEK_API_KEY')and only then falls back to
DEEPSEEK_API_KEYfrom the environment — so the documented order now matches
the host's. - The DSH compatibility tables in all three READMEs name
0.2.1-rc.1, and the
development section's assertion count now matches the smoke test (101, not the
stale 58).
v0.3.0
The peak/off-peak tariff now follows Chinese public holidays, rates and the seasonal tariff are per provider, and a provider without a prompt cache can now declare cached: false.
- The peak/off-peak tariff now honours Chinese public holidays. DeepSeek's rule
is peak on weekdays excluding Chinese public holidays, and off-peak all day
on those holidays — but the plugin only knew weekdays and hours, so on the
National Day holidays (1–7 October 2026) it reportedpeak (×2)and doubled
the rates and the step cost while DeepSeek was charging the off-peak half.
The year's calendar is fetched in the background from a maintained source
(holidayUrl, defaultchinese-daysdata), cached on disk under
<DSH_HOME>/cache/context-governor, and refreshed on its own — no yearly code
edit.holidaysconfig takes'YYYY-MM-DD'dates or ranges and wins over the
source;holidayFetch: falsekeeps the plugin fully offline. Until the
calendar is known the weekday rule applies and the panel says so
(season.holidayKnown); the countdown now skips whole holidays to the next
working peak, and the tariff row reads "off-peak (Chinese holiday)". README.zh.md: a full Chinese translation of the README, since the plugin
already ships a Chinese interface. The language switcher in both existing
READMEs links to it, and the stale assertion count in the dev section was
corrected to match the smoke test.- The balance is printed to the cent.
fmtMoneyused three decimals below 100
(a leftover from the step-cost formatterfmtUsd, where a step can cost a
fraction of a cent), so a¥8.95balance read¥8.950while the tooltip
printed the raw8.95. Money is now two decimals everywhere — chip, panel and
tooltip, in every currency. - The READMEs state plainly that the step cost and the rates are in US dollars
while the balance is shown in the source currency (USD or CNY) without
conversion, so the two must not be compared directly. - At peak the balance and the time indicators are red. The host's
season.color
is now red during peak (it was amber), and the client paints the chip balance,
the chip tariff marker, and the panel's tariff / countdown / Beijing-time /
balance rows with it, so the expensive hours read at a glance. - Fixed a literal "undefined" in the English and Chinese interfaces. The client's
balanceUnknownstring existed only in the Russian dictionary, so on a
non-DeepSeek provider the panel's balance row and the chip tooltip rendered
undefinedinstead of text. A smoke test now compares each language's keys
against English recursively, so a missing key fails the suite instead of
leaking into the UI. - No price UI at all on providers the plugin has no rates for. Previously the
chip and the panel wrote "price unavailable" for cline and friends, which was
noise around numbers that do not exist. The status payload now carries
config.priced, and the client drops the whole price block when it is false:
the chip loses its cost segment, and the panel loses the step-cost,
relative-to-base and rates rows. The peak marker stays (it is a clock reading),
but its×Nmultiplier appears only where rates are known. - Rates and the seasonal tariff are now per provider.
providerRates.<id>
overrides the defaultfreshRate/cacheReadRate/cacheWriteRate/
outputRate(andpeakMultiplier), so a second provider can carry its own
numbers, and a provider with explicit rates is priced even if it is not in
pricedProviders. The DeepSeek season — peak/off-peak, the×Nmultiplier and
the Chinese holidays — now applies only to a seasonal provider, by default an
id starting withdeepseek; a foreign provider declaresseasonal: truein its
providerRatesentry to opt in. Behaviour change: a non-DeepSeek provider no
longer has its rates doubled in DeepSeek's peak hours, and it gets neither the
tariff marker nor the tariff rows. providerRates.<id>.cached: falsefor a provider with no prompt cache. The
arithmetic already worked (zero cache buckets contribute nothing), but the UI
and the signals did not know: the rates row still listed cache-read/cache-write
prices, the panel showed cache rows and a permanent 0% cache-hit, and the
cacheHitLowwarning fired on every step because 0% is below the 90% floor —
plus a cold-prefill alarm on each request, since every token is fresh by
definition there. With the flag the cache rows, the cache rates, the chip's
cache-hit marker and both warnings go away; a caching provider is unaffected.
v0.2.0
First public release.
A session context chip for DeepSeek Harness: prompt size, a cache-aware per-step
cost estimate in USD, cache-hit, bands and the compaction threshold, DeepSeek
balance and the peak/off-peak tariff, plus a one-click handoff.
It never calls a model and spends no tokens.
Highlights
- Token usage comes from the harness
tokenUsageprojection, with an
llm/streamfallback for builds without projections. - The model window and pressure come from the
contextPressureprojection. - The compaction threshold is computed per session, exactly as
dsh-compaction-basicdoes; a session never inherits another model threshold. - Cache input is split into read and write, each with its own rate; cache-hit
counts reads only. - The balance prefers the harness
deepseekAccountservice and falls back to
the DeepSeek API key; it is shown only for DeepSeek providers. - UI in English, Chinese and Russian.
Install
dsh plugin --profile web add github:mpinaev/dsh-context-governorRequires DeepSeek Harness 0.1.7-rc.2 or newer on the 0.1.x/0.2.x lines.
Checks
npm test— 34 assertions, no network, no model calls./scripts/compat-check.sh— boots a spare instance and probes the live API