-
Notifications
You must be signed in to change notification settings - Fork 11
🤖 Pin TODOs to chat bottom with Aggregator state #257
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- Add TodoWrite and TodoRead tools for managing task lists during operations - Schema includes content, status (pending/in_progress/completed), and activeForm fields - In-memory storage with workspace isolation (ephemeral, conversation-scoped) - UI component displays checklist with visual indicators (✓/⏳/○) - Full-replacement semantics (replaces entire list on each call) - Unit tests for storage layer Generated with `cmux`
Changes: - Replace in-memory Map storage with filesystem storage in stream's tmpdir - TODOs are now automatically cleaned up when stream ends - Each stream has isolated TODO storage (no cross-stream pollution) - Test helper functions updated to use tempDir instead of workspaceId Benefits: - Fixes memory leaks (TODOs no longer survive across conversations) - Proper stream isolation (concurrent streams don't share TODOs) - Automatic lifecycle management via streamManager cleanup - TODOs are inspectable during debugging (stored as todos.json) _Generated with `cmux`_
Enforce ordering rules for todo_write tool: - TODOs must be ordered: pending → in_progress → completed - Only one task can be in_progress at a time - Empty lists are allowed (all completed or nothing to do) Changes: - Added validateTodos() function with state machine validation - writeTodos() now validates before persisting to disk - Updated all tests to use valid todo ordering - Added 4 new test cases for validation rules Benefits: - Prevents model from creating invalid TODO states - Clear error messages guide model to fix ordering - Validation happens before filesystem write (atomic) _Generated with `cmux`_
Remove invalid type parameters from jest.fn() mock - Jest's Mock type only accepts 0-1 type arguments in TypeScript, not the tuple syntax used previously. _Generated with `cmux`_
_Generated with `cmux`_
- Reduced vertical spacing: gap 8px→3px, padding 8px→4px - Tighter line-height: 1.5→1.35 - Smaller font size: 12px→11px (activeForm 10px) - Thinner border-left: 3px→2px - Subtler backgrounds (92%/96% transparency vs 90%/95%) - Added opacity to completed items for visual hierarchy - Refined icon and text sizes for density
- In-progress tasks now display activeForm instead of content - Added CSS animation for ellipsis (...) on activeForm - Animation cycles through '', '.', '..', '...' every 1.5s - Increased activeForm font size to 11px (matches other text) - Removed margin-top since activeForm is now the primary text
- Changed animation from content change to width animation - Uses overflow: hidden with steps(4, end) for smooth dots reveal - Fixed width prevents layout shifts and line breaks - Ellipsis animates from 0 width to 1em, showing dots progressively
Changes: - Validation now enforces completed first, in_progress middle, pending last - Updated all test fixtures to match new order - Updated tool description to emphasize using TODOs for all complex multi-step operations - Fixed ellipsis animation to prevent line breaks (width animation with overflow:hidden) - In-progress tasks now show only activeForm (not content) with animated ellipsis This creates a more natural progress view: what's done → what's happening → what's next
- Use TooltipWrapper pattern for emoji display (matches other tools) - Removed ToolName component in favor of tooltip - Added instruction to mark all todos completed before finishing stream - Ensures consistency with bash, file_read, etc. tool displays
- Created TodoList.tsx with all styling and rendering logic - TodoToolCall now uses shared component - Changed default expansion to false (collapsed by default) - Keeps historical record when expanded - Prepares for PinnedTodoList component reuse
- Track current TODOs in Aggregator when todo_write succeeds - Clear TODOs when stream ends, aborts, or errors - Add getCurrentTodos() getter for efficient access - Single source of truth for TODO state - Automatic cleanup on stream completion
- Simple passthrough to Aggregator.getCurrentTodos() - Returns empty array if workspace doesn't exist - Efficient O(1) lookup by workspace ID - No caching needed since Aggregator manages state
- Reuses TodoList component for rendering - Subscribes to WorkspaceStore for reactivity - Shows only when TODOs exist - Styled with border and max-height - Ready to be positioned in chat
- Added to AIView.tsx right before StreamingBarrier - Shows at bottom of message list - Only renders when TODOs exist for current workspace - Automatically updates when TODOs change via WorkspaceStore subscription
Resolved conflict in TodoToolCall.tsx by keeping refactored version that uses shared TodoList component.
- Remove unused workspaceState variable in PinnedTodoList - Add proper TodoItem type imports instead of inline import() - Use TodoItem[] for simple array types (not Array<TodoItem>) - Fix formatting with prettier
Instead of duplicating 'this.currentTodos = []' and 'this.activeStreams.delete()' in handleStreamEnd, handleStreamAbort, and handleStreamError, extract to a single private method. Benefits: - DRY: Single source of truth for stream cleanup - Maintainability: Adding new stream-scoped state only requires updating one place - Clarity: Explicit method name documents intent
- Small, subtle header above the pinned TODO list - Uses monospace font at 10px with secondary text color - Letterspacing for visual clarity - Helps identify the component in the chat view
Use 1px dashed border with hsl(0deg 0% 28.64%) for a more subtle, distinguished look that separates the TODO list from the chat.
Schema changes:
- Removed activeForm field from TodoItem type
- Updated tool description to use tense-based content:
- Past tense for completed ('Added tests')
- Present progressive for in_progress ('Adding tests')
- Imperative for pending ('Add tests')
- Saves tokens by using single field with context-appropriate tense
UI improvements:
- Made pinned TODO list collapsible with animated caret
- Colon disappears when collapsed ('TODO:' → 'TODO')
- Collapse state persisted globally with usePersistedState
- Blue color and ellipsis animation for in_progress items
- Updated TodoList component to handle all statuses with single field
Tests:
- Removed all activeForm references from tests
- All 11 tests still pass
Changed 'before finishing the stream' to 'before finishing your response' for better clarity from the AI's perspective.
ammario
approved these changes
Oct 15, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Refactors TODO display to pin at bottom of chat (before StreamingBarrier) with state managed by Aggregator.
Changes
Shared TODO List Component:
Backend - Aggregator:
Frontend - WorkspaceStore:
UI:
Generated with
cmux