From 0caf685b4fbcc1d7e3e1ad9d99e5e6ebdac4b063 Mon Sep 17 00:00:00 2001 From: Smartsheet-JB-Brown Date: Wed, 16 Apr 2025 12:33:20 -0700 Subject: [PATCH] rolled back unintended changes not related or needed to support package manager. first phases of build pass, but fail at type checking on things that don't seem related to what I've done --- .roo/iterate-cli.ts | 137 ------------ .roo/iterations/PM-CLEANUP-20250412.json | 24 -- .roo/iterations/PM-STATE-FIX-20250412.json | 63 ------ ..._4d3f7a2e-8c1b-4f9d-b5e2-9c1d8f3a6b4d.json | 84 ------- .../task_e2e_analysis_20250412.json | 94 -------- .roomodes | 40 ++++ esbuild.js | 1 - src/__mocks__/fs/promises.ts | 210 ++++++++++++++++++ src/core/__tests__/Cline.test.ts | 185 ++++++++++++--- src/i18n/setup.ts | 2 +- src/utils/__tests__/git.test.js.map | 1 - src/utils/git.js.map | 1 - .../components/PackageManagerItemCard.tsx | 3 +- .../package-manager/components/TypeGroup.tsx | 3 +- .../package-manager/state/useStateManager.ts | 117 ---------- webview-ui/src/i18n.ts | 20 -- webview-ui/src/utils/context-mentions.ts | 6 +- 17 files changed, 408 insertions(+), 583 deletions(-) delete mode 100644 .roo/iterate-cli.ts delete mode 100644 .roo/iterations/PM-CLEANUP-20250412.json delete mode 100644 .roo/iterations/PM-STATE-FIX-20250412.json delete mode 100644 .roo/iterations/task_4d3f7a2e-8c1b-4f9d-b5e2-9c1d8f3a6b4d.json delete mode 100644 .roo/iterations/task_e2e_analysis_20250412.json create mode 100644 .roomodes create mode 100644 src/__mocks__/fs/promises.ts delete mode 100644 src/utils/__tests__/git.test.js.map delete mode 100644 src/utils/git.js.map delete mode 100644 webview-ui/src/components/package-manager/state/useStateManager.ts delete mode 100644 webview-ui/src/i18n.ts diff --git a/.roo/iterate-cli.ts b/.roo/iterate-cli.ts deleted file mode 100644 index 4eb4102b3a..0000000000 --- a/.roo/iterate-cli.ts +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/env node -import { program } from "commander" -import { taskManager } from "./task-manager" -import { execSync } from "child_process" - -program.name("iterate").description("CLI to manage task iterations") - -program - .command("create ") - .description("Create a new iteration") - .requiredOption("-d, --description ", "Task description") - .action(async (taskId: string, options: { description: string }) => { - try { - await taskManager.createIteration(taskId, options.description) - console.log(`Created iteration: ${taskId}`) - } catch (error) { - console.error("Failed to create iteration:", error) - process.exit(1) - } - }) - -program - .command("list") - .description("List all iterations") - .action(async () => { - try { - const iterations = await taskManager.listIterations() - console.log("Available iterations:") - for (const taskId of iterations) { - const task = await taskManager.getIteration(taskId) - if (task) { - console.log(`- ${taskId}: ${task.description} (${task.current_state.status})`) - } - } - } catch (error) { - console.error("Failed to list iterations:", error) - process.exit(1) - } - }) - -program - .command("status ") - .description("Show iteration status") - .action(async (taskId: string) => { - try { - const task = await taskManager.getIteration(taskId) - if (!task) { - console.log("No such iteration") - return - } - - console.log(`Iteration: ${task.task_id}`) - console.log(`Description: ${task.description}`) - console.log(`Status: ${task.current_state.status}`) - - if (task.checkpoints.length > 0) { - console.log("\nCheckpoints:") - task.checkpoints.forEach((checkpoint, i) => { - console.log(`${i + 1}. ${checkpoint.description}`) - console.log(` Changes: ${checkpoint.changes.join(", ")}`) - console.log(` Timestamp: ${checkpoint.timestamp}`) - }) - } - - if (task.test_results) { - console.log("\nTest results:") - console.log( - `- Unit tests: ${task.test_results.unit_tests.passing} passing, ${task.test_results.unit_tests.failing} failing`, - ) - console.log(`- Linting: ${task.test_results.linting}`) - console.log(`- Manual testing: ${task.test_results.manual_testing}`) - } - - if (task.current_state.final_commit) { - console.log("\nCommit info:") - console.log(`- Hash: ${task.current_state.final_commit.hash}`) - console.log(`- Message: ${task.current_state.final_commit.message}`) - console.log("- Changes:") - task.current_state.final_commit.changes.forEach((change) => { - console.log(` * ${change}`) - }) - } - } catch (error) { - console.error("Failed to get iteration status:", error) - process.exit(1) - } - }) - -program - .command("checkpoint ") - .description("Create a new checkpoint") - .requiredOption("-d, --description ", "Checkpoint description") - .requiredOption("-c, --component ", "Component being modified") - .requiredOption("--changes ", "List of changes") - .requiredOption("--risks ", "List of risks") - .requiredOption("--feedback ", "Expected user feedback") - .action(async (taskId: string, options) => { - try { - const checkpoint = { - id: `checkpoint_${Date.now()}`, - description: options.description, - component: options.component, - changes: options.changes, - risks: options.risks, - expected_feedback: options.feedback, - timestamp: new Date().toISOString(), - } - - await taskManager.addCheckpoint(taskId, checkpoint) - console.log(`Created checkpoint: ${checkpoint.id}`) - } catch (error) { - console.error("Failed to create checkpoint:", error) - process.exit(1) - } - }) - -program - .command("complete ") - .description("Complete an iteration with commit info") - .requiredOption("--message ", "Commit message") - .requiredOption("--changes ", "List of changes") - .action(async (taskId: string, options) => { - try { - const hash = execSync("git rev-parse HEAD").toString().trim() - await taskManager.completeIteration(taskId, { - hash, - message: options.message, - changes: options.changes, - }) - console.log(`Completed iteration: ${taskId}`) - } catch (error) { - console.error("Failed to complete iteration:", error) - process.exit(1) - } - }) - -program.parse() diff --git a/.roo/iterations/PM-CLEANUP-20250412.json b/.roo/iterations/PM-CLEANUP-20250412.json deleted file mode 100644 index 245dff1166..0000000000 --- a/.roo/iterations/PM-CLEANUP-20250412.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "task_id": "PM-CLEANUP-20250412", - "active_checkpoint": "", - "status": "in_progress", - "created_at": "2025-04-12T23:57:44.419Z", - "last_accessed": "2025-04-12T23:57:44.420Z", - "description": "Remove unused YamlParser implementation", - "initial_commit": "4417886324a54ad5c058813474b8a57a9859bba0", - "checkpoints": [], - "test_results": { - "unit_tests": { - "passing": 0, - "failing": 0, - "pending": 0 - }, - "linting": "", - "manual_testing": "" - }, - "pending_decisions": [], - "rollback_info": { - "full_rollback": "git reset --hard 4417886324a54ad5c058813474b8a57a9859bba0", - "partial_rollbacks": {} - } -} diff --git a/.roo/iterations/PM-STATE-FIX-20250412.json b/.roo/iterations/PM-STATE-FIX-20250412.json deleted file mode 100644 index 4682d732ef..0000000000 --- a/.roo/iterations/PM-STATE-FIX-20250412.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "task_id": "PM-STATE-FIX-20250412", - "active_checkpoint": "pm_state_fix_20250412_3", - "status": "in_progress", - "created_at": "2025-04-12T15:44:13-07:00", - "last_accessed": "2025-04-12T15:50:47-07:00", - "description": "Fix package manager state management and refresh issues", - "initial_commit": "4417886324a54ad5c058813474b8a57a9859bba0", - "checkpoints": [ - { - "id": "pm_state_fix_20250412_1", - "commit_hash": "4417886324a54ad5c058813474b8a57a9859bba0", - "description": "UI State Management", - "component": "webview-ui/src/components/package-manager/PackageManagerView.tsx", - "changes": ["Removed premature item clearing", "Fixed state update timing"], - "risks": ["Race conditions between state updates", "Stale data display during refresh"], - "expected_feedback": [ - "Items disappear and reappear during refresh", - "Refresh button gets stuck spinning", - "Old items shown after source changes" - ], - "timestamp": "2025-04-12T15:44:13-07:00" - }, - { - "id": "pm_state_fix_20250412_2", - "commit_hash": "4417886324a54ad5c058813474b8a57a9859bba0", - "description": "Error Handling", - "component": "webview-ui/src/components/package-manager/PackageManagerView.tsx", - "changes": ["Removed client-side error messages", "Improved timeout handling"], - "risks": ["Missing error feedback", "Timeout state confusion"], - "expected_feedback": ["No error message shown on failure", "UI stuck in loading state"], - "timestamp": "2025-04-12T15:45:00-07:00" - }, - { - "id": "pm_state_fix_20250412_3", - "commit_hash": "4417886324a54ad5c058813474b8a57a9859bba0", - "description": "State Reset Logic", - "component": "webview-ui/src/components/package-manager/PackageManagerView.tsx", - "changes": ["Always update items on state change", "Proper timeout cleanup"], - "risks": ["Memory leaks from timeouts", "Inconsistent state after tab switch"], - "expected_feedback": ["Items don't update after source changes", "Refresh button state incorrect"], - "timestamp": "2025-04-12T15:45:30-07:00" - } - ], - "test_results": { - "unit_tests": { - "passing": 1263, - "failing": 0, - "pending": 23 - }, - "linting": "No errors", - "manual_testing": "Confirmed working by user" - }, - "pending_decisions": [], - "rollback_info": { - "full_rollback": "git reset --hard 4417886324a54ad5c058813474b8a57a9859bba0", - "partial_rollbacks": { - "ui_state": "git checkout pm_state_fix_20250412_1", - "error_handling": "git checkout pm_state_fix_20250412_2", - "state_reset": "git checkout pm_state_fix_20250412_3" - } - } -} diff --git a/.roo/iterations/task_4d3f7a2e-8c1b-4f9d-b5e2-9c1d8f3a6b4d.json b/.roo/iterations/task_4d3f7a2e-8c1b-4f9d-b5e2-9c1d8f3a6b4d.json deleted file mode 100644 index 2098b15691..0000000000 --- a/.roo/iterations/task_4d3f7a2e-8c1b-4f9d-b5e2-9c1d8f3a6b4d.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "task_id": "4d3f7a2e-8c1b-4f9d-b5e2-9c1d8f3a6b4d", - "description": "Rename prepare-for-commit routine to iterate", - "created_at": "2025-04-12T17:32:55-07:00", - "checkpoints": [ - { - "id": "checkpoint_1", - "description": "Rename files and directories", - "changes": [ - "Renamed prepare_logs to iterations", - "Renamed prepare-cli.ts to iterate-cli.ts", - "Updated package.json with new names" - ], - "risks": [ - "Breaking existing task logs", - "Path references might be incorrect", - "Package dependencies might need updates" - ], - "expected_feedback": [ - "CLI commands not working", - "Missing or inaccessible logs", - "Build errors from renamed paths" - ], - "timestamp": "2025-04-12T17:33:01-07:00" - }, - { - "id": "checkpoint_2", - "description": "Update task manager implementation", - "changes": [ - "Renamed methods to use 'iteration' terminology", - "Improved TypeScript types", - "Added better error handling", - "Simplified file operations" - ], - "risks": [ - "Type mismatches with existing code", - "Regression in error handling", - "Data format inconsistencies" - ], - "expected_feedback": [ - "Type errors in TypeScript", - "Unexpected error messages", - "Missing or incorrect data in logs" - ], - "timestamp": "2025-04-12T17:33:28-07:00" - }, - { - "id": "checkpoint_3", - "description": "Update CLI interface", - "changes": [ - "Renamed CLI commands to use new terminology", - "Improved command structure", - "Added better error messages", - "Updated command documentation" - ], - "risks": [ - "Breaking existing scripts", - "Confusing user experience during transition", - "Missing command functionality" - ], - "expected_feedback": [ - "CLI commands not recognized", - "Unclear error messages", - "Missing features from old interface" - ], - "timestamp": "2025-04-12T17:33:52-07:00" - } - ], - "current_state": { - "status": "completed", - "summary": "Successfully renamed prepare-for-commit routine to iterate with improved implementation", - "final_commit": { - "hash": "61c9480b", - "message": "refactor: rename prepare-for-commit to iterate", - "changes": [ - "Renamed prepare_logs to iterations", - "Updated task manager to use new terminology", - "Simplified CLI interface", - "Added better TypeScript types", - "Improved error handling" - ] - } - } -} diff --git a/.roo/iterations/task_e2e_analysis_20250412.json b/.roo/iterations/task_e2e_analysis_20250412.json deleted file mode 100644 index f7f51366df..0000000000 --- a/.roo/iterations/task_e2e_analysis_20250412.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "task_id": "e2e_analysis_20250412", - "description": "Analyze value of package manager e2e tests vs unit tests", - "created_at": "2025-04-12T17:37:45-07:00", - "checkpoints": [ - { - "id": "checkpoint_1", - "description": "Analysis of test coverage and complexity", - "component": "e2e/src/suite/package-manager.test.ts, src/__mocks__/vscode.js", - "findings": [ - { - "category": "Unit Test Coverage", - "details": [ - "GitFetcher tests - handles repository cloning and updates", - "MetadataScanner tests - validates component discovery", - "RepositoryStructureValidation tests - ensures correct file structure", - "Schema validation tests - verifies metadata format", - "ParsePackageManagerItems tests - checks item parsing logic", - "GitCommandQuoting tests - ensures safe command handling" - ] - }, - { - "category": "E2E Test Coverage", - "details": [ - "Real cache location testing", - "Package metadata with external items", - "Optional fields handling", - "Invalid source handling", - "Missing metadata handling", - "Localized metadata support" - ] - } - ] - }, - { - "id": "checkpoint_2", - "description": "Implementation of enhanced unit tests", - "component": "src/services/package-manager/__tests__/enhanced/*.test.ts", - "changes": [ - { - "file": "GitFetcher.test.ts", - "improvements": [ - "Added proper VSCode extension context mocking", - "Enhanced cache directory testing", - "Added network error handling tests", - "Added rate limiting tests" - ] - }, - { - "file": "MetadataScanner.test.ts", - "improvements": [ - "Added comprehensive localization testing", - "Enhanced external items validation", - "Added proper TypeScript types", - "Improved error case coverage" - ] - }, - { - "file": "RepositoryStructureValidation.test.ts", - "improvements": [ - "Added proper fs.Stats mocking", - "Enhanced directory structure validation", - "Added security validation tests", - "Improved error handling coverage" - ] - } - ] - }, - { - "id": "checkpoint_3", - "description": "Implementation of changes", - "completed_at": "2025-04-12T17:48:01-07:00", - "changes_made": [ - "Removed e2e/src/suite/package-manager.test.ts", - "Reverted src/__mocks__/vscode.js to simpler version", - "Added enhanced unit test files with proper TypeScript support", - "Fixed all TypeScript errors in new tests" - ], - "commit": { - "hash": "7a62bc50", - "message": "refactor: remove package manager e2e tests in favor of enhanced unit tests", - "stats": { - "files_changed": 7, - "insertions": 496, - "deletions": 466 - } - } - } - ], - "current_state": { - "status": "completed", - "summary": "Successfully replaced e2e tests with enhanced unit tests that provide better coverage, improved maintainability, and reduced complexity. The new tests cover all previous e2e scenarios while adding better error handling, proper TypeScript support, and comprehensive validation of edge cases." - } -} diff --git a/.roomodes b/.roomodes new file mode 100644 index 0000000000..9d1719fa31 --- /dev/null +++ b/.roomodes @@ -0,0 +1,40 @@ +{ + "customModes": [ + { + "slug": "test", + "name": "Test", + "roleDefinition": "You are Roo, a Jest testing specialist with deep expertise in:\n- Writing and maintaining Jest test suites\n- Test-driven development (TDD) practices\n- Mocking and stubbing with Jest\n- Integration testing strategies\n- TypeScript testing patterns\n- Code coverage analysis\n- Test performance optimization\n\nYour focus is on maintaining high test quality and coverage across the codebase, working primarily with:\n- Test files in __tests__ directories\n- Mock implementations in __mocks__\n- Test utilities and helpers\n- Jest configuration and setup\n\nYou ensure tests are:\n- Well-structured and maintainable\n- Following Jest best practices\n- Properly typed with TypeScript\n- Providing meaningful coverage\n- Using appropriate mocking strategies", + "groups": [ + "read", + "browser", + "command", + [ + "edit", + { + "fileRegex": "(__tests__/.*|__mocks__/.*|\\.test\\.(ts|tsx|js|jsx)$|/test/.*|jest\\.config\\.(js|ts)$)", + "description": "Test files, mocks, and Jest configuration" + } + ] + ], + "customInstructions": "When writing tests:\n- Always use describe/it blocks for clear test organization\n- Include meaningful test descriptions\n- Use beforeEach/afterEach for proper test isolation\n- Implement proper error cases\n- Add JSDoc comments for complex test scenarios\n- Ensure mocks are properly typed\n- Verify both positive and negative test cases" + }, + { + "slug": "translate", + "name": "Translate", + "roleDefinition": "You are Roo, a linguistic specialist focused on translating and managing localization files. Your responsibility is to help maintain and update translation files for the application, ensuring consistency and accuracy across all language resources.", + "customInstructions": "# 1. SUPPORTED LANGUAGES AND LOCATION\n- Localize all strings into the following locale files: ca, de, en, es, fr, hi, it, ja, ko, pl, pt-BR, tr, vi, zh-CN, zh-TW\n- The VSCode extension has two main areas that require localization:\n * Core Extension: src/i18n/locales/ (extension backend)\n * WebView UI: webview-ui/src/i18n/locales/ (user interface)\n\n# 2. VOICE, STYLE AND TONE\n- Always use informal speech (e.g., \"du\" instead of \"Sie\" in German) for all translations\n- Maintain a direct and concise style that mirrors the tone of the original text\n- Carefully account for colloquialisms and idiomatic expressions in both source and target languages\n- Aim for culturally relevant and meaningful translations rather than literal translations\n- Preserve the personality and voice of the original content\n- Use natural-sounding language that feels native to speakers of the target language\n- Don't translate the word \"token\" as it means something specific in English that all languages will understand\n- Don't translate domain-specific words (especially technical terms like \"Prompt\") that are commonly used in English in the target language\n\n# 3. CORE EXTENSION LOCALIZATION (src/)\n- Located in src/i18n/locales/\n- NOT ALL strings in core source need internationalization - only user-facing messages\n- Internal error messages, debugging logs, and developer-facing messages should remain in English\n- The t() function is used with namespaces like 'core:errors.missingToolParameter'\n- Be careful when modifying interpolation variables; they must remain consistent across all translations\n- Some strings in formatResponse.ts are intentionally not internationalized since they're internal\n- When updating strings in core.json, maintain all existing interpolation variables\n- Check string usages in the codebase before making changes to ensure you're not breaking functionality\n\n# 4. WEBVIEW UI LOCALIZATION (webview-ui/src/)\n- Located in webview-ui/src/i18n/locales/\n- Uses standard React i18next patterns with the useTranslation hook\n- All user interface strings should be internationalized\n- Always use the Trans component with named components for text with embedded components\n\n example:\n\n`\"changeSettings\": \"You can always change this at the bottom of the settings\",`\n\n```\n \n }}\n />\n```\n\n# 5. TECHNICAL IMPLEMENTATION\n- Use namespaces to organize translations logically\n- Handle pluralization using i18next's built-in capabilities\n- Implement proper interpolation for variables using {{variable}} syntax\n- Don't include defaultValue. The `en` translations are the fallback\n- Always use apply_diff instead of write_to_file when editing existing translation files (much faster and more reliable)\n- When using apply_diff, carefully identify the exact JSON structure to edit to avoid syntax errors\n- Placeholders (like {{variable}}) must remain exactly identical to the English source to maintain code integration and prevent syntax errors\n\n# 6. WORKFLOW AND APPROACH\n- First add or modify English strings, then ask for confirmation before translating to all other languages\n- Use this process for each localization task:\n 1. Identify where the string appears in the UI/codebase\n 2. Understand the context and purpose of the string\n 3. Update English translation first\n 4. Create appropriate translations for all other supported languages\n 5. Validate your changes with the missing translations script\n- Flag or comment if an English source string is incomplete (\"please see this...\") to avoid truncated or unclear translations\n- For UI elements, distinguish between:\n * Button labels: Use short imperative commands (\"Save\", \"Cancel\")\n * Tooltip text: Can be slightly more descriptive\n- Preserve the original perspective: If text is a user command directed at the software, ensure the translation maintains this direction, avoiding language that makes it sound like an instruction from the system to the user\n\n# 7. COMMON PITFALLS TO AVOID\n- Switching between formal and informal addressing styles - always stay informal (\"du\" not \"Sie\")\n- Translating or altering technical terms and brand names that should remain in English\n- Modifying or removing placeholders like {{variable}} - these must remain identical\n- Translating domain-specific terms that are commonly used in English in the target language\n- Changing the meaning or nuance of instructions or error messages\n- Forgetting to maintain consistent terminology throughout the translation\n\n# 8. QUALITY ASSURANCE\n- Maintain consistent terminology across all translations\n- Respect the JSON structure of translation files\n- Watch for placeholders and preserve them in translations\n- Be mindful of text length in UI elements when translating to languages that might require more characters\n- Use context-aware translations when the same string has different meanings\n- Always validate your translation work by running the missing translations script:\n ```\n node scripts/find-missing-translations.js\n ```\n- Address any missing translations identified by the script to ensure complete coverage across all locales\n\n# 9. TRANSLATOR'S CHECKLIST\n- ✓ Used informal tone consistently (\"du\" not \"Sie\")\n- ✓ Preserved all placeholders exactly as in the English source\n- ✓ Maintained consistent terminology with existing translations\n- ✓ Kept technical terms and brand names unchanged where appropriate\n- ✓ Preserved the original perspective (user→system vs system→user)\n- ✓ Adapted the text appropriately for UI context (buttons vs tooltips)", + "groups": [ + "read", + "command", + [ + "edit", + { + "fileRegex": "(.*\\.(md|ts|tsx|js|jsx)$|.*\\.json$)", + "description": "Source code, translation files, and documentation" + } + ] + ], + "source": "project" + } + ] +} \ No newline at end of file diff --git a/esbuild.js b/esbuild.js index 6862e63557..6fc0c24729 100644 --- a/esbuild.js +++ b/esbuild.js @@ -173,7 +173,6 @@ const extensionConfig = { { name: "alias-plugin", setup(build) { - // Handle pkce-challenge alias build.onResolve({ filter: /^pkce-challenge$/ }, (args) => { return { path: require.resolve("pkce-challenge/dist/index.browser.js") } }) diff --git a/src/__mocks__/fs/promises.ts b/src/__mocks__/fs/promises.ts new file mode 100644 index 0000000000..b037cd2457 --- /dev/null +++ b/src/__mocks__/fs/promises.ts @@ -0,0 +1,210 @@ +// Mock file system data +const mockFiles = new Map() +const mockDirectories = new Set() + +// Initialize base test directories +const baseTestDirs = [ + "/mock", + "/mock/extension", + "/mock/extension/path", + "/mock/storage", + "/mock/storage/path", + "/mock/settings", + "/mock/settings/path", + "/mock/mcp", + "/mock/mcp/path", + "/test", + "/test/path", + "/test/storage", + "/test/storage/path", + "/test/storage/path/settings", + "/test/extension", + "/test/extension/path", + "/test/global-storage", + "/test/log/path", +] + +// Helper function to format instructions +const formatInstructions = (sections: string[]): string => { + const joinedSections = sections.filter(Boolean).join("\n\n") + return joinedSections + ? ` +==== + +USER'S CUSTOM INSTRUCTIONS + +The following additional instructions are provided by the user, and should be followed to the best of your ability without interfering with the TOOL USE guidelines. + +${joinedSections}` + : "" +} + +// Helper function to format rule content +const formatRuleContent = (ruleFile: string, content: string): string => { + return `Rules:\n# Rules from ${ruleFile}:\n${content}` +} + +type RuleFiles = { + ".clinerules-code": string + ".clinerules-ask": string + ".clinerules-architect": string + ".clinerules-test": string + ".clinerules-review": string + ".clinerules": string +} + +// Helper function to ensure directory exists +const ensureDirectoryExists = (path: string) => { + const parts = path.split("/") + let currentPath = "" + for (const part of parts) { + if (!part) continue + currentPath += "/" + part + mockDirectories.add(currentPath) + } +} + +const mockFs = { + readFile: jest.fn().mockImplementation(async (filePath: string, encoding?: string) => { + // Return stored content if it exists + if (mockFiles.has(filePath)) { + return mockFiles.get(filePath) + } + + // Handle rule files + const ruleFiles: RuleFiles = { + ".clinerules-code": "# Code Mode Rules\n1. Code specific rule", + ".clinerules-ask": "# Ask Mode Rules\n1. Ask specific rule", + ".clinerules-architect": "# Architect Mode Rules\n1. Architect specific rule", + ".clinerules-test": + "# Test Engineer Rules\n1. Always write tests first\n2. Get approval before modifying non-test code", + ".clinerules-review": + "# Code Reviewer Rules\n1. Provide specific examples in feedback\n2. Focus on maintainability and best practices", + ".clinerules": "# Test Rules\n1. First rule\n2. Second rule", + } + + // Check for exact file name match + const fileName = filePath.split("/").pop() + if (fileName && fileName in ruleFiles) { + return ruleFiles[fileName as keyof RuleFiles] + } + + // Check for file name in path + for (const [ruleFile, content] of Object.entries(ruleFiles)) { + if (filePath.includes(ruleFile)) { + return content + } + } + + // Handle file not found + const error = new Error(`ENOENT: no such file or directory, open '${filePath}'`) + ;(error as any).code = "ENOENT" + throw error + }), + + writeFile: jest.fn().mockImplementation(async (path: string, content: string) => { + // Ensure parent directory exists + const parentDir = path.split("/").slice(0, -1).join("/") + ensureDirectoryExists(parentDir) + mockFiles.set(path, content) + return Promise.resolve() + }), + + mkdir: jest.fn().mockImplementation(async (path: string, options?: { recursive?: boolean }) => { + // Always handle recursive creation + const parts = path.split("/") + let currentPath = "" + + // For recursive or test/mock paths, create all parent directories + if (options?.recursive || path.startsWith("/test") || path.startsWith("/mock")) { + for (const part of parts) { + if (!part) continue + currentPath += "/" + part + mockDirectories.add(currentPath) + } + return Promise.resolve() + } + + // For non-recursive paths, verify parent exists + for (let i = 0; i < parts.length - 1; i++) { + if (!parts[i]) continue + currentPath += "/" + parts[i] + if (!mockDirectories.has(currentPath)) { + const error = new Error(`ENOENT: no such file or directory, mkdir '${path}'`) + ;(error as any).code = "ENOENT" + throw error + } + } + + // Add the final directory + currentPath += "/" + parts[parts.length - 1] + mockDirectories.add(currentPath) + return Promise.resolve() + }), + + access: jest.fn().mockImplementation(async (path: string) => { + // Check if the path exists in either files or directories + if (mockFiles.has(path) || mockDirectories.has(path) || path.startsWith("/test")) { + return Promise.resolve() + } + const error = new Error(`ENOENT: no such file or directory, access '${path}'`) + ;(error as any).code = "ENOENT" + throw error + }), + + rename: jest.fn().mockImplementation(async (oldPath: string, newPath: string) => { + // Check if the old file exists + if (mockFiles.has(oldPath)) { + // Copy content to new path + const content = mockFiles.get(oldPath) + mockFiles.set(newPath, content) + // Delete old file + mockFiles.delete(oldPath) + return Promise.resolve() + } + // If old file doesn't exist, throw an error + const error = new Error(`ENOENT: no such file or directory, rename '${oldPath}'`) + ;(error as any).code = "ENOENT" + throw error + }), + + constants: jest.requireActual("fs").constants, + + // Expose mock data for test assertions + _mockFiles: mockFiles, + _mockDirectories: mockDirectories, + + // Helper to set up initial mock data + _setInitialMockData: () => { + // Set up default MCP settings + mockFiles.set( + "/mock/settings/path/mcp_settings.json", + JSON.stringify({ + mcpServers: { + "test-server": { + command: "node", + args: ["test.js"], + disabled: false, + alwaysAllow: ["existing-tool"], + }, + }, + }), + ) + + // Ensure all base directories exist + baseTestDirs.forEach((dir) => { + const parts = dir.split("/") + let currentPath = "" + for (const part of parts) { + if (!part) continue + currentPath += "/" + part + mockDirectories.add(currentPath) + } + }) + }, +} + +// Initialize mock data +mockFs._setInitialMockData() + +module.exports = mockFs diff --git a/src/core/__tests__/Cline.test.ts b/src/core/__tests__/Cline.test.ts index fdbc49124b..3068085425 100644 --- a/src/core/__tests__/Cline.test.ts +++ b/src/core/__tests__/Cline.test.ts @@ -476,50 +476,167 @@ describe("Cline", () => { }) it("should handle image blocks based on model capabilities", async () => { - // Create a single test instance with image support - const [cline] = Cline.create({ - provider: mockProvider, - apiConfiguration: { - ...mockApiConfig, - apiModelId: "claude-3-sonnet", - }, - task: "test task", - }) + // Create two configurations - one with image support, one without + const configWithImages = { + ...mockApiConfig, + apiModelId: "claude-3-sonnet", + } + const configWithoutImages = { + ...mockApiConfig, + apiModelId: "gpt-3.5-turbo", + } - // Mock image support - jest.spyOn(cline.api, "getModel").mockReturnValue({ - id: "claude-3-sonnet", - info: { supportsImages: true } as ModelInfo, - }) - - // Set up simple conversation history - cline.apiConversationHistory = [ + // Create test conversation history with mixed content + const conversationHistory: (Anthropic.MessageParam & { ts?: number })[] = [ { - role: "user", + role: "user" as const, content: [ - { type: "text", text: "Here is an image" }, - { type: "image", source: { type: "base64", media_type: "image/jpeg", data: "test" } }, + { + type: "text" as const, + text: "Here is an image", + } satisfies Anthropic.TextBlockParam, + { + type: "image" as const, + source: { + type: "base64" as const, + media_type: "image/jpeg", + data: "base64data", + }, + } satisfies Anthropic.ImageBlockParam, + ], + }, + { + role: "assistant" as const, + content: [ + { + type: "text" as const, + text: "I see the image", + } satisfies Anthropic.TextBlockParam, ], }, ] - // Mock createMessage - const createMessageSpy = jest.fn().mockReturnValue( - (async function* () { - yield { type: "text", text: "response" } - })(), - ) - jest.spyOn(cline.api, "createMessage").mockImplementation(createMessageSpy) + // Test with model that supports images + const [clineWithImages, taskWithImages] = Cline.create({ + provider: mockProvider, + apiConfiguration: configWithImages, + task: "test task", + }) - // Trigger request - await cline.recursivelyMakeClineRequests([{ type: "text", text: "test" }]) + // Mock the model info to indicate image support + jest.spyOn(clineWithImages.api, "getModel").mockReturnValue({ + id: "claude-3-sonnet", + info: { + supportsImages: true, + supportsPromptCache: true, + supportsComputerUse: true, + contextWindow: 200000, + maxTokens: 4096, + inputPrice: 0.25, + outputPrice: 0.75, + } as ModelInfo, + }) - // Verify image block was preserved - const calls = createMessageSpy.mock.calls - expect(calls[0][1][0].content[1]).toHaveProperty("type", "image") + clineWithImages.apiConversationHistory = conversationHistory - // Clean up - await cline.abortTask(true) + // Test with model that doesn't support images + const [clineWithoutImages, taskWithoutImages] = Cline.create({ + provider: mockProvider, + apiConfiguration: configWithoutImages, + task: "test task", + }) + + // Mock the model info to indicate no image support + jest.spyOn(clineWithoutImages.api, "getModel").mockReturnValue({ + id: "gpt-3.5-turbo", + info: { + supportsImages: false, + supportsPromptCache: false, + supportsComputerUse: false, + contextWindow: 16000, + maxTokens: 2048, + inputPrice: 0.1, + outputPrice: 0.2, + } as ModelInfo, + }) + + clineWithoutImages.apiConversationHistory = conversationHistory + + // Mock abort state for both instances + Object.defineProperty(clineWithImages, "abort", { + get: () => false, + set: () => {}, + configurable: true, + }) + + Object.defineProperty(clineWithoutImages, "abort", { + get: () => false, + set: () => {}, + configurable: true, + }) + + // Mock environment details and context loading + jest.spyOn(clineWithImages as any, "getEnvironmentDetails").mockResolvedValue("") + jest.spyOn(clineWithoutImages as any, "getEnvironmentDetails").mockResolvedValue("") + jest.spyOn(clineWithImages as any, "loadContext").mockImplementation(async (content) => [content, ""]) + jest.spyOn(clineWithoutImages as any, "loadContext").mockImplementation(async (content) => [ + content, + "", + ]) + + // Set up mock streams + const mockStreamWithImages = (async function* () { + yield { type: "text", text: "test response" } + })() + + const mockStreamWithoutImages = (async function* () { + yield { type: "text", text: "test response" } + })() + + // Set up spies + const imagesSpy = jest.fn().mockReturnValue(mockStreamWithImages) + const noImagesSpy = jest.fn().mockReturnValue(mockStreamWithoutImages) + + jest.spyOn(clineWithImages.api, "createMessage").mockImplementation(imagesSpy) + jest.spyOn(clineWithoutImages.api, "createMessage").mockImplementation(noImagesSpy) + + // Set up conversation history with images + clineWithImages.apiConversationHistory = [ + { + role: "user", + content: [ + { type: "text", text: "Here is an image" }, + { type: "image", source: { type: "base64", media_type: "image/jpeg", data: "base64data" } }, + ], + }, + ] + + clineWithImages.abandoned = true + await taskWithImages.catch(() => {}) + + clineWithoutImages.abandoned = true + await taskWithoutImages.catch(() => {}) + + // Trigger API requests + await clineWithImages.recursivelyMakeClineRequests([{ type: "text", text: "test request" }]) + await clineWithoutImages.recursivelyMakeClineRequests([{ type: "text", text: "test request" }]) + + // Get the calls + const imagesCalls = imagesSpy.mock.calls + const noImagesCalls = noImagesSpy.mock.calls + + // Verify model with image support preserves image blocks + expect(imagesCalls[0][1][0].content).toHaveLength(2) + expect(imagesCalls[0][1][0].content[0]).toEqual({ type: "text", text: "Here is an image" }) + expect(imagesCalls[0][1][0].content[1]).toHaveProperty("type", "image") + + // Verify model without image support converts image blocks to text + expect(noImagesCalls[0][1][0].content).toHaveLength(2) + expect(noImagesCalls[0][1][0].content[0]).toEqual({ type: "text", text: "Here is an image" }) + expect(noImagesCalls[0][1][0].content[1]).toEqual({ + type: "text", + text: "[Referenced image in conversation]", + }) }) it.skip("should handle API retry with countdown", async () => { diff --git a/src/i18n/setup.ts b/src/i18n/setup.ts index 2d567e5096..058f357b46 100644 --- a/src/i18n/setup.ts +++ b/src/i18n/setup.ts @@ -24,7 +24,7 @@ if (!isTestEnv) { const fs = require("fs") const path = require("path") - const localesDir = path.join(__dirname, "locales") + const localesDir = path.join(__dirname, "i18n", "locales") try { // Find all language directories diff --git a/src/utils/__tests__/git.test.js.map b/src/utils/__tests__/git.test.js.map deleted file mode 100644 index 959511f6c4..0000000000 --- a/src/utils/__tests__/git.test.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"git.test.js","sourceRoot":"","sources":["git.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/utils/git.js.map b/src/utils/git.js.map deleted file mode 100644 index 6f723294cc..0000000000 --- a/src/utils/git.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"git.js","sourceRoot":"","sources":["git.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/webview-ui/src/components/package-manager/components/PackageManagerItemCard.tsx b/webview-ui/src/components/package-manager/components/PackageManagerItemCard.tsx index 186bc9b11a..fa773f39ce 100644 --- a/webview-ui/src/components/package-manager/components/PackageManagerItemCard.tsx +++ b/webview-ui/src/components/package-manager/components/PackageManagerItemCard.tsx @@ -6,7 +6,7 @@ import { groupItemsByType, GroupedItems } from "../utils/grouping" import { ExpandableSection } from "./ExpandableSection" import { TypeGroup } from "./TypeGroup" import { ViewState } from "../PackageManagerViewStateManager" -import { t } from "@/i18n" +import { useAppTranslation } from "@/i18n/TranslationContext" interface PackageManagerItemCardProps { item: PackageManagerItem @@ -23,6 +23,7 @@ export const PackageManagerItemCard: React.FC = ({ activeTab, setActiveTab, }) => { + const { t } = useAppTranslation() const isValidUrl = (urlString: string): boolean => { try { new URL(urlString) diff --git a/webview-ui/src/components/package-manager/components/TypeGroup.tsx b/webview-ui/src/components/package-manager/components/TypeGroup.tsx index 0315e93346..de1008a248 100644 --- a/webview-ui/src/components/package-manager/components/TypeGroup.tsx +++ b/webview-ui/src/components/package-manager/components/TypeGroup.tsx @@ -1,6 +1,6 @@ import React from "react" import { cn } from "@/lib/utils" -import { t } from "@/i18n" +import { useAppTranslation } from "@/i18n/TranslationContext" interface TypeGroupProps { type: string @@ -18,6 +18,7 @@ interface TypeGroupProps { } export const TypeGroup: React.FC = ({ type, items, className }) => { + const { t } = useAppTranslation() const getTypeLabel = (type: string) => { switch (type) { case "mode": diff --git a/webview-ui/src/components/package-manager/state/useStateManager.ts b/webview-ui/src/components/package-manager/state/useStateManager.ts deleted file mode 100644 index b1f0dd0248..0000000000 --- a/webview-ui/src/components/package-manager/state/useStateManager.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { useCallback, useReducer } from "react" -import { PackageManagerItem, PackageManagerSource } from "@services/package-manager" -import { PackageManagerViewStateManager } from "./PackageManagerViewStateManager" - -interface State { - allItems: PackageManagerItem[] - displayItems: PackageManagerItem[] - isFetching: boolean - activeTab: "browse" | "sources" - filters: { - search: string - type: string - tags: string[] - } - sortConfig: { - by: "name" | "lastUpdated" - order: "asc" | "desc" - } - sources: PackageManagerSource[] - refreshingUrls: string[] -} - -type Action = - | { type: "FETCH_ITEMS" } - | { type: "SET_ACTIVE_TAB"; payload: { tab: "browse" | "sources" } } - | { type: "UPDATE_FILTERS"; payload: { filters: Partial } } - | { type: "UPDATE_SORT"; payload: { sortConfig: Partial } } - | { type: "UPDATE_SOURCES"; payload: { sources: PackageManagerSource[] } } - | { type: "REFRESH_SOURCE"; payload: { url: string } } - -const initialState: State = { - allItems: [], - displayItems: [], - isFetching: false, - activeTab: "browse", - filters: { - search: "", - type: "", - tags: [], - }, - sortConfig: { - by: "name", - order: "asc", - }, - sources: [], - refreshingUrls: [], -} - -const stateManager = new PackageManagerViewStateManager() - -function reducer(state: State, action: Action): State { - switch (action.type) { - case "FETCH_ITEMS": - return { - ...state, - isFetching: true, - } - - case "SET_ACTIVE_TAB": - return { - ...state, - activeTab: action.payload.tab, - } - - case "UPDATE_FILTERS": - const newFilters = { - ...state.filters, - ...action.payload.filters, - } - stateManager.setItems(state.allItems) - stateManager.setFilters(newFilters) - return { - ...state, - filters: newFilters, - displayItems: stateManager.getFilteredAndSortedItems(), - } - - case "UPDATE_SORT": - const newSortConfig = { - ...state.sortConfig, - ...action.payload.sortConfig, - } - stateManager.setSortBy(newSortConfig.by) - stateManager.setSortOrder(newSortConfig.order) - stateManager.setItems(state.allItems) - return { - ...state, - sortConfig: newSortConfig, - displayItems: stateManager.getFilteredAndSortedItems(), - } - - case "UPDATE_SOURCES": - return { - ...state, - sources: action.payload.sources, - } - - case "REFRESH_SOURCE": - return { - ...state, - refreshingUrls: [...state.refreshingUrls, action.payload.url], - } - - default: - return state - } -} - -export function useStateManager() { - const [state, dispatch] = useReducer(reducer, initialState) - - const transition = useCallback((action: Action) => { - dispatch(action) - }, []) - - return [state, { transition }] as const -} diff --git a/webview-ui/src/i18n.ts b/webview-ui/src/i18n.ts deleted file mode 100644 index e525756648..0000000000 --- a/webview-ui/src/i18n.ts +++ /dev/null @@ -1,20 +0,0 @@ -import i18next from "i18next" -import { initReactI18next } from "react-i18next" -import packageManagerEn from "../../src/i18n/locales/en/package_manager.json" - -// Initialize i18next -i18next.use(initReactI18next).init({ - resources: { - en: { - package_manager: packageManagerEn, - }, - }, - lng: "en", - fallbackLng: "en", - interpolation: { - escapeValue: false, - }, -}) - -export const t = i18next.t -export default i18next diff --git a/webview-ui/src/utils/context-mentions.ts b/webview-ui/src/utils/context-mentions.ts index 93ba4f2904..5d240d8fd2 100644 --- a/webview-ui/src/utils/context-mentions.ts +++ b/webview-ui/src/utils/context-mentions.ts @@ -1,13 +1,13 @@ import { mentionRegex } from "../../../src/shared/context-mentions" import { Fzf } from "fzf" import { ModeConfig } from "../../../src/shared/modes" +import * as path from "path" export interface SearchResult { path: string type: "file" | "folder" label?: string } - export function insertMention( text: string, position: number, @@ -231,13 +231,11 @@ export function getContextMenuOptions( // Convert search results to queryItems format const searchResultItems = dynamicSearchResults.map((result) => { const formattedPath = result.path.startsWith("/") ? result.path : `/${result.path}` - const pathParts = formattedPath.split("/") - const fileName = pathParts[pathParts.length - 1] return { type: result.type === "folder" ? ContextMenuOptionType.Folder : ContextMenuOptionType.File, value: formattedPath, - label: result.label || fileName, + label: result.label || path.basename(result.path), description: formattedPath, } })