The supported set is now the two V4-generation lines (0.1.7-rc.2+ and
0.2.0-rc.2+): the manifest's dshReleases, the peer floors (>=0.1.7-rc.2,
cordis ^4.0.4 — both lines vendor 4.0.4), the devDependency pins, the
baseline matrix, the release workflow's tag fetch, and the compatibility
docs.
With every supported line on session format V4, the V3-only paths leave:
the fold reads the tool result's first-class message alone (source.callId
pairing, message.isError — the admission validation refuses any row whose
data.error outlives it); the settings.register host face module is gone
(the Config-form entry schema serves the preferences); the client drops
the settingsScope/settings.plugin.item card seat, the retired sessions.open
jump fallback, the legacy icon spellings, and the settings-dialog leg of
the settings jump; the history page's tool/result mapper reads the V4
message (its V3 wrapper reads were dropping result content on supported
lines); the cache probe rides the 2-arg cachedSnapshot face. The baseline
gate stays: a below-floor harness composes the fallback units and the
upgrade prompt, and an undetectable version still fails open.
Verified: pnpm run lint:fix && pnpm run test && pnpm run build green (1918
tests, 100% per-file coverage); the compat matrix passes against the real
dsh sources at both baseline tags; live on dsh 0.2.0-rc.2 the plugin
composes, the Plugins-page preference card renders and round-trips a
write, the insights warm-up fills the heatmap, and the session jump and
Context tab work end to end.
Drop @deepseek-ai/dsh-invariants and @deepseek-ai/dsh-scope (unreferenced
since the two-baseline re-fit) and the duplicate zod entry from
devDependencies; the dependencies entry stays the runtime one. Declare
react-dom as an optional peer - the client bundle requires it and the
host's platform module table provides it, mirroring the react peer.
Refresh dev-only tooling in range: oxlint 1.85.0, oxlint-tsgolint,
simple-icons, @types/node, jsdom, eslint-plugin-sonarjs, playwright-core.
Everything coupled to the dsh baselines stays put on purpose: the
primitives resolution shim at the versions dsh-v0.1.5-rc.1 itself
resolves, dev cordis 4.0.2 against the vendored packages' exact peers,
lightningcss 1.32.0 deduped with @tailwindcss/node, and the zod floor at
^4.4.3 to match the harness's own. Drop the two orphaned
minimumReleaseAgeExclude rows along with the removed packages.
The supported range is now two baselines - dsh-v0.1.5-rc.1 (session
format V3) and dsh-v0.1.7-rc.2 (V4) - enforced by the runtime gate at
BASELINE_DSH_VERSION = 0.1.5-rc.1; below it the fallback units and the
upgrade modal take over (0.1.2/0.1.3 hosts were previously served by the
real folds).
The pre-V3 log shapes are dead code on every supported harness: the
running harness migrates historical logs on every read path (or refuses
the session wholesale), and 0.1.5-rc.1 rejects a request/header carrying
header.system outright. The fold therefore drops the V0/V2-only paths -
the header.system envelope system prompt, assistant/chunk floods,
{start, end} replacement endpoints, tool/code-dispatch - and the state
fields only they wrote (systemsFromHeader, the stepStart decode
accumulators). stateVersion stays 20: no supported log folds
differently, and pre-V3-era cached rows are discarded by the projection
cache's identity gate (and the strict stepStart sub-schema) instead of
served. The headers unit folds metadata-only epochs (envelope
systemTokens write dropped; the v1 cached-row read-compat and its pinned
stateVersion 1 stay); replaceRangeOf speaks startSeq/endSeq only; the
browser's epoch fetch maps request/header to tools and system/message to
the prompt text.
tests/baselines.ts re-fits to the two entries (the right Sidebar seam is
required on both), the compat matrix drives both tags' REAL sources
(canonical logs re-shaped to V3, the hostile probe renumbered past them),
and the version fixtures pin the new floor. Manifest: dshReleases
{0.1.5-rc.1, 0.1.7-rc.2}, dsh peers >=0.1.5-rc.1 (satisfies the 0.1.7
admission check under includePrerelease), devDeps pinned to the
0.1.5-rc.1 surface plus the ui-primitives runtime closure the client
lane inlines (test-only), and the release workflow fetches the two tags.
docs/compatibility.md is rewritten around the two-line matrix; README,
AGENTS.md and the issue template follow.
Also riding this move, from the audit pass: the fold re-proves an inject
source's form before it books the event record (the harness validates
`kind` but not `form` - a hostile one previously failed the strict
wire/state schemas on every delivery, the #44 freeze class), the headers
unit guards a data-less envelope (it has no try/catch of its own), the
schemastery schema annotations drop the explicit z<T> wrappers the 3.18.4
Mode generics reject, and the version-history note records why
stateVersion is deliberately not bumped.
The Config-form generation (dsh 0.1.7+) derives the Plugins page's live
form from each loader entry's own Config schema, so the entry schema must
be the schemastery one: cordis keeps validating the config: block through
its Standard Schema face, and the same schema now carries the six display
preferences as .volatile() fields (live-editable there, namespace = the
entry id). The fold bounds stay ordinary fields — their edit remounts the
entry, a preference edit commits volatile-only.
The .volatile() modifier ships only with the newer schemastery, so the
builder feature-detects it and the same bundle loads on the older lines
(3.18.2 predates the modifier). The devDependency bumps to 3.18.4 to
exercise the marked path in tests. Deliberate relaxations against the
replaced zod schema: unknown keys merge through, and integers are
expressed as min 1 + step 1.
Replace the hardcoded DeepSeek rate table with a client-fetched price
book: @opencode-ai/models reads the models.dev registry once per page
load, every entry is re-proved at the boundary, and a failed fetch
degrades to a dash + note with backed-off automatic retries.
- cost totals rekey per (provider, model); only DeepSeek splits a
pricing period (peak windows at list price, all other hours half
price) — every other provider bills everything at list price
- provider ids resolve through a shared rename table (deepseek-official,
kimi-coding, minimax-cn, zai-coding-cn) with verbatim passthrough for
unmapped ids; model ids match exactly, case-insensitively, or by
suffix (k3 -> kimi-k3), ambiguous matches price nothing
- CNY display converts at the fixed 1 CNY = 0.15 USD; the tooltip lists
per-1M rates for the models the session billed, with peak|off-peak
pairs and the DeepSeek note shown on DeepSeek sessions only
- stateVersion 18: cached rows refold from the log, which rebuilds the
new cost keys and periods
The install/runtime compatibility floor moves from 0.1.1-rc2+ and
0.1.2-alpha2+ to 0.1.2-rc.1+. The 0.1.1 line and the 0.1.2-alpha previews
leave the support matrix, so every pre-0.1.2 fallback they existed for is
removed outright:
- client history: drop the legacy `connection.api.sessions.history` face,
the `result`-nested envelope, and the `events` rows field — the gateway
`remote.session.page` face and its ClientResult envelope are the only
served shapes.
- client image loader: drop the pre-0.1.2 `conversation.resolveImage` face;
`uiConversation.imageUrl` only.
- client node join: drop the pre-0.1.2 `useSession.nodes` seat;
`useChat`'s ChatSnapshot `legacy.nodes` only (UseSessionLike removed).
- tests/baselines.ts: single baseline `v0.1.2-rc.1`; HostSeam dropped (the
registry generation hard-codes header-passing init and seq-0 eager
seeding, now mirrored with the exact `init(header, inheritedEventCount)`
arity); ClientSeam slimmed to the consumed probes.
- deps: devDeps re-pinned to the 0.1.2-rc.1 generation (types compile
against the real rc.1 surfaces); cordis ^4.0.2 and schemastery ^3.18.2
per the rc.1 peer requirements; dsh-scope/dsh-invariants declared as dev
deps; peer floors >=0.1.2-rc.1; dshReleases table trimmed.
- release workflow fetches only the dsh-v0.1.2-rc.1 tag; docs updated
(AGENTS.md, README, docs/compatibility.md).
- verified against the rc.1 sources: the tool-attribution map (names and
packages, incl. the documented `subagent_fork` alias), MCP naming, the
page/imageUrl/legacy.nodes faces, and the registry contract.
Pin the dsh devDependency types to 0.1.2-alpha.2 and refresh
minimumReleaseAgeExclude to the baseline versions. Typecheck proves the
alpha.2 face with zero code changes, and the jsdom lane renders with the
real 0.1.2-alpha.2 primitives; the rc.2 face stays covered by the
mirrored compat layers and the real-code matrix.
Bump @deepseek-ai/dsh-session, dsh-session-projection, dsh-client-ui-primitives
to 0.1.0-rc.8 to match the released @deepseek-ai/dsh@0.1.0-rc.8 contract.
Drop @deepseek-ai/dsh-token-meter: only referenced in comments, never
imported. Runtime occupancy is read from the official 'contextPressure'
projection key registered by dsh itself; pricing is computed locally in
src/host/pricing.ts.
@deepseek-ai/cordis stays at ^4.0.1 (already matches dsh 0.1.0-rc.8).
- pnpm-workspace.yaml declares the project as its own workspace root, so
pnpm never walks up into a parent workspace (e.g. $HOME); esbuild's
postinstall is explicitly allowed
- package.json gains the packageManager field (pnpm@11.9.0)
- package-lock.json replaced by pnpm-lock.yaml
- README development commands now use pnpm