# The harness patch this plugin needs English | [中文](README.zh.md) `harness-session-pin.patch` applies to a DeepSeek Harness checkout at `dsh-v0.1.1-rc.2`. Without it this plugin never activates: it injects `sessionPins`, and no stock harness provides that service. ## Why a patch instead of a plugin The plugin renders a pin control on each sidebar session row and lifts pinned sessions above every workspace. Neither is reachable from outside `@deepseek-ai/dsh-client-ui-workspace`, which as of `0.1.1-rc.2`: - declares only two slots, both for the directory-picking flow, and neither on a session row; - hardcodes the session row's context menu to rename, fork, and archive; - keeps session grouping and ordering in `createWorkspaceViewStore()`, private to the package. So the patch adds one service and the surface that consumes it, rather than working around a seam that does not exist. ## What it changes | File | Change | |---|---| | `ui-workspace/src/client/session-pins.ts` | New file: the single-provider client registry behind `ctx.sessionPins` | | `ui-workspace/src/client/index.ts` | Provides `ctx.sessionPins`; injects `togglePinnedSession` | | `ui-workspace/src/client/contract/slots.ts` | `hooks.sessionPins` and `togglePinnedSession` on the browser's injected share | | `ui-workspace/src/client/WorkspaceBrowser.tsx` | Renders the pinned section; removes pinned rows from ordinary groups | | `ui-workspace/src/client/rows/Rows.tsx`, `tree.ts` | `derivePinned` and the row-level pin control | | `ui-workspace/src/client/{WorkspaceBrowser,rows/Rows}.module.css` | Styles for both | | `ui-workspace/src/client/locales.ts`, `README*` | Copy for the above | | `ui-primitives/src/icons/index.tsx` | `IconPinOutline16` | | Tests beside each | Coverage for the registry, the rows, the tree, and the browser | ## Applying it ```sh cd git checkout dsh-v0.1.1-rc.2 git apply /path/to/harness-session-pin.patch ``` Then register this plugin's sources with the two TypeScript aggregates, which the patch deliberately leaves alone because their contents vary by checkout: ```jsonc // tsconfig.base.json — compilerOptions.paths "@deepseek-ai/dsh-client-ui-session-pin": ["./packages/client/ui-session-pin/src"], // tsconfig.client.json — references { "path": "./packages/client/ui-session-pin" }, ``` Build and mount the plugin as usual afterwards. ## When this patch can go away Three things are needed upstream; the first two do not exist as of `0.1.1-rc.2`: 1. An extension point on the sidebar session row — something like `sidebar.workspaces.session.action`, with `sessionId` and the row's state in the owner props. 2. A way to influence session ordering, since pinning lifts rows to the top and ordering lives in that private store. 3. A plugin-owned settings namespace. **This one arrived in `rc.7`**, which deleted the hardcoded `WEB_SETTINGS_NAMESPACES` allowlist in `packages/host/apiproxy/src/api-proxy.ts` and now serves whatever `ctx.settings.describe()` returns. The patch shrank accordingly. Track those two, not this file: every upstream release so far has made this patch smaller, and `rc.8` removed a second piece of it by deriving browser hooks through `PropsHooks` instead of a hand-written type. ## Rejected alternative A plugin can register its own browser into `sidebar.workspaces` at a higher priority and shadow the official one entirely, touching no harness code. That means vendoring the whole sidebar — roughly 2400 lines after bundling — and realigning it on every upgrade, which is harder to maintain than the patch above.