diff --git a/.changeset/clean-taxis-feel.md b/.changeset/clean-taxis-feel.md new file mode 100644 index 0000000000..4c8d60f3ef --- /dev/null +++ b/.changeset/clean-taxis-feel.md @@ -0,0 +1,6 @@ +--- +"roo-cline": patch +--- + +Add support for `gemini-2.5-flash-preview-05-20` on the Vertex provider +Add support for `gemini-2.5-flash-preview-05-20:thinking` on the Vertex provider diff --git a/.changeset/curly-plants-pull.md b/.changeset/curly-plants-pull.md new file mode 100644 index 0000000000..0f425cb859 --- /dev/null +++ b/.changeset/curly-plants-pull.md @@ -0,0 +1,11 @@ +--- +"roo-cline": patch +--- + +New models for the Chutes provider: + +- Qwen/Qwen3-235B-A22B +- Qwen/Qwen3-32B +- Qwen/Qwen3-30B-A3B +- Qwen/Qwen3-14B +- Qwen/Qwen3-8B diff --git a/.changeset/fair-houses-deny.md b/.changeset/fair-houses-deny.md new file mode 100644 index 0000000000..eaabea6749 --- /dev/null +++ b/.changeset/fair-houses-deny.md @@ -0,0 +1,5 @@ +--- +"roo-cline": patch +--- + +Shows in the UI when the context is intelligently condensed diff --git a/.changeset/four-emus-invite.md b/.changeset/four-emus-invite.md new file mode 100644 index 0000000000..34c5ebf5af --- /dev/null +++ b/.changeset/four-emus-invite.md @@ -0,0 +1,5 @@ +--- +"roo-cline": patch +--- + +Add a UI indicator while the context is condensing diff --git a/.changeset/fruity-spoons-smash.md b/.changeset/fruity-spoons-smash.md new file mode 100644 index 0000000000..10546c5bd1 --- /dev/null +++ b/.changeset/fruity-spoons-smash.md @@ -0,0 +1,5 @@ +--- +"roo-cline": minor +--- + +Added an auto-approve API request limit setting similar to Cline diff --git a/.changeset/gold-meals-tell.md b/.changeset/gold-meals-tell.md new file mode 100644 index 0000000000..3cc54103d5 --- /dev/null +++ b/.changeset/gold-meals-tell.md @@ -0,0 +1,5 @@ +--- +"roo-cline": patch +--- + +Use YAML as default custom modes format diff --git a/.changeset/seven-kids-return.md b/.changeset/seven-kids-return.md new file mode 100644 index 0000000000..d4da5cbc03 --- /dev/null +++ b/.changeset/seven-kids-return.md @@ -0,0 +1,10 @@ +--- +"roo-cline": minor +--- + +Adds refresh models button for Unbound provider +Adds a button above model picker to refresh models based on the current API Key. + +1. Clicking the refresh button saves the API Key and calls /models endpoint using that. +2. Gets the new models and updates the current model if it is invalid for the given API Key. +3. The refresh button also flushes existing Unbound models and refetches them. diff --git a/.changeset/slimy-paths-design.md b/.changeset/slimy-paths-design.md new file mode 100644 index 0000000000..7a46f4b7d0 --- /dev/null +++ b/.changeset/slimy-paths-design.md @@ -0,0 +1,5 @@ +--- +"roo-cline": patch +--- + +Fixed bug that prevented some file links from working in the Agent output diff --git a/.changeset/tired-dogs-worry.md b/.changeset/tired-dogs-worry.md new file mode 100644 index 0000000000..96bc50f854 --- /dev/null +++ b/.changeset/tired-dogs-worry.md @@ -0,0 +1,5 @@ +--- +"roo-cline": patch +--- + +Adds a button to intelligently condense the context window diff --git a/.changeset/young-dancers-join.md b/.changeset/young-dancers-join.md new file mode 100644 index 0000000000..d6aab3351e --- /dev/null +++ b/.changeset/young-dancers-join.md @@ -0,0 +1,5 @@ +--- +"roo-cline": patch +--- + +Fix settings import when global settings are omitted diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 93f9eeaa5b..2a350d20e8 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,3 +1,3 @@ -# Ran Prettier on all files - https://github.com/RooVetGit/Roo-Code/pull/404 +# Ran Prettier on all files - https://github.com/RooCodeInc/Roo-Code/pull/404 60a0a824b96a0b326af4d8871b6903f4ddcfe114 579bdd9dbf6d2d569e5e7adb5ff6292b1e42ea34 diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 5757f05ab1..c4c2d8242e 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -2,11 +2,17 @@ name: Bug Report description: Clearly report a bug with detailed repro steps labels: ["bug"] body: + - type: markdown + attributes: + value: | + **Thanks for your report!** Please check existing issues first: + 👉 https://github.com/RooCodeInc/Roo-Code/issues + - type: input id: version attributes: label: App Version - description: Specify exactly which version you're using (e.g., v3.3.1) + description: What version of Roo Code are you using? (e.g., v3.3.1) validations: required: true @@ -14,22 +20,28 @@ body: id: provider attributes: label: API Provider - description: Choose the API provider involved - multiple: false options: - - OpenRouter - Anthropic - - Google Gemini + - AWS Bedrock + - Chutes AI - DeepSeek - - OpenAI - - OpenAI Compatible - - GCP Vertex AI - - Amazon Bedrock - - Requesty - Glama - - VS Code LM API + - Google Gemini + - Google Vertex AI + - Groq + - Human Relay Provider + - LiteLLM - LM Studio + - Mistral AI - Ollama + - OpenAI + - OpenAI Compatible + - OpenRouter + - Requesty + - Unbound + - VS Code Language Model API + - xAI (Grok) + - Not Applicable / Other validations: required: true @@ -37,44 +49,38 @@ body: id: model attributes: label: Model Used - description: Clearly specify the exact model (e.g., Claude 3.7 Sonnet) - validations: - required: true - - - type: textarea - id: what-happened - attributes: - label: Actual vs. Expected Behavior - description: Clearly state what actually happened and what you expected instead. - placeholder: Provide precise details of the issue here. + description: Exact model name (e.g., Claude 3.7 Sonnet). Use N/A if irrelevant. validations: required: true - type: textarea id: steps attributes: - label: Detailed Steps to Reproduce + label: 🔁 Steps to Reproduce description: | - List the exact steps someone must follow to reproduce this bug: - 1. Starting conditions (software state, settings, environment) - 2. Precise actions taken (every click, selection, input) - 3. Clearly observe and report outcomes - value: | - 1. - 2. - 3. + Help us see what you saw. Give clear, numbered steps: + + 1. Setup (OS, extension version, settings) + 2. Exact actions (clicks, input, files, commands) + 3. What happened after each step + + Think like you're writing a recipe. Without this, we can't reproduce the issue. validations: required: true - type: textarea - id: logs + id: what-happened attributes: - label: Relevant API Request Output - description: Paste relevant API logs or outputs here (formatted automatically as code) - render: shell + label: 💥 Outcome Summary (Optional) + description: | + Recap what went wrong in one or two lines. Use this if the bug is weird, unexpected, or needs extra context. + + Example: "Expected code to run, but got an empty response and no error." + placeholder: Expected ___, but got ___. - type: textarea - id: additional-context + id: logs attributes: - label: Additional Context - description: Include extra details, screenshots, or related issues. + label: 📄 Relevant Logs or Errors + description: Paste API logs, terminal output, or errors here. Use triple backticks (```) for code formatting. + render: shell \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 70472c2597..0351ad1930 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ blank_issues_enabled: false contact_links: - name: Feature Request - url: https://github.com/RooVetGit/Roo-Code/discussions/categories/feature-requests + url: https://github.com/RooCodeInc/Roo-Code/discussions/categories/feature-requests about: Share and vote on feature requests for Roo Code - name: Leave a Review url: https://marketplace.visualstudio.com/items?itemName=RooVeterinaryInc.roo-cline&ssr=false#review-details diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000000..062f405b83 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,76 @@ +name: Detailed Feature Proposal +description: Propose a specific, actionable feature or enhancement for implementation +labels: ["proposal", "enhancement"] +body: + - type: markdown + attributes: + value: | + **Thank you for proposing a detailed feature for Roo Code!** + + This template is for submitting specific, actionable proposals that you or others intend to implement after discussion and approval. It's a key part of our [Issue-First Approach](../../CONTRIBUTING.md). + + - **For general ideas or less defined suggestions**, please use [GitHub Discussions](https://github.com/RooCodeInc/Roo-Code/discussions/categories/feature-requests?discussions_q=is%3Aopen+category%3A%22Feature+Requests%22+sort%3Atop) first. + - **Before submitting**, please search existing [GitHub Issues](https://github.com/RooCodeInc/Roo-Code/issues) and [Discussions](https://github.com/RooCodeInc/Roo-Code/discussions) to avoid duplicates. + + For guidance or to discuss your idea, join the [Roo Code Discord](https://discord.gg/roocode) and DM **Hannes Rudolph** (`hrudolph`). + + A maintainer (especially @hannesrudolph) will review this proposal. **Do not start implementation until this proposal is approved and assigned.** + - type: textarea + id: problem-description + attributes: + label: What problem does this proposed feature solve? + description: Clearly describe the problem, use case, or opportunity this feature addresses. Why is this change needed? + placeholder: e.g., "Users currently cannot..." or "It would be beneficial if..." + validations: + required: true + + - type: textarea + id: proposed-solution + attributes: + label: Describe the proposed solution in detail + description: Provide a clear and comprehensive description of the feature or enhancement. How should it work? What are the key functionalities? + placeholder: Include details on user interaction, expected behavior, and potential impact. + validations: + required: true + + - type: textarea + id: technical-details + attributes: + label: Technical considerations or implementation details (optional) + description: If you have thoughts on how this could be implemented, or specific technical aspects to consider, please share them. + placeholder: e.g., "This might involve changes to X component..." or "We should consider Y library..." + + - type: textarea + id: alternatives-considered + attributes: + label: Describe alternatives considered (if any) + description: What other ways could this problem be solved or this functionality be achieved? Why is your proposed solution preferred? + placeholder: Briefly outline any alternative approaches and why they were not chosen. + + - type: textarea + id: additional-context + attributes: + label: Additional Context & Mockups + description: Add any other context, mockups, screenshots, or links that help illustrate the proposal. + + - type: checkboxes + id: checklist + attributes: + label: Proposal Checklist + description: Please confirm the following before submitting. + options: + - label: I have searched existing Issues and Discussions to ensure this proposal is not a duplicate. + required: true + - label: This proposal is for a specific, actionable change intended for implementation (not a general idea). + required: true + - label: I understand that this proposal requires review and approval before any development work begins. + required: true + + - type: checkboxes + id: willingness-to-contribute + attributes: + label: Are you interested in implementing this feature if approved? + description: (This is optional and does not affect the proposal's consideration) + options: + - label: Yes, I would like to contribute to implementing this feature. + required: false \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index de7e461cb9..e013eea277 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,35 +1,83 @@ -## Context + + +### Related GitHub Issue - + -## Implementation +Closes: # + +### Description -Some description of HOW you achieved it. Perhaps give a high level description of the program flow. Did you need to refactor something? What tradeoffs did you take? Are there things in here which you’d particularly like people to pay close attention to? +### Test Procedure + -## Screenshots +### Type of Change -| before | after | -| ------ | ----- | -| | | + -## How to Test +- [ ] 🐛 **Bug Fix**: Non-breaking change that fixes an issue. +- [ ] ✨ **New Feature**: Non-breaking change that adds functionality. +- [ ] 💥 **Breaking Change**: Fix or feature that would cause existing functionality to not work as expected. +- [ ] ♻️ **Refactor**: Code change that neither fixes a bug nor adds a feature. +- [ ] 💅 **Style**: Changes that do not affect the meaning of the code (white-space, formatting, etc.). +- [ ] 📚 **Documentation**: Updates to documentation files. +- [ ] ⚙️ **Build/CI**: Changes to the build process or CI configuration. +- [ ] 🧹 **Chore**: Other changes that don't modify `src` or test files. - + +- [ ] **Issue Linked**: This PR is linked to an approved GitHub Issue (see "Related GitHub Issue" above). +- [ ] **Scope**: My changes are focused on the linked issue (one major feature/fix per PR). +- [ ] **Self-Review**: I have performed a thorough self-review of my code. +- [ ] **Code Quality**: + - [ ] My code adheres to the project's style guidelines. + - [ ] There are no new linting errors or warnings (`npm run lint`). + - [ ] All debug code (e.g., `console.log`) has been removed. +- [ ] **Testing**: + - [ ] New and/or updated tests have been added to cover my changes. + - [ ] All tests pass locally (`npm test`). + - [ ] The application builds successfully with my changes. +- [ ] **Branch Hygiene**: My branch is up-to-date (rebased) with the `main` branch. +- [ ] **Documentation Impact**: I have considered if my changes require documentation updates (see "Documentation Updates" section below). +- [ ] **Changeset**: A changeset has been created using `npm run changeset` if this PR includes user-facing changes or dependency updates. +- [ ] **Contribution Guidelines**: I have read and agree to the [Contributor Guidelines](../CONTRIBUTING.md). -A straightforward scenario of how to test your changes will help reviewers that are not familiar with the part of the code that you are changing but want to see it in action. This section can include a description or step-by-step instructions of how to get to the state of v2 that your change affects. +### Screenshots / Videos -A "How To Test" section can look something like this: + -- Sign in with a user with tracks -- Activate `show_awesome_cat_gifs` feature (add `?feature.show_awesome_cat_gifs=1` to your URL) -- You should see a GIF with cats dancing +### Documentation Updates + -## Get in Touch +### Additional Notes - + diff --git a/.github/scripts/get_prev_version_refs.py b/.github/scripts/get_prev_version_refs.py index 09d7d4cd0b..48d535bddb 100644 --- a/.github/scripts/get_prev_version_refs.py +++ b/.github/scripts/get_prev_version_refs.py @@ -10,7 +10,7 @@ def run_git_command(command): def parse_merge_commit(line): # Parse merge commit messages like: - # "355dc82 Merge pull request #71 from RooVetGit/better-error-handling" + # "355dc82 Merge pull request #71 from RooCodeInc/better-error-handling" pattern = r"([a-f0-9]+)\s+Merge pull request #(\d+) from (.+)" match = re.match(pattern, line) if match: diff --git a/.github/workflows/build-vsix.yml b/.github/workflows/build-vsix.yml new file mode 100644 index 0000000000..ab6bd95129 --- /dev/null +++ b/.github/workflows/build-vsix.yml @@ -0,0 +1,45 @@ +name: Build VSIX + +on: + pull_request: + types: [labeled] + branches: [ main ] + +jobs: + build: + runs-on: ubuntu-latest + if: github.event.label.name == 'build' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version-file: 'package.json' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Install all dependencies + run: npm run install:all + + - name: Build Extension + run: npm run build + + - name: Upload VSIX artifact + uses: actions/upload-artifact@v4 + with: + name: extension-vsix + path: bin/*.vsix + + - name: Comment PR with artifact link + if: github.event_name == 'pull_request' + uses: peter-evans/create-or-update-comment@v4 + with: + issue-number: ${{ github.event.pull_request.number }} + body: | + Build successful! 🚀 + You can download the VSIX extension [here](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}). diff --git a/.github/workflows/code-qa.yml b/.github/workflows/code-qa.yml index 7e027d0fc9..667d0b6bf8 100644 --- a/.github/workflows/code-qa.yml +++ b/.github/workflows/code-qa.yml @@ -78,8 +78,10 @@ jobs: run: npm run install:all - name: Compile (to build and copy WASM files) run: npm run compile - - name: Run unit tests + - name: Run jest unit tests run: npx jest --silent + - name: Run vitest unit tests + run: npx vitest run --silent test-webview: runs-on: ${{ matrix.os }} diff --git a/.github/workflows/marketplace-publish.yml b/.github/workflows/marketplace-publish.yml index 0080b10687..834f38caf3 100644 --- a/.github/workflows/marketplace-publish.yml +++ b/.github/workflows/marketplace-publish.yml @@ -29,9 +29,7 @@ jobs: git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - name: Install Dependencies - run: | - npm install -g vsce ovsx - npm run install:all + run: npm run install:all - name: Create .env file run: echo "POSTHOG_API_KEY=${{ secrets.POSTHOG_API_KEY }}" >> .env - name: Package Extension diff --git a/.github/workflows/update-contributors.yml b/.github/workflows/update-contributors.yml index 18e978a07e..2fadbb83d9 100644 --- a/.github/workflows/update-contributors.yml +++ b/.github/workflows/update-contributors.yml @@ -14,10 +14,10 @@ jobs: pull-requests: write # Needed for creating PRs steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '18' cache: 'npm' diff --git a/.gitignore b/.gitignore index 1277732969..4085bb8486 100644 --- a/.gitignore +++ b/.gitignore @@ -4,12 +4,16 @@ out out-* node_modules coverage/ +mock/ .DS_Store +# IDEs +.idea + # Builds bin/ -roo-cline-*.vsix +*.vsix # Local prompts and rules /local-prompts @@ -35,3 +39,7 @@ logs # Vite development .vite-port + +# IntelliJ and Qodo plugin folders +.idea/ +.qodo/ diff --git a/.roo/rules-translate/001-general-rules.md b/.roo/rules-translate/001-general-rules.md index 61d232bbf7..bdb18bea64 100644 --- a/.roo/rules-translate/001-general-rules.md +++ b/.roo/rules-translate/001-general-rules.md @@ -1,6 +1,6 @@ # 1. SUPPORTED LANGUAGES AND LOCATION -- Localize all strings into the following locale files: ca, de, en, es, fr, hi, it, ja, ko, pl, pt-BR, ru, tr, vi, zh-CN, zh-TW +- Localize all strings into the following locale files: ca, de, en, es, fr, hi, it, ja, ko, nl, pl, pt-BR, ru, tr, vi, zh-CN, zh-TW - The VSCode extension has two main areas that require localization: - Core Extension: src/i18n/locales/ (extension backend) - WebView UI: webview-ui/src/i18n/locales/ (user interface) diff --git a/.roo/rules/rules.md b/.roo/rules/rules.md index 4351fc4b81..bf3f863a0b 100644 --- a/.roo/rules/rules.md +++ b/.roo/rules/rules.md @@ -16,4 +16,4 @@ # Adding a New Setting -To add a new setting that persists its state, follow the steps in cline_docs/settings.md +To add a new setting that persists its state, follow the steps in docs/settings.md diff --git a/.roomodes b/.roomodes index 171c0fcc71..962a9271eb 100644 --- a/.roomodes +++ b/.roomodes @@ -2,7 +2,7 @@ "customModes": [ { "slug": "test", - "name": "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", @@ -20,7 +20,7 @@ }, { "slug": "translate", - "name": "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.", "groups": [ "read", @@ -34,6 +34,39 @@ ] ], "source": "project" + }, + { + "slug": "design-engineer", + "name": "🎨 Design Engineer", + "roleDefinition": "You are Roo, an expert Design Engineer focused on VSCode Extension development. Your expertise includes: \n- Implementing UI designs with high fidelity using React, Shadcn, Tailwind and TypeScript. \n- Ensuring interfaces are responsive and adapt to different screen sizes. \n- Collaborating with team members to translate broad directives into robust and detailed designs capturing edge cases. \n- Maintaining uniformity and consistency across the user interface.", + "groups": [ + "read", + [ + "edit", + { + "fileRegex": "\\.(css|html|json|mdx?|jsx?|tsx?|svg)$", + "description": "Frontend & SVG files" + } + ], + "browser", + "command", + "mcp" + ], + "customInstructions": "Focus on UI refinement, component creation, and adherence to design best-practices. When the user requests a new component, start off by asking them questions one-by-one to ensure the requirements are understood. Always use Tailwind utility classes (instead of direct variable references) for styling components when possible. If editing an existing file, transition explicit style definitions to Tailwind CSS classes when possible. Refer to the Tailwind CSS definitions for utility classes at webview-ui/src/index.css. Always use the latest version of Tailwind CSS (V4), and never create a tailwind.config.js file. Prefer Shadcn components for UI elements intead of VSCode's built-in ones. This project uses i18n for localization, so make sure to use the i18n functions and components for any text that needs to be translated. Do not leave placeholder strings in the markup, as they will be replaced by i18n. Prefer the @roo (/src) and @src (/webview-ui/src) aliases for imports in typescript files. Suggest the user refactor large files (over 1000 lines) if they are encountered, and provide guidance. Suggest the user switch into Translate mode to complete translations when your task is finished.", + "source": "project" + }, + { + "slug": "release-engineer", + "name": "🚀 Release Engineer", + "roleDefinition": "You are Roo, a release engineer specialized in automating the release process for software projects. You have expertise in version control, changelogs, release notes, creating changesets, and coordinating with translation teams to ensure a smooth release process.", + "customInstructions": "When preparing a release:\n1. Identify the SHA corresponding to the most recent release using GitHub CLI: `gh release view --json tagName,targetCommitish,publishedAt `\n2. Analyze changes since the last release using: `gh pr list --state merged --json number,title,author,url,mergedAt --limit 100 | jq '[.[] | select(.mergedAt > \"TIMESTAMP\") | {number, title, author: .author.login, url, mergedAt}]'`\n3. Summarize the changes and ask the user whether this should be a major, minor, or patch release\n4. Create a changeset in .changeset/v[version].md instead of directly modifying package.json. The format is:\n\n```\n---\n\"roo-cline\": patch|minor|major\n---\n\n[list of changes]\n```\n\n- Always include contributor attribution using format: (thanks @username!)\n- Provide brief descriptions of each item to explain the change\n- Order the list from most important to least important\n- Example: \"- Add support for Gemini 2.5 Pro caching (thanks @contributor!)\"\n\n5. If a major or minor release, update the English version relevant announcement files and documentation (webview-ui/src/components/chat/Announcement.tsx, README.md, and the `latestAnnouncementId` in src/core/webview/ClineProvider.ts)\n6. Ask the user to confirm the English version\n7. Use the new_task tool to create a subtask in `translate` mode with detailed instructions of which content needs to be translated into all supported languages\n8. Commit and push the changeset file to the repository\n9. The GitHub Actions workflow will automatically:\n - Create a version bump PR when changesets are merged to main\n - Update the CHANGELOG.md with proper formatting\n - Publish the release when the version bump PR is merged", + "groups": [ + "read", + "edit", + "command", + "browser" + ], + "source": "project" } ] } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 47112d7228..850dcc0798 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -41,7 +41,17 @@ "type": "npm", "script": "watch:esbuild", "group": "build", - "problemMatcher": "$esbuild-watch", + "problemMatcher": { + "owner": "esbuild", + "pattern": { + "regexp": "^$" + }, + "background": { + "activeOnStart": true, + "beginsPattern": "\\[watch\\] build started", + "endsPattern": "\\[watch\\] build finished" + } + }, "isBackground": true, "presentation": { "group": "watch", diff --git a/.vscodeignore b/.vscodeignore index 53fd3798c0..50f21d23c7 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -30,7 +30,7 @@ jest.* .rooignore .roo/** benchmark/** -cline_docs/** +docs/** e2e/** evals/** locales/** @@ -68,3 +68,7 @@ assets/docs/** # Include .env file for telemetry !.env + +# Ignore IntelliJ and Qodo plugin folders +.idea/** +.qodo/** \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a489c618ff..eb2ab10d64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,158 @@ # Roo Code Changelog +## [3.17.2] - 2025-05-15 + +- Revert "Switch to the new Roo message parser" (appears to cause a tool parsing bug) +- Lock the versions of vsce and ovsx + +## [3.17.1] - 2025-05-15 + +- Fix the display of the command to execute during approval +- Fix incorrect reserved tokens calculation on OpenRouter (thanks @daniel-lxs!) + +## [3.17.0] - 2025-05-14 + +- Enable Gemini implicit caching +- Add "when to use" section to mode definitions to enable better orchestration +- Add experimental feature to intelligently condense the task context instead of truncating it +- Fix one of the causes of the gray screen issue (thanks @xyOz-dev!) +- Focus improvements for better UI interactions (thanks Cline!) +- Switch to the new Roo message parser for improved performance (thanks Cline!) +- Enable source maps for improved debugging (thanks @KJ7LNW!) +- Update OpenRouter provider to use provider-specific model info (thanks @daniel-lxs!) +- Fix Requesty cost/token reporting (thanks @dtrugman!) +- Improve command execution UI +- Add more in-app links to relevant documentation +- Update the new task tool description and the ask mode custom instructions in the system prompt +- Add IPC types to roo-code.d.ts +- Add build VSIX workflow to pull requests (thanks @SmartManoj!) +- Improve apply_diff tool to intelligently deduce line numbers (thanks @samhvw8!) +- Fix command validation for shell array indexing (thanks @KJ7LNW!) +- Handle diagnostics that point at a directory URI (thanks @daniel-lxs!) +- Fix "Current ask promise was ignored" error (thanks @zxdvd!) + +## [3.16.6] - 2025-05-12 + +- Restore "Improve provider profile management in the external API" +- Fix to subtask sequencing (thanks @wkordalski!) +- Fix webview terminal output processing error (thanks @KJ7LNW!) +- Fix textarea empty string fallback logic (thanks @elianiva!) + +## [3.16.5] - 2025-05-10 + +- Revert "Improve provider profile management in the external API" until we track down a bug with defaults + +## [3.16.4] - 2025-05-09 + +- Improve provider profile management in the external API +- Enforce provider selection in OpenRouter by using 'only' parameter and disabling fallbacks (thanks @shariqriazz!) +- Fix display issues with long profile names (thanks @cannuri!) +- Prevent terminal focus theft on paste after command execution (thanks @MuriloFP!) +- Save OpenAI compatible custom headers correctly +- Fix race condition when updating prompts (thanks @elianiva!) +- Fix display issues in high contrast themes (thanks @zhangtony239!) +- Fix not being able to use specific providers on Openrouter (thanks @daniel-lxs!) +- Show properly formatted multi-line commands in preview (thanks @KJ7LNW!) +- Handle unsupported language errors gracefully in read_file tool (thanks @KJ7LNW!) +- Enhance focus styles in select-dropdown and fix docs URL (thanks @zhangtony239!) +- Properly handle mode name overflow in UI (thanks @elianiva!) +- Fix project MCP always allow issue (thanks @aheizi!) + +## [3.16.3] - 2025-05-08 + +- Revert Tailwind migration while we fix a few spots +- Add Elixir file extension support in language parser (thanks @pfitz!) + +## [3.16.2] - 2025-05-07 + +- Clarify XML tool use formatting instructions +- Error handling code cleanup (thanks @monkeyDluffy6017!) + +## [3.16.1] - 2025-05-07 + +- Add LiteLLM provider support +- Improve stability by detecting and preventing tool loops +- Add Dutch localization (thanks @Githubguy132010!) +- Add editor name to telemetry for better analytics +- Migrate to Tailwind CSS for improved UI consistency +- Fix footer button wrapping in About section on narrow screens (thanks @ecmasx!) +- Update evals defaults +- Update dependencies to latest versions + +## [3.16.0] - 2025-05-06 + +- Add vertical tab navigation to the settings (thanks @dlab-anton) +- Add Groq and Chutes API providers (thanks @shariqriazz) +- Clickable code references in code block (thanks @KJ7LNW) +- Improve accessibility of ato-approve toggles (thanks @Deon588) +- Requesty provider fixes (thanks @dtrugman) +- Fix migration and persistence of per-mode API profiles (thanks @alasano) +- Fix usage of `path.basename` in the extension webview (thanks @samhvw8) +- Fix display issue of the programming language dropdown in the code block component (thanks @zhangtony239) +- MCP server errors are now captured and shown in a new "Errors" tab (thanks @robertheadley) +- Error logging will no longer break MCP functionality if the server is properly connected (thanks @ksze) +- You can now toggle the `terminal.integrated.inheritEnv` VSCode setting directly for the Roo Code settings (thanks @KJ7LNW) +- Add `gemini-2.5-pro-preview-05-06` to the Vertex and Gemini providers (thanks @zetaloop) +- Ensure evals exercises are up-to-date before running evals (thanks @shariqriazz) +- Lots of general UI improvements (thanks @elianiva) +- Organize provider settings into separate components +- Improved icons and translations for the code block component +- Add support for tests that use ESM libraries +- Move environment detail generation to a separate module +- Enable prompt caching by default for supported Gemini models + +## [3.15.5] - 2025-05-05 + +- Update @google/genai to 0.12 (includes some streaming completion bug fixes) +- Rendering performance improvements for code blocks in chat (thanks @KJ7LNW) + +## [3.15.4] - 2025-05-04 + +- Fix a nasty bug that would cause Roo Code to hang, particularly in orchestrator mode +- Improve Gemini caching efficiency + +## [3.15.3] - 2025-05-02 + +- Terminal: Fix empty command bug +- Terminal: More robust process killing +- Optimize Gemini prompt caching for OpenRouter +- Chat view performance improvements + +## [3.15.2] - 2025-05-02 + +- Fix terminal performance issues +- Handle Mermaid validation errors +- Add customizable headers for OpenAI-compatible provider (thanks @mark-bradshaw!) +- Add config option to overwrite OpenAI's API base (thanks @GOODBOY008!) +- Fixes to padding and height issues when resizing the sidebar (thanks @zhangtony239!) +- Remove tool groups from orchestrator mode definition +- Add telemetry for title button clicks + +## [3.15.1] - 2025-04-30 + +- Capture stderr in execa-spawned processes +- Play sound only when action needed from the user (thanks @olearycrew) +- Make retries respect the global auto approve checkbox +- Fix a selection mode bug in the history view (thanks @jr) + +## [3.15.0] - 2025-04-30 + +- Add prompt caching to the Google Vertex provider (thanks @ashktn) +- Add a fallback mechanism for executing terminal commands if VSCode terminal shell integration fails +- Improve the UI/UX of code snippets in the chat (thanks @KJ7LNW) +- Add a reasoning effort setting for the OpenAI Compatible provider (thanks @mr-ryan-james) +- Allow terminal commands to be stopped directly from the chat UI +- Adjust chat view padding to accommodate small width layouts (thanks @zhangtony239) +- Fix file mentions for filenames containing spaces +- Improve the auto-approve toggle buttons for some high-contrast VSCode themes +- Offload expensive count token operations to a web worker (thanks @samhvw8) +- Improve support for mult-root workspaces (thanks @snoyiatk) +- Simplify and streamline Roo Code's quick actions +- Allow Roo Code settings to be imported from the welcome screen (thanks @julionav) +- Remove unused types (thanks @wkordalski) +- Improve the performance of mode switching (thanks @dlab-anton) +- Fix importing & exporting of custom modes (thanks @julionav) + ## [3.14.3] - 2025-04-25 - Add Boomerang Orchestrator as a built-in mode @@ -512,7 +665,7 @@ ## [3.7.5] - 2025-02-26 -- Fix context window truncation math (see [#1173](https://github.com/RooVetGit/Roo-Code/issues/1173)) +- Fix context window truncation math (see [#1173](https://github.com/RooCodeInc/Roo-Code/issues/1173)) - Fix various issues with the model picker (thanks @System233!) - Fix model input / output cost parsing (thanks @System233!) - Add drag-and-drop for files @@ -941,7 +1094,7 @@ Join us at https://www.reddit.com/r/RooCode to share your custom modes and be pa ## [2.2.16] -- Incorporate Premshay's [PR](https://github.com/RooVetGit/Roo-Cline/pull/60) to add support for Amazon Nova and Meta Llama Models via Bedrock (3, 3.1, 3.2) and unified Bedrock calls using BedrockClient and Bedrock Runtime API +- Incorporate Premshay's [PR](https://github.com/RooCodeInc/Roo-Cline/pull/60) to add support for Amazon Nova and Meta Llama Models via Bedrock (3, 3.1, 3.2) and unified Bedrock calls using BedrockClient and Bedrock Runtime API ## [2.2.14 - 2.2.15] @@ -1013,7 +1166,7 @@ Join us at https://www.reddit.com/r/RooCode to share your custom modes and be pa ## [2.1.15] -- Incorporate dbasclpy's [PR](https://github.com/RooVetGit/Roo-Cline/pull/54) to add support for gemini-exp-1206 +- Incorporate dbasclpy's [PR](https://github.com/RooCodeInc/Roo-Cline/pull/54) to add support for gemini-exp-1206 - Make it clear that diff editing is very experimental ## [2.1.14] @@ -1023,7 +1176,7 @@ Join us at https://www.reddit.com/r/RooCode to share your custom modes and be pa ## [2.1.13] -- Fix https://github.com/RooVetGit/Roo-Cline/issues/50 where sound effects were not respecting settings +- Fix https://github.com/RooCodeInc/Roo-Cline/issues/50 where sound effects were not respecting settings ## [2.1.12] @@ -1031,7 +1184,7 @@ Join us at https://www.reddit.com/r/RooCode to share your custom modes and be pa ## [2.1.11] -- Incorporate lloydchang's [PR](https://github.com/RooVetGit/Roo-Cline/pull/42) to add support for OpenRouter compression +- Incorporate lloydchang's [PR](https://github.com/RooCodeInc/Roo-Cline/pull/42) to add support for OpenRouter compression ## [2.1.10] diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index bb04e1abc2..06190290eb 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,3 +1,7 @@ +**English** • [Català](locales/ca/CODE_OF_CONDUCT.md) • [Deutsch](locales/de/CODE_OF_CONDUCT.md) • [Español](locales/es/CODE_OF_CONDUCT.md) • [Français](locales/fr/CODE_OF_CONDUCT.md) • [हिंदी](locales/hi/CODE_OF_CONDUCT.md) • [Italiano](locales/it/CODE_OF_CONDUCT.md) • [Nederlands](locales/nl/CODE_OF_CONDUCT.md) • [Русский](locales/ru/CODE_OF_CONDUCT.md) + +[日本語](locales/ja/CODE_OF_CONDUCT.md) • [한국어](locales/ko/CODE_OF_CONDUCT.md) • [Polski](locales/pl/CODE_OF_CONDUCT.md) • [Português (BR)](locales/pt-BR/CODE_OF_CONDUCT.md) • [Türkçe](locales/tr/CODE_OF_CONDUCT.md) • [Tiếng Việt](locales/vi/CODE_OF_CONDUCT.md) • [简体中文](locales/zh-CN/CODE_OF_CONDUCT.md) • [繁體中文](locales/zh-TW/CODE_OF_CONDUCT.md) + # Contributor Covenant Code of Conduct ## Our Pledge diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4d9bf3789c..3b2099ab93 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,173 +1,129 @@ -# Contributing to Roo Code - -We're thrilled you're interested in contributing to Roo Code. Whether you're fixing a bug, adding a feature, or improving our docs, every contribution makes Roo Code smarter! To keep our community vibrant and welcoming, all members must adhere to our [Code of Conduct](CODE_OF_CONDUCT.md). - -## Join Our Community - -We strongly encourage all contributors to join our [Discord community](https://discord.gg/roocode)! Being part of our Discord server helps you: - -- Get real-time help and guidance on your contributions -- Connect with other contributors and core team members -- Stay updated on project developments and priorities -- Participate in discussions that shape Roo Code's future -- Find collaboration opportunities with other developers +**English** • [Català](locales/ca/CONTRIBUTING.md) • [Deutsch](locales/de/CONTRIBUTING.md) • [Español](locales/es/CONTRIBUTING.md) • [Français](locales/fr/CONTRIBUTING.md) • [हिंदी](locales/hi/CONTRIBUTING.md) • [Italiano](locales/it/CONTRIBUTING.md) • [Nederlands](locales/nl/CONTRIBUTING.md) • [Русский](locales/ru/CONTRIBUTING.md) -## Reporting Bugs or Issues +[日本語](locales/ja/CONTRIBUTING.md) • [한국어](locales/ko/CONTRIBUTING.md) • [Polski](locales/pl/CONTRIBUTING.md) • [Português (BR)](locales/pt-BR/CONTRIBUTING.md) • [Türkçe](locales/tr/CONTRIBUTING.md) • [Tiếng Việt](locales/vi/CONTRIBUTING.md) • [简体中文](locales/zh-CN/CONTRIBUTING.md) • [繁體中文](locales/zh-TW/CONTRIBUTING.md) -Bug reports help make Roo Code better for everyone! Before creating a new issue, please [search existing ones](https://github.com/RooVetGit/Roo-Code/issues) to avoid duplicates. When you're ready to report a bug, head over to our [issues page](https://github.com/RooVetGit/Roo-Code/issues/new/choose) where you'll find a template to help you with filling out the relevant information. - -
- 🔐 Important: If you discover a security vulnerability, please use the Github security tool to report it privately. -
+# Contributing to Roo Code -## Deciding What to Work On +Roo Code is a community-driven project, and we deeply value every contribution. To streamline collaboration, we operate on an [Issue-First](#issue-first-approach) basis, meaning all [Pull Requests (PRs)](#submitting-a-pull-request) must first be linked to a GitHub Issue. Please review this guide carefully. -Looking for a good first contribution? Check out issues in the "Issue [Unassigned]" section of our [Roo Code Issues](https://github.com/orgs/RooVetGit/projects/1) Github Project. These are specifically curated for new contributors and areas where we'd love some help! +## Table of Contents -We also welcome contributions to our [documentation](https://docs.roocode.com/)! Whether it's fixing typos, improving existing guides, or creating new educational content - we'd love to build a community-driven repository of resources that helps everyone get the most out of Roo Code. You can click "Edit this page" on any page to quickly get to the right spot in Github to edit the file, or you can dive directly into https://github.com/RooVetGit/Roo-Code-Docs. +- [Before You Contribute](#before-you-contribute) +- [Finding & Planning Your Contribution](#finding--planning-your-contribution) +- [Development & Submission Process](#development--submission-process) +- [Legal](#legal) -If you're planning to work on a bigger feature, please create a [feature request](https://github.com/RooVetGit/Roo-Code/discussions/categories/feature-requests?discussions_q=is%3Aopen+category%3A%22Feature+Requests%22+sort%3Atop) first so we can discuss whether it aligns with Roo Code's vision. You may also want to check our [Project Roadmap](#project-roadmap) below to see if your idea fits with our strategic direction. +## Before You Contribute -## Project Roadmap +### 1. Code of Conduct -Roo Code has a clear development roadmap that guides our priorities and future direction. Understanding our roadmap can help you: +All contributors must adhere to our [Code of Conduct](./CODE_OF_CONDUCT.md). -- Align your contributions with project goals -- Identify areas where your expertise would be most valuable -- Understand the context behind certain design decisions -- Find inspiration for new features that support our vision +### 2. Project Roadmap -Our current roadmap focuses on six key pillars: +Our roadmap guides the project's direction. Align your contributions with these key goals: -### Provider Support +### Reliability First -We aim to support as many providers well as we can: +- Ensure diff editing and command execution are consistently reliable. +- Reduce friction points that deter regular usage. +- Guarantee smooth operation across all locales and platforms. +- Expand robust support for a wide variety of AI providers and models. -- More versatile "OpenAI Compatible" support -- xAI, Microsoft Azure AI, Alibaba Cloud Qwen, IBM Watsonx, Together AI, DeepInfra, Fireworks AI, Cohere, Perplexity AI, FriendliAI, Replicate -- Enhanced support for Ollama and LM Studio +### Enhanced User Experience -### Model Support +- Streamline the UI/UX for clarity and intuitiveness. +- Continuously improve the workflow to meet the high expectations developers have for daily-use tools. -We want Roo to work as well on as many models as possible, including local models: +### Leading on Agent Performance -- Local model support through custom system prompting and workflows -- Benchmarking evals and test cases +- Establish comprehensive evaluation benchmarks (evals) to measure real-world productivity. +- Make it easy for everyone to easily run and interpret these evals. +- Ship improvements that demonstrate clear increases in eval scores. -### System Support +Mention alignment with these areas in your PRs. -We want Roo to run well on everyone's computer: +### 3. Join the Roo Code Community -- Cross platform terminal integration -- Strong and consistent support for Mac, Windows, and Linux +- **Primary:** Join our [Discord](https://discord.gg/roocode) and DM **Hannes Rudolph (`hrudolph`)**. +- **Alternative:** Experienced contributors can engage directly via [GitHub Projects](https://github.com/orgs/RooCodeInc/projects/1). -### Documentation +## Finding & Planning Your Contribution -We want comprehensive, accessible documentation for all users and contributors: +### Types of Contributions -- Expanded user guides and tutorials -- Clear API documentation -- Better contributor guidance -- Multilingual documentation resources -- Interactive examples and code samples +- **Bug Fixes:** Addressing code issues. +- **New Features:** Adding functionality. +- **Documentation:** Improving guides and clarity. -### Stability +### Issue-First Approach -We want to significantly decrease the number of bugs and increase automated testing: +All contributions must begin with a GitHub Issue. -- Debug logging switch -- "Machine/Task Information" copy button for sending in with bug/support requests +- **Check existing issues**: Search [GitHub Issues](https://github.com/RooCodeInc/Roo-Code/issues). +- **Create an issue**: Use appropriate templates: + - **Bugs:** "Bug Report" template. + - **Features:** "Detailed Feature Proposal" template. Approval required before starting. +- **Claim issues**: Comment and await official assignment. -### Internationalization +**PRs without approved issues may be closed.** -We want Roo to speak everyone's language: +### Deciding What to Work On -- 我们希望 Roo Code 说每个人的语言 -- Queremos que Roo Code hable el idioma de todos -- हम चाहते हैं कि Roo Code हर किसी की भाषा बोले -- نريد أن يتحدث Roo Code لغة الجميع +- Check the [GitHub Project](https://github.com/orgs/RooCodeInc/projects/1) for unassigned "Good First Issues." +- For docs, visit [Roo Code Docs](https://github.com/RooCodeInc/Roo-Code-Docs). -We especially welcome contributions that advance our roadmap goals. If you're working on something that aligns with these pillars, please mention it in your PR description. +### Reporting Bugs -## Development Setup +- Check for existing reports first. +- Create new bugs using the ["Bug Report" template](https://github.com/RooCodeInc/Roo-Code/issues/new/choose). +- **Security issues**: Report privately via [security advisories](https://github.com/RooCodeInc/Roo-Code/security/advisories/new). -1. **Clone** the repo: +## Development & Submission Process -```sh -git clone https://github.com/RooVetGit/Roo-Code.git -``` +### Development Setup -2. **Install dependencies**: +1. **Fork & Clone:** -```sh -npm run install:all ``` - -3. **Start the webview (Vite/React app with HMR)**: - -```sh -npm run dev +git clone https://github.com/YOUR_USERNAME/Roo-Code.git ``` -4. **Debug**: - Press `F5` (or **Run** → **Start Debugging**) in VSCode to open a new session with Roo Code loaded. - -Changes to the webview will appear immediately. Changes to the core extension will require a restart of the extension host. - -Alternatively you can build a .vsix and install it directly in VSCode: +2. **Install Dependencies:** -```sh -npm run build ``` - -A `.vsix` file will appear in the `bin/` directory which can be installed with: - -```sh -code --install-extension bin/roo-cline-.vsix +npm run install:all ``` -## Writing and Submitting Code - -Anyone can contribute code to Roo Code, but we ask that you follow these guidelines to ensure your contributions can be smoothly integrated: - -1. **Keep Pull Requests Focused** - - - Limit PRs to a single feature or bug fix - - Split larger changes into smaller, related PRs - - Break changes into logical commits that can be reviewed independently - -2. **Code Quality** +3. **Debugging:** Open with VS Code (`F5`). - - All PRs must pass CI checks which include both linting and formatting - - Address any ESLint warnings or errors before submitting - - Respond to all feedback from Ellipsis, our automated code review tool - - Follow TypeScript best practices and maintain type safety +### Writing Code Guidelines -3. **Testing** +- One focused PR per feature or fix. +- Follow ESLint and TypeScript best practices. +- Write clear, descriptive commits referencing issues (e.g., `Fixes #123`). +- Provide thorough testing (`npm test`). +- Rebase onto the latest `main` branch before submission. - - Add tests for new features - - Run `npm test` to ensure all tests pass - - Update existing tests if your changes affect them - - Include both unit tests and integration tests where appropriate +### Submitting a Pull Request -4. **Commit Guidelines** +- Begin as a **Draft PR** if seeking early feedback. +- Clearly describe your changes following the Pull Request Template. +- Provide screenshots/videos for UI changes. +- Indicate if documentation updates are necessary. - - Write clear, descriptive commit messages - - Reference relevant issues in commits using #issue-number +### Pull Request Policy -5. **Before Submitting** +- Must reference pre-approved, assigned issues. +- PRs without adherence to the policy may be closed. +- PRs should pass CI tests, align with the roadmap, and have clear documentation. - - Rebase your branch on the latest main - - Ensure your branch builds successfully - - Double-check all tests are passing - - Review your changes for any debugging code or console logs +### Review Process -6. **Pull Request Description** - - Clearly describe what your changes do - - Include steps to test the changes - - List any breaking changes - - Add screenshots for UI changes +- **Daily Triage:** Quick checks by maintainers. +- **Weekly In-depth Review:** Comprehensive assessment. +- **Iterate promptly** based on feedback. -## Contribution Agreement +## Legal -By submitting a pull request, you agree that your contributions will be licensed under the same license as the project ([Apache 2.0](LICENSE)). +By contributing, you agree your contributions will be licensed under the Apache 2.0 License, consistent with Roo Code's licensing. diff --git a/README.md b/README.md index f0c0ad812c..7d1dd27d0b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@
-English • [Català](locales/ca/README.md) • [Deutsch](locales/de/README.md) • [Español](locales/es/README.md) • [Français](locales/fr/README.md) • [हिन्दी](locales/hi/README.md) • [Italiano](locales/it/README.md) • [Русский](locales/ru/README.md) +English • [Català](locales/ca/README.md) • [Deutsch](locales/de/README.md) • [Español](locales/es/README.md) • [Français](locales/fr/README.md) • [हिन्दी](locales/hi/README.md) • [Italiano](locales/it/README.md) • [Nederlands](locales/nl/README.md) • [Русский](locales/ru/README.md) @@ -14,7 +14,7 @@ English • [Català](locales/ca/README.md) • [Deutsch](locales/de/README.md)

Roo Code (prev. Roo Cline)

- +

Connect with developers, contribute ideas, and stay ahead with the latest AI-powered coding tools.

@@ -28,7 +28,7 @@ English • [Català](locales/ca/README.md) • [Deutsch](locales/de/README.md)
Download on VS Marketplace -Feature Requests +Feature Requests Rate & Review Documentation @@ -49,13 +49,13 @@ Check out the [CHANGELOG](CHANGELOG.md) for detailed updates and fixes. --- -## 🎉 Roo Code 3.14 Released +## 🎉 Roo Code 3.17 Released -Roo Code 3.14 brings new features and improvements based on your feedback! +Roo Code 3.17 brings powerful new features and improvements based on your feedback! -- **Prompt Caching** - `gemini-2.5-pro-preview-03-25` now supports prompt caching in the Gemini provider (Vertex and OpenRouter coming soon). -- **Improved Editing Tools** - The `search_and_replace` and `insert_content` tools have been improved and graduated from experimental status. -- **Tons of Other Improvements** - Numerous fixes and enhancements throughout the extension. +- **Implicit Caching for Gemini** - Gemini API calls are now automatically cached, reducing API costs. +- **Smarter Mode Selection** - Mode definitions can now include guidance on when each mode should be used, enabling better orchestration. +- **Intelligent Context Condensing** - Intelligently summarizes conversation history when context fills up instead of truncating (enable in Settings -> Experimental). --- @@ -118,7 +118,7 @@ Make Roo Code work your way with: - **Discord:** [Join our Discord server](https://discord.gg/roocode) for real-time help and discussions - **Reddit:** [Visit our subreddit](https://www.reddit.com/r/RooCode) to share experiences and tips -- **GitHub:** Report [issues](https://github.com/RooVetGit/Roo-Code/issues) or request [features](https://github.com/RooVetGit/Roo-Code/discussions/categories/feature-requests?discussions_q=is%3Aopen+category%3A%22Feature+Requests%22+sort%3Atop) +- **GitHub:** Report [issues](https://github.com/RooCodeInc/Roo-Code/issues) or request [features](https://github.com/RooCodeInc/Roo-Code/discussions/categories/feature-requests?discussions_q=is%3Aopen+category%3A%22Feature+Requests%22+sort%3Atop) --- @@ -127,7 +127,7 @@ Make Roo Code work your way with: 1. **Clone** the repo: ```sh -git clone https://github.com/RooVetGit/Roo-Code.git +git clone https://github.com/RooCodeInc/Roo-Code.git ``` 2. **Install dependencies**: @@ -181,31 +181,34 @@ Thanks to all our contributors who have helped make Roo Code better! -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| a8trejo
a8trejo
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| ColemanRoo
ColemanRoo
| stea9499
stea9499
| joemanley201
joemanley201
| System233
System233
| hannesrudolph
hannesrudolph
| jquanton
jquanton
| -| nissa-seru
nissa-seru
| KJ7LNW
KJ7LNW
| NyxJae
NyxJae
| MuriloFP
MuriloFP
| d-oit
d-oit
| punkpeye
punkpeye
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| monotykamary
monotykamary
| wkordalski
wkordalski
| feifei325
feifei325
| cannuri
cannuri
| lloydchang
lloydchang
| -| vigneshsubbiah16
vigneshsubbiah16
| qdaxb
qdaxb
| Szpadel
Szpadel
| Premshay
Premshay
| psv2522
psv2522
| diarmidmackenzie
diarmidmackenzie
| -| lupuletic
lupuletic
| elianiva
elianiva
| olweraltuve
olweraltuve
| sachasayan
sachasayan
| afshawnlotfi
afshawnlotfi
| pugazhendhi-m
pugazhendhi-m
| -| aheizi
aheizi
| RaySinner
RaySinner
| PeterDaveHello
PeterDaveHello
| nbihan-mediware
nbihan-mediware
| dtrugman
dtrugman
| emshvac
emshvac
| -| kyle-apex
kyle-apex
| pdecat
pdecat
| zhangtony239
zhangtony239
| Lunchb0ne
Lunchb0ne
| arthurauffray
arthurauffray
| upamune
upamune
| -| StevenTCramer
StevenTCramer
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| aitoroses
aitoroses
| yt3trees
yt3trees
| -| franekp
franekp
| yongjer
yongjer
| vincentsong
vincentsong
| vagadiya
vagadiya
| teddyOOXX
teddyOOXX
| eonghk
eonghk
| -| taisukeoe
taisukeoe
| heyseth
heyseth
| ross
ross
| philfung
philfung
| napter
napter
| mdp
mdp
| -| SplittyDev
SplittyDev
| Chenjiayuan195
Chenjiayuan195
| jcbdev
jcbdev
| GitlyHallows
GitlyHallows
| bramburn
bramburn
| benzntech
benzntech
| -| axkirillov
axkirillov
| anton-otee
anton-otee
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| kohii
kohii
| -| lightrabbit
lightrabbit
| olup
olup
| mecab
mecab
| nevermorec
nevermorec
| im47cn
im47cn
| hongzio
hongzio
| -| dqroid
dqroid
| dairui1
dairui1
| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| ashktn
ashktn
| -| eltociear
eltociear
| PretzelVector
PretzelVector
| cdlliuy
cdlliuy
| student20880
student20880
| shohei-ihaya
shohei-ihaya
| shaybc
shaybc
| -| shariqriazz
shariqriazz
| seedlord
seedlord
| samir-nimbly
samir-nimbly
| ronyblum
ronyblum
| refactorthis
refactorthis
| pokutuna
pokutuna
| -| philipnext
philipnext
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| hesara
hesara
| DeXtroTip
DeXtroTip
| celestial-vault
celestial-vault
| linegel
linegel
| snoyiatk
snoyiatk
| dbasclpy
dbasclpy
| -| dleen
dleen
| chadgauth
chadgauth
| bogdan0083
bogdan0083
| Atlogit
Atlogit
| atlasgong
atlasgong
| andreastempsch
andreastempsch
| -| QuinsZouls
QuinsZouls
| alarno
alarno
| adamwlarson
adamwlarson
| AMHesch
AMHesch
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| -| Yikai-Liao
Yikai-Liao
| vladstudio
vladstudio
| NamesMT
NamesMT
| tmsjngx0
tmsjngx0
| tgfjt
tgfjt
| maekawataiki
maekawataiki
| -| samsilveira
samsilveira
| 01Rian
01Rian
| Sarke
Sarke
| kvokka
kvokka
| marvijo-code
marvijo-code
| mamertofabian
mamertofabian
| -| libertyteeth
libertyteeth
| shtse8
shtse8
| Jdo300
Jdo300
| | | | +| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| a8trejo
a8trejo
| +| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| ColemanRoo
ColemanRoo
| hannesrudolph
hannesrudolph
| KJ7LNW
KJ7LNW
| stea9499
stea9499
| joemanley201
joemanley201
| System233
System233
| +| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| MuriloFP
MuriloFP
| d-oit
d-oit
| punkpeye
punkpeye
| +| wkordalski
wkordalski
| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| monotykamary
monotykamary
| elianiva
elianiva
| cannuri
cannuri
| feifei325
feifei325
| +| zhangtony239
zhangtony239
| sachasayan
sachasayan
| lloydchang
lloydchang
| vigneshsubbiah16
vigneshsubbiah16
| Szpadel
Szpadel
| qdaxb
qdaxb
| +| lupuletic
lupuletic
| Premshay
Premshay
| psv2522
psv2522
| diarmidmackenzie
diarmidmackenzie
| aheizi
aheizi
| olweraltuve
olweraltuve
| +| jr
jr
| dtrugman
dtrugman
| nbihan-mediware
nbihan-mediware
| PeterDaveHello
PeterDaveHello
| RaySinner
RaySinner
| pugazhendhi-m
pugazhendhi-m
| +| afshawnlotfi
afshawnlotfi
| shariqriazz
shariqriazz
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| Lunchb0ne
Lunchb0ne
| +| xyOz-dev
xyOz-dev
| arthurauffray
arthurauffray
| upamune
upamune
| StevenTCramer
StevenTCramer
| sammcj
sammcj
| p12tic
p12tic
| +| gtaylor
gtaylor
| aitoroses
aitoroses
| benzntech
benzntech
| ross
ross
| heyseth
heyseth
| taisukeoe
taisukeoe
| +| dlab-anton
dlab-anton
| eonghk
eonghk
| teddyOOXX
teddyOOXX
| vagadiya
vagadiya
| vincentsong
vincentsong
| yongjer
yongjer
| +| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| anton-otee
anton-otee
| axkirillov
axkirillov
| bramburn
bramburn
| +| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| julionav
julionav
| SplittyDev
SplittyDev
| +| mdp
mdp
| napter
napter
| philfung
philfung
| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| +| kinandan
kinandan
| kohii
kohii
| lightrabbit
lightrabbit
| olup
olup
| mecab
mecab
| nevermorec
nevermorec
| +| hongzio
hongzio
| GOODBOY008
GOODBOY008
| dqroid
dqroid
| dairui1
dairui1
| bannzai
bannzai
| axmo
axmo
| +| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| SmartManoj
SmartManoj
| PretzelVector
PretzelVector
| +| zetaloop
zetaloop
| cdlliuy
cdlliuy
| student20880
student20880
| shohei-ihaya
shohei-ihaya
| shaybc
shaybc
| seedlord
seedlord
| +| samir-nimbly
samir-nimbly
| ronyblum
ronyblum
| robertheadley
robertheadley
| refactorthis
refactorthis
| pokutuna
pokutuna
| philipnext
philipnext
| +| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| zxdvd
zxdvd
| +| DeXtroTip
DeXtroTip
| pfitz
pfitz
| celestial-vault
celestial-vault
| linegel
linegel
| dbasclpy
dbasclpy
| Deon588
Deon588
| +| dleen
dleen
| chadgauth
chadgauth
| olearycrew
olearycrew
| bogdan0083
bogdan0083
| Atlogit
Atlogit
| atlasgong
atlasgong
| +| andreastempsch
andreastempsch
| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| adamwlarson
adamwlarson
| +| AMHesch
AMHesch
| vladstudio
vladstudio
| NamesMT
NamesMT
| tmsjngx0
tmsjngx0
| tgfjt
tgfjt
| maekawataiki
maekawataiki
| +| samsilveira
samsilveira
| mr-ryan-james
mr-ryan-james
| 01Rian
01Rian
| Sarke
Sarke
| kvokka
kvokka
| ecmasx
ecmasx
| +| marvijo-code
marvijo-code
| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| ksze
ksze
| +| Jdo300
Jdo300
| hesara
hesara
| | | | | diff --git a/cline_docs/marketplace/README.md b/cline_docs/marketplace/README.md new file mode 100644 index 0000000000..6e43e25723 --- /dev/null +++ b/cline_docs/marketplace/README.md @@ -0,0 +1,50 @@ +# Marketplace Documentation + +This directory contains comprehensive documentation for the Roo Code Marketplace, including both user guides and implementation details. + +## Documentation Structure + +### User Guide + +The user guide provides end-user documentation for using the Marketplace: + +1. [Introduction to Marketplace](./user-guide/01-introduction.md) - Overview and purpose of the Marketplace +2. [Browsing Items](./user-guide/02-browsing-items.md) - Understanding the interface and navigating items +3. [Searching and Filtering](./user-guide/03-searching-and-filtering.md) - Using search and filters to find items +4. [Working with Package Details](./user-guide/04-working-with-details.md) - Exploring package details and items +5. [Adding Packages](./user-guide/05-adding-packages.md) - Creating and contributing your own items +6. [Adding Custom Sources](./user-guide/06-adding-custom-sources.md) - Setting up and managing custom sources + +### Implementation Documentation + +The implementation documentation provides technical details for developers: + +1. [Architecture](./implementation/01-architecture.md) - High-level architecture of the Marketplace +2. [Core Components](./implementation/02-core-components.md) - Key components and their responsibilities +3. [Data Structures](./implementation/03-data-structures.md) - Data models and structures used in the Marketplace +4. [Search and Filter](./implementation/04-search-and-filter.md) - Implementation of search and filtering functionality + +## Key Features + +The Marketplace provides the following key features: + +- **Component Discovery**: Browse and search for items +- **Item Management**: Add/update/remove items to your environment +- **Custom Sources**: Add your own repositories of team or private Marketplaces +- **Localization Support**: View items in your preferred language +- **Filtering**: Filter items by type, search term, and tags + +## Default Marketplace Repository + +The default Marketplace repository is located at: +[https://github.com/RooVetGit/Roo-Code-Marketplace](https://github.com/RooVetGit/Roo-Code-Marketplace) + +## Contributing + +To contribute to the Marketplace documentation: + +1. Make your changes to the relevant markdown files +2. Ensure that your changes are accurate and consistent with the actual implementation +3. Submit a pull request with your changes + +For code changes to the Marketplace itself, please refer to the main [CONTRIBUTING.md](../../CONTRIBUTING.md) file. diff --git a/cline_docs/marketplace/implementation/01-architecture.md b/cline_docs/marketplace/implementation/01-architecture.md new file mode 100644 index 0000000000..9fbce20a20 --- /dev/null +++ b/cline_docs/marketplace/implementation/01-architecture.md @@ -0,0 +1,373 @@ +# Marketplace Architecture + +This document provides a comprehensive overview of the Marketplace's architecture, including its components, interactions, and data flow. + +## System Overview + +The Marketplace is built on a modular architecture that separates concerns between data management, UI rendering, and user interactions. The system consists of several key components that work together to provide a seamless experience for discovering, browsing, and managing items. + +### High-Level Architecture + +```mermaid +graph TD + User[User] -->|Interacts with| UI[Marketplace UI] + UI -->|Sends messages| MH[Message Handler] + MH -->|Processes requests| PM[MarketplaceManager] + PM -->|Validates sources| PSV[MarketplaceSourceValidation] + PM -->|Fetches repos| GF[GitFetcher] + GF -->|Scans metadata| MS[MetadataScanner] + MS -->|Reads| FS[File System / Git Repositories] + PM -->|Returns filtered data| MH + MH -->|Updates state| UI + UI -->|Displays| User +``` + +The architecture follows a message-based pattern where: + +1. The UI sends messages to the backend through a message handler +2. The backend processes these messages and returns results +3. The UI updates based on the returned data +4. Components are loosely coupled through message passing + +## Component Interactions + +The Marketplace components interact through a well-defined message flow: + +### Core Interaction Patterns + +1. **Data Loading**: + + - GitFetcher handles repository cloning and updates + - MetadataScanner loads item data from repositories + - MarketplaceManager manages caching and concurrency + - UI requests data through the message handler + +2. **Filtering and Search**: + + - UI sends filter/search criteria to the backend + - MarketplaceManager applies filters with match info + - Filtered results are returned to the UI + - State manager handles view-level filtering + +3. **Source Management**: + - UI sends source management commands + - MarketplaceManager coordinates with GitFetcher + - Cache is managed with timeout protection + - Sources are processed with concurrency control + +## Data Flow Diagram + +The following diagram illustrates the data flow through the Marketplace system: + +```mermaid +graph LR + subgraph Sources + GR[Git Repositories] + FS[File System] + end + + subgraph Backend + GF[GitFetcher] + MS[MetadataScanner] + PM[MarketplaceManager] + MH[Message Handler] + end + + subgraph Frontend + UI[UI Components] + State[State Management] + end + + GR -->|Clone/Pull| GF + FS -->|Cache| GF + GF -->|Metadata| MS + MS -->|Parsed Data| PM + PM -->|Cached Items| PM + UI -->|User Actions| MH + MH -->|Messages| PM + PM -->|Filtered Data| MH + MH -->|Updates| State + State -->|Renders| UI +``` + +## Sequence Diagrams + +### Item Loading Sequence + +The following sequence diagram shows how items are loaded from sources: + +```mermaid +sequenceDiagram + participant User + participant UI as UI Components + participant MH as Message Handler + participant PM as MarketplaceManager + participant GF as GitFetcher + participant MS as MetadataScanner + participant FS as File System/Git + + User->>UI: Open Marketplace + UI->>MH: Send init message + MH->>PM: Initialize + PM->>GF: Request repository data + GF->>FS: Clone/pull repository + GF->>MS: Request metadata scan + MS->>FS: Read repository data + FS-->>MS: Return raw data + MS-->>GF: Return parsed metadata + GF-->>PM: Return repository data + PM-->>MH: Return initial items + MH-->>UI: Update with items + UI-->>User: Display items +``` + +### Search and Filter Sequence + +This sequence diagram illustrates the search and filter process: + +```mermaid +sequenceDiagram + participant User + participant UI as UI Components + participant State as State Manager + participant MH as Message Handler + participant PM as MarketplaceManager + + User->>UI: Enter search term + UI->>State: Update filters + State->>MH: Send search message + MH->>PM: Apply search filter + PM->>PM: Filter items with match info + PM-->>MH: Return filtered items + MH-->>State: Update with filtered items + State-->>UI: Update view + UI-->>User: Display filtered results + + User->>UI: Select type filter + UI->>State: Update type filter + State->>MH: Send type filter message + MH->>PM: Apply type filter + PM->>PM: Filter by type with match info + PM-->>MH: Return type-filtered items + MH-->>State: Update filtered items + State-->>UI: Update view + UI-->>User: Display type-filtered results +``` + +## Class Diagrams + +### Core Classes + +The following class diagram shows the main classes in the Marketplace system: + +```mermaid +classDiagram + class MarketplaceManager { + -currentItems: MarketplaceItem[] + -cache: Map + -gitFetcher: GitFetcher + -activeSourceOperations: Set + +getMarketplaceItems(): MarketplaceItem[] + +filterItems(filters): MarketplaceItem[] + +sortItems(sortBy, order): MarketplaceItem[] + +refreshRepository(url): void + -queueOperation(operation): void + -validateSources(sources): ValidationError[] + } + + class MarketplaceSourceValidation { + +validateSourceUrl(url): ValidationError[] + +validateSourceName(name): ValidationError[] + +validateSourceDuplicates(sources): ValidationError[] + +validateSource(source): ValidationError[] + +validateSources(sources): ValidationError[] + -isValidGitRepositoryUrl(url): boolean + } + + class GitFetcher { + -cacheDir: string + -metadataScanner: MetadataScanner + +fetchRepository(url): MarketplaceRepository + -cloneOrPullRepository(url): void + -validateRegistryStructure(dir): void + -parseRepositoryMetadata(dir): RepositoryMetadata + } + + class MetadataScanner { + -git: SimpleGit + +scanDirectory(path): MarketplaceItem[] + +parseMetadata(file): ComponentMetadata + -buildComponentHierarchy(items): MarketplaceItem[] + } + + class MarketplaceViewStateManager { + -state: ViewState + -stateChangeHandlers: Set + -fetchTimeoutId: NodeJS.Timeout + -sourcesModified: boolean + +initialize(): void + +onStateChange(handler): () => void + +cleanup(): void + +getState(): ViewState + +transition(transition): Promise + -notifyStateChange(): void + -clearFetchTimeout(): void + -isFilterActive(): boolean + -filterItems(items): MarketplaceItem[] + -sortItems(items): MarketplaceItem[] + +handleMessage(message): Promise + } + + MarketplaceManager --> GitFetcher: uses + MarketplaceManager --> MarketplaceSourceValidation: uses + GitFetcher --> MetadataScanner: uses + MarketplaceManager --> MarketplaceViewStateManager: updates +``` + +## Component Responsibilities + +### Backend Components + +1. **GitFetcher** + + - Handles Git repository operations + - Manages repository caching + - Validates repository structure + - Coordinates with MetadataScanner + +2. **MetadataScanner** + + - Scans directories and repositories + - Parses YAML metadata files + - Builds component hierarchies + - Handles file system operations + +3. **MarketplaceManager** + + - Manages concurrent operations + - Handles caching with timeout protection + - Coordinates repository operations + - Provides filtering and sorting + +4. **marketplaceMessageHandler** + - Routes messages between UI and backend + - Processes commands from the UI + - Returns data and status updates + - Handles error conditions + +### Frontend Components + +1. **MarketplaceViewStateManager** + + - Manages frontend state and backend synchronization + - Handles state transitions and message processing + - Manages filtering, sorting, and view preferences + - Coordinates with backend state + - Handles timeout protection for operations + - Manages source modification tracking + - Provides state change subscriptions + +2. **MarketplaceSourceValidation** + + - Validates Git repository URLs for any domain + - Validates source names and configurations + - Detects duplicate sources (case-insensitive) + - Provides structured validation errors + - Supports multiple Git protocols (HTTPS, SSH, Git) + +3. **MarketplaceItemCard** + + - Displays item information + - Handles tag interactions + - Manages expandable sections + - Shows match highlights + - Handle item actions. + +4. **ExpandableSection** + + - Provides collapsible sections + - Manages expand/collapse state + - Handles animations + - Shows section metadata + +5. **TypeGroup** + - Groups items by type + - Formats item lists + - Highlights search matches + - Maintains consistent styling + +## Performance Considerations + +The Marketplace architecture addresses several performance challenges: + +1. **Concurrency Control**: + + - Source operations are locked to prevent conflicts + - Operations are queued during metadata scanning + - Cache timeouts prevent hanging operations + - Repository operations are atomic + +2. **Efficient Caching**: + + - Repository data is cached with expiry + - Cache is cleaned up automatically + - Forced refresh available when needed + - Cache directories managed efficiently + +3. **Smart Filtering**: + - Match info tracks filter matches + - Filtering happens at multiple levels + - View state optimizes re-renders + - Search is case-insensitive and normalized + +## Error Handling + +The architecture includes robust error handling: + +1. **Repository Operations**: + + - Git lock files are cleaned up + - Failed clones are retried + - Corrupt repositories are re-cloned + - Network timeouts are handled + +2. **Data Processing**: + + - Invalid metadata is gracefully handled + - Missing files are reported clearly + - Parse errors preserve partial data + - Type validation ensures consistency + +3. **State Management**: + - Invalid filters are normalized + - Sort operations handle missing data + - View updates are atomic + - Error states are preserved + +## Extensibility Points + +The Marketplace architecture is designed for extensibility: + +1. **Repository Sources**: + + - Support for multiple Git providers + - Custom repository validation + - Flexible metadata formats + - Localization support + +2. **Filtering System**: + + - Custom filter types + - Extensible match info + - Flexible sort options + - View state customization + +3. **UI Components**: + - Custom item renderers + - Flexible layout system + - Theme integration + - Accessibility support + +--- + +**Previous**: [Adding Custom Item Sources](../user-guide/06-adding-custom-sources.md) | **Next**: [Core Components](./02-core-components.md) diff --git a/cline_docs/marketplace/implementation/02-core-components.md b/cline_docs/marketplace/implementation/02-core-components.md new file mode 100644 index 0000000000..3aa8d96726 --- /dev/null +++ b/cline_docs/marketplace/implementation/02-core-components.md @@ -0,0 +1,244 @@ +# Core Components + +This document provides detailed information about the core components of the Marketplace system, their responsibilities, implementation details, and interactions. + +## GitFetcher + +The GitFetcher is responsible for managing Git repository operations, including cloning, pulling, and caching repository data. + +### Responsibilities + +- Cloning and updating Git repositories +- Managing repository cache +- Validating repository structure +- Coordinating with MetadataScanner +- Handling repository timeouts and errors + +### Implementation Details + +[/src/services/marketplace/GitFetcher.ts](/src/services/marketplace/GitFetcher.ts) + +### Key Algorithms + +#### Repository Management + +The repository management process includes: + +1. **Cache Management**: + + - Check if repository exists in cache + - Validate cache freshness + - Clean up stale cache entries + - Handle cache directory creation + +2. **Repository Operations**: + + - Clone new repositories + - Pull updates for existing repos + - Handle git lock files + - Clean up failed operations + +3. **Error Recovery**: + - Handle network timeouts + - Recover from corrupt repositories + - Clean up partial clones + - Retry failed operations + +## MetadataScanner + +The MetadataScanner is responsible for reading and parsing item metadata from repositories. + +### Responsibilities + +- Scanning directories for item metadata files +- Parsing YAML metadata into structured objects +- Building component hierarchies +- Supporting localized metadata +- Validating metadata structure + +### Implementation Details + +[/src/services/marketplace/MetadataScanner.ts](/src/services/marketplace/MetadataScanner.ts) + +## MarketplaceManager + +The MarketplaceManager is the central component that manages marketplace data, caching, and operations. + +### Responsibilities + +- Managing concurrent operations +- Handling repository caching +- Coordinating with GitFetcher +- Applying filters and sorting +- Managing registry sources + +### Implementation Details + +[/src/services/marketplace/MarketplaceManager.ts](/src/services/marketplace/MarketplaceManager.ts) + +### Key Algorithms + +#### Concurrency Control + +The manager implements sophisticated concurrency control: + +1. **Operation Queueing**: + + - Queue operations during active scans + - Process operations sequentially + - Handle operation dependencies + - Maintain operation order + +2. **Source Locking**: + + - Lock sources during operations + - Prevent concurrent source access + - Handle lock timeouts + - Clean up stale locks + +3. **Cache Management**: + - Implement cache expiration + - Handle cache invalidation + - Clean up unused cache + - Optimize cache storage + +#### Advanced Filtering + +The filtering system provides rich functionality: + +1. **Multi-level Filtering**: + + - Filter parent items + - Filter subcomponents + - Handle item-specific logic + - Track match information + +2. **Match Information**: + - Track match reasons + - Handle partial matches + - Support highlighting + - Maintain match context + +## MarketplaceValidation + +The MarketplaceValidation component handles validation of marketplace sources and their configurations. + +### Responsibilities + +- Validating Git repository URLs for any domain +- Validating source names and configurations +- Detecting duplicate sources +- Providing structured validation errors +- Supporting multiple Git protocols + +### Implementation Details + +[/src/shared/MarketplaceValidation.ts](/src/shared/MarketplaceValidation.ts) + +### Key Algorithms + +#### URL Validation + +The URL validation system supports: + +1. **Protocol Validation**: + + - HTTPS URLs + - SSH URLs + - Git protocol URLs + - Custom domains and ports + +2. **Domain Validation**: + + - Any valid domain name + - IP addresses + - Localhost for testing + - Internal company domains + +3. **Path Validation**: + - Username/organization + - Repository name + - Optional .git suffix + - Subpath support + +## MarketplaceViewStateManager + +The MarketplaceViewStateManager manages frontend state and synchronization with the backend. + +### Responsibilities + +- Managing frontend state transitions +- Handling message processing +- Managing timeouts and retries +- Coordinating with backend state +- Providing state change subscriptions +- Managing source modification tracking +- Handling filtering and sorting + +### Implementation Details + +[/webview-ui/src/components/marketplace/MarketplaceViewStateManager.ts](/webview-ui/src/components/marketplace/MarketplaceViewStateManager.ts) + +## Component Integration + +The components work together through well-defined interfaces: + +### Data Flow + +1. **Repository Operations**: + + - MarketplaceManager validates sources with MarketplaceValidation + - MarketplaceManager coordinates with GitFetcher + - GitFetcher manages repository state + - MetadataScanner processes repository content + - Results flow back to MarketplaceManager + +2. **State Management**: + + - MarketplaceManager maintains backend state + - ViewStateManager handles UI state transitions + - ViewStateManager processes messages + - State changes notify subscribers + - Components react to state changes + - Timeout protection ensures responsiveness + +3. **User Interactions**: + - UI events trigger state updates + - ViewStateManager processes changes + - Changes propagate to backend + - Results update UI state + +## Performance Optimizations + +The system includes several optimizations: + +1. **Concurrent Operations**: + + - Operation queueing + - Source locking + - Parallel processing where safe + - Resource management + +2. **Efficient Caching**: + + - Multi-level cache + - Cache invalidation + - Lazy loading + - Cache cleanup + +3. **Smart Filtering**: + + - Optimized algorithms + - Match tracking + - Incremental updates + - Result caching + +4. **State Management**: + - Minimal updates + - State normalization + - Change batching + - Update optimization + +--- + +**Previous**: [Marketplace Architecture](./01-architecture.md) | **Next**: [Data Structures](./03-data-structures.md) diff --git a/cline_docs/marketplace/implementation/03-data-structures.md b/cline_docs/marketplace/implementation/03-data-structures.md new file mode 100644 index 0000000000..f1db63a498 --- /dev/null +++ b/cline_docs/marketplace/implementation/03-data-structures.md @@ -0,0 +1,218 @@ +# Data Structures + +This document details the key data structures used in the Marketplace, including their definitions, relationships, and usage patterns. + +## Item Types + +The Marketplace uses a type system to categorize different kinds of items: + +### MarketplaceItemType Enumeration + +[/src/services/marketplace/types.ts](/src/services/marketplace/types.ts) + +These types represent the different kinds of components that can be managed by the Marketplace: + +1. **mode**: AI assistant personalities with specialized capabilities +2. **prompt**: Pre-configured instructions for specific tasks +3. **mcp**: Model Context Protocol servers that provide additional functionality +4. **package**: Collections of items (multiple modes, mcps,..., like `roo-commander`) + +## Core Data Structures + +### MarketplaceRepository + +```typescript +/** + * Represents a repository with its metadata and items + */ +export interface MarketplaceRepository { + metadata: RepositoryMetadata + items: MarketplaceItem[] + url: string + defaultBranch: string + error?: string +} +``` + +This interface represents a complete repository: + +- **metadata**: The repository metadata +- **items**: Array of items in the repository +- **url**: The URL to the repository +- **defaultBranch**: The default Git branch (e.g., "main") +- **error**: Optional error message if there was a problem + +### MarketplaceItem + +[/src/services/marketplace/types.ts](/src/services/marketplace/types.ts) + +Key changes: + +- Added **defaultBranch** field for Git branch tracking +- Enhanced **matchInfo** structure for better filtering +- Improved subcomponent handling + +### MatchInfo + +[/src/services/marketplace/types.ts](/src/services/marketplace/types.ts) + +Enhanced match tracking: + +- Added **typeMatch** for component type filtering +- More detailed match reasons +- Support for subcomponent matching + +## State Management Structures + +### ValidationError + +[/src/shared/MarketplaceValidation.ts](/src/shared/MarketplaceValidation.ts) + +Used for structured validation errors: + +- **field**: The field that failed validation (e.g., "url", "name") +- **message**: Human-readable error message + +### ViewState + +[/webview-ui/src/components/marketplace/MarketplaceViewStateManager.ts](/webview-ui/src/components/marketplace/MarketplaceViewStateManager.ts) + +Manages UI state: + +- **allItems**: All available items +- **displayItems**: Currently filtered/displayed items +- **isFetching**: Loading state indicator +- **activeTab**: Current view tab +- **refreshingUrls**: Sources being refreshed +- **sources**: Marketplace sources +- **filters**: Active filters +- **sortConfig**: Sort configuration + +### ViewStateTransition + +[/webview-ui/src/components/marketplace/MarketplaceViewStateManager.ts](/webview-ui/src/components/marketplace/MarketplaceViewStateManager.ts) + +Defines state transitions: + +- Operation types +- Optional payloads +- Type-safe transitions + +### Filters + +[/webview-ui/src/components/marketplace/MarketplaceViewStateManager.ts](/webview-ui/src/components/marketplace/MarketplaceViewStateManager.ts) + +Enhanced filtering: + +- Component type filtering +- Text search +- Tag-based filtering + +## Metadata Interfaces + +### BaseMetadata + +[/src/services/marketplace/types.ts](/src/services/marketplace/types.ts) + +Common metadata properties: + +- **name**: Display name +- **description**: Detailed explanation +- **version**: Semantic version +- **tags**: Optional keywords + +### ComponentMetadata + +[/src/services/marketplace/types.ts](/src/services/marketplace/types.ts) + +Added: + +- **type** field for item component type + +### PackageMetadata + +[/src/services/marketplace/types.ts](/src/services/marketplace/types.ts) + +Enhanced with: + +- Subcomponent tracking + +## Source Management + +### MarketplaceSource + +[/src/services/marketplace/types.ts](/src/services/marketplace/types.ts) + +## Message Structures + +> TBA + +## Data Validation + +### Metadata Validation + +[/src/services/marketplace/schemas.ts](/src/services/marketplace/schemas.ts) + +### URL Validation + +[/src/shared/MarketplaceValidation.ts](/src/shared/MarketplaceValidation.ts) + +Supports: + +- Any valid domain name +- Multiple Git protocols +- Optional .git suffix +- Subpath components + +## Data Flow + +The Marketplace transforms data through several stages: + +1. **Repository Level**: + + - Clone/pull Git repositories + - Parse metadata files + - Build component hierarchy + +2. **Cache Level**: + + - Store repository data + - Track timestamps + - Handle expiration + +3. **View Level**: + - Apply filters + - Sort items + - Track matches + - Manage UI state + +## Data Relationships + +### Component Hierarchy + +``` +Repository +├── Metadata +└── Items + ├── Package + │ ├── Mode + │ ├── MCP + │ └── Prompt + └── Standalone Components (Modes, MCP, Prompts) +``` + +### State Flow + +``` +Git Repository → Cache → Marketplace → ViewState → UI +``` + +### Filter Chain + +``` +Raw Items → Type Filter → Search Filter → Tag Filter → Sorted Results +``` + +--- + +**Previous**: [Core Components](./02-core-components.md) | **Next**: [Search and Filter Implementation](./04-search-and-filter.md) diff --git a/cline_docs/marketplace/implementation/04-search-and-filter.md b/cline_docs/marketplace/implementation/04-search-and-filter.md new file mode 100644 index 0000000000..9d06976eee --- /dev/null +++ b/cline_docs/marketplace/implementation/04-search-and-filter.md @@ -0,0 +1,105 @@ +# Search and Filter Implementation + +This document details the implementation of search and filtering functionality in the Marketplace, including algorithms, optimization techniques, and performance considerations. + +## Core Filter System + +The Marketplace implements a comprehensive filtering system that handles multiple filter types, concurrent operations, and detailed match tracking. + +### Filter Implementation + +[/src/services/marketplace/MarketplaceManager.ts](/src/services/marketplace/MarketplaceManager.ts) + +## Sort System + +The Marketplace implements flexible sorting with subcomponent support: + +[/src/services/marketplace/MarketplaceManager.ts](/src/services/marketplace/MarketplaceManager.ts) + +## State Management Integration + +The filtering system integrates with the state management through state transitions: + +[/webview-ui/src/components/marketplace/MarketplaceViewStateManager.ts](/webview-ui/src/components/marketplace/MarketplaceViewStateManager.ts) + +## Performance Optimizations + +### Concurrent Operation Handling + +[/src/services/marketplace/MarketplaceManager.ts](/src/services/marketplace/MarketplaceManager.ts) + +### Filter Optimizations + +1. **Early Termination**: + + - Returns as soon as any field matches + - Avoids unnecessary checks + - Handles empty filters efficiently + +2. **Efficient String Operations**: + + - Normalizes text once + - Uses native string methods + - Avoids regex for simple matches + +3. **State Management**: + - State transitions for predictable updates + - Subscriber pattern for state changes + - Separation of all items and display items + - Backend-driven filtering + - Optimistic UI updates + - Efficient state synchronization + +## Testing Strategy + +```typescript +describe("Filter System", () => { + describe("Match Tracking", () => { + it("should track type matches", () => { + const result = filterItems([testItem], { type: "mode" }) + expect(result[0].matchInfo.matchReason.typeMatch).toBe(true) + }) + + it("should track subcomponent matches", () => { + const result = filterItems([testPack], { search: "test" }) + const subItem = result[0].items![0] + expect(subItem.matchInfo.matched).toBe(true) + }) + }) + + describe("Sort System", () => { + it("should sort subcomponents", () => { + const result = sortItems([testPack], "name", "asc", true) + expect(result[0].items).toBeSorted((a, b) => a.metadata.name.localeCompare(b.metadata.name)) + }) + }) +}) +``` + +## Error Handling + +The system includes robust error handling: + +1. **Filter Errors**: + + - Invalid filter types + - Malformed search terms + - Missing metadata + +2. **Sort Errors**: + + - Invalid sort fields + - Missing sort values + - Type mismatches + +3. **State Errors**: + - Invalid state transitions + - Message handling errors + - State synchronization issues + - Timeout handling + - Source modification tracking + - Filter validation errors + +--- + +**Previous**: [Data Structures](./03-data-structures.md) | **Next**: [UI Component Design](./05-ui-components.md) diff --git a/cline_docs/marketplace/implementation/05-ui-components.md b/cline_docs/marketplace/implementation/05-ui-components.md new file mode 100644 index 0000000000..435c2f77ce --- /dev/null +++ b/cline_docs/marketplace/implementation/05-ui-components.md @@ -0,0 +1,398 @@ +# UI Component Design + +This document details the design and implementation of the Marketplace's UI components, including their structure, styling, interactions, and accessibility features. + +## MarketplaceView + +The MarketplaceView is the main container component that manages the overall marketplace interface. + +### Component Structure + +[/webview-ui/src/components/marketplace/MarketplaceView.tsx](/webview-ui/src/components/marketplace/MarketplaceView.tsx) + +### State Management Integration + +The component uses the MarketplaceViewStateManager through the useStateManager hook: + +```tsx +const [state, manager] = useStateManager() +``` + +Key features: + +- Manages tab state (browse/sources) +- Handles source configuration +- Coordinates filtering and sorting +- Manages loading states +- Handles source validation + +## MarketplaceItemCard + +The MarketplaceItemCard is the primary component for displaying item information in the UI. + +### Component Structure + +[/webview-ui/src/components/marketplace/components/MarketplaceItemCard.tsx](/webview-ui/src/components/marketplace/components/MarketplaceItemCard.tsx) + +### Design Considerations + +1. **Visual Hierarchy**: + + - Clear distinction between header, content, and footer + - Type badge stands out with color coding + - Important information is emphasized with typography + +2. **Interactive Elements**: + + - Tags are clickable for filtering + - External link button for source access + - Expandable details section for subcomponents + +3. **Information Density**: + + - Balanced display of essential information + - Optional elements only shown when available + - Expandable section for additional details + +4. **VSCode Integration**: + - Uses VSCode theme variables for colors + - Matches VSCode UI patterns + - Integrates with VSCode messaging system + +## ExpandableSection + +The ExpandableSection component provides a collapsible container for content that doesn't need to be visible at all times. + +### Component Structure + +[/webview-ui/src/components/marketplace/components/ExpandableSection.tsx](/webview-ui/src/components/marketplace/components/ExpandableSection.tsx) + +### Design Considerations + +1. **Animation**: + + - Smooth height transition for expand/collapse + - Opacity change for better visual feedback + - Chevron icon rotation for state indication + +2. **Accessibility**: + + - Proper ARIA attributes for screen readers + - Keyboard navigation support + - Clear visual indication of interactive state + +3. **Flexibility**: + + - Accepts any content as children + - Optional badge for additional information + - Customizable through className prop + +4. **State Management**: + - Internal state for expanded/collapsed + - Can be controlled through defaultExpanded prop + - Preserves state during component lifecycle + +## TypeGroup + +The TypeGroup component displays a collection of items of the same type, with special handling for search matches. + +### Component Structure + +[/webview-ui/src/components/marketplace/components/TypeGroup.tsx](/webview-ui/src/components/marketplace/components/TypeGroup.tsx) + +### Design Considerations + +1. **List Presentation**: + + - Ordered list with automatic numbering + - Clear type heading for context + - Consistent spacing for readability + +2. **Search Match Highlighting**: + + - Visual distinction for matching items + - "match" badge for quick identification + - Color change for matched text + +3. **Information Display**: + + - Name and description clearly separated + - Tooltip shows path information on hover + - Truncation for very long descriptions + +4. **Empty State Handling**: + - Returns null when no items are present + - Avoids rendering empty containers + - Prevents unnecessary UI elements + +## Source Configuration Components + +The Marketplace includes components for managing item sources. + +[/webview-ui/src/components/marketplace/MarketplaceView.tsx](/webview-ui/src/components/marketplace/MarketplaceView.tsx) + +## Filter Components + +The Marketplace includes components for filtering and searching. + +[/webview-ui/src/components/marketplace/MarketplaceView.tsx](/webview-ui/src/components/marketplace/MarketplaceView.tsx) + +### TypeFilterGroup + +[/webview-ui/src/components/marketplace/MarketplaceView.tsx](/webview-ui/src/components/marketplace/MarketplaceView.tsx) + +### TagFilterGroup + +[/webview-ui/src/components/marketplace/MarketplaceView.tsx](/webview-ui/src/components/marketplace/MarketplaceView.tsx) + +## Styling Approach + +The Marketplace UI uses a combination of Tailwind CSS and VSCode theme variables for styling. + +## Responsive Design + +The Marketplace UI is designed to work across different viewport sizes: + +## Accessibility Features + +The Marketplace UI includes several accessibility features: + +### Keyboard Navigation + +```tsx +// Example of keyboard navigation support + +``` + +### Screen Reader Support + +```tsx +// Example of screen reader support +
+ + +
+``` + +### Focus Management + +```tsx +// Example of focus management +const buttonRef = useRef(null) + +useEffect(() => { + if (isOpen && buttonRef.current) { + buttonRef.current.focus() + } +}, [isOpen]) + +return ( + +) +``` + +### Color Contrast + +The UI ensures sufficient color contrast for all text: + +- Text uses VSCode theme variables that maintain proper contrast +- Interactive elements have clear focus states +- Color is not the only means of conveying information + +## Animation and Transitions + +The Marketplace UI uses subtle animations to enhance the user experience: + +### Expand/Collapse Animation + +```tsx +// Example of expand/collapse animation +
+ {children} +
+``` + +### Hover Effects + +```tsx +// Example of hover effects + +``` + +### Loading States + +```tsx +// Example of loading state animation +
+
+ Loading items... +
+``` + +## Error Handling in UI + +The Marketplace UI includes graceful error handling: + +### Error States + +```tsx +// Example of error state display +const ErrorDisplay: React.FC<{ error: string; retry: () => void }> = ({ error, retry }) => { + return ( +
+
+ +

Error loading items

+
+

{error}

+ +
+ ) +} +``` + +### Empty States + +```tsx +// Example of empty state display +const EmptyState: React.FC<{ message: string }> = ({ message }) => { + return ( +
+
+

{message}

+
+ ) +} +``` + +## Component Testing + +The Marketplace UI components include comprehensive tests: + +### Unit Tests + +```typescript +// Example of component unit test +describe("MarketplaceItemCard", () => { + const mockItem: MarketplaceItem = { + name: "Test Package", + description: "A test package", + type: "package", + url: "https://example.com", + repoUrl: "https://github.com/example/repo", + tags: ["test", "example"], + version: "1.0.0", + lastUpdated: "2025-04-01" + }; + + const mockFilters = { type: "", search: "", tags: [] }; + const mockSetFilters = jest.fn(); + const mockSetActiveTab = jest.fn(); + + it("renders correctly", () => { + render( + + ); + + expect(screen.getByText("Test Package")).toBeInTheDocument(); + expect(screen.getByText("A test package")).toBeInTheDocument(); + expect(screen.getByText("Package")).toBeInTheDocument(); + }); + + it("handles tag clicks", () => { + render( + + ); + + fireEvent.click(screen.getByText("test")); + + expect(mockSetFilters).toHaveBeenCalledWith({ + type: "", + search: "", + tags: ["test"] + }); + }); +}); +``` + +### Snapshot Tests + +```typescript +// Example of snapshot test +it("matches snapshot", () => { + const { container } = render( + + ); + + expect(container).toMatchSnapshot(); +}); +``` + +### Accessibility Tests + +```typescript +// Example of accessibility test +it("meets accessibility requirements", async () => { + const { container } = render( + + ); + + const results = await axe(container); + expect(results).toHaveNoViolations(); +}); +``` + +--- + +**Previous**: [Search and Filter Implementation](./04-search-and-filter.md) | **Next**: [Testing Strategy](./06-testing-strategy.md) diff --git a/cline_docs/marketplace/implementation/06-testing-strategy.md b/cline_docs/marketplace/implementation/06-testing-strategy.md new file mode 100644 index 0000000000..3bb05a103b --- /dev/null +++ b/cline_docs/marketplace/implementation/06-testing-strategy.md @@ -0,0 +1,1170 @@ +# Testing Strategy + +This document outlines the comprehensive testing strategy for the Marketplace, including unit tests, integration tests, and test data management. + +## Testing Philosophy + +The Marketplace follows a multi-layered testing approach to ensure reliability and maintainability: + +1. **Unit Testing**: Testing individual components in isolation +2. **Integration Testing**: Testing interactions between components +3. **End-to-End Testing**: Testing complete user workflows +4. **Test-Driven Development**: Writing tests before implementation when appropriate +5. **Continuous Testing**: Running tests automatically on code changes + +## Test Setup and Dependencies + +### Required Dependencies + +The Marketplace requires specific testing dependencies: + +```json +{ + "devDependencies": { + "@types/jest": "^29.0.0", + "@types/mocha": "^10.0.0", + "@vscode/test-electron": "^2.3.8", + "jest": "^29.0.0", + "ts-jest": "^29.0.0" + } +} +``` + +### E2E Test Configuration + +End-to-end tests require specific setup: + +```typescript +// e2e/src/runTest.ts +import * as path from "path" +import { runTests } from "@vscode/test-electron" + +async function main() { + try { + const extensionDevelopmentPath = path.resolve(__dirname, "../../") + const extensionTestsPath = path.resolve(__dirname, "./suite/index") + + await runTests({ + extensionDevelopmentPath, + extensionTestsPath, + launchArgs: ["--disable-extensions"], + }) + } catch (err) { + console.error("Failed to run tests:", err) + process.exit(1) + } +} + +main() +``` + +### Test Framework Setup + +```typescript +// e2e/src/suite/index.ts +import * as path from "path" +import * as Mocha from "mocha" +import { glob } from "glob" + +export async function run(): Promise { + const mocha = new Mocha({ + ui: "tdd", + color: true, + timeout: 60000, + }) + + const testsRoot = path.resolve(__dirname, ".") + const files = await glob("**/**.test.js", { cwd: testsRoot }) + + files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f))) + + try { + return new Promise((resolve, reject) => { + mocha.run((failures) => { + failures > 0 ? reject(new Error(`${failures} tests failed.`)) : resolve() + }) + }) + } catch (err) { + console.error(err) + throw err + } +} +``` + +### TypeScript Configuration + +E2E tests require specific TypeScript configuration: + +```json +// e2e/tsconfig.json +{ + "compilerOptions": { + "module": "commonjs", + "target": "ES2020", + "lib": ["ES2020"], + "sourceMap": true, + "strict": true, + "types": ["mocha", "node", "@vscode/test-electron"] + }, + "exclude": ["node_modules", ".vscode-test"] +} +``` + +## Unit Tests + +Unit tests focus on testing individual functions, classes, and components in isolation. + +### Backend Unit Tests + +Backend unit tests verify the functionality of core services and utilities: + +#### MetadataScanner Tests + +```typescript +describe("MetadataScanner", () => { + let scanner: MetadataScanner + + beforeEach(() => { + scanner = new MetadataScanner() + }) + + describe("parseMetadataFile", () => { + it("should parse valid YAML metadata", async () => { + // Mock file system + jest.spyOn(fs, "readFile").mockImplementation((path, options, callback) => { + callback( + null, + Buffer.from(` + name: "Test Package" + description: "A test package" + version: "1.0.0" + type: "package" + `), + ) + }) + + const result = await scanner["parseMetadataFile"]("test/path/metadata.en.yml") + + expect(result).toEqual({ + name: "Test Package", + description: "A test package", + version: "1.0.0", + type: "package", + }) + }) + + it("should handle invalid YAML", async () => { + // Mock file system with invalid YAML + jest.spyOn(fs, "readFile").mockImplementation((path, options, callback) => { + callback( + null, + Buffer.from(` + name: "Invalid YAML + description: Missing quote + `), + ) + }) + + await expect(scanner["parseMetadataFile"]("test/path/metadata.en.yml")).rejects.toThrow() + }) + }) + + describe("scanDirectory", () => { + // Tests for directory scanning + }) +}) +``` + +#### MarketplaceManager Tests + +```typescript +describe("MarketplaceManager", () => { + let manager: MarketplaceManager + let mockContext: vscode.ExtensionContext + + beforeEach(() => { + // Create mock context + mockContext = { + extensionPath: "/test/path", + globalStorageUri: { fsPath: "/test/storage" }, + globalState: { + get: jest.fn().mockImplementation((key, defaultValue) => defaultValue), + update: jest.fn().mockResolvedValue(undefined), + }, + } as unknown as vscode.ExtensionContext + + manager = new MarketplaceManager(mockContext) + }) + + describe("filterItems", () => { + it("should filter by type", () => { + // Set up test data + manager["currentItems"] = [ + { name: "Item 1", type: "mode", description: "Test item 1" }, + { name: "Item 2", type: "package", description: "Test item 2" }, + ] as MarketplaceItem[] + + const result = manager.filterItems({ type: "mode" }) + + expect(result).toHaveLength(1) + expect(result[0].name).toBe("Item 1") + }) + + it("should filter by search term", () => { + // Set up test data + manager["currentItems"] = [ + { name: "Alpha Item", type: "mode", description: "Test item" }, + { name: "Beta Item", type: "package", description: "Another test" }, + ] as MarketplaceItem[] + + const result = manager.filterItems({ search: "alpha" }) + + expect(result).toHaveLength(1) + expect(result[0].name).toBe("Alpha Item") + }) + + // More filter tests... + }) + + describe("addSource", () => { + // Tests for adding sources + }) +}) +``` + +#### Search Utilities Tests + +```typescript +describe("searchUtils", () => { + describe("containsSearchTerm", () => { + it("should return true for exact matches", () => { + expect(containsSearchTerm("hello world", "hello")).toBe(true) + }) + + it("should be case insensitive", () => { + expect(containsSearchTerm("Hello World", "hello")).toBe(true) + expect(containsSearchTerm("hello world", "WORLD")).toBe(true) + }) + + it("should handle undefined inputs", () => { + expect(containsSearchTerm(undefined, "test")).toBe(false) + expect(containsSearchTerm("test", "")).toBe(false) + }) + }) + + describe("itemMatchesSearch", () => { + it("should match on name", () => { + const item = { + name: "Test Item", + description: "Description", + } + + expect(itemMatchesSearch(item, "test")).toEqual({ + matched: true, + matchReason: { + nameMatch: true, + descriptionMatch: false, + }, + }) + }) + + // More search matching tests... + }) +}) +``` + +### Frontend Unit Tests + +Frontend unit tests verify the functionality of UI components: + +#### MarketplaceItemCard Tests + +```typescript +describe("MarketplaceItemCard", () => { + const mockItem: MarketplaceItem = { + name: "Test Package", + description: "A test package", + type: "package", + url: "https://example.com", + repoUrl: "https://github.com/example/repo", + tags: ["test", "example"], + version: "1.0.0", + lastUpdated: "2025-04-01" + }; + + const mockFilters = { type: "", search: "", tags: [] }; + const mockSetFilters = jest.fn(); + const mockSetActiveTab = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it("renders correctly", () => { + render( + + ); + + expect(screen.getByText("Test Package")).toBeInTheDocument(); + expect(screen.getByText("A test package")).toBeInTheDocument(); + expect(screen.getByText("Package")).toBeInTheDocument(); + }); + + it("handles tag clicks", () => { + render( + + ); + + fireEvent.click(screen.getByText("test")); + + expect(mockSetFilters).toHaveBeenCalledWith({ + type: "", + search: "", + tags: ["test"] + }); + }); + + // More component tests... +}); +``` + +#### ExpandableSection Tests + +```typescript +describe("ExpandableSection", () => { + it("renders collapsed by default", () => { + render( + +
Test Content
+
+ ); + + expect(screen.getByText("Test Section")).toBeInTheDocument(); + expect(screen.queryByText("Test Content")).not.toBeVisible(); + }); + + it("expands when clicked", () => { + render( + +
Test Content
+
+ ); + + fireEvent.click(screen.getByText("Test Section")); + + expect(screen.getByText("Test Content")).toBeVisible(); + }); + + it("can be expanded by default", () => { + render( + +
Test Content
+
+ ); + + expect(screen.getByText("Test Content")).toBeVisible(); + }); + + // More component tests... +}); +``` + +#### TypeGroup Tests + +```typescript +describe("TypeGroup", () => { + const mockItems = [ + { name: "Item 1", description: "Description 1" }, + { name: "Item 2", description: "Description 2" } + ]; + + it("renders type heading and items", () => { + render(); + + expect(screen.getByText("Modes")).toBeInTheDocument(); + expect(screen.getByText("Item 1")).toBeInTheDocument(); + expect(screen.getByText("Item 2")).toBeInTheDocument(); + }); + + it("highlights items matching search term", () => { + render(); + + const item1 = screen.getByText("Item 1"); + const item2 = screen.getByText("Item 2"); + + expect(item1.className).toContain("text-vscode-textLink"); + expect(item2.className).not.toContain("text-vscode-textLink"); + expect(screen.getByText("match")).toBeInTheDocument(); + }); + + // More component tests... +}); +``` + +## Integration Tests + +Integration tests verify that different components work together correctly. + +### Backend Integration Tests + +```typescript +describe("Marketplace Integration", () => { + let manager: MarketplaceManager + let metadataScanner: MetadataScanner + let templateItems: MarketplaceItem[] + + beforeAll(async () => { + // Load real data from template + metadataScanner = new MetadataScanner() + const templatePath = path.resolve(__dirname, "marketplace-template") + templateItems = await metadataScanner.scanDirectory(templatePath, "https://example.com") + }) + + beforeEach(() => { + // Create a real context-like object + const context = { + extensionPath: path.resolve(__dirname, "../../../../"), + globalStorageUri: { fsPath: path.resolve(__dirname, "../../../../mock/settings/path") }, + } as vscode.ExtensionContext + + // Create real instances + manager = new MarketplaceManager(context) + + // Set up manager with template data + manager["currentItems"] = [...templateItems] + }) + + describe("Message Handler Integration", () => { + it("should handle search messages", async () => { + const message = { + type: "search", + search: "data platform", + typeFilter: "", + tagFilters: [], + } + + const result = await handleMarketplaceMessages(message, manager) + + expect(result.type).toBe("searchResults") + expect(result.data).toHaveLength(1) + expect(result.data[0].name).toContain("Data Platform") + }) + + it("should handle type filter messages", async () => { + const message = { + type: "search", + search: "", + typeFilter: "mode", + tagFilters: [], + } + + const result = await handleMarketplaceMessages(message, manager) + + expect(result.type).toBe("searchResults") + expect(result.data.every((item) => item.type === "mode")).toBe(true) + }) + + // More message handler tests... + }) + + describe("End-to-End Flow", () => { + it("should find items with matching subcomponents", async () => { + const message = { + type: "search", + search: "validator", + typeFilter: "", + tagFilters: [], + } + + const result = await handleMarketplaceMessages(message, manager) + + expect(result.data.length).toBeGreaterThan(0) + + // Check that subcomponents are marked as matches + const hasMatchingSubcomponent = result.data.some((item) => + item.items?.some((subItem) => subItem.matchInfo?.matched), + ) + expect(hasMatchingSubcomponent).toBe(true) + }) + + // More end-to-end flow tests... + }) +}) +``` + +### Frontend Integration Tests + +```typescript +describe("Marketplace UI Integration", () => { + const mockItems: MarketplaceItem[] = [ + { + name: "Test Package", + description: "A test package", + type: "package", + url: "https://example.com", + repoUrl: "https://github.com/example/repo", + tags: ["test", "example"], + items: [ + { + type: "mode", + path: "/test/path", + metadata: { + name: "Test Mode", + description: "A test mode", + type: "mode" + } + } + ] + }, + { + name: "Test Mode", + description: "Another test item", + type: "mode", + url: "https://example.com", + repoUrl: "https://github.com/example/repo", + tags: ["example"] + } + ]; + + beforeEach(() => { + // Mock VSCode API + (vscode.postMessage as jest.Mock).mockClear(); + }); + + it("should filter items when search is entered", async () => { + render(); + + // Both items should be visible initially + expect(screen.getByText("Test Package")).toBeInTheDocument(); + expect(screen.getByText("Test Mode")).toBeInTheDocument(); + + // Enter search term + const searchInput = screen.getByPlaceholderText("Search items..."); + fireEvent.change(searchInput, { target: { value: "another" } }); + + // Wait for debounce + await waitFor(() => { + expect(screen.queryByText("Test Package")).not.toBeInTheDocument(); + expect(screen.getByText("Test Mode")).toBeInTheDocument(); + }); + }); + + it("should expand details when search matches subcomponents", async () => { + render(); + + // Enter search term that matches a subcomponent + const searchInput = screen.getByPlaceholderText("Search items..."); + fireEvent.change(searchInput, { target: { value: "test mode" } }); + + // Wait for debounce and expansion + await waitFor(() => { + expect(screen.getByText("Test Mode")).toBeInTheDocument(); + expect(screen.getByText("A test mode")).toBeInTheDocument(); + }); + + // Check that the match is highlighted + const modeElement = screen.getByText("Test Mode"); + expect(modeElement.className).toContain("text-vscode-textLink"); + }); + + // More UI integration tests... +}); +``` + +## Test Data Management + +The Marketplace uses several approaches to manage test data: + +### Mock Data + +Mock data is used for simple unit tests: + +```typescript +const mockItems: MarketplaceItem[] = [ + { + name: "Test Package", + description: "A test package", + type: "package", + url: "https://example.com", + repoUrl: "https://github.com/example/repo", + tags: ["test", "example"], + version: "1.0.0", + }, + // More mock items... +] +``` + +### Test Fixtures + +Test fixtures provide more complex data structures: + +```typescript +// fixtures/metadata.ts +export const metadataFixtures = { + basic: { + name: "Basic Package", + description: "A basic package for testing", + version: "1.0.0", + type: "package", + }, + + withTags: { + name: "Tagged Package", + description: "A package with tags", + version: "1.0.0", + type: "package", + tags: ["test", "fixture", "example"], + }, + + withSubcomponents: { + name: "Complex Package", + description: "A package with subcomponents", + version: "1.0.0", + type: "package", + items: [ + { + type: "mode", + path: "/test/path/mode", + metadata: { + name: "Test Mode", + description: "A test mode", + type: "mode", + }, + }, + { + type: "mcp", + path: "/test/path/server", + metadata: { + name: "Test Server", + description: "A test server", + type: "mcp", + }, + }, + ], + }, +} +``` + +### Template Data + +Real template data is used for integration tests: + +```typescript +beforeAll(async () => { + // Load real data from template + metadataScanner = new MetadataScanner() + const templatePath = path.resolve(__dirname, "marketplace-template") + templateItems = await metadataScanner.scanDirectory(templatePath, "https://example.com") +}) +``` + +### Test Data Generators + +Generators create varied test data: + +```typescript +// Test data generator +function generatePackageItems(count: number): MarketplaceItem[] { + const types: MarketplaceItemType[] = ["mode", "mcp", "package", "prompt"] + const tags = ["test", "example", "data", "ui", "server", "client"] + + return Array.from({ length: count }, (_, i) => { + const type = types[i % types.length] + const randomTags = tags.filter(() => Math.random() > 0.5).slice(0, Math.floor(Math.random() * 4)) + + return { + name: `Test ${type} ${i + 1}`, + description: `This is a test ${type} for testing purposes`, + type, + url: `https://example.com/${type}/${i + 1}`, + repoUrl: "https://github.com/example/repo", + tags: randomTags.length ? randomTags : undefined, + version: "1.0.0", + lastUpdated: new Date().toISOString(), + items: type === "package" ? generateSubcomponents(Math.floor(Math.random() * 5) + 1) : undefined, + } + }) +} + +function generateSubcomponents(count: number): MarketplaceItem["items"] { + const types: MarketplaceItemType[] = ["mode", "mcp", "prompt"] + + return Array.from({ length: count }, (_, i) => { + const type = types[i % types.length] + + return { + type, + path: `/test/path/${type}/${i + 1}`, + metadata: { + name: `Test ${type} ${i + 1}`, + description: `This is a test ${type} subcomponent`, + type, + }, + } + }) +} +``` + +## Type Filter Test Plan + +This section outlines the test plan for the type filtering functionality in the Marketplace, particularly focusing on the improvements to make type filter behavior consistent with search term behavior. + +### Unit Tests + +#### 1. Basic Type Filtering Tests + +**Test: Filter by Package Type** + +- **Input**: Items with various types including "package" +- **Filter**: `{ type: "package" }` +- **Expected**: Only items with type "package" are returned +- **Verification**: Check that the returned items all have type "package" + +**Test: Filter by Mode Type** + +- **Input**: Items with various types including "mode" +- **Filter**: `{ type: "mode" }` +- **Expected**: Only items with type "mode" are returned +- **Verification**: Check that the returned items all have type "mode" + +**Test: Filter by mcp Type** + +- **Input**: Items with various types including "mcp" +- **Filter**: `{ type: "mcp" }` +- **Expected**: Only items with type "mcp" are returned +- **Verification**: Check that the returned items all have type "mcp" + +#### 2. Package with Subcomponents Tests + +**Test: Package with Matching Subcomponents** + +- **Input**: A package with subcomponents of various types +- **Filter**: `{ type: "mode" }` +- **Expected**: The package is returned if it contains at least one subcomponent with type "mode" +- **Verification**: + - Check that the package is returned + - Check that `item.matchInfo.matched` is `true` + - Check that `item.matchInfo.matchReason.hasMatchingSubcomponents` is `true` + - Check that subcomponents with type "mode" have `subItem.matchInfo.matched` set to `true` + - Check that subcomponents with other types have `subItem.matchInfo.matched` set to `false` + +**Test: Package with No Matching Subcomponents** + +- **Input**: A package with subcomponents of various types, but none matching the filter +- **Filter**: `{ type: "prompt" }` +- **Expected**: The package is not returned +- **Verification**: Check that the package is not in the returned items + +**Test: Package with No Subcomponents** + +- **Input**: A package with no subcomponents +- **Filter**: `{ type: "mode" }` +- **Expected**: The package is not returned (since it's not a mode and has no subcomponents) +- **Verification**: Check that the package is not in the returned items + +#### 3. Combined Filtering Tests + +**Test: Type Filter and Search Term** + +- **Input**: Various items including packages with subitems +- **Filter**: `{ type: "mode", search: "test" }` +- **Expected**: Only items that match both the type filter and the search term are returned +- **Verification**: + - Check that all returned items have type "mode" or are packages with mode subcomponents + - Check that all returned items have "test" in their name or description, or have subcomponents with "test" in their name or description + +**Test: Type Filter and Tags** + +- **Input**: Various items with different tags +- **Filter**: `{ type: "mode", tags: ["test"] }` +- **Expected**: Only items that match both the type filter and have the "test" tag are returned +- **Verification**: Check that all returned items have type "mode" or are packages with mode subcomponents, and have the "test" tag + +### Integration Tests + +#### 1. UI Display Tests + +**Test: Type Filter UI Updates** + +- **Action**: Apply a type filter in the UI +- **Expected**: + - The UI shows only items that match the filter + - For packages, subcomponents that match the filter are highlighted or marked in some way +- **Verification**: Visually inspect the UI to ensure it correctly displays which items and subcomponents match the filter + +**Test: Type Filter and Search Combination** + +- **Action**: Apply both a type filter and a search term in the UI +- **Expected**: The UI shows only items that match both the type filter and the search term +- **Verification**: Visually inspect the UI to ensure it correctly displays which items match both filters + +#### 2. Real Data Tests + +**Test: Filter with Real Package Data** + +- **Input**: Real package data from the default package source +- **Action**: Apply various type filters +- **Expected**: The results match the expected behavior for each filter +- **Verification**: Check that the results are consistent with the expected behavior + +### Regression Tests + +#### 1. Search Term Filtering + +**Test: Search Term Only** + +- **Input**: Various items including packages with subcomponents +- **Filter**: `{ search: "test" }` +- **Expected**: The behavior is unchanged from before the type filter improvements +- **Verification**: Compare the results with the expected behavior from the previous implementation + +#### 2. Tag Filtering + +**Test: Tag Filter Only** + +- **Input**: Various items with different tags +- **Filter**: `{ tags: ["test"] }` +- **Expected**: The behavior is unchanged from before the type filter improvements +- **Verification**: Compare the results with the expected behavior from the previous implementation + +#### 3. No Filters + +**Test: No Filters Applied** + +- **Input**: Various items +- **Filter**: `{}` +- **Expected**: All items are returned +- **Verification**: Check that all items are returned and that their `matchInfo` properties are set correctly + +### Edge Cases + +#### 1. Empty Input + +**Test: Empty Items Array** + +- **Input**: Empty array +- **Filter**: `{ type: "mode" }` +- **Expected**: Empty array is returned +- **Verification**: Check that an empty array is returned + +#### 2. Invalid Filters + +**Test: Invalid Type** + +- **Input**: Various items +- **Filter**: `{ type: "invalid" as MarketplaceItemType }` +- **Expected**: No items are returned (since none match the invalid type) +- **Verification**: Check that an empty array is returned + +#### 3. Null or Undefined Values + +**Test: Null Subcomponents** + +- **Input**: A package with `items: null` +- **Filter**: `{ type: "mode" }` +- **Expected**: The package is not returned (since it has no subcomponents to match) +- **Verification**: Check that the package is not in the returned items + +**Test: Undefined Metadata** + +- **Input**: A package with subcomponents that have `metadata: undefined` +- **Filter**: `{ type: "mode" }` +- **Expected**: The package is returned if any subcomponents have type "mode" +- **Verification**: Check that the package is returned if appropriate and that subcomponents with undefined metadata are handled correctly + +### Performance Tests + +#### 1. Large Dataset + +**Test: Filter Large Dataset** + +- **Input**: A large number of items (e.g., 1000+) +- **Filter**: Various filters +- **Expected**: The filtering completes in a reasonable time +- **Verification**: Measure the time taken to filter the items and ensure it's within acceptable limits + +#### 2. Deep Nesting + +**Test: Deeply Nested Items** + +- **Input**: Items with deeply nested subcomponents +- **Filter**: Various filters +- **Expected**: The filtering correctly handles the nested structure +- **Verification**: Check that the results are correct for deeply nested structures + +## Test Organization + +The Marketplace tests are organized by functionality rather than by file structure: + +### Consolidated Test Files + +``` +src/services/marketplace/__tests__/ +├── Marketplace.consolidated.test.ts # Combined tests +├── searchUtils.test.ts # Search utility tests +└── PackageSubcomponents.test.ts # Subcomponent tests +``` + +### Test Structure + +Tests are organized into logical groups: + +```typescript +describe("Marketplace", () => { + // Shared setup + + describe("Direct Filtering", () => { + // Tests for filtering functionality + }) + + describe("Message Handler Integration", () => { + // Tests for message handling + }) + + describe("Sorting", () => { + // Tests for sorting functionality + }) +}) +``` + +## Test Coverage + +The Marketplace maintains high test coverage: + +### Coverage Goals + +- **Backend Logic**: 90%+ coverage +- **UI Components**: 80%+ coverage +- **Integration Points**: 85%+ coverage + +### Coverage Reporting + +```typescript +// jest.config.js +module.exports = { + // ...other config + collectCoverage: true, + coverageReporters: ["text", "lcov", "html"], + coverageThreshold: { + global: { + branches: 80, + functions: 85, + lines: 85, + statements: 85, + }, + "src/services/marketplace/*.ts": { + branches: 90, + functions: 90, + lines: 90, + statements: 90, + }, + }, +} +``` + +### Critical Path Testing + +Critical paths have additional test coverage: + +1. **Search and Filter**: Comprehensive tests for all filter combinations +2. **Message Handling**: Tests for all message types and error conditions +3. **UI Interactions**: Tests for all user interaction flows + +## Test Performance + +The Marketplace tests are optimized for performance: + +### Fast Unit Tests + +```typescript +// Fast unit tests with minimal dependencies +describe("containsSearchTerm", () => { + it("should return true for exact matches", () => { + expect(containsSearchTerm("hello world", "hello")).toBe(true) + }) + + // More tests... +}) +``` + +### Optimized Integration Tests + +```typescript +// Optimized integration tests +describe("Marketplace Integration", () => { + // Load template data once for all tests + beforeAll(async () => { + templateItems = await metadataScanner.scanDirectory(templatePath) + }) + + // Create fresh manager for each test + beforeEach(() => { + manager = new MarketplaceManager(mockContext) + manager["currentItems"] = [...templateItems] + }) + + // Tests... +}) +``` + +### Parallel Test Execution + +```typescript +// jest.config.js +module.exports = { + // ...other config + maxWorkers: "50%", // Use 50% of available cores + maxConcurrency: 5, // Run up to 5 tests concurrently +} +``` + +## Continuous Integration + +The Marketplace tests are integrated into the CI/CD pipeline: + +### GitHub Actions Workflow + +```yaml +# .github/workflows/test.yml +name: Tests + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: "16" + + - name: Install dependencies + run: npm ci + + - name: Run tests + run: npm test + + - name: Upload coverage + uses: codecov/codecov-action@v2 + with: + file: ./coverage/lcov.info +``` + +### Pre-commit Hooks + +```json +// package.json +{ + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "*.{ts,tsx}": ["eslint --fix", "jest --findRelatedTests"] + } +} +``` + +## Test Debugging + +The Marketplace includes tools for debugging tests: + +### Debug Logging + +```typescript +// Debug logging in tests +describe("Complex integration test", () => { + it("should handle complex search", async () => { + // Enable debug logging for this test + const originalDebug = process.env.DEBUG + process.env.DEBUG = "marketplace:*" + + // Test logic... + + // Restore debug setting + process.env.DEBUG = originalDebug + }) +}) +``` + +### Visual Debugging + +```typescript +// Visual debugging for UI tests +describe("UI component test", () => { + it("should render correctly", async () => { + const { container } = render(); + + // Save screenshot for visual debugging + if (process.env.SAVE_SCREENSHOTS) { + const screenshot = await page.screenshot(); + fs.writeFileSync("./screenshots/item-card.png", screenshot); + } + + // Test assertions... + }); +}); +``` + +## Test Documentation + +The Marketplace tests include comprehensive documentation: + +### Test Comments + +```typescript +/** + * Tests the search functionality with various edge cases + * + * Edge cases covered: + * - Empty search term + * - Case sensitivity + * - Special characters + * - Very long search terms + * - Matching in subcomponents + */ +describe("Search functionality", () => { + // Tests... +}) +``` + +### Test Scenarios + +```typescript +describe("Package filtering", () => { + /** + * Scenario: User filters by type and search term + * Given: A list of items of different types + * When: The user selects a type filter and enters a search term + * Then: Only items of the selected type containing the search term should be shown + */ + it("should combine type and search filters", () => { + // Test implementation... + }) +}) +``` + +--- + +**Previous**: [UI Component Design](./05-ui-components.md) | **Next**: [Extending the Marketplace](./07-extending.md) diff --git a/cline_docs/marketplace/implementation/07-extending.md b/cline_docs/marketplace/implementation/07-extending.md new file mode 100644 index 0000000000..73e6e0e2c2 --- /dev/null +++ b/cline_docs/marketplace/implementation/07-extending.md @@ -0,0 +1,926 @@ +# Extending the Marketplace + +This document provides guidance on extending the Marketplace with new features, component types, and customizations. + +## Adding New Component Types + +The Marketplace is designed to be extensible, allowing for the addition of new component types beyond the default ones (mode, mcp, prompt, package). + +### Extending the MarketplaceItemType + +To add a new component type: + +1. **Update the MarketplaceItemType Type**: + +```typescript +/** + * Supported component types + */ +export type MarketplaceItemType = "mode" | "prompt" | "package" | "mcp" | "your-new-type" +``` + +2. **Update Type Label Functions**: + +```typescript +const getTypeLabel = (type: string) => { + switch (type) { + case "mode": + return "Mode" + case "mcp": + return "MCP Server" + case "prompt": + return "Prompt" + case "package": + return "Package" + case "your-new-type": + return "Your New Type" + default: + return "Other" + } +} +``` + +3. **Update Type Color Functions**: + +```typescript +const getTypeColor = (type: string) => { + switch (type) { + case "mode": + return "bg-blue-600" + case "mcp": + return "bg-green-600" + case "prompt": + return "bg-purple-600" + case "package": + return "bg-orange-600" + case "your-new-type": + return "bg-yellow-600" // Choose a distinctive color + default: + return "bg-gray-600" + } +} +``` + +4. **Update Type Group Labels**: + +```typescript +const getTypeGroupLabel = (type: string) => { + switch (type) { + case "mode": + return "Modes" + case "mcp": + return "MCP Servers" + case "prompt": + return "Prompts" + case "package": + return "Packages" + case "your-new-type": + return "Your New Types" + default: + return `${type.charAt(0).toUpperCase()}${type.slice(1)}s` + } +} +``` + +### Directory Structure for New Types + +When adding a new component type, follow this directory structure in your source repository: + +``` +repository-root/ +├── metadata.en.yml +├── your-new-type/ # Directory for your new component type +│ ├── component-1/ +│ │ └── metadata.en.yml +│ └── component-2/ +│ └── metadata.en.yml +└── ... +``` + +### Metadata for New Types + +The metadata for your new component type should follow the standard format: + +```yaml +name: "Your Component Name" +description: "Description of your component" +version: "1.0.0" +type: "your-new-type" +tags: + - relevant-tag-1 + - relevant-tag-2 +``` + +### UI Considerations for New Types + +When adding a new component type, consider these UI aspects: + +1. **Type Filtering**: + + - Add your new type to the type filter options + - Ensure proper labeling and styling + +2. **Type-Specific Rendering**: + + - Consider if your type needs special rendering in the UI + - Add any type-specific UI components or styles + +3. **Type Icons**: + - Choose an appropriate icon for your type + - Add it to the icon mapping + +```typescript +const getTypeIcon = (type: string) => { + switch (type) { + case "mode": + return "codicon-person" + case "mcp": + return "codicon-server" + case "prompt": + return "codicon-comment" + case "package": + return "codicon-package" + case "your-new-type": + return "codicon-your-icon" // Choose an appropriate icon + default: + return "codicon-symbol-misc" + } +} +``` + +## Creating Custom Templates + +You can create custom templates to provide a starting point for users creating new components. + +### Template Structure + +A custom template should follow this structure: + +``` +custom-template/ +├── metadata.en.yml +├── README.md +└── [component-specific files] +``` + +### Template Metadata + +The template metadata should include: + +```yaml +name: "Your Template Name" +description: "Description of your template" +version: "1.0.0" +type: "your-component-type" +template: true +templateFor: "your-component-type" +``` + +### Template Registration + +Register your template with the Marketplace: + +```typescript +// In your extension code +const registerTemplates = (context: vscode.ExtensionContext) => { + const templatePath = path.join(context.extensionPath, "templates", "your-template") + marketplace.registerTemplate(templatePath) +} +``` + +### Template Usage + +Users can create new components from your template: + +```typescript +// In the UI +const createFromTemplate = (templateName: string) => { + vscode.postMessage({ + type: "createFromTemplate", + templateName, + }) +} +``` + +## Implementing New Features + +The Marketplace is designed to be extended with new features. Here's how to implement common types of features: + +### Adding a New Filter Type + +To add a new filter type (beyond type, search, and tags): + +1. **Update the Filters Interface**: + +```typescript +interface Filters { + type: string + search: string + tags: string[] + yourNewFilter: string // Add your new filter +} +``` + +2. **Update the Filter Function**: + +```typescript +export function filterItems( + items: MarketplaceItem[], + filters: { + type?: string + search?: string + tags?: string[] + yourNewFilter?: string // Add your new filter + }, +): MarketplaceItem[] { + // Existing filter logic... + + // Add your new filter logic + if (filters.yourNewFilter) { + result = result.filter((item) => { + // Your filter implementation + return yourFilterLogic(item, filters.yourNewFilter) + }) + } + + return result +} +``` + +3. **Add UI Controls**: + +```tsx +const YourNewFilterControl: React.FC<{ + value: string + onChange: (value: string) => void +}> = ({ value, onChange }) => { + return ( +
+

Your New Filter

+ {/* Your filter UI controls */} +
+ ) +} +``` + +4. **Integrate with the Main UI**: + +```tsx + + + + + + +``` + +### Adding a New View Mode + +To add a new view mode (beyond the card view): + +1. **Add a View Mode State**: + +```typescript +type ViewMode = "card" | "list" | "yourNewView" + +const [viewMode, setViewMode] = useState("card") +``` + +2. **Create the View Component**: + +```tsx +const YourNewView: React.FC<{ + items: MarketplaceItem[] + filters: Filters + setFilters: (filters: Filters) => void +}> = ({ items, filters, setFilters }) => { + return
{/* Your view implementation */}
+} +``` + +3. **Add View Switching Controls**: + +```tsx +const ViewModeSelector: React.FC<{ + viewMode: ViewMode + setViewMode: (mode: ViewMode) => void +}> = ({ viewMode, setViewMode }) => { + return ( +
+ + + +
+ ) +} +``` + +4. **Integrate with the Main UI**: + +```tsx +
+
+ + {/* Other toolbar items */} +
+ +
+ {viewMode === "card" && } + {viewMode === "list" && } + {viewMode === "yourNewView" && } +
+
+``` + +### Adding Custom Actions + +To add custom actions for package items: + +1. **Create an Action Handler**: + +```typescript +const handleCustomAction = (item: MarketplaceItem) => { + vscode.postMessage({ + type: "customAction", + item: item.name, + itemType: item.type, + }) +} +``` + +2. **Add Action Button to the UI**: + +```tsx + +``` + +3. **Handle the Action in the Message Handler**: + +```typescript +case "customAction": + // Handle the custom action + const { item, itemType } = message; + // Your custom action implementation + return { + type: "customActionResult", + success: true, + data: { /* result data */ } + }; +``` + +## Customizing the UI + +The Marketplace UI can be customized in several ways: + +### Custom Styling + +To customize the styling: + +1. **Add Custom CSS Variables**: + +```css +/* In your CSS file */ +:root { + --package-card-bg: var(--vscode-panel-background); + --package-card-border: var(--vscode-panel-border); + --package-card-hover: var(--vscode-list-hoverBackground); + --your-custom-variable: #your-color; +} +``` + +2. **Use Custom Classes**: + +```tsx +
+
{/* Your custom UI */}
+
+``` + +3. **Add Custom Themes**: + +```typescript +type Theme = "default" | "compact" | "detailed" | "yourCustomTheme" + +const [theme, setTheme] = useState("default") + +// Theme-specific styles +const getThemeClasses = (theme: Theme) => { + switch (theme) { + case "compact": + return "compact-theme" + case "detailed": + return "detailed-theme" + case "yourCustomTheme": + return "your-custom-theme" + default: + return "default-theme" + } +} +``` + +### Custom Components + +To replace or extend existing components: + +1. **Create a Custom Component**: + +```tsx +const CustomPackageCard: React.FC = (props) => { + // Your custom implementation + return ( +
+ {/* Your custom UI */} +

{props.item.name}

+ {/* Additional custom elements */} +
{/* Custom footer content */}
+
+ ) +} +``` + +2. **Use Component Injection**: + +```tsx +interface ComponentOverrides { + PackageCard?: React.MarketplaceItemType + ExpandableSection?: React.MarketplaceItemType + TypeGroup?: React.MarketplaceItemType +} + +const MarketplaceView: React.FC<{ + initialItems: MarketplaceItem[] + componentOverrides?: ComponentOverrides +}> = ({ initialItems, componentOverrides = {} }) => { + // Component selection logic + const PackageCard = componentOverrides.PackageCard || MarketplaceItemCard + + return ( +
+ {items.map((item) => ( + + ))} +
+ ) +} +``` + +### Custom Layouts + +To implement custom layouts: + +1. **Create a Layout Component**: + +```tsx +const CustomLayout: React.FC<{ + sidebar: React.ReactNode + content: React.ReactNode + footer?: React.ReactNode +}> = ({ sidebar, content, footer }) => { + return ( +
+
{sidebar}
+
{content}
+ {footer &&
{footer}
} +
+ ) +} +``` + +2. **Use the Layout in the Main UI**: + +```tsx + + } + content={ +
+ {filteredItems.map((item) => ( + + ))} +
+ } + footer={
{`Showing ${filteredItems.length} of ${items.length} packages`}
} +/> +``` + +## Extending Backend Functionality + +The Marketplace backend can be extended with new functionality: + +### Custom Source Providers + +To add support for new source types: + +1. **Create a Source Provider Interface**: + +```typescript +interface SourceProvider { + type: string + canHandle(url: string): boolean + fetchItems(url: string): Promise +} +``` + +2. **Implement a Custom Provider**: + +```typescript +class CustomSourceProvider implements SourceProvider { + type = "custom" + + canHandle(url: string): boolean { + return url.startsWith("custom://") + } + + async fetchItems(url: string): Promise { + // Your custom implementation + // Fetch items from your custom source + return items + } +} +``` + +3. **Register the Provider**: + +```typescript +// In your extension code +const registerSourceProviders = (marketplace: MarketplaceManager) => { + marketplace.registerSourceProvider(new CustomSourceProvider()) +} +``` + +### Custom Metadata Processors + +To add support for custom metadata formats: + +1. **Create a Metadata Processor Interface**: + +```typescript +interface MetadataProcessor { + canProcess(filePath: string): boolean + process(filePath: string, content: string): Promise +} +``` + +2. **Implement a Custom Processor**: + +```typescript +class CustomMetadataProcessor implements MetadataProcessor { + canProcess(filePath: string): boolean { + return filePath.endsWith(".custom") + } + + async process(filePath: string, content: string): Promise { + // Your custom processing logic + return processedMetadata + } +} +``` + +3. **Register the Processor**: + +```typescript +// In your extension code +const registerMetadataProcessors = (metadataScanner: MetadataScanner) => { + metadataScanner.registerProcessor(new CustomMetadataProcessor()) +} +``` + +### Custom Message Handlers + +To add support for custom messages: + +1. **Extend the Message Handler**: + +```typescript +// In your extension code +const extendMessageHandler = () => { + const originalHandler = handleMarketplaceMessages + + return async (message: any, marketplace: MarketplaceManager) => { + // Handle custom messages + if (message.type === "yourCustomMessage") { + // Your custom message handling + return { + type: "yourCustomResponse", + data: { + /* response data */ + }, + } + } + + // Fall back to the original handler + return originalHandler(message, marketplace) + } +} +``` + +2. **Register the Extended Handler**: + +```typescript +// In your extension code +const customMessageHandler = extendMessageHandler() +context.subscriptions.push( + vscode.commands.registerCommand("marketplace.handleMessage", (message) => { + return customMessageHandler(message, marketplace) + }), +) +``` + +## Integration with Other Systems + +The Marketplace can be integrated with other systems: + +### Integration with External APIs + +To integrate with external APIs: + +1. **Create an API Client**: + +```typescript +class ExternalApiClient { + private baseUrl: string + + constructor(baseUrl: string) { + this.baseUrl = baseUrl + } + + async fetchPackages(): Promise { + const response = await fetch(`${this.baseUrl}/packages`) + const data = await response.json() + + // Transform API data to MarketplaceItem format + return data.map((item) => ({ + name: item.name, + description: item.description, + type: item.type, + url: item.url, + repoUrl: item.repository_url, + // Map other fields + })) + } +} +``` + +2. **Create a Source Provider for the API**: + +```typescript +class ApiSourceProvider implements SourceProvider { + private apiClient: ExternalApiClient + + constructor(apiUrl: string) { + this.apiClient = new ExternalApiClient(apiUrl) + } + + type = "api" + + canHandle(url: string): boolean { + return url.startsWith("api://") + } + + async fetchItems(url: string): Promise { + return this.apiClient.fetchPackages() + } +} +``` + +3. **Register the API Provider**: + +```typescript +// In your extension code +const registerApiProvider = (marketplace: MarketplaceManager) => { + marketplace.registerSourceProvider(new ApiSourceProvider("https://your-api.example.com")) +} +``` + +### Integration with Authentication Systems + +To integrate with authentication systems: + +1. **Create an Authentication Provider**: + +```typescript +class AuthProvider { + private token: string | null = null + + async login(): Promise { + // Your authentication logic + this.token = "your-auth-token" + return true + } + + async getToken(): Promise { + if (!this.token) { + await this.login() + } + return this.token + } + + isAuthenticated(): boolean { + return !!this.token + } +} +``` + +2. **Use Authentication in API Requests**: + +```typescript +class AuthenticatedApiClient extends ExternalApiClient { + private authProvider: AuthProvider + + constructor(baseUrl: string, authProvider: AuthProvider) { + super(baseUrl) + this.authProvider = authProvider + } + + async fetchPackages(): Promise { + const token = await this.authProvider.getToken() + + if (!token) { + throw new Error("Authentication required") + } + + const response = await fetch(`${this.baseUrl}/packages`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + + // Process response as before + } +} +``` + +### Integration with Local Development Tools + +To integrate with local development tools: + +1. **Create a Local Development Provider**: + +```typescript +class LocalDevProvider { + private workspacePath: string + + constructor(workspacePath: string) { + this.workspacePath = workspacePath + } + + async createLocalPackage(template: string, name: string): Promise { + const targetPath = path.join(this.workspacePath, name) + + // Create directory + await fs.promises.mkdir(targetPath, { recursive: true }) + + // Copy template files + // Your implementation + + return targetPath + } + + async buildLocalPackage(packagePath: string): Promise { + // Your build implementation + return true + } + + async testLocalPackage(packagePath: string): Promise { + // Your test implementation + return true + } +} +``` + +2. **Integrate with the Marketplace**: + +```typescript +// In your extension code +const registerLocalDevTools = (context: vscode.ExtensionContext) => { + const workspaceFolders = vscode.workspace.workspaceFolders + + if (!workspaceFolders) { + return + } + + const workspacePath = workspaceFolders[0].uri.fsPath + const localDevProvider = new LocalDevProvider(workspacePath) + + // Register commands + context.subscriptions.push( + vscode.commands.registerCommand("marketplace.createLocal", async (template, name) => { + return localDevProvider.createLocalPackage(template, name) + }), + + vscode.commands.registerCommand("marketplace.buildLocal", async (packagePath) => { + return localDevProvider.buildLocalPackage(packagePath) + }), + + vscode.commands.registerCommand("marketplace.testLocal", async (packagePath) => { + return localDevProvider.testLocalPackage(packagePath) + }), + ) +} +``` + +## Best Practices for Extensions + +When extending the Marketplace, follow these best practices: + +### Maintainable Code + +1. **Follow the Existing Patterns**: + + - Use similar naming conventions + - Follow the same code structure + - Maintain consistent error handling + +2. **Document Your Extensions**: + + - Add JSDoc comments to functions and classes + - Explain the purpose of your extensions + - Document any configuration options + +3. **Write Tests**: + - Add unit tests for new functionality + - Update integration tests as needed + - Ensure test coverage remains high + +### Performance Considerations + +1. **Lazy Loading**: + + - Load data only when needed + - Defer expensive operations + - Use pagination for large datasets + +2. **Efficient Data Processing**: + + - Minimize data transformations + - Use memoization for expensive calculations + - Batch operations when possible + +3. **UI Responsiveness**: + - Keep the UI responsive during operations + - Show loading indicators for async operations + - Use debouncing for frequent events + +### Compatibility + +1. **VSCode API Compatibility**: + + - Use stable VSCode API features + - Handle API version differences + - Test with multiple VSCode versions + +2. **Cross-Platform Support**: + + - Test on Windows, macOS, and Linux + - Use path.join for file paths + - Handle file system differences + +3. **Theme Compatibility**: + - Use VSCode theme variables + - Test with light and dark themes + - Support high contrast mode + +--- + +**Previous**: [Testing Strategy](./06-testing-strategy.md) diff --git a/cline_docs/marketplace/user-guide/01-introduction.md b/cline_docs/marketplace/user-guide/01-introduction.md new file mode 100644 index 0000000000..4fecb58d2e --- /dev/null +++ b/cline_docs/marketplace/user-guide/01-introduction.md @@ -0,0 +1,58 @@ +# Introduction to Marketplace + +## Overview and Purpose + +The Marketplace is a powerful feature in Roo Code that allows you to discover, browse, and utilize various items to enhance your development experience. It serves as a centralized hub for accessing: + +- **Modes**: Specialized AI assistants with different capabilities +- **MCP Servers**: Model Context Protocol servers that provide additional functionality +- **Prompts**: Pre-configured instructions for specific tasks +- **Packages**: Collections of related components + +The Marketplace simplifies the process of extending Roo Code's capabilities by providing a user-friendly interface to find, filter, and add new components to your environment. + +## Key Features and Capabilities + +### Component Discovery + +- Browse a curated collection of components +- View detailed information about each component +- Explore subcomponents within packages + +### Search and Filter + +- Search by name and description +- Filter by component type (mode, MCP server, etc.) +- Use tags to find related components +- Combine search and filters for precise results + +### Component Details + +- View comprehensive information about each component +- See version information +- Access source repositories directly +- Explore subcomponents organized by type + +### Item Management + +- Add new components to your environment +- Manage custom item sources +- Create and contribute your own packages + +## How to Access the Marketplace + +The Marketplace can be accessed through the Roo Code extension in VS Code: + +1. Open VS Code with the Roo Code extension installed +2. Click on the Roo Code icon in the activity bar +3. Select "Marketplace" from the available options + +Alternatively, you can use the Command Palette: + +1. Press `Ctrl+Shift+P` (Windows/Linux) or `Cmd+Shift+P` (Mac) to open the Command Palette +2. Type "Roo Code: Open Marketplace" +3. Press Enter to open the Marketplace + +--- + +**Next**: [Browsing items](./02-browsing-items.md) diff --git a/cline_docs/marketplace/user-guide/02-browsing-items.md b/cline_docs/marketplace/user-guide/02-browsing-items.md new file mode 100644 index 0000000000..5a98f51fff --- /dev/null +++ b/cline_docs/marketplace/user-guide/02-browsing-items.md @@ -0,0 +1,148 @@ +# Browsing + +## Understanding the Marketplace Interface + +The Marketplace interface is designed to provide a clean, intuitive experience for discovering and exploring available components. The main interface consists of several key areas: + +### Main Sections + +1. **Navigation Tabs** + + - **Browse**: View all available marketplace items + - **Sources**: Manage Marketplace sources + +2. **Filter Panel** + + - Type filters (Modes, MCP Servers, Packages, etc.) + - Search box + - Tag filters + +3. **Results Area** + - Marketplace items displaying component information + - Sorting options + +### Interface Layout + +``` +┌─────────────────────────────────────────────────────────┐ +│ [Browse] [Sources] │ +├─────────────────────────────────────────────────────────┤ +│ FILTERS │ +│ Types: [] Mode [] MCP Server [] Package [] Prompt │ +│ Search: [ ] │ +│ Tags: [Tag cloud] │ +├─────────────────────────────────────────────────────────┤ +│ MARKETPLACE Items │ +│ ┌─────────────────────────────────────────────────┐ │ +│ │ Name [Type] │ │ +│ │ by Author │ │ +│ │ │ │ +│ │ Description text... │ │ +│ │ │ │ +│ │ [Tags] [Tags] [Tags] │ │ +│ │ │ │ +│ │ v1.0.0 Apr 12, 2025 [View] │ │ +│ └─────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────┐ │ +│ │ Another Item [Type] │ │ +│ │ ... │ │ +└─────────────────────────────────────────────────────────┘ +``` + +## Marketplace Item and Information Displayed + +Each item in the Marketplace is represented by a card that contains essential information about the component: + +### Card Elements + +1. **Header Section** + + - **Name**: The name of the component + - **Author**: The creator or maintainer of the component (if available) + - **Type Badge**: Visual indicator of the component type (Mode, MCP Server, etc.) + +2. **Description** + + - A brief overview of the component's purpose and functionality + +3. **Tags** + + - Clickable tags that categorize the component + - Can be used for filtering similar components + +4. **Metadata** + + - **Version**: The current version of the component (if available) + - **Last Updated**: When the component was last modified (if available) + +5. **Actions** + + - **View**: Button to access the component's source repository or documentation + +6. **Details Section** (expandable) + - Shows subcomponents grouped by type + - Displays additional information when expanded + +### Example Item + +``` +┌─────────────────────────────────────────────────────┐ +│ Data Platform Package [Package] │ +│ by Roo Team │ +│ │ +│ A comprehensive data processing and analysis │ +│ package with tools for ETL, visualization, and ML. │ +│ │ +│ [data] [analytics] [machine-learning] │ +│ │ +│ v2.1.0 Apr 10, 2025 [View] │ +│ │ +│ ▼ Component Details │ +│ MCP Servers: │ +│ 1. Data Validator - Validates data formats │ +│ 2. ML Predictor - Makes predictions on data │ +│ │ +│ Modes: │ +│ 1. Data Analyst - Helps with data analysis │ +│ 2. ETL Engineer - Assists with data pipelines │ +└─────────────────────────────────────────────────────┘ +``` + +## Navigating Between Items + +The Marketplace provides several ways to navigate through the available items: + +### Navigation Methods + +1. **Scrolling** + + - Scroll through the list of item cards to browse all available components + +2. **Filtering** + + - Use the filter panel to narrow down the displayed items + - Click on type filters to show only specific component types + - Enter search terms to find items by name or description + - Click on tags to filter by specific categories + +3. **Sorting** + + - Sort pacitemskages by name or last updated date + - Toggle between ascending and descending order + +4. **Tab Navigation** + - Switch between "Browse" and "Sources" tabs to manage Marketplace sources + +### Keyboard Navigation + +For accessibility and efficiency, the Marketplace supports keyboard navigation: + +- **Tab**: Move focus between interactive elements +- **Space/Enter**: Activate buttons or toggle filters +- **Arrow Keys**: Navigate between items +- **Escape**: Close expanded details or clear filters + +--- + +**Previous**: [Introduction to Marketplace](./01-introduction.md) | **Next**: [Searching and Filtering](./03-searching-and-filtering.md) diff --git a/cline_docs/marketplace/user-guide/03-searching-and-filtering.md b/cline_docs/marketplace/user-guide/03-searching-and-filtering.md new file mode 100644 index 0000000000..e63e92f2fc --- /dev/null +++ b/cline_docs/marketplace/user-guide/03-searching-and-filtering.md @@ -0,0 +1,140 @@ +# Searching and Filtering + +The Marketplace provides powerful search and filtering capabilities to help you quickly find the components you need. This guide explains how to effectively use these features to narrow down your search results. + +## Using the Search Functionality + +The search box allows you to find components by matching text in various fields: + +### What Gets Searched + +When you enter a search term, the Marketplace looks for matches in: + +1. **Item Name**: The primary identifier of the item +2. **Description**: The detailed explanation of the item's purpose +3. **Subcomponent Names and Descriptions**: Text within nested items + +### Search Features + +- **Case Insensitive**: Searches ignore letter case for easier matching +- **Whitespace Insensitive**: Extra spaces are normalized in the search +- **Partial Matching**: Finds results that contain your search term anywhere in the text +- **Instant Results**: Results update as you type +- **Match Highlighting**: Matching subcomponents are highlighted and expanded automatically + +### Search Implementation + +The search uses a simple string contains match that is case and whitespace insensitive. This means: + +- "Data" will match "data", "DATA", "Data", etc. +- "machine learning" will match "Machine Learning", "machine-learning", etc. +- Partial words will match: "valid" will match "validation", "validator", etc. + +### Search Tips + +- Use specific, distinctive terms to narrow results +- Try different variations if you don't find what you're looking for +- Search for technology names or specific functionality +- Look for highlighted "match" indicators in expanded details sections + +### Example Searches + +| Search Term | Will Find | +| ------------------ | --------------------------------------------------------------------------- | +| "data" | Items with "data" in their name, description, or subcomponents | +| "validator" | Items that include validation functionality or have validator subcomponents | +| "machine learning" | Items related to machine learning technology | + +## Filtering by Item Type + +The type filter allows you to focus on specific categories of items: + +### Available Type Filters + +- **Mode**: AI assistant personalities with specialized capabilities +- **MCP Server**: Model Context Protocol servers that provide additional functionality +- **Package**: Collections of related items +- **Prompt**: Pre-configured instructions for specific tasks + +### Using Type Filters + +1. Click on a type checkbox to show only items of that type +2. Select multiple types to show items that match any of the selected types +3. Clear all type filters to show all items again + +When filtering by type, packages are handled specially: + +- A package will be included if it matches the selected type +- A package will also be included if it contains any subcomponents matching the selected type +- When viewing a package that was included due to its subcomponents, the matching subcomponents will be highlighted + +### Type Filter Behavior + +- Type filters apply to both the primary item type and it's subcomponents +- Packages are included if they contain subcomponents matching the selected type +- The type is displayed as a badge on each item card +- Type filtering can be combined with search terms and tag filters + +## Using Tags for Filtering + +Tags provide a way to filter items by category, technology, or purpose: + +### Tag Functionality + +- Tags appear as clickable buttons on item cards +- Clicking a tag activates it as a filter +- Active tag filters are highlighted +- Items must have at least one of the selected tags to be displayed + +### Finding and Using Tags + +1. Browse through item cards to discover available tags +2. Click on a tag to filter for items with that tag +3. Click on additional tags to expand your filter (items with any of the selected tags will be shown) +4. Click on an active tag to deactivate it + +### Common Tags + +- Technology areas: "data", "web", "security", "ai" +- Programming languages: "python", "javascript", "typescript" +- Functionality: "testing", "documentation", "analysis" +- Domains: "finance", "healthcare", "education" + +## Combining Search and Filters + +For the most precise results, you can combine search terms, type filters, and tag filters: + +### How Combined Filtering Works + +1. **AND Logic Between Filter Types**: Items must match the search term AND the selected types AND have at least one of the selected tags +2. **OR Logic Within Tag Filters**: Items must have at least one of the selected tags + +### Combined Filter Examples + +| Search Term | Type Filter | Tag Filter | Will Find | +| --------------- | ----------- | ----------------------- | ---------------------------------------------------- | +| "data" | MCP Server | "analytics" | MCP Servers related to data analytics | +| "test" | Mode | "automation", "quality" | Test automation or quality-focused modes | +| "visualization" | Package | "dashboard", "chart" | Packages for creating dashboards or charts | +| "" | Mode | "" | All modes and packages containing mode subcomponents | + +### Clearing Filters + +To reset your search and start over: + +1. Clear the search box +2. Uncheck all type filters +3. Deactivate all tag filters by clicking on them + +### Filter Status Indicators + +The Marketplace provides visual feedback about your current filters: + +- Active type filters are checked +- Active tag filters are highlighted +- The search box shows your current search term +- Result counts may be displayed to show how many items match your filters + +--- + +**Previous**: [Browsing Items](./02-browsing-items.md) | **Next**: [Working with Package Details](./04-working-with-details.md) diff --git a/cline_docs/marketplace/user-guide/04-working-with-details.md b/cline_docs/marketplace/user-guide/04-working-with-details.md new file mode 100644 index 0000000000..ac831c52af --- /dev/null +++ b/cline_docs/marketplace/user-guide/04-working-with-details.md @@ -0,0 +1,143 @@ +# Working with Package Details + +Marketplace items often contain multiple items organized in a hierarchical structure; these items are referred to as "Packages" and must have a type of `package`. The items organized within a package are referred to as "subitems" and have all the same metadata properties of regular items. This guide explains how to work with the details section of package cards to explore and understand the elements within each package. + +## Expanding Package Details + +Most packages in the Marketplace contain subcomponents that are hidden by default to keep the interface clean. You can expand these details to see what's inside each package: + +### How to Expand Details + +1. Look for the "Component Details" section at the bottom of a package card +2. Click on the section header or the chevron icon (▶) to expand it +3. The section will animate open, revealing the components inside the package +4. Click again to collapse the section when you're done + +### Automatic Expansion + +The details section will expand automatically when: + +- Your search term matches text in a subcomponent +- This is the only condition for automatic expansion + +### Details Section Badge + +The details section may display a badge with additional information: + +- **Match count**: When your search term matches subcomponents, a badge shows how many matches were found (e.g., "3 matches") +- This helps you quickly identify which packages contain relevant subcomponents + +## Understanding Component Types + +Components within packages are grouped by their type to make them easier to find and understand: + +### Common Component Types + +1. **Modes** + + - AI assistant personalities with specialized capabilities + - Examples: Code Mode, Architect Mode, Debug Mode + +2. **MCP Servers** + + - Model Context Protocol servers that provide additional functionality + - Examples: File Analyzer, Data Validator, Image Generator + +3. **Prompts** + + - Pre-configured instructions for specific tasks + - Examples: Code Review, Documentation Generator, Test Case Creator + +4. **Packages** + - Nested collections of related components + - Can contain any of the other component types + +### Type Presentation + +Each type section in the details view includes: + +- A header with the type name (pluralized, e.g., "MCP Servers") +- A numbered list of components of that type +- Each component's name and description + +## Viewing Subcomponents + +The details section organizes subcomponents in a clear, structured format: + +### Subcomponent List Format + +``` +Component Details + Type Name: + 1. Component Name - Description text goes here + 2. Another Component - Its description + + Another Type: + 1. First Component - Description + 2. Second Component - Description +``` + +### Subcomponent Information + +Each subcomponent in the list displays: + +1. **Number**: Sequential number within its type group +2. **Name**: The name of the subcomponent +3. **Description**: A brief explanation of the subcomponent's purpose (if available) +4. **Match Indicator**: A "match" badge appears next to items that match your search term + +### Navigating Subcomponents + +- Scroll within the details section to see all subcomponents +- Components are grouped by type, making it easier to find specific functionality +- Long descriptions may be truncated with an ellipsis (...) to save space (limited to 100 characters) + +## Matching Search Terms in Subcomponents + +One of the most powerful features of the Marketplace is the ability to search within subcomponents: + +### How Subcomponent Matching Works + +1. Enter a search term in the search box +2. The Marketplace searches through all subcomponent names and descriptions +3. Packages with matching subcomponents remain visible in the results +4. The details section automatically expands for packages with matches +5. Matching subcomponents are highlighted and marked with a "match" badge + +### Visual Indicators for Matches + +When a subcomponent matches your search: + +- The component name is highlighted in a different color +- A "match" badge appears next to the component +- The details section automatically expands +- A badge on the details section header shows the number of matches + +### Search Implementation + +The search uses a simple string contains match that is case-insensitive: + +- "validator" will match "Data Validator", "Validator Tool", etc. +- "valid" will match "validation" or "validator" +- validator will not match "validation" +- The search will match any part of the name or description that contains the exact search term + +### Example Scenario + +If you search for "validator": + +1. Packages containing components with "validator" in their name or description remain visible +2. The details section expands automatically for packages with matching subcomponents +3. Components like "Data Validator" or those with "validator" in their description are highlighted +4. A badge might show "2 matches" if two subcomponents match your search term + +### Benefits of Subcomponent Matching + +- Find functionality buried deep within packages +- Discover relationships between components +- Identify packages that contain specific tools or capabilities +- Locate similar components across different packages + +--- + +**Previous**: [Searching and Filtering](./03-searching-and-filtering.md) | **Next**: [Adding Packages](./05-adding-packages.md) diff --git a/cline_docs/marketplace/user-guide/05-adding-packages.md b/cline_docs/marketplace/user-guide/05-adding-packages.md new file mode 100644 index 0000000000..55ebd13e37 --- /dev/null +++ b/cline_docs/marketplace/user-guide/05-adding-packages.md @@ -0,0 +1,226 @@ +## Item Structure, Metadata, and Features + +### Overview + +- Every component on the registry is an `item`. +- An `item` can be of type: `mcp`, `mode`, `prompt`, `package` +- Each item apart from `package` is a singular object, i.e: one mode, one mcp server. +- A `package` contains multiple other `item`s + - All internal sub-items of a `package` is contained in the binary on the `package` item metadata itself. +- Each `item` requires specific metadata files and follows a consistent directory structure. + +### Directory Structure + +The `registry` structure could be the root or placed in a `registry` directory of any `git` repository, a sample structure for a registry is: + +``` +registry/ +├── metadata.en.yml # Required metadata for the registry +│ +├── modes/ # `mode` items +│ └── a-mode-name/ +│ └── metadata.en.yml +├── mcps/ # `mcp` items +├── prompts/ # `prompt` items +│ +└── packages/ # `package` items + └── a-package-name/ + ├── metadata.en.yml # Required metadata + ├── metadata.fr.yml # Optional localized metadata (French) + ├── modes/ # `a-package-name`'s internal `mode` items + │ └── my-mode/ + │ └── metadata.en.yml + ├── mcps/ # `a-package-name`'s internal `mcp` items + │ └── my-server/ + │ └── metadata.en.yml + └── prompts/ # `a-package-name`'s internal `prompt` items + └── my-prompt/ + └── metadata.en.yml +``` + +### Metadata File Format + +Metadata files use YAML format and must include specific fields: + +#### `registry`: + +```yaml +name: "My Registry" +description: "A concise description for your registry" +version: "0.0.0" +author: "your name" # optional +authorUrl: "http://your.profile.url/" # optional +``` + +#### `item`: + +```yaml +name: "My Package" +description: "A concise description for your package" +version: "0.0.0" +type: "package" # One of: package, mode, mcp, prompt +sourceUrl: "https://url.to/source-repository" # Optional +binaryUrl: "https://url.to/binary.zip" +binaryHash: "SHA256-of-binary" +binarySource: "https://proof.of/source" # Optional, proof-of-source for the binary (tag/hash reference, build job, etc) +tags: + - tag1 + - tag2 +author: "your name" # optional +authorUrl: "http://your.profile.url/" # optional +``` + +### Localization Support + +You can provide metadata in multiple languages by using locale-specific files: + +**Important Notes on Localization:** + +- Only files with the pattern `metadata.{locale}.yml` are supported +- The Marketplace will display metadata in the user's locale if available +- If the user's locale is not available, it will fall back to English +- The English locale (`metadata.en.yml`) is required as a fallback +- Files without a locale code (e.g., just `metadata.yml`) are not supported + +### Configurable Support + +Powered with [**`Roo Rocket`**](https://github.com/NamesMT/roo-rocket), the registry supports configurable items like: + +- `mcp` with access token inputs. +- `mode` / `prompt` with feature flags. +- And further customizations that a creator can imagine. + - E.g: a `package` could prompt you for the location of its context folder. + +## Contributing Process + +To contribute your package to the official repository, follow these steps: + +### 1. Fork the Repository + +1. Visit the official Roo Code Packages repository: [https://github.com/RooVetGit/Roo-Code-Marketplace](https://github.com/RooVetGit/Roo-Code-Marketplace) +2. Click the "Fork" button in the top-right corner +3. This creates your own copy of the repository where you can make changes + +### 2. Clone Your Fork + +Clone your forked repository to your local machine: + +```bash +git clone https://github.com/YOUR-USERNAME/Roo-Code-Marketplace.git +cd Roo-Code-Marketplace +``` + +### 3. Create Your Item + +1. Create a new directory for your item with an appropriate name +2. Add the required metadata files (and subitem directories for `package`) +3. Follow the structure and format described above +4. Add `sourceUrl` that points to a repository or post with info/document for the item. + +Example of creating a simple package: + +```bash +mkdir -p my-package/modes/my-mode +touch my-package/metadata.en.yml +touch my-package/README.md +touch my-package/modes/my-mode/metadata.en.yml +``` + +### 4. Test Your Package + +Before submitting, test your package by adding your fork as a custom source in the Marketplace: + +1. In VS Code, open the Marketplace +2. Go to the "Settings" tab +3. Click "Add Source" +4. Enter your fork's URL (e.g., `https://github.com/YOUR-USERNAME/Roo-Code-Marketplace`) +5. Click "Add" +6. Verify that your package appears and functions correctly + +### 5. Commit and Push Your Changes + +Once you're satisfied with your package: + +```bash +git add . +git commit -m "Add my-package with mode component" +git push origin main +``` + +### 6. Create a Pull Request + +1. Go to the original repository: [https://github.com/RooVetGit/Roo-Code-Marketplace](https://github.com/RooVetGit/Roo-Code-Marketplace) +2. Click "Pull Requests" and then "New Pull Request" +3. Click "Compare across forks" +4. Select your fork as the head repository +5. Click "Create Pull Request" +6. Provide a clear title and description of your package +7. Submit the pull request + +### 7. Review Process + +After submitting your pull request: + +1. Maintainers will review your package +2. They may request changes or improvements +3. Once approved, your package will be merged into the main repository +4. Your package will be available to all users of the Marketplace + +## Best Practices + +- **Clear Documentation**: Include detailed documentation in your README.md +- **Descriptive Metadata**: Write clear, informative descriptions +- **Appropriate Tags**: Use relevant tags to make your package discoverable +- **Testing**: Thoroughly test your package before submitting +- **Localization**: Consider providing metadata in multiple languages +- **Semantic Versioning**: Follow semantic versioning for version numbers +- **Consistent Naming**: Use clear, descriptive names for components + +## Example package metadatas + +### Data Science Toolkit + +Here's an example of a data science package: + +**data-science-toolkit/metadata.en.yml**: + +```yaml +name: "Data Science Toolkit" +description: "A comprehensive collection of tools for data science workflows" +version: "1.0.0" +type: "package" +tags: + - data + - science + - analysis + - visualization + - machine learning +``` + +**data-science-toolkit/modes/data-scientist-mode/metadata.en.yml**: + +```yaml +name: "Data Scientist Mode" +description: "A specialized mode for data science tasks" +version: "1.0.0" +type: "mode" +tags: + - data + - science + - analysis +``` + +**data-science-toolkit/prompts/data-cleaning/metadata.en.yml**: + +```yaml +name: "Data Cleaning Prompt" +description: "A prompt for cleaning and preprocessing datasets" +version: "1.0.0" +type: "prompt" +tags: + - data + - cleaning + - preprocessing +``` + +**Previous**: [Working with Package Details](./04-working-with-details.md) | **Next**: [Adding Custom Sources](./06-adding-custom-sources.md) diff --git a/cline_docs/marketplace/user-guide/06-adding-custom-sources.md b/cline_docs/marketplace/user-guide/06-adding-custom-sources.md new file mode 100644 index 0000000000..7baf639631 --- /dev/null +++ b/cline_docs/marketplace/user-guide/06-adding-custom-sources.md @@ -0,0 +1,152 @@ +# Adding Custom Marketplace Sources + +The Marketplace allows you to extend its functionality by adding custom sources. This guide explains how to set up and manage your own Marktplace repositories to access additional components beyond the default offerings. + +## Setting up a Marketplace Source Repository + +A Marketplace source repository is a Git repository that contains Marketplace items organized in a specific structure. You can create your own repository to host custom packages: + +### Repository Requirements + +1. **Proper Structure**: The repository must follow the required directory structure +2. **Valid Metadata**: Each package must include properly formatted metadata files +3. **Git Repository**: The source must be a Git repository accessible via HTTPS + +### Building your registry repository + +#### Start from a sample registry repository + +Check the branches of the [**rm-samples**](https://github.com/NamesMT/rm-samples) repository here. + +#### Creating a New Repository + +1. Create a new repository on GitHub, GitLab, or another Git hosting service +2. Initialize the repository with a README.md file +3. Clone the repository to your local machine: + +```bash +git clone https://github.com/your-username/your-registry-repo.git +cd your-registry-repo +``` + +4. Create the basic registry structure: + +```bash +mkdir -p packages modes mcps prompts +touch metadata.en.yml +``` + +5. Add repository metadata to `metadata.en.yml`: + +```yaml +name: "Your Repository Name" +description: "A collection of custom packages for Roo Code" +version: "1.0.0" +``` + +6. Commit and push the initial structure: + +```bash +git add . +git commit -m "Initialize package repository structure" +git push origin main +``` + +## Adding Sources to Roo Code + +Once you have a properly structured source repository, you can add it to your Roo Code Marketplace as a source: + +### Default Package Source + +Roo Code comes with a default package source: + +- URL: `https://github.com/RooVetGit/Roo-Code-Marketplace` +- This source is enabled by default, and anytime all sources have been deleted. + +### Adding a New Source + +1. Open VS Code with the Roo Code extension +2. Navigate to the Marketplace +3. Switch to the "Sources" tab +4. Click the "Add Source" button +5. Enter the repository URL: + - Format: `https://github.com/username/repository.git` + - Example: `https://github.com/your-username/your-registry-repo.git` +6. Click "Add" to save the source + +### Managing Sources + +The "Sources" tab provides several options for managing your registry sources: + +1. **Remove**: Delete a source from your configuration +2. **Refresh**: Update the item list from a source - this is forced git clone/pull to override local caching of data + +### Source Caching and Refreshing + +Marketplace sources are cached to improve performance: + +- **Cache Duration**: Sources are cached for 1 hour (3600000 ms) +- **Force Refresh**: To force an immediate refresh of a source: + 1. Go to the "Sources" tab + 2. Click the "Refresh" button next to the source you want to update + 3. This will bypass the cache and fetch the latest data from the repository + +### Troubleshooting Sources + +If a source isn't loading properly: + +1. Check that the repository URL is correct +2. Ensure the repository follows the required structure +3. Look for error messages in the Marketplace interface +4. Try refreshing the sources list +5. Disable and re-enable the source + +## Creating Private Sources + +For team or organization use, you might want to create private sources: + +### Private Repository Setup + +1. Create a private repository on your Git hosting service +2. Follow the same structure requirements as public repositories +3. Set up appropriate access controls for your team members + +### Authentication Options + +To access private repositories, you may need to: + +1. Configure Git credentials on your system +2. Use a personal access token with appropriate permissions +3. Set up SSH keys for authentication + +### Organization Best Practices + +For teams and organizations: + +1. Designate maintainers responsible for the source +2. Establish quality standards for contributed items and packages +3. Create a review process for new additions +4. Document usage guidelines for team members +5. Consider implementing versioning for your items and packages + +## Using Multiple Sources + +The Marketplace supports multiple sources simultaneously: + +### Benefits of Multiple Sources + +- Access components from different providers +- Separate internal and external components +- Test new work before contributing them to the main repository +- Create specialized sources for different projects or teams + +### Source Management Strategy + +1. Keep the default source enabled for core components +2. Add specialized sources for specific needs +3. Create a personal source for testing and development +4. Refresh sources after you've pushed changes to them to get the latest items + +--- + +**Previous**: [Adding Packages](./05-adding-packages.md) | **Next**: [Marketplace Architecture](../implementation/01-architecture.md) diff --git a/cline_docs/bedrock/bedrock-cache-strategy-documentation.md b/docs/bedrock/bedrock-cache-strategy-documentation.md similarity index 100% rename from cline_docs/bedrock/bedrock-cache-strategy-documentation.md rename to docs/bedrock/bedrock-cache-strategy-documentation.md diff --git a/cline_docs/bedrock/model-identification.md b/docs/bedrock/model-identification.md similarity index 100% rename from cline_docs/bedrock/model-identification.md rename to docs/bedrock/model-identification.md diff --git a/cline_docs/settings.md b/docs/settings.md similarity index 100% rename from cline_docs/settings.md rename to docs/settings.md diff --git a/e2e/.vscode-test.mjs b/e2e/.vscode-test.mjs index ccc8b495ea..c83f12c4bb 100644 --- a/e2e/.vscode-test.mjs +++ b/e2e/.vscode-test.mjs @@ -2,18 +2,15 @@ * See: https://code.visualstudio.com/api/working-with-extensions/testing-extension */ -import { defineConfig } from '@vscode/test-cli'; +import { defineConfig } from "@vscode/test-cli" export default defineConfig({ - label: 'integrationTest', - files: 'out/suite/**/*.test.js', - workspaceFolder: '.', + label: "integrationTest", + files: "out/suite/**/*.test.js", + workspaceFolder: ".", mocha: { - ui: 'tdd', + ui: "tdd", timeout: 60000, }, - launchArgs: [ - '--enable-proposed-api=RooVeterinaryInc.roo-cline', - '--disable-extensions' - ] -}); + launchArgs: ["--enable-proposed-api=RooVeterinaryInc.roo-cline", "--disable-extensions"], +}) diff --git a/e2e/package-lock.json b/e2e/package-lock.json index 278df120c2..bb6a34c082 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -8,11 +8,12 @@ "name": "e2e", "version": "0.1.0", "devDependencies": { + "@roo-code/types": "^1.12.0", "@types/mocha": "^10.0.10", - "@vscode/test-cli": "^0.0.9", + "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.0", "mocha": "^11.1.0", - "typescript": "^5.4.5" + "typescript": "5.8.3" } }, "node_modules/@bcoe/v8-coverage": { @@ -89,6 +90,16 @@ "node": ">=14" } }, + "node_modules/@roo-code/types": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@roo-code/types/-/types-1.12.0.tgz", + "integrity": "sha512-djdZ4lzsiOc+umX357JvcSwRlAMm05P+8DU58IFyZERmEh8wkm4TglDuaaRVGtQSHw9YGFikqfruLtZSEb7zJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "zod": "^3.24.4" + } + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -104,9 +115,9 @@ "license": "MIT" }, "node_modules/@vscode/test-cli": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@vscode/test-cli/-/test-cli-0.0.9.tgz", - "integrity": "sha512-vsl5/ueE3Jf0f6XzB0ECHHMsd5A0Yu6StElb8a+XsubZW7kHNAOw4Y3TSSuDzKEpLnJ92nbMy1Zl+KLGCE6NaA==", + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@vscode/test-cli/-/test-cli-0.0.10.tgz", + "integrity": "sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA==", "dev": true, "license": "MIT", "dependencies": { @@ -318,16 +329,16 @@ } }, "node_modules/@vscode/test-electron": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.4.1.tgz", - "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.5.2.tgz", + "integrity": "sha512-8ukpxv4wYe0iWMRQU18jhzJOHkeGKbnw7xWRX3Zw1WJA4cEKbHcmmLPdPrPtL6rhDcrlCZN+xKRpv09n4gRHYg==", "dev": true, "license": "MIT", "dependencies": { "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.5", "jszip": "^3.10.1", - "ora": "^7.0.1", + "ora": "^8.1.0", "semver": "^7.6.2" }, "engines": { @@ -411,27 +422,6 @@ "dev": true, "license": "MIT" }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -445,33 +435,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bl": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", - "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -502,31 +465,6 @@ "dev": true, "license": "ISC" }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/c8": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/c8/-/c8-9.1.0.tgz", @@ -622,16 +560,16 @@ } }, "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "license": "MIT", "dependencies": { - "restore-cursor": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -965,6 +903,19 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -1061,27 +1012,6 @@ "node": ">= 14" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", @@ -1374,14 +1304,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/minimatch": { @@ -1411,15 +1344,14 @@ } }, "node_modules/mocha": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz", - "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==", + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.2.2.tgz", + "integrity": "sha512-VlSBxrPYHK4YNOEbFdkCxHQbZMoNzBkoPprqtZRW6311EUF/DlSxoycE2e/2NtRk4WKkIXzyrXDTrlikJMWgbw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-colors": "^4.1.3", "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", + "chokidar": "^4.0.1", "debug": "^4.3.5", "diff": "^5.2.0", "escape-string-regexp": "^4.0.0", @@ -1430,6 +1362,7 @@ "log-symbols": "^4.1.0", "minimatch": "^5.1.6", "ms": "^2.1.3", + "picocolors": "^1.1.1", "serialize-javascript": "^6.0.2", "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", @@ -1446,6 +1379,22 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/mocha/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/mocha/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -1459,6 +1408,20 @@ "node": ">=10" } }, + "node_modules/mocha/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -1503,40 +1466,40 @@ } }, "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/ora": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-7.0.1.tgz", - "integrity": "sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^5.3.0", - "cli-cursor": "^4.0.0", - "cli-spinners": "^2.9.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", - "is-unicode-supported": "^1.3.0", - "log-symbols": "^5.1.0", - "stdin-discarder": "^0.1.0", - "string-width": "^6.1.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1563,28 +1526,41 @@ "license": "MIT" }, "node_modules/ora/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/ora/node_modules/log-symbols": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", - "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^5.0.0", - "is-unicode-supported": "^1.1.0" + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -1593,18 +1569,18 @@ } }, "node_modules/ora/node_modules/string-width": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-6.1.0.tgz", - "integrity": "sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^10.2.1", - "strip-ansi": "^7.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1703,6 +1679,13 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -1773,29 +1756,22 @@ } }, "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "license": "MIT", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -1870,16 +1846,13 @@ } }, "node_modules/stdin-discarder": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", - "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", "dev": true, "license": "MIT", - "dependencies": { - "bl": "^5.0.0" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2110,9 +2083,9 @@ } }, "node_modules/typescript": { - "version": "5.8.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", - "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2382,6 +2355,16 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.25.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.8.tgz", + "integrity": "sha512-iJPWX8HoZ2VE21VrhHGU9jVo/kVDUQyqM9vF0MxDhW/fp2sAl1eVwGJgiYZdHGiMwQJImXIW80lKk0MnfDxqiQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/e2e/package.json b/e2e/package.json index aec42f93f1..22d76db6b5 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -3,19 +3,19 @@ "version": "0.1.0", "private": true, "scripts": { - "lint": "eslint src/**/*.ts", + "lint": "eslint src/**/*.ts --max-warnings=0", "check-types": "tsc --noEmit", "test": "npm run build && npx dotenvx run -f .env.local -- node ./out/runTest.js", "ci": "npm run vscode-test && npm run test", "build": "rimraf out && tsc -p tsconfig.json", "vscode-test": "cd .. && npm run vscode-test" }, - "dependencies": {}, "devDependencies": { + "@roo-code/types": "^1.12.0", "@types/mocha": "^10.0.10", - "@vscode/test-cli": "^0.0.9", + "@vscode/test-cli": "^0.0.10", "@vscode/test-electron": "^2.4.0", "mocha": "^11.1.0", - "typescript": "^5.4.5" + "typescript": "5.8.3" } } diff --git a/e2e/src/suite/extension.test.ts b/e2e/src/suite/extension.test.ts index 1f44824610..54544a2627 100644 --- a/e2e/src/suite/extension.test.ts +++ b/e2e/src/suite/extension.test.ts @@ -1,24 +1,47 @@ import * as assert from "assert" import * as vscode from "vscode" +import { Package } from "@roo-code/types" + suite("Roo Code Extension", () => { test("Commands should be registered", async () => { const expectedCommands = [ - "roo-cline.plusButtonClicked", - "roo-cline.mcpButtonClicked", - "roo-cline.historyButtonClicked", - "roo-cline.popoutButtonClicked", - "roo-cline.settingsButtonClicked", - "roo-cline.openInNewTab", - "roo-cline.explainCode", - "roo-cline.fixCode", - "roo-cline.improveCode", + "SidebarProvider.open", + "SidebarProvider.focus", + "SidebarProvider.resetViewLocation", + "SidebarProvider.toggleVisibility", + "SidebarProvider.removeView", + "activationCompleted", + "plusButtonClicked", + "mcpButtonClicked", + "promptsButtonClicked", + "popoutButtonClicked", + "openInNewTab", + "settingsButtonClicked", + "historyButtonClicked", + "showHumanRelayDialog", + "registerHumanRelayCallback", + "unregisterHumanRelayCallback", + "handleHumanRelayResponse", + "newTask", + "setCustomStoragePath", + "focusInput", + "acceptInput", + "explainCode", + "fixCode", + "improveCode", + "addToContext", + "terminalAddToContext", + "terminalFixCommand", + "terminalExplainCommand", ] - const commands = await vscode.commands.getCommands(true) + const commands = new Set( + (await vscode.commands.getCommands(true)).filter((cmd) => cmd.startsWith(Package.name)), + ) - for (const cmd of expectedCommands) { - assert.ok(commands.includes(cmd), `Command ${cmd} should be registered`) + for (const command of expectedCommands) { + assert.ok(commands.has(`${Package.name}.${command}`), `Command ${command} should be registered`) } }) }) diff --git a/e2e/src/suite/index.ts b/e2e/src/suite/index.ts index 1a3e265662..5331ef37c3 100644 --- a/e2e/src/suite/index.ts +++ b/e2e/src/suite/index.ts @@ -3,7 +3,7 @@ import Mocha from "mocha" import { glob } from "glob" import * as vscode from "vscode" -import type { RooCodeAPI } from "../../../src/exports/roo-code" +import { type RooCodeAPI, Package } from "@roo-code/types" import { waitFor } from "./utils" @@ -12,7 +12,7 @@ declare global { } export async function run() { - const extension = vscode.extensions.getExtension("RooVeterinaryInc.roo-cline") + const extension = vscode.extensions.getExtension(`${Package.publisher}.${Package.name}`) if (!extension) { throw new Error("Extension not found") @@ -26,7 +26,7 @@ export async function run() { openRouterModelId: "google/gemini-2.0-flash-001", }) - await vscode.commands.executeCommand("roo-cline.SidebarProvider.focus") + await vscode.commands.executeCommand(`${Package.name}.SidebarProvider.focus`) await waitFor(() => api.isReady()) // Expose the API to the tests. diff --git a/e2e/src/suite/modes.test.ts b/e2e/src/suite/modes.test.ts index f5cd2141f3..286ab2ce8c 100644 --- a/e2e/src/suite/modes.test.ts +++ b/e2e/src/suite/modes.test.ts @@ -1,6 +1,6 @@ import * as assert from "assert" -import type { ClineMessage } from "../../../src/exports/roo-code" +import type { ClineMessage } from "@roo-code/types" import { waitUntilCompleted } from "./utils" diff --git a/e2e/src/suite/subtasks.test.ts b/e2e/src/suite/subtasks.test.ts index 513b4c218e..b5ff033d12 100644 --- a/e2e/src/suite/subtasks.test.ts +++ b/e2e/src/suite/subtasks.test.ts @@ -1,10 +1,10 @@ import * as assert from "assert" -import type { ClineMessage } from "../../../src/exports/roo-code" +import type { ClineMessage } from "@roo-code/types" import { sleep, waitFor, waitUntilCompleted } from "./utils" -suite("Roo Code Subtasks", () => { +suite.skip("Roo Code Subtasks", () => { test("Should handle subtask cancellation and resumption correctly", async () => { const api = globalThis.api @@ -17,18 +17,17 @@ suite("Roo Code Subtasks", () => { } }) - await api.setConfiguration({ - mode: "ask", - alwaysAllowModeSwitch: true, - alwaysAllowSubtasks: true, - autoApprovalEnabled: true, - enableCheckpoints: false, - }) - const childPrompt = "You are a calculator. Respond only with numbers. What is the square root of 9?" // Start a parent task that will create a subtask. const parentTaskId = await api.startNewTask({ + configuration: { + mode: "ask", + alwaysAllowModeSwitch: true, + alwaysAllowSubtasks: true, + autoApprovalEnabled: true, + enableCheckpoints: false, + }, text: "You are the parent task. " + `Create a subtask by using the new_task tool with the message '${childPrompt}'.` + diff --git a/e2e/src/suite/task.test.ts b/e2e/src/suite/task.test.ts index 434d1fcc4f..e97c3b4f1e 100644 --- a/e2e/src/suite/task.test.ts +++ b/e2e/src/suite/task.test.ts @@ -1,6 +1,6 @@ import * as assert from "assert" -import type { ClineMessage } from "../../../src/exports/roo-code" +import type { ClineMessage } from "@roo-code/types" import { waitUntilCompleted } from "./utils" diff --git a/e2e/src/suite/utils.ts b/e2e/src/suite/utils.ts index 784d299820..d41fa9e8ed 100644 --- a/e2e/src/suite/utils.ts +++ b/e2e/src/suite/utils.ts @@ -1,4 +1,4 @@ -import type { RooCodeAPI } from "../../../src/exports/roo-code" +import type { RooCodeAPI } from "@roo-code/types" type WaitForOptions = { timeout?: number diff --git a/esbuild.js b/esbuild.js index c6a555f5a5..2b684ea248 100644 --- a/esbuild.js +++ b/esbuild.js @@ -32,41 +32,40 @@ const copyWasmFiles = { const nodeModulesDir = path.join(__dirname, "node_modules") const distDir = path.join(__dirname, "dist") - // tiktoken + // tiktoken WASM file fs.copyFileSync( - path.join(nodeModulesDir, "tiktoken", "tiktoken_bg.wasm"), + path.join(nodeModulesDir, "tiktoken", "lite", "tiktoken_bg.wasm"), path.join(distDir, "tiktoken_bg.wasm"), ) - // tree-sitter WASM + // Also copy to the workers directory + fs.mkdirSync(path.join(distDir, "workers"), { recursive: true }) + fs.copyFileSync( + path.join(nodeModulesDir, "tiktoken", "lite", "tiktoken_bg.wasm"), + path.join(distDir, "workers", "tiktoken_bg.wasm"), + ) + + // Main tree-sitter WASM file fs.copyFileSync( path.join(nodeModulesDir, "web-tree-sitter", "tree-sitter.wasm"), path.join(distDir, "tree-sitter.wasm"), ) - // language-specific tree-sitter WASMs - const languageWasmDir = path.join(nodeModulesDir, "tree-sitter-wasms", "out") - const languages = [ - "typescript", - "tsx", - "python", - "rust", - "javascript", - "go", - "cpp", - "c", - "c_sharp", - "ruby", - "java", - "php", - "swift", - "kotlin", - ] - - languages.forEach((lang) => { - const filename = `tree-sitter-${lang}.wasm` - fs.copyFileSync(path.join(languageWasmDir, filename), path.join(distDir, filename)) - }) + // Copy language-specific WASM files + const languageWasmDir = path.join(__dirname, "node_modules", "tree-sitter-wasms", "out") + + // Dynamically read all WASM files from the directory instead of using a hardcoded list + if (fs.existsSync(languageWasmDir)) { + const wasmFiles = fs.readdirSync(languageWasmDir).filter((file) => file.endsWith(".wasm")) + + console.log(`Copying ${wasmFiles.length} tree-sitter WASM files to dist directory`) + + wasmFiles.forEach((filename) => { + fs.copyFileSync(path.join(languageWasmDir, filename), path.join(distDir, filename)) + }) + } else { + console.warn(`Tree-sitter WASM directory not found: ${languageWasmDir}`) + } }) }, } @@ -181,7 +180,7 @@ const extensionConfig = { { name: "alias-plugin", setup(build) { - build.onResolve({ filter: /^pkce-challenge$/ }, (args) => { + build.onResolve({ filter: /^pkce-challenge$/ }, (_args) => { return { path: require.resolve("pkce-challenge/dist/index.browser.js") } }) }, @@ -195,22 +194,31 @@ const extensionConfig = { external: ["vscode"], } +const workerConfig = { + bundle: true, + minify: production, + sourcemap: !production, + logLevel: "silent", + entryPoints: ["src/workers/countTokens.ts"], + format: "cjs", + sourcesContent: false, + platform: "node", + outdir: "dist/workers", +} + async function main() { - const extensionCtx = await esbuild.context(extensionConfig) + const [extensionCtx, workerCtx] = await Promise.all([ + esbuild.context(extensionConfig), + esbuild.context(workerConfig), + ]) if (watch) { - // Start the esbuild watcher - await extensionCtx.watch() - - // Copy and watch locale files - console.log("Copying locale files initially...") + await Promise.all([extensionCtx.watch(), workerCtx.watch()]) copyLocaleFiles() - - // Set up the watcher for locale files setupLocaleWatcher() } else { - await extensionCtx.rebuild() - await extensionCtx.dispose() + await Promise.all([extensionCtx.rebuild(), workerCtx.rebuild()]) + await Promise.all([extensionCtx.dispose(), workerCtx.dispose()]) } } diff --git a/evals/README.md b/evals/README.md index 9f343a6e09..b55a75dcff 100644 --- a/evals/README.md +++ b/evals/README.md @@ -7,7 +7,7 @@ NOTE: This is MacOS only for now! Clone the Roo Code repo: ```sh -git clone https://github.com/RooVetGit/Roo-Code.git +git clone https://github.com/RooCodeInc/Roo-Code.git cd Roo-Code ``` diff --git a/evals/apps/cli/src/index.ts b/evals/apps/cli/src/index.ts index 6b287042b0..3bd71c86a7 100644 --- a/evals/apps/cli/src/index.ts +++ b/evals/apps/cli/src/index.ts @@ -178,6 +178,15 @@ const runExercise = async ({ run, task, server }: { run: Run; task: Task; server const workspacePath = path.resolve(exercisesPath, language, exercise) const taskSocketPath = path.resolve(dirname, `${dirname}/task-${task.id}.sock`) + // Inject foot gun system prompt if present + if (process.env.FOOTGUN_SYSTEM_PROMPT) { + const rooDir = path.join(workspacePath, ".roo") + if (!fs.existsSync(rooDir)) { + fs.mkdirSync(rooDir, { recursive: true }) + } + fs.writeFileSync(path.join(rooDir, "system-prompt-code"), process.env.FOOTGUN_SYSTEM_PROMPT) + } + // If debugging: // Use --wait --log trace or --verbose. // Don't await execa and store result as subprocess. diff --git a/evals/apps/web/package.json b/evals/apps/web/package.json index d52770bbb5..d7b5ca6aed 100644 --- a/evals/apps/web/package.json +++ b/evals/apps/web/package.json @@ -31,7 +31,7 @@ "clsx": "^2.1.1", "cmdk": "^1.1.0", "fuzzysort": "^3.1.0", - "lucide-react": "^0.479.0", + "lucide-react": "^0.510.0", "next": "15.2.2", "next-themes": "^0.4.6", "p-map": "^7.0.3", diff --git a/evals/apps/web/src/app/runs/new/new-run.tsx b/evals/apps/web/src/app/runs/new/new-run.tsx index 71b7422ff3..54dd553b82 100644 --- a/evals/apps/web/src/app/runs/new/new-run.tsx +++ b/evals/apps/web/src/app/runs/new/new-run.tsx @@ -8,6 +8,7 @@ import { zodResolver } from "@hookform/resolvers/zod" import fuzzysort from "fuzzysort" import { toast } from "sonner" import { X, Rocket, Check, ChevronsUpDown, HardDriveUpload, CircleCheck } from "lucide-react" +import { Dialog, DialogContent, DialogTitle, DialogFooter } from "@/components/ui/dialog" import { globalSettingsSchema, providerSettingsSchema, rooCodeDefaults } from "@evals/types" @@ -83,6 +84,10 @@ export function NewRun() { const [model, suite, settings] = watch(["model", "suite", "settings", "concurrency"]) + const [systemPromptDialogOpen, setSystemPromptDialogOpen] = useState(false) + const [systemPrompt, setSystemPrompt] = useState("") + const systemPromptRef = useRef(null) + const onSubmit = useCallback( async (values: FormValues) => { try { @@ -97,13 +102,13 @@ export function NewRun() { values.settings = { ...(values.settings || {}), openRouterModelId } } - const { id } = await createRun(values) + const { id } = await createRun({ ...values, systemPrompt }) router.push(`/runs/${id}`) } catch (e) { toast.error(e instanceof Error ? e.message : "An unknown error occurred.") } }, - [mode, model, models.data, router], + [mode, model, models.data, router, systemPrompt], ) const onFilterModels = useCallback( @@ -313,6 +318,10 @@ export function NewRun() { )} + +
router.push("/")}> + + + Import Foot Gun System Prompt +