Phase 2 of the 0.1.5 adaptation: the plugin stops drawing its own right
panel and contributes tab TYPES to DSH's native right Sidebar, which owns
the right column. The bottom workbench (terminal dock) stays plugin-owned.
Registrations (src/client/native/):
- every TabDescriptor becomes a native tab type (kind = descriptor.id, the
default `extension` band) plus a keyed body in `sidebar.right.pane.tab`
and a live chip title in `sidebar.right.pane.tab.title`
- the `editor` type also claims `dsh-resource://file/**`, so it outranks
the built-in `text` preview (fallback) and every file the product opens
lands in the plugin's editor
- the built-in `files` page kind is TAKEN OVER by an extension
registration of the same kind: `openTab('files')` draws the plugin's
explorer, and the built-in resumes when the plugin unregisters
- registrations follow the plugin registry + the side-card settings: a
type registered later (external plugin) gets its native type too, a
disabled type is unregistered (absent from the guide, refuses opens)
Adapter (src/client/native/tab-adapter.tsx):
- one synthetic plugin `SidebarTab` per native tab id, minted from the
native record + navigation params (or the descriptor's own createTab,
which a native guide open bypasses), kept live across navigations and
updateTab writes
- the explorer's per-tab expansion/reveal sets and the per-kind instance
counter, which the plugin's own layout used to hold
Service routing (src/client/service.ts):
- `setSurface` installs the native write face; openTab/openFile land
natively (a path becomes a resource address, a path-less editor open
becomes the `files` page, the rest carry the seed as navigation params),
closeTab/updateTab/activateTab recognise native tab ids
- new optional `OpenTabSeed.target` ('right' default, 'bottom' keeps the
bottom workbench); the bottom panel's own + menu and auto-terminal pass
'bottom'
- src/client/native/surface.ts probes the controller's per-session writes
(`openTabIn`/`openResourceIn`/`closeIn`, not in `ISidebarRight`) and
queues opens for a session whose surface is not mounted yet
Right panel retired behaviourally (Phase 3 deletes the code): Sidebar
renders its bottom workbench only, keeps the panel collapsed, and hides
the right-panel toggle. The panel-specific e2e specs are removed; the
mount lane now drives the native guide (tab sweep), the plugin explorer
inside the native pane (editor/mermaid/README chunks) and the sidechat
host routes.
Verified: pnpm typecheck / lint / build / test (126 files, 1349 tests) /
check:consumer-types, plus pnpm test:mount against a real
@deepseek-ai/dsh@0.1.5-alpha.1 host (7/7).
43 lines
1.6 KiB
TypeScript
43 lines
1.6 KiB
TypeScript
/**
|
|
* The explorer's `@`-reference button: insert one file or folder reference
|
|
* into the conversation draft of a session.
|
|
*
|
|
* Directories append the folder mention (`@dir/`) as plain text so DSH's
|
|
* folder decoration and completion keep working; files insert a structured
|
|
* chip like the native `@` picker, so the whole reference stays one link
|
|
* instead of decorating only the leading folder. The session-scope context and
|
|
* the conversation input service are resolved at click time; a missing service
|
|
* or scope degrades to a logged no-op, never a crash.
|
|
*
|
|
* Shared by the plugin's own panel and the native right-Sidebar tab body, so
|
|
* both surfaces behave identically.
|
|
*/
|
|
import type { Context } from '../context-types.ts'
|
|
import { appendToDraft, insertFileReference } from './conversation-draft.ts'
|
|
import { relativeTo } from './paths.ts'
|
|
|
|
/**
|
|
* Reference one path in the session's conversation draft.
|
|
* @param ctx - the client context.
|
|
* @param sessionId - the session whose draft receives the reference.
|
|
* @param cwd - that session's workspace root (for the relative spelling).
|
|
* @param path - the absolute or workspace-relative path to reference.
|
|
* @param isDir - whether the path is a directory (folder mention vs file chip).
|
|
*/
|
|
export function referenceInChat(
|
|
ctx: Context,
|
|
sessionId: string,
|
|
cwd: string | undefined,
|
|
path: string,
|
|
isDir: boolean,
|
|
): void {
|
|
const rel = relativeTo(cwd ?? '', path)
|
|
if (isDir) {
|
|
appendToDraft(ctx, sessionId, `@${rel === '.' ? './' : `${rel}/`}`)
|
|
return
|
|
}
|
|
if (!insertFileReference(ctx, sessionId, rel)) {
|
|
appendToDraft(ctx, sessionId, `@${rel}`)
|
|
}
|
|
}
|