@@ -75,7 +75,6 @@ import {
7575 findSidebarProposedPlan ,
7676 findLatestProposedPlan ,
7777 deriveWorkLogEntries ,
78- deriveTodoItems ,
7978 hasActionableProposedPlan ,
8079 hasToolActivityForTurn ,
8180 isLatestTurnSettled ,
@@ -237,7 +236,6 @@ import { ComposerPrimaryActions } from "./chat/ComposerPrimaryActions";
237236import { ComposerPendingApprovalPanel } from "./chat/ComposerPendingApprovalPanel" ;
238237import { ComposerPendingUserInputPanel } from "./chat/ComposerPendingUserInputPanel" ;
239238import { ComposerPlanFollowUpBanner } from "./chat/ComposerPlanFollowUpBanner" ;
240- import { ComposerTodoListPanel } from "./chat/ComposerActiveTasksPanel" ;
241239import { SubagentDetailDrawer } from "./chat/SubagentDetailDrawer" ;
242240import {
243241 getComposerProviderState ,
@@ -748,7 +746,6 @@ export default function ChatView({ threadId, environmentId: environmentIdProp }:
748746 ( store ) => store . setStickyModelSelection ,
749747 ) ;
750748 const timestampFormat = settings . timestampFormat ;
751- const showTodosInComposer = settings . showTodosInComposer ;
752749 const navigate = useNavigate ( ) ;
753750 const queryClient = useQueryClient ( ) ;
754751 const rawSearch = useSearch ( {
@@ -1296,20 +1293,12 @@ export default function ChatView({ threadId, environmentId: environmentIdProp }:
12961293 const phase = derivePhase ( activeThread ?. session ?? null ) ;
12971294 const threadActivities = activeThread ?. activities ?? EMPTY_ACTIVITIES ;
12981295 const timelineThreadActivities = timelineThread ?. activities ?? EMPTY_ACTIVITIES ;
1299- const activeTodoItems = useMemo (
1300- ( ) =>
1301- showTodosInComposer
1302- ? deriveTodoItems ( threadActivities , activeLatestTurn ?. turnId ?? undefined )
1303- : [ ] ,
1304- [ showTodosInComposer , threadActivities , activeLatestTurn ?. turnId ] ,
1305- ) ;
13061296 const workLogEntries = useMemo (
13071297 ( ) =>
13081298 deriveWorkLogEntries ( timelineThreadActivities , timelineLatestTurn ?. turnId ?? undefined , {
1309- excludeTodoToolCalls : showTodosInComposer ,
13101299 isSessionRunning : phase === "running" ,
13111300 } ) ,
1312- [ timelineLatestTurn ?. turnId , timelineThreadActivities , showTodosInComposer , phase ] ,
1301+ [ timelineLatestTurn ?. turnId , timelineThreadActivities , phase ] ,
13131302 ) ;
13141303 const timelineLatestTurnHasToolActivity = useMemo (
13151304 ( ) => hasToolActivityForTurn ( timelineThreadActivities , timelineLatestTurn ?. turnId ) ,
@@ -1383,6 +1372,7 @@ export default function ChatView({ threadId, environmentId: environmentIdProp }:
13831372 ( ) => deriveActivePlanState ( threadActivities , activeLatestTurn ?. turnId ?? undefined ) ,
13841373 [ activeLatestTurn ?. turnId , threadActivities ] ,
13851374 ) ;
1375+ const planSidebarLabel = sidebarProposedPlan || interactionMode === "plan" ? "Plan" : "Tasks" ;
13861376 const showPlanFollowUpPrompt =
13871377 pendingUserInputs . length === 0 &&
13881378 interactionMode === "plan" &&
@@ -1403,7 +1393,9 @@ export default function ChatView({ threadId, environmentId: environmentIdProp }:
14031393 activePendingUserInput : activePendingUserInput ?. requestId ?? null ,
14041394 threadError : activeThread ?. error ,
14051395 } ) ;
1406- const isWorking = phase === "running" || isSendBusy || isConnecting || isRevertingCheckpoint ;
1396+ const hasInFlightTurn = Boolean ( activeLatestTurn && ! activeLatestTurn . completedAt ) ;
1397+ const isWorking =
1398+ phase === "running" || isSendBusy || isConnecting || isRevertingCheckpoint || hasInFlightTurn ;
14071399 const isThreadHydrating = activeThread !== undefined && ! isThreadHydrated ( activeThread ) ;
14081400 const nowIso = new Date ( nowTick ) . toISOString ( ) ;
14091401 const activeWorkStartedAt = deriveActiveWorkStartedAt (
@@ -1415,8 +1407,7 @@ export default function ChatView({ threadId, environmentId: environmentIdProp }:
14151407 const hasComposerHeader =
14161408 isComposerApprovalState ||
14171409 pendingUserInputs . length > 0 ||
1418- ( showPlanFollowUpPrompt && activeProposedPlan !== null ) ||
1419- activeTodoItems . length > 0 ;
1410+ ( showPlanFollowUpPrompt && activeProposedPlan !== null ) ;
14201411 const composerFooterHasWideActions = showPlanFollowUpPrompt || activePendingProgress !== null ;
14211412 const composerFooterActionLayoutKey = useMemo ( ( ) => {
14221413 if ( activePendingProgress ) {
@@ -2352,10 +2343,8 @@ export default function ChatView({ threadId, environmentId: environmentIdProp }:
23522343 const togglePlanSidebar = useCallback ( ( ) => {
23532344 setPlanSidebarOpen ( ( open ) => {
23542345 if ( open ) {
2355- const turnKey = activePlan ?. turnId ?? sidebarProposedPlan ?. turnId ?? null ;
2356- if ( turnKey ) {
2357- planSidebarDismissedForTurnRef . current = turnKey ;
2358- }
2346+ planSidebarDismissedForTurnRef . current =
2347+ activePlan ?. turnId ?? sidebarProposedPlan ?. turnId ?? "__dismissed__" ;
23592348 } else {
23602349 planSidebarDismissedForTurnRef . current = null ;
23612350 }
@@ -2738,6 +2727,18 @@ export default function ChatView({ threadId, environmentId: environmentIdProp }:
27382727 planSidebarDismissedForTurnRef . current = null ;
27392728 } , [ activeThread ?. id ] ) ;
27402729
2730+ // Auto-open the plan sidebar when plan/todo steps arrive for the current turn.
2731+ // Don't auto-open for plans carried over from a previous turn (the user can open manually).
2732+ useEffect ( ( ) => {
2733+ if ( ! activePlan ) return ;
2734+ if ( planSidebarOpen ) return ;
2735+ const latestTurnId = activeLatestTurn ?. turnId ?? null ;
2736+ if ( latestTurnId && activePlan . turnId !== latestTurnId ) return ;
2737+ const turnKey = activePlan . turnId ?? sidebarProposedPlan ?. turnId ?? "__dismissed__" ;
2738+ if ( planSidebarDismissedForTurnRef . current === turnKey ) return ;
2739+ setPlanSidebarOpen ( true ) ;
2740+ } , [ activePlan , activeLatestTurn ?. turnId , planSidebarOpen , sidebarProposedPlan ?. turnId ] ) ;
2741+
27412742 useEffect ( ( ) => {
27422743 if ( ! composerMenuOpen ) {
27432744 setComposerHighlightedItemId ( null ) ;
@@ -4837,6 +4838,7 @@ export default function ChatView({ threadId, environmentId: environmentIdProp }:
48374838 diffOpen = { diffOpen }
48384839 hasPlan = { Boolean ( activePlan || sidebarProposedPlan ) }
48394840 planSidebarOpen = { planSidebarOpen }
4841+ planSidebarLabel = { planSidebarLabel }
48404842 onRunProjectScript = { runProjectScript }
48414843 onAddProjectScript = { saveProjectScript }
48424844 onUpdateProjectScript = { updateProjectScript }
@@ -4984,10 +4986,6 @@ export default function ChatView({ threadId, environmentId: environmentIdProp }:
49844986 planTitle = { proposedPlanTitle ( activeProposedPlan . planMarkdown ) ?? null }
49854987 />
49864988 </ div >
4987- ) : activeTodoItems . length > 0 ? (
4988- < div className = "rounded-t-[19px] border-b border-border/65 bg-muted/20" >
4989- < ComposerTodoListPanel items = { activeTodoItems } />
4990- </ div >
49914989 ) : null }
49924990 < div
49934991 className = { cn (
@@ -5156,7 +5154,7 @@ export default function ChatView({ threadId, environmentId: environmentIdProp }:
51565154 data-chat-composer-footer = "true"
51575155 data-chat-composer-footer-compact = { isComposerFooterCompact ? "true" : "false" }
51585156 className = { cn (
5159- "flex min-w-0 flex-nowrap items-center justify-between gap-2 overflow-hidden px-2.5 pb-2.5 sm:px-3 sm:pb-3" ,
5157+ "flex min-w-0 flex-nowrap items-center justify-between gap-2 overflow-visible px-2.5 pb-2.5 sm:px-3 sm:pb-3" ,
51605158 isComposerFooterCompact ? "gap-1.5" : "gap-2 sm:gap-0" ,
51615159 ) }
51625160 >
@@ -5207,6 +5205,7 @@ export default function ChatView({ threadId, environmentId: environmentIdProp }:
52075205 activePlan = { activePlan !== null }
52085206 interactionMode = { interactionMode }
52095207 planSidebarOpen = { planSidebarOpen }
5208+ planSidebarLabel = { planSidebarLabel }
52105209 traitsMenuContent = { providerTraitsMenuContent }
52115210 onToggleInteractionMode = { toggleInteractionMode }
52125211 onTogglePlanSidebar = { togglePlanSidebar }
@@ -5337,16 +5336,15 @@ export default function ChatView({ threadId, environmentId: environmentIdProp }:
53375336 environmentId = { activeThreadEnvironmentId ! }
53385337 activePlan = { activePlan }
53395338 activeProposedPlan = { sidebarProposedPlan }
5339+ label = { planSidebarLabel }
53405340 markdownCwd = { gitCwd ?? undefined }
53415341 workspaceRoot = { activeWorkspaceRoot }
53425342 timestampFormat = { timestampFormat }
53435343 onClose = { ( ) => {
53445344 setPlanSidebarOpen ( false ) ;
53455345 // Track that the user explicitly dismissed for this turn so auto-open won't fight them.
5346- const turnKey = activePlan ?. turnId ?? sidebarProposedPlan ?. turnId ?? null ;
5347- if ( turnKey ) {
5348- planSidebarDismissedForTurnRef . current = turnKey ;
5349- }
5346+ planSidebarDismissedForTurnRef . current =
5347+ activePlan ?. turnId ?? sidebarProposedPlan ?. turnId ?? "__dismissed__" ;
53505348 } }
53515349 />
53525350 ) : null }
0 commit comments