feat(arena): add IDLE status for agent follow-up task support

- Introduce AgentStatus.IDLE for agents that finished work but can accept follow-up messages
- Add isSettledStatus() helper to check if agent is settled (IDLE or terminal)
- Update ArenaManager to transition to IDLE after agents finish initial task
- Keep agent tabs visible when session is IDLE so users can continue interacting
- Fix listener cleanup to not detach on IDLE (agents remain alive)
- Update tests to expect 'idle' status after successful completion

This enables the arena collaboration feature where agents can receive
additional tasks after completing their initial work.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
tanzhenxin 2026-03-09 21:33:48 +08:00
parent 4a681f435d
commit eaef9efe90
13 changed files with 125 additions and 51 deletions

View file

@ -104,8 +104,8 @@ export const Composer = () => {
{/* Exclusive area: only one component visible at a time */}
{/* Hide footer when a confirmation dialog (e.g. ask_user_question) is active */}
{!showSuggestions &&
uiState.streamingState !== StreamingState.WaitingForConfirmation &&
{uiState.isInputActive &&
!showSuggestions &&
(showShortcuts ? (
<KeyboardShortcuts />
) : (

View file

@ -148,11 +148,13 @@ export const ArenaSessionCard: React.FC<ArenaSessionCardProps> = ({
const colChanges = 10;
const titleLabel =
sessionStatus === 'completed'
? 'Arena Complete'
: sessionStatus === 'cancelled'
? 'Arena Cancelled'
: 'Arena Failed';
sessionStatus === 'idle'
? 'Agents Status · Idle'
: sessionStatus === 'completed'
? 'Arena Complete'
: sessionStatus === 'cancelled'
? 'Arena Cancelled'
: 'Arena Failed';
return (
<Box
@ -266,6 +268,15 @@ export const ArenaSessionCard: React.FC<ArenaSessionCardProps> = ({
<Box height={1} />
{/* Hint */}
{sessionStatus === 'idle' && (
<Box flexDirection="column">
<Text color={theme.text.secondary}>
Switch to an agent tab to continue, or{' '}
<Text color={theme.text.accent}>/arena select</Text> to pick a
winner.
</Text>
</Box>
)}
{sessionStatus === 'completed' && (
<Box>
<Text color={theme.text.secondary}>

View file

@ -12,7 +12,7 @@ import {
type ArenaAgentState,
type InProcessBackend,
type AgentStatsSummary,
isTerminalStatus,
isSettledStatus,
ArenaSessionStatus,
DISPLAY_MODE,
} from '@qwen-code/qwen-code-core';
@ -46,7 +46,7 @@ function pad(
}
function getElapsedMs(agent: ArenaAgentState): number {
if (isTerminalStatus(agent.status)) {
if (isSettledStatus(agent.status)) {
return agent.stats.durationMs;
}
return Date.now() - agent.startedAt;
@ -61,6 +61,8 @@ function getSessionStatusLabel(status: ArenaSessionStatus): {
return { text: 'Running', color: theme.status.success };
case ArenaSessionStatus.INITIALIZING:
return { text: 'Initializing', color: theme.status.warning };
case ArenaSessionStatus.IDLE:
return { text: 'Idle', color: theme.status.success };
case ArenaSessionStatus.COMPLETED:
return { text: 'Completed', color: theme.status.success };
case ArenaSessionStatus.CANCELLED: