mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-12 23:01:21 +00:00
- Create docs/architecture/phase-7-controlled-write-parallelism.md with full architectural design for Phase 7, covering: - Phase 7a: File Lock Manager (advisory file-level locking) - Phase 7b: Write-Capable Background Tasks (allowWrites parameter) - Phase 7c: Persistent Background Task History - Update Phase 6 doc to add forward references to Phase 7 for deferred items - Include risk analysis, testing strategy, dependency chain, and updated roadmap Addresses Issue #12330
327 lines
13 KiB
Markdown
327 lines
13 KiB
Markdown
# Phase 6: Background Task Visibility and Interaction
|
|
|
|
> Architectural design document for Issue #12330
|
|
> Phase 6 of "Support parallel execution of specialized agents and improve context handoff between modes"
|
|
|
|
## 1. Context
|
|
|
|
Phase 5 (Background Tasks Panel UI) is complete. This document proposes the scope, priority, and architecture for Phase 6, which focuses on enabling better visibility and interaction with background tasks.
|
|
|
|
## 2. Current Architecture
|
|
|
|
### Task Lifecycle
|
|
|
|
`ClineProvider` maintains a `clineStack: Task[]` (LIFO). Only the top-of-stack task is "current" -- all state updates, webview messages, and user interactions route through `getCurrentTask()`.
|
|
|
|
```
|
|
ClineProvider
|
|
├── clineStack: Task[] # LIFO stack, sequential execution
|
|
├── taskHistoryStore # Per-task file persistence
|
|
├── getCurrentTask() # Returns top of stack
|
|
├── addClineToStack(task) # Push new task
|
|
└── removeClineFromStack() # Pop completed task
|
|
```
|
|
|
|
### Task Persistence
|
|
|
|
| Layer | File | Purpose |
|
|
|-------|------|---------|
|
|
| Messages | `taskMessages.ts` | Save/load `ClineMessage[]` per task |
|
|
| API History | `apiMessages.ts` | Save/load API conversation history |
|
|
| History Items | `TaskHistoryStore.ts` | Per-task metadata files with in-memory cache |
|
|
| Metadata | `taskMetadata.ts` | Task metadata helpers |
|
|
|
|
### Webview Communication
|
|
|
|
The extension sends typed `ExtensionMessage` objects to the webview. Key message types:
|
|
|
|
- `state` -- Full state snapshot (includes `clineMessages`, `currentTaskId`)
|
|
- `taskHistoryUpdated` -- Full history list refresh
|
|
- `taskHistoryItemUpdated` -- Single history item update
|
|
|
|
Currently, `postStateToWebviewWithoutTaskHistory()` sends state for only the current task. There is no mechanism to send updates for background tasks.
|
|
|
|
### Subtask Support
|
|
|
|
Parent-child relationships exist via `parentTaskId` and `childIds` on `HistoryItem`. The `new_task` tool creates subtasks that push onto the stack. When a subtask completes, it pops and returns control to the parent.
|
|
|
|
## 3. Agreed Scope for Phase 6
|
|
|
|
**In scope (Items 1-3):**
|
|
1. Full conversation replay for completed background tasks
|
|
2. Tab switching / multi-task view
|
|
3. Real-time progress streaming for active background tasks
|
|
|
|
**Deferred to Phase 7 (Items 4-5):**
|
|
4. Write-capable background tasks + basic file locking -- see [`phase-7-controlled-write-parallelism.md`](phase-7-controlled-write-parallelism.md) (Phases 7a, 7b)
|
|
5. Persistent background task history across sessions -- see [`phase-7-controlled-write-parallelism.md`](phase-7-controlled-write-parallelism.md) (Phase 7c)
|
|
|
|
## 4. Feasibility Analysis
|
|
|
|
### Item 1: Full Conversation Replay
|
|
|
|
**Complexity: Medium | Risk: Low**
|
|
|
|
`readTaskMessages(taskId, globalStoragePath)` already loads the full `ClineMessage[]` array from disk for any task. The existing `ChatView` component renders these messages. The main work is creating a read-only wrapper that:
|
|
|
|
- Accepts a `taskId` prop instead of reading from global state
|
|
- Loads messages on mount via a new webview message
|
|
- Hides input controls (chat box, approval buttons)
|
|
- Renders tool calls, outputs, and assistant responses in the same format
|
|
|
|
**Why it's low risk:** No changes to task execution, persistence, or the foreground task flow. Purely additive UI + a new message handler.
|
|
|
|
### Item 2: Tab Switching / Multi-task View
|
|
|
|
**Complexity: Medium-High | Risk: Medium**
|
|
|
|
The webview already has a tab system in `App.tsx` (`tab === "history"`, `tab === "settings"`, `tab === "chat"`). Adding a background tasks view requires:
|
|
|
|
- A new tab or panel within the chat view
|
|
- A list of active/completed background tasks with status indicators
|
|
- Navigation to open a task's replay view or live view
|
|
- State management to track which background task is currently being viewed
|
|
|
|
**Key challenge:** The webview currently receives state for only one task. Viewing a background task must not disrupt the foreground task's state. This requires either:
|
|
- (a) A separate message channel for background task data, or
|
|
- (b) A secondary state context in the webview that can hold background task data alongside the primary task state
|
|
|
|
Option (a) is cleaner and avoids polluting the existing state management.
|
|
|
|
### Item 3: Real-time Progress Streaming
|
|
|
|
**Complexity: High | Risk: Medium-High**
|
|
|
|
Currently, `Task.ts` calls `provider.postStateToWebviewWithoutTaskHistory()` to update the UI. This method sends the full state for the current task only. For background tasks to stream progress:
|
|
|
|
1. `Task.ts` must emit incremental updates even when it is not the "current" task
|
|
2. A new message type (`backgroundTaskProgress`) must carry task-scoped updates
|
|
3. The webview must handle concurrent update streams without degrading performance
|
|
4. Throttling/batching is needed to prevent excessive re-renders
|
|
|
|
**Why it's harder:** Requires changes to the core task execution loop (`Task.ts`), not just additive UI. The task currently assumes it IS the visible task when posting updates.
|
|
|
|
## 5. Recommended Priority Order
|
|
|
|
```
|
|
Phase 6a: Conversation Replay (Foundation -- standalone value)
|
|
│
|
|
▼
|
|
Phase 6b: Tab/Panel Switching (Navigation framework, depends on 6a)
|
|
│
|
|
▼
|
|
Phase 6c: Real-time Progress Streaming (Highest complexity, builds on 6b)
|
|
```
|
|
|
|
Each sub-phase is independently shippable and testable.
|
|
|
|
## 6. Detailed Design
|
|
|
|
### 6a. Conversation Replay
|
|
|
|
#### New Message Types
|
|
|
|
```typescript
|
|
// Webview → Extension
|
|
interface RequestBackgroundTaskMessages {
|
|
type: "requestBackgroundTaskMessages"
|
|
taskId: string
|
|
}
|
|
|
|
// Extension → Webview
|
|
interface BackgroundTaskMessages {
|
|
type: "backgroundTaskMessages"
|
|
taskId: string
|
|
messages: ClineMessage[]
|
|
}
|
|
```
|
|
|
|
#### Extension Handler (webviewMessageHandler.ts)
|
|
|
|
```typescript
|
|
case "requestBackgroundTaskMessages": {
|
|
const taskId = message.taskId
|
|
const globalStoragePath = provider.contextProxy.globalStorageUri.fsPath
|
|
const messages = await readTaskMessages(taskId, globalStoragePath)
|
|
provider.postMessageToWebview({
|
|
type: "backgroundTaskMessages",
|
|
taskId,
|
|
messages: messages ?? [],
|
|
})
|
|
break
|
|
}
|
|
```
|
|
|
|
#### Webview Component
|
|
|
|
```
|
|
BackgroundTaskReplayView
|
|
├── Props: { taskId: string, onClose: () => void }
|
|
├── State: messages (ClineMessage[]), loading (boolean)
|
|
├── On mount: sends requestBackgroundTaskMessages
|
|
├── On message: receives backgroundTaskMessages, filters by taskId
|
|
├── Renders: read-only message list (reuses ChatRow components)
|
|
└── No input controls, no approval buttons
|
|
```
|
|
|
|
### 6b. Tab/Panel Switching
|
|
|
|
#### UI Structure
|
|
|
|
A new icon is added to the existing tab bar (alongside chat, history, settings) as the entry point. The background task view occupies the full tab area.
|
|
|
|
```
|
|
App.tsx
|
|
├── tab === "chat" → ChatView (foreground task)
|
|
├── tab === "history" → HistoryView
|
|
├── tab === "settings" → SettingsView
|
|
└── tab === "bgTask" → BackgroundTaskView
|
|
├── BackgroundTasksList (task list with status badges + error badge on tab icon)
|
|
│ ├── Active tasks
|
|
│ └── Completed tasks
|
|
└── BackgroundTaskReplayView (from 6a) OR BackgroundTaskLiveView (from 6c)
|
|
```
|
|
|
|
#### State Management
|
|
|
|
```typescript
|
|
// New webview state (in App.tsx or dedicated context)
|
|
interface BackgroundTaskViewState {
|
|
selectedTaskId: string | null
|
|
viewMode: "replay" | "live"
|
|
}
|
|
```
|
|
|
|
#### Navigation Flow
|
|
|
|
1. User clicks background tasks icon in the tab bar
|
|
2. App switches to `tab === "bgTask"`
|
|
3. BackgroundTasksList shows available tasks
|
|
4. User clicks a task → sets `selectedTaskId`
|
|
5. If task is completed → opens BackgroundTaskReplayView
|
|
6. If task is active → opens BackgroundTaskLiveView (Phase 6c)
|
|
|
|
### 6c. Real-time Progress Streaming (Minimal Viable Version)
|
|
|
|
> **Design principle:** Keep Phase 6c tightly scoped to avoid expanding the phase. Ship the simplest useful version first; richer detail can be added incrementally in later phases.
|
|
|
|
#### MVP Scope
|
|
|
|
The minimal viable version streams only:
|
|
- **Tool name + status** (started / completed / errored) -- not full parameters or output
|
|
- **Last N updates** (rolling window of ~20 items) -- older entries are discarded client-side
|
|
- **Status changes** (running, paused, completed, errored)
|
|
|
|
What is explicitly **out of scope** for the MVP:
|
|
- Full tool call parameters or output payloads
|
|
- Assistant text streaming
|
|
- Persistent storage of streamed updates (replay from disk covers completed tasks)
|
|
|
|
#### New Message Types
|
|
|
|
```typescript
|
|
// Extension → Webview (incremental updates)
|
|
interface BackgroundTaskProgress {
|
|
type: "backgroundTaskProgress"
|
|
taskId: string
|
|
update: BackgroundTaskUpdate
|
|
}
|
|
|
|
interface BackgroundTaskUpdate {
|
|
kind: "tool_call" | "tool_result" | "status_change" | "error"
|
|
timestamp: number
|
|
toolName?: string // e.g. "read_file", "execute_command"
|
|
status?: string // e.g. "started", "completed", "errored"
|
|
errorMessage?: string // Only for kind === "error"
|
|
}
|
|
```
|
|
|
|
Note: `assistant_text` is excluded from the MVP. The update interface uses typed optional fields instead of `data: any` to keep the contract narrow and safe.
|
|
|
|
#### Task.ts Changes
|
|
|
|
Add a method that emits progress regardless of whether the task is "current":
|
|
|
|
```typescript
|
|
// In Task.ts
|
|
private emitBackgroundProgress(update: BackgroundTaskUpdate) {
|
|
const provider = this.providerRef.deref()
|
|
if (!provider) return
|
|
|
|
// Only emit background updates when this task is NOT the current task
|
|
if (provider.getCurrentTask()?.taskId === this.taskId) return
|
|
|
|
provider.postMessageToWebview({
|
|
type: "backgroundTaskProgress",
|
|
taskId: this.taskId,
|
|
update,
|
|
})
|
|
}
|
|
```
|
|
|
|
The hook points in Task.ts should be minimal -- emit at tool call start and tool call end only. Avoid adding hooks inside the LLM streaming loop for the MVP.
|
|
|
|
#### Throttling Strategy
|
|
|
|
- Batch updates in 500ms windows (conservative default; can be tuned down later)
|
|
- Cap at 5 updates per batch per task
|
|
- Drop older updates if buffer exceeds threshold (keep last N = 20)
|
|
- Priority ordering: status_change > error > tool_result > tool_call
|
|
|
|
#### Webview: BackgroundTaskLiveView
|
|
|
|
```
|
|
BackgroundTaskLiveView
|
|
├── Props: { taskId: string }
|
|
├── State: updates (BackgroundTaskUpdate[], capped at last 20), status
|
|
├── Subscribes to backgroundTaskProgress messages filtered by taskId
|
|
├── Renders: compact list of recent tool calls with status icons
|
|
├── Auto-scrolls to latest update
|
|
└── Shows task status badge (running, paused, completed, errored)
|
|
```
|
|
|
|
The live view intentionally shows a compact summary, not a full chat transcript. Users who want full detail can wait for the task to complete and use the replay view (6a).
|
|
|
|
> **Confirmed:** Streaming is scoped to the currently selected background task only. The extension should not emit `backgroundTaskProgress` messages for tasks the user is not viewing. This keeps message traffic low and the implementation simple.
|
|
|
|
## 7. Testing Strategy
|
|
|
|
| Area | Test Type | Key Scenarios |
|
|
|------|-----------|---------------|
|
|
| Message handler | Unit (vitest) | Request/response for task messages, missing task, corrupt data |
|
|
| BackgroundTaskReplayView | Component (vitest + RTL) | Loading state, message rendering, empty state |
|
|
| Tab switching | Component (vitest + RTL) | Tab navigation, state preservation, back to foreground |
|
|
| Progress streaming | Unit (vitest) | Throttling, batching, concurrent tasks |
|
|
| Integration | E2E (if feasible) | Full flow: start bg task → view progress → replay after completion |
|
|
|
|
## 8. Confirmed Decisions
|
|
|
|
The following decisions were confirmed during design review and should guide implementation.
|
|
|
|
### UI Layout
|
|
|
|
1. **Background task view layout: Full tab** (`tab === "bgTask"`)
|
|
|
|
Start with a full tab for simplicity in Phase 6. A sidebar/hybrid mode may be considered later based on user feedback.
|
|
|
|
2. **Entry point placement: New tab bar icon**
|
|
|
|
Add a new icon in the existing tab bar (alongside chat, history, settings). This is the most discoverable location without cluttering the chat view.
|
|
|
|
3. **Replay view implementation: Thin wrapper around ChatRow components**
|
|
|
|
Create a dedicated `BackgroundTaskReplayView` that wraps `ChatRow` components directly rather than reusing the full `ChatView`. This avoids inheriting input controls, scroll management, and approval button logic that don't apply to read-only replay.
|
|
|
|
### Progress Streaming (6c)
|
|
|
|
4. **Streaming granularity: Minimal level**
|
|
|
|
Stream tool name + status only (started/completed/errored). This provides enough signal to know what the background task is doing without performance risk. Truncated arguments (medium level) can be added in a follow-up if users need more context.
|
|
|
|
5. **Streaming scope: Currently selected task only**
|
|
|
|
Only stream updates for the background task the user is currently viewing. This avoids unnecessary message traffic and keeps the implementation simple.
|
|
|
|
6. **Error surfacing: Badge on the background tasks tab icon**
|
|
|
|
Display a badge on the tab icon when a background task encounters an error. Toast notifications can be added later if users miss errors.
|