omdsh-plugins/omdsh-basemode

Plugin ⭐ 1 MIT ecosystemweb-ui

The session-mode system for the DeepSeek Harness web GUI: the segment registry every mode plugin registers into, the switch that renders them, and the sidebar dots that colour their conversations

Install

`SessionModes` is a type, and it comes from `@omdsh-plugins/omdsh-basemode/client`. Import it with `import type` and never as a value: a cross-plugin VALUE import either inlines a second copy of this package's runtime into your bundle or asks the shell's frozen module table for a specifier it cannot answer, and the client bundle purity gate fails the build over it. That is why the service is resolved by the string `'sessionModes'` above rather than by this package's exported `SESSION_MODES` constant — a service name is a wire name shared with a runtime, not a symbol shared with a package, and both mode plugins in this collection spell it out for themselves for exactly that reason.

Five things are worth knowing before writing one.

**Exactly one segment is active,** and the registry enforces it rather than trusting contributors to agree: marking one active clears the rest. That is also how a contributor learns it lost the column — it watches its own entry go false and takes its surface down.

**Copy arrives localized.** The switch renders `label`, `hint` and `unavailableHint` as given; it owns two words of its own (`switch.aria`, and the fallback shown when a mode is unavailable and named no reason) and knows no mode's name. Re-`update` the segment on `locale/change`.

**A press is a navigation, never a state write.** `enter` is called and the segment is expected to make the world true — by opening a conversation, starting one, or taking the column — after which whatever derives its `active` flag reports it. Nothing here remembers a mode across a reload; there is no node half, deliberately, so there is no stored posture two tabs can disagree about.

**`owns` is asked per conversation, in display order,** and the first claim wins; a segment marked `fallback` takes whatever no one claims. That is what lets the sidebar mark a whole list by mode with nothing about any particular mode in the code that paints it. A classifier that throws declines that conversation rather than taking the browsing region down.

**`inProject` says whether a mode's conversations live somewhere a person works.** It defaults to true, because that is what a conversation in this product is; a mode that files its own in a store of its own declares `false`. Chat is the one that does. It matters to any surface that derives a DIRECTORY from the conversation on screen — Code mode pressing beside a chat used to open a terminal inside the folder chats are filed in — and asking the registry is what keeps "which of these is Chat" out of every other plugin.

## What the column is showing is not what is selected

`sessions.current` answers "which conversation is SELECTED", and that is the same question as "what is on screen" only while every mode's column is the web conversation. Code mode's is a terminal, and it deliberately never selects the conversation that terminal drives — a selected conversation is one the web host would resume, on a log another process owns. So the selection stays on whatever was open behind the terminal.

A surface beside the column that read the selection was therefore silently wrong rather than missing: `omdsh-sidepanel`'s file tree sat beside a terminal in one project describing another. `column` is the honest answer:

Add omdsh-plugins/omdsh-basemode to your DSH config (web profile) to enable.

README

Expand full README Collapse

README is empty.