Merge pull request #1866 from deepseek-harness/feature/workspace-picker-composer

feat(web): open workspace picker from the composer
This commit is contained in:
Terra
2026-08-11 13:01:38 +08:00
committed by GitHub
17 changed files with 227 additions and 36 deletions

View File

@@ -60,6 +60,9 @@ interface BenchOptions {
running?: boolean
subagent?: Exclude<ConversationSnapshot['subagent'], null>
disabled?: boolean
inert?: boolean
workspacePickerOpen?: boolean
onRequestWorkspace?: () => void
promptError?: ConversationSnapshot['promptError']
/** Authoritative queue rows served to the machine overlay (empty = none). */
queue?: ConversationSnapshot['queue']
@@ -168,6 +171,9 @@ function bench(over?: BenchOptions) {
t: over?.t ?? makeTranslate(zh, commonZh),
renderSlot,
variant: over?.variant ?? 'composer',
...(over?.inert === true ? { disabled: true } : {}),
...(over?.workspacePickerOpen !== undefined ? { workspacePickerOpen: over.workspacePickerOpen } : {}),
...(over?.onRequestWorkspace !== undefined ? { onRequestWorkspace: over.onRequestWorkspace } : {}),
...(over?.placeholder !== undefined ? { placeholder: over.placeholder } : {}),
...(over?.accessory !== undefined ? { accessory: over.accessory } : {}),
...(over?.overlay !== undefined ? { overlay: over.overlay } : {}),
@@ -785,6 +791,40 @@ describe('running and lock semantics', () => {
expect(custom.textarea.placeholder).toBe('Custom placeholder')
})
it('the inert textarea opens the Workspace picker by pointer or keyboard', () => {
const onRequestWorkspace = vi.fn()
const { view, textarea } = bench({
inert: true,
workspacePickerOpen: false,
onRequestWorkspace,
placeholder: '选择一个工作区开始',
})
expect(textarea.disabled).toBe(false)
expect(textarea.readOnly).toBe(true)
expect(textarea.getAttribute('aria-haspopup')).toBe('menu')
expect(textarea.getAttribute('aria-expanded')).toBe('false')
expect((view.getByLabelText('命令') as HTMLButtonElement).disabled).toBe(true)
fireEvent.click(textarea)
fireEvent.keyDown(textarea, { key: 'Enter' })
fireEvent.keyDown(textarea, { key: ' ' })
expect(onRequestWorkspace).toHaveBeenCalledTimes(3)
// The WHOLE capsule is the pick target, and its pointerdown never reaches
// the document — the open picker's outside-close must not race the reopen.
const card = view.container.querySelector('[data-composer-card]') as HTMLElement
fireEvent.click(card)
expect(onRequestWorkspace).toHaveBeenCalledTimes(4)
const onDocumentPointerDown = vi.fn()
document.addEventListener('pointerdown', onDocumentPointerDown)
try {
fireEvent.pointerDown(card)
} finally {
document.removeEventListener('pointerdown', onDocumentPointerDown)
}
expect(onDocumentPointerDown).not.toHaveBeenCalled()
})
it('the plan projection swaps the placeholder while its effective target is plan mode', () => {
const active = bench({ plan: { active: true, pending: false } })
expect(active.textarea.placeholder).toBe('描述你的任务以生成计划')