Skip to content

Conversation

@roomote
Copy link
Contributor

@roomote roomote bot commented Dec 3, 2025

Summary

This PR implements conversation forking functionality as requested in #9790. Users can now fork their current conversation at any point, creating a new independent task with its own workspace copy.

What's Changed

Core Implementation

  • Added fork_conversation tool to enable forking conversations at any point
  • Created ForkConversationTool class to handle fork operations
  • Implemented forkConversation method in ClineProvider for workspace copying
  • Added fork metadata fields to HistoryItem for tracking relationships
  • Added TaskForked event for fork tracking

Technical Details

  • Workspace files are copied using rsync (with cp fallback) to a new directory
  • Common ignore patterns (node_modules, .git, etc.) are excluded from copying
  • Fork relationships are tracked via metadata fields in history items
  • The forked task is completely independent - changes don't affect the original

How It Works

Users can fork their conversation using the fork_conversation tool with optional parameters:

  • message_index: The index of the message to fork from (defaults to current point)
  • target_directory: Where to create the forked workspace (defaults to timestamped directory)

Testing

  • All existing tests pass
  • Test snapshots updated to include new tool

Next Steps

  • Add UI components for visualizing fork relationships (fork icon 🔀 in task list)
  • Create unit tests for fork functionality
  • Add integration tests for the complete fork workflow

Addresses #9790

Feedback Welcome

This is a draft PR for initial review. Looking forward to feedback on the implementation approach and any suggestions for improvements.

- Add fork_conversation tool to allow forking conversations at any point
- Create independent task with copied workspace files
- Add fork metadata fields to HistoryItem for tracking relationships
- Implement workspace copying logic with common ignore patterns
- Add TaskForked event for tracking fork operations

This allows users to explore 'what if' scenarios without contaminating
the main conversation context, addressing issue #9790
- Add fork_conversation tool to enable forking conversations at any point
- Create ForkConversationTool class to handle fork operations
- Implement forkConversation method in ClineProvider for workspace copying
- Add fork metadata fields to HistoryItem for tracking relationships
- Update tool configurations and type definitions
- Add TaskForked event for fork tracking
- Update test snapshots to include new tool

This feature allows users to fork their current conversation at any point,
creating a new task with its own workspace copy. This enables exploration
of alternative approaches without affecting the original task.

Addresses #9790
@roomote
Copy link
Contributor Author

roomote bot commented Dec 3, 2025

Rooviewer Clock   See task on Roo Cloud

Review completed. Found 2 issues that need attention:

  • Workspace path mutation without restoration (line 3401)
  • Insufficient error handling in workspace copy operation (lines 3446-3450)

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

await this.updateTaskHistory(forkedHistoryItem)

// 7) Switch to the forked workspace
this.currentWorkspacePath = targetDirectory
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workspace path is permanently changed here without any restoration mechanism. If the fork operation fails after this point (e.g., during task creation at line 3404), or even if it succeeds, the provider's workspace path remains pointing to the forked directory instead of the original. This breaks the invariant that the provider's cwd should match the actual VSCode workspace.

Consider either: (1) not changing currentWorkspacePath at all since the forked task has its own workspace path in its history item, or (2) wrapping this in a try-finally block to restore the original path, or (3) only changing it temporarily within the task creation scope.

Fix it with Roo Code or mention @roomote and request a fix.

Comment on lines +3446 to +3450
try {
// Try rsync first (more efficient)
await execAsync(`rsync -av ${excludeArgs} "${source}/" "${target}/"`)
this.log(`[copyWorkspaceFiles] Successfully copied workspace using rsync`)
} catch (rsyncError) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The shell command execution lacks proper error handling for common failure scenarios. The rsync command could fail due to: (1) insufficient disk space in the target directory, (2) permission denied errors when copying certain files, (3) the source directory being on a network mount that becomes unavailable, or (4) hitting filesystem limits (inode exhaustion, path length limits on Windows).

The current implementation only catches the error and re-throws it with a generic message. Consider adding specific error handling for these cases and providing actionable error messages to the user (e.g., "Insufficient disk space", "Permission denied for file X"). Also consider checking available disk space before attempting the copy.

Fix it with Roo Code or mention @roomote and request a fix.

@hannesrudolph hannesrudolph added the Issue/PR - Triage New issue. Needs quick review to confirm validity and assign labels. label Dec 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Issue/PR - Triage New issue. Needs quick review to confirm validity and assign labels.

Projects

Status: Triage

Development

Successfully merging this pull request may close these issues.

3 participants