feat(chat): add four work detail modes and legacy mappings

This commit is contained in:
imccyu committed 2026-09-23 19:48:45 +08:00
1 parent b660f72d4e
commit 015a9b202c
7 files changed
+47 -28

No files matched your search

+15 -9
View File
@@ -9,22 +9,27 @@ export const CHAT_SETTINGS_NAMESPACE = 'ui-chat'
export const TRANSCRIPT_VIEW_FIELD = 'transcriptView'
/** Work-details presentation modes a user can choose. */
export const TRANSCRIPT_VIEW_MODES = ['compact', 'detailed', 'expanded'] as const
export const TRANSCRIPT_VIEW_MODES = ['compact', 'standard', 'detailed', 'verbose'] as const
/** Work-details presentation mode. */
export type TranscriptViewMode = typeof TRANSCRIPT_VIEW_MODES[number]
/**
* Saved value from the two-mode generation of this setting. Read as `detailed`;
* Saved value from the two-mode generation of this setting. Read as `standard`;
* never offered as a choice and never written back.
*/
export const LEGACY_TRANSCRIPT_VIEW_MODE = 'normal'
/** Every value the durable field accepts: current modes plus the legacy saved value. */
const TRANSCRIPT_VIEW_SETTING_VALUES = [...TRANSCRIPT_VIEW_MODES, LEGACY_TRANSCRIPT_VIEW_MODE] as const
/** Saved `expanded` values read as `detailed`, without being offered or written back. */
export const LEGACY_EXPANDED_TRANSCRIPT_VIEW_MODE = 'expanded'
/** Default preserves the compact process disclosure introduced by Chat. */
export const DEFAULT_TRANSCRIPT_VIEW_MODE: TranscriptViewMode = 'compact'
/** Every value the durable field accepts: current modes plus legacy saved values. */
const TRANSCRIPT_VIEW_SETTING_VALUES = [
...TRANSCRIPT_VIEW_MODES, LEGACY_TRANSCRIPT_VIEW_MODE, LEGACY_EXPANDED_TRANSCRIPT_VIEW_MODE,
] as const
/** Standard process summaries for users without an explicit preference. */
export const DEFAULT_TRANSCRIPT_VIEW_MODE: TranscriptViewMode = 'standard'
/** Performance and usage detail levels accepted by user settings. */
export const PERFORMANCE_USAGE_MODES = ['compact', 'detailed'] as const
@@ -43,8 +48,8 @@ export const DEFAULT_LINK_OPENING: LinkOpening = 'sidebar'
/** Durable Chat section shared by the Host schema and browser scope. */
export interface ChatSettings {
/** Work-details preference; the legacy value is accepted only from existing saved settings. */
transcriptView: TranscriptViewMode | typeof LEGACY_TRANSCRIPT_VIEW_MODE
/** Work-details preference; legacy values are accepted only from existing saved settings. */
transcriptView: TranscriptViewMode | typeof LEGACY_TRANSCRIPT_VIEW_MODE | typeof LEGACY_EXPANDED_TRANSCRIPT_VIEW_MODE
/** Detail level for composer statistics and completed-Turn usage. */
performanceUsage: PerformanceUsageMode
/** Default destination for Chat HTTP(S) links. */
@@ -55,7 +60,8 @@ export interface ChatSettings {
export const ChatSettingsFields = {
linkOpening: z.union(['sidebar', 'new-tab']).default(DEFAULT_LINK_OPENING),
performanceUsage: z.union([...PERFORMANCE_USAGE_MODES]).default(DEFAULT_PERFORMANCE_USAGE),
[TRANSCRIPT_VIEW_FIELD]: z.union([...TRANSCRIPT_VIEW_SETTING_VALUES]).default(DEFAULT_TRANSCRIPT_VIEW_MODE),
// Missing and unrecognized modes both use Standard.
[TRANSCRIPT_VIEW_FIELD]: z.union([...TRANSCRIPT_VIEW_SETTING_VALUES]).default(DEFAULT_TRANSCRIPT_VIEW_MODE).loose(),
}
/** Schema for shared configuration values. */
@@ -138,7 +138,8 @@ export const ChatGroupSeat = memo(function ChatGroupSeat({ groupKey, useChatGrou
const location = node?.location
return location?.kind === 'turn' || location?.kind === 'step' ? location.turn : undefined
})
const grouped = props.usePresentation(policy => turnLocation?.status !== 'open' || policy.stepGrouping !== 'none')
const grouped = props.usePresentation(policy => policy.stepGrouping === 'collapsed'
|| (policy.stepGrouping === 'history' && turnLocation?.status !== 'open'))
const reason = turnLocation?.end?.data.reason.kind
const alwaysOpen = presentation?.turnClosed === false || presentation?.hasInterleavedInput === true
|| reason === 'aborted' || reason === 'error'
+7 -5
View File
@@ -100,11 +100,12 @@ export const zh = {
'settings.links.description': '对话中网页链接的打开位置',
'settings.links.sidebar': '应用内侧边栏',
'settings.links.newTab': '默认浏览器',
'settings.transcript.title': '工作过程展示',
'settings.transcript.description': '控制轮次和步骤的默认展开方式',
'settings.transcript.title': '工作步骤展示',
'settings.transcript.description': '选择希望看到多少工具调用细节',
'settings.transcript.compact': '简洁',
'settings.transcript.standard': '标准',
'settings.transcript.detailed': '详细',
'settings.transcript.expanded': '完全展开',
'settings.transcript.verbose': '完全展开',
'fileOpen.title': '无法打开文件',
'fileOpen.unknown': '无法打开此文件',
'message.extraBlock': '附加内容块',
@@ -281,10 +282,11 @@ export const en = {
'settings.links.sidebar': 'In-App Sidebar',
'settings.links.newTab': 'Default Browser',
'settings.transcript.title': 'Work details',
'settings.transcript.description': 'Controls how turns and steps expand by default',
'settings.transcript.description': 'Choose how much detail to show for tool calls',
'settings.transcript.compact': 'Compact',
'settings.transcript.standard': 'Standard',
'settings.transcript.detailed': 'Detailed',
'settings.transcript.expanded': 'Expanded',
'settings.transcript.verbose': 'Verbose',
'fileOpen.title': 'Couldn’t open file',
'fileOpen.unknown': 'Couldn’t open this file',
'message.extraBlock': 'Extra content block',
@@ -13,8 +13,8 @@ export interface ChatPresentationPolicy {
readonly mode: TranscriptViewMode
/** Whether a normally completed Turn folds its process rows behind the whole-Turn control. */
readonly foldCompletedTurns: boolean
/** Whether running Turns' secondary groups expose a collapsible header; historical groups always do. */
readonly stepGrouping: 'collapsed' | 'none'
/** Collapsible group headers for all Turns, historical Turns only, or no Turns. */
readonly stepGrouping: 'collapsed' | 'history' | 'none'
/** Show the running command, path, query, or reasoning detail in group titles. */
readonly liveProcessDetail: boolean
/** Whether a settled reasoning row previews its first line beside the Think title. */
@@ -29,20 +29,27 @@ const POLICIES: Readonly<Record<TranscriptViewMode, ChatPresentationPolicy>> = {
liveProcessDetail: false,
settledReasoningPreview: false,
},
detailed: {
mode: 'detailed',
standard: {
mode: 'standard',
foldCompletedTurns: true,
stepGrouping: 'collapsed',
liveProcessDetail: true,
settledReasoningPreview: true,
},
expanded: {
mode: 'expanded',
detailed: {
mode: 'detailed',
foldCompletedTurns: true,
stepGrouping: 'none',
stepGrouping: 'history',
liveProcessDetail: true,
settledReasoningPreview: true,
},
verbose: {
mode: 'verbose',
foldCompletedTurns: false,
stepGrouping: 'none',
liveProcessDetail: false,
settledReasoningPreview: true,
},
}
/**
@@ -24,8 +24,9 @@ export type TranscriptViewRowProps =
const LABELS = {
compact: 'settings.transcript.compact',
standard: 'settings.transcript.standard',
detailed: 'settings.transcript.detailed',
expanded: 'settings.transcript.expanded',
verbose: 'settings.transcript.verbose',
} as const satisfies Record<TranscriptViewMode, ChatKey>
/**
@@ -3,14 +3,14 @@
import { createSnapshotStore, type SnapshotStore } from '@deepseek-ai/dsh-client-store'
import type { ConfigForm } from '@deepseek-ai/dsh-client-ui-settings/client'
import {
DEFAULT_TRANSCRIPT_VIEW_MODE, LEGACY_TRANSCRIPT_VIEW_MODE, TRANSCRIPT_VIEW_FIELD,
DEFAULT_TRANSCRIPT_VIEW_MODE, LEGACY_TRANSCRIPT_VIEW_MODE, LEGACY_EXPANDED_TRANSCRIPT_VIEW_MODE, TRANSCRIPT_VIEW_FIELD,
type ChatSettings, type TranscriptViewMode,
} from '../chat-settings.ts'
/** Live work-details preference consumed by Chat and its Settings row. */
export class TranscriptViewPolicy {
private readonly unsubscribe: () => void
/** Reactive current mode; defaults to Compact before Host settings arrive. */
/** Reactive current mode; defaults to Standard before Host settings arrive. */
readonly mode: SnapshotStore<TranscriptViewMode> = createSnapshotStore(DEFAULT_TRANSCRIPT_VIEW_MODE)
/**
@@ -26,7 +26,7 @@ export class TranscriptViewPolicy {
/**
* Publish and persist one explicit user choice.
* @param mode - Compact, Detailed, or Expanded work details.
* @param mode - Compact, Standard, Detailed, or Verbose work details.
*/
setMode(mode: TranscriptViewMode): void {
if (this.mode.getSnapshot() === mode) return
@@ -38,7 +38,9 @@ export class TranscriptViewPolicy {
private adopt(): void {
const section = this.host.getSnapshot().value
if (section === undefined) return
const mode = section.transcriptView === LEGACY_TRANSCRIPT_VIEW_MODE ? 'detailed' : section.transcriptView
const saved = section.transcriptView
const mode = saved === LEGACY_TRANSCRIPT_VIEW_MODE ? 'standard'
: saved === LEGACY_EXPANDED_TRANSCRIPT_VIEW_MODE ? 'detailed' : saved
if (this.mode.getSnapshot() !== mode) this.mode.set(mode)
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ import { TRANSCRIPT_VIEW_FIELD } from './chat-settings.ts'
import { ChatSettingsFields } from './chat-settings.ts'
export {
CHAT_SETTINGS_NAMESPACE, DEFAULT_TRANSCRIPT_VIEW_MODE, LEGACY_TRANSCRIPT_VIEW_MODE, TRANSCRIPT_VIEW_FIELD,
CHAT_SETTINGS_NAMESPACE, DEFAULT_TRANSCRIPT_VIEW_MODE, LEGACY_TRANSCRIPT_VIEW_MODE, LEGACY_EXPANDED_TRANSCRIPT_VIEW_MODE, TRANSCRIPT_VIEW_FIELD,
TRANSCRIPT_VIEW_MODES, type ChatSettings, type TranscriptViewMode,
} from './chat-settings.ts'