feat(chatkit): Agentic UI Dashboard with Widget Actions - #21
Conversation
…et actions ## Summary - Implemented interactive task widgets with status-specific action buttons - Added clear button labels for all widget actions (Start, Complete, Review, etc.) - Created comprehensive widget builders for task lists, forms, and confirmations - Enhanced ChatKit skills/agents with critical debugging lessons and anti-patterns ## Backend Changes - Widget builders: task_list, task_form, audit_timeline, projects - Widget action handler with proper RequestContext handling - Local tool wrappers for MCP → widget streaming - Fixed Action.payload vs Action.arguments bug - Fixed UserMessageItem required fields validation ## Frontend Changes - Workspace page with ChatKit integration - Context badges and progress indicators - Enhanced sidebar with workspace navigation - ChatKit configuration utilities ## Documentation Improvements - Updated chatkit-actions skill with critical implementation details - Added common Pydantic validation errors section - Enhanced chatkit-integration skill with new convergence patterns - Updated expert agent with comprehensive anti-patterns and checklist - Added widget action testing checklist ## Key Learnings Captured - Type annotation vs runtime mismatch (RequestContext) - Action object uses payload, not arguments - UserMessageItem required fields (id, thread_id, created_at, inference_options) - Local tool wrappers needed for widget streaming via RunHooks - Python auto-reload reliability issues 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR implements a comprehensive Agentic UI Dashboard feature that transforms the basic ChatKit integration into an interactive experience with widgets, server actions, and entity tagging. The implementation adds ~6,500 lines of code across backend widget systems, frontend workspace UI, and extensive documentation.
Key Changes
- Backend Widget System: Modular builders for task lists, forms, audit timelines, and projects with server-side action handlers supporting widget interactions
- Frontend Workspace: New
/workspaceroute with full-page AI command center including context badges, progress indicators, and ChatKit integration - Knowledge Capture: Comprehensive documentation of debugging patterns, Pydantic validation fixes, and type annotation mismatches in skills and agent files
Reviewed changes
Copilot reviewed 41 out of 42 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
web-dashboard/src/app/workspace/page.tsx |
New 765-line workspace page with project context, command palette, and integrated ChatKit |
web-dashboard/src/lib/chatkit-config.ts |
Centralized ChatKit configuration with entity tagging and streaming state types |
web-dashboard/src/components/chat/ProgressIndicator.tsx |
Loading indicator for AI response streaming with spinner animation |
web-dashboard/src/components/chat/ContextBadge.tsx |
Project context display with clear functionality and loading states |
web-dashboard/src/components/chat/ChatKitWidget.tsx |
Enhanced with project name fetching, action handlers for navigation, and streaming state tracking |
packages/api/src/taskflow_api/services/widgets/task_list.py |
348-line task list widget builder with status-specific action buttons |
packages/api/src/taskflow_api/services/widgets/task_form.py |
Form and confirmation widgets for task creation with validation |
packages/api/src/taskflow_api/services/widgets/audit_timeline.py |
Timeline widget with relative timestamps and actor type indicators |
packages/api/src/taskflow_api/services/chatkit_server.py |
Major expansion with local tool wrappers, widget streaming hooks, and action handlers (~590 lines added) |
packages/api/src/taskflow_api/routers/members.py |
Split routers for member search (autocomplete) and project-specific members |
packages/mcp-server/src/taskflow_mcp/tools/tasks.py |
Added show_task_form tool for triggering form widget display |
.claude/skills/engineering/chatkit-actions/SKILL.md |
Critical implementation details section with common Pydantic errors and fixes |
.claude/agents/engineering/chatkit-expert-agent.md |
Enhanced anti-patterns and comprehensive testing checklist (14 new items) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| useEffect(() => { | ||
| if (!isAuthenticated) return; | ||
|
|
||
| async function fetchData() { | ||
| try { | ||
| const projectsData = await api.getProjects({ limit: 10 }); | ||
| if (isMountedRef.current) { | ||
| setProjects(projectsData); | ||
| if (projectsData.length > 0 && !selectedProject) { | ||
| setSelectedProject(projectsData[0]); | ||
| // Load tasks for first project | ||
| const tasks = await api.getProjectTasks(projectsData[0].id, { limit: 5 }); | ||
| setRecentTasks(tasks); | ||
| } | ||
| } | ||
| } catch (error) { | ||
| console.error("[Workspace] Failed to load data:", error); | ||
| } | ||
| } | ||
|
|
||
| fetchData(); | ||
| }, [isAuthenticated, selectedProject]); |
There was a problem hiding this comment.
The useEffect dependency array includes selectedProject on line 125, which causes the effect to run whenever the project changes. However, inside the effect (line 112), it only sets the selected project if projectsData.length > 0 && !selectedProject, which will never be true after the first run. This creates an infinite loop: changing the project triggers the effect, which might trigger another change.
Consider removing selectedProject from the dependency array on line 125, or refactoring this logic to separate initial load from project changes.
| const { user, isAuthenticated, isLoading: authLoading, login } = useAuth(); | ||
| const pathname = usePathname(); | ||
| const params = useParams(); | ||
| const router = useRouter(); |
There was a problem hiding this comment.
Unused variable router.
|
|
||
| def test_form_with_project_context(self) -> None: | ||
| """Form shows project context.""" | ||
| widget = build_task_form_widget(project_id=1, project_name="Test Project") |
There was a problem hiding this comment.
Keyword argument 'project_name' is not a supported parameter name of function build_task_form_widget.
| widget = build_task_form_widget(project_id=1, project_name="Test Project") | |
| widget = build_task_form_widget(project_id=1) |
|
|
||
| # Get project info from context | ||
| project_id = context.context.project_id | ||
| project_name = context.context.project_name |
There was a problem hiding this comment.
Variable project_name is not used.
| project_name = context.context.project_name |
| raise ValueError("task_id required") | ||
|
|
||
| # Call MCP tool to complete task | ||
| result = await mcp_server.call_tool( |
There was a problem hiding this comment.
Variable result is not used.
| result = await mcp_server.call_tool( | |
| await mcp_server.call_tool( |
| raise ValueError("task_id required") | ||
|
|
||
| # Call MCP tool to start task | ||
| result = await mcp_server.call_tool( |
There was a problem hiding this comment.
Variable result is not used.
| result = await mcp_server.call_tool( | |
| await mcp_server.call_tool( |
| due_date = payload.get("task.dueDate") or payload.get("due_date") | ||
|
|
There was a problem hiding this comment.
Variable due_date is not used.
| due_date = payload.get("task.dueDate") or payload.get("due_date") |
| # Import all tool modules to register their @mcp.tool() decorators | ||
| # These imports have side effects: they register tools with the mcp instance | ||
| import taskflow_mcp.tools.tasks # noqa: F401 - 9 task tools | ||
| import taskflow_mcp.tools.tasks # noqa: F401 - 10 task tools |
There was a problem hiding this comment.
Import of 'taskflow_mcp' is not used.
| import pytest | ||
|
|
There was a problem hiding this comment.
Import of 'pytest' is not used.
| import pytest |
…ing for Agentic UI features
**Linting Fixes:** - Move httpx import to top of file (E402) - Fix line length issues in comments (E501) - Remove unused variables (F841): project_name, result, due_date - Fix import sorting (I001) - Fix type annotations (UP045): Optional[X] → X | None **Test Fixes:** - Update test_build_empty_task_list to match Card widget structure - Note: Widget tests need updates for new API surface (8 tests failing) - All core tests pass (41/41 tests) **Changes:** - `chatkit_server.py`: Import fixes, unused variable removal, line wrapping - `main.py`: Comment line wrapping - `chat_agent.py`: Multiple line wrapping fixes for long comments - `members.py`: Auto-fixed by ruff (Optional → X | None) - `test_widgets.py`: Updated empty task list test expectations **Widget Test Status:** - Core functionality tests: ✅ 41/41 passing - Widget structure tests:⚠️ 8/15 failing (API surface changes) - Widget tests need follow-up to match new Card/ListView structure 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
**Copilot Feedback Fixes:** Frontend: - Fix useEffect infinite loop in workspace/page.tsx - Removed selectedProject from dependency array - Effect only runs on initial auth, not on project changes - Remove unused router import/variable in ChatKitWidget.tsx Backend Tests: - Update all widget tests to match current API surface - All 15 widget tests now passing ✅ **Widget Test Updates:** TaskListWidget (3 tests): - Update to use widget["children"] instead of widget["items"] - Update item type from "Box" to "ListViewItem" - Fix button label assertions TaskFormWidget (4 tests): - Update widget type from "Box" to "Card" - Remove project_name parameter (doesn't exist) - Simplify assertions to match nested Form structure - Add _flatten_children helper for button detection TaskCreatedConfirmation (1 test): - Update widget type from "Box" to "Card" - Fix field name from "content" to "value" - Check Title/Text/Caption types for success message **Test Results:** - Widget tests: ✅ 15/15 passing (was 7/15) - Core tests: ✅ 41/41 passing - Total: ✅ 56/56 tests passing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Summary
Implements a comprehensive agentic UI dashboard with interactive ChatKit widgets and captures critical debugging lessons from the implementation process.
What Changed
Backend Widget System
Frontend Dashboard
/workspaceroute with ChatKit integrationDocumentation & Knowledge Capture
Key Technical Improvements
Fixed Critical Bugs
.payloadnot.argumentstype="input_text"for user inputWidget Action Enhancements
Knowledge Capture
All debugging lessons documented in skills/agents to prevent future similar issues:
Testing
Files Changed
Backend (15 files):
packages/api/src/taskflow_api/services/widgets/- New widget builderspackages/api/src/taskflow_api/services/chatkit_server.py- Action handler fixespackages/api/src/taskflow_api/services/chat_agent.py- Status workflow updatespackages/mcp-server/src/taskflow_mcp/tools/tasks.py- New show_task_form toolFrontend (8 files):
web-dashboard/src/app/workspace/- New workspace pageweb-dashboard/src/components/chat/- ChatKit widget enhancementsweb-dashboard/src/lib/chatkit-config.ts- Configuration utilitiesDocumentation (4 files):
.claude/skills/engineering/chatkit-actions/SKILL.md.claude/skills/engineering/chatkit-integration/SKILL.md.claude/agents/engineering/chatkit-expert-agent.md.claude/agents/engineering/chatkit-integration-agent.mdSpecs & History (15 files):
specs/008-agentic-ui-dashboard/- Complete spec, plan, taskshistory/prompts/agentic-ui-dashboard/- PHR recordsFuture Work
🤖 Generated with Claude Code