mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-10-26 16:55:08 +00:00
fix(plugins): retain independent row controls during query suspension
This commit is contained in:
1 parent
817d4ec740
commit
f8912d267f
3 files changed
+16
-10
No files matched your search
@@ -45,7 +45,7 @@ import { BundleDetailController, type BundleDetailsState } from './detail-store.
|
||||
import type { LocaleSnapshot } from '@deepseek-ai/dsh-client-locale/client'
|
||||
|
||||
/**
|
||||
* Read whether a bundle or one of its rows has a pending management action.
|
||||
* Read whether a bundle has a pending management action.
|
||||
* @param state Current manager snapshot.
|
||||
* @param packageName Bundle whose controls and observers must wait.
|
||||
* @returns Whether the bundle's management operation is still pending.
|
||||
@@ -53,8 +53,7 @@ import type { LocaleSnapshot } from '@deepseek-ai/dsh-client-locale/client'
|
||||
export function bundleBusy(state: PluginManagerState, packageName: string): boolean {
|
||||
return state.busy.includes(packageName) || state.update?.packageName === packageName
|
||||
|| (state.install.subject?.name === packageName && (isInstallPending(state.install.phase) || state.install.phase === 'checking'))
|
||||
|| (state.packages.find(pkg => pkg.name === packageName)?.rows.some(row =>
|
||||
row.entryId !== undefined && state.busy.includes(rowKey(row.entryId))) ?? false)
|
||||
|
||||
}
|
||||
|
||||
/** The action a failed notice names. */
|
||||
@@ -690,7 +689,14 @@ export class PluginManagerController {
|
||||
* @returns A read-only source; unsubscribe releases the caller's observation.
|
||||
*/
|
||||
observeChanges(packageName: string): HostObservable<boolean> {
|
||||
return { getSnapshot: () => bundleBusy(this.getSnapshot(), packageName), subscribe: listener => this.store.subscribe(listener) }
|
||||
return {
|
||||
getSnapshot: () => {
|
||||
const state = this.getSnapshot()
|
||||
return bundleBusy(state, packageName) || (state.packages.find(pkg => pkg.name === packageName)?.rows.some(row =>
|
||||
row.entryId !== undefined && state.busy.includes(rowKey(row.entryId))) ?? false)
|
||||
},
|
||||
subscribe: listener => this.store.subscribe(listener),
|
||||
}
|
||||
}
|
||||
|
||||
/** Stop publishing and drop every late settlement. */
|
||||
|
||||
@@ -134,7 +134,7 @@ it('shows query failures as unknown while retaining previously displayed apps',
|
||||
fireEvent.click(screen.getByRole('button', { name: en.retry }))
|
||||
expect(f.props.refresh).toHaveBeenCalledTimes(2)
|
||||
f.publish({ system: { ...f.state.getSnapshot().system, busy: true }, busy: true })
|
||||
expect(screen.queryByRole('button', { name: en.retry })).toBeNull()
|
||||
expect(screen.getByRole('button', { name: en.retry }).hasAttribute('disabled')).toBe(true)
|
||||
f.publish({ system: { ...f.state.getSnapshot().system, busy: false, error: null }, busy: false })
|
||||
expect(screen.queryByRole('button', { name: en.retry })).toBeNull()
|
||||
f.publish(observe(value))
|
||||
@@ -292,7 +292,7 @@ it('keeps content mounted and disables actions while management changes are pend
|
||||
const requirements = screen.getByRole('region', { name: en.title })
|
||||
expect(within(requirements).getAllByRole('group')).toHaveLength(4)
|
||||
expect(screen.getByRole('alert').textContent).toContain('provider is reloading')
|
||||
expect(screen.getByRole('button', { name: en.unknown }).hasAttribute('disabled')).toBe(true)
|
||||
expect(within(screen.getByRole('group', { name: en.accessibility })).getByRole('button', { name: en.unknown }).hasAttribute('disabled')).toBe(true)
|
||||
fireEvent.focus(window)
|
||||
expect(f.props.refresh).toHaveBeenCalledTimes(2)
|
||||
f.publish({ system: { ...f.state.getSnapshot().system, busy: true, error: null }, busy: true })
|
||||
@@ -388,14 +388,13 @@ it('loads the runtime setting independently and reports unavailable and read-onl
|
||||
})
|
||||
|
||||
|
||||
it('retains the previous single control while a stale query error is being refreshed', () => {
|
||||
it('retains uncertainty and the diagnostic until a refresh succeeds', () => {
|
||||
const f = fixture()
|
||||
f.publish(observe(value))
|
||||
render(<PermissionPanel {...f.props} />)
|
||||
f.publish({ system: { value: value.system, busy: true, error: 'stale error' }, busy: true })
|
||||
expect(screen.getByRole('button', { name: en.request }).hasAttribute('disabled')).toBe(true)
|
||||
expect(screen.getByRole('button', { name: en.granted }).hasAttribute('disabled')).toBe(true)
|
||||
expect(screen.queryByRole('alert')).toBeNull()
|
||||
for (const button of screen.getAllByRole('button', { name: en.unknown })) expect(button.hasAttribute('disabled')).toBe(true)
|
||||
expect(screen.getByRole('alert').textContent).toContain('stale error')
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -197,6 +197,7 @@ export const SERVICE_WALK_EXEMPTIONS: Record<string, string> = {
|
||||
conversation: 'client-side interface-typed browser service — packages/client/ui-conversation/README.md owns the API',
|
||||
layout: 'client-side interface-typed browser service — packages/client/ui-layout/README.md owns the API',
|
||||
pluginNavigation: 'client-side bundle navigation — packages/client/ui-plugin-manager/README.md owns the API',
|
||||
pluginChanges: 'client-side read-only management activity — packages/client/ui-plugin-manager/README.md owns the API',
|
||||
locale: 'client-side interface-typed browser service — packages/client/locale/README.md owns the API',
|
||||
modelDirectories: 'client-side interface-typed browser service — packages/client/ui-model-selection/README.md owns the API',
|
||||
modules: 'client-side interface-typed browser service — packages/client/modules/README.md owns the API',
|
||||
|
||||
Reference in new issue
Block a user