Quantago Chat Todo Sidebar + Plan State Fixes
Summary
Updated the shared chat UI in packages/chat-ui/src/StreamingChatPanel.tsx to make the Todo/plan panel behave as a global assistant navigator instead of being rendered inside each assistant message row.
What Changed
- Moved Todo panel outside message content
- Removed per-turn plan rendering from
TurnView. - Added one global plan sidebar in the main chat pane layout.
- Messages now render in their own column (
max-w-4xl) without being narrowed by an inline per-message todo card.
- Fixed sticky behavior
- The global plan panel is now rendered once in the chat scroll container and uses
sticky top-3. - This keeps it pinned under the chat header while scrolling conversation content.
- Reduced stuck loading states in plan steps
- Added
normalizePlanForDisplay(...). - If the source assistant turn is already complete (
doneorerror), no tools are running, and the plan has active steps but no pending steps, active steps are auto-normalized todone. - This prevents stale spinner states from persisting after a completed turn.
- Made the plan adaptive/dynamic (GPS-like)
- Added
deriveLatestPlanState(turns). - The sidebar always derives from the latest assistant plan signal found in turns (either
turn.planor tool resultplan). - As new evidence or replanning arrives in later turns, the sidebar automatically updates to the newest plan.
Key Implementation Snippet
const latestPlanState = React.useMemo(() => deriveLatestPlanState(turns), [turns]);
{latestPlanState && (
<div className="hidden w-72 shrink-0 self-start lg:block">
<div className="sticky top-3">
<PlanNote plan={latestPlanState.plan} />
</div>
</div>
)}
Validation
- Ran
pnpm typecheckinprojects/quantago: passed. - Ran
pnpm lintinprojects/quantago: passed with existing unrelated warnings in other files. - Checked edited file diagnostics: no errors in
packages/chat-ui/src/StreamingChatPanel.tsx.