Compare commits

...
Author SHA1 Message Date
figmar f4c44d13d6 feat: align devDeps to 0.2.0-rc.2 (21 packages)
CI / ci (push) Canceled after 0s
CI / ci-windows (push) Canceled after 0s
CI / plugin-mount (push) Canceled after 0s
- Bump 21 @deepseek-ai devDeps from 0.1.5-rc.2 → 0.2.0-rc.2
  (dsh-code-runtime stays at 0.1.5-rc.2 — no 0.2.0-rc.2 published)
- Fix sidechat-routes.ts: source.kind 'plugin' → 'user'
  (0.2.0-rc.2 removed 'plugin' from MessageSourceMap)
- Remove unused SIDE_INJECTION_PLUGIN import
- Fix test fixtures for 0.2.0-rc.2 stricter validation:
  - tool/result message role: 'user' → 'tool'
  - add toolCallId at message top level
  - assertion kind: 'plugin' → 'user'
- Icon migration: Icon*14 → Icon*Regular, Icon*16 → Icon*Medium (19 files)
- SideChatView API migration to 0.2.0-rc.2
- Add 4 new locale keys (sideChatBlockNoExitCode, codeLabel, wrapLabel, unwrapLabel)
- intercept.tsx: guard against undefined matched in SidebarProducedFiles

Verification:
- pnpm run typecheck: PASS
- pnpm run build: PASS
- npx vitest run: 1015 passed | 0 failed | 9 skipped
2026-10-11 18:25:35 +08:00
44 changed files with 1067 additions and 511 deletions
+22 -22
View File
@@ -155,29 +155,29 @@
},
"devDependencies": {
"@cordisjs/plugin-loader": "^1.0.0-rc.5",
"@deepseek-ai/dsh-agent": "0.1.5-rc.2",
"@deepseek-ai/dsh-agent-loop": "0.1.5-rc.2",
"@deepseek-ai/dsh-attachment": "0.1.5-rc.2",
"@deepseek-ai/dsh-client-locale": "0.1.5-rc.2",
"@deepseek-ai/dsh-client-ui-conversation": "0.1.5-rc.2",
"@deepseek-ai/dsh-client-ui-primitives": "0.1.5-rc.2",
"@deepseek-ai/dsh-client-ui-settings": "0.1.5-rc.2",
"@deepseek-ai/dsh-client-ui-sidebar-right": "0.1.5-rc.2",
"@deepseek-ai/dsh-client-ui-slots": "0.1.5-rc.2",
"@deepseek-ai/dsh-agent": "0.2.0-rc.2",
"@deepseek-ai/dsh-agent-loop": "0.2.0-rc.2",
"@deepseek-ai/dsh-attachment": "0.2.0-rc.2",
"@deepseek-ai/dsh-client-locale": "0.2.0-rc.2",
"@deepseek-ai/dsh-client-ui-conversation": "0.2.0-rc.2",
"@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.2",
"@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.2",
"@deepseek-ai/dsh-client-ui-sidebar-right": "0.2.0-rc.2",
"@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.2",
"@deepseek-ai/dsh-code-runtime": "0.1.5-rc.2",
"@deepseek-ai/dsh-host-webserver": "0.1.5-rc.2",
"@deepseek-ai/dsh-invariants": "0.1.5-rc.2",
"@deepseek-ai/dsh-llm": "0.1.5-rc.2",
"@deepseek-ai/dsh-scope": "0.1.5-rc.2",
"@deepseek-ai/dsh-session": "0.1.5-rc.2",
"@deepseek-ai/dsh-session-persistence": "0.1.5-rc.2",
"@deepseek-ai/dsh-session-projection": "0.1.5-rc.2",
"@deepseek-ai/dsh-settings": "0.1.5-rc.2",
"@deepseek-ai/dsh-subagent": "0.1.5-rc.2",
"@deepseek-ai/dsh-system-prompt": "0.1.5-rc.2",
"@deepseek-ai/dsh-tools": "0.1.5-rc.2",
"@deepseek-ai/dsh-user-approval": "0.1.5-rc.2",
"@deepseek-ai/dsh-util-time": "0.1.5-rc.2",
"@deepseek-ai/dsh-host-webserver": "0.2.0-rc.2",
"@deepseek-ai/dsh-invariants": "0.2.0-rc.2",
"@deepseek-ai/dsh-llm": "0.2.0-rc.2",
"@deepseek-ai/dsh-scope": "0.2.0-rc.2",
"@deepseek-ai/dsh-session": "0.2.0-rc.2",
"@deepseek-ai/dsh-session-persistence": "0.2.0-rc.2",
"@deepseek-ai/dsh-session-projection": "0.2.0-rc.2",
"@deepseek-ai/dsh-settings": "0.2.0-rc.2",
"@deepseek-ai/dsh-subagent": "0.2.0-rc.2",
"@deepseek-ai/dsh-system-prompt": "0.2.0-rc.2",
"@deepseek-ai/dsh-tools": "0.2.0-rc.2",
"@deepseek-ai/dsh-user-approval": "0.2.0-rc.2",
"@deepseek-ai/dsh-util-time": "0.2.0-rc.2",
"@eslint/js": "^10.0.1",
"@huanlin/dsh-plugin-better-locale": "^0.1.0",
"@playwright/test": "^1.62.1",
+761 -379
View File
File diff suppressed because it is too large Load Diff
+10 -10
View File
@@ -18,11 +18,11 @@
*/
import { useEffect, useState } from 'react'
import {
IconChevronLeftOutline14,
IconChevronRightOutline14,
IconLinkOutline14,
IconRefreshOutline14,
IconWarningOutline16,
IconChevronLeftOutlineRegular,
IconChevronRightOutlineRegular,
IconLinkOutlineRegular,
IconRefreshOutlineRegular,
IconWarningOutlineMedium,
} from '@deepseek-ai/dsh-client-ui-primitives'
import { VscLinkExternal } from 'react-icons/vsc'
import { api } from './api.ts'
@@ -172,7 +172,7 @@ export function BrowserView(props: TabComponentProps) {
disabled={cursor <= 0}
onClick={goBack}
>
<IconChevronLeftOutline14 />
<IconChevronLeftOutlineRegular />
</button>
<button
type="button"
@@ -182,7 +182,7 @@ export function BrowserView(props: TabComponentProps) {
disabled={cursor >= history.length - 1}
onClick={goForward}
>
<IconChevronRightOutline14 />
<IconChevronRightOutlineRegular />
</button>
<button
type="button"
@@ -191,7 +191,7 @@ export function BrowserView(props: TabComponentProps) {
title={t('refresh')}
onClick={() => { setReloadKey(key => key + 1) }}
>
<IconRefreshOutline14 />
<IconRefreshOutlineRegular />
</button>
<input
className={css.browserInput}
@@ -210,7 +210,7 @@ export function BrowserView(props: TabComponentProps) {
title={t('browserGo')}
onClick={() => { navigateTo(input) }}
>
<IconLinkOutline14 />
<IconLinkOutlineRegular />
</button>
<button
type="button"
@@ -273,7 +273,7 @@ export function BrowserEmbedBlocked(props: {
try { host = new URL(url).hostname } catch { /* keep the raw URL */ }
return (
<div className={css.browserBlocked}>
<IconWarningOutline16 size={16} />
<IconWarningOutlineMedium size={16} />
<div className={css.browserBlockedTitle}>{t('browserEmbedBlocked', { host })}</div>
<div className={css.browserBlockedDesc}>{t('browserEmbedBlockedDesc')}</div>
<div className={css.browserBlockedActions}>
+2 -2
View File
@@ -9,7 +9,7 @@
* renderer — the same one the changes tab's inline preview uses.
*/
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { IconRefreshOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
import { IconRefreshOutlineMedium } from '@deepseek-ai/dsh-client-ui-primitives'
import type { SessionScope } from './api.ts'
import { api } from './api.ts'
import type { SidebarDiffRef } from './state.ts'
@@ -170,7 +170,7 @@ export function DiffTab(props: { sessionId: string; cwd: string | undefined; dif
title={t('refresh')}
onClick={refresh}
>
<IconRefreshOutline16 size={14} />
<IconRefreshOutlineMedium size={14} />
</button>
</div>
{loading && <div className={css.gitPlaceholder}>{t('loading')}</div>}
+4 -4
View File
@@ -25,7 +25,7 @@
import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'
import { createElement } from 'react'
import clsx from 'clsx'
import { IconCheckOutline16, IconFolderOpen16, IconRefreshOutline14 } from '@deepseek-ai/dsh-client-ui-primitives'
import { IconCheckOutlineMedium, IconFolderOpenMedium, IconRefreshOutlineRegular } from '@deepseek-ai/dsh-client-ui-primitives'
import type { Context } from '../context-types.ts'
import { api, isOutsideWorkspaceMessage, mediaUrl, type SessionScope } from './api.ts'
import { BinaryDownload } from './binary-download.tsx'
@@ -447,7 +447,7 @@ export function EditorHost(props: {
title={`${t('save')} (Ctrl/Cmd+S)`}
onClick={() => { controlsRef.current?.save() }}
>
<IconCheckOutline16 size={14} />
<IconCheckOutlineMedium size={14} />
</button>
)}
{saveLabel !== '' && (
@@ -461,7 +461,7 @@ export function EditorHost(props: {
title={t('refresh')}
onClick={refreshFile}
>
<IconRefreshOutline14 size={14} />
<IconRefreshOutlineRegular size={14} />
</button>
)}
<button
@@ -472,7 +472,7 @@ export function EditorHost(props: {
aria-pressed={treeOpen}
onClick={toggleTree}
>
<IconFolderOpen16 size={14} />
<IconFolderOpenMedium size={14} />
</button>
</div>
<div className={css.editorBody}>
+13 -13
View File
@@ -24,8 +24,8 @@ import { useCallback, useEffect, useMemo, useRef, useState, type DragEvent, type
import { createPortal } from 'react-dom'
import clsx from 'clsx'
import {
Button, IconChevronRightOutline14, IconCloseFill14, IconCodeOutline16, IconCopyOutline16, IconDownloadOutline16,
IconEditOutline16, IconLinkOutline16, IconTrashOutline16, Menu, Modal, type MenuEntry, type MenuItem, writeClipboard,
Button, IconChevronRightOutlineRegular, IconCloseFillRegular, IconCodeOutlineMedium, IconCopyOutlineMedium, IconDownloadOutlineMedium,
IconEditOutlineMedium, IconLinkOutlineMedium, IconTrashOutlineMedium, Menu, Modal, type MenuEntry, type MenuItem, writeClipboard,
} from '@deepseek-ai/dsh-client-ui-primitives'
import { SiCursor, SiZedindustries } from 'react-icons/si'
import { VscFolderOpened, VscLinkExternal, VscPin, VscPinned } from 'react-icons/vsc'
@@ -486,7 +486,7 @@ export function FileTree(props: {
if (target.id === 'vscode') return <IconVscode16 size={14} />
if (target.id === 'cursor') return <SiCursor size={14} />
if (target.id === 'zed') return <SiZedindustries size={14} />
return <IconCodeOutline16 size={14} />
return <IconCodeOutlineMedium size={14} />
}
const pinned = openWithTargets
.filter(target => pinnedIds.includes(target.id))
@@ -537,7 +537,7 @@ export function FileTree(props: {
label: (
<span className={css.openWithLabel}>
<span className={css.openWithName}>{t('openWithMenu')}</span>
<IconChevronRightOutline14 size={14} className={css.openWithChevron} aria-hidden />
<IconChevronRightOutlineRegular size={14} className={css.openWithChevron} aria-hidden />
</span>
),
icon: <VscLinkExternal size={14} />,
@@ -661,7 +661,7 @@ export function FileTree(props: {
>
{dirRowIcon(entry.path, isOpen)}
<span className={css.explorerName}>{entry.name}</span>
{entry.isSymlink && <IconLinkOutline16 size={12} className={css.explorerSymlink} />}
{entry.isSymlink && <IconLinkOutlineMedium size={12} className={css.explorerSymlink} />}
{rowActions(entry)}
</div>
{isOpen && renderLevel(entry.path, depth + 1)}
@@ -694,7 +694,7 @@ export function FileTree(props: {
>
{fileRowIcon(entry.path)}
<span className={css.explorerName}>{entry.name}</span>
{entry.isSymlink && <IconLinkOutline16 size={12} className={css.explorerSymlink} />}
{entry.isSymlink && <IconLinkOutlineMedium size={12} className={css.explorerSymlink} />}
{rowActions(entry)}
</div>
)
@@ -726,7 +726,7 @@ export function FileTree(props: {
aria-label={t('dismiss')}
onClick={() => { setActionError(null) }}
>
<IconCloseFill14 />
<IconCloseFillRegular />
</button>
</div>
)}
@@ -829,7 +829,7 @@ export function FileTree(props: {
items={[
// The open escapes head the FILE menu (dirs only get copy).
...(rowMenu?.isDir === false && onOpenFileNewTab !== undefined
? [{ id: 'open-new-tab', label: t('openFileNewTab'), icon: <IconCodeOutline16 size={14} /> }]
? [{ id: 'open-new-tab', label: t('openFileNewTab'), icon: <IconCodeOutlineMedium size={14} /> }]
: []),
...(rowMenu?.isDir === false && onOpenFileSide !== undefined
? [{ id: 'open-side', label: t('openFileSide'), icon: <VscFolderOpened size={14} /> }]
@@ -837,21 +837,21 @@ export function FileTree(props: {
...openWithEntries(),
// Download applies to files only (the host route refuses directories).
...(rowMenu?.isDir === false
? [{ id: 'download', label: t('download'), icon: <IconDownloadOutline16 size={14} /> }]
? [{ id: 'download', label: t('download'), icon: <IconDownloadOutlineMedium size={14} /> }]
: []),
// Upload into a directory (incl. the workspace root row).
...(rowMenu?.isDir === true
? [{ id: 'upload-here', label: t('uploadHere'), icon: <IconUploadOutline16 size={14} /> }]
: []),
{ id: 'relative', label: t('copyRelative'), icon: <IconCopyOutline16 size={14} /> },
{ id: 'absolute', label: t('copyAbsolute'), icon: <IconCopyOutline16 size={14} /> },
{ id: 'relative', label: t('copyRelative'), icon: <IconCopyOutlineMedium size={14} /> },
{ id: 'absolute', label: t('copyAbsolute'), icon: <IconCopyOutlineMedium size={14} /> },
// Explorer mutations close the menu; the workspace ROOT row is the
// session itself — never renamable or deletable (server double-guards).
...(rowMenu !== null && rowMenu.path !== cwd
? [
{ id: 'mutate-sep', type: 'separator' } as MenuEntry,
{ id: 'rename', label: t('rename'), icon: <IconEditOutline16 size={14} /> },
{ id: 'delete', label: t('delete'), icon: <IconTrashOutline16 size={14} />, danger: true },
{ id: 'rename', label: t('rename'), icon: <IconEditOutlineMedium size={14} /> },
{ id: 'delete', label: t('delete'), icon: <IconTrashOutlineMedium size={14} />, danger: true },
]
: []),
]}
+8 -8
View File
@@ -42,9 +42,9 @@
*/
import { Fragment, useEffect, useMemo, useRef, useState, type ReactNode } from 'react'
import {
IconChevronDownOutline14,
IconPlusOutline16,
IconSettingsOutline16,
IconChevronDownOutlineRegular,
IconPlusOutlineMedium,
IconSettingsOutlineMedium,
Input,
Menu,
Modal,
@@ -420,7 +420,7 @@ function SelectMenu(props: {
<span className={css.selectAnchorText}>
{selected.length === 0 ? (placeholder ?? '—') : selected.map(option => textOf(option.title)).join(', ')}
</span>
<IconChevronDownOutline14 size={12} />
<IconChevronDownOutlineRegular size={12} />
</button>
)
@@ -817,7 +817,7 @@ export function SideCardSection({ store, service }: SideCardSectionProps) {
aria-label={`${props.title} ${t('settingsPopup')}`}
onClick={props.onOpenSettings}
>
<IconSettingsOutline16 size={12} />
<IconSettingsOutlineMedium size={12} />
<span>{t('settingsPopup')}</span>
</button>
)}
@@ -893,7 +893,7 @@ export function SideCardSection({ store, service }: SideCardSectionProps) {
title={t('settingsPopup')}
onClick={() => { setStripSettingsOpen(true) }}
>
<IconSettingsOutline16 size={14} />
<IconSettingsOutlineMedium size={14} />
</button>
)}
</span>
@@ -935,7 +935,7 @@ export function SideCardSection({ store, service }: SideCardSectionProps) {
>
<span className={css.cardTop}>
<span className={css.cardIconChip}>
<IconPlusOutline16 size={16} />
<IconPlusOutlineMedium size={16} />
</span>
<span className={css.cardTitle}>{t('addPluginsTabCard')}</span>
</span>
@@ -974,7 +974,7 @@ export function SideCardSection({ store, service }: SideCardSectionProps) {
>
<span className={css.cardTop}>
<span className={css.cardIconChip}>
<IconPlusOutline16 size={16} />
<IconPlusOutlineMedium size={16} />
</span>
<span className={css.cardTitle}>{t('addPluginsViewerCard')}</span>
</span>
+35 -23
View File
@@ -29,16 +29,16 @@ import clsx from 'clsx'
import {
ConnectionIndicator,
DiffBlock,
IconApiOutline14,
IconBrowseOutline16,
IconChevronRightOutline14,
IconEditOutline16,
IconNewChatOutline16,
IconPlusOutline16,
IconSearchOutline16,
IconSendOutline16,
IconSparkle16,
IconStopFill16,
IconApiOutlineRegular,
IconBrowseOutlineMedium,
IconChevronRightOutlineRegular,
IconEditOutlineMedium,
IconNewChatOutlineMedium,
IconPlusOutlineMedium,
IconSearchOutlineMedium,
IconSendOutlineMedium,
IconSparkleMedium,
IconStopFillMedium,
MarkdownText,
Menu,
ReadBlock,
@@ -198,7 +198,7 @@ function CollapsibleRow(props: {
)}
>
<span className={css.sidechatRowChevron}>
<IconChevronRightOutline14 size={12} />
<IconChevronRightOutlineRegular size={12} />
</span>
{leading}
{label}
@@ -239,19 +239,19 @@ function toolLeading(name: string, failed: boolean): React.ReactNode {
switch (name) {
case 'bash':
case 'pwsh':
return <IconApiOutline14 size={14} />
return <IconApiOutlineRegular size={14} />
case 'read':
case 'web_fetch':
return <IconBrowseOutline16 size={14} />
return <IconBrowseOutlineMedium size={14} />
case 'edit':
case 'write':
return <IconEditOutline16 size={14} />
return <IconEditOutlineMedium size={14} />
case 'grep':
case 'glob':
case 'web_search':
return <IconSearchOutline16 size={14} />
return <IconSearchOutlineMedium size={14} />
default:
return <IconSparkle16 size={14} />
return <IconSparkleMedium size={14} />
}
}
@@ -354,13 +354,26 @@ export function SideChatView(props: {
...shared,
signal: (signal: string) => t('sideChatBlockSignal', { signal }),
exitCode: (exitCode: number) => t('sideChatBlockExitCode', { code: exitCode }),
noExitCode: t('sideChatBlockNoExitCode'),
running: t('sideChatBlockRunning'),
failed: t('sideChatBlockFailed'),
done: t('sideChatBlockDone'),
noOutput: t('sideChatBlockNoOutput'),
},
diff: { ...shared, files: (count: number) => t('sideChatBlockFiles', { count }) },
read: { ...shared, window: (shown: number, total: number) => t('sideChatBlockWindow', { shown, total }) },
diff: {
...shared,
codeLabel: t('codeLabel'),
wrapLabel: t('wrapLabel'),
unwrapLabel: t('unwrapLabel'),
files: (count: number) => t('sideChatBlockFiles', { count }),
},
read: {
...shared,
codeLabel: t('codeLabel'),
wrapLabel: t('wrapLabel'),
unwrapLabel: t('unwrapLabel'),
window: (shown: number, total: number) => t('sideChatBlockWindow', { shown, total }),
},
}
}, [])
@@ -593,7 +606,7 @@ export function SideChatView(props: {
const menuItems = useMemo<MenuEntry[]>(() => {
const items: MenuEntry[] = [
{ id: '$new', label: t('sideChatNew'), icon: <IconPlusOutline16 /> },
{ id: '$new', label: t('sideChatNew'), icon: <IconPlusOutlineMedium /> },
]
if (threads.length > 0) {
items.push({ type: 'separator', id: '$sep' })
@@ -674,7 +687,7 @@ export function SideChatView(props: {
return (
<div className={css.sidechat}>
<div className={css.sidechatHero}>
<IconNewChatOutline16 />
<IconNewChatOutlineMedium />
<div
className={clsx(
css.sidechatHeroTitle,
@@ -739,7 +752,6 @@ export function SideChatView(props: {
<ConnectionIndicator
state={connectionState}
disconnectedLabel={t('sideChatConnDisconnected')}
reconnectLabel={t('sideChatConnReconnect')}
connectingLabel={t('sideChatConnConnecting')}
recoveredLabel={t('sideChatConnRecovered')}
reconnectActionLabel={t('sideChatConnReconnectAction')}
@@ -791,7 +803,7 @@ export function SideChatView(props: {
disabled={busy !== null}
title={t('sideChatCancelTitle')}
>
<IconStopFill16 />
<IconStopFillMedium />
</button>
) : (
<button
@@ -802,7 +814,7 @@ export function SideChatView(props: {
disabled={composer.trim() === '' || busy !== null}
title={t('sideChatSend')}
>
<IconSendOutline16 />
<IconSendOutlineMedium />
</button>
)}
</div>
+2 -2
View File
@@ -27,7 +27,7 @@
import { useCallback, useEffect, useMemo, useRef, useState, type DragEvent as ReactDragEvent, type ReactNode } from 'react'
import { useSyncExternalStore } from 'react'
import clsx from 'clsx'
import { IconCloseFill14, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives'
import { IconCloseFillRegular, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives'
import type { Context } from '../context-types.ts'
import { referenceInChat as referenceInChatShared } from './reference-in-chat.ts'
import {
@@ -784,7 +784,7 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) {
aria-label={t('collapseBottomPanel')}
onClick={() => { store.reduce(toggleBottomPanel) }}
>
<IconCloseFill14 />
<IconCloseFillRegular />
</button>
</Tooltip>
<div className={css.panelBody}>
+3 -3
View File
@@ -23,7 +23,7 @@ import { useCallback, useEffect, useMemo, useRef, useState, type KeyboardEvent }
import { useSyncExternalStore } from 'react'
import clsx from 'clsx'
import {
IconRefreshOutline14, StateDot,
IconRefreshOutlineRegular, StateDot,
} from '@deepseek-ai/dsh-client-ui-primitives'
import type {
Context,
@@ -250,7 +250,7 @@ function CatalogRows({
className={css.subagentErrorRetry}
onClick={() => { refresh(parentSessionId) }}
>
<IconRefreshOutline14 />
<IconRefreshOutlineRegular />
{t('retry')}
</button>
</div>
@@ -789,7 +789,7 @@ export function SubagentView(props: {
disabled={rootId === undefined}
onClick={() => { if (rootId !== undefined) refresh(rootId) }}
>
<IconRefreshOutline14 />
<IconRefreshOutlineRegular />
</button>
</div>
<div
+3 -3
View File
@@ -10,7 +10,7 @@
import { useEffect, useRef, useState, type ReactNode } from 'react'
import clsx from 'clsx'
import {
IconCloseFill14, IconPlusOutline16, Menu,
IconCloseFillRegular, IconPlusOutlineMedium, Menu,
} from '@deepseek-ai/dsh-client-ui-primitives'
import type { SidebarTab } from './state.ts'
import { isAgentTabId } from './state.ts'
@@ -241,7 +241,7 @@ export function TabBar(props: {
onClose(tab.id)
}}
>
<IconCloseFill14 />
<IconCloseFillRegular />
</button>
</div>
)
@@ -275,7 +275,7 @@ export function TabBar(props: {
title={t('newTab')}
onClick={() => { setMenuOpen(v => !v); setTabMenu(null) }}
>
<IconPlusOutline16 />
<IconPlusOutlineMedium />
</button>
)}
/>
+2 -2
View File
@@ -19,7 +19,7 @@ import clsx from 'clsx'
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 { IconCheckOutlineMedium, MarkdownText } from '@deepseek-ai/dsh-client-ui-primitives'
import { markdownTextProps } from './markdown-labels.tsx'
import { api, htmlUrl } from './api.ts'
import { markdownPreviewSource } from './markdown-frontmatter.ts'
@@ -462,7 +462,7 @@ export function TextEditor(props: FileViewerProps) {
title={`${t('save')} (Ctrl/Cmd+S)`}
onClick={save}
>
<IconCheckOutline16 />
<IconCheckOutlineMedium />
</button>
)}
{saveLabel !== '' && <span className={clsx(css.editorStatus, saveState === 'failed' && css.editorStatusError)}>{saveLabel}</span>}
+3 -3
View File
@@ -17,7 +17,7 @@
*/
import { useEffect, useRef, useState, type InputHTMLAttributes } from 'react'
import clsx from 'clsx'
import { IconFolderOpen16, IconRefreshOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
import { IconFolderOpenMedium, IconRefreshOutlineMedium } from '@deepseek-ai/dsh-client-ui-primitives'
import { api } from './api.ts'
import type { BetterSidebarService } from './service.ts'
import type { SidebarStore } from './state.ts'
@@ -195,7 +195,7 @@ export function TreePanel(props: {
title={t('refresh')}
onClick={() => { setRefreshTick(tick => tick + 1) }}
>
<IconRefreshOutline16 size={14} />
<IconRefreshOutlineMedium size={14} />
</button>
<button
type="button"
@@ -215,7 +215,7 @@ export function TreePanel(props: {
disabled={busy}
onClick={() => { folderInputRef.current?.click() }}
>
<IconFolderOpen16 size={14} />
<IconFolderOpenMedium size={14} />
</button>
<input
ref={fileInputRef}
+3 -3
View File
@@ -8,7 +8,7 @@
* `browser:<n>` the same way (no quota). The editor IS the files window
* (the old standalone explorer merged into it).
*/
import { IconCodeOutline16, IconPanelLeftOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
import { IconCodeOutlineMedium, IconPanelLeftOutlineMedium } from '@deepseek-ai/dsh-client-ui-primitives'
import type { Context } from '../../context-types.ts'
import {
browserTabIcon, changesTabIcon, filesTabIcon, sidechatTabIcon, tasksTabIcon, terminalTabIcon,
@@ -109,13 +109,13 @@ export function builtinTabs(ctx: Context, options: BuiltinTabOptions = {}): read
options: [
{
value: true,
icon: (size: number) => <IconPanelLeftOutline16 size={size} />,
icon: (size: number) => <IconPanelLeftOutlineMedium size={size} />,
title: () => t('editorExplorerMerged'),
desc: () => t('editorExplorerMergedDesc'),
},
{
value: false,
icon: (size: number) => <IconCodeOutline16 size={size} />,
icon: (size: number) => <IconCodeOutlineMedium size={size} />,
title: () => t('editorExplorerSplit'),
desc: () => t('editorExplorerSplitDesc'),
},
+3 -3
View File
@@ -22,7 +22,7 @@
* and `icon` — so the Side card settings page can render the enable/disable
* inventory without hardcoding (eating our own dogfood).
*/
import { IconCodeOutline16, IconDownloadOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
import { IconCodeOutlineMedium, IconDownloadOutlineMedium } from '@deepseek-ai/dsh-client-ui-primitives'
import { lazyChunkComponent } from '../lazy-chunk.tsx'
import { PdfView } from '../PdfView.tsx'
import { BinaryDownload } from '../binary-download.tsx'
@@ -103,7 +103,7 @@ export function builtinViewers(): readonly FileViewerDescriptor[] {
{
id: 'code',
title: () => t('viewerCode'),
icon: (size: number) => <IconCodeOutline16 size={size} />,
icon: (size: number) => <IconCodeOutlineMedium size={size} />,
exts: [],
priority: -100,
fetchStrategy: 'fsRead',
@@ -112,7 +112,7 @@ export function builtinViewers(): readonly FileViewerDescriptor[] {
{
id: 'binary-download',
title: () => t('viewerBinary'),
icon: (size: number) => <IconDownloadOutline16 size={size} />,
icon: (size: number) => <IconDownloadOutlineMedium size={size} />,
exts: ['doc', 'xls', 'ppt'],
priority: -50,
fetchStrategy: 'binary-download',
+4 -4
View File
@@ -9,7 +9,7 @@
* diff tab via the shell.
*/
import { useEffect, useMemo, useRef, useState, type PointerEvent as ReactPointerEvent } from 'react'
import { IconCloseOutline16, IconRefreshOutline16, IconRightUpOutline16, MarkdownText } from '@deepseek-ai/dsh-client-ui-primitives'
import { IconCloseOutlineMedium, IconRefreshOutlineMedium, IconRightUpOutlineMedium, MarkdownText } from '@deepseek-ai/dsh-client-ui-primitives'
import type { SessionScope } from '../api.ts'
import { api, htmlUrl } from '../api.ts'
import { t } from '../locales.ts'
@@ -491,7 +491,7 @@ export function DiffPane({ target, scope, height, onHeightCommit, onClose, onExp
disabled={loading}
onClick={() => { setTick(value => value + 1) }}
>
<IconRefreshOutline16 size={14} />
<IconRefreshOutlineMedium size={14} />
</button>
<button
type="button"
@@ -500,7 +500,7 @@ export function DiffPane({ target, scope, height, onHeightCommit, onClose, onExp
title={t('changesOpenDiffTab')}
onClick={onExpand}
>
<IconRightUpOutline16 size={14} />
<IconRightUpOutlineMedium size={14} />
</button>
</>
)}
@@ -543,7 +543,7 @@ export function DiffPane({ target, scope, height, onHeightCommit, onClose, onExp
title={t('changesClosePreview')}
onClick={onClose}
>
<IconCloseOutline16 size={14} />
<IconCloseOutlineMedium size={14} />
</button>
</div>
{target.kind === 'op' && htmlOp && rendering && htmlRenderSrc !== ''
+13 -13
View File
@@ -12,8 +12,8 @@
*/
import { useCallback, useEffect, useRef, useState, type MouseEvent, type ReactNode } from 'react'
import {
Button, IconCodeOutline16, IconCopyOutline16, IconPlusOutline16,
IconRefreshOutline16, IconTrashOutline16, Input, Menu, Modal, writeClipboard,
Button, IconCodeOutlineMedium, IconCopyOutlineMedium, IconPlusOutlineMedium,
IconRefreshOutlineMedium, IconTrashOutlineMedium, Input, Menu, Modal, writeClipboard,
} from '@deepseek-ai/dsh-client-ui-primitives'
import type { GitLogEntry, GitStatusEntry, GitStatusResult, GitWorktree, SessionScope } from '../api.ts'
import { api } from '../api.ts'
@@ -450,7 +450,7 @@ export function GitLens(props: GitLensProps) {
disabled={busy}
onClick={() => { void stageEntry(entry, staged) }}
>
{staged ? <IconTrashOutline16 /> : <IconPlusOutline16 />}
{staged ? <IconTrashOutlineMedium /> : <IconPlusOutlineMedium />}
</button>
</div>
)
@@ -504,7 +504,7 @@ export function GitLens(props: GitLensProps) {
title={t('refresh')}
onClick={() => { void refresh() }}
>
<IconRefreshOutline16 size={14} />
<IconRefreshOutlineMedium size={14} />
</button>
</div>
@@ -624,17 +624,17 @@ export function GitLens(props: GitLensProps) {
// that confuses the user; with the fence disarmed (the
// `workspaceFence` pref) the open is allowed through.
...(fileMenu !== null && (store.getPrefs().workspaceFence === false || isWithinWorkspace(scope.cwd ?? '', resolveSidebarPath(repoRoot ?? selectedWorktree ?? scope.cwd, fileMenu.entry.path)))
? [{ id: 'open', label: t('openEditor'), icon: <IconCodeOutline16 size={14} /> }]
? [{ id: 'open', label: t('openEditor'), icon: <IconCodeOutlineMedium size={14} /> }]
: []),
fileMenu?.staged === true
? { id: 'stage', label: t('unstage'), icon: <IconTrashOutline16 size={14} /> }
: { id: 'stage', label: t('stage'), icon: <IconPlusOutline16 size={14} /> },
? { id: 'stage', label: t('unstage'), icon: <IconTrashOutlineMedium size={14} /> }
: { id: 'stage', label: t('stage'), icon: <IconPlusOutlineMedium size={14} /> },
...(fileMenu !== null && !isUntracked(fileMenu.entry)
? [{ id: 'discard', label: t('discard'), icon: <IconTrashOutline16 size={14} />, danger: true }]
? [{ id: 'discard', label: t('discard'), icon: <IconTrashOutlineMedium size={14} />, danger: true }]
: []),
{ type: 'separator', id: 'sep1' },
{ id: 'relative', label: t('copyRelative'), icon: <IconCopyOutline16 size={14} /> },
{ id: 'absolute', label: t('copyAbsolute'), icon: <IconCopyOutline16 size={14} /> },
{ id: 'relative', label: t('copyRelative'), icon: <IconCopyOutlineMedium size={14} /> },
{ id: 'absolute', label: t('copyAbsolute'), icon: <IconCopyOutlineMedium size={14} /> },
]}
onSelect={(id) => {
const target = fileMenu
@@ -683,9 +683,9 @@ export function GitLens(props: GitLensProps) {
onClose={() => { setHistoryMenu(null) }}
items={[
{ id: 'view', label: t('viewCommitDiff') },
{ id: 'copyShort', label: t('copyShortHash'), icon: <IconCopyOutline16 size={14} /> },
{ id: 'copyFull', label: t('copyFullHash'), icon: <IconCopyOutline16 size={14} /> },
{ id: 'copySubject', label: t('copySubject'), icon: <IconCopyOutline16 size={14} /> },
{ id: 'copyShort', label: t('copyShortHash'), icon: <IconCopyOutlineMedium size={14} /> },
{ id: 'copyFull', label: t('copyFullHash'), icon: <IconCopyOutlineMedium size={14} /> },
{ id: 'copySubject', label: t('copySubject'), icon: <IconCopyOutlineMedium size={14} /> },
{ type: 'separator', id: 'sep2' },
{ id: 'revert', label: t('revertCommit'), danger: true },
{ id: 'cherryPick', label: t('cherryPickCommit'), danger: true },
+3 -2
View File
@@ -6,7 +6,7 @@
* deliverables entry; when nothing was produced the selector returns null
* and the original row renders unchanged.
*/
import { IconCodeOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
import { IconCodeOutlineMedium } from '@deepseek-ai/dsh-client-ui-primitives'
import type { Context } from '../context-types.ts'
import { revealPaths, type SidebarStore } from './state.ts'
import { t } from './locales.ts'
@@ -59,6 +59,7 @@ export function SidebarProducedFiles(props: {
onShowInFolder: (files: readonly string[]) => void
}) {
const { matched, openInSidebar, onShowInFolder } = props
if (!matched || matched.length === 0) return null
const shown = matched.slice(0, 6)
const hidden = matched.length - shown.length
return (
@@ -75,7 +76,7 @@ export function SidebarProducedFiles(props: {
title={path}
onClick={() => { openInSidebar(path) }}
>
<IconCodeOutline16 size={12} />
<IconCodeOutlineMedium size={12} />
<span>{name}</span>
</button>
)
+8
View File
@@ -369,6 +369,14 @@ export const ar: Record<string, string> = {
sideChatBlockRunning: 'قيد التشغيل',
sideChatBlockFailed: 'فشل',
sideChatBlockDone: 'اكتمل',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(لا يوجد إخراج)',
sideChatBlockFiles: '{count} ملفات',
sideChatBlockWindow: '{shown} من {total} سطرًا',
+7
View File
@@ -354,6 +354,13 @@ export const de: Record<string, string> = {
sideChatBlockRunning: 'Läuft',
sideChatBlockFailed: 'Fehlgeschlagen',
sideChatBlockDone: 'Fertig',
sideChatBlockNoExitCode: '(kein Exit-Code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(keine Ausgabe)',
sideChatBlockFiles: '{count} Dateien',
sideChatBlockWindow: '{shown} von {total} Zeilen',
+8
View File
@@ -361,6 +361,14 @@ export const fr: Record<string, string> = {
sideChatBlockRunning: 'En cours',
sideChatBlockFailed: 'Échec',
sideChatBlockDone: 'Terminé',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(aucune sortie)',
sideChatBlockFiles: '{count} fichiers',
sideChatBlockWindow: '{shown} sur {total} lignes',
+8
View File
@@ -368,6 +368,14 @@ export const hi: Record<string, string> = {
sideChatBlockRunning: 'चल रहा है',
sideChatBlockFailed: 'विफल',
sideChatBlockDone: 'पूर्ण',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(कोई आउटपुट नहीं)',
sideChatBlockFiles: '{count} फ़ाइलें',
sideChatBlockWindow: 'कुल {total} में से {shown} पंक्तियाँ',
+8
View File
@@ -366,6 +366,14 @@ export const id: Record<string, string> = {
sideChatBlockRunning: 'Berjalan',
sideChatBlockFailed: 'Gagal',
sideChatBlockDone: 'Selesai',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(tanpa output)',
sideChatBlockFiles: '{count} file',
sideChatBlockWindow: '{shown} dari {total} baris',
+8
View File
@@ -359,6 +359,14 @@ export const it: Record<string, string> = {
sideChatBlockRunning: 'In esecuzione',
sideChatBlockFailed: 'Non riuscito',
sideChatBlockDone: 'Completato',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(nessun output)',
sideChatBlockFiles: '{count} file',
sideChatBlockWindow: '{shown} di {total} righe',
+8
View File
@@ -368,6 +368,14 @@ export const ja: Record<string, string> = {
sideChatBlockRunning: '実行中',
sideChatBlockFailed: '失敗',
sideChatBlockDone: '完了',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(出力なし)',
sideChatBlockFiles: '{count} 個のファイル',
sideChatBlockWindow: '全 {total} 行中 {shown} 行を表示',
+8
View File
@@ -360,6 +360,14 @@ export const ko: Record<string, string> = {
sideChatBlockRunning: '실행 중',
sideChatBlockFailed: '실패',
sideChatBlockDone: '완료',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(출력 없음)',
sideChatBlockFiles: '파일 {count}개',
sideChatBlockWindow: '전체 {total}줄 중 {shown}줄 표시',
+7
View File
@@ -366,6 +366,13 @@ export const nl: Record<string, string> = {
sideChatBlockRunning: 'Wordt uitgevoerd',
sideChatBlockFailed: 'Mislukt',
sideChatBlockDone: 'Voltooid',
sideChatBlockNoExitCode: '(geen exitcode)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(geen uitvoer)',
sideChatBlockFiles: '{count} bestanden',
sideChatBlockWindow: '{shown} van {total} regels',
+8
View File
@@ -370,6 +370,14 @@ export const pl: Record<string, string> = {
sideChatBlockRunning: 'Uruchomione',
sideChatBlockFailed: 'Niepowodzenie',
sideChatBlockDone: 'Zakończono',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(brak wyniku)',
sideChatBlockFiles: 'Pliki: {count}',
sideChatBlockWindow: '{shown} z {total} wierszy',
+8
View File
@@ -351,6 +351,14 @@ export const pt: Record<string, string> = {
sideChatBlockRunning: 'Em execução',
sideChatBlockFailed: 'Falhou',
sideChatBlockDone: 'Concluído',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(sem saída)',
sideChatBlockFiles: '{count} arquivos',
sideChatBlockWindow: '{shown} de {total} linhas',
+8
View File
@@ -366,6 +366,14 @@ export const ru: Record<string, string> = {
sideChatBlockRunning: 'Выполняется',
sideChatBlockFailed: 'Ошибка',
sideChatBlockDone: 'Готово',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(нет вывода)',
sideChatBlockFiles: 'Файлов: {count}',
sideChatBlockWindow: '{shown} из {total} строк',
+8
View File
@@ -351,6 +351,14 @@ export const sv: Record<string, string> = {
sideChatBlockRunning: 'Körs',
sideChatBlockFailed: 'Misslyckades',
sideChatBlockDone: 'Klar',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(ingen utdata)',
sideChatBlockFiles: '{count} filer',
sideChatBlockWindow: '{shown} av {total} rader',
+8
View File
@@ -368,6 +368,14 @@ export const th: Record<string, string> = {
sideChatBlockRunning: 'กำลังทำงาน',
sideChatBlockFailed: 'ล้มเหลว',
sideChatBlockDone: 'เสร็จสิ้น',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(ไม่มีเอาต์พุต)',
sideChatBlockFiles: '{count} ไฟล์',
sideChatBlockWindow: '{shown} จาก {total} บรรทัด',
+8
View File
@@ -368,6 +368,14 @@ export const tr: Record<string, string> = {
sideChatBlockRunning: 'Çalışıyor',
sideChatBlockFailed: 'Başarısız',
sideChatBlockDone: 'Tamamlandı',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(çıktı yok)',
sideChatBlockFiles: '{count} dosya',
sideChatBlockWindow: '{total} satırdan {shown} satır',
+8
View File
@@ -368,6 +368,14 @@ export const vi: Record<string, string> = {
sideChatBlockRunning: 'Đang chạy',
sideChatBlockFailed: 'Thất bại',
sideChatBlockDone: 'Hoàn tất',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(không có đầu ra)',
sideChatBlockFiles: '{count} tệp',
sideChatBlockWindow: '{shown} trong {total} dòng',
+8
View File
@@ -383,6 +383,14 @@ export const zhHK: Record<string, string> = {
sideChatBlockRunning: '執行中',
sideChatBlockFailed: '失敗',
sideChatBlockDone: '完成',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: '代码',
wrapLabel: '换行',
unwrapLabel: '不换行',
sideChatBlockNoOutput: '(無輸出)',
sideChatBlockFiles: '{count} 個檔案',
sideChatBlockWindow: '共 {total} 行 · 顯示 {shown} 行',
+8
View File
@@ -383,6 +383,14 @@ export const zhMO: Record<string, string> = {
sideChatBlockRunning: '執行中',
sideChatBlockFailed: '失敗',
sideChatBlockDone: '完成',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: '代码',
wrapLabel: '换行',
unwrapLabel: '不换行',
sideChatBlockNoOutput: '(無輸出)',
sideChatBlockFiles: '{count} 個檔案',
sideChatBlockWindow: '共 {total} 行 · 顯示 {shown} 行',
+8
View File
@@ -383,6 +383,14 @@ export const zhTW: Record<string, string> = {
sideChatBlockRunning: '執行中',
sideChatBlockFailed: '失敗',
sideChatBlockDone: '完成',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: '代码',
wrapLabel: '换行',
unwrapLabel: '不换行',
sideChatBlockNoOutput: '(無輸出)',
sideChatBlockFiles: '{count} 個檔案',
sideChatBlockWindow: '共 {total} 行 · 顯示 {shown} 行',
+11
View File
@@ -380,6 +380,13 @@ export const zh = {
sideChatBlockRunning: '运行中',
sideChatBlockFailed: '失败',
sideChatBlockDone: '完成',
sideChatBlockNoExitCode: '无退出码',
codeLabel: '代码',
wrapLabel: '换行',
unwrapLabel: '不换行',
sideChatBlockNoOutput: '(无输出)',
sideChatBlockFiles: '{count} 个文件',
sideChatBlockWindow: '共 {total} 行 · 显示 {shown} 行',
@@ -822,6 +829,10 @@ export const en: Record<keyof typeof zh, string> = {
sideChatBlockRunning: 'Running',
sideChatBlockFailed: 'Failed',
sideChatBlockDone: 'Done',
sideChatBlockNoExitCode: '(no exit code)',
codeLabel: 'Code',
wrapLabel: 'Wrap',
unwrapLabel: 'Unwrap',
sideChatBlockNoOutput: '(no output)',
sideChatBlockFiles: '{count} files',
sideChatBlockWindow: '{shown} of {total} lines',
+2 -2
View File
@@ -18,7 +18,7 @@
*/
import { useLayoutEffect, useRef, useState } from 'react'
import type { ReactNode } from 'react'
import { IconListPenOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
import { IconListPenOutlineMedium } from '@deepseek-ai/dsh-client-ui-primitives'
import { t } from './locales.ts'
import css from './sidebar.module.css'
@@ -136,7 +136,7 @@ export function MdToc(): ReactNode {
aria-expanded={open}
onClick={() => { setOpen(!open) }}
>
<IconListPenOutline16 />
<IconListPenOutlineMedium />
</button>
)}
</div>
+2 -2
View File
@@ -28,7 +28,7 @@ import { useCallback, useEffect, useLayoutEffect, useRef, useState, type MouseEv
import { createPortal } from 'react-dom'
import { createRoot, type Root } from 'react-dom/client'
import mermaid from 'mermaid'
import { IconCopyOutline16, MarkdownText, writeClipboard } from '@deepseek-ai/dsh-client-ui-primitives'
import { IconCopyOutlineMedium, 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'
@@ -288,7 +288,7 @@ function MermaidDiagram({ code }: { code: string }): React.ReactNode {
aria-label={t('copy')}
title={t('copy')}
>
<IconCopyOutline16 />
<IconCopyOutlineMedium />
<span>{copied ? t('copied') : t('copy')}</span>
</button>
</div>
+2 -2
View File
@@ -10,7 +10,7 @@
* this component owns only its own section.
*/
import { useState } from 'react'
import { IconCloseOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
import { IconCloseOutlineMedium } from '@deepseek-ai/dsh-client-ui-primitives'
import {
isValidCustomEditor,
newCustomEditorId,
@@ -121,7 +121,7 @@ export function OpenWithSettings(props: {
title={t('openWithSettingsRemove')}
onClick={() => { removeCustom(editor.id) }}
>
<IconCloseOutline16 size={14} />
<IconCloseOutlineMedium size={14} />
</button>
</div>
))}
+1 -2
View File
@@ -40,7 +40,6 @@ import {
liveEventsOf,
resolvePresetId,
SIDE_BOUNDARY_PROMPT,
SIDE_INJECTION_PLUGIN,
SIDE_NEW_THREAD_TITLE,
sideLabel,
type SeedEvent,
@@ -159,7 +158,7 @@ function admitFollowup(agent: Agent, blocks: ContentBlock[]): void {
function admitFirstContact(agent: Agent, injectionText: string, question: string): void {
agent.inject(createUserMessage({
content: textPrompt(injectionText),
source: { kind: 'plugin', plugin: SIDE_INJECTION_PLUGIN },
source: { kind: 'user' },
}))
admitFollowup(agent, textPrompt(question))
}
+3 -3
View File
@@ -11,7 +11,7 @@ import { describe, expect, it, vi } from 'vitest'
import { SUBAGENT_DESCRIPTOR_VERSION } from '@deepseek-ai/dsh-subagent'
import { buildSidechatApi } from '../src/sidechat-routes.ts'
import { SidebarError } from '../src/wire.ts'
import { SIDE_BOUNDARY_PROMPT, SIDE_INJECTION_PLUGIN, SIDE_NEW_THREAD_TITLE, sideLabel } from '../src/sidechat-core.ts'
import { SIDE_BOUNDARY_PROMPT, SIDE_NEW_THREAD_TITLE, sideLabel } from '../src/sidechat-core.ts'
import type { Context } from '../src/context-types.ts'
/** A fake live agent (inject/followup/cancel spied). */
@@ -165,7 +165,7 @@ describe('sidechat.start', () => {
// context, no wake), the question is the follow-up that wakes the driver.
expect(child.inject).toHaveBeenCalledTimes(1)
const injection = child.inject.mock.calls[0]![0] as { content: Array<{ type: string; text: string }>; source: { kind: string; plugin: string } }
expect(injection.source).toEqual({ kind: 'plugin', plugin: SIDE_INJECTION_PLUGIN })
expect(injection.source).toEqual({ kind: 'user' })
expect(injection.content[0]!.text.startsWith(SIDE_BOUNDARY_PROMPT)).toBe(true)
expect(injection.content[0]!.text).not.toContain('explain the event flow')
expect(child.followup).toHaveBeenCalledTimes(1)
@@ -259,7 +259,7 @@ describe('sidechat.start', () => {
await api['sidechat.prompt']({ childId, text: 'explain the event flow' })
expect(child.inject).toHaveBeenCalledTimes(1)
const injection = child.inject.mock.calls[0]![0] as { content: Array<{ text: string }>; source: { kind: string } }
expect(injection.source.kind).toBe('plugin')
expect(injection.source.kind).toBe('user')
expect(injection.content[0]!.text.startsWith(SIDE_BOUNDARY_PROMPT)).toBe(true)
expect(injection.content[0]!.text).toContain('`bash` (executing)')
expect(child.followup).toHaveBeenCalledTimes(1)
+2 -1
View File
@@ -185,7 +185,8 @@ describe('sidechat seed fork markers vs the reconstructed inbox', () => {
turn: 2, step: 1,
message: {
id: 'm-r',
role: 'user',
role: 'tool',
toolCallId: 'c1',
content: [{ type: 'tool-result', toolCallId: 'c1', content: [{ type: 'text', text: 'ok' }] }],
source: { kind: 'tool', callId: 'c1' },
},