mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-18 15:48:04 +02:00
166 lines
9.6 KiB
Markdown
166 lines
9.6 KiB
Markdown
# assistant-ui + Tool UI Migration Plan
|
||
|
||
## Goal
|
||
|
||
Replace the custom chat UI in `frontend/src/app/pages/AgentChat/` with [assistant-ui](https://www.assistant-ui.com/) (React chat primitives) and [Tool UI](https://www.tool-ui.com/) (tool call rendering components). This replaces ~5,800 lines of custom chat code with maintained, accessible, schema-driven components.
|
||
|
||
## Decisions
|
||
|
||
- **Tailwind + MUI coexist**: Tailwind is added for assistant-ui/Tool UI; MUI stays for non-chat pages (Dashboard, Settings, etc.)
|
||
- **Clean swap**: No feature flag — old code is replaced directly
|
||
- **No custom styling**: Use default assistant-ui/Tool UI appearance as-is (no theming to match MUI)
|
||
- **SkillBuilderChat**: Included in migration
|
||
- **Sub-agent rendering**: Kept as-is, wired into toolkit as custom tool UIs
|
||
|
||
## Architecture: Before → After
|
||
|
||
### Before
|
||
```
|
||
AgentChat.tsx
|
||
├── useAgentChat.ts (WS lifecycle, session state)
|
||
├── useMessageRendering.ts (branch resolution, render items)
|
||
├── ChatInput.tsx + CommandPicker (custom contentEditable + @/slash picker)
|
||
├── MessageBubble → UserBubbleContent / AssistantBubbleContent (custom markdown)
|
||
├── MessageActionBar (copy/edit/regen/branch)
|
||
├── BranchNavigator (custom branch picker)
|
||
├── ToolCallBubble + toolCallColors + toolCallUtils (custom terminal rendering)
|
||
├── ToolGroupBubble (custom accordion)
|
||
├── ApprovalBar / BatchApprovalBar / QuestionForm (custom HITL)
|
||
├── GmailCard / McpServiceCards (custom MCP rendering)
|
||
├── BrowserAgentInlineFeed (custom progress feed)
|
||
├── DiffViewer (custom diff rendering)
|
||
└── ThinkingBubble (custom reasoning display)
|
||
```
|
||
|
||
### After
|
||
```
|
||
AgentChat.tsx
|
||
├── AssistantRuntimeProvider + ExternalStoreRuntime (bridges Redux + WS)
|
||
├── OpenSwarmThread (assistant-ui Thread + Message + ActionBar + BranchPicker)
|
||
├── OpenSwarmComposer (assistant-ui Composer + ComposerMentionPopover)
|
||
├── Toolkit registry
|
||
│ ├── native-tools.tsx → Tool UI Terminal, CodeBlock, CodeDiff
|
||
│ ├── approval-tools.tsx → Tool UI ApprovalCard, QuestionFlow, OptionList
|
||
│ ├── mcp-tools.tsx → Tool UI MessageDraft, DataTable, ProgressTracker
|
||
│ └── custom-tools.tsx → AgentToolBubble, ViewBubble (kept as-is)
|
||
├── ModelModeSelector (kept, MUI)
|
||
├── MessageQueue (kept, MUI)
|
||
└── ChatHeader (kept, MUI)
|
||
```
|
||
|
||
## Phases & Dependency Graph
|
||
|
||
```
|
||
┌─────────────────────────────────────┐
|
||
│ PHASE 1 — Sequential (blocking) │
|
||
│ Agent 1: Foundation & Packages │
|
||
└──────────────┬──────────────────────┘
|
||
│
|
||
┌─────────┼──────────┬──────────────┬──────────────┐
|
||
│ │ │ │ │
|
||
▼ ▼ ▼ ▼ ▼
|
||
┌─────────┐┌─────────┐┌──────────┐┌──────────┐┌──────────────┐
|
||
│ Agent 2 ││ Agent 3 ││ Agent 4 ││ Agent 5 ││ Agent 6 │
|
||
│ Thread ││Composer ││ Tool UI: ││ Tool UI: ││ Tool UI: │
|
||
│ & ││ & ││ Native ││Approvals ││ MCP Cards │
|
||
│Messages ││Mentions ││ Tools ││ & ││ & Browser │
|
||
│ ││ ││ ││Questions ││ Feed │
|
||
└────┬────┘└────┬────┘└────┬─────┘└────┬─────┘└──────┬───────┘
|
||
│ │ │ │ │
|
||
│ PHASE 2 — All 5 agents run in parallel │
|
||
│ │ │ │ │
|
||
└─────────┴──────────┴────────────┴─────────────┘
|
||
│
|
||
┌───────────▼───────────────┐
|
||
│ PHASE 3 — Sequential │
|
||
│ Agent 7: Integration, │
|
||
│ SkillBuilderChat & │
|
||
│ Cleanup │
|
||
└───────────────────────────┘
|
||
```
|
||
|
||
## Agent Summary
|
||
|
||
| Agent | Plan File | Phase | What It Does |
|
||
|-------|-----------|-------|-------------|
|
||
| 1 | `MIGRATION_AGENT_1.md` | 1 (sequential) | Install Tailwind, shadcn, assistant-ui, Tool UI packages. Create ExternalStoreRuntime adapter, toolkit skeleton, new directory structure. Scaffold `AgentChat.tsx` with provider wrapper. |
|
||
| 2 | `MIGRATION_AGENT_2.md` | 2 (parallel) | Replace message list with `Thread`. Replace bubbles with `Message` primitives. Replace `MessageActionBar` → `ActionBar`, `BranchNavigator` → `BranchPicker`, `ThinkingBubble` → `Reasoning`. |
|
||
| 3 | `MIGRATION_AGENT_3.md` | 2 (parallel) | Replace `ChatInput` + `CommandPicker` with `Composer` + `ComposerMentionPopover`. Create `MentionAdapter` for templates/skills/modes/tools/files. |
|
||
| 4 | `MIGRATION_AGENT_4.md` | 2 (parallel) | Register Tool UI components for native tools: `Terminal` (bash), `CodeBlock` (file read), `CodeDiff` (edit/diff). Replace `ToolCallBubble`, `toolCallColors`, `toolCallUtils`. |
|
||
| 5 | `MIGRATION_AGENT_5.md` | 2 (parallel) | Register Tool UI components for approvals: `ApprovalCard`, `QuestionFlow`, `OptionList`. Replace `ApprovalBar`, `BatchApprovalBar`, `QuestionForm`, `ToolPreview`. |
|
||
| 6 | `MIGRATION_AGENT_6.md` | 2 (parallel) | Register Tool UI for MCP services: `MessageDraft` (Gmail), `DataTable` (Calendar/Drive), `ProgressTracker` (browser feed). Wire `AgentToolBubble` and `ViewBubble` as custom toolkit entries. |
|
||
| 7 | `MIGRATION_AGENT_7.md` | 3 (sequential) | Wire all pieces in `AgentChat.tsx`. Migrate `SkillBuilderChat`. Delete all dead files. Verify build. |
|
||
|
||
## File Ownership (Parallel Safety)
|
||
|
||
During Phase 2, each agent only touches files it owns. No conflicts.
|
||
|
||
| Agent | Creates | Modifies | Deletes |
|
||
|-------|---------|----------|---------|
|
||
| 2 | `thread/` directory | Nothing shared | `MessageBubble`, `UserBubbleContent`, `AssistantBubbleContent`, `MessageActionBar`, `BranchNavigator`, `ThinkingBubble`, `MessageImageThumbnails`, `messageBubbleUtils`, `useMessageRendering` |
|
||
| 3 | `composer/` directory | Nothing shared | `ChatInput`, `useChatSubmit`, `CommandPicker`, `commandPickerTypes`, `useCommandPickerItems`, `CommandPickerIcons`, `SlashCommandPicker`, `AttachmentChips`, `ImageAttachments`, `richEditorUtils`, `RichPromptEditor` |
|
||
| 4 | `toolkit/native-tools.tsx` | Nothing shared | `ToolCallBubble`, `toolCallColors`, `toolCallUtils`, `ElapsedTimer`, `ToolGroupBubble` |
|
||
| 5 | `toolkit/approval-tools.tsx` | Nothing shared | `ApprovalBar`, `BatchApprovalBar`, `QuestionForm`, `ToolPreview`, `approvalUtils` |
|
||
| 6 | `toolkit/mcp-tools.tsx`, `toolkit/custom-tools.tsx` | Nothing shared | `GmailCard`, `McpServiceCards`, `BrowserAgentInlineFeed`, `BrowserFeedEntryRow`, `browserFeedUtils`, `DiffViewer` |
|
||
| 7 | (integration) | `AgentChat.tsx`, `SkillBuilderChat.tsx` | Remaining dead imports/files |
|
||
|
||
## Key Technical Notes
|
||
|
||
### ExternalStoreRuntime Adapter
|
||
|
||
The runtime adapter (`runtime/useOpenSwarmRuntime.ts`) bridges Redux ↔ assistant-ui:
|
||
- **Messages**: Read from `session.messages` + `session.streamingMessage` in Redux
|
||
- **isRunning**: Derived from `session.status === 'running'`
|
||
- **onNew**: Dispatches `sendMessage` thunk → WebSocket
|
||
- **onEdit**: Dispatches `editMessage` thunk → REST API
|
||
- **onCancel**: Dispatches `stopAgent` thunk → REST API
|
||
- **Branches**: Mapped from `session.branches` + `session.active_branch_id`
|
||
|
||
### Message Format Conversion
|
||
|
||
Redux `AgentMessage` → assistant-ui format:
|
||
- `role: 'user'` → `{ role: 'user', content: [{ type: 'text', text }] }`
|
||
- `role: 'assistant'` → `{ role: 'assistant', content: [{ type: 'text', text }] }`
|
||
- `role: 'tool_call'` → `{ role: 'assistant', content: [{ type: 'tool-call', toolCallId, toolName, args }] }`
|
||
- `role: 'tool_result'` → `{ role: 'tool', content: [{ type: 'tool-result', toolCallId, result }] }`
|
||
|
||
### Tailwind + MUI Coexistence
|
||
|
||
Tailwind is configured with a prefix or scoped to assistant-ui components to avoid conflicts with MUI's global styles. The `important` selector strategy or Tailwind's `prefix` option may be needed.
|
||
|
||
### Tool UI Registration Pattern
|
||
|
||
All Tool UI components are registered in toolkit files. Each toolkit file exports a partial `Toolkit` object. The `toolkit/index.ts` merges them:
|
||
|
||
```typescript
|
||
import { nativeToolkit } from './native-tools';
|
||
import { approvalToolkit } from './approval-tools';
|
||
import { mcpToolkit } from './mcp-tools';
|
||
import { customToolkit } from './custom-tools';
|
||
|
||
export const toolkit: Toolkit = {
|
||
...nativeToolkit,
|
||
...approvalToolkit,
|
||
...mcpToolkit,
|
||
...customToolkit,
|
||
};
|
||
```
|
||
|
||
## Lines of Code Impact (Estimated)
|
||
|
||
| Category | Lines |
|
||
|----------|-------|
|
||
| Deleted (old components) | ~5,800 |
|
||
| New bridge/adapter code | ~600–800 |
|
||
| Tool UI components (installed, not authored) | ~2,000 (maintained externally) |
|
||
| **Net reduction in authored code** | **~5,000** |
|
||
|
||
## Estimated Effort
|
||
|
||
| Phase | Agents | Estimated Time |
|
||
|-------|--------|---------------|
|
||
| Phase 1 | Agent 1 | 1–2 hours |
|
||
| Phase 2 | Agents 2–6 (parallel) | 2–4 hours each, ~4 hours wall clock |
|
||
| Phase 3 | Agent 7 | 1–2 hours |
|
||
| **Total wall clock** | | **~6–8 hours** |
|