Commit Graph
40 Commits
Author SHA1 Message Date
bowenliang123 e620e4fbf6 chore(deps): update vitest to 5.0.5
Vitest 5 needs Node >=22.12 and Vite >=6.4 — already satisfied (node 24, vite
8.3.1 auto-installed as its peer) — and needs no config or test change here:
`clearMocks` now defaults on, inline projects inherit the root config, and `-t`
joins suites with ">", none of which this repo relies on.

Paired interleaved runs against v4.1.12, on two warm checkouts and alternating
the version per pair to cancel machine drift: `vitest run` 22.40s -> 20.95s and
`vitest run --coverage` 26.09s -> 25.65s (median per-pair delta -5.8%), with the
same 153 files / 2429 tests and the same 131-file coverage scope at 100% per
file.
2026-10-16 23:06:48 +08:00
bowenliang123 a1772d9717 chore(build): drop redundant tailwindcss direct dependency
@tailwindcss/node already depends on tailwindcss at the same exact
version (4.3.3), so a top-level entry would only risk a second copy
resolving in the build process. The one-copy pin the native-binding
rule requires is now held solely by @tailwindcss/node's exact
dependency; update the tailwind.css comment to match.
2026-10-12 13:57:21 +08:00
bowenliang123 f60e1a5643 build(deps): carry zustand and immer, the rest of the phantom set
@deepseek-ai/dsh-client-store declares both under devDependencies
while its published lib/index.js imports them, so the client lane's
inlined harness bundle needs them hoisted at the root exactly like
`diff` in the previous commit. A clean-room install of the lockfile now
resolves the whole runtime import graph from the checkout alone:
zustand, immer, diff, shiki, katex, anser, clsx, simple-icons and the
micromark/mdast set.
2026-10-09 01:41:58 +08:00
bowenliang123 95d36a3013 build(deps): carry diff, the harness bundle's phantom dependency
@deepseek-ai/dsh-client-ui-primitives declares `diff` under
devDependencies while its published lib/index.js imports it, so the bare
import only resolves when the consumer's workspace hoists it — exactly
how shiki, katex, anser, clsx and the micromark/mdast set are already
carried here. `diff` was the one name missing, which failed the release
workflow's `pnpm test` with "Failed to resolve import \"diff\"" across 47
client suites while passing on any tree with a hoisted copy above it.
2026-10-09 01:37:43 +08:00
bowenliang123 c93a2498b1 chore(deps): drop unused playwright-core
The other suspects from the audit (shiki, katex, anser, clsx, the
mdast/micromark set) stay: the published ui-primitives lib is ESM whose
bare imports are undeclared, and vitest resolves that file for real, so
they are load-bearing devDependencies of this workspace.
2026-10-08 00:18:09 +08:00
bowenliang123 a988c9a8fb feat(compat): drop dsh 0.1.5-rc.1, floor the support matrix at 0.1.7-rc.2
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.
2026-10-07 23:37:52 +08:00
bowenliang123 8103022a1d chore(deps): prune unused devDependencies and refresh the dev toolchain
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.
2026-09-28 10:23:19 +08:00
bowenliang123 53f4cf6248 chore(deps): bump @opencode-ai/models to 0.0.87
Fresher vendored snapshot fallback for the models.dev client; the
providers() entrypoint used by the price-book fetch is unchanged.
2026-09-28 02:37:17 +08:00
bowenliang123 9acbf7eb45 feat: support dsh 0.1.5-rc.1+ and 0.1.7-rc.2+ as the supported lines
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.
2026-09-25 01:08:38 +08:00
bowenliang123 bc2544adfa feat(host): serve the preferences through the entry Config schema
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.
2026-09-23 15:57:28 +08:00
bowenliang123 f3b4c88390 feat(client): lead the Plugin Info rows with site marks
The Plugin / GitHub / Settings labels open with siDeepseek, siGithub,
and the harness's IconSettingsOutline14 gear, riding currentColor at the
label's baseline. simple-icons is a dev-only dependency pinned to the
harness ui-primitives' own 16.31.0 and tree-shakes into lib/client.js as
exactly the two mark paths, so no runtime dependency is added and the
marks are identical to the harness's own SiteGlyph artwork.
2026-09-22 08:08:22 +08:00
Bowen Liang 55aa1fecc3 feat(build): compile Tailwind layout utilities into the client CSS channel
The global-CSS channel now runs @tailwindcss/node's compiler over a new
entry sheet (src/client/styles/tailwind.css) and feeds the resolved
@source globs through the oxide scanner; scanned sources join the watch
graph so class-list edits rebuild the sheet. The entry carries no
preflight and no theme import — just the spacing scale anchored to 4px —
and emits utilities unlayered, so the injected <style> cascade matches
the hand-written sheets it precedes. lightningcss and the Tailwind
packages are pinned to one exact version each: the config process loads
the oxide and lightningcss native bindings together, and duplicate
copies break the napi calls.
2026-09-13 01:55:31 +08:00
Bowen Liang 7cf9284362 feat(stats): estimate session cost from models.dev prices
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
2026-09-13 00:35:03 +08:00
Bowen Liang 4c276c87da chore(deps): update oxlint to 1.82.0
oxlint-tsgolint stays an explicit exact devDependency: oxlint declares
it only as an optional peer dependency, so no package manager installs
it for us and type-aware linting fails loudly without it.
2026-09-12 01:50:11 +08:00
Bowen Liang befa7a986c chore(deps): update tsdown to 0.23.0
No config changes needed: the config only uses deps.neverBundle /
deps.alwaysBundle and dts, all carried over. The rolldown-plugin-dts
0.28.5 bump emits direct export declarations instead of declare +
re-export in lib/index.d.ts; the exported surface is unchanged and the
built JS is byte-identical.
2026-09-12 01:45:29 +08:00
bowenliang123 97ae8ff2ee feat(client): preview File Activity files in the right Sidebar
Clicking a file name in the File Activity card now opens the file's preview
tab in the right Sidebar — the shipped document-preview viewer, reached the
same way the built-in Files sidebar reaches it — on harnesses that serve that
column (dsh 0.1.5-rc.1+). The address is built with the harness's own
browser-safe `fileAddressFor`, inlined by the client bundle exactly as the
Sidebar's file types inline it, so a path under the workspace collapses to the
session-relative spelling and every route to one file settles on one tab.

The capability is OPTIONAL by contract, like the tab registration itself: the
opener reads `ctx.sidebarRight.openResource` through the runtime boundary and
re-proves it per call, and reports whether the column took the address. An
absent column, a face that refuses the address, or an unencodable log path
falls through to the pre-existing system-open behavior, so an older line is
fully functional and nothing becomes an inert click. Pattern rows and
directory targets are never previewable.

Adds the `@deepseek-ai/dsh-util-workspace-path` dev dependency (itself
browser-safe), allows it in the client bundle purity gate, pins the
resource-navigation seam in the compat matrix, and covers the address builder,
the card's preview-then-fallback click, and the optional opener per baseline.
2026-09-11 18:45:28 +08:00
Bowen Liang 7ffb13af91 chore: align @types/react-dom to 18.x matching the dsh web baseline 2026-09-06 21:10:45 +08:00
Bowen Liang 1d5a68e6aa chore: replace native pre-commit hook with husky running pnpm test 2026-09-06 21:10:45 +08:00
bowenliang123 33068ee1c9 compat: narrow the support matrix to dsh 0.1.2-rc.1+
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.
2026-09-04 17:23:08 +08:00
bowenliang123 e87f139e91 build: track the newest published dsh surface (0.1.2-alpha.2)
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.
2026-08-31 14:58:31 +08:00
bowenliang123 1dab8dcdbf build: track the 0.1.2 client module graph
Drop the deleted `@deepseek-ai/dsh-client-runtime` from dsh.client.inject
and remove the preloaded-client-externals channel that died with it; mirror
0.1.2's platform module table (+ dsh-client-store) in the client bundle's
purity gate; widen the dsh peer ranges to >=0.1.0-rc.7 so 0.1.2 prereleases
resolve; pin the devDependency types to the newest published surface
(0.1.1-rc.2); the bundle smoke's fake ctx now honors inject callbacks.
2026-08-28 22:32:31 +08:00
Bowen Liang f106b720ac test: rebuild the suite at source level with 100% per-file coverage gates
The old suite exercised the built lib/ bundle, so v8 remapped almost
nothing (8% src coverage) and every run needed a build first. The new
suite imports src/ directly under two vitest projects (node for
host/shared, jsdom for client), rendering real React 18 trees against
the real dictionaries and ui-primitives, with faithful in-memory
harness faces (cordis inject/effect, locale chain, slots, sessions
provide) instead of plugin mocks.

- 43 fine-grained, stateless, single-module spec files (606 tests)
  forked across workers: ~2.5s wall, no build step
- v8 thresholds at 100/100/100/100 per file over src/**
- host specs drive the real projection definitions (init/apply/view)
  plus one full cordis + SessionStore + SessionProjectionRegistry
  integration; the framework's snapshotJsonValue pins the
  projection-cache precondition on every intermediate fold state
- oxlint's src ruleset now covers tests/** as well
- typecheck covers the tests via tsconfig.tests.json
2026-08-26 00:58:39 +08:00
Bowen Liang 9a64d2ab48 Add vitest coverage command with HTML report
Introduce `pnpm run coverage` to run vitest with v8 instrumentation,
generate a browsable HTML report under ./coverage/, and gate it from
git. Scope coverage to the src tree only: lib/ is the tsdown build
artifact and has no executable surface to cover. Exclusions are
limited to pure type modules (ambient .d.ts, src/shared/types.ts,
src/host/compat.ts) so the summary reflects runnable code.
2026-08-25 21:13:38 +08:00
Bowen Liang 0219d8045f feat: per-user settings namespace with default trend granularity preference
Register the dsh-context settings namespace on the Host (dsh-settings seam,
schemastery schema, optional composition) and claim its Plugin configuration
card in the browser (settings.plugin.item, keyed by namespace). The card
edits the default trend granularity the Context tab opens with; in-chart
toggling stays mount-local and never writes back.

Degrades cleanly: no settings provider -> no registration, no card, step
default; remote browser (memory mode) -> unavailable scope, no card.
2026-08-24 03:36:57 +08:00
bowenliang123 8692c31162 build: adopt the official lint stack (oxlint + tsgolint, type-aware)
Mirror dsh's own lint setup (oxlint 1.76.0 pinned exact, oxlint-tsgolint
7.0.2001 with options.typeAware, correctness category off, hand-picked
rule list; jsPlugins: eslint-plugin-sonarjs + @stylistic/eslint-plugin
with the official style profile: indent 2, semi never, single quotes,
comma-dangle multiline, max-len 140). Scope mirrors official too: src TS
only, generated/bundled output (lib, *.js, *.mjs, *.config.ts) ignored.

Wiring: pnpm run lint / lint:fix scripts, plus a Lint step in the
release workflow between Build and Test.

Fixes applied (runtime behavior unchanged; verified against dsh
0.1.0-rc.7 and 0.1.1-rc.2 wire shapes, see below):

- autofix pass: arrow-parens, comma-dangle, eol-last, indent, quotes
- restrict-plus-operands: 31 string+number concatenations -> template
  literals (restrict-template-expressions allows numbers)
- no-unused-vars: drop unused imports/destructured names
- no-unnecessary-type-conversion: drop redundant String() where the
  field is already string-typed
- no-unsafe-*: type the fetch-json boundary in latestVersion, narrow
  unknown before spread/cast instead of trusting any
- no-unnecessary-condition, three honest categories:
  * boundary sanitizers (services.timelineOf/headersOf, RawBlocks,
    headers.recordOf) now read through Record<string, unknown> instead
    of casting first, so the defensive checks are type-meaningful again
  * post-sanitize consumers (contextView/headline/assemble/browser)
    drop the fallback-empty-array on collections the sanitizer
    guarantees
  * array-index-undefined gaps (fold turn attach, headers dedupe) use
    .at() so the past-the-end guard is real to the type system
- no-non-null-assertion: stackedBar reserve carries the checked max
- no-floating-promises: void the fire-and-forget version check
- intentional-contract suppressions with rationale: react.ts keeps its
  injected require (closure-factory loader contract)
- type-honest hardening kept deliberately: MessageSource.sections
  entries stay nullable (foreign plugins author snapshot sources) and
  isInjection still rejects a null source — foreign message payloads
  must never crash the fold

Cross-version audit (0.1.0-rc.7 vs 0.1.1-rc.2, message parsing focus):
- core/session types.ts: only additive optional interrupted on
  assistant/message (unread by us); every event payload we fold
  (request/header, request/context, tool/call, tool/result,
  user/message, assistant/message, compaction/*) is byte-identical
- llm types.ts / message.ts / content.ts block shapes: identical
- token-meter estimate.ts: identical, and official has NO null-entry
  guards on content blocks — our removed guards match official trust,
  our retained fallback-empty-string / typeof reads stay a leniency
  superset
- deriveEventMessage (core/session surface.ts): identical
- ui-conversation chat-nodes contract: unchanged; our client reads are
  minimally-typed unknowns by design
- tool/call callId is a branded string in both versions, so the
  narrowed typeof guard drops only an impossible coercion
2026-08-22 03:10:41 +08:00
bowenliang123 598a2e06fa refactor(client): move styles to a real stylesheet through the official CSS channel
- tsdown.config.ts gains the three CSS virtual loaders mirrored verbatim
  from packages/client/tsdown.client.ts: .module.css (lightningcss-hashed
  class map + tagged injection), .css?inline (compiled text), and plain
  .css (unhashed tagged injection), each registered as a watch dependency
- src/client/styles.ts (223 rules as a string array) becomes
  src/client/styles.css — real stylesheet authoring, minified by
  lightningcss at build (client bundle 134.8 -> 130.3 kB)
- injection now happens at factory materialization with the official tag
  shape (data-plugin + data-plugin-css + dedupe guard), replacing the
  hand-rolled ctx.effect; the HMR receiver owns removal by data-plugin,
  so the hmr spec pins that lifecycle instead of fiber disposal
- Decision: class names keep the flat lc-* namespace (the anti-collision
  discipline, per the research note) instead of per-component hashed
  modules — the stylesheet's rules are interconnected across components
  (parent:hover child, shared state classes) and 241 test selectors read
  literal classes off the built bundle, which a content hash would make
  unknowable; the hashed .module.css channel is mirrored and available
  for future self-contained components
- globals.d.ts declares the *.css / *.module.css module shapes for the
  strict typecheck
2026-08-22 02:39:19 +08:00
bowenliang123 49f1439dae test: migrate to vitest, split the monolithic client spec into modules
- vitest is the runner (matches the official harness); the two bare-node
  scripts and the manual repro become 13 spec files under tests/
- the 1637-line client.test.mjs splits into focused modules (chart /
  browser / linkage / composition-link / tool-chip-bridge /
  browser-autoload / images / modal / resilience), each booting a fresh
  view bed from tests/helpers/viewBed.mjs — the stateful fake-React
  harness, fake ctx, fixtures, and tree walkers now live in one place
- tests/hmr-safety.client.spec.mjs (jsdom lane, @vitest-environment):
  fiber dispose removes every registration — locale dicts, slot rows,
  trigger source, provide contribution, and the plugin-owned style tag
- host spec gains the same dispose-removes-registrations pin for the two
  session-projection units
- the real-React jsdom mount (was npm run repro, broken since the tsdown
  switch by its own string surgery) now runs the bundle verbatim through
  __ModuleLoader__ and is part of the suite; fixed two latent harness
  bugs along the way: the slot-register capture was overwritten by the
  later overlay registration, and the granularity query needed scoping
  to the trend row (the events card reuses the pill-button classes)
- bundle evaluation in all specs runs the artifact verbatim via the
  boot handoff — no string surgery, decoupled from bundler layout
- scripts.test is now typecheck + vitest run; scripts.repro is gone
2026-08-22 02:33:28 +08:00
bowenliang123 021db5f2a2 build: migrate tsup to tsdown, mirroring the official client-bundle preset
- banner/intro/footer three-part closure-factory wrap (verbatim from
  packages/client/tsdown.client.ts), intro now owns var module/exports
- deps.neverBundle/alwaysBundle guards: host keeps production deps
  external, client keeps only module-table specifiers external
- bundle purity gate: any non-requested @deepseek-ai/* value import is
  a build error (INLINE_SAFE / vendored-library / generated-remote
  allowances mirrored)
- NODE_ENV + import.meta.env defines for inlined node-idiom deps
- client sourcemap on, matching the official artifact contract
- client smoke test now runs the bundle verbatim through the
  __ModuleLoader__ handoff instead of slicing the factory body by
  exact output strings (decoupled from bundler layout)
2026-08-22 02:14:44 +08:00
Bowen Liang 85076ae10c chore: bump version to 0.19.2
Lower @deepseek-ai/dsh-client-ui-primitives, @deepseek-ai/dsh-session and
@deepseek-ai/dsh-session-projection peer and dev deps from ^0.1.0-rc.8 to
^0.1.0-rc.7 so the package declares compatibility with the DSH Community
Market desktop runtime (currently @deepseek-ai/dsh 0.1.0-rc.7).
2026-08-20 23:38:48 +08:00
bowenliang123 dab80c6232 build: switch to tsup and declare harness runtime deps as peers
Replace the hand-rolled esbuild script (scripts/build.mjs) with a single
tsup config that already existed but never ran: tsup re-bundles the config
into a temp .mjs, so import.meta.url pointed at the temp dir and the
package.json read failed, silently leaving no entries. Read the manifest
from process.cwd() instead. The host half now keeps @deepseek-ai/dsh-session
external (resolving to the harness's single runtime instance) instead of
inlining it; the client half keeps the __ModuleLoader__.load wrap.

Align deps with the official dsh convention: runtime harness packages
(cordis, dsh-session, client-ui-primitives, react) move to peerDependencies
with dev mirrors (client-only ones optional); zod stays a dependency;
exact rc pins become caret ranges (^0.1.0-rc.8) so rc9/0.2 releases don't
break installs. Drop the esbuild devDependency (tsup brings its own) and
add tsup itself.
2026-08-20 16:09:16 +08:00
Bowen Liang c535c3b7bc chore: align @deepseek-ai/dsh-* devDeps with dsh 0.1.0-rc.8
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).
2026-08-20 00:59:23 +08:00
Bowen Liang 9e3434d093 chore: move playwright-core to devDependencies 2026-08-19 19:56:45 +08:00
Bowen Liang 2dab549f98 fix: remove the husky pre-commit check to comply with DeepSeek Harness Desktop's plugin install verification requirements 2026-08-18 20:52:24 +08:00
Bowen Liang 81b9ecd7f0 context browser 1 2026-08-18 02:34:58 +08:00
Bowen Liang c229fd1d9b chore(deps): bump @deepseek-ai/dsh-* dev deps from 0.1.0-rc.6 to 0.1.0-rc.7 2026-08-17 21:31:57 +08:00
bowenliang123 38dbd2ad92 refactor(ui): move the context tab onto the harness's React stack
All view components are now tsx JSX function components instead of
hand-rolled h() factories; the bundle externalizes the framework seed words
(react, @deepseek-ai/dsh-client-ui-primitives) so the loader module table
resolves the single shared framework instance at runtime.

Reuses shared ui-primitives where a clean fit exists (injection and
model-switch event glyphs -> IconPlusOutline16/IconBranchOutline16); the
bespoke data-viz chrome (charts, shared-hover tooltip) intentionally stays
custom but continues to draw the shared --dsw-alias-* tokens.

esbuild uses the classic JSX transform, so the emitted createElement trees
are isomorphic to the previous h() calls and the element-parsing tests, the
chart-render assertions, and the real-React repro all stay green unchanged.
Adds @deepseek-ai/dsh-client-ui-primitives as a type devDep and documents the
framework-reuse findings in docs/redesign.md §8.
2026-08-16 03:51:00 +08:00
bowenliang123 6bebd495e9 feat: route context timeline through the harness session-projection pipeline
Replace the custom /dsh-context RPC channel + 2s client polling with a native
contextTimeline session-projection unit: the host registers one pure
init/apply/view unit on ctx.sessionProjections (framework-driven, persisted by
the projection cache, streamed via session/projection push frames), and the
client reads the finished value through the framework standard
useProjection seat. Deletes the client stale-while-revalidate cache and the
local service type stubs; grows the modern shelf registration (locale) and
adds the published @deepseek-ai/* types as devDeps plus zod as the single
runtime dependency (wire schema, kept external in the host bundle).

Fixes tool-result node attribution to read the durable source.callId /
content toolCallId instead of the never-present block.callId (tool labels had
silently never rendered).

Retention is tightened to trim by whole turn-runs deterministically (bounded
state, no 1200<->1500 oscillation under incremental folding).

Tests now drive the projection unit directly (host) and feed the view through
a useProjection stub (client); all chart/render assertions preserved. Adds
docs/redesign.md (review + target architecture, phases 0-3 landed) and
docs/CLIENT_SURFACE.md (client-side audit).
2026-08-16 03:25:01 +08:00
bowenliang123 d09173ccd5 test: real-React + jsdom render smoke for the granularity toggle
Mounts the built client bundle with actual react/react-dom inside jsdom,
feeds a 460-request snapshot through the RPC, and toggles step -> turn ->
step — the flow reported to black-screen the tab. Renders cleanly, so the
black screen is not in the render path (layout-effect suspicion remains,
needs the real console error to pin down).
2026-08-14 23:44:49 +08:00
bowenliang123 a49a1c6fba chore: husky pre-commit hook runs tsc --noEmit
Every commit is now type-guarded: the hook runs `pnpm run typecheck`
(strict, noEmit), so type errors fail the commit. Husky auto-installs the
hooks on install via the prepare script.
2026-08-14 23:03:58 +08:00
bowenliang123 89436bf31d chore: switch the package manager from npm to pnpm
- 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
2026-08-14 19:31:57 +08:00