From efaaed9f7381f7d9d1d027193b870cf0596adb4e Mon Sep 17 00:00:00 2001 From: MuriloFP Date: Thu, 3 Jul 2025 15:26:24 -0300 Subject: [PATCH 1/5] feat: add Issue Fixer Orchestrator mode --- .../1_Workflow.xml | 402 +++++++++++++----- .../2_best_practices.xml | 31 +- .roomodes | 3 +- 3 files changed, 315 insertions(+), 121 deletions(-) diff --git a/.roo/rules-issue-fixer-orchestrator/1_Workflow.xml b/.roo/rules-issue-fixer-orchestrator/1_Workflow.xml index 2ad4bf65fc7..3e6619993ec 100644 --- a/.roo/rules-issue-fixer-orchestrator/1_Workflow.xml +++ b/.roo/rules-issue-fixer-orchestrator/1_Workflow.xml @@ -27,7 +27,7 @@ Delegate: Analyze Requirements & Explore Codebase - Launch a subtask in `code` mode to perform a detailed analysis of the issue and the codebase. The subtask will be responsible for identifying affected files and creating an implementation plan. + Launch a subtask in `architect` mode to perform a detailed analysis of the issue and the codebase. The subtask will be responsible for identifying affected files and creating an implementation plan. The context file `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/issue_context.json` will be the input for this subtask. The subtask should write its findings (the implementation plan) to a new file: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/implementation_plan.md`. @@ -36,19 +36,50 @@ **Task: Analyze Issue and Create Implementation Plan** - You are an expert software architect. Your task is to analyze the provided GitHub issue and the current codebase to create a detailed implementation plan. + You are an expert software architect. Your task is to analyze the provided GitHub issue and the current codebase to create a detailed implementation plan with a focus on understanding component interactions and dependencies. 1. **Read Issue Context**: The full issue details and comments are in `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/issue_context.json`. Read this file to understand all requirements, acceptance criteria, and technical discussions. - 2. **Explore Codebase**: Use `codebase_search`, `read_file`, and other tools to explore the codebase. Identify all files that will need to be modified or created to address the issue. Analyze existing patterns and conventions. - - 3. **Create Implementation Plan**: Based on your analysis, create a comprehensive implementation plan. The plan should be detailed enough for another developer to execute. It must include: - - A summary of the issue and the proposed solution. - - A list of all files to be created or modified. - - A step-by-step guide for the code changes required in each file. - - A plan for writing or updating tests. - - 4. **Save the Plan**: Write the complete implementation plan to `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/implementation_plan.md`. + 2. **Perform Architectural Analysis**: + - **Map Component Interactions**: Trace the complete data flow from entry points to outputs + - **Identify Paired Operations**: For any operation (e.g., export), find its counterpart (e.g., import) + - **Find Similar Patterns**: Search for existing implementations of similar features + - **Analyze Dependencies**: Identify all consumers of the functionality being modified + - **Assess Impact**: Determine how changes will affect other parts of the system + + 3. **Explore Codebase Systematically**: + - Use `codebase_search` FIRST to find all related functionality + - Search for paired operations (if modifying export, search for import) + - Find all files that consume or depend on the affected functionality + - Identify configuration files, tests, and documentation that need updates + - Study similar features to understand established patterns + + 4. **Create Comprehensive Implementation Plan**: The plan must include: + - **Issue Summary**: Clear description of the problem and proposed solution + - **Architectural Context**: + - Data flow diagram showing component interactions + - List of paired operations that must be updated together + - Dependencies and consumers of the affected functionality + - **Impact Analysis**: + - All files that will be affected (directly and indirectly) + - Potential breaking changes + - Performance implications + - **Implementation Steps**: + - Detailed, ordered steps for each file modification + - Specific code changes with context + - Validation and error handling requirements + - **Testing Strategy**: + - Unit tests for individual components + - Integration tests for component interactions + - Edge cases and error scenarios + + 5. **Save the Plan**: Write the complete implementation plan to `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/implementation_plan.md`. + + **Critical Requirements:** + - Always search for and analyze paired operations (import/export, save/load, etc.) + - Map the complete data flow before proposing changes + - Identify all integration points and dependencies + - Consider backward compatibility and migration needs **Completion Protocol:** - This is your only task. Do not deviate from these instructions. @@ -110,19 +141,43 @@ **Task: Implement Code Changes Based on Plan** - You are an expert software developer. Your task is to implement the code changes exactly as described in the provided implementation plan. + You are an expert software developer. Your task is to implement the code changes with full awareness of system interactions and dependencies. - 1. **Read the Plan**: The implementation plan is located at `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/implementation_plan.md`. Follow its instructions carefully. + 1. **Read the Plan**: The implementation plan is located at `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/implementation_plan.md`. Pay special attention to: + - The architectural context section + - Component interaction diagrams + - Identified dependencies and related operations + - Impact analysis - 2. **Implement Changes**: Use `apply_diff` and `write_to_file` to make the specified code changes. Adhere to all coding standards and patterns mentioned in the plan. + 2. **Validate Understanding**: Before coding, ensure you understand: + - How data flows through the system + - All related operations that must be updated together + - Dependencies that could be affected + - Integration points with other components - 3. **Implement Tests**: Write new unit and integration tests as specified in the plan to ensure quality and prevent regressions. + 3. **Implement Holistically**: + - **Update Related Operations Together**: If modifying one operation, update all related operations + - **Maintain Consistency**: Ensure data structures, validation, and error handling are consistent + - **Consider Side Effects**: Account for how changes propagate through the system + - **Follow Existing Patterns**: Use established patterns from similar features - 4. **Track Modified Files**: As you modify or create files, keep a running list. + 4. **Implement Tests**: + - Write tests that verify component interactions + - Test related operations together + - Include edge cases and error scenarios + - Verify data consistency across operations - 5. **Save Modified Files List**: After all changes are implemented and tested, save the list of all file paths you created or modified to `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/modified_files.json`. The format should be a JSON array of strings. + 5. **Track Modified Files**: As you modify or create files, keep a running list. + + 6. **Save Modified Files List**: After all changes are implemented and tested, save the list of all file paths you created or modified to `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/modified_files.json`. The format should be a JSON array of strings. Example: `["src/components/NewFeature.tsx", "src/__tests__/NewFeature.spec.ts"]` + **Critical Reminders:** + - Never implement changes in isolation - consider the full system impact + - Always update related operations together to maintain consistency + - Test component interactions, not just individual functions + - Follow the architectural analysis from the planning phase + Once the `modified_files.json` file is saved, your task is complete. @@ -325,122 +380,233 @@ - Create Pull Request + Delegate: Review Changes Before PR - This is the final step where the orchestrator takes all the prepared materials and creates the pull request. + Before creating the pull request, delegate to the PR reviewer mode to get feedback on the implementation and proposed changes. - 1. **Read PR Summary**: - - - - .roo/temp/issue-fixer-orchestrator/[TASK_ID]/pr_summary.json - - - - - 2. **Get Final Approval**: Present the PR title and body to the user for final approval, providing an option to request changes. + + pr-reviewer + + **Task: Review Implementation Before PR Creation** - - - I have prepared the pull request. Please review and confirm. + You are an expert code reviewer. Your task is to review the implementation for issue #[issue-number] and provide feedback before a pull request is created. - **Title**: [Insert title from pr_summary.json] + **Context Files:** + - **Issue Details**: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/issue_context.json` + - **Implementation Plan**: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/implementation_plan.md` + - **Modified Files**: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/modified_files.json` + - **Verification Results**: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/verification_results.md` + - **Translation Summary** (if exists): `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/translation_summary.md` + - **Draft PR Summary**: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/pr_summary.json` + + **Your Review Focus:** + 1. **Code Quality**: Review the actual code changes for: + - Adherence to project coding standards + - Proper error handling and edge cases + - Performance considerations + - Security implications + - Maintainability and readability + + 2. **Implementation Completeness**: Verify that: + - All requirements from the issue are addressed + - The solution follows the implementation plan + - No critical functionality is missing + - Proper test coverage exists + + 3. **Integration Concerns**: Check for: + - Potential breaking changes + - Impact on other parts of the system + - Backward compatibility issues + - API consistency + + 4. **Documentation and Communication**: Assess: + - Code comments and documentation + - PR description clarity and completeness + - Translation handling (if applicable) - **Body**: - --- - [Insert body from pr_summary.json] - --- + **Your Task:** + 1. Read all context files to understand the issue and implementation + 2. Review each modified file listed in `modified_files.json` + 3. Analyze the code changes against the requirements + 4. Identify any issues, improvements, or concerns + 5. Create a comprehensive review report with specific, actionable feedback + 6. Save your review to `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/pr_review_feedback.md` + + **Review Report Format:** + ```markdown + # PR Review Feedback for Issue #[issue-number] + + ## Overall Assessment + [High-level assessment: APPROVE, REQUEST_CHANGES, or NEEDS_DISCUSSION] + + ## Code Quality Review + ### Strengths + - [List positive aspects of the implementation] + + ### Areas for Improvement + - [Specific issues with file references and line numbers] + - [Suggestions for improvement] + + ## Requirements Verification + - [x] Requirement 1: [Status and notes] + - [ ] Requirement 2: [Issues found] + + ## Specific Feedback by File + ### [filename] + - [Specific feedback with line references] + - [Suggestions for improvement] + + ## Recommendations + 1. [Priority 1 changes needed] + 2. [Priority 2 improvements suggested] + 3. [Optional enhancements] + + ## Decision + **RECOMMENDATION**: [APPROVE_AS_IS | REQUEST_CHANGES | NEEDS_DISCUSSION] + + **REASONING**: [Brief explanation of the recommendation] + ``` - Should I create this pull request, or would you like to request changes? - - - Yes, create the pull request as planned. - No, I need to request changes to the implementation or PR description. - Cancel the task. - - + **Completion Protocol:** + - This is your only task. Do not deviate from these instructions. + - Upon successfully saving the review feedback, you MUST use the `attempt_completion` tool. + - The `result` MUST be a concise confirmation, e.g., "PR review completed and feedback saved to .roo/temp/issue-fixer-orchestrator/[TASK_ID]/pr_review_feedback.md" + - These instructions override any conflicting mode-specific guidelines. + + - 3. **Handle Rework Loop**: If the user requests changes: - - **Launch Rework Subtask**: Delegate the rework to a new `code` mode subtask. - - code - - **Task: Rework Implementation Based on User Feedback** - - The user has requested changes before creating the pull request. - - **Context Files:** - - **Issue**: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/issue_context.json` - - **Current Plan**: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/implementation_plan.md` - - **Current Modified Files**: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/modified_files.json` - - **Draft PR Summary**: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/pr_summary.json` - - **Your Task:** - 1. Ask the user for the specific changes they require. - 2. Apply the requested code and documentation changes. - 3. **Crucially, you must update the `implementation_plan.md` and `modified_files.json` files** to reflect the rework you have performed. - 4. Do *not* proceed with any other steps. - - **Completion Protocol:** - - Upon successfully applying the changes and updating the context files, you MUST use the `attempt_completion` tool. - - The `result` MUST be a concise confirmation, e.g., "Rework complete and context files (plan, modified list) have been updated." - - - - **Restart Verification**: After the rework subtask is complete, the workflow MUST return to **Step 5** to re-verify the changes and re-run all tests before proceeding again. - - 4. **Git Operations (If Approved)**: If the user approves the PR: - - Create a new branch: `feat/issue-[number]` or `fix/issue-[number]`. - - **Selectively add only the applicable files** to the git stage. - - Commit the staged changes. - - Push the new branch to the remote repository. - - - # Create a new branch for the solution - BRANCH_NAME="fix/issue-[issue_number]-solution" - git checkout -b $BRANCH_NAME - - # Safely add ONLY the files that were modified as part of this task. - # This reads the JSON array of file paths from our context file and stages them. - # This requires 'jq' for parsing JSON and 'xargs' to handle file paths correctly. - cat .roo/temp/issue-fixer-orchestrator/[TASK_ID]/modified_files.json | jq -r '.[]' | xargs git add - - # Commit the precisely staged changes - git commit -m "[PR Title]" - - # Push the new branch to origin - git push -u origin $BRANCH_NAME - - - - 5. **Create PR**: Use the `gh` CLI to create the pull request. - - gh pr create --repo [owner]/[repo] --base main --title "[PR Title from JSON]" --body "[PR Body from JSON]" - - - 6. **Link to Issue**: Comment on the original issue with the PR link. - - gh issue comment [issue_number] --repo [owner]/[repo] --body "PR #[new PR number] has been created." - + After the review subtask completes, read and process the feedback. - Monitor PR Checks and Cleanup + Process Review Feedback and Decide Next Steps - After creating the PR, monitor the CI checks and then clean up the temporary files. + After the PR review is complete, read the feedback and decide whether to make changes or proceed with PR creation. + + 1. **Read Review Feedback**: + + + + .roo/temp/issue-fixer-orchestrator/[TASK_ID]/pr_review_feedback.md + + + + + 2. **Present Feedback to User**: Show the review feedback and ask for direction. + + + The PR review has been completed. Here is the feedback: + + --- + [Insert content of pr_review_feedback.md here] + --- + + Based on this review, how would you like to proceed? + + + Implement the suggested changes before creating the PR + Create the PR as-is, ignoring the review feedback + Discuss specific feedback points before deciding + Cancel the task + + + + 3. **Handle User Decision**: + + **If user chooses to implement changes:** + - Launch a rework subtask to address the review feedback + + code + + **Task: Address PR Review Feedback** + + The PR review has identified areas for improvement. Your task is to address the feedback before creating the pull request. + + **Context Files:** + - **Issue**: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/issue_context.json` + - **Current Plan**: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/implementation_plan.md` + - **Current Modified Files**: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/modified_files.json` + - **Review Feedback**: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/pr_review_feedback.md` + - **Draft PR Summary**: `.roo/temp/issue-fixer-orchestrator/[TASK_ID]/pr_summary.json` + + **Your Task:** + 1. Read the review feedback carefully + 2. Address each point raised by the reviewer + 3. Make the necessary code changes + 4. Update tests if needed + 5. **Update the `modified_files.json` file** to reflect any new or changed files + 6. **Update the `implementation_plan.md`** if the approach has changed significantly + + **Important Notes:** + - Focus on the specific issues identified in the review + - Maintain the overall solution approach unless the review suggests otherwise + - Ensure all changes are properly tested + - Do not proceed with any other workflow steps + + **Completion Protocol:** + - Upon successfully addressing the feedback and updating context files, you MUST use the `attempt_completion` tool. + - The `result` MUST be a concise confirmation, e.g., "Review feedback addressed and context files updated." + + + - **After rework completion**: Return to **Step 5** (Verify and Test) to re-verify the changes + + **If user chooses to proceed as-is:** + - Continue to the next step (Create Pull Request) + + **If user wants to discuss or cancel:** + - Handle accordingly based on user input + + - 1. **Monitor Checks**: Use `--watch` to monitor CI status in real-time. - - gh pr checks [PR URL or number] --repo [owner]/[repo] --watch - + + Prepare Branch and Present PR Template + + This step prepares the branch and commits, then presents the PR template to the user for confirmation before creating the actual pull request. + + 1. Read Issue Context for Issue Number: + Use read_file to get the issue context from .roo/temp/issue-fixer-orchestrator/[TASK_ID]/issue_context.json + + 2. Git Operations - Create branch and commit changes: + - Create a new branch: feat/issue-[number] or fix/issue-[number] + - Selectively add only the applicable files to the git stage + - Commit the staged changes + - Push the new branch to the remote repository + + Use execute_command with: + BRANCH_NAME="fix/issue-[issue_number]-solution" + git checkout -b $BRANCH_NAME + cat .roo/temp/issue-fixer-orchestrator/[TASK_ID]/modified_files.json | jq -r '.[]' | xargs git add + git commit -m "[PR Title]" + git push -u origin $BRANCH_NAME + + 3. Present PR Template - Instead of creating the PR automatically, present the standardized PR template to the user: + Use ask_followup_question to ask: "The branch has been created and changes have been committed. I have prepared a standardized PR template for this issue. Would you like me to create the pull request using the standard Roo Code PR template, or would you prefer to make changes first?" + + Provide these options: + - Yes, create the pull request with the standard template + - No, I want to make changes to the implementation first + - No, I want to customize the PR template before creating it + - Cancel the task + + 4. Handle User Decision: + If user chooses to create the PR: Use gh CLI to create the pull request with the standard template + If user chooses to make changes: Launch a rework subtask using new_task with code mode + If user wants to customize the template: Ask for their preferred PR title and body + + 5. Link to Issue - After PR creation, comment on the original issue with the PR link using gh issue comment + + - 2. **Report Status**: Inform the user of the final status of the checks. + + Monitor PR Checks and Cleanup + + After creating the PR (if created), monitor the CI checks and then clean up the temporary files. - 3. **Cleanup**: Remove the temporary task directory. - - rm -rf .roo/temp/issue-fixer-orchestrator/[TASK_ID] - - + 1. Monitor Checks - Use gh pr checks with --watch to monitor CI status in real-time + 2. Report Status - Inform the user of the final status of the checks + 3. Cleanup - Remove the temporary task directory using rm -rf .roo/temp/issue-fixer-orchestrator/[TASK_ID] + This concludes the orchestration workflow. diff --git a/.roo/rules-issue-fixer-orchestrator/2_best_practices.xml b/.roo/rules-issue-fixer-orchestrator/2_best_practices.xml index e6251d67b23..b9a9b52db78 100644 --- a/.roo/rules-issue-fixer-orchestrator/2_best_practices.xml +++ b/.roo/rules-issue-fixer-orchestrator/2_best_practices.xml @@ -27,6 +27,17 @@ Always use `codebase_search` FIRST to understand the codebase structure and find all related files before using other tools like `read_file`. + + Critical: Understand Component Interactions + + Map the complete data flow from input to output + Identify ALL paired operations (import/export, save/load, encode/decode) + Find all consumers and dependencies of the affected code + Trace how data transformations occur throughout the system + Understand error propagation and handling patterns + + + Investigation Checklist for Bug Fixes Search for the specific error message or broken functionality. @@ -34,6 +45,8 @@ Locate related test files to understand expected behavior. Identify all dependencies and import/export patterns for the affected code. Find similar, working patterns in the codebase to use as a reference. + **CRITICAL**: For any operation being fixed, find and analyze its paired operations + Trace the complete data flow to understand all affected components @@ -42,10 +55,26 @@ Find potential integration points (e.g., API routes, UI component registries). Locate relevant configuration files that may need to be updated. Identify common patterns, components, and utilities that should be reused. + **CRITICAL**: Design paired operations together (e.g., both import AND export) + Map all data transformations and state changes + Identify all downstream consumers of the new functionality + + Always Implement Paired Operations Together + + When fixing export, ALWAYS check and update import + When modifying save, ALWAYS verify load handles the changes + When changing serialization, ALWAYS update deserialization + When updating create, consider read/update/delete operations + + + Paired operations must maintain consistency. Changes to one without the other leads to data corruption, import failures, or broken functionality. + + + - Always read multiple related files together to understand the full context, including coding conventions, testing patterns, and error handling approaches. + Always read multiple related files together to understand the full context. Never assume a change is isolated - trace its impact through the entire system. \ No newline at end of file diff --git a/.roomodes b/.roomodes index 3b178f234fa..213d7b8314a 100644 --- a/.roomodes +++ b/.roomodes @@ -9,7 +9,7 @@ customModes: - Ensuring modes have appropriate tool group permissions - Crafting clear whenToUse descriptions for the Orchestrator - Following XML structuring best practices for clarity and parseability - + You help users create new modes by: - Gathering requirements about the mode's purpose and workflow - Defining appropriate roleDefinition and whenToUse descriptions @@ -182,4 +182,3 @@ customModes: - edit - command source: project - description: Issue Fixer mode ported into an orchestrator From 185220e57ce08198855f66e3c65f4b21270b2811 Mon Sep 17 00:00:00 2001 From: MuriloFP Date: Fri, 18 Jul 2025 16:00:08 -0300 Subject: [PATCH 2/5] fix: add Git installation check for checkpoints feature (#3109) - Export checkGitInstalled() function from utils/git.ts - Add Git check before initializing checkpoint service - Show user-friendly VSCode warning when Git is not installed - Include 'Learn More' button that links to Git download page - Disable checkpoints gracefully when Git is missing This prevents silent failures and provides clear feedback to users when Git is required but not installed. --- src/core/checkpoints/index.ts | 66 ++++++++++++++++++++++++++--------- src/utils/git.ts | 2 +- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/core/checkpoints/index.ts b/src/core/checkpoints/index.ts index dcbe796eb70..88c6e9c56b1 100644 --- a/src/core/checkpoints/index.ts +++ b/src/core/checkpoints/index.ts @@ -6,6 +6,7 @@ import { TelemetryService } from "@roo-code/telemetry" import { Task } from "../task/Task" import { getWorkspacePath } from "../../utils/path" +import { checkGitInstalled } from "../../utils/git" import { ClineApiReqInfo } from "../../shared/ExtensionMessage" import { getApiMetrics } from "../../shared/getApiMetrics" @@ -70,25 +71,56 @@ export function getCheckpointService(cline: Task) { cline.checkpointServiceInitializing = true - service.on("initialize", () => { - log("[Task#getCheckpointService] service initialized") - - try { - const isCheckpointNeeded = - typeof cline.clineMessages.find(({ say }) => say === "checkpoint_saved") === "undefined" - - cline.checkpointService = service - cline.checkpointServiceInitializing = false - - if (isCheckpointNeeded) { - log("[Task#getCheckpointService] no checkpoints found, saving initial checkpoint") - checkpointSave(cline) + // Check if Git is installed before initializing the service + checkGitInstalled() + .then((gitInstalled) => { + if (!gitInstalled) { + log("[Task#getCheckpointService] Git is not installed, disabling checkpoints") + cline.enableCheckpoints = false + cline.checkpointServiceInitializing = false + + // Show user-friendly notification + vscode.window + .showWarningMessage( + "Git is required for the checkpoints feature. Please install Git to enable checkpoints.", + "Learn More", + ) + .then((selection) => { + if (selection === "Learn More") { + vscode.env.openExternal(vscode.Uri.parse("https://git-scm.com/downloads")) + } + }) + + return } - } catch (err) { - log("[Task#getCheckpointService] caught error in on('initialize'), disabling checkpoints") + + // Git is installed, proceed with initialization + service.on("initialize", () => { + log("[Task#getCheckpointService] service initialized") + + try { + const isCheckpointNeeded = + typeof cline.clineMessages.find(({ say }) => say === "checkpoint_saved") === "undefined" + + cline.checkpointService = service + cline.checkpointServiceInitializing = false + + if (isCheckpointNeeded) { + log("[Task#getCheckpointService] no checkpoints found, saving initial checkpoint") + checkpointSave(cline) + } + } catch (err) { + log("[Task#getCheckpointService] caught error in on('initialize'), disabling checkpoints") + cline.enableCheckpoints = false + } + }) + }) + .catch((err) => { + log("[Task#getCheckpointService] error checking Git installation, disabling checkpoints") + console.error(err) cline.enableCheckpoints = false - } - }) + cline.checkpointServiceInitializing = false + }) service.on("checkpoint", ({ isFirst, fromHash: from, toHash: to }) => { try { diff --git a/src/utils/git.ts b/src/utils/git.ts index fd6abfa3097..7fc24e450cd 100644 --- a/src/utils/git.ts +++ b/src/utils/git.ts @@ -210,7 +210,7 @@ async function checkGitRepo(cwd: string): Promise { } } -async function checkGitInstalled(): Promise { +export async function checkGitInstalled(): Promise { try { await execAsync("git --version") return true From f5511e9a39a8a4dd61b725ca10e1aa56dfabe8d0 Mon Sep 17 00:00:00 2001 From: MuriloFP Date: Fri, 18 Jul 2025 16:32:04 -0300 Subject: [PATCH 3/5] fix: use i18n translations for Git warning message - Use t() function for warning message and Learn More button - Add translations to common.json for git_not_installed error - Follow project's i18n patterns for consistency --- src/core/checkpoints/index.ts | 8 +++----- src/i18n/locales/en/common.json | 4 +++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/checkpoints/index.ts b/src/core/checkpoints/index.ts index 88c6e9c56b1..861f9586b02 100644 --- a/src/core/checkpoints/index.ts +++ b/src/core/checkpoints/index.ts @@ -7,6 +7,7 @@ import { Task } from "../task/Task" import { getWorkspacePath } from "../../utils/path" import { checkGitInstalled } from "../../utils/git" +import { t } from "../../i18n" import { ClineApiReqInfo } from "../../shared/ExtensionMessage" import { getApiMetrics } from "../../shared/getApiMetrics" @@ -81,12 +82,9 @@ export function getCheckpointService(cline: Task) { // Show user-friendly notification vscode.window - .showWarningMessage( - "Git is required for the checkpoints feature. Please install Git to enable checkpoints.", - "Learn More", - ) + .showWarningMessage(t("common:errors.git_not_installed"), t("common:buttons.learn_more")) .then((selection) => { - if (selection === "Learn More") { + if (selection === t("common:buttons.learn_more")) { vscode.env.openExternal(vscode.Uri.parse("https://git-scm.com/downloads")) } }) diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index b0fdb9d8df8..4f69b2c8947 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "Could not open file!", "checkpoint_timeout": "Timed out when attempting to restore checkpoint.", "checkpoint_failed": "Failed to restore checkpoint.", + "git_not_installed": "Git is required for the checkpoints feature. Please install Git to enable checkpoints.", "no_workspace": "Please open a project folder first", "update_support_prompt": "Failed to update support prompt", "reset_support_prompt": "Failed to reset support prompt", @@ -107,7 +108,8 @@ }, "buttons": { "save": "Save", - "edit": "Edit" + "edit": "Edit", + "learn_more": "Learn More" }, "tasks": { "canceled": "Task error: It was stopped and canceled by the user.", From b6ee08546c5e492f99fc933fc4ead2accd5c592b Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Tue, 22 Jul 2025 13:53:30 -0500 Subject: [PATCH 4/5] feat: improve Git installation check implementation - Add comprehensive unit tests for checkGitInstalled function - Improve error handling specificity to differentiate Git check failures - Refactor promise chains to async/await pattern for better readability - Add JSDoc documentation to exported checkGitInstalled function - Add missing translations for Git warning messages in all locales These improvements enhance code quality, maintainability, and user experience while maintaining backward compatibility with the checkpoint service. --- src/core/checkpoints/index.ts | 37 +++++++++++++--------- src/i18n/locales/ca/common.json | 4 ++- src/i18n/locales/de/common.json | 4 ++- src/i18n/locales/es/common.json | 4 ++- src/i18n/locales/fr/common.json | 4 ++- src/i18n/locales/hi/common.json | 4 ++- src/i18n/locales/id/common.json | 4 ++- src/i18n/locales/it/common.json | 4 ++- src/i18n/locales/ja/common.json | 4 ++- src/i18n/locales/ko/common.json | 4 ++- src/i18n/locales/nl/common.json | 4 ++- src/i18n/locales/pl/common.json | 4 ++- src/i18n/locales/pt-BR/common.json | 4 ++- src/i18n/locales/ru/common.json | 4 ++- src/i18n/locales/tr/common.json | 4 ++- src/i18n/locales/vi/common.json | 4 ++- src/i18n/locales/zh-CN/common.json | 4 ++- src/i18n/locales/zh-TW/common.json | 4 ++- src/utils/__tests__/git.spec.ts | 49 ++++++++++++++++++++++++++++++ src/utils/git.ts | 9 ++++++ 20 files changed, 132 insertions(+), 31 deletions(-) diff --git a/src/core/checkpoints/index.ts b/src/core/checkpoints/index.ts index 861f9586b02..648bbe1c62c 100644 --- a/src/core/checkpoints/index.ts +++ b/src/core/checkpoints/index.ts @@ -73,21 +73,24 @@ export function getCheckpointService(cline: Task) { cline.checkpointServiceInitializing = true // Check if Git is installed before initializing the service - checkGitInstalled() - .then((gitInstalled) => { + ;(async () => { + try { + const gitInstalled = await checkGitInstalled() + if (!gitInstalled) { log("[Task#getCheckpointService] Git is not installed, disabling checkpoints") cline.enableCheckpoints = false cline.checkpointServiceInitializing = false // Show user-friendly notification - vscode.window - .showWarningMessage(t("common:errors.git_not_installed"), t("common:buttons.learn_more")) - .then((selection) => { - if (selection === t("common:buttons.learn_more")) { - vscode.env.openExternal(vscode.Uri.parse("https://git-scm.com/downloads")) - } - }) + const selection = await vscode.window.showWarningMessage( + t("common:errors.git_not_installed"), + t("common:buttons.learn_more"), + ) + + if (selection === t("common:buttons.learn_more")) { + vscode.env.openExternal(vscode.Uri.parse("https://git-scm.com/downloads")) + } return } @@ -112,13 +115,19 @@ export function getCheckpointService(cline: Task) { cline.enableCheckpoints = false } }) - }) - .catch((err) => { - log("[Task#getCheckpointService] error checking Git installation, disabling checkpoints") - console.error(err) + } catch (err) { + // Differentiate between Git check errors and other errors + if (err?.message?.includes("git") || err?.message?.includes("Git")) { + log("[Task#getCheckpointService] Git check failed, disabling checkpoints") + console.error("Git check error:", err) + } else { + log("[Task#getCheckpointService] Unexpected error during initialization, disabling checkpoints") + console.error("Initialization error:", err) + } cline.enableCheckpoints = false cline.checkpointServiceInitializing = false - }) + } + })() service.on("checkpoint", ({ isFirst, fromHash: from, toHash: to }) => { try { diff --git a/src/i18n/locales/ca/common.json b/src/i18n/locales/ca/common.json index 772156286e5..82c636ed14a 100644 --- a/src/i18n/locales/ca/common.json +++ b/src/i18n/locales/ca/common.json @@ -32,6 +32,7 @@ "could_not_open_file_generic": "No s'ha pogut obrir el fitxer!", "checkpoint_timeout": "S'ha esgotat el temps en intentar restaurar el punt de control.", "checkpoint_failed": "Ha fallat la restauració del punt de control.", + "git_not_installed": "Git és necessari per a la funció de punts de control. Si us plau, instal·la Git per activar els punts de control.", "no_workspace": "Si us plau, obre primer una carpeta de projecte", "update_support_prompt": "Ha fallat l'actualització del missatge de suport", "reset_support_prompt": "Ha fallat el restabliment del missatge de suport", @@ -111,7 +112,8 @@ }, "buttons": { "save": "Desar", - "edit": "Editar" + "edit": "Editar", + "learn_more": "Més informació" }, "tasks": { "canceled": "Error de tasca: Ha estat aturada i cancel·lada per l'usuari.", diff --git a/src/i18n/locales/de/common.json b/src/i18n/locales/de/common.json index c136fba8092..65a6f441c24 100644 --- a/src/i18n/locales/de/common.json +++ b/src/i18n/locales/de/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "Datei konnte nicht geöffnet werden!", "checkpoint_timeout": "Zeitüberschreitung beim Versuch, den Checkpoint wiederherzustellen.", "checkpoint_failed": "Fehler beim Wiederherstellen des Checkpoints.", + "git_not_installed": "Git ist für die Checkpoint-Funktion erforderlich. Bitte installiere Git, um Checkpoints zu aktivieren.", "no_workspace": "Bitte öffne zuerst einen Projektordner", "update_support_prompt": "Fehler beim Aktualisieren der Support-Nachricht", "reset_support_prompt": "Fehler beim Zurücksetzen der Support-Nachricht", @@ -107,7 +108,8 @@ }, "buttons": { "save": "Speichern", - "edit": "Bearbeiten" + "edit": "Bearbeiten", + "learn_more": "Mehr erfahren" }, "tasks": { "canceled": "Aufgabenfehler: Die Aufgabe wurde vom Benutzer gestoppt und abgebrochen.", diff --git a/src/i18n/locales/es/common.json b/src/i18n/locales/es/common.json index 39cf48383eb..aeea8952e42 100644 --- a/src/i18n/locales/es/common.json +++ b/src/i18n/locales/es/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "¡No se pudo abrir el archivo!", "checkpoint_timeout": "Se agotó el tiempo al intentar restaurar el punto de control.", "checkpoint_failed": "Error al restaurar el punto de control.", + "git_not_installed": "Git es necesario para la función de puntos de control. Por favor, instala Git para activar los puntos de control.", "no_workspace": "Por favor, abre primero una carpeta de proyecto", "update_support_prompt": "Error al actualizar el mensaje de soporte", "reset_support_prompt": "Error al restablecer el mensaje de soporte", @@ -107,7 +108,8 @@ }, "buttons": { "save": "Guardar", - "edit": "Editar" + "edit": "Editar", + "learn_more": "Más información" }, "tasks": { "canceled": "Error de tarea: Fue detenida y cancelada por el usuario.", diff --git a/src/i18n/locales/fr/common.json b/src/i18n/locales/fr/common.json index ace5bbe47a6..fb17b68f677 100644 --- a/src/i18n/locales/fr/common.json +++ b/src/i18n/locales/fr/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "Impossible d'ouvrir le fichier !", "checkpoint_timeout": "Expiration du délai lors de la tentative de rétablissement du checkpoint.", "checkpoint_failed": "Échec du rétablissement du checkpoint.", + "git_not_installed": "Git est requis pour la fonctionnalité des points de contrôle. Veuillez installer Git pour activer les points de contrôle.", "no_workspace": "Veuillez d'abord ouvrir un espace de travail", "update_support_prompt": "Erreur lors de la mise à jour du prompt de support", "reset_support_prompt": "Erreur lors de la réinitialisation du prompt de support", @@ -107,7 +108,8 @@ }, "buttons": { "save": "Enregistrer", - "edit": "Modifier" + "edit": "Modifier", + "learn_more": "En savoir plus" }, "tasks": { "canceled": "Erreur de tâche : Elle a été arrêtée et annulée par l'utilisateur.", diff --git a/src/i18n/locales/hi/common.json b/src/i18n/locales/hi/common.json index 84dbe9052af..d88d1ce37be 100644 --- a/src/i18n/locales/hi/common.json +++ b/src/i18n/locales/hi/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "फ़ाइल नहीं खोली जा सकी!", "checkpoint_timeout": "चेकपॉइंट को पुनर्स्थापित करने का प्रयास करते समय टाइमआउट हो गया।", "checkpoint_failed": "चेकपॉइंट पुनर्स्थापित करने में विफल।", + "git_not_installed": "चेकपॉइंट सुविधा के लिए Git आवश्यक है। कृपया चेकपॉइंट সক্ষম करने के लिए Git इंस्टॉल करें।", "no_workspace": "कृपया पहले प्रोजेक्ट फ़ोल्डर खोलें", "update_support_prompt": "सपोर्ट प्रॉम्प्ट अपडेट करने में विफल", "reset_support_prompt": "सपोर्ट प्रॉम्प्ट रीसेट करने में विफल", @@ -107,7 +108,8 @@ }, "buttons": { "save": "सहेजें", - "edit": "संपादित करें" + "edit": "संपादित करें", + "learn_more": "और अधिक जानें" }, "tasks": { "canceled": "टास्क त्रुटि: इसे उपयोगकर्ता द्वारा रोका और रद्द किया गया था।", diff --git a/src/i18n/locales/id/common.json b/src/i18n/locales/id/common.json index fb2a30994ee..d50f78a0236 100644 --- a/src/i18n/locales/id/common.json +++ b/src/i18n/locales/id/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "Tidak dapat membuka file!", "checkpoint_timeout": "Timeout saat mencoba memulihkan checkpoint.", "checkpoint_failed": "Gagal memulihkan checkpoint.", + "git_not_installed": "Git diperlukan untuk fitur checkpoint. Silakan instal Git untuk mengaktifkan checkpoint.", "no_workspace": "Silakan buka folder proyek terlebih dahulu", "update_support_prompt": "Gagal memperbarui support prompt", "reset_support_prompt": "Gagal mereset support prompt", @@ -107,7 +108,8 @@ }, "buttons": { "save": "Simpan", - "edit": "Edit" + "edit": "Edit", + "learn_more": "Pelajari Lebih Lanjut" }, "tasks": { "canceled": "Error tugas: Dihentikan dan dibatalkan oleh pengguna.", diff --git a/src/i18n/locales/it/common.json b/src/i18n/locales/it/common.json index 4681612e9d7..6620914d834 100644 --- a/src/i18n/locales/it/common.json +++ b/src/i18n/locales/it/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "Impossibile aprire il file!", "checkpoint_timeout": "Timeout durante il tentativo di ripristinare il checkpoint.", "checkpoint_failed": "Impossibile ripristinare il checkpoint.", + "git_not_installed": "Git è richiesto per la funzione di checkpoint. Per favore, installa Git per abilitare i checkpoint.", "no_workspace": "Per favore, apri prima una cartella di progetto", "update_support_prompt": "Errore durante l'aggiornamento del messaggio di supporto", "reset_support_prompt": "Errore durante il ripristino del messaggio di supporto", @@ -107,7 +108,8 @@ }, "buttons": { "save": "Salva", - "edit": "Modifica" + "edit": "Modifica", + "learn_more": "Scopri di più" }, "tasks": { "canceled": "Errore attività: È stata interrotta e annullata dall'utente.", diff --git a/src/i18n/locales/ja/common.json b/src/i18n/locales/ja/common.json index 38fc9d27c53..79c0d37df0b 100644 --- a/src/i18n/locales/ja/common.json +++ b/src/i18n/locales/ja/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "ファイルを開けませんでした!", "checkpoint_timeout": "チェックポイントの復元を試みる際にタイムアウトしました。", "checkpoint_failed": "チェックポイントの復元に失敗しました。", + "git_not_installed": "チェックポイント機能にはGitが必要です。チェックポイントを有効にするにはGitをインストールしてください。", "no_workspace": "まずプロジェクトフォルダを開いてください", "update_support_prompt": "サポートメッセージの更新に失敗しました", "reset_support_prompt": "サポートメッセージのリセットに失敗しました", @@ -107,7 +108,8 @@ }, "buttons": { "save": "保存", - "edit": "編集" + "edit": "編集", + "learn_more": "詳細" }, "tasks": { "canceled": "タスクエラー:ユーザーによって停止およびキャンセルされました。", diff --git a/src/i18n/locales/ko/common.json b/src/i18n/locales/ko/common.json index d76a82a7c20..3f25199595d 100644 --- a/src/i18n/locales/ko/common.json +++ b/src/i18n/locales/ko/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "파일을 열 수 없습니다!", "checkpoint_timeout": "체크포인트 복원을 시도하는 중 시간 초과되었습니다.", "checkpoint_failed": "체크포인트 복원에 실패했습니다.", + "git_not_installed": "체크포인트 기능을 사용하려면 Git이 필요합니다. 체크포인트를 활성화하려면 Git을 설치하세요.", "no_workspace": "먼저 프로젝트 폴더를 열어주세요", "update_support_prompt": "지원 프롬프트 업데이트에 실패했습니다", "reset_support_prompt": "지원 프롬프트 재설정에 실패했습니다", @@ -107,7 +108,8 @@ }, "buttons": { "save": "저장", - "edit": "편집" + "edit": "편집", + "learn_more": "더 알아보기" }, "tasks": { "canceled": "작업 오류: 사용자에 의해 중지 및 취소되었습니다.", diff --git a/src/i18n/locales/nl/common.json b/src/i18n/locales/nl/common.json index 5caa0534ee8..0beebc8f874 100644 --- a/src/i18n/locales/nl/common.json +++ b/src/i18n/locales/nl/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "Kon bestand niet openen!", "checkpoint_timeout": "Time-out bij het herstellen van checkpoint.", "checkpoint_failed": "Herstellen van checkpoint mislukt.", + "git_not_installed": "Git is vereist voor de checkpoint-functie. Installeer Git om checkpoints in te schakelen.", "no_workspace": "Open eerst een projectmap", "update_support_prompt": "Bijwerken van ondersteuningsprompt mislukt", "reset_support_prompt": "Resetten van ondersteuningsprompt mislukt", @@ -107,7 +108,8 @@ }, "buttons": { "save": "Opslaan", - "edit": "Bewerken" + "edit": "Bewerken", + "learn_more": "Meer informatie" }, "tasks": { "canceled": "Taakfout: gestopt en geannuleerd door gebruiker.", diff --git a/src/i18n/locales/pl/common.json b/src/i18n/locales/pl/common.json index 77008aa0abc..727d1d58685 100644 --- a/src/i18n/locales/pl/common.json +++ b/src/i18n/locales/pl/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "Nie można otworzyć pliku!", "checkpoint_timeout": "Upłynął limit czasu podczas próby przywrócenia punktu kontrolnego.", "checkpoint_failed": "Nie udało się przywrócić punktu kontrolnego.", + "git_not_installed": "Funkcja punktów kontrolnych wymaga oprogramowania Git. Zainstaluj Git, aby włączyć punkty kontrolne.", "no_workspace": "Najpierw otwórz folder projektu", "update_support_prompt": "Nie udało się zaktualizować komunikatu wsparcia", "reset_support_prompt": "Nie udało się zresetować komunikatu wsparcia", @@ -107,7 +108,8 @@ }, "buttons": { "save": "Zapisz", - "edit": "Edytuj" + "edit": "Edytuj", + "learn_more": "Dowiedz się więcej" }, "tasks": { "canceled": "Błąd zadania: Zostało zatrzymane i anulowane przez użytkownika.", diff --git a/src/i18n/locales/pt-BR/common.json b/src/i18n/locales/pt-BR/common.json index 6f63d9d1ed8..4fed2375c6e 100644 --- a/src/i18n/locales/pt-BR/common.json +++ b/src/i18n/locales/pt-BR/common.json @@ -32,6 +32,7 @@ "could_not_open_file_generic": "Não foi possível abrir o arquivo!", "checkpoint_timeout": "Tempo esgotado ao tentar restaurar o ponto de verificação.", "checkpoint_failed": "Falha ao restaurar o ponto de verificação.", + "git_not_installed": "O Git é necessário para o recurso de checkpoints. Por favor, instale o Git para habilitar os checkpoints.", "no_workspace": "Por favor, abra primeiro uma pasta de projeto", "update_support_prompt": "Falha ao atualizar o prompt de suporte", "reset_support_prompt": "Falha ao redefinir o prompt de suporte", @@ -111,7 +112,8 @@ }, "buttons": { "save": "Salvar", - "edit": "Editar" + "edit": "Editar", + "learn_more": "Saiba Mais" }, "tasks": { "canceled": "Erro na tarefa: Foi interrompida e cancelada pelo usuário.", diff --git a/src/i18n/locales/ru/common.json b/src/i18n/locales/ru/common.json index 4e354bcbc5a..2100a9b5aa0 100644 --- a/src/i18n/locales/ru/common.json +++ b/src/i18n/locales/ru/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "Не удалось открыть файл!", "checkpoint_timeout": "Превышено время ожидания при попытке восстановления контрольной точки.", "checkpoint_failed": "Не удалось восстановить контрольную точку.", + "git_not_installed": "Для функции контрольных точек требуется Git. Пожалуйста, установите Git, чтобы включить контрольные точки.", "no_workspace": "Пожалуйста, сначала откройте папку проекта", "update_support_prompt": "Не удалось обновить промпт поддержки", "reset_support_prompt": "Не удалось сбросить промпт поддержки", @@ -107,7 +108,8 @@ }, "buttons": { "save": "Сохранить", - "edit": "Редактировать" + "edit": "Редактировать", + "learn_more": "Узнать больше" }, "tasks": { "canceled": "Ошибка задачи: Она была остановлена и отменена пользователем.", diff --git a/src/i18n/locales/tr/common.json b/src/i18n/locales/tr/common.json index 5de82d00c6e..150cc7d3f88 100644 --- a/src/i18n/locales/tr/common.json +++ b/src/i18n/locales/tr/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "Dosya açılamadı!", "checkpoint_timeout": "Kontrol noktasını geri yüklemeye çalışırken zaman aşımına uğradı.", "checkpoint_failed": "Kontrol noktası geri yüklenemedi.", + "git_not_installed": "Kontrol noktaları özelliği için Git gereklidir. Kontrol noktalarını etkinleştirmek için lütfen Git'i yükleyin.", "no_workspace": "Lütfen önce bir proje klasörü açın", "update_support_prompt": "Destek istemi güncellenemedi", "reset_support_prompt": "Destek istemi sıfırlanamadı", @@ -107,7 +108,8 @@ }, "buttons": { "save": "Kaydet", - "edit": "Düzenle" + "edit": "Düzenle", + "learn_more": "Daha Fazla Bilgi" }, "tasks": { "canceled": "Görev hatası: Kullanıcı tarafından durduruldu ve iptal edildi.", diff --git a/src/i18n/locales/vi/common.json b/src/i18n/locales/vi/common.json index 014bddda58f..61477237b5f 100644 --- a/src/i18n/locales/vi/common.json +++ b/src/i18n/locales/vi/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "Không thể mở tệp!", "checkpoint_timeout": "Đã hết thời gian khi cố gắng khôi phục điểm kiểm tra.", "checkpoint_failed": "Không thể khôi phục điểm kiểm tra.", + "git_not_installed": "Yêu cầu Git cho tính năng điểm kiểm tra. Vui lòng cài đặt Git để bật điểm kiểm tra.", "no_workspace": "Vui lòng mở thư mục dự án trước", "update_support_prompt": "Không thể cập nhật lời nhắc hỗ trợ", "reset_support_prompt": "Không thể đặt lại lời nhắc hỗ trợ", @@ -107,7 +108,8 @@ }, "buttons": { "save": "Lưu", - "edit": "Chỉnh sửa" + "edit": "Chỉnh sửa", + "learn_more": "Tìm hiểu thêm" }, "tasks": { "canceled": "Lỗi nhiệm vụ: Nó đã bị dừng và hủy bởi người dùng.", diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json index 268ee5fbb18..8c2d2183050 100644 --- a/src/i18n/locales/zh-CN/common.json +++ b/src/i18n/locales/zh-CN/common.json @@ -33,6 +33,7 @@ "could_not_open_file_generic": "无法打开文件!", "checkpoint_timeout": "尝试恢复检查点时超时。", "checkpoint_failed": "恢复检查点失败。", + "git_not_installed": "存档点功能需要 Git。请安装 Git 以启用存档点。", "no_workspace": "请先打开项目文件夹", "update_support_prompt": "更新支持消息失败", "reset_support_prompt": "重置支持消息失败", @@ -112,7 +113,8 @@ }, "buttons": { "save": "保存", - "edit": "编辑" + "edit": "编辑", + "learn_more": "了解更多" }, "tasks": { "canceled": "任务错误:它已被用户停止并取消。", diff --git a/src/i18n/locales/zh-TW/common.json b/src/i18n/locales/zh-TW/common.json index dec20a1f9a5..4d3dbad9296 100644 --- a/src/i18n/locales/zh-TW/common.json +++ b/src/i18n/locales/zh-TW/common.json @@ -28,6 +28,7 @@ "could_not_open_file_generic": "無法開啟檔案!", "checkpoint_timeout": "嘗試恢復檢查點時超時。", "checkpoint_failed": "恢復檢查點失敗。", + "git_not_installed": "存檔點功能需要 Git。請安裝 Git 以啟用存檔點。", "no_workspace": "請先開啟專案資料夾", "update_support_prompt": "更新支援訊息失敗", "reset_support_prompt": "重設支援訊息失敗", @@ -107,7 +108,8 @@ }, "buttons": { "save": "儲存", - "edit": "編輯" + "edit": "編輯", + "learn_more": "了解更多" }, "tasks": { "canceled": "工作錯誤:它已被使用者停止並取消。", diff --git a/src/utils/__tests__/git.spec.ts b/src/utils/__tests__/git.spec.ts index 3ab306feec3..f87ae5667b8 100644 --- a/src/utils/__tests__/git.spec.ts +++ b/src/utils/__tests__/git.spec.ts @@ -4,6 +4,7 @@ import * as fs from "fs" import * as path from "path" import { + checkGitInstalled, searchCommits, getCommitInfo, getWorkingState, @@ -83,6 +84,54 @@ describe("git utils", () => { vitest.clearAllMocks() }) + describe("checkGitInstalled", () => { + it("should return true when git --version succeeds", async () => { + vitest.mocked(exec).mockImplementation((command: string, options: any, callback: any) => { + if (command === "git --version") { + callback(null, { stdout: "git version 2.39.2", stderr: "" }) + return {} as any + } + callback(new Error("Unexpected command")) + return {} as any + }) + + const result = await checkGitInstalled() + expect(result).toBe(true) + expect(vitest.mocked(exec)).toHaveBeenCalledWith("git --version", {}, expect.any(Function)) + }) + + it("should return false when git --version fails", async () => { + vitest.mocked(exec).mockImplementation((command: string, options: any, callback: any) => { + if (command === "git --version") { + callback(new Error("git not found")) + return {} as any + } + callback(new Error("Unexpected command")) + return {} as any + }) + + const result = await checkGitInstalled() + expect(result).toBe(false) + expect(vitest.mocked(exec)).toHaveBeenCalledWith("git --version", {}, expect.any(Function)) + }) + + it("should handle unexpected errors gracefully", async () => { + vitest.mocked(exec).mockImplementation((command: string, options: any, callback: any) => { + if (command === "git --version") { + // Simulate an unexpected error + callback(new Error("Unexpected system error")) + return {} as any + } + callback(new Error("Unexpected command")) + return {} as any + }) + + const result = await checkGitInstalled() + expect(result).toBe(false) + expect(vitest.mocked(exec)).toHaveBeenCalledWith("git --version", {}, expect.any(Function)) + }) + }) + describe("searchCommits", () => { const mockCommitData = [ "abc123def456", diff --git a/src/utils/git.ts b/src/utils/git.ts index 7fc24e450cd..42d069416e8 100644 --- a/src/utils/git.ts +++ b/src/utils/git.ts @@ -210,6 +210,15 @@ async function checkGitRepo(cwd: string): Promise { } } +/** + * Checks if Git is installed on the system by attempting to run git --version + * @returns {Promise} True if Git is installed and accessible, false otherwise + * @example + * const isGitInstalled = await checkGitInstalled(); + * if (!isGitInstalled) { + * console.log("Git is not installed"); + * } + */ export async function checkGitInstalled(): Promise { try { await execAsync("git --version") From b90d128e57d4ddbbe0afeb1f2164154329efeb92 Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Tue, 22 Jul 2025 15:22:08 -0500 Subject: [PATCH 5/5] refactor: improve Git check pattern in checkpoint initialization - Extract Git check logic into separate async function for better readability - Remove awkward semicolon before IIFE - Add clear comments explaining the fire-and-forget pattern - Pass provider variable correctly to avoid redundant access - Improve error handling and logging --- src/core/checkpoints/index.ts | 105 +++++++++++++++++----------------- 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/src/core/checkpoints/index.ts b/src/core/checkpoints/index.ts index 648bbe1c62c..02fb5dfc5a1 100644 --- a/src/core/checkpoints/index.ts +++ b/src/core/checkpoints/index.ts @@ -73,61 +73,65 @@ export function getCheckpointService(cline: Task) { cline.checkpointServiceInitializing = true // Check if Git is installed before initializing the service - ;(async () => { - try { - const gitInstalled = await checkGitInstalled() + // Note: This is intentionally fire-and-forget to match the original IIFE pattern + // The service is returned immediately while Git check happens asynchronously + checkGitInstallation(cline, service, log, provider) - if (!gitInstalled) { - log("[Task#getCheckpointService] Git is not installed, disabling checkpoints") - cline.enableCheckpoints = false - cline.checkpointServiceInitializing = false + return service + } catch (err) { + log(`[Task#getCheckpointService] ${err.message}`) + cline.enableCheckpoints = false + return undefined + } +} - // Show user-friendly notification - const selection = await vscode.window.showWarningMessage( - t("common:errors.git_not_installed"), - t("common:buttons.learn_more"), - ) +async function checkGitInstallation( + cline: Task, + service: RepoPerTaskCheckpointService, + log: (message: string) => void, + provider: any, +) { + try { + const gitInstalled = await checkGitInstalled() - if (selection === t("common:buttons.learn_more")) { - vscode.env.openExternal(vscode.Uri.parse("https://git-scm.com/downloads")) - } + if (!gitInstalled) { + log("[Task#getCheckpointService] Git is not installed, disabling checkpoints") + cline.enableCheckpoints = false + cline.checkpointServiceInitializing = false - return - } + // Show user-friendly notification + const selection = await vscode.window.showWarningMessage( + t("common:errors.git_not_installed"), + t("common:buttons.learn_more"), + ) - // Git is installed, proceed with initialization - service.on("initialize", () => { - log("[Task#getCheckpointService] service initialized") - - try { - const isCheckpointNeeded = - typeof cline.clineMessages.find(({ say }) => say === "checkpoint_saved") === "undefined" - - cline.checkpointService = service - cline.checkpointServiceInitializing = false - - if (isCheckpointNeeded) { - log("[Task#getCheckpointService] no checkpoints found, saving initial checkpoint") - checkpointSave(cline) - } - } catch (err) { - log("[Task#getCheckpointService] caught error in on('initialize'), disabling checkpoints") - cline.enableCheckpoints = false - } - }) - } catch (err) { - // Differentiate between Git check errors and other errors - if (err?.message?.includes("git") || err?.message?.includes("Git")) { - log("[Task#getCheckpointService] Git check failed, disabling checkpoints") - console.error("Git check error:", err) - } else { - log("[Task#getCheckpointService] Unexpected error during initialization, disabling checkpoints") - console.error("Initialization error:", err) + if (selection === t("common:buttons.learn_more")) { + await vscode.env.openExternal(vscode.Uri.parse("https://git-scm.com/downloads")) + } + + return + } + + // Git is installed, proceed with initialization + service.on("initialize", () => { + log("[Task#getCheckpointService] service initialized") + + try { + const isCheckpointNeeded = + typeof cline.clineMessages.find(({ say }) => say === "checkpoint_saved") === "undefined" + + cline.checkpointService = service + cline.checkpointServiceInitializing = false + + if (isCheckpointNeeded) { + log("[Task#getCheckpointService] no checkpoints found, saving initial checkpoint") + checkpointSave(cline) } + } catch (err) { + log("[Task#getCheckpointService] caught error in on('initialize'), disabling checkpoints") cline.enableCheckpoints = false - cline.checkpointServiceInitializing = false } - })() + }) service.on("checkpoint", ({ isFirst, fromHash: from, toHash: to }) => { try { @@ -154,12 +158,11 @@ export function getCheckpointService(cline: Task) { log(`[Task#getCheckpointService] initShadowGit -> ${err.message}`) cline.enableCheckpoints = false }) - - return service } catch (err) { - log(`[Task#getCheckpointService] ${err.message}`) + log(`[Task#getCheckpointService] Unexpected error during Git check: ${err.message}`) + console.error("Git check error:", err) cline.enableCheckpoints = false - return undefined + cline.checkpointServiceInitializing = false } }