diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 7aa370f7d2a2..f97ca2577b78 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -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" @@ -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, @@ -2016,6 +2025,8 @@ export class ClineProvider openRouterImageGenerationSelectedModel, openRouterUseMiddleOutTransform, featureRoomoteControlEnabled, + isGitRepository, + isGithubRepository, } } @@ -2250,6 +2261,8 @@ export class ClineProvider return false } })(), + isGitRepository: false, // Will be computed in getStateToPostToWebview + isGithubRepository: false, // Will be computed in getStateToPostToWebview } } diff --git a/src/core/webview/__tests__/ClineProvider.spec.ts b/src/core/webview/__tests__/ClineProvider.spec.ts index a8ab39108d95..b7293da02f41 100644 --- a/src/core/webview/__tests__/ClineProvider.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.spec.ts @@ -562,6 +562,8 @@ describe("ClineProvider", () => { taskSyncEnabled: false, featureRoomoteControlEnabled: false, checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, + isGitRepository: false, + isGithubRepository: false, } const message: ExtensionMessage = { diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index 7d2759c91905..336c5c899751 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -362,6 +362,8 @@ export type ExtensionState = Pick< remoteControlEnabled: boolean taskSyncEnabled: boolean featureRoomoteControlEnabled: boolean + isGitRepository: boolean + isGithubRepository: boolean } export interface ClineSayTool { diff --git a/src/shared/__tests__/support-prompts.spec.ts b/src/shared/__tests__/support-prompts.spec.ts index ea6a193d5a20..e74459c5114e 100644 --- a/src/shared/__tests__/support-prompts.spec.ts +++ b/src/shared/__tests__/support-prompts.spec.ts @@ -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}" diff --git a/src/shared/support-prompt.ts b/src/shared/support-prompt.ts index 51f4310fc2e3..b17b9b6ac6db 100644 --- a/src/shared/support-prompt.ts +++ b/src/shared/support-prompt.ts @@ -44,6 +44,7 @@ type SupportPromptType = | "TERMINAL_FIX" | "TERMINAL_EXPLAIN" | "NEW_TASK" + | "CREATE_PR" const supportPromptConfigs: Record = { ENHANCE: { @@ -174,6 +175,61 @@ Please provide: NEW_TASK: { template: `\${userInput}`, }, + CREATE_PR: { + template: ` +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. + + + +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 ...HEAD + - Also get commit messages: git log ..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, use ask_followup_question tool to ask the user if they want to install gh CLI + - If the user agrees, follow one of the installation methods depending on their OS: + * 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 --head --title "" --body "" + +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, use ask_followup_question tool to confirm with the user before proceeding with installation instructions. +`, + }, } as const export const supportPrompt = { diff --git a/src/utils/__tests__/git.spec.ts b/src/utils/__tests__/git.spec.ts index 16b404f9e067..2f702ee96d39 100644 --- a/src/utils/__tests__/git.spec.ts +++ b/src/utils/__tests__/git.spec.ts @@ -12,6 +12,7 @@ import { extractRepositoryName, getWorkspaceGitInfo, convertGitUrlToHttps, + isGitHubRepository, } from "../git" import { truncateOutput } from "../../integrations/misc/extract-text" @@ -33,6 +34,7 @@ vitest.mock("fs", () => ({ promises: { access: vitest.fn(), readFile: vitest.fn(), + stat: vitest.fn(), }, })) @@ -470,6 +472,12 @@ describe("getGitRepositoryInfo", () => { // Mock successful access to .git directory vitest.mocked(fs.promises.access).mockResolvedValue(undefined) + // Mock stat to indicate .git is a directory (not a worktree file) + vitest.mocked(fs.promises.stat).mockResolvedValue({ + isFile: () => false, + isDirectory: () => true, + } as any) + // Mock git config file content const mockConfig = ` [core] @@ -524,6 +532,12 @@ describe("getGitRepositoryInfo", () => { // Mock successful access to .git directory vitest.mocked(fs.promises.access).mockResolvedValue(undefined) + // Mock stat to indicate .git is a directory (not a worktree file) + vitest.mocked(fs.promises.stat).mockResolvedValue({ + isFile: () => false, + isDirectory: () => true, + } as any) + // Mock git config file without URL const mockConfig = ` [core] @@ -561,6 +575,12 @@ describe("getGitRepositoryInfo", () => { // Mock successful access to .git directory vitest.mocked(fs.promises.access).mockResolvedValue(undefined) + // Mock stat to indicate .git is a directory (not a worktree file) + vitest.mocked(fs.promises.stat).mockResolvedValue({ + isFile: () => false, + isDirectory: () => true, + } as any) + // Setup the readFile mock to return different values based on the path gitSpy.mockImplementation((path: any, encoding: any) => { if (path === configPath) { @@ -588,6 +608,12 @@ describe("getGitRepositoryInfo", () => { // Mock successful access to .git directory vitest.mocked(fs.promises.access).mockResolvedValue(undefined) + // Mock stat to indicate .git is a directory (not a worktree file) + vitest.mocked(fs.promises.stat).mockResolvedValue({ + isFile: () => false, + isDirectory: () => true, + } as any) + // Setup the readFile mock to return different values based on the path gitSpy.mockImplementation((path: any, encoding: any) => { if (path === configPath) { @@ -619,6 +645,12 @@ describe("getGitRepositoryInfo", () => { // Mock successful access to .git directory vitest.mocked(fs.promises.access).mockResolvedValue(undefined) + // Mock stat to indicate .git is a directory (not a worktree file) + vitest.mocked(fs.promises.stat).mockResolvedValue({ + isFile: () => false, + isDirectory: () => true, + } as any) + // Mock git config file with SSH URL const mockConfig = ` [core] @@ -654,6 +686,99 @@ describe("getGitRepositoryInfo", () => { defaultBranch: "main", }) }) + + it("should handle git worktrees where .git is a file", async () => { + // Clear previous mocks + vitest.clearAllMocks() + + // Create a spy to track the implementation + const accessSpy = vitest.spyOn(fs.promises, "access") + const statSpy = vitest.spyOn(fs.promises, "stat") + const readFileSpy = vitest.spyOn(fs.promises, "readFile") + + // Mock successful access to .git file (not directory) + accessSpy.mockResolvedValue(undefined) + + // Mock stat to indicate .git is a file (worktree) + statSpy.mockResolvedValue({ + isFile: () => true, + isDirectory: () => false, + } as any) + + // Mock .git file content (worktree reference) + const gitFileContent = "gitdir: /path/to/main/repo/.git/worktrees/my-worktree" + + // Mock git config file content from the actual git directory + const mockConfig = ` +[core] + repositoryformatversion = 0 + filemode = true + bare = false +[remote "origin"] + url = https://github.com/RooCodeInc/Roo-Code.git + fetch = +refs/heads/*:refs/remotes/origin/* +[branch "main"] + remote = origin + merge = refs/heads/main +` + // Mock HEAD file content + const mockHead = "ref: refs/heads/feature-branch" + + // Setup the readFile mock to return different values based on the path + readFileSpy.mockImplementation((filePath: any, encoding: any) => { + const pathStr = String(filePath) + if (pathStr.endsWith(".git")) { + // Reading the .git file itself + return Promise.resolve(gitFileContent) + } else if (pathStr.includes("config")) { + return Promise.resolve(mockConfig) + } else if (pathStr.includes("HEAD")) { + return Promise.resolve(mockHead) + } + return Promise.reject(new Error(`Unexpected path: ${pathStr}`)) + }) + + const result = await getGitRepositoryInfo(workspaceRoot) + + // Verify that the worktree was handled correctly + expect(result).toEqual({ + repositoryUrl: "https://github.com/RooCodeInc/Roo-Code.git", + repositoryName: "RooCodeInc/Roo-Code", + defaultBranch: "main", + }) + + // Verify the .git file was read + expect(statSpy).toHaveBeenCalledWith(gitDir) + expect(readFileSpy).toHaveBeenCalledWith(gitDir, "utf8") + }) + + it("should return empty object if .git file has invalid format", async () => { + // Clear previous mocks + vitest.clearAllMocks() + + // Create a spy to track the implementation + const accessSpy = vitest.spyOn(fs.promises, "access") + const statSpy = vitest.spyOn(fs.promises, "stat") + const readFileSpy = vitest.spyOn(fs.promises, "readFile") + + // Mock successful access to .git file + accessSpy.mockResolvedValue(undefined) + + // Mock stat to indicate .git is a file (worktree) + statSpy.mockResolvedValue({ + isFile: () => true, + isDirectory: () => false, + } as any) + + // Mock invalid .git file content + const gitFileContent = "invalid content without gitdir" + + readFileSpy.mockResolvedValue(gitFileContent) + + const result = await getGitRepositoryInfo(workspaceRoot) + + expect(result).toEqual({}) + }) }) describe("convertGitUrlToHttps", () => { @@ -774,6 +899,60 @@ describe("extractRepositoryName", () => { }) }) +describe("isGitHubRepository", () => { + it("should return true for github.com HTTPS URLs", () => { + expect(isGitHubRepository("https://github.com/user/repo.git")).toBe(true) + expect(isGitHubRepository("https://github.com/user/repo")).toBe(true) + }) + + it("should return true for github.com SSH URLs", () => { + expect(isGitHubRepository("git@github.com:user/repo.git")).toBe(true) + expect(isGitHubRepository("ssh://git@github.com/user/repo.git")).toBe(true) + }) + + it("should return true for GitHub URLs with different casing", () => { + expect(isGitHubRepository("https://GitHub.com/user/repo.git")).toBe(true) + expect(isGitHubRepository("https://GITHUB.COM/user/repo.git")).toBe(true) + }) + + it("should return true for GitHub subdomains", () => { + expect(isGitHubRepository("https://gist.github.com/user/repo")).toBe(true) + expect(isGitHubRepository("https://api.github.com/repos/user/repo")).toBe(true) + expect(isGitHubRepository("git@gist.github.com:user/repo.git")).toBe(true) + }) + + it("should return false for non-GitHub URLs", () => { + expect(isGitHubRepository("https://gitlab.com/user/repo.git")).toBe(false) + expect(isGitHubRepository("https://bitbucket.org/user/repo.git")).toBe(false) + expect(isGitHubRepository("git@gitlab.com:user/repo.git")).toBe(false) + }) + + it("should return false for malicious URLs with github.com in hostname", () => { + // Security: These URLs have "github.com" as part of the hostname but are not GitHub + expect(isGitHubRepository("https://malicious-github.com/user/repo.git")).toBe(false) + expect(isGitHubRepository("https://github.com.evil.com/user/repo.git")).toBe(false) + expect(isGitHubRepository("https://fake-github.com/user/repo.git")).toBe(false) + expect(isGitHubRepository("git@malicious-github.com:user/repo.git")).toBe(false) + expect(isGitHubRepository("ssh://git@github.com.evil.com/user/repo.git")).toBe(false) + }) + + it("should return false for URLs with github.com in the path", () => { + // Security: These URLs have "github.com" in the path but not as the hostname + expect(isGitHubRepository("https://evil.com/github.com/malicious/repo.git")).toBe(false) + expect(isGitHubRepository("https://attacker.com/fake/github.com/path")).toBe(false) + expect(isGitHubRepository("git@evil.com:github.com/user/repo.git")).toBe(false) + }) + + it("should return false for undefined or empty URLs", () => { + expect(isGitHubRepository(undefined)).toBe(false) + expect(isGitHubRepository("")).toBe(false) + }) + + it("should handle sanitized GitHub URLs", () => { + expect(isGitHubRepository("https://github.com/user/repo")).toBe(true) + }) +}) + describe("getWorkspaceGitInfo", () => { const workspaceRoot = "/test/workspace" @@ -804,6 +983,12 @@ describe("getWorkspaceGitInfo", () => { // Mock successful access to .git directory gitSpy.mockResolvedValue(undefined) + // Mock stat to indicate .git is a directory (not a worktree file) + vitest.mocked(fs.promises.stat).mockResolvedValue({ + isFile: () => false, + isDirectory: () => true, + } as any) + // Mock git config file content const mockConfig = ` [remote "origin"] diff --git a/src/utils/git.ts b/src/utils/git.ts index 3bb562bf43f9..f0c3dd4e5864 100644 --- a/src/utils/git.ts +++ b/src/utils/git.ts @@ -29,9 +29,9 @@ export interface GitCommit { */ export async function getGitRepositoryInfo(workspaceRoot: string): Promise { try { - const gitDir = path.join(workspaceRoot, ".git") + let gitDir = path.join(workspaceRoot, ".git") - // Check if .git directory exists + // Check if .git exists (could be a directory or file) try { await fs.access(gitDir) } catch { @@ -39,6 +39,31 @@ export async function getGitRepositoryInfo(workspaceRoot: string): Promise(null) const userRespondedRef = useRef(false) const [currentFollowUpTs, setCurrentFollowUpTs] = useState(null) + const [prCreationRequested, setPrCreationRequested] = useState(false) const clineAskRef = useRef(clineAsk) useEffect(() => { @@ -403,8 +408,16 @@ const ChatViewComponent: React.ForwardRefRenderFunction 0) { + // Reset PR creation flag when user sends any message + // This allows creating another PR if more changes are made + setPrCreationRequested(false) + // Queue message if: // - Task is busy (sendingDisabled) // - API request in progress (isStreaming) @@ -723,8 +741,17 @@ const ChatViewComponent: React.ForwardRefRenderFunction { cloudIsAuthenticated: false, sharingEnabled: false, profileThresholds: {}, - hasOpenedModeSelector: false, // Add the new required property + hasOpenedModeSelector: false, maxImageFileSize: 5, maxTotalImageSize: 20, remoteControlEnabled: false, taskSyncEnabled: false, featureRoomoteControlEnabled: false, - checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, // Add the checkpoint timeout property + checkpointTimeout: DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, + isGitRepository: false, + isGithubRepository: false, } const prevState: ExtensionState = { diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index 16ea62c44390..debc459a417c 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -40,7 +40,7 @@ "tooltip": "Torna a provar l'operació" }, "startNewTask": { - "title": "Començar una nova tasca", + "title": "Tasca nova", "tooltip": "Comença una nova tasca" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "Aprovar", "tooltip": "Aprova aquesta acció" }, + "createPR": { + "title": "Crea PR", + "tooltip": "Crea una pull request a partir dels teus canvis" + }, "runCommand": { "title": "Ordre", "tooltip": "Executa aquesta ordre" diff --git a/webview-ui/src/i18n/locales/ca/prompts.json b/webview-ui/src/i18n/locales/ca/prompts.json index 66cd1c768848..b4ccb5099bc5 100644 --- a/webview-ui/src/i18n/locales/ca/prompts.json +++ b/webview-ui/src/i18n/locales/ca/prompts.json @@ -143,6 +143,10 @@ "NEW_TASK": { "label": "Iniciar nova tasca", "description": "Inicieu una nova tasca amb l'entrada proporcionada. Disponible a la paleta de comandes." + }, + "CREATE_PR": { + "label": "Crear Sol·licitud d'Extracció", + "description": "Genera instruccions per preparar, revisar i crear una sol·licitud d'extracció (PR) utilitzant el CLI de GitHub. Pots personalitzar aquesta plantilla." } } }, diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index a3f14d12549b..5c2ef18a751c 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -40,7 +40,7 @@ "tooltip": "Versuch erneut starten" }, "startNewTask": { - "title": "Neue Aufgabe starten", + "title": "Neue Aufgabe", "tooltip": "Beginne eine neue Aufgabe" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "Genehmigen", "tooltip": "Diese Aktion genehmigen" }, + "createPR": { + "title": "PR erstellen", + "tooltip": "Erstelle einen Pull Request aus deinen Änderungen" + }, "runCommand": { "title": "Befehl", "tooltip": "Diesen Befehl ausführen" diff --git a/webview-ui/src/i18n/locales/de/prompts.json b/webview-ui/src/i18n/locales/de/prompts.json index 9588ff665122..35869187f2dc 100644 --- a/webview-ui/src/i18n/locales/de/prompts.json +++ b/webview-ui/src/i18n/locales/de/prompts.json @@ -143,6 +143,10 @@ "NEW_TASK": { "label": "Neue Aufgabe starten", "description": "Starte eine neue Aufgabe mit deiner Eingabe. Verfügbar in der Befehlspalette." + }, + "CREATE_PR": { + "label": "Pull Request erstellen", + "description": "Erzeuge Anweisungen zum Stagen, Überprüfen und Erstellen eines PR mit dem GitHub CLI. Du kannst diese Vorlage anpassen." } } }, diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index 6f47f040c67b..5c50eaaf773d 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -35,8 +35,12 @@ "tooltip": "Try the operation again" }, "startNewTask": { - "title": "Start New Task", - "tooltip": "Begin a new task" + "title": "New Task", + "tooltip": "Start a new task" + }, + "createPR": { + "title": "Create PR", + "tooltip": "Create a pull request from your changes" }, "proceedAnyways": { "title": "Proceed Anyways", diff --git a/webview-ui/src/i18n/locales/en/prompts.json b/webview-ui/src/i18n/locales/en/prompts.json index 19837c6b2c33..eee9df734d37 100644 --- a/webview-ui/src/i18n/locales/en/prompts.json +++ b/webview-ui/src/i18n/locales/en/prompts.json @@ -142,6 +142,10 @@ "NEW_TASK": { "label": "Start New Task", "description": "Start a new task with user input. Available in the Command Palette." + }, + "CREATE_PR": { + "label": "Create Pull Request", + "description": "Generate instructions to stage, review, and create a PR using the GitHub CLI. You can customize this template." } } }, diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index e6084b371399..c9853d3116d2 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -35,7 +35,7 @@ "tooltip": "Intenta la operación de nuevo" }, "startNewTask": { - "title": "Iniciar nueva tarea", + "title": "Nueva tarea", "tooltip": "Comienza una nueva tarea" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "Aprobar", "tooltip": "Aprobar esta acción" }, + "createPR": { + "title": "Crear PR", + "tooltip": "Crear un pull request a partir de tus cambios" + }, "runCommand": { "title": "Comando", "tooltip": "Ejecutar este comando" diff --git a/webview-ui/src/i18n/locales/es/prompts.json b/webview-ui/src/i18n/locales/es/prompts.json index e800cee888c6..8227fb1d0dc5 100644 --- a/webview-ui/src/i18n/locales/es/prompts.json +++ b/webview-ui/src/i18n/locales/es/prompts.json @@ -143,6 +143,10 @@ "NEW_TASK": { "label": "Iniciar nueva tarea", "description": "Inicia una nueva tarea con entrada del usuario. Disponible en la Paleta de comandos." + }, + "CREATE_PR": { + "label": "Crear Pull Request", + "description": "Genera instrucciones para preparar, revisar y crear un PR usando el CLI de GitHub. Puedes personalizar esta plantilla." } } }, diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index 38d63358ca98..81749eff5b10 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -40,7 +40,7 @@ "tooltip": "Tenter à nouveau l'opération" }, "startNewTask": { - "title": "Commencer une nouvelle tâche", + "title": "Nouvelle tâche", "tooltip": "Démarrer une nouvelle tâche" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "Approuver", "tooltip": "Approuver cette action" }, + "createPR": { + "title": "Créer une PR", + "tooltip": "Créer une pull request à partir de vos modifications" + }, "runCommand": { "title": "Commande", "tooltip": "Exécuter cette commande" diff --git a/webview-ui/src/i18n/locales/fr/prompts.json b/webview-ui/src/i18n/locales/fr/prompts.json index 527109e136e9..335ec3f67880 100644 --- a/webview-ui/src/i18n/locales/fr/prompts.json +++ b/webview-ui/src/i18n/locales/fr/prompts.json @@ -143,6 +143,10 @@ "NEW_TASK": { "label": "Démarrer une nouvelle tâche", "description": "Démarre une nouvelle tâche avec ton entrée. Disponible dans la palette de commandes." + }, + "CREATE_PR": { + "label": "Créer une Pull Request", + "description": "Génère des instructions pour préparer, réviser et créer une PR en utilisant le CLI de GitHub. Vous pouvez personnaliser ce modèle." } } }, diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index 9bc4b4619766..5406f2980cea 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -40,7 +40,7 @@ "tooltip": "ऑपरेशन फिर से प्रयास करें" }, "startNewTask": { - "title": "नया कार्य शुरू करें", + "title": "नया कार्य", "tooltip": "नया कार्य शुरू करें" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "स्वीकृत करें", "tooltip": "इस क्रिया को स्वीकृत करें" }, + "createPR": { + "title": "पीआर बनाएं", + "tooltip": "अपने परिवर्तनों से एक पुल अनुरोध बनाएं" + }, "runCommand": { "title": "कमांड", "tooltip": "इस कमांड को निष्पादित करें" diff --git a/webview-ui/src/i18n/locales/hi/prompts.json b/webview-ui/src/i18n/locales/hi/prompts.json index d493aa3430c1..e569f8a1e935 100644 --- a/webview-ui/src/i18n/locales/hi/prompts.json +++ b/webview-ui/src/i18n/locales/hi/prompts.json @@ -143,6 +143,10 @@ "NEW_TASK": { "label": "नया कार्य शुरू करें", "description": "इनपुट के साथ नया कार्य शुरू करें। कमांड पैलेट में उपलब्ध है।" + }, + "CREATE_PR": { + "label": "पुल रिक्वेस्ट बनाएं", + "description": "गिटहब सीएलआई का उपयोग करके पीआर को स्टेज, समीक्षा और बनाने के लिए निर्देश उत्पन्न करें। आप इस टेम्पलेट को अनुकूलित कर सकते हैं।" } } }, diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index b61b47b3d884..7ff0d9593bf9 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -38,7 +38,7 @@ "tooltip": "Coba operasi lagi" }, "startNewTask": { - "title": "Mulai Tugas Baru", + "title": "Tugas Baru", "tooltip": "Mulai tugas baru" }, "reportBug": { @@ -66,6 +66,10 @@ "title": "Setujui", "tooltip": "Setujui aksi ini" }, + "createPR": { + "title": "Buat PR", + "tooltip": "Buat pull request dari perubahan Anda" + }, "read-batch": { "approve": { "title": "Setujui Semua" diff --git a/webview-ui/src/i18n/locales/id/prompts.json b/webview-ui/src/i18n/locales/id/prompts.json index 58bf91eb8b44..8c02a29e08b8 100644 --- a/webview-ui/src/i18n/locales/id/prompts.json +++ b/webview-ui/src/i18n/locales/id/prompts.json @@ -143,6 +143,10 @@ "NEW_TASK": { "label": "Mulai Tugas Baru", "description": "Mulai tugas baru dengan input pengguna. Tersedia di Command Palette." + }, + "CREATE_PR": { + "label": "Buat Pull Request", + "description": "Hasilkan instruksi untuk menyiapkan, meninjau, dan membuat PR menggunakan GitHub CLI. Anda dapat menyesuaikan template ini." } } }, diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index 082c489e9313..e09d8945b56d 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -40,7 +40,7 @@ "tooltip": "Prova di nuovo l'operazione" }, "startNewTask": { - "title": "Inizia nuova attività", + "title": "Nuova attività", "tooltip": "Inizia una nuova attività" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "Approva", "tooltip": "Approva questa azione" }, + "createPR": { + "title": "Crea PR", + "tooltip": "Crea una pull request dalle tue modifiche" + }, "runCommand": { "title": "Comando", "tooltip": "Esegui questo comando" diff --git a/webview-ui/src/i18n/locales/it/prompts.json b/webview-ui/src/i18n/locales/it/prompts.json index 2a0503ef71ff..faeb1cc99eeb 100644 --- a/webview-ui/src/i18n/locales/it/prompts.json +++ b/webview-ui/src/i18n/locales/it/prompts.json @@ -143,6 +143,10 @@ "NEW_TASK": { "label": "Avvia nuova attività", "description": "Avvia una nuova attività con il tuo input. Disponibile nella palette dei comandi." + }, + "CREATE_PR": { + "label": "Crea Pull Request", + "description": "Genera istruzioni per preparare, revisionare e creare una PR utilizzando la CLI di GitHub. Puoi personalizzare questo template." } } }, diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index 531afc067e4d..535ad09bb98f 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -40,7 +40,7 @@ "tooltip": "操作を再試行" }, "startNewTask": { - "title": "新しいタスクを開始", + "title": "新規タスク", "tooltip": "新しいタスクを開始" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "承認", "tooltip": "このアクションを承認" }, + "createPR": { + "title": "PRを作成", + "tooltip": "変更からプルリクエストを作成します" + }, "runCommand": { "title": "コマンド", "tooltip": "このコマンドを実行" diff --git a/webview-ui/src/i18n/locales/ja/prompts.json b/webview-ui/src/i18n/locales/ja/prompts.json index 2aba5bff7764..308d2b7ea097 100644 --- a/webview-ui/src/i18n/locales/ja/prompts.json +++ b/webview-ui/src/i18n/locales/ja/prompts.json @@ -143,6 +143,10 @@ "NEW_TASK": { "label": "新しいタスクを開始", "description": "入力内容で新しいタスクを開始できます。コマンドパレットから利用できます。" + }, + "CREATE_PR": { + "label": "プルリクエストの作成", + "description": "GitHub CLI を使用して、PR のステージング、レビュー、作成の手順を生成します。このテンプレートはカスタマイズできます。" } } }, diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index 9f7818bc4757..a2163c6de882 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -40,7 +40,7 @@ "tooltip": "작업 다시 시도" }, "startNewTask": { - "title": "새 작업 시작", + "title": "새 작업", "tooltip": "새 작업 시작하기" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "승인", "tooltip": "이 작업 승인" }, + "createPR": { + "title": "PR 생성", + "tooltip": "변경 사항으로 풀 리퀘스트를 생성합니다" + }, "runCommand": { "title": "명령", "tooltip": "이 명령 실행" diff --git a/webview-ui/src/i18n/locales/ko/prompts.json b/webview-ui/src/i18n/locales/ko/prompts.json index fd0505df73c9..b3accfcace35 100644 --- a/webview-ui/src/i18n/locales/ko/prompts.json +++ b/webview-ui/src/i18n/locales/ko/prompts.json @@ -143,6 +143,10 @@ "NEW_TASK": { "label": "새 작업 시작", "description": "입력한 내용으로 새 작업을 시작할 수 있습니다. 명령 팔레트에서 이용 가능합니다." + }, + "CREATE_PR": { + "label": "풀 리퀘스트 생성", + "description": "GitHub CLI를 사용하여 PR을 스테이징, 검토하고 생성하는 지침을 생성합니다. 이 템플릿을 사용자 정의할 수 있습니다." } } }, diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index 97380d370af0..a950d8102c9d 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -35,7 +35,7 @@ "tooltip": "Probeer de bewerking opnieuw" }, "startNewTask": { - "title": "Nieuwe taak starten", + "title": "Nieuwe taak", "tooltip": "Begin een nieuwe taak" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "Goedkeuren", "tooltip": "Deze actie goedkeuren" }, + "createPR": { + "title": "PR aanmaken", + "tooltip": "Een pull request aanmaken van je wijzigingen" + }, "runCommand": { "title": "Commando", "tooltip": "Voer dit commando uit" diff --git a/webview-ui/src/i18n/locales/nl/prompts.json b/webview-ui/src/i18n/locales/nl/prompts.json index 3fafb466b9f1..5b32aa72cfd1 100644 --- a/webview-ui/src/i18n/locales/nl/prompts.json +++ b/webview-ui/src/i18n/locales/nl/prompts.json @@ -143,6 +143,10 @@ "NEW_TASK": { "label": "Nieuwe taak starten", "description": "Start een nieuwe taak met gebruikersinvoer. Beschikbaar via de Command Palette." + }, + "CREATE_PR": { + "label": "Pull Request aanmaken", + "description": "Genereer instructies om een PR voor te bereiden, te beoordelen en aan te maken met de GitHub CLI. Je kunt dit sjabloon aanpassen." } } }, diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index 414262eaa7cf..47da28d8d4dc 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -40,7 +40,7 @@ "tooltip": "Spróbuj ponownie wykonać operację" }, "startNewTask": { - "title": "Rozpocznij nowe zadanie", + "title": "Nowe zadanie", "tooltip": "Rozpocznij nowe zadanie" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "Zatwierdź", "tooltip": "Zatwierdź tę akcję" }, + "createPR": { + "title": "Utwórz PR", + "tooltip": "Utwórz pull request ze swoich zmian" + }, "runCommand": { "title": "Polecenie", "tooltip": "Wykonaj to polecenie" diff --git a/webview-ui/src/i18n/locales/pl/prompts.json b/webview-ui/src/i18n/locales/pl/prompts.json index ab85673c2528..beea08b50235 100644 --- a/webview-ui/src/i18n/locales/pl/prompts.json +++ b/webview-ui/src/i18n/locales/pl/prompts.json @@ -143,6 +143,10 @@ "NEW_TASK": { "label": "Rozpocznij nowe zadanie", "description": "Rozpocznij nowe zadanie z wprowadzonymi danymi. Dostępne w palecie poleceń." + }, + "CREATE_PR": { + "label": "Utwórz Pull Request", + "description": "Wygeneruj instrukcje dotyczące przygotowania, przeglądu i utworzenia PR za pomocą GitHub CLI. Możesz dostosować ten szablon." } } }, diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index 0baa415bc7d3..773fc55ff9a0 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -40,7 +40,7 @@ "tooltip": "Tentar a operação novamente" }, "startNewTask": { - "title": "Iniciar nova tarefa", + "title": "Nova Tarefa", "tooltip": "Começar uma nova tarefa" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "Aprovar", "tooltip": "Aprovar esta ação" }, + "createPR": { + "title": "Criar PR", + "tooltip": "Crie um pull request a partir das suas alterações" + }, "runCommand": { "title": "Comando", "tooltip": "Executar este comando" diff --git a/webview-ui/src/i18n/locales/pt-BR/prompts.json b/webview-ui/src/i18n/locales/pt-BR/prompts.json index 75d9316eee6e..1e690dcb4bad 100644 --- a/webview-ui/src/i18n/locales/pt-BR/prompts.json +++ b/webview-ui/src/i18n/locales/pt-BR/prompts.json @@ -143,6 +143,10 @@ "NEW_TASK": { "label": "Iniciar Nova Tarefa", "description": "Inicie uma nova tarefa com a entrada fornecida. Disponível na paleta de comandos." + }, + "CREATE_PR": { + "label": "Criar Pull Request", + "description": "Gere instruções para preparar, revisar e criar um PR usando a CLI do GitHub. Você pode personalizar este modelo." } } }, diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index 10cca124d355..4cc607d0297d 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -35,7 +35,7 @@ "tooltip": "Попробовать выполнить операцию снова" }, "startNewTask": { - "title": "Начать новую задачу", + "title": "Новая задача", "tooltip": "Начать новую задачу" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "Одобрить", "tooltip": "Одобрить это действие" }, + "createPR": { + "title": "Создать PR", + "tooltip": "Создать pull request из ваших изменений" + }, "runCommand": { "title": "Команда", "tooltip": "Выполнить эту команду" diff --git a/webview-ui/src/i18n/locales/ru/prompts.json b/webview-ui/src/i18n/locales/ru/prompts.json index 097e16917377..44f962d85d0d 100644 --- a/webview-ui/src/i18n/locales/ru/prompts.json +++ b/webview-ui/src/i18n/locales/ru/prompts.json @@ -140,6 +140,10 @@ "NEW_TASK": { "label": "Начать новую задачу", "description": "Начать новую задачу с пользовательским вводом. Доступно в палитре команд." + }, + "CREATE_PR": { + "label": "Создать Pull Request", + "description": "Создайте инструкции для подготовки, проверки и создания PR с помощью GitHub CLI. Вы можете настроить этот шаблон." } } }, diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index 9b92b937a799..73b9434b35ef 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -40,7 +40,7 @@ "tooltip": "İşlemi tekrar dene" }, "startNewTask": { - "title": "Yeni Görev Başlat", + "title": "Yeni Görev", "tooltip": "Yeni bir görev başlat" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "Onayla", "tooltip": "Bu eylemi onayla" }, + "createPR": { + "title": "PR Oluştur", + "tooltip": "Değişikliklerinizden bir pull request oluşturun" + }, "runCommand": { "title": "Komut", "tooltip": "Bu komutu çalıştır" diff --git a/webview-ui/src/i18n/locales/tr/prompts.json b/webview-ui/src/i18n/locales/tr/prompts.json index 611b16eecba2..92ae6fad504f 100644 --- a/webview-ui/src/i18n/locales/tr/prompts.json +++ b/webview-ui/src/i18n/locales/tr/prompts.json @@ -140,6 +140,10 @@ "NEW_TASK": { "label": "Yeni Görev Başlat", "description": "Girdiyle yeni bir görev başlat. Komut paletinde kullanılabilir." + }, + "CREATE_PR": { + "label": "Pull Request Oluştur", + "description": "GitHub CLI'yi kullanarak bir PR'ı hazırlamak, incelemek ve oluşturmak için talimatlar oluşturun. Bu şablonu özelleştirebilirsiniz." } } }, diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index 39cb1cf01663..a82423dffd78 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -40,7 +40,7 @@ "tooltip": "Thử lại thao tác" }, "startNewTask": { - "title": "Bắt đầu nhiệm vụ mới", + "title": "Nhiệm vụ mới", "tooltip": "Bắt đầu một nhiệm vụ mới" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "Phê duyệt", "tooltip": "Phê duyệt hành động này" }, + "createPR": { + "title": "Tạo PR", + "tooltip": "Tạo một pull request từ các thay đổi của bạn" + }, "runCommand": { "title": "Lệnh", "tooltip": "Thực thi lệnh này" diff --git a/webview-ui/src/i18n/locales/vi/prompts.json b/webview-ui/src/i18n/locales/vi/prompts.json index 9c9f59c78acd..4e76560a05d2 100644 --- a/webview-ui/src/i18n/locales/vi/prompts.json +++ b/webview-ui/src/i18n/locales/vi/prompts.json @@ -140,6 +140,10 @@ "NEW_TASK": { "label": "Bắt đầu tác vụ mới", "description": "Bắt đầu tác vụ mới với nội dung đã nhập. Có sẵn trong bảng lệnh." + }, + "CREATE_PR": { + "label": "Tạo Pull Request", + "description": "Tạo hướng dẫn để chuẩn bị, xem xét và tạo một PR bằng GitHub CLI. Bạn có thể tùy chỉnh mẫu này." } } }, diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index ef87b819ea99..16723f53a9d0 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -40,7 +40,7 @@ "tooltip": "再次尝试操作" }, "startNewTask": { - "title": "开始新任务", + "title": "新任务", "tooltip": "开始一个新任务" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "批准", "tooltip": "批准此操作" }, + "createPR": { + "title": "创建 PR", + "tooltip": "从您的更改创建拉取请求" + }, "runCommand": { "title": "命令", "tooltip": "执行此命令" diff --git a/webview-ui/src/i18n/locales/zh-CN/prompts.json b/webview-ui/src/i18n/locales/zh-CN/prompts.json index c73f2be4a2aa..b2b509f7f403 100644 --- a/webview-ui/src/i18n/locales/zh-CN/prompts.json +++ b/webview-ui/src/i18n/locales/zh-CN/prompts.json @@ -140,6 +140,10 @@ "NEW_TASK": { "label": "新任务", "description": "控制开始新任务时的用户提示词。可在首页对话框中使用。" + }, + "CREATE_PR": { + "label": "创建拉取请求", + "description": "生成使用 GitHub CLI 来暂存、审查和创建 PR 的说明。你可以自定义此模板。" } } }, diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index 985859bec418..6accdcd4dbb1 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -35,7 +35,7 @@ "tooltip": "再次嘗試操作" }, "startNewTask": { - "title": "開始新工作", + "title": "新工作", "tooltip": "開始一項新工作" }, "proceedAnyways": { @@ -60,6 +60,10 @@ "title": "核准", "tooltip": "核准此操作" }, + "createPR": { + "title": "建立 PR", + "tooltip": "從您的變更建立拉取請求" + }, "read-batch": { "approve": { "title": "全部核准" diff --git a/webview-ui/src/i18n/locales/zh-TW/prompts.json b/webview-ui/src/i18n/locales/zh-TW/prompts.json index e21f4070e822..b88884c6a031 100644 --- a/webview-ui/src/i18n/locales/zh-TW/prompts.json +++ b/webview-ui/src/i18n/locales/zh-TW/prompts.json @@ -142,6 +142,10 @@ "NEW_TASK": { "label": "開始新工作", "description": "根據使用者輸入開始一個新的任務。可在命令選擇區使用。" + }, + "CREATE_PR": { + "label": "建立拉取請求", + "description": "產生使用 GitHub CLI 來暫存、審查和建立 PR 的說明。您可以自訂此範本。" } } },