mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 11:41:04 +00:00
chore(vscode-ide-companion, webui): update plan md
This commit is contained in:
parent
3f42639d49
commit
73b4a9b560
6 changed files with 203 additions and 201 deletions
428
packages/webui/docs/WEBUI_MIGRATION_PLAN_EN.md
Normal file
428
packages/webui/docs/WEBUI_MIGRATION_PLAN_EN.md
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
# WebUI Component Library Extraction Plan
|
||||
|
||||
## 1. Background and Goals
|
||||
|
||||
### 1.1 Background
|
||||
|
||||
`packages/vscode-ide-companion` is a VSCode extension whose core content is a WebView page with UI components provided by React. As the product line expands, more scenarios require building products with Web UI:
|
||||
|
||||
- **Chrome Browser Extension** - Sidebar chat interface
|
||||
- **Web Chat Page** - Pure web application
|
||||
- **Conversation Share Page** - Render conversations as static HTML
|
||||
|
||||
For excellent software engineering architecture, we need to unify and reuse UI components across products.
|
||||
|
||||
### 1.2 Goals
|
||||
|
||||
1. Extract components from `vscode-ide-companion/src/webview/` into an independent `@qwen-code/webui` package
|
||||
2. Establish a layered architecture: Pure UI components + Business UI components
|
||||
3. Use Vite + Storybook for development and component showcase
|
||||
4. Abstract platform capabilities through Platform Context for cross-platform reuse
|
||||
5. Provide Tailwind CSS preset to ensure UI consistency across products
|
||||
|
||||
---
|
||||
|
||||
## 2. Current State Analysis
|
||||
|
||||
### 2.1 Current Code Structure
|
||||
|
||||
`packages/vscode-ide-companion/src/webview/` contains 77 files:
|
||||
|
||||
```
|
||||
webview/
|
||||
├── App.tsx # Main entry
|
||||
├── components/
|
||||
│ ├── icons/ # 8 icon components
|
||||
│ ├── layout/ # 8 layout components
|
||||
│ │ ├── ChatHeader.tsx
|
||||
│ │ ├── InputForm.tsx
|
||||
│ │ ├── SessionSelector.tsx
|
||||
│ │ ├── EmptyState.tsx
|
||||
│ │ ├── Onboarding.tsx
|
||||
│ │ └── ...
|
||||
│ ├── messages/ # Message display components
|
||||
│ │ ├── UserMessage.tsx
|
||||
│ │ ├── Assistant/
|
||||
│ │ ├── MarkdownRenderer/
|
||||
│ │ ├── ThinkingMessage.tsx
|
||||
│ │ ├── Waiting/
|
||||
│ │ └── toolcalls/ # 16 tool call components
|
||||
│ ├── PermissionDrawer/ # Permission request drawer
|
||||
│ └── Tooltip.tsx
|
||||
├── hooks/ # Custom hooks
|
||||
├── handlers/ # Message handlers
|
||||
├── styles/ # CSS styles
|
||||
└── utils/ # Utility functions
|
||||
```
|
||||
|
||||
### 2.2 Key Dependency Analysis
|
||||
|
||||
**Platform Coupling Points:**
|
||||
|
||||
- `useVSCode` hook - Calls `acquireVsCodeApi()` for message communication
|
||||
- `handlers/` - Handles VSCode message protocol
|
||||
- Some type definitions come from `../types/` directory
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ App.tsx (Entry) │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ hooks/ │ handlers/ │ components/ │
|
||||
│ ├─useVSCode ◄───┼──────────────────┼──────────────────┤
|
||||
│ ├─useSession │ ├─MessageRouter │ ├─icons/ │
|
||||
│ ├─useFileContext│ ├─AuthHandler │ ├─layout/ │
|
||||
│ └─... │ └─... │ ├─messages/ │
|
||||
│ │ │ └─PermDrawer/ │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ VSCode API (acquireVsCodeApi) │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Target Architecture
|
||||
|
||||
### 3.1 Layered Architecture Design
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Layer 3: Platform Adapters │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │VSCode Adapter│ │Chrome Adapter│ │ Web Adapter │ │
|
||||
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
|
||||
├─────────┼────────────────┼────────────────┼────────────┤
|
||||
│ │ │ │ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────┐ │
|
||||
│ │ Platform Context Provider │ │
|
||||
│ └─────────────────────────────────────────────────┘ │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ Layer 2: Chat Components │
|
||||
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ MessageList│ │ ChatHeader │ │ InputForm │ │
|
||||
│ └────────────┘ └────────────┘ └────────────┘ │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ Layer 1: Primitives (Pure UI) │
|
||||
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
|
||||
│ │ Button │ │ Input │ │ Icons │ │Tooltip │ │
|
||||
│ └────────┘ └────────┘ └────────┘ └────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.2 Platform Context Design
|
||||
|
||||
```typescript
|
||||
// @qwen-code/webui/src/context/PlatformContext.ts
|
||||
interface PlatformContext {
|
||||
// Message communication
|
||||
postMessage: (message: unknown) => void;
|
||||
onMessage: (handler: (message: unknown) => void) => () => void;
|
||||
|
||||
// File operations
|
||||
openFile?: (path: string) => void;
|
||||
attachFile?: () => void;
|
||||
|
||||
// Authentication
|
||||
login?: () => void;
|
||||
|
||||
// Platform info
|
||||
platform: 'vscode' | 'chrome' | 'web' | 'share';
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Technical Solution
|
||||
|
||||
### 4.1 Build Configuration (Vite Library Mode)
|
||||
|
||||
**Output formats:**
|
||||
|
||||
- ESM (`dist/index.js`) - Primary format
|
||||
- CJS (`dist/index.cjs`) - Compatibility
|
||||
- TypeScript declarations (`dist/index.d.ts`)
|
||||
|
||||
```javascript
|
||||
// vite.config.ts
|
||||
export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'src/index.ts'),
|
||||
formats: ['es', 'cjs'],
|
||||
fileName: (format) => `index.${format === 'es' ? 'js' : 'cjs'}`,
|
||||
},
|
||||
rollupOptions: {
|
||||
external: ['react', 'react-dom'],
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### 4.2 Tailwind Preset Solution
|
||||
|
||||
```javascript
|
||||
// @qwen-code/webui/tailwind.preset.js
|
||||
module.exports = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
'app-primary': 'var(--app-primary)',
|
||||
'app-background': 'var(--app-primary-background)',
|
||||
'app-foreground': 'var(--app-primary-foreground)',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Consumer's tailwind.config.js
|
||||
module.exports = {
|
||||
presets: [require('@qwen-code/webui/tailwind.preset')],
|
||||
content: [
|
||||
'./src/**/*.{ts,tsx}',
|
||||
'./node_modules/@qwen-code/webui/dist/**/*.js',
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
### 4.3 Storybook Configuration
|
||||
|
||||
```
|
||||
packages/webui/
|
||||
├── .storybook/
|
||||
│ ├── main.ts # Storybook config
|
||||
│ ├── preview.ts # Global decorators
|
||||
│ └── manager.ts # UI config
|
||||
└── src/
|
||||
└── stories/ # Story files
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Component Migration Classification
|
||||
|
||||
### 5.1 Batch 1: No-dependency Components (Ready to migrate)
|
||||
|
||||
| Component | Source Path | Complexity | Notes |
|
||||
| ------------------ | ------------------------ | ---------- | --------------------------- |
|
||||
| Icons | `components/icons/` | Low | 8 icon components, pure SVG |
|
||||
| Tooltip | `components/Tooltip.tsx` | Low | Pure UI |
|
||||
| WaitingMessage | `messages/Waiting/` | Low | Loading state display |
|
||||
| InterruptedMessage | `messages/Waiting/` | Low | Interrupted state display |
|
||||
|
||||
### 5.2 Batch 2: Light-dependency Components (Need props abstraction)
|
||||
|
||||
| Component | Source Path | Dependency | Refactoring |
|
||||
| ---------------- | ------------------------------ | ----------- | ---------------- |
|
||||
| UserMessage | `messages/UserMessage.tsx` | onFileClick | Props injection |
|
||||
| AssistantMessage | `messages/Assistant/` | onFileClick | Props injection |
|
||||
| ThinkingMessage | `messages/ThinkingMessage.tsx` | onFileClick | Props injection |
|
||||
| MarkdownRenderer | `messages/MarkdownRenderer/` | None | Direct migration |
|
||||
| EmptyState | `layout/EmptyState.tsx` | None | Direct migration |
|
||||
| ChatHeader | `layout/ChatHeader.tsx` | callbacks | Props injection |
|
||||
|
||||
### 5.3 Batch 3: Medium-dependency Components (Need Context)
|
||||
|
||||
| Component | Source Path | Dependency | Refactoring |
|
||||
| ------------------- | ---------------------------- | --------------------- | ----------------- |
|
||||
| InputForm | `layout/InputForm.tsx` | Multiple callbacks | Context + Props |
|
||||
| SessionSelector | `layout/SessionSelector.tsx` | session data | Props injection |
|
||||
| CompletionMenu | `layout/CompletionMenu.tsx` | items data | Props injection |
|
||||
| PermissionDrawer | `PermissionDrawer/` | callbacks | Context + Props |
|
||||
| ToolCall components | `messages/toolcalls/` | Various tool displays | Modular migration |
|
||||
|
||||
### 5.4 Batch 4: Heavy-dependency (Keep in platform package)
|
||||
|
||||
| Component/Module | Notes |
|
||||
| ---------------- | ------------------------------------------------- |
|
||||
| App.tsx | Main entry, contains business orchestration logic |
|
||||
| hooks/ | Most require platform adaptation |
|
||||
| handlers/ | VSCode message handling |
|
||||
| Onboarding | Authentication related, platform-specific |
|
||||
|
||||
---
|
||||
|
||||
## 6. Incremental Migration Strategy
|
||||
|
||||
### 6.1 Migration Principles
|
||||
|
||||
1. **Bidirectional compatibility**: During migration, vscode-ide-companion can import from both webui and local
|
||||
2. **One-by-one replacement**: For each migrated component, replace import path in VSCode extension and verify
|
||||
3. **No breaking changes**: Ensure the extension builds and runs normally after each migration
|
||||
|
||||
### 6.2 Migration Workflow
|
||||
|
||||
```
|
||||
Developer ──► @qwen-code/webui ──► vscode-ide-companion
|
||||
│ │ │
|
||||
│ 1. Copy component to webui │
|
||||
│ 2. Add Story for verification │
|
||||
│ 3. Export from index.ts │
|
||||
│ │ │
|
||||
│ └──────────────────────┤
|
||||
│ │
|
||||
│ 4. Update import path
|
||||
│ 5. Delete original component
|
||||
│ 6. Build and test
|
||||
```
|
||||
|
||||
### 6.3 Example: Migrating Icons
|
||||
|
||||
```typescript
|
||||
// Before: vscode-ide-companion/src/webview/components/icons/index.ts
|
||||
export { FileIcon } from './FileIcons.js';
|
||||
|
||||
// After: Update import
|
||||
import { FileIcon } from '@qwen-code/webui';
|
||||
// or import { FileIcon } from '@qwen-code/webui/icons';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Task Breakdown
|
||||
|
||||
### Phase 0: Infrastructure Setup (Prerequisites)
|
||||
|
||||
- [ ] **T0-1**: Vite build configuration
|
||||
- [ ] **T0-2**: Storybook configuration
|
||||
- [ ] **T0-3**: Tailwind preset creation
|
||||
- [ ] **T0-4**: Platform Context definition
|
||||
- [ ] **T0-5**: Shared types migration
|
||||
|
||||
### Phase 1: Pure UI Components Migration
|
||||
|
||||
- [ ] **T1-1**: Icons components migration (8 files)
|
||||
- [ ] **T1-2**: Tooltip component migration
|
||||
- [ ] **T1-3**: WaitingMessage / InterruptedMessage migration
|
||||
- [ ] **T1-4**: Basic Button/Input components refinement
|
||||
|
||||
### Phase 2: Message Components Migration
|
||||
|
||||
- [ ] **T2-1**: MarkdownRenderer migration
|
||||
- [ ] **T2-2**: UserMessage migration
|
||||
- [ ] **T2-3**: AssistantMessage migration
|
||||
- [ ] **T2-4**: ThinkingMessage migration
|
||||
|
||||
### Phase 3: Layout Components Migration
|
||||
|
||||
- [ ] **T3-1**: ChatHeader migration
|
||||
- [ ] **T3-2**: EmptyState migration
|
||||
- [ ] **T3-3**: InputForm migration (requires Context)
|
||||
- [ ] **T3-4**: SessionSelector migration
|
||||
- [ ] **T3-5**: CompletionMenu migration
|
||||
|
||||
### Phase 4: Complex Components Migration
|
||||
|
||||
- [ ] **T4-1**: PermissionDrawer migration
|
||||
- [ ] **T4-2**: ToolCall series components migration (16 files)
|
||||
|
||||
### Phase 5: Platform Adapters
|
||||
|
||||
- [ ] **T5-1**: VSCode Adapter implementation
|
||||
- [ ] **T5-2**: Chrome Extension Adapter
|
||||
- [ ] **T5-3**: Web/Share Page Adapter
|
||||
|
||||
---
|
||||
|
||||
## 8. Risks and Considerations
|
||||
|
||||
### 8.1 Common Pitfalls
|
||||
|
||||
1. **Tailwind Class Name Tree Shaking**
|
||||
- Problem: Tailwind class names may be removed after library bundling
|
||||
- Solution: Consumer's `content` config needs to include `node_modules/@qwen-code/webui`
|
||||
|
||||
2. **CSS Variable Scope**
|
||||
- Problem: Variables like `var(--app-primary)` need to be defined by consumers
|
||||
- Solution: Provide default CSS variables file, or define fallbacks in Tailwind preset
|
||||
|
||||
3. **React Version Compatibility**
|
||||
- Current vscode-ide-companion uses React 19, webui's peerDependencies is React 18
|
||||
- Need to update peerDependencies to `"react": "^18.0.0 || ^19.0.0"`
|
||||
|
||||
4. **ESM/CJS Compatibility**
|
||||
- VSCode extensions may require CJS format
|
||||
- Vite needs to be configured for dual format output
|
||||
|
||||
### 8.2 Industry References
|
||||
|
||||
- **Radix UI**: Pure Headless components, styles completely controlled by consumers
|
||||
- **shadcn/ui**: Copy components into project, rather than importing as dependency
|
||||
- **Ant Design**: Complete component library, customization through ConfigProvider
|
||||
|
||||
### 8.3 Acceptance Criteria
|
||||
|
||||
Each migration task completion requires:
|
||||
|
||||
1. Component has corresponding Storybook Story
|
||||
2. Import in vscode-ide-companion has been updated
|
||||
3. Extension builds successfully (`npm run build:vscode`)
|
||||
4. Extension functionality works (manual testing or existing tests pass)
|
||||
|
||||
---
|
||||
|
||||
## 9. Time Estimation
|
||||
|
||||
| Phase | Tasks | Estimated Days | Parallelizable |
|
||||
| ------- | ----- | -------------- | -------------- |
|
||||
| Phase 0 | 5 | 2-3 days | Partially |
|
||||
| Phase 1 | 4 | 1-2 days | Fully |
|
||||
| Phase 2 | 4 | 2-3 days | Fully |
|
||||
| Phase 3 | 5 | 3-4 days | Partially |
|
||||
| Phase 4 | 2 | 3-4 days | Yes |
|
||||
| Phase 5 | 3 | 2-3 days | Yes |
|
||||
|
||||
**Total**: Approximately 13-19 person-days (sequential execution), can be reduced to 1-2 weeks with parallel work
|
||||
|
||||
---
|
||||
|
||||
## 10. Development and Debugging Workflow
|
||||
|
||||
### 10.1 Component Development Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Development Workflow │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 1. Develop/Modify Component │
|
||||
│ └── Edit files in @qwen-code/webui/src/ │
|
||||
│ │
|
||||
│ 2. Debug with Storybook │
|
||||
│ └── npm run storybook (port 6006) │
|
||||
│ └── View component in isolation │
|
||||
│ └── Test different props/states │
|
||||
│ │
|
||||
│ 3. Build Library │
|
||||
│ └── npm run build │
|
||||
│ └── Outputs: dist/index.js, dist/index.cjs, dist/index.d.ts │
|
||||
│ │
|
||||
│ 4. Use in VSCode Extension │
|
||||
│ └── import { Component } from '@qwen-code/webui' │
|
||||
│ └── No UI code modifications in vscode-ide-companion │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 10.2 Debugging Commands
|
||||
|
||||
```bash
|
||||
# Start Storybook for component development
|
||||
cd packages/webui
|
||||
npm run storybook
|
||||
|
||||
# Watch mode for library development
|
||||
npm run dev
|
||||
|
||||
# Build library for production
|
||||
npm run build
|
||||
|
||||
# Type checking
|
||||
npm run typecheck
|
||||
```
|
||||
|
||||
### 10.3 Key Principles
|
||||
|
||||
1. **Single Source of Truth**: All UI components live in `@qwen-code/webui`
|
||||
2. **Storybook First**: Debug and validate components in Storybook before integration
|
||||
3. **No UI Code in Consumers**: `vscode-ide-companion` only imports and uses components
|
||||
4. **Platform Abstraction**: Use `PlatformContext` for platform-specific behaviors
|
||||
Loading…
Add table
Add a link
Reference in a new issue