Keep both Remote contributions master and this branch add: the mount loop
now carries commandsRemote, goalsRemote, pluginInventoryRemote, and
messageFeedbackRemote, with both new tsconfig references retained.
The grep, glob, and web_search tool rows all rendered as "Search" with
the same magnifier icon, so a transcript full of local searches was
indistinguishable from web searches. Grep and glob now carry their own
command-named titles through TOOL_TITLES, and the web_search row wears
a new globe glyph (IconGlobeOutline14) while keeping its "Search" title.
The step and the Models page both asked one question of a join that
describes every provider: is deepseek-official's credential stored? A user
who configured some other route was taken over on every blank session, and
the DeepSeek setup card opened over them on every visit to Models with a
Cancel that could not close it — while clearing the add card's draft,
because it shared the row-editor close handler.
providerUsable(row) now answers what both surfaces need: the route is
registered and whatever credential its profile names is stored. Readiness
(renamed onboardingReadiness) ends on any usable row, needsSetup takes the
same fact, and each card kind owns its own close handler.
Fixes#2325
Second alignment step for #2248: document-level drag intake behind the new
DropOverlay atom, lightbox close icon and shared dialog mask, DeepSeek Chat
thumbnail rules (single 240px long edge with ratio clamp, 64px tiles, merged
consecutive assistant images), image limits raised to 20/10MiB/100MiB and
published to clients as the imageLimits projection, whole-batch intake
pre-check with product-copy banners, and attachment-error reasons mapped to
localized copy.
The flat-list ordering change duplicated the document-level native-drag
acceptance effect and the status-dot block across the search and session
rows, tripping the duplication gate. Extract useNativeDragAcceptance and
SessionStatusDots so both call sites share one implementation.
Adapt to two contract changes master introduced:
- The generated Remote face now wraps every business result in
RemoteResult, folding carrier failures into an ok:false branch instead
of rejecting. The controller reads that envelope at its three call
sites and maps a carrier failure onto the same settled shape the
controls already render; three specs cover the new branch.
- Client packages split their tsconfig into host and client halves, and
the host aggregate now compiles any test not named *.client.spec.*.
Rename this package's specs to the client convention and drop the
../connection project reference, which pointed at a solution file that
no longer carries the client sources.
Keep master's mount loop with its rollback-on-failure in api-remotes and
add messageFeedbackRemote to it.
The locale plugin's inject list gained 'remote' and 'settingsScope' on
2026-08-10, but the built-bundle harness mounted it without providing
those services, so the locale fiber never started and the trajectory
plugin's apply never ran — the ring assertion saw no 'trajectory' entry.
Provide the same stubs ui-layout's apply bench uses.
A test file under packages/client now says which face it covers:
`*.client.spec.{ts,tsx}` and its `*.client.{ts,tsx}` helpers belong to the
Client aggregate, `*.host.spec.ts` to the host aggregate. The carrier's four
node-half specs take the Host suffix.
The two suffixes are mutually exclusive, so each aggregate excludes the
other's and both keep one broad test glob: `exclude` wins over `include`, and
`packages/client/**` no longer has to be excluded wholesale from the host
program with per-file `files` entries carved back out of it. A Host-face spec
that reaches only Host source therefore needs no cross-face project
reference, which the split-project rule rejects.
vitest still discovers every file through `**/*.spec.{ts,tsx}`.
Resolve the note-erasure race the review found: a control that rendered
before the first list read held no item and passed note=undefined, so
switching a rating silently dropped the stored note. The controller now
owns note resolution and toggle-vs-retract, deciding from the committed
item inside the serialized mutation, and clearNote expresses deletion.
Also from review:
- serialize the reconnect re-read behind queued mutations (resync), so a
list reply cannot resurrect a version a newer mutation replaced
- re-check disposal after the seeding read, so an unloaded fiber never
reaches the wire
- drop Object.freeze on Maps, which does not prevent set/delete
- declare the @deepseek-ai/dsh-client-connection dependency it imports
- surface a failed list load in the controls
- drop the /client value exports that had no consumer
- state the per-turn render scope in the README and subsystem pages
- align the package version with the root