fix: remove redundant context workbar tab

The assistant workbar duplicated attachment and knowledge-library controls already available in the composer, while its memory section exposed an unimplemented placeholder. The workbar now keeps Task Center, Files, Browser, and Results, with future task context and memory details assigned to Task Center.

Release note: 移除助手工作栏中重复且暂未完整实现的上下文页签;附件与知识库继续在会话输入区管理,工作栏保留任务中心、工作区、浏览器和成果。
This commit is contained in:
mesalogo
2026-08-22 17:50:01 +08:00
parent 7c34abdfbf
commit 58d774ae0c
11 changed files with 50 additions and 268 deletions
+2 -3
View File
@@ -8125,10 +8125,9 @@ describe('App', () => {
screen.queryByRole('region', { name: '当前会话的任务' })
).not.toBeInTheDocument()
expect(screen.queryByText('最近任务')).not.toBeInTheDocument()
fireEvent.click(screen.getByRole('tab', { name: '上下文' }))
expect(
screen.getByText('尚未添加文件、截图或剪贴板内容。')
).toBeInTheDocument()
screen.queryByRole('tab', { name: '上下文' })
).not.toBeInTheDocument()
fireEvent.click(screen.getByRole('tab', { name: '工作区' }))
expect(
screen.getByText(/选择文件后在当前工作区内预览/)
-18
View File
@@ -3466,13 +3466,6 @@ function App(): React.JSX.Element {
})),
[activeProjectId, assistantArtifacts]
)
const enabledSidebarLibraries = useMemo(
() =>
knowledgeSnapshot.libraries.filter((library) =>
enabledKnowledgeLibraryIds.includes(library.id)
),
[enabledKnowledgeLibraryIds, knowledgeSnapshot.libraries]
)
const pendingHeartbeatSuggestionCount = useMemo(() => {
const memoryIds = new Set(
heartbeatEntries.flatMap((entry) => entry.proposedMemoryIds)
@@ -6752,13 +6745,6 @@ function App(): React.JSX.Element {
}
}
const removeAttachment = (attachmentId: string): void => {
void window.goodbuddy.context.remove(attachmentId)
updateAttachments((current) =>
current.filter((attachment) => attachment.id !== attachmentId)
)
}
const startWebSpeechInput = async (): Promise<void> => {
const SpeechRecognition =
getSpeechRecognitionConstructor(window)
@@ -9854,11 +9840,8 @@ function App(): React.JSX.Element {
<RightAssistantSidebar
approvals={pendingSidebarApprovals}
artifacts={sidebarArtifacts}
attachments={attachments}
browserState={browserStates[activeId]}
conversationTitles={conversationTitles}
enabledLibraries={enabledSidebarLibraries}
memories={assistantMemories}
onCreateCustomTask={() => openCustomTaskDialog('current')}
schedules={assistantSchedules}
selectedTaskId={selectedAssistantTaskId}
@@ -9922,7 +9905,6 @@ function App(): React.JSX.Element {
mergeArtifacts(current, [artifact])
)
}}
onRemoveAttachment={removeAttachment}
onOpenTask={openAssistantTask}
onRemoveSchedule={removeAssistantSchedule}
onRespondApproval={(approval, decision) => {
@@ -22,7 +22,7 @@ beforeEach(() => {
})
function renderSidebar({
tab = 'context',
tab = 'tasks',
artifacts = [],
onLoadArtifact = vi.fn(async () => undefined),
restoreFocusRef
@@ -38,9 +38,6 @@ function renderSidebar({
<RightAssistantSidebar
approvals={[]}
artifacts={artifacts}
attachments={[]}
enabledLibraries={[]}
memories={[]}
schedules={[]}
tasks={[]}
conversationTitles={new Map()}
@@ -57,7 +54,6 @@ function renderSidebar({
onOpenWorkspaceEntry={vi.fn(async () => undefined)}
onInteractBrowser={vi.fn(async () => undefined)}
onRefreshChanges={vi.fn(async () => undefined)}
onRemoveAttachment={vi.fn()}
onRemoveSchedule={vi.fn(async () => undefined)}
onRespondApproval={vi.fn()}
onRunSchedule={vi.fn(async () => undefined)}
@@ -231,12 +227,12 @@ describe('RightAssistantSidebar resizing', () => {
}
})
it('exposes the task center and four reusable work surfaces', () => {
it('exposes the task center and three reusable work surfaces', () => {
renderSidebar()
expect(
screen.getAllByRole('tab').map((tab) => tab.textContent)
).toEqual(['任务中心', '上下文', '工作区', '浏览器', '成果'])
).toEqual(['任务中心', '工作区', '浏览器', '成果'])
expect(
screen.queryByRole('tab', { name: '预览' })
).not.toBeInTheDocument()
+2 -105
View File
@@ -1,5 +1,4 @@
import {
CheckCircle2,
ChevronLeft,
ChevronRight,
CircleAlert,
@@ -11,13 +10,11 @@ import {
Plus,
RefreshCw,
ShieldAlert,
Upload,
X
Upload
} from 'lucide-react'
import { useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import type {
AssistantMemory,
AssistantSchedule,
AssistantTask,
WorkspaceChanges,
@@ -27,9 +24,7 @@ import type {
import { MarkdownRenderer } from './MarkdownRenderer'
import type {
ApprovalDecision,
BrowserLiveState,
ContextAttachment,
KnowledgeLibrary
BrowserLiveState
} from '../../shared/contracts'
import { WorkspaceFilesPanel } from './WorkspaceFilesPanel'
import { SegmentedControl } from './WorkspacePrimitives'
@@ -40,7 +35,6 @@ import {
export type AssistantSidebarTab =
| 'tasks'
| 'context'
| 'workspace'
| 'browser'
| 'results'
@@ -67,9 +61,6 @@ type RightAssistantSidebarProps = {
tab: AssistantSidebarTab
approvals: PendingSidebarApproval[]
artifacts: SidebarArtifact[]
attachments: ContextAttachment[]
enabledLibraries: KnowledgeLibrary[]
memories: AssistantMemory[]
schedules: AssistantSchedule[]
tasks: AssistantTask[]
conversationTitles: ReadonlyMap<string, string>
@@ -84,7 +75,6 @@ type RightAssistantSidebarProps = {
onCreateCustomTask: () => void
onImportArtifacts: () => Promise<void>
onLoadArtifact: (artifactId: string) => Promise<void>
onRemoveAttachment: (attachmentId: string) => void
onRefreshChanges: () => Promise<void>
onListWorkspaceDirectory: (
path: string
@@ -110,7 +100,6 @@ type RightAssistantSidebarProps = {
const tabIds: AssistantSidebarTab[] = [
'tasks',
'context',
'workspace',
'browser',
'results'
@@ -173,9 +162,6 @@ export function RightAssistantSidebar({
tab,
approvals,
artifacts,
attachments,
enabledLibraries,
memories,
schedules,
tasks,
conversationTitles,
@@ -190,7 +176,6 @@ export function RightAssistantSidebar({
onCreateCustomTask,
onImportArtifacts,
onLoadArtifact,
onRemoveAttachment,
onRefreshChanges,
onListWorkspaceDirectory,
onLoadWorkspaceFile,
@@ -264,9 +249,6 @@ export function RightAssistantSidebar({
'attention' | 'active' | 'paused' | 'finished'
>('active')
const [actionError, setActionError] = useState('')
const activeMemories = memories.filter(
(memory) => memory.status === 'confirmed'
)
const artifactPreview =
artifacts.find((artifact) => artifact.id === selectedArtifactId)
const currentWorkspacePreview =
@@ -827,91 +809,6 @@ export function RightAssistantSidebar({
</section>
)}
{tab === 'context' && (
<section className="assistant-sidebar__section">
<p className="assistant-sidebar__section-description">
{t('sidebar.context.description')}
</p>
<h3>
<FileText size={15} />
{t('sidebar.context.attachmentsTitle')}
</h3>
{attachments.length === 0 ? (
<p className="assistant-sidebar__empty">
{t('sidebar.context.noAttachments')}
</p>
) : (
attachments.map((attachment) => (
<article
className="assistant-sidebar__context"
key={attachment.id}
>
<span>
<strong>{attachment.name}</strong>
<small>
{t('sidebar.context.attachmentDetails', {
kind: attachment.kind,
formattedSize:
attachment.size.toLocaleString(locale)
})}
</small>
</span>
<button
aria-label={t(
'sidebar.context.removeAttachment',
{ name: attachment.name }
)}
className="icon-button"
onClick={() => onRemoveAttachment(attachment.id)}
type="button"
>
<X size={14} />
</button>
</article>
))
)}
<h3>
<FolderTree size={15} />
{t('sidebar.context.librariesTitle')}
</h3>
{enabledLibraries.length === 0 ? (
<p className="assistant-sidebar__empty">
{t('sidebar.context.noLibraries')}
</p>
) : (
enabledLibraries.map((library) => (
<div className="assistant-sidebar__library" key={library.id}>
<strong>{library.name}</strong>
<small>
{t('sidebar.context.documentCount', {
formattedCount:
library.documentCount.toLocaleString(locale)
})}
</small>
</div>
))
)}
<h3>
<CheckCircle2 size={15} />
{t('sidebar.context.memoriesTitle')}
</h3>
{activeMemories.length === 0 ? (
<p className="assistant-sidebar__empty">
{t('sidebar.context.noMemories')}
</p>
) : (
activeMemories.map((memory) => (
<article
className="assistant-sidebar__memory"
key={memory.id}
>
<span>{memory.content}</span>
</article>
))
)}
</section>
)}
{tab === 'workspace' && (
currentWorkspacePreview ? (
<section className="assistant-sidebar__preview">
@@ -78,11 +78,6 @@ export const workspace = {
label: 'Task center',
description: 'Review approvals and manage automations'
},
context: {
label: 'Context',
description:
'View attachments, knowledge libraries, and memories used in this conversation'
},
workspace: {
label: 'Files',
description: 'Browse project files, Git changes, and file contents'
@@ -134,22 +129,6 @@ export const workspace = {
'This stops future automatic runs but keeps the task, conversation, and existing results.'
}
},
context: {
description:
'View the attachments, knowledge libraries, and confirmed memories used in this conversation.',
attachmentsTitle: 'Attachments',
noAttachments:
'No files, screenshots, or clipboard content have been added.',
attachmentDetails: '{{kind}} · {{formattedSize}} bytes',
removeAttachment: 'Remove {{name}} from context',
librariesTitle: 'Enabled knowledge libraries',
noLibraries:
'No knowledge libraries are enabled for this conversation.',
documentCount: '{{formattedCount}} documents',
memoriesTitle: 'Confirmed memories',
noMemories:
'There are no confirmed long-term memories in the current scope.'
},
workspace: {
back: 'Back to workspace',
title: 'Files',
@@ -75,10 +75,6 @@ export const workspace = {
label: '任务中心',
description: '处理待审批操作并管理自动化'
},
context: {
label: '上下文',
description: '查看本次对话使用的附件、知识库与记忆'
},
workspace: {
label: '工作区',
description: '浏览项目文件、Git 变更与文件内容'
@@ -128,18 +124,6 @@ export const workspace = {
deleteMessage: '这会停止后续自动运行,但保留任务、会话和既有结果。'
}
},
context: {
description: '查看当前对话实际使用的附件、知识库与已确认记忆。',
attachmentsTitle: '本次附件',
noAttachments: '尚未添加文件、截图或剪贴板内容。',
attachmentDetails: '{{kind}} · {{formattedSize}} 字节',
removeAttachment: '移除上下文 {{name}}',
librariesTitle: '已启用知识库',
noLibraries: '当前对话未启用知识库。',
documentCount: '{{formattedCount}} 个文档',
memoriesTitle: '已确认记忆',
noMemories: '当前范围没有已确认的长期记忆。'
},
workspace: {
back: '返回工作区',
title: '工作区',
+3 -57
View File
@@ -3433,27 +3433,21 @@ button > svg {
background: var(--accent-subtle);
}
.assistant-sidebar__row span,
.assistant-sidebar__context span,
.assistant-sidebar__library {
.assistant-sidebar__row span {
display: flex;
min-width: 0;
flex-direction: column;
gap: 3px;
}
.assistant-sidebar__row strong,
.assistant-sidebar__context strong,
.assistant-sidebar__library strong {
.assistant-sidebar__row strong {
overflow: hidden;
font-size: 11px;
text-overflow: ellipsis;
white-space: nowrap;
}
.assistant-sidebar__row small,
.assistant-sidebar__context small,
.assistant-sidebar__library small {
.assistant-sidebar__row small {
overflow: hidden;
color: var(--text-muted);
font-size: 9px;
@@ -3497,48 +3491,6 @@ button > svg {
font-size: 9px;
}
.assistant-sidebar__context {
display: flex;
align-items: center;
justify-content: space-between;
padding: 9px 10px;
border: 1px solid var(--border-subtle);
border-radius: 9px;
gap: 8px;
}
.assistant-sidebar__library {
padding: 9px 10px;
border: 1px solid var(--border-subtle);
border-radius: 9px;
background: var(--surface-subtle);
}
.assistant-sidebar__memory {
display: flex;
align-items: flex-start;
justify-content: space-between;
padding: 9px 10px;
border: 1px solid var(--accent-selected);
border-radius: 9px;
background: var(--accent-subtle);
color: var(--accent);
font-size: 10px;
gap: 8px;
line-height: 1.45;
}
.assistant-sidebar__memory > span {
display: flex;
flex-direction: column;
gap: 3px;
}
.assistant-sidebar__memory > span small {
color: var(--warning);
font-size: 8px;
}
.assistant-sidebar__schedule-form {
display: flex;
flex-direction: column;
@@ -12655,7 +12607,6 @@ details.settings-section > :not(summary) + :not(summary) {
.settings-section,
.settings-tabs,
.assistant-sidebar__row,
.assistant-sidebar__library,
.assistant-sidebar__diff,
.assistant-sidebar__preview pre,
.tool-activity,
@@ -12680,7 +12631,6 @@ details.settings-section > :not(summary) + :not(summary) {
.topbar,
.assistant-sidebar,
.assistant-sidebar__tabs,
.assistant-sidebar__context,
.assistant-sidebar__preview > header,
.divider,
.runtime-picker__divider,
@@ -13334,13 +13284,9 @@ details.settings-section > :not(summary) + :not(summary) {
.assistant-sidebar__diff,
.assistant-sidebar__empty,
.assistant-sidebar__import,
.assistant-sidebar__memory,
.assistant-sidebar__memory > span small,
.assistant-sidebar__preview > header small,
.assistant-sidebar__preview pre,
.assistant-sidebar__row small,
.assistant-sidebar__context small,
.assistant-sidebar__library small,
.assistant-sidebar__schedule button,
.assistant-sidebar__schedule small,
.assistant-sidebar__schedule strong,