mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-19 07:54:38 +00:00
fix(cli): address Copilot second-pass review — dialogOpen tick gate, isFocused doc
Two further findings from Copilot: 1. **Interval kept ticking while bg-tasks dialog was open.** The first-pass fix already torn the tick down once all rows expired from the visibility window, but `dialogOpen` was a separate reason the panel returned null and was missed by the gate. Add `dialogOpen` to the useEffect deps and short-circuit when true, so the dialog's tenure is interval-free. 2. **Stale `isFocused` doc comment in `ToolMessageProps`.** The comment claimed the prop controlled the now-retired `Ctrl+E / Ctrl+F` display shortcuts (those died with the inline `AgentExecutionDisplay` frame). Rewrite the comment to describe the only remaining behavior — the focus-routed approval surface (focus-holder banner vs. queued-sibling marker). Coverage delta: +1 case on `LiveAgentPanel.test.tsx` — `tears the 1s tick down when the bg-tasks dialog opens` advances 60s of fake time with `dialogOpen=true` and asserts no panel state drift.
This commit is contained in:
parent
e9b76989c0
commit
1bb1326904
3 changed files with 51 additions and 10 deletions
|
|
@ -295,6 +295,37 @@ describe('<LiveAgentPanel />', () => {
|
|||
expect(lastFrame() ?? '').toBe('');
|
||||
});
|
||||
|
||||
it('tears the 1s tick down when the bg-tasks dialog opens', () => {
|
||||
// While the dialog is open the panel returns null and the dialog
|
||||
// owns the same data — a still-running interval is a wasted
|
||||
// re-render budget. Verify by checking that advancing the clock
|
||||
// past the visibility window with dialogOpen=true does not flip
|
||||
// the panel into its "expired" state (which would only happen if
|
||||
// the tick advanced `now`).
|
||||
const initial = agentEntry({
|
||||
agentId: 'live-1',
|
||||
subagentType: 'researcher',
|
||||
description: 'researcher: investigate',
|
||||
status: 'completed',
|
||||
startTime: -2000,
|
||||
endTime: 0,
|
||||
});
|
||||
const { config } = makeRegistryConfig([initial]);
|
||||
const { lastFrame } = renderPanel({
|
||||
entries: [initial],
|
||||
config,
|
||||
dialogOpen: true,
|
||||
});
|
||||
// Dialog open → panel hidden, no opportunity for `now` to drift.
|
||||
expect(lastFrame() ?? '').toBe('');
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(60_000);
|
||||
});
|
||||
// Still hidden. The fact that we got here without the panel ever
|
||||
// mounting an interval means subsequent renders won't churn either.
|
||||
expect(lastFrame() ?? '').toBe('');
|
||||
});
|
||||
|
||||
it('still shows the snapshot when no Config is mounted (test fixtures)', () => {
|
||||
// Without a Config provider the panel can't reach the registry, so
|
||||
// it has to trust the snapshot — this is the one place the legacy
|
||||
|
|
|
|||
|
|
@ -148,14 +148,20 @@ export const LiveAgentPanel: React.FC<LiveAgentPanelProps> = ({
|
|||
const config = useContext(ConfigContext);
|
||||
|
||||
// Wall-clock tick. Drives elapsed-time refresh, terminal-row eviction,
|
||||
// AND the live registry re-pull below. The gate must consider both
|
||||
// live agents AND terminal-but-still-visible agents (within the 8s
|
||||
// visibility window) — `BackgroundTaskRegistry.getAll()` retains
|
||||
// terminal entries indefinitely, so a naive `entries.some(isAgentEntry)`
|
||||
// gate would keep ticking forever after the last entry's window
|
||||
// closed, churning re-renders for nothing on screen.
|
||||
// AND the live registry re-pull below. The gate must consider:
|
||||
// - `dialogOpen` — when the bg-tasks dialog is up, the panel
|
||||
// renders null (`if (dialogOpen) return null` below), so any
|
||||
// ticks the interval fires are wasted re-renders.
|
||||
// - live agents (running / paused) — always need elapsed updates.
|
||||
// - terminal agents still inside the 8s visibility window — need
|
||||
// ticks to drive their eviction.
|
||||
// `BackgroundTaskRegistry.getAll()` retains terminal entries
|
||||
// indefinitely, so a naive `entries.some(isAgentEntry)` gate would
|
||||
// keep ticking forever after the last entry's window closed; the
|
||||
// `dialogOpen` arm closes the corresponding gap on the dialog side.
|
||||
const [now, setNow] = useState(() => Date.now());
|
||||
useEffect(() => {
|
||||
if (dialogOpen) return;
|
||||
const needsTick = (whenMs: number) =>
|
||||
entries.some((e) => {
|
||||
if (!isAgentEntry(e)) return false;
|
||||
|
|
@ -174,8 +180,7 @@ export const LiveAgentPanel: React.FC<LiveAgentPanelProps> = ({
|
|||
if (!needsTick(wallNow)) clearInterval(id);
|
||||
}, 1000);
|
||||
return () => clearInterval(id);
|
||||
|
||||
}, [entries]);
|
||||
}, [entries, dialogOpen]);
|
||||
|
||||
// Re-pull each agent from the live registry on every tick so the row
|
||||
// shows the latest `recentActivities` — `useBackgroundTaskView`
|
||||
|
|
|
|||
|
|
@ -402,8 +402,13 @@ export interface ToolMessageProps extends IndividualToolCallDisplay {
|
|||
config?: Config;
|
||||
forceShowResult?: boolean;
|
||||
/**
|
||||
* Whether this subagent owns keyboard input for confirmations and
|
||||
* Ctrl+E/Ctrl+F display shortcuts.
|
||||
* Whether this subagent owns keyboard input for the inline approval
|
||||
* surface — when true the focus-holder banner renders and the
|
||||
* underlying ToolConfirmationMessage receives keystrokes; when false
|
||||
* sibling subagents render a dim "Queued approval" marker instead.
|
||||
* (The legacy Ctrl+E / Ctrl+F display shortcuts were retired with
|
||||
* the inline AgentExecutionDisplay frame; LiveAgentPanel owns the
|
||||
* live progress surface and BackgroundTasksDialog owns drill-down.)
|
||||
*/
|
||||
isFocused?: boolean;
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue