Skip to main content

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​

  1. 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.
  1. 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.
  1. Reduced stuck loading states in plan steps
  • Added normalizePlanForDisplay(...).
  • If the source assistant turn is already complete (done or error), no tools are running, and the plan has active steps but no pending steps, active steps are auto-normalized to done.
  • This prevents stale spinner states from persisting after a completed turn.
  1. 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.plan or tool result plan).
  • 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 typecheck in projects/quantago: passed.
  • Ran pnpm lint in projects/quantago: passed with existing unrelated warnings in other files.
  • Checked edited file diagnostics: no errors in packages/chat-ui/src/StreamingChatPanel.tsx.