feat: adapt to DSH 0.1.2-alpha.1 (Remote gateway + token auth + MarkdownText labels)
Dual-version compatibility: the plugin now works identically on
0.1.0-rc.8 ~ 0.1.1-rc.2 and 0.1.2-alpha.1 (the latter verified against a
source build of the dsh-v0.1.2-alpha.1 tag: mount smoke 14/14 + aggregate
double-mount; 0.1.1-rc.2 re-verified 14/14).
- MarkdownText: alpha.1 renamed the flat optional `codeLabels` prop to a
required nested `labels: { code: {copyLabel, copiedLabel}, footnotes }`;
the old prop alone crashes fence rendering with "reading 'code'". All
four render sites (mermaid / MarkdownHtml / TextEditor / SideChatView)
now go through src/client/markdown-labels.tsx (dual-shape object passed
under both prop names).
- e2e mount lanes speak both host dialects (tests/e2e/host-protocol.ts +
host.ts, unit-locked by tests/e2e-host-protocol.spec.ts):
- one-time-token browser auth: the launch URL grep extends past the
`/?token=` query (truncating at `/` loses the token), goto navigates
the token URL (browser cookie exchange), and stamped navigations
pre-seed the context cookie via addCookies — the exchange 303 drops
sibling query params;
- Remote gateway: dot endpoints first, slash endpoints on 404 fallback,
with args keyed by the controller parameter name (workspace/create ->
{request}, session/list -> {_request}; verified on a live host).
- package.json: drop the @deepseek-ai/dsh-client-runtime peer (package
removed upstream in alpha.1; zero references in the source — the chunk
externals entry stays and is resolution-tolerant).
- scripts/e2e-mount.sh: fix a latent set -u crash in the npx fallback
branch ($DSH_CMD followed by a full-width comma parsed as part of the
variable name).
- CI pin stays at @deepseek-ai/dsh@0.1.1-rc.2 until alpha.1 publishes to
npm (comment updated); README/AGENTS document the new contracts.
- Version lockstep bumped to 0.17.1.
This commit is contained in:
@@ -19,6 +19,7 @@ import { createElement, type ReactNode } from 'react'
|
||||
import DOMPurify from 'dompurify'
|
||||
import { MarkdownText } from '@deepseek-ai/dsh-client-ui-primitives'
|
||||
import type { ComponentType } from 'react'
|
||||
import { markdownTextProps } from './markdown-labels.tsx'
|
||||
import { lazyChunkComponent } from './lazy-chunk.tsx'
|
||||
import { resolveLocalMediaDest } from './markdown-images.ts'
|
||||
import {
|
||||
@@ -193,7 +194,7 @@ function MarkdownSegment({ text, hasMermaid, media, codeLabels }: MarkdownSegmen
|
||||
<div ref={containerRef}>
|
||||
{hasMermaid
|
||||
? <LazyMermaidMarkdown text={text} codeLabels={codeLabels} />
|
||||
: <MarkdownText text={text} codeLabels={codeLabels} />}
|
||||
: <MarkdownText {...markdownTextProps(text, codeLabels)} />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
StateDot,
|
||||
type MenuEntry,
|
||||
} from '@deepseek-ai/dsh-client-ui-primitives'
|
||||
import { markdownTextProps } from './markdown-labels.tsx'
|
||||
import { IconHistoryOutline16, IconSaveOutline16 } from './icons.tsx'
|
||||
import type { Context, SidebarHistoryEntry } from '../context-types.ts'
|
||||
import {
|
||||
@@ -186,13 +187,13 @@ function renderRow(row: SidechatTranscriptRow, labels: RowLabels): React.ReactNo
|
||||
case 'user':
|
||||
return (
|
||||
<div key={`${row.kind}:${row.seq}`} className={css.sidechatUser}>
|
||||
<MarkdownText text={row.text} codeLabels={labels} />
|
||||
<MarkdownText {...markdownTextProps(row.text, labels)} />
|
||||
</div>
|
||||
)
|
||||
case 'assistant':
|
||||
return (
|
||||
<div key={`${row.kind}:${row.seq}`} className={css.sidechatAssistant}>
|
||||
<MarkdownText text={row.text} codeLabels={labels} />
|
||||
<MarkdownText {...markdownTextProps(row.text, labels)} />
|
||||
</div>
|
||||
)
|
||||
case 'reasoning':
|
||||
|
||||
@@ -20,6 +20,7 @@ import { EditorState } from '@codemirror/state'
|
||||
import { EditorView as CodeMirrorView, keymap, lineNumbers } from '@codemirror/view'
|
||||
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands'
|
||||
import { IconCheckOutline16, MarkdownText } from '@deepseek-ai/dsh-client-ui-primitives'
|
||||
import { markdownTextProps } from './markdown-labels.tsx'
|
||||
import { api, htmlUrl } from './api.ts'
|
||||
import { rewriteLocalImageUrls } from './markdown-images.ts'
|
||||
import { languageForPath } from './lang.ts'
|
||||
@@ -422,7 +423,7 @@ export function TextEditor(props: FileViewerProps) {
|
||||
? <MarkdownDocument info={htmlInfo} media={htmlMedia} codeLabels={codeLabels} />
|
||||
: hasMermaid
|
||||
? <LazyMermaidMarkdown text={previewText} codeLabels={codeLabels} />
|
||||
: <MarkdownText text={previewText} codeLabels={codeLabels} />}
|
||||
: <MarkdownText {...markdownTextProps(previewText, codeLabels)} />}
|
||||
</div>
|
||||
)}
|
||||
{html && mode === 'preview' && (
|
||||
|
||||
@@ -67,6 +67,13 @@ type ChunkFactory = (require: (spec: string) => unknown) => ChunkExports
|
||||
* (stripClientSuffix). dsh-client-web-react / dsh-client-schema-form were
|
||||
* dropped in DSH 0.1.0-rc.8 (no rc.8 publish, nothing requires them) — the
|
||||
* chunks never asked for them, so they no longer belong here.
|
||||
*
|
||||
* DSH 0.1.2-alpha.1 removed the `dsh-client-runtime` package outright (the
|
||||
* seed table gained bare-name `@deepseek-ai/dsh-client-store` instead); the
|
||||
* runtime/client row below stays for 0.1.1-rc.x hosts — no chunk requires
|
||||
* it, and {@link buildExternalsRequire} keeps an unresolvable spec
|
||||
* undefined until a chunk actually asks (only then is it a loud error), so
|
||||
* the entry is inert on 0.1.2-alpha.1+.
|
||||
*/
|
||||
export const CHUNK_EXTERNALS: readonly string[] = [
|
||||
'react',
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copy-button / chrome labels for DSH's shared `MarkdownText`, shaped for
|
||||
* BOTH prop generations the plugin supports:
|
||||
*
|
||||
* - 0.1.1-rc.x: optional flat prop `codeLabels` — the renderer reads
|
||||
* `labels.copyLabel` / `labels.copiedLabel` directly.
|
||||
* - 0.1.2-alpha.1+: renamed to a REQUIRED `labels` prop with a nested shape
|
||||
* (`labels.code.copyLabel` + a screen-reader-only `labels.footnotes`
|
||||
* heading). Passing only the old prop crashes the fence render with
|
||||
* "Cannot read properties of undefined (reading 'code')" — the exact
|
||||
* regression the mount lane caught on a real 0.1.2-alpha.1 host.
|
||||
*
|
||||
* The union object satisfies both readers, and {@link markdownTextProps}
|
||||
* passes it under BOTH prop names — each host ignores the one it does not
|
||||
* know. `footnotes` is left empty (the heading is sr-only; give it a real
|
||||
* string only if a locale key ever earns its place in all 19 dictionaries).
|
||||
*/
|
||||
import type { ComponentProps } from 'react'
|
||||
import { MarkdownText } from '@deepseek-ai/dsh-client-ui-primitives'
|
||||
|
||||
/** The flat copy-button pair the plugin threads through its own props
|
||||
* (e.g. MermaidMarkdownProps.codeLabels — the chunk contract stays put). */
|
||||
export interface MarkdownCopyLabels {
|
||||
copyLabel: string
|
||||
copiedLabel: string
|
||||
}
|
||||
|
||||
/** The dual-generation chrome labels object (see module doc). */
|
||||
export interface MarkdownChromeLabels extends MarkdownCopyLabels {
|
||||
/** 0.1.2-alpha.1+ nested reads. */
|
||||
code: MarkdownCopyLabels
|
||||
/** 0.1.2-alpha.1+ sr-only footnotes heading. */
|
||||
footnotes: string
|
||||
}
|
||||
|
||||
/** Build the dual-shape chrome labels from a flat copy-button pair. */
|
||||
export function markdownChromeLabels(labels: MarkdownCopyLabels): MarkdownChromeLabels {
|
||||
return {
|
||||
copyLabel: labels.copyLabel,
|
||||
copiedLabel: labels.copiedLabel,
|
||||
code: { copyLabel: labels.copyLabel, copiedLabel: labels.copiedLabel },
|
||||
footnotes: '',
|
||||
}
|
||||
}
|
||||
|
||||
/** MarkdownText props carrying the labels under BOTH prop names. The cast is
|
||||
* load-bearing: the plugin builds against the 0.1.1-rc.x declaration, where
|
||||
* `labels` does not exist yet (and vice versa on a 0.1.2-alpha.1+ host). */
|
||||
export function markdownTextProps(text: string, labels: MarkdownCopyLabels): ComponentProps<typeof MarkdownText> {
|
||||
const chrome = markdownChromeLabels(labels)
|
||||
return { text, codeLabels: chrome, labels: chrome } as unknown as ComponentProps<typeof MarkdownText>
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import { createRoot, type Root } from 'react-dom/client'
|
||||
import mermaid from 'mermaid'
|
||||
import { IconCopyOutline16, MarkdownText, writeClipboard } from '@deepseek-ai/dsh-client-ui-primitives'
|
||||
import { isDarkScheme, subscribeColorScheme } from './theme.ts'
|
||||
import { markdownTextProps } from './markdown-labels.tsx'
|
||||
import { t } from './locales.ts'
|
||||
import { sanitizeSvg } from './mermaid-sanitize.ts'
|
||||
import type { MermaidMarkdownProps } from './mermaid-blocks.ts'
|
||||
@@ -399,7 +400,7 @@ export function MermaidMarkdown({ text, codeLabels }: MermaidMarkdownProps): Rea
|
||||
|
||||
return (
|
||||
<div className={css.mermaidMarkdown} ref={containerRef}>
|
||||
<MarkdownText text={text} codeLabels={codeLabels} />
|
||||
<MarkdownText {...markdownTextProps(text, codeLabels)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -472,7 +472,7 @@ export function matchUrlTarget(tabs: readonly TabDescriptor[], url: URL): TabDes
|
||||
* The plugin version this service instance reports. Keep in lockstep with
|
||||
* `package.json`'s version — `tests/service.spec.ts` asserts the pair.
|
||||
*/
|
||||
export const SIDEBAR_SERVICE_VERSION = '0.17.0'
|
||||
export const SIDEBAR_SERVICE_VERSION = '0.17.1'
|
||||
|
||||
/**
|
||||
* Monotonic capability list consumers use to gate new API usage (features
|
||||
|
||||
Reference in New Issue
Block a user