Skip to content
Open
15 changes: 14 additions & 1 deletion src/core/webview/ClineProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ import { MdmService } from "../../services/mdm/MdmService"

import { fileExistsAtPath } from "../../utils/fs"
import { setTtsEnabled, setTtsSpeed } from "../../utils/tts"
import { getWorkspaceGitInfo } from "../../utils/git"
import { getWorkspaceGitInfo, isGitHubRepository } from "../../utils/git"
import { getWorkspacePath } from "../../utils/path"
import { OrganizationAllowListViolationError } from "../../utils/errors"

Expand Down Expand Up @@ -1886,6 +1886,15 @@ export class ClineProvider
const currentMode = mode ?? defaultModeSlug
const hasSystemPromptOverride = await this.hasFileBasedSystemPromptOverride(currentMode)

// Check if the current workspace is a git repository
const gitInfo = await getWorkspaceGitInfo()
// A repository is valid if we found ANY git info (not just a remote URL)
// This includes defaultBranch, which is populated even for worktrees.
const isGitRepository = Object.keys(gitInfo).length > 0

// Check if the repository is specifically a GitHub repository
const isGithubRepository = isGitHubRepository(gitInfo.repositoryUrl)

return {
version: this.context.extension?.packageJSON?.version ?? "",
apiConfiguration,
Expand Down Expand Up @@ -2016,6 +2025,8 @@ export class ClineProvider
openRouterImageGenerationSelectedModel,
openRouterUseMiddleOutTransform,
featureRoomoteControlEnabled,
isGitRepository,
isGithubRepository,
}
}

Expand Down Expand Up @@ -2250,6 +2261,8 @@ export class ClineProvider
return false
}
})(),
isGitRepository: false, // Will be computed in getStateToPostToWebview
isGithubRepository: false, // Will be computed in getStateToPostToWebview
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/core/webview/__tests__/ClineProvider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,8 @@ describe("ClineProvider", () => {
taskSyncEnabled: false,
featureRoomoteControlEnabled: false,
checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS,
isGitRepository: false,
isGithubRepository: false,
}

const message: ExtensionMessage = {
Expand Down
2 changes: 2 additions & 0 deletions src/shared/ExtensionMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,8 @@ export type ExtensionState = Pick<
remoteControlEnabled: boolean
taskSyncEnabled: boolean
featureRoomoteControlEnabled: boolean
isGitRepository: boolean
isGithubRepository: boolean
}

export interface ClineSayTool {
Expand Down
13 changes: 13 additions & 0 deletions src/shared/__tests__/support-prompts.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,19 @@ describe("Code Action Prompts", () => {
})
})

describe("CREATE_PR prompt", () => {
it("should return default template when no custom prompts provided", () => {
const template = supportPrompt.get(undefined, "CREATE_PR")
expect(template).toBe(supportPrompt.default.CREATE_PR)
})

it("should create CREATE_PR prompt containing key instructions", () => {
const prompt = supportPrompt.create("CREATE_PR", {}, undefined)
expect(prompt).toContain("Stage and commit")
expect(prompt).toContain("gh pr create")
})
})

describe("create with custom prompts", () => {
it("should use custom template when provided", () => {
const customTemplate = "Custom template for ${filePath}"
Expand Down
55 changes: 55 additions & 0 deletions src/shared/support-prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type SupportPromptType =
| "TERMINAL_FIX"
| "TERMINAL_EXPLAIN"
| "NEW_TASK"
| "CREATE_PR"

const supportPromptConfigs: Record<SupportPromptType, SupportPromptConfig> = {
ENHANCE: {
Expand Down Expand Up @@ -174,6 +175,60 @@ Please provide:
NEW_TASK: {
template: `\${userInput}`,
},
CREATE_PR: {
template: `<task>
Stage and commit any outstanding changes, then review the changes made in this branch versus main/master and create a pull request using the gh CLI.
</task>

<instructions>
1. Check if there are any unstaged/uncommitted changes:
- Run: git status
- If changes exist, stage and commit them with a descriptive message

2. Identify the base branch (main or master):
- Check which exists: git branch --list main master
- Use the one that exists as base branch

3. Get current branch name:
- Run: git branch --show-current

4. Analyze all changes between current branch and base:
- Run: git diff <base-branch>...HEAD
- Also get commit messages: git log <base-branch>..HEAD --oneline

5. Generate PR title and description:
- Analyze the diff and commit messages
- Create concise, descriptive title (50 chars max)
- Write clear PR description explaining:
* What changed and why
* Key implementation details
* Any breaking changes or important notes

6. Get repository info:
- Extract from: git remote get-url origin
- Parse to get org/repo format

7. Check if gh CLI is installed:
- Run: gh --version
- If not found, guide user to install:
* macOS: brew install gh
* Windows: winget install GitHub.cli
* Linux: See https://github.com/cli/cli#installation
* After install: gh auth login

8. Create the pull request:
- Run: gh pr create --repo <org/repo> --head <current-branch> --title "<generated-title>" --body "<generated-description>"

9. After successful PR creation:
- Extract PR URL from gh output
- Present success message with:
* Link to the created PR
* Offer to have it reviewed by Roo Code Cloud's PR Reviewer agent
* Link: https://roocode.com/reviewer

If gh CLI is not installed or authenticated, provide clear setup instructions and wait for user to complete setup before proceeding.
</instructions>`,
},
} as const

export const supportPrompt = {
Expand Down
Loading