tcgbp/dsh-flash ↗★ 0

dsh-flash

Quick Control panel core for DSH Workbench — the floating/docked quick-control panel with the extensible switch registry, the skin system and the alert surfaces. Publishes the `dockFlashPanel` service; the dock-base integration ships separately as `dock-flash`. 适合需要自定义控制面板、皮肤系统和警报界面的 DSH 开发者。

패키지
dsh-flash
호환성
미검증
Cordis peer 범위
>=4.0.0-rc.1 <5.0.0-0 || >=4.0.1-0 <5.0.0-0
버전
1.0.0
라이선스
Apache-2.0
최근 업데이트
2026. 10. 8.

설치

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:tcgbp/dsh-flash

dsh-flash

Quick Control panel core for the DSH web UI — the floating/docked quick-control panel with an extensible switch registry other plugins register their own controls into, the skin system, zh/en i18n and the alert surfaces. The DSH Workbench (dock-base) integration ships separately as the dock-flash adapter.

中文文档

Core + adapter

This package is the panel and nothing else. It owns the React panel, the quickControl switch registry, the skin system, the alert surfaces, the standalone floating ⚡ trigger, and the whole host half (src/index.ts → dist/index.js). It has no dependency on dock-base at all, so it runs on its own, and it always offers the panel and the ⚡ trigger. A dock host takes the panel by claiming the dockFlashPanel service; only then does the core stand its own ⚡ down.

The dock-base (Workbench) integration is a separate, thin adapter package — dock-flash v3 — that depends on this one and registers the panel, the plugin card, the activity-bar item, the editor view and the command through ctx.workbench.

dsh-flash ──provides "dockFlashPanel"──▶ dock-flash ──ctx.workbench──▶ dock-base Workbench
   this package: panel, switch              the adapter: 5 registrations
   registry, skins, i18n, alerts,           + the claim/release handshake
   standalone ⚡, host routes

The dependency arrow points one way: this package never imports or names dock-flash. It publishes the service and stands its own ⚡ down when a host claims it; whoever claims it is a stranger it does not have to know about. That is what lets the panel work both standalone and under dock-base from one build, and why the core can be installed on a profile that has no dock-base at all.

What you wantInstallYou get
Workbench (dock-base) integrationdock-flash@^3, which pulls this package in — plus dock-baseSidebar/floating panel, plugin card, activity-bar ⚡, editor view, the dock-flash:openQuickControl command
Only the standalone floating ⚡dsh-flash aloneA ⚡ trigger in the configured conversation slot → floating panel

Upgrading from dock-flash v2

Nothing breaks by default. Your ^2.x dependency range keeps you on the old single package, which still exists under the same name — the split added a new major (dock-flash@^3) rather than replacing v2. To move to the split, install dock-flash@^3; it depends on this package and pulls it in.

One profile edit is required, and it is easy to miss. In the profile's cordis.patch.yml the entry that carries your panel settings reads - id: dock-flash / name: dock-flash. That name: is an assertion about the target row's current specifier, not a rename. After the split, id: dock-flash resolves to this core row, whose specifier is dsh-flash, so the assertion mismatches, DSH prints patch: name mismatch for "dock-flash" (expected "dsh-flash", got "dock-flash"), skipping and the whole config: block is dropped — silently reverting your panel order, your skin and your trigger position/size. Change that entry's name: dock-flash to name: dsh-flash and keep id: dock-flash.

The settings namespace itself does not change. The profile patch entry id deliberately stays dock-flash, because that entry id is the settings namespace every already-published user preference lives under. The settings section, the persisted dock-flash:… keys and the /plugins/dock-flash/… host routes are all unchanged across the split — the name: fix above is the only edit the upgrade needs.

Modes

ModeConditionUIAvailable switches
Claimed (Workbench)the dock-flash adapter (and dock-base) installed⚡ in the activity bar → sidebar/floating panel; the core's standalone ⚡ is suppressed while the panel is claimedAppearance + System
Standalonedsh-flash installed alone⚡ trigger in the configured conversation slot → floating panelAppearance + Layout + System

Features

Built-in switches

Built-in switches are grouped into Appearance / Layout / System (compact two-column layout). The Layout group is offered in standalone mode only:

GroupSwitchTypeDescriptionStandalone
🎨 AppearanceThemeselectLists what the theme service publishes, minus the dead options. While a theme publishes its own palette (Dream: Abyss / Aurora / …), those palettes are the list and Light / Dark / System are withheld — the palette paints over the base scheme and fixes its own colour scheme, so none of the three could do anything. With no palette published — no skin installed, or a restyling skin such as Claude — the list is Light / Dark / System, and Follow-system really does resolve against the OS✅
🎨 AppearanceSkinselectDynamically discovers installed skin plugins and switches between them, through DSH's own plugin manager — dsh-market is neither needed nor consulted. Every switch writes BOTH layers: the loader ENTRY row (what the running page acts on) and dsh.profile.bundles (what the next boot composes), because writing only one of them is how a skin came back after a reload, or could never be switched on again✅
🎨 AppearanceTurn RailtoggleMoves DSH's built-in turn navigator from the right gutter to the left. Hidden unless DSH's own rail is on screen and no other timeline plugin owns it✅
🎨 AppearanceFullscreentoggleBrowser Fullscreen API — enter/exit fullscreen✅
🎨 AppearanceLog DownloadtoggleShow/hide the session log download button✅
📐 LayoutClose on BlurbuttongroupOff / On — auto-close the panel when clicking outside. Also a toggle in the panel header (both modes)✅
📐 LayoutTrigger PositionselectInput Left / Input Right / Session Header / Header Utils — where the standalone ⚡ trigger goes — or Conversation top-right, a floating button inside the conversation you can drag anywhere within it✅
📐 LayoutTrigger Button Sizeslider24–64 px — how big the standalone ⚡ entry point is drawn, glyph and corner radius included. The draggable Conversation top-right position allows the full range; the slot positions cap at 48px so the button still fits the input row, and the row shows the size actually in force✅
🖱️ Right-click(the draggable ⚡ itself)menuReset position / current offset / version (click to copy a diagnostic) / layer and rest opacity presets. Not a switch in the panel: the layer and the opacity only apply to the floating button, and the menu deliberately does not repeat trigger-size, trigger-position or close-on-blur✅
⚙️ SystemLanguagebuttongroup中文 / English — switches DSH global UI language✅
⚙️ SystemMissing CompanionslogNames every companion plugin that is not running, splitting installed, not running from not installed — a package that is present but silent is a different problem from one that is absent. Read-only: it prints the dsh plugin --profile add … command for the ones genuinely missing (and points at the DSH Plugins page on the reserved desktop profile, which the CLI refuses), plus a copy button. A ✕ hides both rows through the same visibility store the ◉ mode writes, so nothing is unregistered and ticking them again brings them back✅

The Layout group only renders in standalone mode. When a host claims the panel, close-on-blur exists solely as the panel-header toggle, so no built-in switch carries group: 'layout' and the category is skipped entirely.

Dock layout is not configured here. Dock edge, auto-hide, reserve space and icon scaling are dock-base's own settings — this package deliberately does not duplicate them. In the Layout group it owns only trigger-position, trigger-size and close-on-blur, all standalone-only.

Turn Rail only offers itself while DSH's own rail is what you see. It stays hidden with no session open, in a session without turns, while DSH's own @container (width MutationObserver)

  • 🎨 Skin System — Multi-layer discovery + categorized switching (CSS / Managed / Excluded)
  • 🛡️ Error Boundaries — All panel components are wrapped so a render error cannot crash the host that mounted the panel
  • 🔌 Standalone Mode — Works with no host at all: a ⚡ trigger injected into the configured conversation slot opens a floating popup panel
  • 📝 Recent Changes — Auto-records switch operations (30s TTL), displayed in "old value → new value" format
  • 🩺 Connection Diagnostics — (moved to the dsh-flash-proxy plugin) — NO_PROXY policy, connection test, and diagnostics log
  • 🧮 Reorderable and hideable Panel — A ⇅ icon in the Workbench and Extensions tab headers opens a reorder mode: ▲▼ move groups and switches, and the result is saved in your DSH profile, so it follows you to another browser or machine. Beside it, a ◉ icon opens a visibility mode with a ●/○ box on every row: untick a switch you never use and it disappears from the panel, while staying listed here so you can bring it back. Both configuration pages list every registered control, including any a plugin is standing down right now — those rows are dimmed with the reason on hover, so a control that does not apply at the moment can still be ordered or hidden. The two modes are mutually exclusive and each has its own ↺ reset. Switches that declare a cluster move as one unit with a fixed internal order and are drawn as one card whose members fold

Host-side features

src/index.ts (host half) provides:

  • Registers the dock-flash settings namespace (panel preferences, trigger preferences, host alert queue settings)
  • Exposes HTTP routes:
    • GET /plugins/dock-flash/host-alerts — drains the server-push alert queue
    • POST /plugins/dock-flash/push-alert — pushes an alert into the queue
    • POST /plugins/dock-flash/clear-alerts — clears the alert queue
    • GET /plugins/dock-flash/health — lightweight heartbeat + Node.js memory stats
    • GET /plugins/dock-flash/profile-packages — profile inventory for skin discovery
    • POST /plugins/dock-flash/set-plugin-entry — live plugin enable/disable via patch edit

System proxy features have moved to the dsh-flash-proxy plugin — proxy mode, NO_PROXY policy, testUrl, connection diagnostics, and the five dsh-flash-proxy:* QuickControl switches now live there.

The monitors are companion plugins. This package owns no monitor of its own: the context monitor lives in dsh-flash-ctx-mon, the memory/GC monitor in dsh-flash-mem-mon, and the network audit in dsh-flash-net-mon. Each keeps its own settings namespace, registers its alert provider through the dockFlashAlerts service and its switch through quickControl, so it appears in this panel with its own ⚙ config page. This package keeps the shared alert registry, the host-pushed alert queue, and the label/link mappings that surface those companion alerts. They are separate installs — see Installation.

Structure

src/index.ts      HOST half — settings namespace + alert routes + profile inventory (tsc → dist/)
lib/client.js     BROWSER half — quickControl registry + dynamic panel + skin system + i18n
cordis.patch.yml  bundle layer — inserts host rows into the profile

The cordis.patch.yml row keeps the entry id dock-flash while the package is named dsh-flash: the entry id is the settings namespace, so keeping it is what makes the split migration-free.

Core contract

lib/client.js publishes two services:

PublishedAPIPurpose
Panel servicectx.provide('dockFlashPanel', { version: 1, Panel, ErrorBoundary, Header, icon, registry, i18n, host })Everything a dock host needs to claim and mount the panel. A host that finds no service, or one whose version it does not speak, leaves the standalone ⚡ in place rather than drawing half a panel
Switch registryctx.provide('quickControl', registry)Other plugins register their own switches

The panel service exposes host.claim() / confirm() / release(): an unconfirmed claim is undone by a watchdog, so a host that dies mid-mount cannot leave the ⚡ suppressed.

What the adapter adds

The dock-base (Workbench) integration lives in the separate dock-flash v3 adapter, which interacts through ctx.workbench:

RegistrationAPIDescription
Sidebar Panelctx.workbench.registerPanel()Quick control panel (sideBar area)
Plugin Entryctx.workbench.registerPlugin()Settings panel card
Activity Bar Itemctx.workbench.registerActivityBarItem()Lightning icon ⚡, click to open sidebar
Editor Viewctx.workbench.registerEditorView()Quick control panel (draggable to floating window)
Commandctx.workbench.registerCommand()dock-flash:openQuickControl command

When no host claims the panel, this package runs standalone: it mounts a floating ⚡ trigger button and popup panel directly in the DOM, providing access to all non-layout switches.


🧩 Dynamic Discovery API

This plugin publishes the quickControl service. Other plugins obtain the registry via ctx.get('quickControl') and register their own switches.

Switch Types

TypeDescriptionRequired Fields
toggleBoolean switchgetValue(), setValue(boolean)
sliderNumeric slidergetValue(), setValue(number), min, max, step
selectDropdown selectgetValue(), setValue(any), options
buttongroupButton groupgetValue(), setValue(any), options
actionAction buttonrun()
logRead-only multi-line blockgetLines()

QuickSwitchDefinition

interface QuickSwitchOption {
  label: string | (() => string)
  value: any
}

interface QuickSwitchDefinition {
  /** Globally unique id; use "plugin:switch" format, e.g. "dock-git:show-stash" */
  id: string
  /** Display label (supports functional i18n) */
  label: string | (() => string)
  /** Icon (emoji or text) */
  icon?: string
  /** Switch type */
  type: 'toggle' | 'slider' | 'select' | 'buttongroup' | 'action' | 'log'
  /** Sort weight (ascending); built-in items use 10-60, start from 100 */
  order?: number
  /** Built-in group: 'appearance' | 'layout' | 'system' (only for dock-flash:* items; ignored by third-party switches) */
  group?: string
  /**
   * Optional cluster label. Switches sharing a label are drawn as ONE card and
   * reordered as one unit (a single ▲▼ pair), keeping a fixed internal order —
   * their `order` field. The card opens folded to its head row and its members
   * can be revealed behind a centred ▼/▲ toggle on the card's bottom edge.
   */
  cluster?: string

  // ── Common to toggle / slider / select / buttongroup ──
  getValue?: () => any
  setValue?: (value: any) => void

  // ── Slider-specific ──
  min?: number
  max?: number
  step?: number
  formatLabel?: (value: number) => string

  // ── Select / buttongroup-specific ──
  options?: QuickSwitchOption[] | (() => QuickSwitchOption[])

  // ── Action-s