diff --git a/.changeset/curly-states-see.md b/.changeset/curly-states-see.md new file mode 100644 index 0000000000..0d1ff62117 --- /dev/null +++ b/.changeset/curly-states-see.md @@ -0,0 +1,5 @@ +--- +"roo-cline": patch +--- + +Close the browsertool properly when a remote browser is configured but a fallback local one is used diff --git a/.dockerignore b/.dockerignore index 11d03a1c54..514136ac91 100644 --- a/.dockerignore +++ b/.dockerignore @@ -61,7 +61,6 @@ __tests__ # Ignore development config files .eslintrc* .prettierrc* -jest.config* # Ignore most directories except what we need for the build apps/ diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 6e2c5b3244..85263d8813 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,33 +1,28 @@ name: Detailed Feature Proposal -description: Propose a specific, actionable feature or enhancement for implementation +description: Report a specific problem that needs solving in Roo Code labels: ["proposal", "enhancement"] body: - type: markdown attributes: value: | - **Thank you for proposing a feature for Roo Code!** + **Thank you for submitting a feature request for Roo Code!** - This template is for specific, actionable proposals following our [Issue-First Approach](https://github.com/RooCodeInc/Roo-Code/blob/main/CONTRIBUTING.md). + This template helps you describe problems that need solving. Focus on the problem - the Roo team will work to design solutions unless you want to contribute the implementation yourself. - **Quality over speed:** We prefer detailed, clear proposals over quick ones. Vague proposals often get closed or require multiple rounds of clarification, which wastes everyone's time. + **Quality over speed:** We prefer detailed, clear problem descriptions over quick ones. Vague requests often get closed or require multiple rounds of clarification, which wastes everyone's time. **Before submitting:** - Search existing [Issues](https://github.com/RooCodeInc/Roo-Code/issues) and [Discussions](https://github.com/RooCodeInc/Roo-Code/discussions) to avoid duplicates - - For general ideas, use [GitHub Discussions](https://github.com/RooCodeInc/Roo-Code/discussions/categories/feature-requests) first, or use the #collaboration-board channel in our [Discord](https://discord.gg/roocode) - - Join [Discord](https://discord.gg/roocode) and DM **Hannes Rudolph** (`hrudolph`) for guidance - - **Review process:** A maintainer (especially @hannesrudolph) will review this proposal. **Do not start implementation until approved and assigned.** We're a small team with limited resources, so every code addition needs careful consideration. We're always happy to receive clear, actionable proposals though! + - For general ideas, use [GitHub Discussions](https://github.com/RooCodeInc/Roo-Code/discussions/categories/feature-requests) instead of this template. - type: markdown attributes: value: | - ## ❌ Common mistakes that lead to proposal rejection: + ## ❌ Common mistakes that lead to request rejection: - **Vague problem descriptions:** "UI is bad" -> Should be: "Submit button is invisible on dark theme" - - **Solution without context:** "Add feature X" -> Should explain the problem first, then the solution - **Missing user impact:** "This would be cool" -> Should explain who benefits and how - - **No acceptance criteria:** How do we know when it's done? What does success look like? + - **No specific context:** Describe exactly when and how the problem occurs - If you're unsure how a good proposal should look like, you can check out our [Roadmap](https://github.com/orgs/RooCodeInc/projects/1/views/1?query=sort%3Aupdated-desc+is%3Aopen&filterQuery=is%3Aissue%2Copen%2Cclosed+label%3A%22feature+request%22+status%3A%22Issue+%5BUnassigned%5D%22%2C%22Issue+%5BIn+Progress%5D%22) where we have a list of all open feature requests that are ready to be implemented or currently being worked on. - type: textarea id: problem-description @@ -55,11 +50,68 @@ body: validations: required: true + + - type: textarea + id: additional-context + attributes: + label: Additional context (optional) + description: Mockups, screenshots, links, user quotes, or other relevant information that supports your proposal. + + - type: checkboxes + id: checklist + attributes: + label: Request checklist + options: + - label: I've searched existing Issues and Discussions for duplicates + required: true + - label: This describes a specific problem with clear impact and context + required: true + + - type: markdown + attributes: + value: | + --- + + ## 🛠️ **Optional: Contributing & Technical Analysis** + + **🎯 Just reporting a problem?** You can click "Submit new issue" right now! The sections below are only needed if you want to contribute a solution via pull request. + + **⚠️ Only continue if you want to:** + - Propose a specific solution design + - Implement the feature yourself via pull request + - Provide technical analysis to help with implementation + + **For contributors who continue:** + - A maintainer (especially @hannesrudolph) will review this proposal. **Do not start implementation until approved and assigned.** We're a small team with limited resources, so every code addition needs careful consideration. We're always happy to receive clear, actionable proposals though! + - Join [Discord](https://discord.gg/roocode) and DM **Hannes Rudolph** (`hrudolph`) for guidance on implementation + - Check our [Roadmap](https://github.com/orgs/RooCodeInc/projects/1/views/1?query=sort%3Aupdated-desc+is%3Aopen&filterQuery=is%3Aissue%2Copen%2Cclosed+label%3A%22feature+request%22+status%3A%22Issue+%5BUnassigned%5D%22%2C%22Issue+%5BIn+Progress%5D%22) to see open feature requests ready to be implemented or currently being worked on + + - type: checkboxes + id: willingness-to-contribute + attributes: + label: Interested in implementing this? + description: | + **Important:** If you check "Yes" below, the technical sections become REQUIRED. + We need detailed technical analysis from contributors to ensure quality implementation. + options: + - label: Yes, I'd like to help implement this feature + required: false + + - type: checkboxes + id: implementation-approval + attributes: + label: Implementation requirements + options: + - label: I understand this needs approval before implementation begins + required: false + - type: textarea id: proposed-solution attributes: - label: How should this be solved? + label: How should this be solved? (REQUIRED if contributing, optional otherwise) description: | + **If you want to implement this feature, this section is REQUIRED.** + **Describe your solution in detail.** Explain not just what to build, but how it should work. ✅ **Good examples:** @@ -77,14 +129,14 @@ body: - How will users interact with it? - What will the new behaviour look like? placeholder: Describe the specific changes and how they will work. Include user interaction details if relevant. - validations: - required: true - type: textarea id: acceptance-criteria attributes: - label: How will we know it works? (Acceptance Criteria) + label: How will we know it works? (Acceptance Criteria - REQUIRED if contributing, optional otherwise) description: | + **If you want to implement this feature, this section is REQUIRED.** + **This is crucial - don't skip it.** Define what "working" looks like with specific, testable criteria. **Format suggestion:** @@ -108,42 +160,14 @@ body: placeholder: | Define specific, testable criteria. What should users be able to do? What should happen? What should NOT happen? Use the Given/When/Then format above or your own clear structure. - validations: - required: true - - - type: textarea - id: estimated-effort - attributes: - label: Estimated effort and complexity - description: | - **Help us understand the scope.** This helps with planning and prioritisation. - - **Please include:** - - **Size estimate:** XS/Small/Medium/Large/XL (or hours/days if you prefer) - - **Reasoning:** What makes it this size? Which parts are complex? - - **Main challenges:** What's the trickiest bit to implement? - - **Dependencies:** Does this require other changes or external libraries? - - **Example:** - ``` - Size: Large (2-3 weeks) - Reasoning: Touches task execution engine, UI components, and state management - Main challenges: Preventing memory leaks with parallel execution and managing shared resources - Dependencies: Might need to add a new dependency for the new feature - ``` - placeholder: | - Size: [your estimate] - Reasoning: [why this size?] - Main challenges: [what's tricky?] - Dependencies: [what else is needed?] - validations: - required: true - type: textarea id: technical-considerations attributes: - label: Technical considerations (optional but helpful) + label: Technical considerations (REQUIRED if contributing, optional otherwise) description: | + **If you want to implement this feature, this section is REQUIRED.** + Share technical insights that could help planning: - Implementation approach or architecture changes - Performance implications @@ -155,40 +179,13 @@ body: - type: textarea id: trade-offs-and-risks attributes: - label: Trade-offs and risks (optional) + label: Trade-offs and risks (REQUIRED if contributing, optional otherwise) description: | + **If you want to implement this feature, this section is REQUIRED.** + What could go wrong or what alternatives did you consider? - Alternative approaches and why you chose this one - Potential negative impacts (performance, UX, etc.) - Breaking changes or migration concerns - Edge cases that need careful handling placeholder: 'e.g., "Alternative: use library X but it is 500KB larger", "Risk: might slow older devices", "Breaking: changes API response format"' - - - type: textarea - id: additional-context - attributes: - label: Additional context (optional) - description: Mockups, screenshots, links, user quotes, or other relevant information that supports your proposal. - - - type: checkboxes - id: checklist - attributes: - label: Proposal checklist - options: - - label: I've searched existing Issues and Discussions for duplicates - required: true - - label: This is a specific, actionable proposal with clear problem and solution - required: true - - label: I've included concrete acceptance criteria - required: true - - label: I understand this needs approval before implementation begins - required: true - - - type: checkboxes - id: willingness-to-contribute - attributes: - label: Interested in implementing this? - description: Optional - doesn't affect proposal consideration - options: - - label: Yes, I'd like to help implement this feature - required: false diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 6ae2fd2fa5..765c70614c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -30,19 +30,6 @@ Detail the steps to test your changes. This helps reviewers verify your work. - Include relevant testing environment details if applicable. --> -### Type of Change - - - -- [ ] 🐛 **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. - ### Pre-Submission Checklist @@ -50,17 +37,8 @@ Detail the steps to test your changes. This helps reviewers verify your work. - [ ] **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. +- [ ] **Testing**: New and/or updated tests have been added to cover my changes (if applicable). - [ ] **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). ### Screenshots / Videos diff --git a/.github/workflows/evals.yml b/.github/workflows/evals.yml index 9d8f9fb49b..b99fd7659e 100644 --- a/.github/workflows/evals.yml +++ b/.github/workflows/evals.yml @@ -41,7 +41,7 @@ jobs: EOF - name: Build image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . file: packages/evals/Dockerfile.runner diff --git a/.github/workflows/website-preview.yml b/.github/workflows/website-preview.yml index 49523e0686..6966005eaf 100644 --- a/.github/workflows/website-preview.yml +++ b/.github/workflows/website-preview.yml @@ -5,7 +5,10 @@ on: branches-ignore: - main paths: - - 'apps/web-roo-code/**' + - "apps/web-roo-code/**" + pull_request: + paths: + - "apps/web-roo-code/**" workflow_dispatch: env: @@ -21,11 +24,11 @@ jobs: - name: Check if VERCEL_TOKEN exists id: check run: | - if [ -n "${{ secrets.VERCEL_TOKEN }}" ]; then - echo "has-vercel-token=true" >> $GITHUB_OUTPUT - else - echo "has-vercel-token=false" >> $GITHUB_OUTPUT - fi + if [ -n "${{ secrets.VERCEL_TOKEN }}" ]; then + echo "has-vercel-token=true" >> $GITHUB_OUTPUT + else + echo "has-vercel-token=false" >> $GITHUB_OUTPUT + fi preview: runs-on: ubuntu-latest @@ -43,4 +46,39 @@ jobs: - name: Build Project Artifacts run: npx vercel build --token=${{ secrets.VERCEL_TOKEN }} - name: Deploy Project Artifacts to Vercel - run: npx vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} + id: deploy + run: | + DEPLOYMENT_URL=$(npx vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }}) + echo "deployment_url=$DEPLOYMENT_URL" >> $GITHUB_OUTPUT + echo "Preview deployed to: $DEPLOYMENT_URL" + + - name: Comment PR with preview link + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + const deploymentUrl = '${{ steps.deploy.outputs.deployment_url }}'; + const commentIdentifier = ''; + + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + + const existingComment = comments.find(comment => + comment.body.includes(commentIdentifier) + ); + + if (existingComment) { + return; + } + + const comment = commentIdentifier + '\n🚀 **Preview deployed!**\n\nYour changes have been deployed to Vercel:\n\n**Preview URL:** ' + deploymentUrl + '\n\nThis preview will be updated automatically when you push new commits to this PR.'; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: comment + }); diff --git a/.roo/rules-issue-writer/1_workflow.xml b/.roo/rules-issue-writer/1_workflow.xml index 9c71a589ad..a861bcafbb 100644 --- a/.roo/rules-issue-writer/1_workflow.xml +++ b/.roo/rules-issue-writer/1_workflow.xml @@ -30,10 +30,11 @@ - Any error messages or logs For Feature Requests, ensure you have: - - Specific problem description with impact - - Detailed proposed solution - - Clear acceptance criteria in Given/When/Then format - - Effort estimation with reasoning + - Specific problem description with impact (who is affected, when it happens, current vs expected behavior, impact) + - Additional context if available (mockups, screenshots, links) + + IMPORTANT: Do NOT ask for solution design, acceptance criteria, or technical details + unless the user explicitly states they want to contribute the implementation. Use multiple ask_followup_question calls if needed to gather all information. Be specific in your questions based on what's missing. @@ -63,8 +64,31 @@ - Explore Codebase for Context + Determine if User Wants to Contribute + Before exploring the codebase, determine if the user wants to contribute the implementation: + + + Are you interested in implementing this feature yourself, or are you just reporting the problem for the Roo team to solve? + + Just reporting the problem - the Roo team can design the solution + I want to contribute and implement this feature myself + I'm not sure yet, but I'd like to provide technical analysis + + + + Based on their response: + - If just reporting: Skip to step 6 (Draft Issue - Problem Only) + - If contributing: Continue to step 5 (Explore Codebase) + - If providing analysis: Continue to step 5 but make technical sections optional + + + + + Explore Codebase for Contributors + + ONLY perform this step if the user wants to contribute or provide technical analysis. + Use codebase_search FIRST to understand the relevant parts of the codebase: For Bug Reports: @@ -88,22 +112,27 @@ - read_file on specific files to understand implementation - search_files for specific error messages or patterns - Formulate an independent technical plan to solve the problem, disregarding any solution proposed by the issue author. + Formulate an independent technical plan to solve the problem. Document all relevant findings including: - File paths and line numbers - Current implementation details - Your proposed implementation plan - Related code that might be affected + + Then gather additional technical details: + - Ask for proposed solution approach + - Request acceptance criteria in Given/When/Then format + - Discuss technical considerations and trade-offs - - Draft Complete Issue Content + + Draft Issue Content - Create the complete issue body following the exact template structure. + Create the issue body based on whether the user is just reporting or contributing. - For Bug Reports, format as: + For Bug Reports, format is the same regardless of contribution intent: ``` ## App Version [version from user] @@ -137,6 +166,7 @@ [paste any error messages or logs] ``` + [If user is contributing, add:] ## Technical Analysis Based on my investigation: @@ -146,7 +176,7 @@ - **Proposed Fix:** [Detail the fix from your implementation plan.] ``` - For Feature Requests, format as: + For Feature Requests - PROBLEM REPORTERS (not contributing): ``` ## What specific problem does this solve? @@ -158,9 +188,43 @@ **Expected behavior:** [what should happen] **Impact:** [time wasted, errors, productivity loss] + ## Additional context + + [Any mockups, screenshots, links, or other supporting information] + + ## Related Discussions + + [If any related discussions were found, list them here] + - Closes #[discussion number] - [discussion title] + - Related to #[discussion number] - [discussion title] + ``` + + For Feature Requests - CONTRIBUTORS (implementing the feature): + ``` + ## What specific problem does this solve? + + [Detailed problem description following the template guidelines] + + **Who is affected:** [user groups] + **When this happens:** [specific scenarios] + **Current behavior:** [what happens now] + **Expected behavior:** [what should happen] + **Impact:** [time wasted, errors, productivity loss] + + ## Additional context + + [Any mockups, screenshots, links, or other supporting information] + + --- + + ## 🛠️ Contributing & Technical Analysis + + ✅ **I'm interested in implementing this feature** + ✅ **I understand this needs approval before implementation begins** + ## How should this be solved? - [Based on your independent analysis, describe your proposed solution here. Disregard the author's proposal.] + [Based on your analysis, describe the proposed solution] **What will change:** - [Specific change 1] @@ -182,29 +246,32 @@ [Add multiple scenarios as needed] - ## Estimated Effort and Complexity + ## Technical Considerations - **Size:** [estimate] - **Reasoning:** [why this size] - **Main challenges:** [technical difficulties] - **Dependencies:** [what's needed] - - ## Technical Implementation Plan - - Based on my analysis from the previous step: + **Implementation approach:** - Key files to modify: [list with paths] - Current architecture: [brief description] - Integration points: [where this fits] - Similar patterns in codebase: [examples] - - Implementation Steps: [Provide a detailed, step-by-step guide for your proposed solution.] - ## Technical Considerations + **Performance implications:** + [Any performance considerations] - [Any additional technical details] + **Compatibility concerns:** + [Any compatibility issues] ## Trade-offs and Risks - [Alternatives considered and potential issues] + **Alternatives considered:** + - [Alternative 1]: [Why not chosen] + - [Alternative 2]: [Why not chosen] + + **Potential risks:** + - [Risk 1]: [Mitigation strategy] + - [Risk 2]: [Mitigation strategy] + + **Breaking changes:** + [Any breaking changes or migration needs] ## Related Discussions @@ -215,7 +282,7 @@ - + Review and Confirm with User Present the complete drafted issue to the user for review: @@ -238,7 +305,7 @@ - + Create GitHub Issue Once user confirms, create the issue using the GitHub MCP tool: @@ -251,7 +318,7 @@ "owner": "RooCodeInc", "repo": "Roo-Code", "title": "[Create a descriptive title based on the issue content]", - "body": "[The complete formatted issue body from step 4]", + "body": "[The complete formatted issue body from step 6]", "labels": [Use ["bug"] for bug reports or ["proposal", "enhancement"] for features] } diff --git a/.roo/rules-issue-writer/2_github_issue_templates.xml b/.roo/rules-issue-writer/2_github_issue_templates.xml index 006c513808..3130f2026e 100644 --- a/.roo/rules-issue-writer/2_github_issue_templates.xml +++ b/.roo/rules-issue-writer/2_github_issue_templates.xml @@ -69,9 +69,9 @@ Detailed Feature Proposal - Propose a specific, actionable feature or enhancement for implementation + Report a specific problem that needs solving in Roo Code ["proposal", "enhancement"] - + @@ -95,9 +95,30 @@ Be specific about the problem, who it affects, and the impact. Avoid generic statements like "it's slow" or "it's confusing." - - + + + Mockups, screenshots, links, user quotes, or other relevant information that supports your proposal. + + + + + + + **Important:** If you check "Yes" below, the technical sections become REQUIRED. + We need detailed technical analysis from contributors to ensure quality implementation. + + + + + + + + + + + **If you want to implement this feature, this section is REQUIRED.** + **Describe your solution in detail.** Explain not just what to build, but how it should work. ✅ **Good examples:** @@ -117,9 +138,11 @@ Describe the specific changes and how they will work. Include user interaction details if relevant. - - + + + **If you want to implement this feature, this section is REQUIRED.** + **This is crucial - don't skip it.** Define what "working" looks like with specific, testable criteria. **Format suggestion:** @@ -146,35 +169,11 @@ Use the Given/When/Then format above or your own clear structure. - - + + - **Help us understand the scope.** This helps with planning and prioritisation. + **If you want to implement this feature, this section is REQUIRED.** - **Please include:** - - **Size estimate:** XS/Small/Medium/Large/XL - - **Reasoning:** What makes it this size? Which parts are complex? - - **Main challenges:** What's the trickiest bit to implement? - - **Dependencies:** Does this require other changes or external libraries? - - **Example:** - ``` - Size: Large - Reasoning: Touches task execution engine, UI components, and state management - Main challenges: Preventing memory leaks with parallel execution and managing shared resources - Dependencies: Might need to add a new dependency for the new feature - ``` - - - Size: [your estimate] - Reasoning: [why this size?] - Main challenges: [what's tricky?] - Dependencies: [what else is needed?] - - - - - Share technical insights that could help planning: - Implementation approach or architecture changes - Performance implications @@ -184,9 +183,11 @@ e.g., "Will need to refactor task manager", "Could impact memory usage on large files", "Requires a large portion of code to be rewritten" - - + + + **If you want to implement this feature, this section is REQUIRED.** + What could go wrong or what alternatives did you consider? - Alternative approaches and why you chose this one - Potential negative impacts (performance, UX, etc.) @@ -195,10 +196,24 @@ e.g., "Alternative: use library X but it is 500KB larger", "Risk: might slow older devices", "Breaking: changes API response format" - - - Mockups, screenshots, links, user quotes, or other relevant information that supports your proposal. - - + + + + + Template now focuses on problem reporting first, with solution contribution as optional + + + Only problem description and context are required for basic submission + + + Technical fields (solution, acceptance criteria, etc.) are only required if user wants to contribute + + + Users can submit after describing the problem without technical details + + + Implementation guidance moved to contributor section only + + \ No newline at end of file diff --git a/.roo/rules-issue-writer/3_best_practices.xml b/.roo/rules-issue-writer/3_best_practices.xml index fc2332dac9..6d70cba144 100644 --- a/.roo/rules-issue-writer/3_best_practices.xml +++ b/.roo/rules-issue-writer/3_best_practices.xml @@ -1,14 +1,38 @@ - - Always search for existing similar issues before creating a new one - - Search GitHub Discussions (especially feature-requests category) for related topics - - Include specific version numbers and environment details - - Use code blocks with syntax highlighting for code snippets - - Reference specific files and line numbers from codebase exploration - - Make titles descriptive but concise (e.g., "Dark theme: Submit button invisible due to white-on-grey text") - - For bugs, always test if the issue is reproducible - - For features, ensure the proposal aligns with project goals - - Include screenshots or mockups when relevant (ask user to provide) - - Link to related issues or PRs if found during exploration - - Add "Closes #[number]" for discussions that would be fully addressed by the issue - - Add "Related to #[number]" for partially related discussions + + - Focus on helping users describe problems clearly, not solutions + - The Roo team will design solutions unless the user explicitly wants to contribute + - Don't push users to provide technical details they may not have + - Make it easy for non-technical users to report issues effectively + + + + - Always search for existing similar issues before creating a new one + - Search GitHub Discussions (especially feature-requests category) for related topics + - Include specific version numbers and environment details + - Use code blocks with syntax highlighting for code snippets + - Make titles descriptive but concise (e.g., "Dark theme: Submit button invisible due to white-on-grey text") + - For bugs, always test if the issue is reproducible + - Include screenshots or mockups when relevant (ask user to provide) + - Link to related issues or PRs if found during exploration + - Add "Closes #[number]" for discussions that would be fully addressed by the issue + - Add "Related to #[number]" for partially related discussions + + + + - Only explore codebase if user wants to contribute + - Reference specific files and line numbers from codebase exploration + - Ensure technical proposals align with project architecture + - Include implementation steps and technical analysis + - Provide clear acceptance criteria in Given/When/Then format + - Consider trade-offs and alternative approaches + + + + - Be supportive and encouraging to problem reporters + - Don't overwhelm users with technical questions upfront + - Clearly indicate when technical sections are optional + - Guide contributors through the additional requirements + - Make the "submit now" option clear for problem reporters + \ No newline at end of file diff --git a/.roo/rules-issue-writer/4_common_mistakes_to_avoid.xml b/.roo/rules-issue-writer/4_common_mistakes_to_avoid.xml index 7818d5e29a..2013bd73d8 100644 --- a/.roo/rules-issue-writer/4_common_mistakes_to_avoid.xml +++ b/.roo/rules-issue-writer/4_common_mistakes_to_avoid.xml @@ -1,10 +1,30 @@ - - Vague descriptions like "doesn't work" or "broken" - - Missing reproduction steps for bugs - - Feature requests without clear problem statements - - No acceptance criteria for features - - Forgetting to include technical context from code exploration - - Not checking for duplicates - - Using wrong labels or no labels - - Titles that don't summarize the issue + + - Vague descriptions like "doesn't work" or "broken" + - Missing reproduction steps for bugs + - Feature requests without clear problem statements + - Not explaining the impact on users + - Forgetting to specify when/how the problem occurs + - Using wrong labels or no labels + - Titles that don't summarize the issue + - Not checking for duplicates + + + + - Asking for technical details from non-contributing users + - Exploring codebase before confirming user wants to contribute + - Requiring acceptance criteria from problem reporters + - Making the process too complex for simple problem reports + - Not clearly indicating the "submit now" option + - Overwhelming users with contributor requirements upfront + + + + - Starting implementation before approval + - Not providing detailed technical analysis when contributing + - Missing acceptance criteria for contributed features + - Forgetting to include technical context from code exploration + - Not considering trade-offs and alternatives + - Proposing solutions without understanding current architecture + \ No newline at end of file diff --git a/.roo/rules-issue-writer/5_github_mcp_tool_usage.xml b/.roo/rules-issue-writer/5_github_mcp_tool_usage.xml index b99229acff..b5ae5d8aec 100644 --- a/.roo/rules-issue-writer/5_github_mcp_tool_usage.xml +++ b/.roo/rules-issue-writer/5_github_mcp_tool_usage.xml @@ -4,7 +4,8 @@ Here's when and how to use each tool in the issue creation workflow. Note: Issue body formatting should follow the templates defined in - and + 2_github_issue_templates.xml, with different formats for problem reporters + vs contributors. @@ -93,10 +94,15 @@ - + + + These tools should ONLY be used if the user has indicated they want to + contribute the implementation. Skip these for problem reporters. + + - For bug reports, check recent commits that might have introduced the issue. + For bug reports from contributors, check recent commits that might have introduced the issue. Look for commits touching the affected files. @@ -137,7 +143,7 @@ Use to find code patterns across the repository on GitHub. - Complements local codebase_search tool. + Complements local codebase_search tool for contributors. @@ -174,15 +180,15 @@ - + Only use after: 1. Confirming no duplicates exist - 2. Gathering all required information per or - 3. Exploring codebase for context + 2. Gathering all required information + 3. Determining if user is contributing or just reporting 4. Getting user confirmation @@ -194,13 +200,13 @@ "owner": "RooCodeInc", "repo": "Roo-Code", "title": "[Descriptive title of the bug]", - "body": "[Format according to fields]", + "body": "[Format according to bug report template]", "labels": ["bug"] } - + github create_issue @@ -208,21 +214,35 @@ { "owner": "RooCodeInc", "repo": "Roo-Code", - "title": "[Descriptive title of the feature request]", - "body": "[Format according to fields]", + "title": "[Problem-focused title]", + "body": "[Problem description only - no technical details]", "labels": ["proposal", "enhancement"] } - + + + + github + create_issue + + { + "owner": "RooCodeInc", + "repo": "Roo-Code", + "title": "[Problem-focused title with implementation intent]", + "body": "[Full template including technical analysis sections]", + "labels": ["proposal", "enhancement"] + } + + + - ONLY Use if user wants to add additional information after creation. - + ONLY use if user wants to add additional information after creation. @@ -233,7 +253,7 @@ "owner": "RooCodeInc", "repo": "Roo-Code", "issue_number": 456, - "body": "Blah blah blah, additional context or comments." + "body": "Additional context or comments." } @@ -281,21 +301,30 @@ - During codebase exploration: + Decision point for contribution: + 1. Ask user if they want to contribute implementation + 2. If yes: Use contributor tools for codebase investigation + 3. If no: Skip directly to creating a problem-focused issue + 4. This saves time for problem reporters + + + + During codebase exploration (CONTRIBUTORS ONLY): 1. Use list_commits to find recent changes to affected files 2. Use search_code for additional code references 3. Check list_pull_requests for related PRs 4. Include findings in the technical context section - - - - When creating the issue: - 1. Format the issue body according to or - 2. Use create_issue with complete formatted body - 3. Capture the returned issue number - 4. If related issues were found, use add_issue_comment to link them - 5. Show user the created issue URL + + + When creating the issue: + 1. Format differently based on contributor vs problem reporter + 2. Problem reporters: Simple problem description + context + 3. Contributors: Full template with technical sections + 4. Use create_issue with appropriate body format + 5. Capture the returned issue number + 6. Show user the created issue URL + diff --git a/.roo/rules-pr-fixer/1_workflow.xml b/.roo/rules-pr-fixer/1_workflow.xml new file mode 100644 index 0000000000..c27004c430 --- /dev/null +++ b/.roo/rules-pr-fixer/1_workflow.xml @@ -0,0 +1,57 @@ + + + This mode is designed to help resolve issues in existing pull requests. It analyzes PR feedback from GitHub, checks for failing tests and merge conflicts, gathers context, and guides the user toward a solution. + + + + + Understand the user's request +
+ Parse the user's input to identify the pull request URL or number. Extract the repository owner and name. +
+
+ + Gather PR context + + use_mcp_tool (github): get_pull_request, get_pull_request_comments + gh cli: Check workflow status and logs for failing tests. + gh cli: Check for merge conflicts. + + +
+ + + + Analyze the gathered information to identify the core problems. + + Summarize review comments and requested changes. + Identify the root cause of failing tests by analyzing logs. + Determine if merge conflicts exist. + + + + + Synthesize the findings and present them to the user. + + Present a summary of the issues found (reviews, failing tests, conflicts). + Use ask_followup_question to ask the user how they want to proceed with fixing the issues. + + + + + Execute the user's chosen course of action. + + Check out the PR branch locally using 'gh pr checkout'. + Apply code changes based on review feedback. + Fix failing tests. + Resolve conflicts by rebasing the PR branch and force-pushing. + + + + + + All actionable review comments have been addressed. + All tests are passing. + The PR is free of merge conflicts. + +
\ No newline at end of file diff --git a/.roo/rules-pr-fixer/2_best_practices.xml b/.roo/rules-pr-fixer/2_best_practices.xml new file mode 100644 index 0000000000..1576daa3c1 --- /dev/null +++ b/.roo/rules-pr-fixer/2_best_practices.xml @@ -0,0 +1,56 @@ + + + + Context is Key + Always gather full context before attempting a fix. This includes reading all relevant PR comments, checking CI/CD logs, and understanding the surrounding code. + Without full context, fixes may be incomplete or introduce new issues. + + + Incremental Fixes + Address issues one at a time (e.g., fix tests first, then address comments). This makes the process more manageable and easier to validate. + Tackling all issues at once can be complex and error-prone. + + + + + + How to correctly escape conflict markers when using apply_diff. + + + + + + + Have all review comments been addressed? + Are all CI/CD checks passing? + Is the PR free of merge conflicts? + Have the changes been tested locally? + + + \ No newline at end of file diff --git a/.roo/rules-pr-fixer/3_common_patterns.xml b/.roo/rules-pr-fixer/3_common_patterns.xml new file mode 100644 index 0000000000..848be1482d --- /dev/null +++ b/.roo/rules-pr-fixer/3_common_patterns.xml @@ -0,0 +1,48 @@ + + + A set of commands to quickly assess the state of a Pull Request. + + + + Commands to investigate why a specific test is failing. + + + + A sequence of commands to resolve merge conflicts locally using rebase. + + + + Command to check out a pull request branch locally. + + + diff --git a/.roo/rules-pr-fixer/4_tool_usage.xml b/.roo/rules-pr-fixer/4_tool_usage.xml new file mode 100644 index 0000000000..e6f828b9f2 --- /dev/null +++ b/.roo/rules-pr-fixer/4_tool_usage.xml @@ -0,0 +1,44 @@ + + + + use_mcp_tool (server: github) + Use at the start to get all review comments and PR metadata. + Provides the core context of what needs to be fixed from a human perspective. + + + gh pr checks + After getting comments, to check the technical status. + Quickly identifies if there are failing automated checks that need investigation. + + + + + + + Always fetch details to get the branch name, owner, repo slug, and mergeable state. + + + + + + Parse all comments to create a checklist of required changes. + Ignore comments that are not actionable or have been resolved. + + + + + + Use this command to get the exact error messages from failing tests. + Search the log for keywords like 'error', 'failed', or 'exception' to quickly find the root cause. + + + + + + After analyzing all the problems (reviews, tests, conflicts), present a summary to the user. + Provide clear, actionable next steps as suggestions. + Example suggestions: "Address review comments first.", "Tackle the failing tests.", "Resolve merge conflicts." + + + + \ No newline at end of file diff --git a/.roo/rules-pr-fixer/5_examples.xml b/.roo/rules-pr-fixer/5_examples.xml new file mode 100644 index 0000000000..77905cc3a6 --- /dev/null +++ b/.roo/rules-pr-fixer/5_examples.xml @@ -0,0 +1,91 @@ + + + + A pull request has a failing CI check and a review comment asking for a change. + + + + Fix PR #4365 in RooCodeInc/Roo-Code. + + + + + Get PR details and review comments. + + + github + get_pull_request + + { + "owner": "RooCodeInc", + "repo": "Roo-Code", + "pullNumber": 4365 + } + + + + github + get_pull_request_comments + + { + "owner": "RooCodeInc", + "repo": "Roo-Code", + "pullNumber": 4365 + } + + + + Get the branch name, list of review comments, and check for mergeability. + + + + Check CI status. + + +gh pr checks 4365 + + + Identify which check is failing. + + + + Get logs for the failing check. + + +gh run view --log-failed + + + Find the specific error message causing the test to fail. + + + + Check out the pull request branch. + + + gh pr checkout 4365 + + + The PR branch is now ready for local edits. + + + + Summarize findings and ask the user for the next action. + + +I've checked out the branch. I've found a failing test related to 'XYZ' and a review comment asking to rename a variable. How should we proceed? + +First, apply the change requested in the review comment. +Let's start by fixing the failing test. +Show me the code for the failing test and the file with the requested change. + + + + + + + + Always gather all information before proposing a solution. + Use a combination of the GitHub MCP server and the `gh` CLI to get a complete picture of the PR's status. + + + diff --git a/.roo/rules-pr-reviewer/1_workflow.xml b/.roo/rules-pr-reviewer/1_workflow.xml index 55f9e64839..c27efaf4d5 100644 --- a/.roo/rules-pr-reviewer/1_workflow.xml +++ b/.roo/rules-pr-reviewer/1_workflow.xml @@ -137,8 +137,8 @@ Your suggestions should: - Use a **friendly, curious tone** — prefer asking: "Is this intentional?" or "Could we approach this differently to improve X?" - Avoid assumptions or judgments; ask questions instead of declaring problems. - - Skip unnecessary praise. At most, use a neutral acknowledgment like "Thanks for your contribution." - - Use Markdown **only when necessary for clarity** (e.g., links, code blocks). Avoid excessive formatting. + - Skip ALL praise and positive comments. Focus exclusively on issues that need attention. + - Use Markdown sparingly — only for code blocks or when absolutely necessary for clarity. Avoid markdown headings (###, ##, etc.) entirely. - Avoid including internal evaluation terminology (e.g., scores or internal tags) in public comments. When linking to specific lines or files, use full GitHub URLs relative to the repository, e.g. diff --git a/.roo/rules-pr-reviewer/2_best_practices.xml b/.roo/rules-pr-reviewer/2_best_practices.xml index ed26705f74..29adcba946 100644 --- a/.roo/rules-pr-reviewer/2_best_practices.xml +++ b/.roo/rules-pr-reviewer/2_best_practices.xml @@ -6,8 +6,11 @@ - Focus on the changes made, not unrelated code - Ensure all changes are directly related to the linked issue - Use a friendly, curious tone in all comments - - Ask questions rather than making assumptions + - Ask questions rather than making assumptions - there may be intentions behind the code choices - Provide actionable feedback with specific suggestions + - Focus exclusively on issues and improvements - skip all praise or positive comments + - Use minimal markdown - avoid headings (###, ##) and excessive formatting + - Only use markdown for code blocks or when absolutely necessary for clarity - Consider the PR's scope - suggest breaking up large PRs - Verify proper i18n implementation for UI changes - Check for test coverage without executing tests diff --git a/.roo/rules-pr-reviewer/3_common_mistakes_to_avoid.xml b/.roo/rules-pr-reviewer/3_common_mistakes_to_avoid.xml index 464499edf2..6a5b707c12 100644 --- a/.roo/rules-pr-reviewer/3_common_mistakes_to_avoid.xml +++ b/.roo/rules-pr-reviewer/3_common_mistakes_to_avoid.xml @@ -3,7 +3,9 @@ - Making judgmental or harsh comments - Providing feedback on code outside the PR's scope - Overlooking unrelated changes not tied to the main issue - - Using excessive praise or unnecessary formatting + - Including ANY praise or positive comments - focus only on issues + - Using markdown headings (###, ##, #) in review comments + - Using excessive markdown formatting when plain text would suffice - Submitting comments without user preview/approval - Ignoring existing PR comments and discussions - Forgetting to check for an associated issue for additional context @@ -13,6 +15,6 @@ - Using internal evaluation terminology in public comments - Not providing actionable suggestions for improvements - Reviewing only the diff without local context - - Making assumptions instead of asking clarifying questions + - Making assumptions instead of asking clarifying questions about potential intentions - Forgetting to link to specific lines with full GitHub URLs \ No newline at end of file diff --git a/.roomodes b/.roomodes index 0e3ab97541..236026c738 100644 --- a/.roomodes +++ b/.roomodes @@ -25,6 +25,8 @@ customModes: - fileRegex: (\.roomodes$|\.roo/.*\.xml$|\.yaml$) description: Mode configuration files and XML instructions - command + - mcp + source: project - slug: test name: 🧪 Test roleDefinition: >- @@ -241,4 +243,20 @@ customModes: description: Temporary documentation extraction files only - command - mcp - + - slug: pr-fixer + name: 🛠️ PR Fixer + roleDefinition: "You are Roo, a pull request resolution specialist. Your focus + is on addressing feedback and resolving issues within existing pull + requests. Your expertise includes: - Analyzing PR review comments to + understand required changes. - Checking CI/CD workflow statuses to + identify failing tests. - Fetching and analyzing test logs to diagnose + failures. - Identifying and resolving merge conflicts. - Guiding the user + through the resolution process." + whenToUse: Use this mode to fix pull requests. It can analyze PR feedback from + GitHub, check for failing tests, and help resolve merge conflicts before + applying the necessary code changes. + groups: + - read + - edit + - command + - mcp diff --git a/.vscode/settings.json b/.vscode/settings.json index 16a5c02292..6eb636c982 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,5 +9,6 @@ "dist": true // set this to false to include "dist" folder in search results }, // Turn off tsc task auto detection since we have the necessary tasks as npm scripts - "typescript.tsc.autoDetect": "off" + "typescript.tsc.autoDetect": "off", + "vitest.disableWorkspaceWarning": true } diff --git a/CHANGELOG.md b/CHANGELOG.md index ea8b451e3e..daee785b6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,55 @@ # Roo Code Changelog +## [3.21.3] - 2025-06-21 + +- Add profile-specific context condensing thresholds (thanks @SannidhyaSah!) +- Fix context length for lmstudio and ollama (thanks @thecolorblue!) +- Resolve MCP tool eye icon state and hide in chat context (thanks @daniel-lxs!) + +## [3.21.2] - 2025-06-20 + +- Add LaTeX math equation rendering in chat window +- Add toggle for excluding MCP server tools from the prompt (thanks @Rexarrior!) +- Add symlink support to list_files tool +- Fix marketplace blanking after populating +- Fix recursive directory scanning in @ mention "Add Folder" functionality (thanks @village-way!) +- Resolve phantom subtask display on cancel during API retry +- Correct Gemini 2.5 Flash pricing (thanks @daniel-lxs!) +- Resolve marketplace timeout issues and display installed MCPs (thanks @daniel-lxs!) +- Onboarding tweaks to emphasize modes (thanks @brunobergher!) +- Rename 'Boomerang Tasks' to 'Task Orchestration' for clarity +- Remove command execution from attempt_completion +- Fix markdown for links followed by punctuation (thanks @xyOz-dev!) + +## [3.21.1] - 2025-06-19 + +- Fix tree-sitter issues that were preventing codebase indexing from working correctly +- Improve error handling for codebase search embeddings +- Resolve MCP server execution on Windows with node version managers +- Default 'Enable MCP Server Creation' to false +- Rate limit correctly when starting a subtask (thanks @olweraltuve!) + +## [3.21.0] - 2025-06-17 + +- Add Roo Marketplace to make it easy to discover and install great MCPs and modes! +- Add Gemini 2.5 models (Pro, Flash and Flash Lite) (thanks @daniel-lxs!) +- Add support for Excel (.xlsx) files in tools (thanks @chrarnoldus!) +- Add max tokens checkbox option for OpenAI compatible provider (thanks @AlexandruSmirnov!) +- Update provider models and prices for Groq & Mistral (thanks @KanTakahiro!) +- Add proper error handling for API conversation history issues (thanks @KJ7LNW!) +- Fix ambiguous model id error (thanks @elianiva!) +- Fix save/discard/revert flow for Prompt Settings (thanks @hassoncs!) +- Fix codebase indexing alignment with list-files hidden directory filtering (thanks @daniel-lxs!) +- Fix subtask completion mismatch (thanks @feifei325!) +- Fix Windows path normalization in MCP variable injection (thanks @daniel-lxs!) +- Update marketplace branding to 'Roo Marketplace' (thanks @SannidhyaSah!) +- Refactor to more consistent history UI (thanks @elianiva!) +- Adjust context menu positioning to be near Copilot +- Update evals Docker setup to work on Windows (thanks @StevenTCramer!) +- Include current working directory in terminal details +- Encourage use of start_line in multi-file diff to match legacy diff +- Always focus the panel when clicked to ensure menu buttons are visible (thanks @hassoncs!) + ## [3.20.3] - 2025-06-13 - Resolve diff editor race condition in multi-monitor setups (thanks @daniel-lxs!) diff --git a/README.md b/README.md index a8744447b4..e374ea9c3d 100644 --- a/README.md +++ b/README.md @@ -49,13 +49,13 @@ Check out the [CHANGELOG](CHANGELOG.md) for detailed updates and fixes. --- -## 🎉 Roo Code 3.20 Released +## 🎉 Roo Code 3.21 Released -Roo Code 3.20 brings major new features and improvements based on your feedback! +Roo Code 3.21 brings major new features and improvements based on your feedback! -- **Experimental Marketplace** - Discover and install modes and MCPs from the new marketplace (enable in Experimental Settings). -- **Enhanced File Operations** - Multiple concurrent file writes now available in Experimental Settings, and multiple concurrent reads has graduated from experimental and now lives in the Context Settings. -- **MCP Improvements & More** - Enhanced MCP support, more Mermaid controls, thinking support in Amazon Bedrock, and much more! +- **Roo Marketplace Launch** - The marketplace is now live! The marketplace is now live! Discover and install modes and MCPs easier than ever before. +- **Gemini 2.5 Models** - Added support for new Gemini 2.5 Pro, Flash, and Flash Lite models. +- **Excel File Support & More** - Added Excel (.xlsx) file support and numerous bug fixes and improvements! --- @@ -176,38 +176,40 @@ Thanks to all our contributors who have helped make Roo Code better! -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| joemanley201
joemanley201
| -| System233
System233
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| MuriloFP
MuriloFP
| jr
jr
| -| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| elianiva
elianiva
| sachasayan
sachasayan
| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| -| monotykamary
monotykamary
| cannuri
cannuri
| zhangtony239
zhangtony239
| qdaxb
qdaxb
| feifei325
feifei325
| xyOz-dev
xyOz-dev
| -| pugazhendhi-m
pugazhendhi-m
| shariqriazz
shariqriazz
| lloydchang
lloydchang
| vigneshsubbiah16
vigneshsubbiah16
| dtrugman
dtrugman
| Szpadel
Szpadel
| -| diarmidmackenzie
diarmidmackenzie
| psv2522
psv2522
| Premshay
Premshay
| lupuletic
lupuletic
| kiwina
kiwina
| aheizi
aheizi
| -| PeterDaveHello
PeterDaveHello
| olweraltuve
olweraltuve
| chrarnoldus
chrarnoldus
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| RaySinner
RaySinner
| -| afshawnlotfi
afshawnlotfi
| pdecat
pdecat
| noritaka1166
noritaka1166
| kyle-apex
kyle-apex
| emshvac
emshvac
| Lunchb0ne
Lunchb0ne
| -| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| arthurauffray
arthurauffray
| upamune
upamune
| NamesMT
NamesMT
| -| taylorwilsdon
taylorwilsdon
| StevenTCramer
StevenTCramer
| sammcj
sammcj
| Ruakij
Ruakij
| p12tic
p12tic
| gtaylor
gtaylor
| -| hassoncs
hassoncs
| aitoroses
aitoroses
| anton-otee
anton-otee
| SannidhyaSah
SannidhyaSah
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| dlab-anton
dlab-anton
| eonghk
eonghk
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| benzntech
benzntech
| axkirillov
axkirillov
| bramburn
bramburn
| olearycrew
olearycrew
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| -| jcbdev
jcbdev
| mr-ryan-james
mr-ryan-james
| ross
ross
| philfung
philfung
| napter
napter
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| SplittyDev
SplittyDev
| mdp
mdp
| kohii
kohii
| kinandan
kinandan
| jwcraig
jwcraig
| -| shoopapa
shoopapa
| im47cn
im47cn
| hongzio
hongzio
| hatsu38
hatsu38
| GOODBOY008
GOODBOY008
| forestyoo
forestyoo
| -| dqroid
dqroid
| dairui1
dairui1
| tmsjngx0
tmsjngx0
| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| -| amittell
amittell
| vladstudio
vladstudio
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| zxdvd
zxdvd
| nevermorec
nevermorec
| -| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| student20880
student20880
| shohei-ihaya
shohei-ihaya
| -| shaybc
shaybc
| seedlord
seedlord
| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| -| pokutuna
pokutuna
| philipnext
philipnext
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| -| mlopezr
mlopezr
| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| -| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| devxpain
devxpain
| -| chadgauth
chadgauth
| bogdan0083
bogdan0083
| Atlogit
Atlogit
| atlasgong
atlasgong
| andreastempsch
andreastempsch
| alasano
alasano
| -| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| adamwlarson
adamwlarson
| -| adamhill
adamhill
| AMHesch
AMHesch
| tgfjt
tgfjt
| maekawataiki
maekawataiki
| samsilveira
samsilveira
| 01Rian
01Rian
| -| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| kvokka
kvokka
| ecmasx
ecmasx
| -| mollux
mollux
| marvijo-code
marvijo-code
| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| -| ksze
ksze
| Jdo300
Jdo300
| hesara
hesara
| DeXtroTip
DeXtroTip
| pfitz
pfitz
| celestial-vault
celestial-vault
| +| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| +| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| joemanley201
joemanley201
| +| System233
System233
| jquanton
jquanton
| nissa-seru
nissa-seru
| NyxJae
NyxJae
| jr
jr
| MuriloFP
MuriloFP
| +| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| sachasayan
sachasayan
| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| +| monotykamary
monotykamary
| cannuri
cannuri
| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| qdaxb
qdaxb
| +| shariqriazz
shariqriazz
| pugazhendhi-m
pugazhendhi-m
| vigneshsubbiah16
vigneshsubbiah16
| lloydchang
lloydchang
| dtrugman
dtrugman
| Szpadel
Szpadel
| +| chrarnoldus
chrarnoldus
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| Premshay
Premshay
| lupuletic
lupuletic
| +| kiwina
kiwina
| aheizi
aheizi
| PeterDaveHello
PeterDaveHello
| afshawnlotfi
afshawnlotfi
| RaySinner
RaySinner
| nbihan-mediware
nbihan-mediware
| +| ChuKhaLi
ChuKhaLi
| hassoncs
hassoncs
| emshvac
emshvac
| kyle-apex
kyle-apex
| noritaka1166
noritaka1166
| pdecat
pdecat
| +| SannidhyaSah
SannidhyaSah
| StevenTCramer
StevenTCramer
| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| +| dleffel
dleffel
| arthurauffray
arthurauffray
| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| +| Ruakij
Ruakij
| p12tic
p12tic
| gtaylor
gtaylor
| aitoroses
aitoroses
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| +| taisukeoe
taisukeoe
| avtc
avtc
| dlab-anton
dlab-anton
| eonghk
eonghk
| kcwhite
kcwhite
| ronyblum
ronyblum
| +| teddyOOXX
teddyOOXX
| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| +| yt3trees
yt3trees
| benzntech
benzntech
| axkirillov
axkirillov
| anton-otee
anton-otee
| bramburn
bramburn
| olearycrew
olearycrew
| +| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| julionav
julionav
| SplittyDev
SplittyDev
| +| mdp
mdp
| napter
napter
| ross
ross
| philfung
philfung
| dairui1
dairui1
| dqroid
dqroid
| +| forestyoo
forestyoo
| GOODBOY008
GOODBOY008
| hatsu38
hatsu38
| hongzio
hongzio
| im47cn
im47cn
| shoopapa
shoopapa
| +| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| +| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| zxdvd
zxdvd
| vladstudio
vladstudio
| tmsjngx0
tmsjngx0
| +| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| student20880
student20880
| +| shohei-ihaya
shohei-ihaya
| shaybc
shaybc
| seedlord
seedlord
| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| +| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| +| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| +| kohii
kohii
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| dflatline
dflatline
| +| Deon588
Deon588
| dleen
dleen
| devxpain
devxpain
| chadgauth
chadgauth
| brunobergher
brunobergher
| thecolorblue
thecolorblue
| +| bogdan0083
bogdan0083
| Atlogit
Atlogit
| atlasgong
atlasgong
| andreastempsch
andreastempsch
| alasano
alasano
| QuinsZouls
QuinsZouls
| +| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| adamwlarson
adamwlarson
| adamhill
adamhill
| +| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| 01Rian
01Rian
| RSO
RSO
| +| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| +| marvijo-code
marvijo-code
| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| +| KanTakahiro
KanTakahiro
| ksze
ksze
| Jdo300
Jdo300
| hesara
hesara
| DeXtroTip
DeXtroTip
| pfitz
pfitz
| +| celestial-vault
celestial-vault
| | | | | | diff --git a/apps/vscode-e2e/src/suite/extension.test.ts b/apps/vscode-e2e/src/suite/extension.test.ts index 3283dfcc56..e7a92521cf 100644 --- a/apps/vscode-e2e/src/suite/extension.test.ts +++ b/apps/vscode-e2e/src/suite/extension.test.ts @@ -1,7 +1,11 @@ import * as assert from "assert" import * as vscode from "vscode" -suite("Roo Code Extension", () => { +import { setDefaultSuiteTimeout } from "./test-utils" + +suite("Roo Code Extension", function () { + setDefaultSuiteTimeout(this) + test("Commands should be registered", async () => { const expectedCommands = [ "SidebarProvider.open", diff --git a/apps/vscode-e2e/src/suite/index.ts b/apps/vscode-e2e/src/suite/index.ts index 04c36a34e1..ab0be6e5df 100644 --- a/apps/vscode-e2e/src/suite/index.ts +++ b/apps/vscode-e2e/src/suite/index.ts @@ -27,13 +27,11 @@ export async function run() { globalThis.api = api - // Configure Mocha with grep pattern if provided const mochaOptions: Mocha.MochaOptions = { ui: "tdd", - timeout: 300_000, + timeout: 20 * 60 * 1_000, // 20m } - // Apply grep filter if TEST_GREP is set if (process.env.TEST_GREP) { mochaOptions.grep = process.env.TEST_GREP console.log(`Running tests matching pattern: ${process.env.TEST_GREP}`) @@ -42,17 +40,16 @@ export async function run() { const mocha = new Mocha(mochaOptions) const cwd = path.resolve(__dirname, "..") - // Get test files based on filter let testFiles: string[] + if (process.env.TEST_FILE) { - // Run specific test file const specificFile = process.env.TEST_FILE.endsWith(".js") ? process.env.TEST_FILE : `${process.env.TEST_FILE}.js` + testFiles = await glob(`**/${specificFile}`, { cwd }) console.log(`Running specific test file: ${specificFile}`) } else { - // Run all test files testFiles = await glob("**/**.test.js", { cwd }) } @@ -62,7 +59,6 @@ export async function run() { testFiles.forEach((testFile) => mocha.addFile(path.resolve(cwd, testFile))) - // Let's go! return new Promise((resolve, reject) => mocha.run((failures) => (failures === 0 ? resolve() : reject(new Error(`${failures} tests failed.`)))), ) diff --git a/apps/vscode-e2e/src/suite/modes.test.ts b/apps/vscode-e2e/src/suite/modes.test.ts index 817d5f71ce..81d8a2b7fb 100644 --- a/apps/vscode-e2e/src/suite/modes.test.ts +++ b/apps/vscode-e2e/src/suite/modes.test.ts @@ -1,8 +1,11 @@ import * as assert from "assert" import { waitUntilCompleted } from "./utils" +import { setDefaultSuiteTimeout } from "./test-utils" + +suite("Roo Code Modes", function () { + setDefaultSuiteTimeout(this) -suite("Roo Code Modes", () => { test("Should handle switching modes correctly", async () => { const modes: string[] = [] diff --git a/apps/vscode-e2e/src/suite/task.test.ts b/apps/vscode-e2e/src/suite/task.test.ts index e97c3b4f1e..96b1198fd4 100644 --- a/apps/vscode-e2e/src/suite/task.test.ts +++ b/apps/vscode-e2e/src/suite/task.test.ts @@ -3,8 +3,11 @@ import * as assert from "assert" import type { ClineMessage } from "@roo-code/types" import { waitUntilCompleted } from "./utils" +import { setDefaultSuiteTimeout } from "./test-utils" + +suite("Roo Code Task", function () { + setDefaultSuiteTimeout(this) -suite("Roo Code Task", () => { test("Should handle prompt and response correctly", async () => { const api = globalThis.api diff --git a/apps/vscode-e2e/src/suite/test-utils.ts b/apps/vscode-e2e/src/suite/test-utils.ts new file mode 100644 index 0000000000..1ad33844ba --- /dev/null +++ b/apps/vscode-e2e/src/suite/test-utils.ts @@ -0,0 +1,5 @@ +export const DEFAULT_SUITE_TIMEOUT = 120_000 + +export function setDefaultSuiteTimeout(context: Mocha.Suite) { + context.timeout(DEFAULT_SUITE_TIMEOUT) +} diff --git a/apps/vscode-e2e/src/suite/tools/apply-diff.test.ts b/apps/vscode-e2e/src/suite/tools/apply-diff.test.ts index ac8ffa6f58..64d019aef0 100644 --- a/apps/vscode-e2e/src/suite/tools/apply-diff.test.ts +++ b/apps/vscode-e2e/src/suite/tools/apply-diff.test.ts @@ -6,8 +6,11 @@ import * as vscode from "vscode" import type { ClineMessage } from "@roo-code/types" import { waitFor, sleep } from "../utils" +import { setDefaultSuiteTimeout } from "../test-utils" + +suite("Roo Code apply_diff Tool", function () { + setDefaultSuiteTimeout(this) -suite("Roo Code apply_diff Tool", () => { let workspaceDir: string // Pre-created test files that will be used across tests @@ -491,9 +494,6 @@ ${testFile.content}\nAssume the file exists and you can modify it directly.`, }) test("Should handle apply_diff errors gracefully", async function () { - // Increase timeout for this specific test - this.timeout(90_000) - const api = globalThis.api const messages: ClineMessage[] = [] const testFile = testFiles.errorHandling @@ -605,9 +605,6 @@ Assume the file exists and you can modify it directly.`, }) test("Should apply multiple search/replace blocks to edit two separate functions", async function () { - // Increase timeout for this specific test - this.timeout(60_000) - const api = globalThis.api const messages: ClineMessage[] = [] const testFile = testFiles.multiSearchReplace diff --git a/apps/vscode-e2e/src/suite/tools/execute-command.test.ts b/apps/vscode-e2e/src/suite/tools/execute-command.test.ts index 7bed887e6d..21933d0879 100644 --- a/apps/vscode-e2e/src/suite/tools/execute-command.test.ts +++ b/apps/vscode-e2e/src/suite/tools/execute-command.test.ts @@ -6,8 +6,11 @@ import * as vscode from "vscode" import type { ClineMessage } from "@roo-code/types" import { waitFor, sleep, waitUntilCompleted } from "../utils" +import { setDefaultSuiteTimeout } from "../test-utils" + +suite("Roo Code execute_command Tool", function () { + setDefaultSuiteTimeout(this) -suite("Roo Code execute_command Tool", () => { let workspaceDir: string // Pre-created test files that will be used across tests @@ -331,9 +334,6 @@ Avoid at all costs suggesting a command when using the attempt_completion tool`, }) test("Should execute multiple commands sequentially", async function () { - // Increase timeout for this test - this.timeout(90_000) - const api = globalThis.api const testFile = testFiles.multiCommand let taskStarted = false @@ -447,9 +447,6 @@ After both commands are executed, use the attempt_completion tool to complete th }) test("Should handle long-running commands", async function () { - // Increase timeout for this test - this.timeout(60_000) - const api = globalThis.api let taskStarted = false let _taskCompleted = false diff --git a/apps/vscode-e2e/src/suite/tools/insert-content.test.ts b/apps/vscode-e2e/src/suite/tools/insert-content.test.ts index c98c30cb46..c9d65d0d0b 100644 --- a/apps/vscode-e2e/src/suite/tools/insert-content.test.ts +++ b/apps/vscode-e2e/src/suite/tools/insert-content.test.ts @@ -6,8 +6,11 @@ import * as vscode from "vscode" import type { ClineMessage } from "@roo-code/types" import { waitFor, sleep } from "../utils" +import { setDefaultSuiteTimeout } from "../test-utils" + +suite("Roo Code insert_content Tool", function () { + setDefaultSuiteTimeout(this) -suite("Roo Code insert_content Tool", () => { let workspaceDir: string // Pre-created test files that will be used across tests diff --git a/apps/vscode-e2e/src/suite/tools/list-files.test.ts b/apps/vscode-e2e/src/suite/tools/list-files.test.ts index 9612869435..5340a13a16 100644 --- a/apps/vscode-e2e/src/suite/tools/list-files.test.ts +++ b/apps/vscode-e2e/src/suite/tools/list-files.test.ts @@ -6,8 +6,11 @@ import * as vscode from "vscode" import type { ClineMessage } from "@roo-code/types" import { waitFor, sleep } from "../utils" +import { setDefaultSuiteTimeout } from "../test-utils" + +suite("Roo Code list_files Tool", function () { + setDefaultSuiteTimeout(this) -suite("Roo Code list_files Tool", () => { let workspaceDir: string let testFiles: { rootFile1: string @@ -387,6 +390,124 @@ This directory contains various files and subdirectories for testing the list_fi } }) + test("Should list symlinked files and directories", async function () { + const api = globalThis.api + const messages: ClineMessage[] = [] + let taskCompleted = false + let toolExecuted = false + let listResults: string | null = null + + // Listen for messages + const messageHandler = ({ message }: { message: ClineMessage }) => { + messages.push(message) + + // Check for tool execution and capture results + if (message.type === "say" && message.say === "api_req_started") { + const text = message.text || "" + if (text.includes("list_files")) { + toolExecuted = true + console.log("list_files tool executed (symlinks):", text.substring(0, 200)) + + // Extract list results from the tool execution + try { + const jsonMatch = text.match(/\{"request":".*?"\}/) + if (jsonMatch) { + const requestData = JSON.parse(jsonMatch[0]) + if (requestData.request && requestData.request.includes("Result:")) { + listResults = requestData.request + console.log("Captured symlink test results:", listResults?.substring(0, 300)) + } + } + } catch (e) { + console.log("Failed to parse symlink test results:", e) + } + } + } + } + api.on("message", messageHandler) + + // Listen for task completion + const taskCompletedHandler = (id: string) => { + if (id === taskId) { + taskCompleted = true + } + } + api.on("taskCompleted", taskCompletedHandler) + + let taskId: string + try { + // Create a symlink test directory + const testDirName = `symlink-test-${Date.now()}` + const testDir = path.join(workspaceDir, testDirName) + await fs.mkdir(testDir, { recursive: true }) + + // Create a source directory with content + const sourceDir = path.join(testDir, "source") + await fs.mkdir(sourceDir, { recursive: true }) + const sourceFile = path.join(sourceDir, "source-file.txt") + await fs.writeFile(sourceFile, "Content from symlinked file") + + // Create symlinks to file and directory + const symlinkFile = path.join(testDir, "link-to-file.txt") + const symlinkDir = path.join(testDir, "link-to-dir") + + try { + await fs.symlink(sourceFile, symlinkFile) + await fs.symlink(sourceDir, symlinkDir) + console.log("Created symlinks successfully") + } catch (symlinkError) { + console.log("Symlink creation failed (might be platform limitation):", symlinkError) + // Skip test if symlinks can't be created + console.log("Skipping symlink test - platform doesn't support symlinks") + return + } + + // Start task to list files in symlink test directory + taskId = await api.startNewTask({ + configuration: { + mode: "code", + autoApprovalEnabled: true, + alwaysAllowReadOnly: true, + alwaysAllowReadOnlyOutsideWorkspace: true, + }, + text: `I have created a test directory with symlinks at "${testDirName}". Use the list_files tool to list the contents of this directory. It should show both the original files/directories and the symlinked ones. The directory contains symlinks to both a file and a directory.`, + }) + + console.log("Symlink test Task ID:", taskId) + + // Wait for task completion + await waitFor(() => taskCompleted, { timeout: 60_000 }) + + // Verify the list_files tool was executed + assert.ok(toolExecuted, "The list_files tool should have been executed") + + // Verify the tool returned results + assert.ok(listResults, "Tool execution results should be captured") + + const results = listResults as string + console.log("Symlink test results:", results) + + // Check that symlinked items are visible + assert.ok( + results.includes("link-to-file.txt") || results.includes("source-file.txt"), + "Should see either the symlink or the target file", + ) + assert.ok( + results.includes("link-to-dir") || results.includes("source/"), + "Should see either the symlink or the target directory", + ) + + console.log("Test passed! Symlinked files and directories are now visible") + + // Cleanup + await fs.rm(testDir, { recursive: true, force: true }) + } finally { + // Clean up + api.off("message", messageHandler) + api.off("taskCompleted", taskCompletedHandler) + } + }) + test("Should list files in workspace root directory", async function () { const api = globalThis.api const messages: ClineMessage[] = [] diff --git a/apps/vscode-e2e/src/suite/tools/read-file.test.ts b/apps/vscode-e2e/src/suite/tools/read-file.test.ts index 026fbd588d..007e88b21c 100644 --- a/apps/vscode-e2e/src/suite/tools/read-file.test.ts +++ b/apps/vscode-e2e/src/suite/tools/read-file.test.ts @@ -7,8 +7,11 @@ import * as vscode from "vscode" import type { ClineMessage } from "@roo-code/types" import { waitFor, sleep } from "../utils" +import { setDefaultSuiteTimeout } from "../test-utils" + +suite("Roo Code read_file Tool", function () { + setDefaultSuiteTimeout(this) -suite("Roo Code read_file Tool", () => { let tempDir: string let testFiles: { simple: string @@ -118,7 +121,6 @@ suite("Roo Code read_file Tool", () => { }) test("Should read a simple text file", async function () { - this.timeout(90_000) // Increase timeout for this test const api = globalThis.api const messages: ClineMessage[] = [] let taskStarted = false @@ -264,7 +266,6 @@ suite("Roo Code read_file Tool", () => { }) test("Should read a multiline file", async function () { - this.timeout(90_000) // Increase timeout const api = globalThis.api const messages: ClineMessage[] = [] let taskCompleted = false @@ -376,7 +377,6 @@ suite("Roo Code read_file Tool", () => { }) test("Should read file with line range", async function () { - this.timeout(90_000) // Increase timeout const api = globalThis.api const messages: ClineMessage[] = [] let taskCompleted = false @@ -562,7 +562,6 @@ suite("Roo Code read_file Tool", () => { }) test("Should read XML content file", async function () { - this.timeout(90_000) // Increase timeout const api = globalThis.api const messages: ClineMessage[] = [] let taskCompleted = false @@ -634,7 +633,6 @@ suite("Roo Code read_file Tool", () => { }) test("Should read multiple files in sequence", async function () { - this.timeout(90_000) // Increase timeout const api = globalThis.api const messages: ClineMessage[] = [] let taskCompleted = false @@ -708,7 +706,6 @@ Assume both files exist and you can read them directly. Read each file and tell }) test("Should read large file efficiently", async function () { - this.timeout(90_000) // Increase timeout const api = globalThis.api const messages: ClineMessage[] = [] let taskCompleted = false diff --git a/apps/vscode-e2e/src/suite/tools/search-and-replace.test.ts b/apps/vscode-e2e/src/suite/tools/search-and-replace.test.ts index 7f404dd402..459b109350 100644 --- a/apps/vscode-e2e/src/suite/tools/search-and-replace.test.ts +++ b/apps/vscode-e2e/src/suite/tools/search-and-replace.test.ts @@ -6,8 +6,11 @@ import * as vscode from "vscode" import type { ClineMessage } from "@roo-code/types" import { waitFor, sleep } from "../utils" +import { setDefaultSuiteTimeout } from "../test-utils" + +suite("Roo Code search_and_replace Tool", function () { + setDefaultSuiteTimeout(this) -suite("Roo Code search_and_replace Tool", () => { let workspaceDir: string // Pre-created test files that will be used across tests @@ -253,9 +256,6 @@ Assume the file exists and you can modify it directly.`, }) test("Should perform regex pattern replacement", async function () { - // Increase timeout for this test - this.timeout(90_000) - const api = globalThis.api const messages: ClineMessage[] = [] const testFile = testFiles.regexReplace diff --git a/apps/vscode-e2e/src/suite/tools/search-files.test.ts b/apps/vscode-e2e/src/suite/tools/search-files.test.ts index b0faeeed79..cc28739943 100644 --- a/apps/vscode-e2e/src/suite/tools/search-files.test.ts +++ b/apps/vscode-e2e/src/suite/tools/search-files.test.ts @@ -6,8 +6,11 @@ import * as vscode from "vscode" import type { ClineMessage } from "@roo-code/types" import { waitFor, sleep } from "../utils" +import { setDefaultSuiteTimeout } from "../test-utils" + +suite("Roo Code search_files Tool", function () { + setDefaultSuiteTimeout(this) -suite("Roo Code search_files Tool", () => { let workspaceDir: string let testFiles: { jsFile: string diff --git a/apps/vscode-e2e/src/suite/tools/use-mcp-tool.test.ts b/apps/vscode-e2e/src/suite/tools/use-mcp-tool.test.ts index 0971ec44e1..df57ae88c6 100644 --- a/apps/vscode-e2e/src/suite/tools/use-mcp-tool.test.ts +++ b/apps/vscode-e2e/src/suite/tools/use-mcp-tool.test.ts @@ -7,8 +7,11 @@ import * as vscode from "vscode" import type { ClineMessage } from "@roo-code/types" import { waitFor, sleep } from "../utils" +import { setDefaultSuiteTimeout } from "../test-utils" + +suite("Roo Code use_mcp_tool Tool", function () { + setDefaultSuiteTimeout(this) -suite("Roo Code use_mcp_tool Tool", () => { let tempDir: string let testFiles: { simple: string diff --git a/apps/vscode-e2e/src/suite/tools/write-to-file.test.ts b/apps/vscode-e2e/src/suite/tools/write-to-file.test.ts index c07282bb87..814213b2bc 100644 --- a/apps/vscode-e2e/src/suite/tools/write-to-file.test.ts +++ b/apps/vscode-e2e/src/suite/tools/write-to-file.test.ts @@ -6,8 +6,11 @@ import * as os from "os" import type { ClineMessage } from "@roo-code/types" import { waitFor, sleep } from "../utils" +import { setDefaultSuiteTimeout } from "../test-utils" + +suite("Roo Code write_to_file Tool", function () { + setDefaultSuiteTimeout(this) -suite("Roo Code write_to_file Tool", () => { let tempDir: string let testFilePath: string diff --git a/apps/web-evals/package.json b/apps/web-evals/package.json index 69d0571c43..b210fa085e 100644 --- a/apps/web-evals/package.json +++ b/apps/web-evals/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "lint": "next lint", + "lint": "next lint --max-warnings 0", "check-types": "tsc -b", "dev": "scripts/check-services.sh && next dev", "format": "prettier --write src", @@ -32,7 +32,7 @@ "clsx": "^2.1.1", "cmdk": "^1.1.0", "fuzzysort": "^3.1.0", - "lucide-react": "^0.513.0", + "lucide-react": "^0.518.0", "next": "^15.2.5", "next-themes": "^0.4.6", "p-map": "^7.0.3", diff --git a/apps/web-roo-code/package.json b/apps/web-roo-code/package.json index f621afade0..02812dc471 100644 --- a/apps/web-roo-code/package.json +++ b/apps/web-roo-code/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "lint": "next lint", + "lint": "next lint --max-warnings 0", "check-types": "tsc --noEmit", "dev": "next dev", "build": "next build", @@ -21,7 +21,7 @@ "embla-carousel-autoplay": "^8.6.0", "embla-carousel-react": "^8.6.0", "framer-motion": "^12.15.0", - "lucide-react": "^0.513.0", + "lucide-react": "^0.518.0", "next": "^15.2.5", "next-themes": "^0.4.6", "posthog-js": "^1.248.1", diff --git a/apps/web-roo-code/src/app/enterprise/page.tsx b/apps/web-roo-code/src/app/enterprise/page.tsx index d5eab2af4d..c89d2abd11 100644 --- a/apps/web-roo-code/src/app/enterprise/page.tsx +++ b/apps/web-roo-code/src/app/enterprise/page.tsx @@ -16,17 +16,18 @@ export default async function Enterprise() {

- Roo Code for + Roo Code Cloud for Enterprise

- A next-generation, AI-powered{" "} + The{" "} - coding partner + control-plane {" "} - for enterprise development teams. + for AI-powered software development. Gain visibility, governance, and control over + your AI coding initiatives.

@@ -63,28 +64,28 @@ export default async function Enterprise() {
-

Roo Code Enterprise

+

Roo Code Cloud Control-Plane

- An AI extension of your team that handles coding tasks, from new code generation to - refactoring, bug fixing, and documentation. + A unified control system for managing Roo Code across your organization, with the + flexibility to extend governance to your broader AI toolkit.

- Accelerate development cycles + Centralized Roo Code management
- Enterprise-grade security + Real-time usage visibility
- Custom-tailored to your workflow + Enterprise policy enforcement
- Improve collaboration and onboarding + Extensible to other AI tools
@@ -97,10 +98,12 @@ export default async function Enterprise() {
-

Empower Your Development Team

+

+ Take Control of Your AI Development +

- Roo Code functions like an entire AI dev team embedded in your developers' IDE, ready - to accelerate software delivery and improve code quality. + Roo Code Cloud provides enterprise-grade control and visibility for Roo Code deployments, + with an extensible architecture for your evolving AI strategy.

@@ -110,23 +113,23 @@ export default async function Enterprise() {
-

Accelerate Development Cycles

+

Centralized AI Management Hub

- Supercharge development with AI assistance that helps developers code faster while - maintaining quality. + Manage Roo Code deployments enterprise-wide, with an extensible platform ready for your + broader AI ecosystem.

  • - Faster time-to-market + Centralized token management
  • - AI pair-programming + Multi-model support for Roo
  • - Improved code quality + Extensible architecture
@@ -136,22 +139,22 @@ export default async function Enterprise() {
-

Augment Your Team with AI Agents

+

Real-Time Usage Visibility

- Roo Code functions like an AI extension of your team, handling various coding tasks. + Track Roo Code usage across teams with detailed analytics and cost attribution.

  • - New code generation + Token consumption tracking
  • - Refactoring and bug fixing + Cost attribution by team
  • - Automate complex migrations + AI adoption insights
@@ -161,22 +164,23 @@ export default async function Enterprise() {
-

Enterprise-Grade Security

+

Enterprise-Grade Governance

- Keep your data private with on-premises models, keeping proprietary code in-house. + Implement security policies for Roo Code that align with your enterprise AI governance + framework.

  • - Security and compliance + Model allow-lists
  • - No external cloud dependencies + Data residency controls
  • - Open-source and extensible + Audit trail compliance
@@ -186,23 +190,23 @@ export default async function Enterprise() {
-

Custom-Tailored to Your Workflow

+

5-Minute Control-Plane Setup

- Developers can create Custom Modes for specialized tasks like security auditing or - performance tuning. + Deploy your Roo Code control-plane instantly with our SaaS solution. No infrastructure + required.

  • - Integrate with internal tools + Instant deployment
  • - Adapt to existing workflows + SAML/SCIM integration
  • - Custom AI behaviors + REST API access
@@ -212,23 +216,22 @@ export default async function Enterprise() {
-

Collaboration and Onboarding

+

Manage AI Development Costs

- Ask Mode enables developers to query their codebase in plain language and receive - instant answers. + Track and control Roo Code costs with detailed analytics and budget controls.

  • - Accelerates onboarding + Unified cost visibility
  • - Improves cross-team collaboration + Department chargebacks
  • - Makes code more accessible + Usage optimization
@@ -238,22 +241,22 @@ export default async function Enterprise() {
-

Faster Delivery, Lower Costs

+

Zero Friction for Developers

- Automate routine tasks to accelerate software releases and reduce costs. + Developers get seamless Roo Code access while you maintain governance and visibility.

  • - Improved code quality & consistency + Automatic token refresh
  • - Empowered developers, happier teams + Local sidecar architecture
  • - Rapid knowledge sharing + No workflow disruption
@@ -265,16 +268,15 @@ export default async function Enterprise() {
-

What Makes Roo Code Unique

+

Why You Need a Control-Plane

- Unlike traditional code editors or basic autocomplete tools, Roo Code is an autonomous - coding agent with powerful capabilities. + See how Roo Code Cloud brings enterprise control to AI-powered development.

-

Traditional AI Coding Assistants

+

Current State: AI Tool Sprawl

  • - Limited to autocomplete and simple suggestions + Roo Code tokens managed individually by developers
  • - Lack project-wide context understanding + No visibility into AI tool usage or costs
  • - Can't execute commands or perform web actions + Inconsistent security practices
  • - No customization for enterprise workflows + Shadow AI spend on corporate cards
  • - Often require sending code to external cloud services + No centralized governance framework
-

Roo Code Enterprise

+

Roo Code Cloud Control-Plane

  • - Full-featured AI dev team with natural language communication + Centralized Roo Code management dashboard
  • - Deep understanding of your entire codebase + Complete visibility into usage and costs
  • - Can run tests, execute commands, and perform web actions + Consistent policy enforcement
  • - Custom modes for specialized enterprise tasks + Controlled, trackable AI investments
  • - On-premises deployment option for data privacy + Enterprise-ready governance platform
@@ -391,8 +393,8 @@ export default async function Enterprise() { Ready to Transform Your Development Process?

- Join our early access program and be among the first to experience the power of Roo Code for - Enterprise. + Join our early access program and be among the first to experience the power of Roo Code + Cloud for Enterprise.

@@ -410,15 +412,6 @@ export default async function Enterprise() {
-
diff --git a/apps/web-roo-code/src/app/privacy/page.tsx b/apps/web-roo-code/src/app/privacy/page.tsx index ab9962cdfa..ea12094ebb 100644 --- a/apps/web-roo-code/src/app/privacy/page.tsx +++ b/apps/web-roo-code/src/app/privacy/page.tsx @@ -1,175 +1,266 @@ import { Metadata } from "next" export const metadata: Metadata = { - title: "Privacy Policy - Roo Code Marketing Website", + title: "Privacy Policy - Roo Code", description: - "Privacy policy for the Roo Code marketing website. Learn how we handle your data and protect your privacy.", + "Privacy policy for Roo Code Cloud and marketing website. Learn how we handle your data and protect your privacy.", } export default function Privacy() { return ( <>
-
+

- Roo Code Marketing Landing Page Privacy Policy + Roo Code Cloud Privacy Policy

-

Last Updated: March 7th, 2025

+

Last Updated: June 19, 2025

- Roo Code respects your privacy and is committed to being transparent about how data is collected - and used on our marketing landing page. This policy focuses on data handling for the Roo Code - marketing website. For details on how your data is handled within the Roo Code extension itself, - please refer to our separate{" "} - - Roo Code Extension Privacy Policy - - . + This Privacy Policy explains how Roo Code, Inc. ("Roo Code," "we," + "our," or "us") collects, uses, and shares information when you:

- -

Where Your Data Goes (And Where It Doesn't)

- -

Website Analytics & Tracking

-
    +
    • - We use PostHog (and its standard features) on our marketing landing page to analyze site - traffic and usage trends. This collection includes information such as your IP address, - browser type, device information, and pages visited. + browse any page under roocode.com (the Marketing Site); and/or
    • - These analytics help us understand how users engage with the website, so we can improve - content and design. -
    • -
    • We do not collect code, project data, or any AI-related prompts on this page.
    • -
    - -

    Cookies and Similar Technologies

    -
      -
    • - Our marketing website may use cookies or similar tracking technologies to remember user - preferences and provide aggregated analytics. -
    • -
    • - Cookies help with things like user session management, remembering certain selections or - preferences, and compiling anonymous statistics. + create an account for, sign in to, or otherwise use Roo Code Cloud at{" "} + app.roocode.com or through the Roo Code extension while authenticated to + that Cloud account (the Cloud Service).
    -

    Forms & Voluntary Submissions

    -
      -
    • - If you submit your email or other personal data on our landing page (for example, to receive - updates or join a waiting list), we collect that information voluntarily provided by you. -
    • -
    • - We do not share or sell this data to third parties for their own marketing purposes. It is - used only to communicate with you about Roo Code, respond to inquiries, or send updates - you've requested. -
    • -
    - -

    Third-Party Integrations

    -
      -
    • - Our website may embed content or links to external platforms (e.g., for processing payments - or handling support). Any data you provide through these external sites is governed by the - privacy policies of those platforms. -
    • -
    - -

    How We Use Your Data

    - -

    Site Improvements & Marketing

    -
      -
    • - We analyze aggregated user behavior to measure the effectiveness of our site, troubleshoot - any issues, and guide future improvements. -
    • -
    • - If you sign up for newsletters or updates, we use your email or other contact information - only to send you relevant Roo Code communications. -
    • -
    - -

    No Selling or Sharing of Data

    -
      -
    • - We do not sell or share your personally identifiable information with third parties for - their marketing. -
    • -
    • We do not train any models on your marketing site data.
    • -
    - -

    Your Choices & Control

    - -

    Manage Cookies

    -
      -
    • - Most browsers allow you to manage or block cookies. If you disable cookies, some features of - the site may not function properly. -
    • -
    - -

    Opt-Out of Communications

    -
      -
    • - If you have signed up to receive updates, you can unsubscribe anytime by following the - instructions in our emails or contacting us directly. -
    • -
    - -

    Request Deletion

    -
      -
    • - You may request the deletion of any personal data you've provided through our marketing - forms by reaching out to us at{" "} - - support@roocode.com - - . -
    • -
    - -

    Security & Updates

    -
      -
    • - We take reasonable measures to protect your data from unauthorized access or disclosure, but - no website can be 100% secure. -
    • -
    • - If our privacy practices for the marketing site change, we will update this policy and note - the effective date at the top. -
    • -
    - -

    Contact Us

    -

    - If you have questions or concerns about this Privacy Policy or wish to make a request regarding - your data, please reach out to us at{" "} - - support@roocode.com - - . -

    - -
    -

    - By using the Roo Code marketing landing page, you agree to this Privacy Policy. If you use - the Roo Code extension, please see our separate{" "} +

    +

    Extension‑Only Usage

    +

    + If you run the Roo Code extension without connecting to a Cloud account, + your data is governed by the standalone{" "} Roo Code Extension Privacy Policy - {" "} - for details on data handling in the extension. + + .

    + +

    Quick Summary

    +
      +
    • + Your source code never transits Roo Code servers. It stays on your device + and is sent directly—via a client‑to‑provider TLS connection—to the + third‑party AI model you select. Roo Code never stores, inspects, or trains on your code. +
    • +
    • + Prompts and chat snippets are collected by default in Roo Code Cloud so you + can search and re‑use past conversations. Organization admins can disable this collection at + any time. +
    • +
    • + We collect only the data needed to operate Roo Code Cloud, do not sell + customer data, and do not use your content to train models. +
    • +
    + +

    1. Information We Collect

    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    CategoryExamplesSource
    Account Information + Name, email, organization, auth tokens + You
    + Workspace Configuration + + Org settings, allow‑lists, rules files, modes, dashboards + You / Extension (when signed in)
    + Prompts, Chat Snippets & Token Counts + + Text prompts, model outputs, token counts + Extension (when signed in)
    Usage Data + Feature clicks, error logs, performance metrics (captured via PostHog) + Services automatically (PostHog)
    Payment Data + Tokenized card details, billing address, invoices + Payment processor (Stripe)
    Marketing Data + Cookies, IP address, browser type, page views,{" "} + voluntary form submissions (e.g., newsletter or wait‑list + sign‑ups) + + Marketing Site automatically / You +
    +
    + +

    2. How We Use Information

    +
      +
    • + Operate & secure Roo Code Cloud (authentication, completions, abuse + prevention) +
    • +
    • + Provide support & improve features (debugging, analytics, product + decisions) +
    • +
    • + Process payments & manage subscriptions +
    • +
    • + Send product updates and roadmap communications (opt‑out available) +
    • +
    + +

    3. Where Your Data Goes (And Doesn't)

    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    DataSent To + Not Sent To +
    + Code & files you work on + + Your chosen model provider (direct client → provider TLS) + + Roo Code servers; ad networks; model‑training pipelines +
    + Prompts, chat snippets & token counts (Cloud) + + Roo Code Cloud (encrypted at rest) + Any third‑party
    + Workspace Configuration + + Roo Code Cloud (encrypted at rest) + Any third-party
    Usage & Telemetry + PostHog (self‑hosted analytics platform) + Ad networks or data brokers
    Payment DataStripe (PCI‑DSS Level 1) + Roo Code servers (we store only the Stripe customer ID) +
    +
    + +

    4. Data Retention

    +
      +
    • + Source Code: Never stored on Roo Code servers. +
    • +
    • + Prompts & Chat Snippets: Persist in your Cloud workspace until you or your + organization admin deletes them or disables collection. +
    • +
    • + Operational Logs & Analytics: Retained only as needed to operate and secure + Roo Code Cloud. +
    • +
    + +

    5. Your Choices

    +
      +
    • + Manage cookies: You can block or delete cookies in your browser settings; + some site features may not function without them. +
    • +
    • + Disable prompt collection in Organization settings. +
    • +
    • + Delete your Cloud account at any time from{" "} + Security Settings inside Roo Code Cloud. +
    • +
    + +

    6. Security Practices

    +

    + We use TLS for all data in transit, AES‑256 encryption at rest, least‑privilege IAM, continuous + monitoring, routine penetration testing, and maintain a SOC 2 program. +

    + +

    7. Updates to This Policy

    +

    + If our privacy practices change, we will update this policy and note the new{" "} + Last Updated date at the top. For material changes that affect Cloud + workspaces, we will also email registered workspace owners before the changes take effect. +

    + +

    8. Contact Us

    +

    + Questions or concerns? Email{" "} + + privacy@roocode.com + + . +

diff --git a/apps/web-roo-code/src/app/terms/page.tsx b/apps/web-roo-code/src/app/terms/page.tsx new file mode 100644 index 0000000000..545e577457 --- /dev/null +++ b/apps/web-roo-code/src/app/terms/page.tsx @@ -0,0 +1,320 @@ +import { Metadata } from "next" + +export const metadata: Metadata = { + title: "Terms of Service - Roo Code", + description: + "Terms of Service for Roo Code Cloud. Learn about our service terms, commercial conditions, and legal framework.", +} + +export default function Terms() { + return ( + <> +
+
+

+ Roo Code Cloud Terms of Service +

+

+ (Version 1.0 – Effective June 19, 2025) +

+ +

+ These Terms of Service ("TOS") govern access to and use of the Roo + Code Cloud service (the "Service"). They apply to: +

+
    +
  • + (a) every Sales Order Form or similar document mutually + executed by Roo Code and the customer that references these TOS; and +
  • +
  • + (b) any{" "} + online plan-selection, self-service sign-up, or in-app purchase flow{" "} + through which a customer clicks an "I Agree" (or equivalent) button to accept + these TOS — such flow also being an "Order Form." +
  • +
+ +

+ By creating an account, clicking to accept, or using the Service, the person or + entity doing so ("Customer") agrees to be bound by these TOS, even if + no separate Order Form is signed. +

+ +

+ If Roo Code and Customer later execute a Master Subscription Agreement (" + MSA"), the MSA governs; otherwise, these TOS and the applicable Order Form + together form the entire agreement (the "Agreement"). +

+ +

1. Agreement Framework

+
    +
  1. + Incorporation of Standard Terms. +
    + The{" "} + + Common Paper Cloud Service Standard Terms v 2.0 + {" "} + (the "Standard Terms") are incorporated by reference. If these + TOS conflict with the Standard Terms, these TOS control. +
  2. +
  3. + Order of Precedence. +
    + (a) Order Form (b) these TOS (c) Standard Terms. +
  4. +
+ +

2. Key Commercial Terms

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TermValue
+ Governing Law / Forum + + Delaware law; exclusive jurisdiction and venue in the state or federal courts + located in Delaware +
+ Plans & Subscription Periods + + Free Plan: month-to-month. +
+ Paid Plans: Monthly or Annual, as selected in an Order + Form or the online flow. +
+ Auto-Renewal & Non-Renewal Notice + + Free Plan: renews continuously until cancelled in the dashboard. +
+ Paid Plans: renew for the same period unless either party gives 30 + days' written notice before the current period ends. +
Fees & Usage + Free Plan: Subscription Fee = $0. +
+ Paid Plans: Fees stated in the Order Form or online checkout{" "} + plus usage-based fees, calculated and invoiced monthly. +
Payment Terms + Monthly paid plans: credit-card charge on the billing date. +
+ Annual paid plans: invoiced Net 30 (credit card optional). +
+ General Liability Cap + + The greater of (i) USD 100 and (ii) 1 × Fees paid or payable in the 12 months + before the event giving rise to liability. +
+ Increased Cap / Unlimited Claims + None
Trial / PilotNot offered
Beta Features + None – only generally available features are provided +
Security Standard + Roo Code maintains commercially reasonable administrative, physical, and + technical safeguards +
Machine-Learning Use + Roo Code does not use Customer Content to train, fine-tune, or + improve any ML or AI models +
+ Data Processing Addendum (DPA) + + GDPR/CCPA-ready DPA available upon written request +
+ Publicity / Logo Rights + + Roo Code may identify Customer (name & logo) in marketing materials unless + Customer opts out in writing +
+
+ +

3. Modifications to the Standard Terms

+
    +
  1. + Section 1.6 (Machine Learning). +
    + "Provider will not use Customer Content or Usage Data to train, fine-tune, or improve + any machine-learning or AI model, except with Customer's prior written consent." +
  2. +
  3. + Section 3 (Security). +
    + Replace "reasonable" with "commercially reasonable." +
  4. +
  5. + Section 4 (Fees & Payment). +
    + Add usage-billing language above and delete any provision allowing unilateral fee increases. +
  6. +
  7. + Section 5 (Term & Termination). +
    + Insert auto-renewal and free-plan language above. +
  8. +
  9. + Sections 7 (Trials / Betas) and any SLA references. +
    + Deleted – Roo Code offers no trials, pilots, betas, or SLA credits under these TOS. +
  10. +
  11. + Section 12.12 (Publicity). +
    + As reflected in the "Publicity / Logo Rights" row above. +
  12. +
+ +

4. Use of the Service

+

+ Customer may access and use the Service solely for its internal business purposes and subject to + the Acceptable Use Policy in the Standard Terms. +

+ +

5. Account Management & Termination

+
    +
  • + Self-service cancellation or downgrade. +
    + Customer may cancel a Free Plan immediately, or cancel/downgrade a Paid Plan effective at + the end of the current billing cycle, via the web dashboard. +
  • +
  • + Either party may otherwise terminate the Agreement as allowed under Section 5 of the + Standard Terms. +
  • +
+ +

6. Privacy & Data

+

+ Roo Code's Privacy Notice ( + + https://roocode.com/privacy + + ) explains how Roo Code collects and handles personal information. If Customer requires a DPA, + email{" "} + + support@roocode.com + + . +

+ +

7. Warranty Disclaimer

+

+ Except as expressly stated in the Agreement, the Service is provided{" "} + "as is," and all implied warranties are disclaimed to the maximum + extent allowed by law. +

+ +

8. Limitation of Liability

+

+ The caps in Section 2 apply to all claims under the Agreement, whether in contract, tort, or + otherwise, except for Excluded Claims defined in the Standard Terms. +

+ +

9. Miscellaneous

+
    +
  1. + Assignment. +
    + Customer may not assign the Agreement without Roo Code's prior written consent, except + to a successor in a merger or sale of substantially all assets. +
  2. +
  3. + Export Compliance. +
    + Each party will comply with all applicable export-control laws and regulations and will not + export or re-export any software or technical data without the required government licences. +
  4. +
  5. + Entire Agreement. +
    + The Agreement supersedes all prior or contemporaneous agreements for the Service. +
  6. +
  7. + Amendments. +
    + Roo Code may update these TOS by posting a revised version at the same URL and emailing or + in-app notifying Customer at least 30 days before changes take effect. Continued use after + the effective date constitutes acceptance. +
  8. +
+ +

10. Contact

+

+ Roo Code, Inc. +
+ 98 Graceland Dr, San Rafael, CA 94901 USA +
+ Email:{" "} + + support@roocode.com + +

+
+
+ + ) +} diff --git a/apps/web-roo-code/src/components/chromes/footer.tsx b/apps/web-roo-code/src/components/chromes/footer.tsx index 850f5f3d3e..0d322f31e1 100644 --- a/apps/web-roo-code/src/components/chromes/footer.tsx +++ b/apps/web-roo-code/src/components/chromes/footer.tsx @@ -246,6 +246,13 @@ export function Footer() { Careers +
  • + + Terms of Service + +
  • diff --git a/locales/ca/README.md b/locales/ca/README.md index 32b916dcb8..c653f54fbb 100644 --- a/locales/ca/README.md +++ b/locales/ca/README.md @@ -50,13 +50,13 @@ Consulteu el [CHANGELOG](../../CHANGELOG.md) per a actualitzacions i correccions --- -## 🎉 Roo Code 3.20 Llançat +## 🎉 Roo Code 3.21 Llançat -Roo Code 3.20 aporta noves funcionalitats majors i millores basades en els vostres comentaris! +Roo Code 3.21 aporta noves funcionalitats majors i millores basades en els vostres comentaris! -- **Marketplace Experimental** - Descobriu i instal·leu modes i MCPs des del nou marketplace (activeu-lo als Paràmetres Experimentals). -- **Operacions de Fitxers Millorades** - Múltiples escriptures de fitxers simultànies ara disponibles als Paràmetres Experimentals, i múltiples lectures simultànies s'han graduat de l'experimental i ara viuen als Paràmetres de Context. -- **Millores MCP i Més** - Suport MCP millorat, més controls Mermaid, suport de pensament a Amazon Bedrock, i molt més! +- **Llançament del Marketplace Roo** - El marketplace ja està en funcionament! El marketplace ja està en funcionament! Descobreix i instal·la modes i MCP més fàcilment que mai. +- **Models Gemini 2.5** - S'ha afegit suport per als nous models Gemini 2.5 Pro, Flash i Flash Lite. +- **Suport per a fitxers Excel i més** - S'ha afegit suport per a fitxers Excel (.xlsx) i nombroses correccions d'errors i millores! --- @@ -184,35 +184,37 @@ Gràcies a tots els nostres col·laboradors que han ajudat a millorar Roo Code! |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## Llicència diff --git a/locales/de/README.md b/locales/de/README.md index 2cf784c83a..24f1e4d69e 100644 --- a/locales/de/README.md +++ b/locales/de/README.md @@ -50,13 +50,13 @@ Sehen Sie sich das [CHANGELOG](../../CHANGELOG.md) für detaillierte Updates und --- -## 🎉 Roo Code 3.20 veröffentlicht +## 🎉 Roo Code 3.21 veröffentlicht -Roo Code 3.20 bringt wichtige neue Funktionen und Verbesserungen basierend auf eurem Feedback! +Roo Code 3.21 bringt wichtige neue Funktionen und Verbesserungen basierend auf eurem Feedback! -- **Experimenteller Marketplace** - Entdecke und installiere Modi und MCPs aus dem neuen Marketplace (aktiviere ihn in den Experimentellen Einstellungen). -- **Verbesserte Dateioperationen** - Mehrere gleichzeitige Dateischreibvorgänge sind jetzt in den Experimentellen Einstellungen verfügbar, und mehrere gleichzeitige Leseoperationen sind aus dem experimentellen Stadium graduiert und befinden sich nun in den Kontext-Einstellungen. -- **MCP-Verbesserungen & Mehr** - Erweiterte MCP-Unterstützung, mehr Mermaid-Steuerelemente, Thinking-Unterstützung in Amazon Bedrock und vieles mehr! +- **Roo Marketplace Launch** - Der Marketplace ist jetzt live! Der Marketplace ist jetzt live! Entdecke und installiere Modi und MCPs einfacher als je zuvor. +- **Gemini 2.5 Modelle** - Unterstützung für neue Gemini 2.5 Pro, Flash und Flash Lite Modelle hinzugefügt. +- **Excel-Datei-Unterstützung & Mehr** - Excel (.xlsx) Datei-Unterstützung hinzugefügt und zahlreiche Fehlerbehebungen und Verbesserungen! --- @@ -184,35 +184,37 @@ Danke an alle unsere Mitwirkenden, die geholfen haben, Roo Code zu verbessern! |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## Lizenz diff --git a/locales/es/README.md b/locales/es/README.md index 05083f12a3..adeca0a876 100644 --- a/locales/es/README.md +++ b/locales/es/README.md @@ -50,13 +50,13 @@ Consulta el [CHANGELOG](../../CHANGELOG.md) para ver actualizaciones detalladas --- -## 🎉 Roo Code 3.20 Lanzado +## 🎉 Roo Code 3.21 Lanzado -¡Roo Code 3.20 trae importantes nuevas funciones y mejoras basadas en vuestros comentarios! +¡Roo Code 3.21 trae importantes nuevas funciones y mejoras basadas en vuestros comentarios! -- **Marketplace Experimental** - Descubre e instala modos y MCPs desde el nuevo marketplace (habilítalo en Configuraciones Experimentales). -- **Operaciones de Archivo Mejoradas** - Múltiples escrituras de archivos concurrentes ahora disponibles en Configuraciones Experimentales, y múltiples lecturas concurrentes se ha graduado de experimental y ahora vive en las Configuraciones de Contexto. -- **Mejoras de MCP y Más** - Soporte mejorado de MCP, más controles de Mermaid, soporte de pensamiento en Amazon Bedrock, ¡y mucho más! +- **Lanzamiento del Marketplace de Roo** - ¡El marketplace ya está en funcionamiento! ¡El marketplace ya está en funcionamiento! Descubre e instala modos y MCPs más fácilmente que nunca. +- **Modelos Gemini 2.5** - Se ha añadido soporte para los nuevos modelos Gemini 2.5 Pro, Flash y Flash Lite. +- **Soporte de Archivos Excel y Más** - ¡Se ha añadido soporte para archivos Excel (.xlsx) y numerosas correcciones de errores y mejoras! --- @@ -184,35 +184,37 @@ Usamos [changesets](https://github.com/changesets/changesets) para versionar y p |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## Licencia diff --git a/locales/fr/README.md b/locales/fr/README.md index 0aa7803fe0..80140b85fb 100644 --- a/locales/fr/README.md +++ b/locales/fr/README.md @@ -50,13 +50,13 @@ Consultez le [CHANGELOG](../../CHANGELOG.md) pour des mises à jour détaillées --- -## 🎉 Roo Code 3.20 est sorti +## 🎉 Roo Code 3.21 est sorti -Roo Code 3.20 apporte de nouvelles fonctionnalités majeures et des améliorations basées sur vos retours ! +Roo Code 3.21 apporte de nouvelles fonctionnalités majeures et des améliorations basées sur vos retours ! -- **Marketplace Expérimental** - Découvrez et installez des modes et des MCPs depuis le nouveau marketplace (activez-le dans les Paramètres Expérimentaux). -- **Opérations de Fichiers Améliorées** - Plusieurs écritures de fichiers simultanées maintenant disponibles dans les Paramètres Expérimentaux, et plusieurs lectures simultanées ont été promues de l'expérimental et vivent maintenant dans les Paramètres de Contexte. -- **Améliorations MCP et Plus** - Support MCP amélioré, plus de contrôles Mermaid, support de réflexion dans Amazon Bedrock, et bien plus ! +- **Le marketplace est maintenant en ligne ! Le marketplace est maintenant en ligne !** Découvrez et installez des modes et des MCPs plus facilement que jamais. +- **Ajout du support pour les nouveaux modèles Gemini 2.5 Pro, Flash et Flash Lite.** +- **Support des Fichiers Excel et Plus !** - Support MCP amélioré, plus de contrôles Mermaid, support de réflexion dans Amazon Bedrock, et bien plus ! --- @@ -184,35 +184,37 @@ Merci à tous nos contributeurs qui ont aidé à améliorer Roo Code ! |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## Licence diff --git a/locales/hi/README.md b/locales/hi/README.md index ea858d9103..9f20242d89 100644 --- a/locales/hi/README.md +++ b/locales/hi/README.md @@ -50,13 +50,13 @@ --- -## 🎉 Roo Code 3.20 जारी +## 🎉 Roo Code 3.21 जारी -Roo Code 3.20 आपकी प्रतिक्रियाओं के आधार पर प्रमुख नई सुविधाएँ और सुधार लाता है! +Roo Code 3.21 आपकी प्रतिक्रियाओं के आधार पर प्रमुख नई सुविधाएँ और सुधार लाता है! -- **प्रयोगात्मक मार्केटप्लेस** - नए मार्केटप्लेस से मोड्स और MCPs खोजें और इंस्टॉल करें (प्रयोगात्मक सेटिंग्स में सक्षम करें)। -- **उन्नत फ़ाइल ऑपरेशन** - प्रयोगात्मक सेटिंग्स में अब मल्टिपल समकालिक फ़ाइल राइट उपलब्ध है, और मल्टिपल समकालिक रीड प्रयोगात्मक से स्नातक हो गया है और अब कॉन्टेक्स्ट सेटिंग्स में रहता है। -- **MCP सुधार और अधिक** - उन्नत MCP समर्थन, अधिक Mermaid नियंत्रण, Amazon Bedrock में विचार समर्थन, और बहुत कुछ! +- **मार्केटप्लेस अब लाइव है! मार्केटप्लेस अब लाइव है!** मोड्स और MCPs को पहले से कहीं आसान तरीके से खोजें और इंस्टॉल करें। +- **नए Gemini 2.5 Pro, Flash और Flash Lite मॉडल्स के लिए समर्थन जोड़ा गया।** +- **Excel (.xlsx) फ़ाइल समर्थन और अधिक!** - उन्नत MCP समर्थन, अधिक Mermaid नियंत्रण, Amazon Bedrock में विचार समर्थन, और बहुत कुछ! --- @@ -184,35 +184,37 @@ Roo Code को बेहतर बनाने में मदद करने |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## लाइसेंस diff --git a/locales/id/README.md b/locales/id/README.md index 5e6cf614e0..3381b865b0 100644 --- a/locales/id/README.md +++ b/locales/id/README.md @@ -49,13 +49,13 @@ Lihat [CHANGELOG](../../CHANGELOG.md) untuk update dan perbaikan detail. --- -## 🎉 Roo Code 3.20 Dirilis +## 🎉 Roo Code 3.21 Dirilis -Roo Code 3.20 menghadirkan fitur baru utama dan perbaikan berdasarkan feedback kamu! +Roo Code 3.21 menghadirkan fitur baru utama dan perbaikan berdasarkan feedback kamu! -- **Marketplace Eksperimental** - Temukan dan install mode serta MCP dari marketplace baru (aktifkan di Experimental Settings). -- **Operasi File yang Ditingkatkan** - Multiple concurrent file writes kini tersedia di Experimental Settings, dan multiple concurrent reads telah lulus dari eksperimental dan sekarang berada di Context Settings. -- **Perbaikan MCP & Lainnya** - Dukungan MCP yang ditingkatkan, kontrol Mermaid lebih banyak, dukungan thinking di Amazon Bedrock, dan masih banyak lagi! +- **Marketplace sekarang live! Marketplace sekarang live!** Temukan dan install mode serta MCP lebih mudah dari sebelumnya. +- **Ditambahkan dukungan untuk model Gemini 2.5 Pro, Flash, dan Flash Lite yang baru.** +- **Dukungan File Excel (.xlsx) & Lainnya!** - Dukungan MCP yang ditingkatkan, kontrol Mermaid lebih banyak, dukungan thinking di Amazon Bedrock, dan masih banyak lagi! --- @@ -178,35 +178,37 @@ Terima kasih kepada semua kontributor kami yang telah membantu membuat Roo Code |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## License diff --git a/locales/it/README.md b/locales/it/README.md index 4e0d019ca8..964db4ff34 100644 --- a/locales/it/README.md +++ b/locales/it/README.md @@ -50,13 +50,13 @@ Consulta il [CHANGELOG](../../CHANGELOG.md) per aggiornamenti dettagliati e corr --- -## 🎉 Roo Code 3.20 Rilasciato +## 🎉 Roo Code 3.21 Rilasciato -Roo Code 3.20 porta nuove funzionalità principali e miglioramenti basati sui vostri feedback! +Roo Code 3.21 porta nuove funzionalità principali e miglioramenti basati sui vostri feedback! -- **Marketplace Sperimentale** - Scopri e installa mode e MCP dal nuovo marketplace (abilita nelle Impostazioni Sperimentali). -- **Operazioni su File Migliorate** - Scritture multiple simultanee di file ora disponibili nelle Impostazioni Sperimentali, e letture multiple simultanee sono uscite dalla fase sperimentale e ora vivono nelle Impostazioni Contesto. -- **Miglioramenti MCP e Altro** - Supporto MCP migliorato, più controlli Mermaid, supporto thinking in Amazon Bedrock, e molto altro! +- **Il marketplace è ora live! Il marketplace è ora live!** Scopri e installa mode e MCP più facilmente che mai. +- **Aggiunto supporto per i nuovi modelli Gemini 2.5 Pro, Flash e Flash Lite.** +- **Supporto File Excel (.xlsx) e Altro!** - Supporto MCP migliorato, più controlli Mermaid, supporto thinking in Amazon Bedrock, e molto altro! --- @@ -184,35 +184,37 @@ Grazie a tutti i nostri contributori che hanno aiutato a migliorare Roo Code! |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## Licenza diff --git a/locales/ja/README.md b/locales/ja/README.md index ba00310f79..90c32409fc 100644 --- a/locales/ja/README.md +++ b/locales/ja/README.md @@ -50,13 +50,13 @@ --- -## 🎉 Roo Code 3.20 リリース +## 🎉 Roo Code 3.21 リリース -Roo Code 3.20は、皆様のフィードバックに基づく新しい主要機能と改善をもたらします! +Roo Code 3.21は、皆様のフィードバックに基づく新しい主要機能と改善をもたらします! -- **実験的マーケットプレイス** - 新しいマーケットプレイスからモードとMCPを発見してインストール(実験的設定で有効化)。 -- **ファイル操作の改善** - ファイルの同時書き込み機能が実験的設定で利用可能になり、同時読み込み機能は実験的段階を卒業してコンテキスト設定に移動しました。 -- **MCP改善など** - MCP サポートの向上、Mermaid制御の追加、Amazon Bedrock thinking サポート、その他多数! +- **マーケットプレイスが稼働開始!マーケットプレイスが稼働開始!** これまで以上に簡単にモードとMCPを発見してインストールできます。 +- **新しいGemini 2.5 Pro、Flash、Flash Liteモデルのサポートを追加。** +- **Excel ファイルサポートなど** - MCP サポートの向上、Mermaid制御の追加、Amazon Bedrock thinking サポート、その他多数! --- @@ -184,35 +184,37 @@ Roo Codeの改善に貢献してくれたすべての貢献者に感謝します |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## ライセンス diff --git a/locales/ko/README.md b/locales/ko/README.md index f439588142..dce892ffb9 100644 --- a/locales/ko/README.md +++ b/locales/ko/README.md @@ -50,13 +50,13 @@ --- -## 🎉 Roo Code 3.20 출시 +## 🎉 Roo Code 3.21 출시 -Roo Code 3.20이 여러분의 피드백을 바탕으로 한 새로운 주요 기능과 개선사항을 제공합니다! +Roo Code 3.21이 여러분의 피드백을 바탕으로 한 새로운 주요 기능과 개선사항을 제공합니다! -- **실험적 마켓플레이스** - 새로운 마켓플레이스에서 모드와 MCP를 발견하고 설치하세요 (실험적 설정에서 활성화). -- **향상된 파일 작업** - 다중 동시 파일 쓰기가 실험적 설정에서 사용 가능하며, 다중 동시 읽기는 실험적 단계를 졸업하여 컨텍스트 설정으로 이동했습니다. -- **MCP 개선 등** - 향상된 MCP 지원, 더 많은 Mermaid 제어, Amazon Bedrock thinking 지원 등! +- **마켓플레이스가 이제 라이브입니다! 마켓플레이스가 이제 라이브입니다!** 그 어느 때보다 쉽게 모드와 MCP를 발견하고 설치하세요. +- **새로운 Gemini 2.5 Pro, Flash, Flash Lite 모델 지원을 추가했습니다.** +- **Excel 파일 지원 등** - 향상된 MCP 지원, 더 많은 Mermaid 제어, Amazon Bedrock thinking 지원 등! --- @@ -184,35 +184,37 @@ Roo Code를 더 좋게 만드는 데 도움을 준 모든 기여자에게 감사 |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## 라이선스 diff --git a/locales/nl/README.md b/locales/nl/README.md index a52efdb1eb..7ca8251e73 100644 --- a/locales/nl/README.md +++ b/locales/nl/README.md @@ -50,13 +50,13 @@ Bekijk de [CHANGELOG](../../CHANGELOG.md) voor gedetailleerde updates en fixes. --- -## 🎉 Roo Code 3.20.0 Uitgebracht +## 🎉 Roo Code 3.21 Uitgebracht -Roo Code 3.20.0 brengt krachtige nieuwe functies en verbeteringen op basis van jullie feedback! +Roo Code 3.21 brengt krachtige nieuwe functies en verbeteringen op basis van jullie feedback! -- **Experimentele marktplaats voor modi en MCP's** - Ontdek en deel aangepaste modi en MCP-integraties met de community via onze nieuwe experimentele marktplaats. -- **Verbeterde bestandsoperaties** - Meerdere gelijktijdige schrijfacties nu beschikbaar in experimentele instellingen, plus meerdere gelijktijdige leesacties gepromoveerd naar contextinstellingen voor betere prestaties. -- **MCP-verbeteringen** - Verbeterde Mermaid-controls voor betere diagramvisualisatie en nieuwe Amazon Bedrock thinking-ondersteuning voor meer geavanceerde AI-interacties. +- **De marketplace is nu live! De marketplace is nu live!** Ontdek en installeer modi en MCP's eenvoudiger dan ooit tevoren. +- **Ondersteuning toegevoegd voor nieuwe Gemini 2.5 Pro, Flash en Flash Lite modellen.** +- **Excel Bestandsondersteuning & Meer** - Verbeterde Mermaid-controls voor betere diagramvisualisatie en nieuwe Amazon Bedrock thinking-ondersteuning voor meer geavanceerde AI-interacties! --- @@ -184,35 +184,37 @@ Dank aan alle bijdragers die Roo Code beter hebben gemaakt! |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## Licentie diff --git a/locales/pl/README.md b/locales/pl/README.md index b074b34675..351d755a29 100644 --- a/locales/pl/README.md +++ b/locales/pl/README.md @@ -50,13 +50,13 @@ Sprawdź [CHANGELOG](../../CHANGELOG.md), aby uzyskać szczegółowe informacje --- -## 🎉 Roo Code 3.20.0 został wydany +## 🎉 Roo Code 3.21 został wydany -Roo Code 3.20.0 wprowadza potężne nowe funkcje i usprawnienia na podstawie opinii użytkowników! +Roo Code 3.21 wprowadza potężne nowe funkcje i usprawnienia na podstawie opinii użytkowników! -- **Eksperymentalne marketplace dla trybów i MCP** - Odkrywaj i dziel się niestandardowymi trybami oraz integracjami MCP ze społecznością poprzez nasze nowe eksperymentalne marketplace. -- **Ulepszone operacje na plikach** - Wiele równoczesnych operacji zapisu dostępnych w ustawieniach eksperymentalnych, plus wiele równoczesnych operacji czytania zaawansowanych do ustawień kontekstu dla lepszej wydajności. -- **Ulepszenia MCP** - Ulepszone kontrolki Mermaid dla lepszej wizualizacji diagramów oraz nowe wsparcie Amazon Bedrock thinking dla bardziej zaawansowanych interakcji z AI. +- **Marketplace jest teraz na żywo! Marketplace jest teraz na żywo!** Odkrywaj i instaluj tryby oraz MCP łatwiej niż kiedykolwiek wcześniej. +- **Dodano wsparcie dla nowych modeli Gemini 2.5 Pro, Flash i Flash Lite.** +- **Wsparcie plików Excel i więcej** - Ulepszone kontrolki Mermaid dla lepszej wizualizacji diagramów oraz nowe wsparcie Amazon Bedrock thinking dla bardziej zaawansowanych interakcji z AI! --- @@ -184,35 +184,37 @@ Dziękujemy wszystkim naszym współtwórcom, którzy pomogli ulepszyć Roo Code |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## Licencja diff --git a/locales/pt-BR/README.md b/locales/pt-BR/README.md index ce887b6aa5..d773d8fcca 100644 --- a/locales/pt-BR/README.md +++ b/locales/pt-BR/README.md @@ -50,13 +50,13 @@ Confira o [CHANGELOG](../../CHANGELOG.md) para atualizações e correções deta --- -## 🎉 Roo Code 3.20.0 foi lançado +## 🎉 Roo Code 3.21 foi lançado -O Roo Code 3.20.0 introduz novos recursos poderosos e melhorias baseadas no feedback dos usuários! +O Roo Code 3.21 introduz novos recursos poderosos e melhorias baseadas no feedback dos usuários! -- **Marketplace experimental para modos e MCP** - Descubra e compartilhe modos personalizados e integrações MCP com a comunidade através do nosso novo marketplace experimental. -- **Operações de arquivo aprimoradas** - Múltiplas operações de escrita simultâneas disponíveis nas configurações experimentais, além de múltiplas operações de leitura simultâneas promovidas para configurações de contexto para melhor performance. -- **Melhorias no MCP** - Controles Mermaid aprimorados para melhor visualização de diagramas e novo suporte Amazon Bedrock thinking para interações de IA mais avançadas. +- **O marketplace está agora disponível! O marketplace está agora disponível!** Descubra e instale modos e MCPs mais facilmente do que nunca. +- **Adicionado suporte para os novos modelos Gemini 2.5 Pro, Flash e Flash Lite.** +- **Suporte a Arquivos Excel e Mais** - Controles Mermaid aprimorados para melhor visualização de diagramas e novo suporte Amazon Bedrock thinking para interações de IA mais avançadas! --- @@ -184,35 +184,37 @@ Obrigado a todos os nossos contribuidores que ajudaram a tornar o Roo Code melho |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## Licença diff --git a/locales/ru/README.md b/locales/ru/README.md index 1c62495472..368a70a986 100644 --- a/locales/ru/README.md +++ b/locales/ru/README.md @@ -50,13 +50,13 @@ --- -## 🎉 Выпущен Roo Code 3.20 +## 🎉 Выпущен Roo Code 3.21 -Roo Code 3.20 представляет экспериментальный маркетплейс и улучшения файловых операций! +Roo Code 3.21 представляет экспериментальный маркетплейс и улучшения файловых операций! -- **Экспериментальный маркетплейс для режимов и MCP** - Откройте для себя и установите пользовательские режимы и MCP серверы из нашего экспериментального маркетплейса в настройках. -- **Улучшенные файловые операции** - Множественная одновременная запись файлов теперь доступна в экспериментальных настройках, а множественное одновременное чтение перешло в настройки контекста. -- **Улучшения MCP** - Новые элементы управления Mermaid и поддержка мышления Amazon Bedrock для расширенных возможностей MCP. +- **Маркетплейс теперь доступен! Маркетплейс теперь доступен!** Открывайте и устанавливайте режимы и MCP проще, чем когда-либо. +- **Добавлена поддержка новых моделей Gemini 2.5 Pro, Flash и Flash Lite.** +- **Поддержка файлов Excel и многое другое!** - Новые элементы управления Mermaid и поддержка мышления Amazon Bedrock для расширенных возможностей MCP. --- @@ -184,35 +184,37 @@ code --install-extension bin/roo-cline-.vsix |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## Лицензия diff --git a/locales/tr/README.md b/locales/tr/README.md index b528fa31d8..6a039e79b1 100644 --- a/locales/tr/README.md +++ b/locales/tr/README.md @@ -50,13 +50,13 @@ Detaylı güncellemeler ve düzeltmeler için [CHANGELOG](../../CHANGELOG.md) do --- -## 🎉 Roo Code 3.20 Yayınlandı +## 🎉 Roo Code 3.21 Yayınlandı -Roo Code 3.20 deneysel pazar yeri ve gelişmiş dosya işlemleri sunuyor! +Roo Code 3.21 deneysel pazar yeri ve gelişmiş dosya işlemleri sunuyor! -- **Modlar ve MCP için deneysel pazar yeri** - Ayarlarda deneysel pazar yerimizden özel modları ve MCP sunucularını keşfedin ve kurun. -- **Gelişmiş dosya işlemleri** - Çoklu eşzamanlı dosya yazma artık deneysel ayarlarda mevcut, çoklu eşzamanlı okuma ise bağlam ayarlarına taşındı. -- **MCP iyileştirmeleri** - Gelişmiş MCP yetenekleri için yeni Mermaid kontrolleri ve Amazon Bedrock düşünce desteği. +- **Pazar yeri artık canlı! Pazar yeri artık canlı!** Modları ve MCP'leri her zamankinden daha kolay keşfedin ve kurun. +- **Yeni Gemini 2.5 Pro, Flash ve Flash Lite modelleri için destek eklendi.** +- **Excel Dosya Desteği ve Daha Fazlası!** - Gelişmiş MCP yetenekleri için yeni Mermaid kontrolleri ve Amazon Bedrock düşünce desteği. --- @@ -184,35 +184,37 @@ Roo Code'u daha iyi hale getirmeye yardımcı olan tüm katkıda bulunanlara te |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## Lisans diff --git a/locales/vi/README.md b/locales/vi/README.md index b8e85d4250..2e59bb759f 100644 --- a/locales/vi/README.md +++ b/locales/vi/README.md @@ -50,13 +50,13 @@ Kiểm tra [CHANGELOG](../../CHANGELOG.md) để biết thông tin chi tiết v --- -## 🎉 Đã Phát Hành Roo Code 3.20 +## 🎉 Đã Phát Hành Roo Code 3.21 -Roo Code 3.20 giới thiệu marketplace thử nghiệm và cải tiến các thao tác tập tin! +Roo Code 3.21 giới thiệu marketplace thử nghiệm và cải tiến các thao tác tập tin! -- **Marketplace thử nghiệm cho các chế độ và MCP** - Khám phá và cài đặt các chế độ tùy chỉnh và máy chủ MCP từ marketplace thử nghiệm của chúng tôi trong cài đặt. -- **Cải tiến các thao tác tập tin** - Ghi đồng thời nhiều tập tin hiện có sẵn trong cài đặt thử nghiệm, và đọc đồng thời nhiều tập tin đã được chuyển sang cài đặt ngữ cảnh. -- **Cải tiến MCP** - Các điều khiển Mermaid mới và hỗ trợ suy nghĩ Amazon Bedrock cho khả năng MCP nâng cao. +- **Marketplace hiện đã hoạt động! Marketplace hiện đã hoạt động!** Khám phá và cài đặt các chế độ và MCP dễ dàng hơn bao giờ hết. +- **Đã thêm hỗ trợ cho các mô hình Gemini 2.5 Pro, Flash và Flash Lite mới.** +- **Hỗ trợ tập tin Excel và nhiều hơn nữa!** - Các điều khiển Mermaid mới và hỗ trợ suy nghĩ Amazon Bedrock cho khả năng MCP nâng cao. --- @@ -184,35 +184,37 @@ Cảm ơn tất cả những người đóng góp đã giúp cải thiện Roo C |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## Giấy Phép diff --git a/locales/zh-CN/README.md b/locales/zh-CN/README.md index 0d726f2fe2..dc8b338941 100644 --- a/locales/zh-CN/README.md +++ b/locales/zh-CN/README.md @@ -50,13 +50,13 @@ --- -## 🎉 Roo Code 3.20 已发布 +## 🎉 Roo Code 3.21 已发布 -Roo Code 3.20 根据您的反馈带来重要的新功能和改进! +Roo Code 3.21 根据您的反馈带来重要的新功能和改进! -- **实验性市场** - 从新市场发现和安装模式和 MCP(在实验性设置中启用)。 -- **增强的文件操作** - 多个并发文件写入现在在实验性设置中可用,多个并发读取已从实验性功能毕业,现在位于上下文设置中。 -- **MCP 改进与更多功能** - 增强的 MCP 支持、更多 Mermaid 控件、Amazon Bedrock 中的思考支持,以及更多功能! +- **市场现已上线!市场现已上线!** 从新市场发现和安装模式和 MCP 比以往更容易(在实验性设置中启用)。 +- **新增 Gemini 2.5 Pro、Flash 和 Flash Lite 模型支持。** 多个并发文件写入现在在实验性设置中可用,多个并发读取已从实验性功能毕业,现在位于上下文设置中。 +- **Excel 文件支持及更多功能!** - 增强的 MCP 支持、更多 Mermaid 控件、Amazon Bedrock 中的思考支持,以及更多功能! --- @@ -184,35 +184,37 @@ code --install-extension bin/roo-cline-.vsix |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## 许可证 diff --git a/locales/zh-TW/README.md b/locales/zh-TW/README.md index 30987c4fe8..85dfce876b 100644 --- a/locales/zh-TW/README.md +++ b/locales/zh-TW/README.md @@ -51,13 +51,13 @@ --- -## 🎉 Roo Code 3.20 已發布 +## 🎉 Roo Code 3.21 已發布 -Roo Code 3.20 推出實驗性市集和檔案操作改進! +Roo Code 3.21 推出實驗性市集和檔案操作改進! -- **模式和 MCP 的實驗性市集** - 在設定中從我們的實驗性市集探索並安裝自訂模式和 MCP 伺服器。 -- **改進的檔案操作** - 多重同時檔案寫入現在可在實驗性設定中使用,多重同時讀取已移至上下文設定。 -- **MCP 改進** - 新的 Mermaid 控制項和 Amazon Bedrock 思考支援,提供增強的 MCP 功能。 +- **市集現已上線!市集現已上線!** 從新市集探索並安裝模式和 MCP 比以往更容易(在實驗性設定中啟用)。 +- **新增 Gemini 2.5 Pro、Flash 和 Flash Lite 模型支援。** 多重同時檔案寫入現在可在實驗性設定中使用,多重同時讀取已移至上下文設定。 +- **Excel 檔案支援及更多功能!** - 新的 Mermaid 控制項和 Amazon Bedrock 思考支援,提供增強的 MCP 功能。 --- @@ -185,35 +185,37 @@ code --install-extension bin/roo-cline-.vsix |mrubens
    mrubens
    |saoudrizwan
    saoudrizwan
    |cte
    cte
    |samhvw8
    samhvw8
    |daniel-lxs
    daniel-lxs
    |hannesrudolph
    hannesrudolph
    | |:---:|:---:|:---:|:---:|:---:|:---:| |KJ7LNW
    KJ7LNW
    |a8trejo
    a8trejo
    |ColemanRoo
    ColemanRoo
    |canrobins13
    canrobins13
    |stea9499
    stea9499
    |joemanley201
    joemanley201
    | -|System233
    System233
    |nissa-seru
    nissa-seru
    |jquanton
    jquanton
    |NyxJae
    NyxJae
    |MuriloFP
    MuriloFP
    |jr
    jr
    | -|d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |elianiva
    elianiva
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | -|monotykamary
    monotykamary
    |cannuri
    cannuri
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    |feifei325
    feifei325
    |xyOz-dev
    xyOz-dev
    | -|pugazhendhi-m
    pugazhendhi-m
    |shariqriazz
    shariqriazz
    |lloydchang
    lloydchang
    |vigneshsubbiah16
    vigneshsubbiah16
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | -|diarmidmackenzie
    diarmidmackenzie
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    |kiwina
    kiwina
    |aheizi
    aheizi
    | -|PeterDaveHello
    PeterDaveHello
    |olweraltuve
    olweraltuve
    |chrarnoldus
    chrarnoldus
    |ChuKhaLi
    ChuKhaLi
    |nbihan-mediware
    nbihan-mediware
    |RaySinner
    RaySinner
    | -|afshawnlotfi
    afshawnlotfi
    |pdecat
    pdecat
    |noritaka1166
    noritaka1166
    |kyle-apex
    kyle-apex
    |emshvac
    emshvac
    |Lunchb0ne
    Lunchb0ne
    | -|SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    | -|taylorwilsdon
    taylorwilsdon
    |StevenTCramer
    StevenTCramer
    |sammcj
    sammcj
    |Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    | -|hassoncs
    hassoncs
    |aitoroses
    aitoroses
    |anton-otee
    anton-otee
    |SannidhyaSah
    SannidhyaSah
    |heyseth
    heyseth
    |taisukeoe
    taisukeoe
    | -|avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    |teddyOOXX
    teddyOOXX
    | -|vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    |yt3trees
    yt3trees
    | -|benzntech
    benzntech
    |axkirillov
    axkirillov
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    |snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    | -|jcbdev
    jcbdev
    |mr-ryan-james
    mr-ryan-james
    |ross
    ross
    |philfung
    philfung
    |napter
    napter
    |Chenjiayuan195
    Chenjiayuan195
    | -|julionav
    julionav
    |SplittyDev
    SplittyDev
    |mdp
    mdp
    |kohii
    kohii
    |kinandan
    kinandan
    |jwcraig
    jwcraig
    | -|shoopapa
    shoopapa
    |im47cn
    im47cn
    |hongzio
    hongzio
    |hatsu38
    hatsu38
    |GOODBOY008
    GOODBOY008
    |forestyoo
    forestyoo
    | -|dqroid
    dqroid
    |dairui1
    dairui1
    |tmsjngx0
    tmsjngx0
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | -|amittell
    amittell
    |vladstudio
    vladstudio
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |nevermorec
    nevermorec
    | -|PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    |shohei-ihaya
    shohei-ihaya
    | -|shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    |qingyuan1109
    qingyuan1109
    | -|pokutuna
    pokutuna
    |philipnext
    philipnext
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    |mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    | -|mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    | -|EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    |Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    | -|chadgauth
    chadgauth
    |bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    | -|QuinsZouls
    QuinsZouls
    |HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    | -|adamhill
    adamhill
    |AMHesch
    AMHesch
    |tgfjt
    tgfjt
    |maekawataiki
    maekawataiki
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    | -|RSO
    RSO
    |SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    | -|mollux
    mollux
    |marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    | -|ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    |celestial-vault
    celestial-vault
    | +|System233
    System233
    |jquanton
    jquanton
    |nissa-seru
    nissa-seru
    |NyxJae
    NyxJae
    |jr
    jr
    |MuriloFP
    MuriloFP
    | +|elianiva
    elianiva
    |d-oit
    d-oit
    |punkpeye
    punkpeye
    |wkordalski
    wkordalski
    |sachasayan
    sachasayan
    |Smartsheet-JB-Brown
    Smartsheet-JB-Brown
    | +|monotykamary
    monotykamary
    |cannuri
    cannuri
    |xyOz-dev
    xyOz-dev
    |feifei325
    feifei325
    |zhangtony239
    zhangtony239
    |qdaxb
    qdaxb
    | +|shariqriazz
    shariqriazz
    |pugazhendhi-m
    pugazhendhi-m
    |vigneshsubbiah16
    vigneshsubbiah16
    |lloydchang
    lloydchang
    |dtrugman
    dtrugman
    |Szpadel
    Szpadel
    | +|chrarnoldus
    chrarnoldus
    |diarmidmackenzie
    diarmidmackenzie
    |olweraltuve
    olweraltuve
    |psv2522
    psv2522
    |Premshay
    Premshay
    |lupuletic
    lupuletic
    | +|kiwina
    kiwina
    |aheizi
    aheizi
    |PeterDaveHello
    PeterDaveHello
    |afshawnlotfi
    afshawnlotfi
    |RaySinner
    RaySinner
    |nbihan-mediware
    nbihan-mediware
    | +|ChuKhaLi
    ChuKhaLi
    |hassoncs
    hassoncs
    |emshvac
    emshvac
    |kyle-apex
    kyle-apex
    |noritaka1166
    noritaka1166
    |pdecat
    pdecat
    | +|SannidhyaSah
    SannidhyaSah
    |StevenTCramer
    StevenTCramer
    |Lunchb0ne
    Lunchb0ne
    |SmartManoj
    SmartManoj
    |vagadiya
    vagadiya
    |slytechnical
    slytechnical
    | +|dleffel
    dleffel
    |arthurauffray
    arthurauffray
    |upamune
    upamune
    |NamesMT
    NamesMT
    |taylorwilsdon
    taylorwilsdon
    |sammcj
    sammcj
    | +|Ruakij
    Ruakij
    |p12tic
    p12tic
    |gtaylor
    gtaylor
    |aitoroses
    aitoroses
    |mr-ryan-james
    mr-ryan-james
    |heyseth
    heyseth
    | +|taisukeoe
    taisukeoe
    |avtc
    avtc
    |dlab-anton
    dlab-anton
    |eonghk
    eonghk
    |kcwhite
    kcwhite
    |ronyblum
    ronyblum
    | +|teddyOOXX
    teddyOOXX
    |vincentsong
    vincentsong
    |yongjer
    yongjer
    |zeozeozeo
    zeozeozeo
    |ashktn
    ashktn
    |franekp
    franekp
    | +|yt3trees
    yt3trees
    |benzntech
    benzntech
    |axkirillov
    axkirillov
    |anton-otee
    anton-otee
    |bramburn
    bramburn
    |olearycrew
    olearycrew
    | +|snoyiatk
    snoyiatk
    |GitlyHallows
    GitlyHallows
    |jcbdev
    jcbdev
    |Chenjiayuan195
    Chenjiayuan195
    |julionav
    julionav
    |SplittyDev
    SplittyDev
    | +|mdp
    mdp
    |napter
    napter
    |ross
    ross
    |philfung
    philfung
    |dairui1
    dairui1
    |dqroid
    dqroid
    | +|forestyoo
    forestyoo
    |GOODBOY008
    GOODBOY008
    |hatsu38
    hatsu38
    |hongzio
    hongzio
    |im47cn
    im47cn
    |shoopapa
    shoopapa
    | +|jwcraig
    jwcraig
    |kinandan
    kinandan
    |nevermorec
    nevermorec
    |bannzai
    bannzai
    |axmo
    axmo
    |asychin
    asychin
    | +|amittell
    amittell
    |Yoshino-Yukitaro
    Yoshino-Yukitaro
    |Yikai-Liao
    Yikai-Liao
    |zxdvd
    zxdvd
    |vladstudio
    vladstudio
    |tmsjngx0
    tmsjngx0
    | +|tgfjt
    tgfjt
    |PretzelVector
    PretzelVector
    |zetaloop
    zetaloop
    |cdlliuy
    cdlliuy
    |user202729
    user202729
    |student20880
    student20880
    | +|shohei-ihaya
    shohei-ihaya
    |shaybc
    shaybc
    |seedlord
    seedlord
    |samir-nimbly
    samir-nimbly
    |robertheadley
    robertheadley
    |refactorthis
    refactorthis
    | +|qingyuan1109
    qingyuan1109
    |pokutuna
    pokutuna
    |philipnext
    philipnext
    |village-way
    village-way
    |oprstchn
    oprstchn
    |nobu007
    nobu007
    | +|mosleyit
    mosleyit
    |moqimoqidea
    moqimoqidea
    |mlopezr
    mlopezr
    |mecab
    mecab
    |olup
    olup
    |lightrabbit
    lightrabbit
    | +|kohii
    kohii
    |linegel
    linegel
    |edwin-truthsearch-io
    edwin-truthsearch-io
    |EamonNerbonne
    EamonNerbonne
    |dbasclpy
    dbasclpy
    |dflatline
    dflatline
    | +|Deon588
    Deon588
    |dleen
    dleen
    |devxpain
    devxpain
    |chadgauth
    chadgauth
    |brunobergher
    brunobergher
    |thecolorblue
    thecolorblue
    | +|bogdan0083
    bogdan0083
    |Atlogit
    Atlogit
    |atlasgong
    atlasgong
    |andreastempsch
    andreastempsch
    |alasano
    alasano
    |QuinsZouls
    QuinsZouls
    | +|HadesArchitect
    HadesArchitect
    |alarno
    alarno
    |nexon33
    nexon33
    |adilhafeez
    adilhafeez
    |adamwlarson
    adamwlarson
    |adamhill
    adamhill
    | +|AMHesch
    AMHesch
    |maekawataiki
    maekawataiki
    |AlexandruSmirnov
    AlexandruSmirnov
    |samsilveira
    samsilveira
    |01Rian
    01Rian
    |RSO
    RSO
    | +|SECKainersdorfer
    SECKainersdorfer
    |R-omk
    R-omk
    |Sarke
    Sarke
    |kvokka
    kvokka
    |ecmasx
    ecmasx
    |mollux
    mollux
    | +|marvijo-code
    marvijo-code
    |mamertofabian
    mamertofabian
    |monkeyDluffy6017
    monkeyDluffy6017
    |libertyteeth
    libertyteeth
    |shtse8
    shtse8
    |Rexarrior
    Rexarrior
    | +|KanTakahiro
    KanTakahiro
    |ksze
    ksze
    |Jdo300
    Jdo300
    |hesara
    hesara
    |DeXtroTip
    DeXtroTip
    |pfitz
    pfitz
    | +|celestial-vault
    celestial-vault
    | | | | | | ## 授權 diff --git a/package.json b/package.json index 0b6c07ce78..0741895029 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,10 @@ }, "pnpm": { "overrides": { - "tar-fs": ">=2.1.3" + "tar-fs": ">=2.1.3", + "esbuild": ">=0.25.0", + "undici": ">=5.29.0", + "brace-expansion": ">=2.0.2" } } } diff --git a/packages/cloud/src/AuthService.ts b/packages/cloud/src/AuthService.ts index 68036ce3c9..f64007f0d2 100644 --- a/packages/cloud/src/AuthService.ts +++ b/packages/cloud/src/AuthService.ts @@ -1,17 +1,17 @@ import crypto from "crypto" import EventEmitter from "events" -import axios from "axios" import * as vscode from "vscode" import { z } from "zod" import type { CloudUserInfo, CloudOrganizationMembership } from "@roo-code/types" -import { getClerkBaseUrl, getRooCodeApiUrl } from "./Config" +import { getClerkBaseUrl, getRooCodeApiUrl, PRODUCTION_CLERK_BASE_URL } from "./Config" import { RefreshTimer } from "./RefreshTimer" import { getUserAgent } from "./utils" export interface AuthServiceEvents { + "attempting-session": [data: { previousState: AuthState }] "inactive-session": [data: { previousState: AuthState }] "active-session": [data: { previousState: AuthState }] "logged-out": [data: { previousState: AuthState }] @@ -25,20 +25,76 @@ const authCredentialsSchema = z.object({ type AuthCredentials = z.infer -const AUTH_CREDENTIALS_KEY = "clerk-auth-credentials" const AUTH_STATE_KEY = "clerk-auth-state" -type AuthState = "initializing" | "logged-out" | "active-session" | "inactive-session" +type AuthState = "initializing" | "logged-out" | "active-session" | "attempting-session" | "inactive-session" + +const clerkSignInResponseSchema = z.object({ + response: z.object({ + created_session_id: z.string(), + }), +}) + +const clerkCreateSessionTokenResponseSchema = z.object({ + jwt: z.string(), +}) + +const clerkMeResponseSchema = z.object({ + response: z.object({ + first_name: z.string().optional(), + last_name: z.string().optional(), + image_url: z.string().optional(), + primary_email_address_id: z.string().optional(), + email_addresses: z + .array( + z.object({ + id: z.string(), + email_address: z.string(), + }), + ) + .optional(), + }), +}) + +const clerkOrganizationMembershipsSchema = z.object({ + response: z.array( + z.object({ + id: z.string(), + role: z.string(), + permissions: z.array(z.string()).optional(), + created_at: z.number().optional(), + updated_at: z.number().optional(), + organization: z.object({ + id: z.string(), + name: z.string(), + slug: z.string().optional(), + image_url: z.string().optional(), + has_image: z.boolean().optional(), + created_at: z.number().optional(), + updated_at: z.number().optional(), + }), + }), + ), +}) + +class InvalidClientTokenError extends Error { + constructor() { + super("Invalid/Expired client token") + Object.setPrototypeOf(this, InvalidClientTokenError.prototype) + } +} export class AuthService extends EventEmitter { private context: vscode.ExtensionContext private timer: RefreshTimer private state: AuthState = "initializing" private log: (...args: unknown[]) => void + private readonly authCredentialsKey: string private credentials: AuthCredentials | null = null private sessionToken: string | null = null private userInfo: CloudUserInfo | null = null + private isFirstRefreshAttempt: boolean = false constructor(context: vscode.ExtensionContext, log?: (...args: unknown[]) => void) { super() @@ -46,6 +102,14 @@ export class AuthService extends EventEmitter { this.context = context this.log = log || console.log + // Calculate auth credentials key based on Clerk base URL + const clerkBaseUrl = getClerkBaseUrl() + if (clerkBaseUrl !== PRODUCTION_CLERK_BASE_URL) { + this.authCredentialsKey = `clerk-auth-credentials-${clerkBaseUrl}` + } else { + this.authCredentialsKey = "clerk-auth-credentials" + } + this.timer = new RefreshTimer({ callback: async () => { await this.refreshSession() @@ -67,7 +131,7 @@ export class AuthService extends EventEmitter { this.credentials.clientToken !== credentials.clientToken || this.credentials.sessionId !== credentials.sessionId ) { - this.transitionToInactiveSession(credentials) + this.transitionToAttemptingSession(credentials) } } else { if (this.state !== "logged-out") { @@ -94,9 +158,24 @@ export class AuthService extends EventEmitter { this.log("[auth] Transitioned to logged-out state") } - private transitionToInactiveSession(credentials: AuthCredentials): void { + private transitionToAttemptingSession(credentials: AuthCredentials): void { this.credentials = credentials + const previousState = this.state + this.state = "attempting-session" + + this.sessionToken = null + this.userInfo = null + this.isFirstRefreshAttempt = true + + this.emit("attempting-session", { previousState }) + + this.timer.start() + + this.log("[auth] Transitioned to attempting-session state") + } + + private transitionToInactiveSession(): void { const previousState = this.state this.state = "inactive-session" @@ -105,8 +184,6 @@ export class AuthService extends EventEmitter { this.emit("inactive-session", { previousState }) - this.timer.start() - this.log("[auth] Transitioned to inactive-session state") } @@ -126,7 +203,7 @@ export class AuthService extends EventEmitter { this.context.subscriptions.push( this.context.secrets.onDidChange((e) => { - if (e.key === AUTH_CREDENTIALS_KEY) { + if (e.key === this.authCredentialsKey) { this.handleCredentialsChange() } }), @@ -134,11 +211,11 @@ export class AuthService extends EventEmitter { } private async storeCredentials(credentials: AuthCredentials): Promise { - await this.context.secrets.store(AUTH_CREDENTIALS_KEY, JSON.stringify(credentials)) + await this.context.secrets.store(this.authCredentialsKey, JSON.stringify(credentials)) } private async loadCredentials(): Promise { - const credentialsJson = await this.context.secrets.get(AUTH_CREDENTIALS_KEY) + const credentialsJson = await this.context.secrets.get(this.authCredentialsKey) if (!credentialsJson) return null try { @@ -155,7 +232,7 @@ export class AuthService extends EventEmitter { } private async clearCredentials(): Promise { - await this.context.secrets.delete(AUTH_CREDENTIALS_KEY) + await this.context.secrets.delete(this.authCredentialsKey) } /** @@ -208,7 +285,7 @@ export class AuthService extends EventEmitter { throw new Error("Invalid state parameter. Authentication request may have been tampered with.") } - const { credentials } = await this.clerkSignIn(code) + const credentials = await this.clerkSignIn(code) await this.storeCredentials(credentials) @@ -267,16 +344,27 @@ export class AuthService extends EventEmitter { /** * Check if the user is authenticated * - * @returns True if the user is authenticated (has an active or inactive session) + * @returns True if the user is authenticated (has an active, attempting, or inactive session) */ public isAuthenticated(): boolean { - return this.state === "active-session" || this.state === "inactive-session" + return ( + this.state === "active-session" || this.state === "attempting-session" || this.state === "inactive-session" + ) } public hasActiveSession(): boolean { return this.state === "active-session" } + /** + * Check if the user has an active session or is currently attempting to acquire one + * + * @returns True if the user has an active session or is attempting to get one + */ + public hasOrIsAcquiringActiveSession(): boolean { + return this.state === "active-session" || this.state === "attempting-session" + } + /** * Refresh the session * @@ -285,7 +373,6 @@ export class AuthService extends EventEmitter { private async refreshSession(): Promise { if (!this.credentials) { this.log("[auth] Cannot refresh session: missing credentials") - this.state = "inactive-session" return } @@ -300,6 +387,13 @@ export class AuthService extends EventEmitter { this.fetchUserInfo() } } catch (error) { + if (error instanceof InvalidClientTokenError) { + this.log("[auth] Invalid/Expired client token: clearing credentials") + this.clearCredentials() + } else if (this.isFirstRefreshAttempt && this.state === "attempting-session") { + this.isFirstRefreshAttempt = false + this.transitionToInactiveSession() + } this.log("[auth] Failed to refresh session", error) throw error } @@ -323,103 +417,93 @@ export class AuthService extends EventEmitter { return this.userInfo } - private async clerkSignIn(ticket: string): Promise<{ credentials: AuthCredentials; sessionToken: string }> { + private async clerkSignIn(ticket: string): Promise { const formData = new URLSearchParams() formData.append("strategy", "ticket") formData.append("ticket", ticket) - const response = await axios.post(`${getClerkBaseUrl()}/v1/client/sign_ins`, formData, { + const response = await fetch(`${getClerkBaseUrl()}/v1/client/sign_ins`, { + method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "User-Agent": this.userAgent(), }, + body: formData.toString(), + signal: AbortSignal.timeout(10000), }) + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`) + } + + const { + response: { created_session_id: sessionId }, + } = clerkSignInResponseSchema.parse(await response.json()) + // 3. Extract the client token from the Authorization header. - const clientToken = response.headers.authorization + const clientToken = response.headers.get("authorization") if (!clientToken) { throw new Error("No authorization header found in the response") } - // 4. Find the session using created_session_id and extract the JWT. - const sessionId = response.data?.response?.created_session_id - - if (!sessionId) { - throw new Error("No session ID found in the response") - } - - // Find the session in the client sessions array. - const session = response.data?.client?.sessions?.find((s: { id: string }) => s.id === sessionId) - - if (!session) { - throw new Error("Session not found in the response") - } - - // Extract the session token (JWT) and store it. - const sessionToken = session.last_active_token?.jwt - - if (!sessionToken) { - throw new Error("Session does not have a token") - } - - const credentials = authCredentialsSchema.parse({ clientToken, sessionId }) - - return { credentials, sessionToken } + return authCredentialsSchema.parse({ clientToken, sessionId }) } private async clerkCreateSessionToken(): Promise { const formData = new URLSearchParams() formData.append("_is_native", "1") - const response = await axios.post( - `${getClerkBaseUrl()}/v1/client/sessions/${this.credentials!.sessionId}/tokens`, - formData, - { - headers: { - "Content-Type": "application/x-www-form-urlencoded", - Authorization: `Bearer ${this.credentials!.clientToken}`, - "User-Agent": this.userAgent(), - }, + const response = await fetch(`${getClerkBaseUrl()}/v1/client/sessions/${this.credentials!.sessionId}/tokens`, { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + Authorization: `Bearer ${this.credentials!.clientToken}`, + "User-Agent": this.userAgent(), }, - ) + body: formData.toString(), + signal: AbortSignal.timeout(10000), + }) - const sessionToken = response.data?.jwt - - if (!sessionToken) { - throw new Error("No JWT found in refresh response") + if (response.status >= 400 && response.status < 500) { + throw new InvalidClientTokenError() + } else if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`) } - return sessionToken + const data = clerkCreateSessionTokenResponseSchema.parse(await response.json()) + + return data.jwt } private async clerkMe(): Promise { - const response = await axios.get(`${getClerkBaseUrl()}/v1/me`, { + const response = await fetch(`${getClerkBaseUrl()}/v1/me`, { headers: { Authorization: `Bearer ${this.credentials!.clientToken}`, "User-Agent": this.userAgent(), }, + signal: AbortSignal.timeout(10000), }) - const userData = response.data?.response - - if (!userData) { - throw new Error("No response user data") + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`) } + const { response: userData } = clerkMeResponseSchema.parse(await response.json()) + const userInfo: CloudUserInfo = {} - userInfo.name = `${userData?.first_name} ${userData?.last_name}` - const primaryEmailAddressId = userData?.primary_email_address_id - const emailAddresses = userData?.email_addresses + userInfo.name = `${userData.first_name} ${userData.last_name}` + const primaryEmailAddressId = userData.primary_email_address_id + const emailAddresses = userData.email_addresses if (primaryEmailAddressId && emailAddresses) { userInfo.email = emailAddresses.find( - (email: { id: string }) => primaryEmailAddressId === email?.id, + (email: { id: string }) => primaryEmailAddressId === email.id, )?.email_address } - userInfo.picture = userData?.image_url + userInfo.picture = userData.image_url // Fetch organization memberships separately try { @@ -433,6 +517,7 @@ export class AuthService extends EventEmitter { userInfo.organizationId = organization.id userInfo.organizationName = organization.name userInfo.organizationRole = primaryOrgMembership.role + userInfo.organizationImageUrl = organization.image_url } } } catch (error) { @@ -444,51 +529,38 @@ export class AuthService extends EventEmitter { } private async clerkGetOrganizationMemberships(): Promise { - const response = await axios.get(`${getClerkBaseUrl()}/v1/me/organization_memberships`, { + const response = await fetch(`${getClerkBaseUrl()}/v1/me/organization_memberships`, { headers: { Authorization: `Bearer ${this.credentials!.clientToken}`, "User-Agent": this.userAgent(), }, + signal: AbortSignal.timeout(10000), }) - // The response structure is: { response: [...] } - // Extract the organization memberships from the response.response array - return response.data?.response || [] + return clerkOrganizationMembershipsSchema.parse(await response.json()).response } private async clerkLogout(credentials: AuthCredentials): Promise { const formData = new URLSearchParams() formData.append("_is_native", "1") - await axios.post(`${getClerkBaseUrl()}/v1/client/sessions/${credentials.sessionId}/remove`, formData, { + const response = await fetch(`${getClerkBaseUrl()}/v1/client/sessions/${credentials.sessionId}/remove`, { + method: "POST", headers: { + "Content-Type": "application/x-www-form-urlencoded", Authorization: `Bearer ${credentials.clientToken}`, "User-Agent": this.userAgent(), }, + body: formData.toString(), + signal: AbortSignal.timeout(10000), }) + + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`) + } } private userAgent(): string { return getUserAgent(this.context) } - - private static _instance: AuthService | null = null - - static get instance() { - if (!this._instance) { - throw new Error("AuthService not initialized") - } - - return this._instance - } - - static async createInstance(context: vscode.ExtensionContext, log?: (...args: unknown[]) => void) { - if (this._instance) { - throw new Error("AuthService instance already created") - } - - this._instance = new AuthService(context, log) - await this._instance.initialize() - return this._instance - } } diff --git a/packages/cloud/src/CloudService.ts b/packages/cloud/src/CloudService.ts index fe3bad970c..c53538f1bc 100644 --- a/packages/cloud/src/CloudService.ts +++ b/packages/cloud/src/CloudService.ts @@ -37,16 +37,19 @@ export class CloudService { } try { - this.authService = await AuthService.createInstance(this.context, this.log) + this.authService = new AuthService(this.context, this.log) + await this.authService.initialize() + this.authService.on("attempting-session", this.authListener) this.authService.on("inactive-session", this.authListener) this.authService.on("active-session", this.authListener) this.authService.on("logged-out", this.authListener) this.authService.on("user-info", this.authListener) - this.settingsService = await SettingsService.createInstance(this.context, () => + this.settingsService = new SettingsService(this.context, this.authService, () => this.callbacks.stateChanged?.(), ) + this.settingsService.initialize() this.telemetryClient = new TelemetryClient(this.authService, this.settingsService) @@ -87,6 +90,11 @@ export class CloudService { return this.authService!.hasActiveSession() } + public hasOrIsAcquiringActiveSession(): boolean { + this.ensureInitialized() + return this.authService!.hasOrIsAcquiringActiveSession() + } + public getUserInfo(): CloudUserInfo | null { this.ensureInitialized() return this.authService!.getUserInfo() @@ -136,9 +144,9 @@ export class CloudService { // ShareService - public async shareTask(taskId: string): Promise { + public async shareTask(taskId: string, visibility: "organization" | "public" = "organization") { this.ensureInitialized() - return this.shareService!.shareTask(taskId) + return this.shareService!.shareTask(taskId, visibility) } public async canShareTask(): Promise { @@ -150,6 +158,8 @@ export class CloudService { public dispose(): void { if (this.authService) { + this.authService.off("attempting-session", this.authListener) + this.authService.off("inactive-session", this.authListener) this.authService.off("active-session", this.authListener) this.authService.off("logged-out", this.authListener) this.authService.off("user-info", this.authListener) @@ -162,13 +172,7 @@ export class CloudService { } private ensureInitialized(): void { - if ( - !this.isInitialized || - !this.authService || - !this.settingsService || - !this.telemetryClient || - !this.shareService - ) { + if (!this.isInitialized) { throw new Error("CloudService not initialized.") } } diff --git a/packages/cloud/src/SettingsService.ts b/packages/cloud/src/SettingsService.ts index d849cc03ae..3ee56000e8 100644 --- a/packages/cloud/src/SettingsService.ts +++ b/packages/cloud/src/SettingsService.ts @@ -14,14 +14,12 @@ import { RefreshTimer } from "./RefreshTimer" const ORGANIZATION_SETTINGS_CACHE_KEY = "organization-settings" export class SettingsService { - private static _instance: SettingsService | null = null - private context: vscode.ExtensionContext private authService: AuthService private settings: OrganizationSettings | undefined = undefined private timer: RefreshTimer - private constructor(context: vscode.ExtensionContext, authService: AuthService, callback: () => void) { + constructor(context: vscode.ExtensionContext, authService: AuthService, callback: () => void) { this.context = context this.authService = authService @@ -44,6 +42,10 @@ export class SettingsService { this.removeSettings() } + this.authService.on("attempting-session", () => { + this.timer.start() + }) + this.authService.on("active-session", () => { this.timer.start() }) @@ -53,7 +55,7 @@ export class SettingsService { this.removeSettings() }) - if (this.authService.hasActiveSession()) { + if (this.authService.hasOrIsAcquiringActiveSession()) { this.timer.start() } } @@ -121,22 +123,4 @@ export class SettingsService { public dispose(): void { this.timer.stop() } - - static get instance() { - if (!this._instance) { - throw new Error("SettingsService not initialized") - } - - return this._instance - } - - static async createInstance(context: vscode.ExtensionContext, callback: () => void) { - if (this._instance) { - throw new Error("SettingsService instance already created") - } - - this._instance = new SettingsService(context, AuthService.instance, callback) - this._instance.initialize() - return this._instance - } } diff --git a/packages/cloud/src/ShareService.ts b/packages/cloud/src/ShareService.ts index 96eb20963e..42ea9c9fcf 100644 --- a/packages/cloud/src/ShareService.ts +++ b/packages/cloud/src/ShareService.ts @@ -7,6 +7,8 @@ import type { AuthService } from "./AuthService" import type { SettingsService } from "./SettingsService" import { getUserAgent } from "./utils" +export type ShareVisibility = "organization" | "public" + export class ShareService { private authService: AuthService private settingsService: SettingsService @@ -19,19 +21,19 @@ export class ShareService { } /** - * Share a task: Create link and copy to clipboard - * Returns true if successful, false if failed + * Share a task with specified visibility + * Returns the share response data */ - async shareTask(taskId: string): Promise { + async shareTask(taskId: string, visibility: ShareVisibility = "organization") { try { const sessionToken = this.authService.getSessionToken() if (!sessionToken) { - return false + throw new Error("Authentication required") } const response = await axios.post( `${getRooCodeApiUrl()}/api/extension/share`, - { taskId }, + { taskId, visibility }, { headers: { "Content-Type": "application/json", @@ -47,14 +49,12 @@ export class ShareService { if (data.success && data.shareUrl) { // Copy to clipboard await vscode.env.clipboard.writeText(data.shareUrl) - return true - } else { - this.log("[share] Share failed:", data.error) - return false } + + return data } catch (error) { this.log("[share] Error sharing task:", error) - return false + throw error } } diff --git a/packages/cloud/src/__mocks__/vscode.ts b/packages/cloud/src/__mocks__/vscode.ts index c4261941c4..ac9082375e 100644 --- a/packages/cloud/src/__mocks__/vscode.ts +++ b/packages/cloud/src/__mocks__/vscode.ts @@ -18,14 +18,18 @@ export interface ExtensionContext { get: (key: string) => Promise store: (key: string, value: string) => Promise delete: (key: string) => Promise + onDidChange: (listener: (e: { key: string }) => void) => { dispose: () => void } } globalState: { get: (key: string) => T | undefined update: (key: string, value: any) => Promise } + subscriptions: any[] extension?: { packageJSON?: { version?: string + publisher?: string + name?: string } } } @@ -36,14 +40,18 @@ export const mockExtensionContext: ExtensionContext = { get: vi.fn().mockResolvedValue(undefined), store: vi.fn().mockResolvedValue(undefined), delete: vi.fn().mockResolvedValue(undefined), + onDidChange: vi.fn().mockReturnValue({ dispose: vi.fn() }), }, globalState: { get: vi.fn().mockReturnValue(undefined), update: vi.fn().mockResolvedValue(undefined), }, + subscriptions: [], extension: { packageJSON: { version: "1.0.0", + publisher: "RooVeterinaryInc", + name: "roo-cline", }, }, } diff --git a/packages/cloud/src/__tests__/AuthService.spec.ts b/packages/cloud/src/__tests__/AuthService.spec.ts new file mode 100644 index 0000000000..f4d4e98510 --- /dev/null +++ b/packages/cloud/src/__tests__/AuthService.spec.ts @@ -0,0 +1,1048 @@ +// npx vitest run src/__tests__/AuthService.spec.ts + +import { vi, Mock, beforeEach, afterEach, describe, it, expect } from "vitest" +import crypto from "crypto" +import * as vscode from "vscode" + +import { AuthService } from "../AuthService" +import { RefreshTimer } from "../RefreshTimer" +import * as Config from "../Config" +import * as utils from "../utils" + +// Mock external dependencies +vi.mock("../RefreshTimer") +vi.mock("../Config") +vi.mock("../utils") +vi.mock("crypto") + +// Mock fetch globally +const mockFetch = vi.fn() +global.fetch = mockFetch + +// Mock vscode module +vi.mock("vscode", () => ({ + window: { + showInformationMessage: vi.fn(), + showErrorMessage: vi.fn(), + }, + env: { + openExternal: vi.fn(), + uriScheme: "vscode", + }, + Uri: { + parse: vi.fn((uri: string) => ({ toString: () => uri })), + }, +})) + +describe("AuthService", () => { + let authService: AuthService + let mockTimer: { + start: Mock + stop: Mock + reset: Mock + } + let mockLog: Mock + let mockContext: { + subscriptions: { push: Mock } + secrets: { + get: Mock + store: Mock + delete: Mock + onDidChange: Mock + } + globalState: { + get: Mock + update: Mock + } + extension: { + packageJSON: { + version: string + publisher: string + name: string + } + } + } + + beforeEach(() => { + // Reset all mocks + vi.clearAllMocks() + + // Setup mock context with proper subscriptions array + mockContext = { + subscriptions: { + push: vi.fn(), + }, + secrets: { + get: vi.fn().mockResolvedValue(undefined), + store: vi.fn().mockResolvedValue(undefined), + delete: vi.fn().mockResolvedValue(undefined), + onDidChange: vi.fn().mockReturnValue({ dispose: vi.fn() }), + }, + globalState: { + get: vi.fn().mockReturnValue(undefined), + update: vi.fn().mockResolvedValue(undefined), + }, + extension: { + packageJSON: { + version: "1.0.0", + publisher: "RooVeterinaryInc", + name: "roo-cline", + }, + }, + } + + // Setup timer mock + mockTimer = { + start: vi.fn(), + stop: vi.fn(), + reset: vi.fn(), + } + vi.mocked(RefreshTimer).mockImplementation(() => mockTimer as unknown as RefreshTimer) + + // Setup config mocks - use production URL by default to maintain existing test behavior + vi.mocked(Config.getClerkBaseUrl).mockReturnValue("https://clerk.roocode.com") + vi.mocked(Config.getRooCodeApiUrl).mockReturnValue("https://api.test.com") + + // Setup utils mock + vi.mocked(utils.getUserAgent).mockReturnValue("Roo-Code 1.0.0") + + // Setup crypto mock + vi.mocked(crypto.randomBytes).mockReturnValue(Buffer.from("test-random-bytes") as never) + + // Setup log mock + mockLog = vi.fn() + + authService = new AuthService(mockContext as unknown as vscode.ExtensionContext, mockLog) + }) + + afterEach(() => { + vi.clearAllMocks() + }) + + describe("constructor", () => { + it("should initialize with correct default values", () => { + expect(authService.getState()).toBe("initializing") + expect(authService.isAuthenticated()).toBe(false) + expect(authService.hasActiveSession()).toBe(false) + expect(authService.getSessionToken()).toBeUndefined() + expect(authService.getUserInfo()).toBeNull() + }) + + it("should create RefreshTimer with correct configuration", () => { + expect(RefreshTimer).toHaveBeenCalledWith({ + callback: expect.any(Function), + successInterval: 50_000, + initialBackoffMs: 1_000, + maxBackoffMs: 300_000, + }) + }) + + it("should use console.log as default logger", () => { + const serviceWithoutLog = new AuthService(mockContext as unknown as vscode.ExtensionContext) + // Can't directly test console.log usage, but constructor should not throw + expect(serviceWithoutLog).toBeInstanceOf(AuthService) + }) + }) + + describe("initialize", () => { + it("should handle credentials change and setup event listener", async () => { + await authService.initialize() + + expect(mockContext.subscriptions.push).toHaveBeenCalled() + expect(mockContext.secrets.onDidChange).toHaveBeenCalled() + }) + + it("should not initialize twice", async () => { + await authService.initialize() + const firstCallCount = vi.mocked(mockContext.secrets.onDidChange).mock.calls.length + + await authService.initialize() + expect(mockContext.secrets.onDidChange).toHaveBeenCalledTimes(firstCallCount) + expect(mockLog).toHaveBeenCalledWith("[auth] initialize() called after already initialized") + }) + + it("should transition to logged-out when no credentials exist", async () => { + mockContext.secrets.get.mockResolvedValue(undefined) + + const loggedOutSpy = vi.fn() + authService.on("logged-out", loggedOutSpy) + + await authService.initialize() + + expect(authService.getState()).toBe("logged-out") + expect(loggedOutSpy).toHaveBeenCalledWith({ previousState: "initializing" }) + }) + + it("should transition to attempting-session when valid credentials exist", async () => { + const credentials = { clientToken: "test-token", sessionId: "test-session" } + mockContext.secrets.get.mockResolvedValue(JSON.stringify(credentials)) + + const attemptingSessionSpy = vi.fn() + authService.on("attempting-session", attemptingSessionSpy) + + await authService.initialize() + + expect(authService.getState()).toBe("attempting-session") + expect(attemptingSessionSpy).toHaveBeenCalledWith({ previousState: "initializing" }) + expect(mockTimer.start).toHaveBeenCalled() + }) + + it("should handle invalid credentials gracefully", async () => { + mockContext.secrets.get.mockResolvedValue("invalid-json") + + const loggedOutSpy = vi.fn() + authService.on("logged-out", loggedOutSpy) + + await authService.initialize() + + expect(authService.getState()).toBe("logged-out") + expect(mockLog).toHaveBeenCalledWith("[auth] Failed to parse stored credentials:", expect.any(Error)) + }) + + it("should handle credentials change events", async () => { + let onDidChangeCallback: (e: { key: string }) => void + + mockContext.secrets.onDidChange.mockImplementation((callback: (e: { key: string }) => void) => { + onDidChangeCallback = callback + return { dispose: vi.fn() } + }) + + await authService.initialize() + + // Simulate credentials change event + const newCredentials = { clientToken: "new-token", sessionId: "new-session" } + mockContext.secrets.get.mockResolvedValue(JSON.stringify(newCredentials)) + + const attemptingSessionSpy = vi.fn() + authService.on("attempting-session", attemptingSessionSpy) + + onDidChangeCallback!({ key: "clerk-auth-credentials" }) + await new Promise((resolve) => setTimeout(resolve, 0)) // Wait for async handling + + expect(attemptingSessionSpy).toHaveBeenCalled() + }) + }) + + describe("login", () => { + beforeEach(async () => { + await authService.initialize() + }) + + it("should generate state and open external URL", async () => { + const mockOpenExternal = vi.fn() + const vscode = await import("vscode") + vi.mocked(vscode.env.openExternal).mockImplementation(mockOpenExternal) + + await authService.login() + + expect(crypto.randomBytes).toHaveBeenCalledWith(16) + expect(mockContext.globalState.update).toHaveBeenCalledWith( + "clerk-auth-state", + "746573742d72616e646f6d2d6279746573", + ) + expect(mockOpenExternal).toHaveBeenCalledWith( + expect.objectContaining({ + toString: expect.any(Function), + }), + ) + }) + + it("should use package.json values for redirect URI", async () => { + const mockOpenExternal = vi.fn() + const vscode = await import("vscode") + vi.mocked(vscode.env.openExternal).mockImplementation(mockOpenExternal) + + await authService.login() + + const expectedUrl = + "https://api.test.com/extension/sign-in?state=746573742d72616e646f6d2d6279746573&auth_redirect=vscode%3A%2F%2FRooVeterinaryInc.roo-cline" + expect(mockOpenExternal).toHaveBeenCalledWith( + expect.objectContaining({ + toString: expect.any(Function), + }), + ) + + // Verify the actual URL + const calledUri = mockOpenExternal.mock.calls[0][0] + expect(calledUri.toString()).toBe(expectedUrl) + }) + + it("should handle errors during login", async () => { + vi.mocked(crypto.randomBytes).mockImplementation(() => { + throw new Error("Crypto error") + }) + + await expect(authService.login()).rejects.toThrow("Failed to initiate Roo Code Cloud authentication") + expect(mockLog).toHaveBeenCalledWith("[auth] Error initiating Roo Code Cloud auth: Error: Crypto error") + }) + }) + + describe("handleCallback", () => { + beforeEach(async () => { + await authService.initialize() + }) + + it("should handle invalid parameters", async () => { + const vscode = await import("vscode") + const mockShowInfo = vi.fn() + vi.mocked(vscode.window.showInformationMessage).mockImplementation(mockShowInfo) + + await authService.handleCallback(null, "state") + expect(mockShowInfo).toHaveBeenCalledWith("Invalid Roo Code Cloud sign in url") + + await authService.handleCallback("code", null) + expect(mockShowInfo).toHaveBeenCalledWith("Invalid Roo Code Cloud sign in url") + }) + + it("should validate state parameter", async () => { + mockContext.globalState.get.mockReturnValue("stored-state") + + await expect(authService.handleCallback("code", "different-state")).rejects.toThrow( + "Failed to handle Roo Code Cloud callback", + ) + expect(mockLog).toHaveBeenCalledWith("[auth] State mismatch in callback") + }) + + it("should successfully handle valid callback", async () => { + const storedState = "valid-state" + mockContext.globalState.get.mockReturnValue(storedState) + + // Mock successful Clerk sign-in response + const mockResponse = { + ok: true, + json: () => + Promise.resolve({ + response: { created_session_id: "session-123" }, + }), + headers: { + get: (header: string) => (header === "authorization" ? "Bearer token-123" : null), + }, + } + mockFetch.mockResolvedValue(mockResponse) + + const vscode = await import("vscode") + const mockShowInfo = vi.fn() + vi.mocked(vscode.window.showInformationMessage).mockImplementation(mockShowInfo) + + await authService.handleCallback("auth-code", storedState) + + expect(mockContext.secrets.store).toHaveBeenCalledWith( + "clerk-auth-credentials", + JSON.stringify({ clientToken: "Bearer token-123", sessionId: "session-123" }), + ) + expect(mockShowInfo).toHaveBeenCalledWith("Successfully authenticated with Roo Code Cloud") + }) + + it("should handle Clerk API errors", async () => { + const storedState = "valid-state" + mockContext.globalState.get.mockReturnValue(storedState) + + mockFetch.mockResolvedValue({ + ok: false, + status: 400, + statusText: "Bad Request", + }) + + const loggedOutSpy = vi.fn() + authService.on("logged-out", loggedOutSpy) + + await expect(authService.handleCallback("auth-code", storedState)).rejects.toThrow( + "Failed to handle Roo Code Cloud callback", + ) + expect(loggedOutSpy).toHaveBeenCalled() + }) + }) + + describe("logout", () => { + beforeEach(async () => { + await authService.initialize() + }) + + it("should clear credentials and call Clerk logout", async () => { + // Set up credentials first by simulating a login state + const credentials = { clientToken: "test-token", sessionId: "test-session" } + + // Manually set the credentials in the service + authService["credentials"] = credentials + + // Mock successful logout response + mockFetch.mockResolvedValue({ ok: true }) + + const vscode = await import("vscode") + const mockShowInfo = vi.fn() + vi.mocked(vscode.window.showInformationMessage).mockImplementation(mockShowInfo) + + await authService.logout() + + expect(mockContext.secrets.delete).toHaveBeenCalledWith("clerk-auth-credentials") + expect(mockContext.globalState.update).toHaveBeenCalledWith("clerk-auth-state", undefined) + expect(mockFetch).toHaveBeenCalledWith( + "https://clerk.roocode.com/v1/client/sessions/test-session/remove", + expect.objectContaining({ + method: "POST", + headers: expect.objectContaining({ + Authorization: "Bearer test-token", + }), + }), + ) + expect(mockShowInfo).toHaveBeenCalledWith("Logged out from Roo Code Cloud") + }) + + it("should handle logout without credentials", async () => { + const vscode = await import("vscode") + const mockShowInfo = vi.fn() + vi.mocked(vscode.window.showInformationMessage).mockImplementation(mockShowInfo) + + await authService.logout() + + expect(mockContext.secrets.delete).toHaveBeenCalled() + expect(mockFetch).not.toHaveBeenCalled() + expect(mockShowInfo).toHaveBeenCalledWith("Logged out from Roo Code Cloud") + }) + + it("should handle Clerk logout errors gracefully", async () => { + // Set up credentials first by simulating a login state + const credentials = { clientToken: "test-token", sessionId: "test-session" } + + // Manually set the credentials in the service + authService["credentials"] = credentials + + // Mock failed logout response + mockFetch.mockRejectedValue(new Error("Network error")) + + const vscode = await import("vscode") + const mockShowInfo = vi.fn() + vi.mocked(vscode.window.showInformationMessage).mockImplementation(mockShowInfo) + + await authService.logout() + + expect(mockLog).toHaveBeenCalledWith("[auth] Error calling clerkLogout:", expect.any(Error)) + expect(mockShowInfo).toHaveBeenCalledWith("Logged out from Roo Code Cloud") + }) + }) + + describe("state management", () => { + it("should return correct state", () => { + expect(authService.getState()).toBe("initializing") + }) + + it("should return correct authentication status", async () => { + await authService.initialize() + expect(authService.isAuthenticated()).toBe(false) + + // Create a new service instance with credentials + const credentials = { clientToken: "test-token", sessionId: "test-session" } + mockContext.secrets.get.mockResolvedValue(JSON.stringify(credentials)) + + const authenticatedService = new AuthService(mockContext as unknown as vscode.ExtensionContext, mockLog) + await authenticatedService.initialize() + + expect(authenticatedService.isAuthenticated()).toBe(true) + expect(authenticatedService.hasActiveSession()).toBe(false) + }) + + it("should return session token only for active sessions", () => { + expect(authService.getSessionToken()).toBeUndefined() + + // Manually set state to active-session for testing + // This would normally happen through refreshSession + authService["state"] = "active-session" + authService["sessionToken"] = "test-jwt" + + expect(authService.getSessionToken()).toBe("test-jwt") + }) + + it("should return correct values for new methods", async () => { + await authService.initialize() + expect(authService.hasOrIsAcquiringActiveSession()).toBe(false) + + // Create a new service instance with credentials (attempting-session) + const credentials = { clientToken: "test-token", sessionId: "test-session" } + mockContext.secrets.get.mockResolvedValue(JSON.stringify(credentials)) + + const attemptingService = new AuthService(mockContext as unknown as vscode.ExtensionContext, mockLog) + await attemptingService.initialize() + + expect(attemptingService.hasOrIsAcquiringActiveSession()).toBe(true) + expect(attemptingService.hasActiveSession()).toBe(false) + + // Manually set state to active-session for testing + attemptingService["state"] = "active-session" + expect(attemptingService.hasOrIsAcquiringActiveSession()).toBe(true) + expect(attemptingService.hasActiveSession()).toBe(true) + }) + }) + + describe("session refresh", () => { + beforeEach(async () => { + // Set up with credentials + const credentials = { clientToken: "test-token", sessionId: "test-session" } + mockContext.secrets.get.mockResolvedValue(JSON.stringify(credentials)) + await authService.initialize() + }) + + it("should refresh session successfully", async () => { + // Mock successful token creation and user info fetch + mockFetch + .mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve({ jwt: "new-jwt-token" }), + }) + .mockResolvedValueOnce({ + ok: true, + json: () => + Promise.resolve({ + response: { + first_name: "John", + last_name: "Doe", + image_url: "https://example.com/avatar.jpg", + primary_email_address_id: "email-1", + email_addresses: [{ id: "email-1", email_address: "john@example.com" }], + }, + }), + }) + + const activeSessionSpy = vi.fn() + const userInfoSpy = vi.fn() + authService.on("active-session", activeSessionSpy) + authService.on("user-info", userInfoSpy) + + // Trigger refresh by calling the timer callback + const timerCallback = vi.mocked(RefreshTimer).mock.calls[0][0].callback + await timerCallback() + + // Wait for async operations to complete + await new Promise((resolve) => setTimeout(resolve, 0)) + + expect(authService.getState()).toBe("active-session") + expect(authService.hasActiveSession()).toBe(true) + expect(authService.getSessionToken()).toBe("new-jwt-token") + expect(activeSessionSpy).toHaveBeenCalledWith({ previousState: "attempting-session" }) + expect(userInfoSpy).toHaveBeenCalledWith({ + userInfo: { + name: "John Doe", + email: "john@example.com", + picture: "https://example.com/avatar.jpg", + }, + }) + }) + + it("should handle invalid client token error", async () => { + // Mock 401 response (invalid token) + mockFetch.mockResolvedValue({ + ok: false, + status: 401, + statusText: "Unauthorized", + }) + + const timerCallback = vi.mocked(RefreshTimer).mock.calls[0][0].callback + + await expect(timerCallback()).rejects.toThrow() + expect(mockContext.secrets.delete).toHaveBeenCalledWith("clerk-auth-credentials") + expect(mockLog).toHaveBeenCalledWith("[auth] Invalid/Expired client token: clearing credentials") + }) + + it("should handle network errors during refresh", async () => { + mockFetch.mockRejectedValue(new Error("Network error")) + + const timerCallback = vi.mocked(RefreshTimer).mock.calls[0][0].callback + + await expect(timerCallback()).rejects.toThrow("Network error") + expect(mockLog).toHaveBeenCalledWith("[auth] Failed to refresh session", expect.any(Error)) + }) + + it("should transition to inactive-session on first attempt failure", async () => { + // Mock failed token creation response + mockFetch.mockResolvedValue({ + ok: false, + status: 500, + statusText: "Internal Server Error", + }) + + const inactiveSessionSpy = vi.fn() + authService.on("inactive-session", inactiveSessionSpy) + + // Verify we start in attempting-session state + expect(authService.getState()).toBe("attempting-session") + expect(authService["isFirstRefreshAttempt"]).toBe(true) + + const timerCallback = vi.mocked(RefreshTimer).mock.calls[0][0].callback + + await expect(timerCallback()).rejects.toThrow() + + // Should transition to inactive-session after first failure + expect(authService.getState()).toBe("inactive-session") + expect(authService["isFirstRefreshAttempt"]).toBe(false) + expect(inactiveSessionSpy).toHaveBeenCalledWith({ previousState: "attempting-session" }) + }) + + it("should not transition to inactive-session on subsequent failures", async () => { + // First, transition to inactive-session by failing the first attempt + mockFetch.mockResolvedValue({ + ok: false, + status: 500, + statusText: "Internal Server Error", + }) + + const timerCallback = vi.mocked(RefreshTimer).mock.calls[0][0].callback + await expect(timerCallback()).rejects.toThrow() + + // Verify we're now in inactive-session + expect(authService.getState()).toBe("inactive-session") + expect(authService["isFirstRefreshAttempt"]).toBe(false) + + const inactiveSessionSpy = vi.fn() + authService.on("inactive-session", inactiveSessionSpy) + + // Subsequent failure should not trigger another transition + await expect(timerCallback()).rejects.toThrow() + + expect(authService.getState()).toBe("inactive-session") + expect(inactiveSessionSpy).not.toHaveBeenCalled() + }) + + it("should clear credentials on 401 during first refresh attempt (bug fix)", async () => { + // Mock 401 response during first refresh attempt + mockFetch.mockResolvedValue({ + ok: false, + status: 401, + statusText: "Unauthorized", + }) + + const loggedOutSpy = vi.fn() + authService.on("logged-out", loggedOutSpy) + + const timerCallback = vi.mocked(RefreshTimer).mock.calls[0][0].callback + await expect(timerCallback()).rejects.toThrow() + + // Should clear credentials (not just transition to inactive-session) + expect(mockContext.secrets.delete).toHaveBeenCalledWith("clerk-auth-credentials") + expect(mockLog).toHaveBeenCalledWith("[auth] Invalid/Expired client token: clearing credentials") + + // Simulate credentials cleared event + mockContext.secrets.get.mockResolvedValue(undefined) + await authService["handleCredentialsChange"]() + + expect(authService.getState()).toBe("logged-out") + expect(loggedOutSpy).toHaveBeenCalledWith({ previousState: "attempting-session" }) + }) + }) + + describe("user info", () => { + it("should return null initially", () => { + expect(authService.getUserInfo()).toBeNull() + }) + + it("should parse user info correctly", async () => { + // Set up with credentials + const credentials = { clientToken: "test-token", sessionId: "test-session" } + mockContext.secrets.get.mockResolvedValue(JSON.stringify(credentials)) + await authService.initialize() + + // Clear previous mock calls + mockFetch.mockClear() + + // Mock successful responses + mockFetch + .mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve({ jwt: "jwt-token" }), + }) + .mockResolvedValueOnce({ + ok: true, + json: () => + Promise.resolve({ + response: { + first_name: "Jane", + last_name: "Smith", + image_url: "https://example.com/jane.jpg", + primary_email_address_id: "email-2", + email_addresses: [ + { id: "email-1", email_address: "jane.old@example.com" }, + { id: "email-2", email_address: "jane@example.com" }, + ], + }, + }), + }) + .mockResolvedValueOnce({ + ok: true, + json: () => + Promise.resolve({ + response: [ + { + id: "org_member_id_1", + role: "member", + organization: { + id: "org_1", + name: "Org 1", + }, + }, + ], + }), + }) + + const timerCallback = vi.mocked(RefreshTimer).mock.calls[0][0].callback + await timerCallback() + + // Wait for async operations to complete + await new Promise((resolve) => setTimeout(resolve, 0)) + + const userInfo = authService.getUserInfo() + expect(userInfo).toEqual({ + name: "Jane Smith", + email: "jane@example.com", + picture: "https://example.com/jane.jpg", + organizationId: "org_1", + organizationName: "Org 1", + organizationRole: "member", + }) + }) + + it("should handle missing user info fields", async () => { + // Set up with credentials + const credentials = { clientToken: "test-token", sessionId: "test-session" } + mockContext.secrets.get.mockResolvedValue(JSON.stringify(credentials)) + await authService.initialize() + + // Clear previous mock calls + mockFetch.mockClear() + + // Mock responses with minimal data + mockFetch + .mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve({ jwt: "jwt-token" }), + }) + .mockResolvedValueOnce({ + ok: true, + json: () => + Promise.resolve({ + response: { + first_name: "John", + last_name: "Doe", + // Missing other fields + }, + }), + }) + + const timerCallback = vi.mocked(RefreshTimer).mock.calls[0][0].callback + await timerCallback() + + // Wait for async operations to complete + await new Promise((resolve) => setTimeout(resolve, 0)) + + const userInfo = authService.getUserInfo() + expect(userInfo).toEqual({ + name: "John Doe", + email: undefined, + picture: undefined, + }) + }) + }) + + describe("event emissions", () => { + it("should emit logged-out event", async () => { + const loggedOutSpy = vi.fn() + authService.on("logged-out", loggedOutSpy) + + await authService.initialize() + + expect(loggedOutSpy).toHaveBeenCalledWith({ previousState: "initializing" }) + }) + + it("should emit attempting-session event", async () => { + const credentials = { clientToken: "test-token", sessionId: "test-session" } + mockContext.secrets.get.mockResolvedValue(JSON.stringify(credentials)) + + const attemptingSessionSpy = vi.fn() + authService.on("attempting-session", attemptingSessionSpy) + + await authService.initialize() + + expect(attemptingSessionSpy).toHaveBeenCalledWith({ previousState: "initializing" }) + }) + + it("should emit active-session event", async () => { + // Set up with credentials + const credentials = { clientToken: "test-token", sessionId: "test-session" } + mockContext.secrets.get.mockResolvedValue(JSON.stringify(credentials)) + await authService.initialize() + + // Clear previous mock calls + mockFetch.mockClear() + + // Mock both the token creation and user info fetch + mockFetch + .mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve({ jwt: "jwt-token" }), + }) + .mockResolvedValueOnce({ + ok: true, + json: () => + Promise.resolve({ + response: { + first_name: "Test", + last_name: "User", + }, + }), + }) + + const activeSessionSpy = vi.fn() + authService.on("active-session", activeSessionSpy) + + const timerCallback = vi.mocked(RefreshTimer).mock.calls[0][0].callback + await timerCallback() + + // Wait for async operations to complete + await new Promise((resolve) => setTimeout(resolve, 0)) + + expect(activeSessionSpy).toHaveBeenCalledWith({ previousState: "attempting-session" }) + }) + + it("should emit user-info event", async () => { + // Set up with credentials + const credentials = { clientToken: "test-token", sessionId: "test-session" } + mockContext.secrets.get.mockResolvedValue(JSON.stringify(credentials)) + await authService.initialize() + + // Clear previous mock calls + mockFetch.mockClear() + + mockFetch + .mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve({ jwt: "jwt-token" }), + }) + .mockResolvedValueOnce({ + ok: true, + json: () => + Promise.resolve({ + response: { + first_name: "Test", + last_name: "User", + }, + }), + }) + + const userInfoSpy = vi.fn() + authService.on("user-info", userInfoSpy) + + const timerCallback = vi.mocked(RefreshTimer).mock.calls[0][0].callback + await timerCallback() + + // Wait for async operations to complete + await new Promise((resolve) => setTimeout(resolve, 0)) + + expect(userInfoSpy).toHaveBeenCalledWith({ + userInfo: { + name: "Test User", + email: undefined, + picture: undefined, + }, + }) + }) + }) + + describe("error handling", () => { + it("should handle credentials change errors", async () => { + mockContext.secrets.get.mockRejectedValue(new Error("Storage error")) + + await authService.initialize() + + expect(mockLog).toHaveBeenCalledWith("[auth] Error handling credentials change:", expect.any(Error)) + }) + + it("should handle malformed JSON in credentials", async () => { + mockContext.secrets.get.mockResolvedValue("invalid-json{") + + await authService.initialize() + + expect(authService.getState()).toBe("logged-out") + expect(mockLog).toHaveBeenCalledWith("[auth] Failed to parse stored credentials:", expect.any(Error)) + }) + + it("should handle invalid credentials schema", async () => { + mockContext.secrets.get.mockResolvedValue(JSON.stringify({ invalid: "data" })) + + await authService.initialize() + + expect(authService.getState()).toBe("logged-out") + expect(mockLog).toHaveBeenCalledWith("[auth] Invalid credentials format:", expect.any(Array)) + }) + + it("should handle missing authorization header in sign-in response", async () => { + const storedState = "valid-state" + mockContext.globalState.get.mockReturnValue(storedState) + + mockFetch.mockResolvedValue({ + ok: true, + json: () => + Promise.resolve({ + response: { created_session_id: "session-123" }, + }), + headers: { + get: () => null, // No authorization header + }, + }) + + await expect(authService.handleCallback("auth-code", storedState)).rejects.toThrow( + "Failed to handle Roo Code Cloud callback", + ) + }) + }) + + describe("timer integration", () => { + it("should stop timer on logged-out transition", async () => { + await authService.initialize() + + expect(mockTimer.stop).toHaveBeenCalled() + }) + + it("should start timer on attempting-session transition", async () => { + const credentials = { clientToken: "test-token", sessionId: "test-session" } + mockContext.secrets.get.mockResolvedValue(JSON.stringify(credentials)) + + await authService.initialize() + + expect(mockTimer.start).toHaveBeenCalled() + }) + }) + + describe("auth credentials key scoping", () => { + it("should use default key when getClerkBaseUrl returns production URL", async () => { + // Mock getClerkBaseUrl to return production URL + vi.mocked(Config.getClerkBaseUrl).mockReturnValue("https://clerk.roocode.com") + + const service = new AuthService(mockContext as unknown as vscode.ExtensionContext, mockLog) + const credentials = { clientToken: "test-token", sessionId: "test-session" } + + await service.initialize() + await service["storeCredentials"](credentials) + + expect(mockContext.secrets.store).toHaveBeenCalledWith( + "clerk-auth-credentials", + JSON.stringify(credentials), + ) + }) + + it("should use scoped key when getClerkBaseUrl returns custom URL", async () => { + const customUrl = "https://custom.clerk.com" + // Mock getClerkBaseUrl to return custom URL + vi.mocked(Config.getClerkBaseUrl).mockReturnValue(customUrl) + + const service = new AuthService(mockContext as unknown as vscode.ExtensionContext, mockLog) + const credentials = { clientToken: "test-token", sessionId: "test-session" } + + await service.initialize() + await service["storeCredentials"](credentials) + + expect(mockContext.secrets.store).toHaveBeenCalledWith( + `clerk-auth-credentials-${customUrl}`, + JSON.stringify(credentials), + ) + }) + + it("should load credentials using scoped key", async () => { + const customUrl = "https://custom.clerk.com" + vi.mocked(Config.getClerkBaseUrl).mockReturnValue(customUrl) + + const service = new AuthService(mockContext as unknown as vscode.ExtensionContext, mockLog) + const credentials = { clientToken: "test-token", sessionId: "test-session" } + mockContext.secrets.get.mockResolvedValue(JSON.stringify(credentials)) + + await service.initialize() + const loadedCredentials = await service["loadCredentials"]() + + expect(mockContext.secrets.get).toHaveBeenCalledWith(`clerk-auth-credentials-${customUrl}`) + expect(loadedCredentials).toEqual(credentials) + }) + + it("should clear credentials using scoped key", async () => { + const customUrl = "https://custom.clerk.com" + vi.mocked(Config.getClerkBaseUrl).mockReturnValue(customUrl) + + const service = new AuthService(mockContext as unknown as vscode.ExtensionContext, mockLog) + + await service.initialize() + await service["clearCredentials"]() + + expect(mockContext.secrets.delete).toHaveBeenCalledWith(`clerk-auth-credentials-${customUrl}`) + }) + + it("should listen for changes on scoped key", async () => { + const customUrl = "https://custom.clerk.com" + vi.mocked(Config.getClerkBaseUrl).mockReturnValue(customUrl) + + let onDidChangeCallback: (e: { key: string }) => void + + mockContext.secrets.onDidChange.mockImplementation((callback: (e: { key: string }) => void) => { + onDidChangeCallback = callback + return { dispose: vi.fn() } + }) + + const service = new AuthService(mockContext as unknown as vscode.ExtensionContext, mockLog) + await service.initialize() + + // Simulate credentials change event with scoped key + const newCredentials = { clientToken: "new-token", sessionId: "new-session" } + mockContext.secrets.get.mockResolvedValue(JSON.stringify(newCredentials)) + + const attemptingSessionSpy = vi.fn() + service.on("attempting-session", attemptingSessionSpy) + + onDidChangeCallback!({ key: `clerk-auth-credentials-${customUrl}` }) + await new Promise((resolve) => setTimeout(resolve, 0)) // Wait for async handling + + expect(attemptingSessionSpy).toHaveBeenCalled() + }) + + it("should not respond to changes on different scoped keys", async () => { + const customUrl = "https://custom.clerk.com" + vi.mocked(Config.getClerkBaseUrl).mockReturnValue(customUrl) + + let onDidChangeCallback: (e: { key: string }) => void + + mockContext.secrets.onDidChange.mockImplementation((callback: (e: { key: string }) => void) => { + onDidChangeCallback = callback + return { dispose: vi.fn() } + }) + + const service = new AuthService(mockContext as unknown as vscode.ExtensionContext, mockLog) + await service.initialize() + + const inactiveSessionSpy = vi.fn() + service.on("inactive-session", inactiveSessionSpy) + + // Simulate credentials change event with different scoped key + onDidChangeCallback!({ key: "clerk-auth-credentials-https://other.clerk.com" }) + await new Promise((resolve) => setTimeout(resolve, 0)) // Wait for async handling + + expect(inactiveSessionSpy).not.toHaveBeenCalled() + }) + + it("should not respond to changes on default key when using scoped key", async () => { + const customUrl = "https://custom.clerk.com" + vi.mocked(Config.getClerkBaseUrl).mockReturnValue(customUrl) + + let onDidChangeCallback: (e: { key: string }) => void + + mockContext.secrets.onDidChange.mockImplementation((callback: (e: { key: string }) => void) => { + onDidChangeCallback = callback + return { dispose: vi.fn() } + }) + + const service = new AuthService(mockContext as unknown as vscode.ExtensionContext, mockLog) + await service.initialize() + + const inactiveSessionSpy = vi.fn() + service.on("inactive-session", inactiveSessionSpy) + + // Simulate credentials change event with default key + onDidChangeCallback!({ key: "clerk-auth-credentials" }) + await new Promise((resolve) => setTimeout(resolve, 0)) // Wait for async handling + + expect(inactiveSessionSpy).not.toHaveBeenCalled() + }) + }) +}) diff --git a/packages/cloud/src/__tests__/CloudService.test.ts b/packages/cloud/src/__tests__/CloudService.test.ts index 03b28568d5..c7dc07fcae 100644 --- a/packages/cloud/src/__tests__/CloudService.test.ts +++ b/packages/cloud/src/__tests__/CloudService.test.ts @@ -79,7 +79,7 @@ describe("CloudService", () => { } as unknown as vscode.ExtensionContext mockAuthService = { - initialize: vi.fn(), + initialize: vi.fn().mockResolvedValue(undefined), login: vi.fn(), logout: vi.fn(), isAuthenticated: vi.fn().mockReturnValue(false), @@ -108,11 +108,8 @@ describe("CloudService", () => { }, } - vi.mocked(AuthService.createInstance).mockResolvedValue(mockAuthService as unknown as AuthService) - Object.defineProperty(AuthService, "instance", { get: () => mockAuthService, configurable: true }) - - vi.mocked(SettingsService.createInstance).mockResolvedValue(mockSettingsService as unknown as SettingsService) - Object.defineProperty(SettingsService, "instance", { get: () => mockSettingsService, configurable: true }) + vi.mocked(AuthService).mockImplementation(() => mockAuthService as unknown as AuthService) + vi.mocked(SettingsService).mockImplementation(() => mockSettingsService as unknown as SettingsService) vi.mocked(TelemetryService.hasInstance).mockReturnValue(true) Object.defineProperty(TelemetryService, "instance", { @@ -135,8 +132,8 @@ describe("CloudService", () => { const cloudService = await CloudService.createInstance(mockContext, callbacks) expect(cloudService).toBeInstanceOf(CloudService) - expect(AuthService.createInstance).toHaveBeenCalledWith(mockContext, expect.any(Function)) - expect(SettingsService.createInstance).toHaveBeenCalledWith(mockContext, expect.any(Function)) + expect(AuthService).toHaveBeenCalledWith(mockContext, expect.any(Function)) + expect(SettingsService).toHaveBeenCalledWith(mockContext, mockAuthService, expect.any(Function)) }) it("should throw error if instance already exists", async () => { diff --git a/packages/cloud/src/__tests__/ShareService.test.ts b/packages/cloud/src/__tests__/ShareService.test.ts index b46cefa6a0..55fc4e7c38 100644 --- a/packages/cloud/src/__tests__/ShareService.test.ts +++ b/packages/cloud/src/__tests__/ShareService.test.ts @@ -17,6 +17,7 @@ vi.mock("vscode", () => ({ window: { showInformationMessage: vi.fn(), showErrorMessage: vi.fn(), + showQuickPick: vi.fn(), }, env: { clipboard: { @@ -68,7 +69,7 @@ describe("ShareService", () => { }) describe("shareTask", () => { - it("should share task and copy to clipboard", async () => { + it("should share task with organization visibility and copy to clipboard", async () => { const mockResponse = { data: { success: true, @@ -76,16 +77,16 @@ describe("ShareService", () => { }, } - ;(mockAuthService.hasActiveSession as any).mockReturnValue(true) ;(mockAuthService.getSessionToken as any).mockReturnValue("session-token") mockedAxios.post.mockResolvedValue(mockResponse) - const result = await shareService.shareTask("task-123") + const result = await shareService.shareTask("task-123", "organization") - expect(result).toBe(true) + expect(result.success).toBe(true) + expect(result.shareUrl).toBe("https://app.roocode.com/share/abc123") expect(mockedAxios.post).toHaveBeenCalledWith( "https://app.roocode.com/api/extension/share", - { taskId: "task-123" }, + { taskId: "task-123", visibility: "organization" }, { headers: { "Content-Type": "application/json", @@ -97,6 +98,48 @@ describe("ShareService", () => { expect(vscode.env.clipboard.writeText).toHaveBeenCalledWith("https://app.roocode.com/share/abc123") }) + it("should share task with public visibility", async () => { + const mockResponse = { + data: { + success: true, + shareUrl: "https://app.roocode.com/share/abc123", + }, + } + + ;(mockAuthService.getSessionToken as any).mockReturnValue("session-token") + mockedAxios.post.mockResolvedValue(mockResponse) + + const result = await shareService.shareTask("task-123", "public") + + expect(result.success).toBe(true) + expect(mockedAxios.post).toHaveBeenCalledWith( + "https://app.roocode.com/api/extension/share", + { taskId: "task-123", visibility: "public" }, + expect.any(Object), + ) + }) + + it("should default to organization visibility when not specified", async () => { + const mockResponse = { + data: { + success: true, + shareUrl: "https://app.roocode.com/share/abc123", + }, + } + + ;(mockAuthService.getSessionToken as any).mockReturnValue("session-token") + mockedAxios.post.mockResolvedValue(mockResponse) + + const result = await shareService.shareTask("task-123") + + expect(result.success).toBe(true) + expect(mockedAxios.post).toHaveBeenCalledWith( + "https://app.roocode.com/api/extension/share", + { taskId: "task-123", visibility: "organization" }, + expect.any(Object), + ) + }) + it("should handle API error response", async () => { const mockResponse = { data: { @@ -105,55 +148,26 @@ describe("ShareService", () => { }, } - ;(mockAuthService.hasActiveSession as any).mockReturnValue(true) ;(mockAuthService.getSessionToken as any).mockReturnValue("session-token") mockedAxios.post.mockResolvedValue(mockResponse) - const result = await shareService.shareTask("task-123") + const result = await shareService.shareTask("task-123", "organization") - expect(result).toBe(false) + expect(result.success).toBe(false) + expect(result.error).toBe("Task not found") }) it("should handle authentication errors", async () => { - ;(mockAuthService.hasActiveSession as any).mockReturnValue(false) + ;(mockAuthService.getSessionToken as any).mockReturnValue(null) - const result = await shareService.shareTask("task-123") - - expect(result).toBe(false) - expect(mockedAxios.post).not.toHaveBeenCalled() - }) - - it("should handle 403 error for disabled sharing", async () => { - ;(mockAuthService.hasActiveSession as any).mockReturnValue(true) - ;(mockAuthService.getSessionToken as any).mockReturnValue("session-token") - - const error = { - isAxiosError: true, - response: { - status: 403, - data: { - error: "Task sharing is not enabled for this organization", - }, - }, - } - - mockedAxios.isAxiosError.mockReturnValue(true) - mockedAxios.post.mockRejectedValue(error) - - const result = await shareService.shareTask("task-123") - - expect(result).toBe(false) + await expect(shareService.shareTask("task-123", "organization")).rejects.toThrow("Authentication required") }) it("should handle unexpected errors", async () => { - ;(mockAuthService.hasActiveSession as any).mockReturnValue(true) ;(mockAuthService.getSessionToken as any).mockReturnValue("session-token") - mockedAxios.post.mockRejectedValue(new Error("Network error")) - const result = await shareService.shareTask("task-123") - - expect(result).toBe(false) + await expect(shareService.shareTask("task-123", "organization")).rejects.toThrow("Network error") }) }) diff --git a/packages/telemetry/package.json b/packages/telemetry/package.json index 25c842089b..42d0df387c 100644 --- a/packages/telemetry/package.json +++ b/packages/telemetry/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@roo-code/types": "workspace:^", - "posthog-node": "^4.7.0", + "posthog-node": "^5.0.0", "zod": "^3.25.61" }, "devDependencies": { diff --git a/packages/telemetry/src/TelemetryService.ts b/packages/telemetry/src/TelemetryService.ts index 956f49313a..728809f8bd 100644 --- a/packages/telemetry/src/TelemetryService.ts +++ b/packages/telemetry/src/TelemetryService.ts @@ -173,7 +173,7 @@ export class TelemetryService { itemType, itemName, target, - ... (properties || {}), + ...(properties || {}), }) } diff --git a/packages/types/src/cloud.ts b/packages/types/src/cloud.ts index 6f5547b3d5..dc5ef439dc 100644 --- a/packages/types/src/cloud.ts +++ b/packages/types/src/cloud.ts @@ -13,6 +13,7 @@ export interface CloudUserInfo { organizationId?: string organizationName?: string organizationRole?: string + organizationImageUrl?: string } /** @@ -139,6 +140,8 @@ export const shareResponseSchema = z.object({ success: z.boolean(), shareUrl: z.string().optional(), error: z.string().optional(), + isNewShare: z.boolean().optional(), + manageUrl: z.string().optional(), }) export type ShareResponse = z.infer diff --git a/packages/types/src/experiment.ts b/packages/types/src/experiment.ts index e48aeab4f5..10384db8ed 100644 --- a/packages/types/src/experiment.ts +++ b/packages/types/src/experiment.ts @@ -6,7 +6,7 @@ import type { Keys, Equals, AssertEqual } from "./type-fu.js" * ExperimentId */ -export const experimentIds = ["powerSteering", "disableCompletionCommand", "multiFileApplyDiff"] as const +export const experimentIds = ["powerSteering", "multiFileApplyDiff"] as const export const experimentIdsSchema = z.enum(experimentIds) @@ -18,7 +18,6 @@ export type ExperimentId = z.infer export const experimentsSchema = z.object({ powerSteering: z.boolean().optional(), - disableCompletionCommand: z.boolean().optional(), multiFileApplyDiff: z.boolean().optional(), }) diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts index 5b729a125f..bfd071a755 100644 --- a/packages/types/src/global-settings.ts +++ b/packages/types/src/global-settings.ts @@ -103,6 +103,7 @@ export const globalSettingsSchema = z.object({ customSupportPrompts: customSupportPromptsSchema.optional(), enhancementApiConfigId: z.string().optional(), historyPreviewCollapsed: z.boolean().optional(), + profileThresholds: z.record(z.string(), z.number()).optional(), }) export type GlobalSettings = z.infer diff --git a/packages/types/src/provider-settings.ts b/packages/types/src/provider-settings.ts index 2238081ea4..adc474ddd8 100644 --- a/packages/types/src/provider-settings.ts +++ b/packages/types/src/provider-settings.ts @@ -9,6 +9,7 @@ import { codebaseIndexProviderSchema } from "./codebase-index.js" export const providerNames = [ "anthropic", + "claude-code", "glama", "openrouter", "bedrock", @@ -76,6 +77,10 @@ const anthropicSchema = apiModelIdProviderModelSchema.extend({ anthropicUseAuthToken: z.boolean().optional(), }) +const claudeCodeSchema = apiModelIdProviderModelSchema.extend({ + claudeCodePath: z.string().optional(), +}) + const glamaSchema = baseProviderSettingsSchema.extend({ glamaModelId: z.string().optional(), glamaApiKey: z.string().optional(), @@ -214,6 +219,7 @@ const defaultSchema = z.object({ export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProvider", [ anthropicSchema.merge(z.object({ apiProvider: z.literal("anthropic") })), + claudeCodeSchema.merge(z.object({ apiProvider: z.literal("claude-code") })), glamaSchema.merge(z.object({ apiProvider: z.literal("glama") })), openRouterSchema.merge(z.object({ apiProvider: z.literal("openrouter") })), bedrockSchema.merge(z.object({ apiProvider: z.literal("bedrock") })), @@ -240,6 +246,7 @@ export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProv export const providerSettingsSchema = z.object({ apiProvider: providerNamesSchema.optional(), ...anthropicSchema.shape, + ...claudeCodeSchema.shape, ...glamaSchema.shape, ...openRouterSchema.shape, ...bedrockSchema.shape, diff --git a/packages/types/src/providers/claude-code.ts b/packages/types/src/providers/claude-code.ts new file mode 100644 index 0000000000..ebf053a532 --- /dev/null +++ b/packages/types/src/providers/claude-code.ts @@ -0,0 +1,13 @@ +import type { ModelInfo } from "../model.js" +import { anthropicModels } from "./anthropic.js" + +// Claude Code +export type ClaudeCodeModelId = keyof typeof claudeCodeModels +export const claudeCodeDefaultModelId: ClaudeCodeModelId = "claude-sonnet-4-20250514" +export const claudeCodeModels = { + "claude-sonnet-4-20250514": anthropicModels["claude-sonnet-4-20250514"], + "claude-opus-4-20250514": anthropicModels["claude-opus-4-20250514"], + "claude-3-7-sonnet-20250219": anthropicModels["claude-3-7-sonnet-20250219"], + "claude-3-5-sonnet-20241022": anthropicModels["claude-3-5-sonnet-20241022"], + "claude-3-5-haiku-20241022": anthropicModels["claude-3-5-haiku-20241022"], +} as const satisfies Record diff --git a/packages/types/src/providers/gemini.ts b/packages/types/src/providers/gemini.ts index e2efdf3f08..a7225c7330 100644 --- a/packages/types/src/providers/gemini.ts +++ b/packages/types/src/providers/gemini.ts @@ -53,9 +53,9 @@ export const geminiModels = { contextWindow: 1_048_576, supportsImages: true, supportsPromptCache: true, - inputPrice: 0.15, - outputPrice: 0.6, - cacheReadsPrice: 0.0375, + inputPrice: 0.3, + outputPrice: 2.5, + cacheReadsPrice: 0.075, cacheWritesPrice: 1.0, maxThinkingTokens: 24_576, supportsReasoningBudget: true, diff --git a/packages/types/src/providers/index.ts b/packages/types/src/providers/index.ts index 5f1c08041f..267401bd91 100644 --- a/packages/types/src/providers/index.ts +++ b/packages/types/src/providers/index.ts @@ -1,6 +1,7 @@ export * from "./anthropic.js" export * from "./bedrock.js" export * from "./chutes.js" +export * from "./claude-code.js" export * from "./deepseek.js" export * from "./gemini.js" export * from "./glama.js" @@ -8,6 +9,7 @@ export * from "./groq.js" export * from "./lite-llm.js" export * from "./lm-studio.js" export * from "./mistral.js" +export * from "./ollama.js" export * from "./openai.js" export * from "./openrouter.js" export * from "./requesty.js" diff --git a/packages/types/src/providers/lm-studio.ts b/packages/types/src/providers/lm-studio.ts index f83bbc1039..9e39ae5608 100644 --- a/packages/types/src/providers/lm-studio.ts +++ b/packages/types/src/providers/lm-studio.ts @@ -1 +1,19 @@ +import type { ModelInfo } from "../model.js" + export const LMSTUDIO_DEFAULT_TEMPERATURE = 0 + +// LM Studio +// https://lmstudio.ai/docs/cli/ls +export const lMStudioDefaultModelId = "mistralai/devstral-small-2505" +export const lMStudioDefaultModelInfo: ModelInfo = { + maxTokens: 8192, + contextWindow: 200_000, + supportsImages: true, + supportsComputerUse: true, + supportsPromptCache: true, + inputPrice: 0, + outputPrice: 0, + cacheWritesPrice: 0, + cacheReadsPrice: 0, + description: "LM Studio hosted models", +} diff --git a/packages/types/src/providers/ollama.ts b/packages/types/src/providers/ollama.ts new file mode 100644 index 0000000000..d269da8f4d --- /dev/null +++ b/packages/types/src/providers/ollama.ts @@ -0,0 +1,17 @@ +import type { ModelInfo } from "../model.js" + +// Ollama +// https://ollama.com/models +export const ollamaDefaultModelId = "devstral:24b" +export const ollamaDefaultModelInfo: ModelInfo = { + maxTokens: 4096, + contextWindow: 200_000, + supportsImages: true, + supportsComputerUse: true, + supportsPromptCache: true, + inputPrice: 0, + outputPrice: 0, + cacheWritesPrice: 0, + cacheReadsPrice: 0, + description: "Ollama hosted models", +} diff --git a/packages/types/src/providers/vertex.ts b/packages/types/src/providers/vertex.ts index b264fc8175..b048c19403 100644 --- a/packages/types/src/providers/vertex.ts +++ b/packages/types/src/providers/vertex.ts @@ -30,8 +30,10 @@ export const vertexModels = { contextWindow: 1_048_576, supportsImages: true, supportsPromptCache: true, - inputPrice: 0.15, - outputPrice: 0.6, + inputPrice: 0.3, + outputPrice: 2.5, + cacheReadsPrice: 0.075, + cacheWritesPrice: 1.0, maxThinkingTokens: 24_576, supportsReasoningBudget: true, }, diff --git a/packages/types/src/vscode.ts b/packages/types/src/vscode.ts index 4f6dfbfa85..e6640e9bb6 100644 --- a/packages/types/src/vscode.ts +++ b/packages/types/src/vscode.ts @@ -51,6 +51,7 @@ export const commandIds = [ "focusInput", "acceptInput", + "focusPanel", ] as const export type CommandId = (typeof commandIds)[number] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 391b356d0f..7ab6e2821f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,9 @@ settings: overrides: tar-fs: '>=2.1.3' + esbuild: '>=0.25.0' + undici: '>=5.29.0' + brace-expansion: '>=2.0.2' importers: @@ -21,7 +24,7 @@ importers: specifier: 3.3.2 version: 3.3.2 esbuild: - specifier: ^0.25.0 + specifier: '>=0.25.0' version: 0.25.5 eslint: specifier: ^9.27.0 @@ -165,8 +168,8 @@ importers: specifier: ^3.1.0 version: 3.1.0 lucide-react: - specifier: ^0.513.0 - version: 0.513.0(react@18.3.1) + specifier: ^0.518.0 + version: 0.518.0(react@18.3.1) next: specifier: ^15.2.5 version: 15.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -230,7 +233,7 @@ importers: version: 4.1.6 vitest: specifier: ^3.2.3 - version: 3.2.3(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.15.29)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) apps/web-roo-code: dependencies: @@ -268,8 +271,8 @@ importers: specifier: ^12.15.0 version: 12.16.0(@emotion/is-prop-valid@1.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) lucide-react: - specifier: ^0.513.0 - version: 0.513.0(react@18.3.1) + specifier: ^0.518.0 + version: 0.518.0(react@18.3.1) next: specifier: ^15.2.5 version: 15.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -346,7 +349,7 @@ importers: version: 20.17.57 vitest: specifier: ^3.2.3 - version: 3.2.3(@types/debug@4.1.12)(@types/node@20.17.57)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.17.57)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) packages/cloud: dependencies: @@ -377,7 +380,7 @@ importers: version: 1.100.0 vitest: specifier: ^3.2.3 - version: 3.2.3(@types/debug@4.1.12)(@types/node@20.17.57)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.17.57)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) packages/config-eslint: devDependencies: @@ -479,7 +482,7 @@ importers: version: 4.19.4 vitest: specifier: ^3.2.3 - version: 3.2.3(@types/debug@4.1.12)(@types/node@20.17.57)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.17.57)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) packages/ipc: dependencies: @@ -504,7 +507,7 @@ importers: version: 9.2.3 vitest: specifier: ^3.2.3 - version: 3.2.3(@types/debug@4.1.12)(@types/node@20.17.57)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.17.57)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) packages/telemetry: dependencies: @@ -512,8 +515,8 @@ importers: specifier: workspace:^ version: link:../types posthog-node: - specifier: ^4.7.0 - version: 4.17.2 + specifier: ^5.0.0 + version: 5.1.1 zod: specifier: ^3.25.61 version: 3.25.61 @@ -532,7 +535,7 @@ importers: version: 1.100.0 vitest: specifier: ^3.2.3 - version: 3.2.3(@types/debug@4.1.12)(@types/node@20.17.57)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.17.57)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) packages/types: dependencies: @@ -554,7 +557,7 @@ importers: version: 8.5.0(jiti@2.4.2)(postcss@8.5.4)(tsx@4.19.4)(typescript@5.8.3)(yaml@2.8.0) vitest: specifier: ^3.2.3 - version: 3.2.3(@types/debug@4.1.12)(@types/node@20.17.57)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.17.57)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) src: dependencies: @@ -576,6 +579,9 @@ importers: '@google/genai': specifier: ^1.0.0 version: 1.3.0(@modelcontextprotocol/sdk@1.12.0) + '@lmstudio/sdk': + specifier: ^1.1.1 + version: 1.2.0 '@mistralai/mistralai': specifier: ^1.3.6 version: 1.6.1(zod@3.25.61) @@ -676,8 +682,8 @@ importers: specifier: ^12.0.0 version: 12.0.0 openai: - specifier: ^4.78.1 - version: 4.103.0(ws@8.18.2)(zod@3.25.61) + specifier: ^5.0.0 + version: 5.5.1(ws@8.18.2)(zod@3.25.61) os-name: specifier: ^6.0.0 version: 6.1.0 @@ -691,17 +697,17 @@ importers: specifier: ^1.1.1 version: 1.1.1 pkce-challenge: - specifier: ^4.1.0 - version: 4.1.0 + specifier: ^5.0.0 + version: 5.0.0 pretty-bytes: - specifier: ^6.1.1 - version: 6.1.1 + specifier: ^7.0.0 + version: 7.0.0 ps-tree: specifier: ^1.2.0 version: 1.2.0 puppeteer-chromium-resolver: - specifier: ^23.0.0 - version: 23.0.0 + specifier: ^24.0.0 + version: 24.0.1 puppeteer-core: specifier: ^23.4.0 version: 23.11.1 @@ -715,8 +721,8 @@ importers: specifier: ^0.16.0 version: 0.16.0 serialize-error: - specifier: ^11.0.3 - version: 11.0.3 + specifier: ^12.0.0 + version: 12.0.0 simple-git: specifier: ^3.27.0 version: 3.27.0 @@ -821,8 +827,8 @@ importers: specifier: 3.3.2 version: 3.3.2 esbuild: - specifier: ^0.25.0 - version: 0.25.4 + specifier: '>=0.25.0' + version: 0.25.5 execa: specifier: ^9.5.2 version: 9.5.3 @@ -855,7 +861,7 @@ importers: version: 5.8.3 vitest: specifier: ^3.2.3 - version: 3.2.3(@types/debug@4.1.12)(@types/node@20.17.50)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.17.50)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) zod-to-ts: specifier: ^1.2.0 version: 1.2.0(typescript@5.8.3)(zod@3.25.61) @@ -949,6 +955,9 @@ importers: i18next-http-backend: specifier: ^3.0.2 version: 3.0.2 + katex: + specifier: ^0.16.11 + version: 0.16.22 knuth-shuffle-seeded: specifier: ^1.0.6 version: 1.0.6 @@ -956,8 +965,8 @@ importers: specifier: ^11.1.0 version: 11.1.0 lucide-react: - specifier: ^0.513.0 - version: 0.513.0(react@18.3.1) + specifier: ^0.518.0 + version: 0.518.0(react@18.3.1) mermaid: specifier: ^11.4.1 version: 11.6.0 @@ -965,8 +974,8 @@ importers: specifier: ^1.227.2 version: 1.242.1 pretty-bytes: - specifier: ^6.1.1 - version: 6.1.1 + specifier: ^7.0.0 + version: 7.0.0 react: specifier: ^18.3.1 version: 18.3.1 @@ -994,9 +1003,15 @@ importers: rehype-highlight: specifier: ^7.0.0 version: 7.0.2 + rehype-katex: + specifier: ^7.0.1 + version: 7.0.1 remark-gfm: specifier: ^4.0.1 version: 4.0.1 + remark-math: + specifier: ^6.0.0 + version: 6.0.0 remove-markdown: specifier: ^0.6.0 version: 0.6.2 @@ -1013,8 +1028,8 @@ importers: specifier: ^6.1.13 version: 6.1.18(react-dom@18.3.1(react@18.3.1))(react@18.3.1) tailwind-merge: - specifier: ^2.6.0 - version: 2.6.0 + specifier: ^3.0.0 + version: 3.3.0 tailwindcss: specifier: ^4.0.0 version: 4.1.6 @@ -1037,9 +1052,6 @@ importers: specifier: ^3.25.61 version: 3.25.61 devDependencies: - '@jest/globals': - specifier: ^29.7.0 - version: 29.7.0 '@roo-code/config-eslint': specifier: workspace:^ version: link:../packages/config-eslint @@ -1058,6 +1070,9 @@ importers: '@types/jest': specifier: ^29.0.0 version: 29.5.14 + '@types/katex': + specifier: ^0.16.7 + version: 0.16.7 '@types/node': specifier: 20.x version: 20.17.57 @@ -1070,30 +1085,21 @@ importers: '@types/shell-quote': specifier: ^1.7.5 version: 1.7.5 - '@types/testing-library__jest-dom': - specifier: ^5.14.5 - version: 5.14.9 '@types/vscode-webview': specifier: ^1.57.5 version: 1.57.5 '@vitejs/plugin-react': specifier: ^4.3.4 version: 4.4.1(vite@6.3.5(@types/node@20.17.57)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)) + '@vitest/ui': + specifier: ^3.2.3 + version: 3.2.4(vitest@3.2.4) identity-obj-proxy: specifier: ^3.0.0 version: 3.0.0 - jest: - specifier: ^29.7.0 - version: 29.7.0(@types/node@20.17.57)(babel-plugin-macros@3.1.0) - jest-environment-jsdom: - specifier: ^29.7.0 - version: 29.7.0 - jest-simple-dot-reporter: - specifier: ^1.0.5 - version: 1.0.5 - ts-jest: - specifier: ^29.2.5 - version: 29.3.3(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(esbuild@0.25.5)(jest@29.7.0(@types/node@20.17.57)(babel-plugin-macros@3.1.0))(typescript@5.8.3) + jsdom: + specifier: ^26.0.0 + version: 26.1.0 typescript: specifier: 5.8.3 version: 5.8.3 @@ -1102,7 +1108,7 @@ importers: version: 6.3.5(@types/node@20.17.57)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) vitest: specifier: ^3.2.3 - version: 3.2.3(@types/debug@4.1.12)(@types/node@20.17.57)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.17.57)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) packages: @@ -1132,6 +1138,9 @@ packages: '@anthropic-ai/vertex-sdk@0.7.0': resolution: {integrity: sha512-zNm3hUXgYmYDTyveIxOyxbcnh5VXFkrLo4bSnG6LAfGzW7k3k2iCNDSVKtR9qZrK2BCid7JtVu7jsEKaZ/9dSw==} + '@asamuzakjp/css-color@3.2.0': + resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + '@aws-crypto/crc32@3.0.0': resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==} @@ -1375,97 +1384,6 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-syntax-async-generators@7.8.4': - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-bigint@7.8.3': - resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-properties@7.12.13': - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-static-block@7.14.5': - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-attributes@7.27.1': - resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-meta@7.10.4': - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-json-strings@7.8.3': - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-jsx@7.27.1': - resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-logical-assignment-operators@7.10.4': - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-numeric-separator@7.10.4': - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-object-rest-spread@7.8.3': - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3': - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-chaining@7.8.3': - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-private-property-in-object@7.14.5': - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-top-level-await@7.14.5': - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-typescript@7.27.1': - resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx-self@7.27.1': resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} engines: {node: '>=6.9.0'} @@ -1578,6 +1496,34 @@ packages: '@chevrotain/utils@11.0.3': resolution: {integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==} + '@csstools/color-helpers@5.0.2': + resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-color-parser@3.0.10': + resolution: {integrity: sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + '@dotenvx/dotenvx@1.44.2': resolution: {integrity: sha512-2C44+G2dch4cB6zw7+oGQ9VcFQuuVhc5xOzfVvY7iUEj2PRhiVMIB6SpNMK1V5TvpdqrAqCYFjclK18Mh9vwNQ==} hasBin: true @@ -1617,432 +1563,150 @@ packages: resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==} deprecated: 'Merged into tsx: https://tsx.is' - '@esbuild/aix-ppc64@0.25.4': - resolution: {integrity: sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - '@esbuild/aix-ppc64@0.25.5': resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.18.20': - resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm64@0.25.4': - resolution: {integrity: sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - '@esbuild/android-arm64@0.25.5': resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.18.20': - resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - - '@esbuild/android-arm@0.25.4': - resolution: {integrity: sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - '@esbuild/android-arm@0.25.5': resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.18.20': - resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - - '@esbuild/android-x64@0.25.4': - resolution: {integrity: sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - '@esbuild/android-x64@0.25.5': resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.18.20': - resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-arm64@0.25.4': - resolution: {integrity: sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-arm64@0.25.5': resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.18.20': - resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - - '@esbuild/darwin-x64@0.25.4': - resolution: {integrity: sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - '@esbuild/darwin-x64@0.25.5': resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.18.20': - resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-arm64@0.25.4': - resolution: {integrity: sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - '@esbuild/freebsd-arm64@0.25.5': resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.18.20': - resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.25.4': - resolution: {integrity: sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - '@esbuild/freebsd-x64@0.25.5': resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.18.20': - resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm64@0.25.4': - resolution: {integrity: sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - '@esbuild/linux-arm64@0.25.5': resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.18.20': - resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-arm@0.25.4': - resolution: {integrity: sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - '@esbuild/linux-arm@0.25.5': resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.18.20': - resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-ia32@0.25.4': - resolution: {integrity: sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - '@esbuild/linux-ia32@0.25.5': resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.18.20': - resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-loong64@0.25.4': - resolution: {integrity: sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-loong64@0.25.5': resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.18.20': - resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-mips64el@0.25.4': - resolution: {integrity: sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - '@esbuild/linux-mips64el@0.25.5': resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.18.20': - resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-ppc64@0.25.4': - resolution: {integrity: sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - '@esbuild/linux-ppc64@0.25.5': resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.18.20': - resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-riscv64@0.25.4': - resolution: {integrity: sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - '@esbuild/linux-riscv64@0.25.5': resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.18.20': - resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-s390x@0.25.4': - resolution: {integrity: sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - '@esbuild/linux-s390x@0.25.5': resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.18.20': - resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - - '@esbuild/linux-x64@0.25.4': - resolution: {integrity: sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - '@esbuild/linux-x64@0.25.5': resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.4': - resolution: {integrity: sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - '@esbuild/netbsd-arm64@0.25.5': resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.18.20': - resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.25.4': - resolution: {integrity: sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - '@esbuild/netbsd-x64@0.25.5': resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.4': - resolution: {integrity: sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - '@esbuild/openbsd-arm64@0.25.5': resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.18.20': - resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.25.4': - resolution: {integrity: sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - '@esbuild/openbsd-x64@0.25.5': resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.18.20': - resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - - '@esbuild/sunos-x64@0.25.4': - resolution: {integrity: sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - '@esbuild/sunos-x64@0.25.5': resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.18.20': - resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-arm64@0.25.4': - resolution: {integrity: sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - '@esbuild/win32-arm64@0.25.5': resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.18.20': - resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-ia32@0.25.4': - resolution: {integrity: sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - '@esbuild/win32-ia32@0.25.5': resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.18.20': - resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - - '@esbuild/win32-x64@0.25.4': - resolution: {integrity: sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@esbuild/win32-x64@0.25.5': resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==} engines: {node: '>=18'} @@ -2097,10 +1761,6 @@ packages: '@fast-csv/parse@4.3.6': resolution: {integrity: sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==} - '@fastify/busboy@2.1.1': - resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} - engines: {node: '>=14'} - '@floating-ui/core@1.7.0': resolution: {integrity: sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==} @@ -2266,76 +1926,18 @@ packages: resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} engines: {node: '>=18.0.0'} - '@istanbuljs/load-nyc-config@1.1.0': - resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} - engines: {node: '>=8'} - '@istanbuljs/schema@0.1.3': resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} - '@jest/console@29.7.0': - resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/core@29.7.0': - resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - '@jest/environment@29.7.0': - resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/expect-utils@29.7.0': resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/expect@29.7.0': - resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/fake-timers@29.7.0': - resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/globals@29.7.0': - resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/reporters@29.7.0': - resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - '@jest/schemas@29.6.3': resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/source-map@29.6.3': - resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/test-result@29.7.0': - resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/test-sequencer@29.7.0': - resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/transform@29.7.0': - resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/types@29.6.3': resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2425,6 +2027,12 @@ packages: cpu: [x64] os: [win32] + '@lmstudio/lms-isomorphic@0.4.5': + resolution: {integrity: sha512-Or9KS1Iz3LC7D7WMe4zbqAqKOlDsVcrvMoQFBhmydzzxOg+eYBM5gtfgMMjcwjM0BuUVPhYOjTWEyfXpqfVJzg==} + + '@lmstudio/sdk@1.2.0': + resolution: {integrity: sha512-Eoolmi1cSuGXmLYwtn6pD9eOwjMTb+bQ4iv+i/EYz/hCc+HtbfJamoKfyyw4FogRc03RHsXHe1X18voR40D+2g==} + '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -2723,6 +2331,9 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@puppeteer/browsers@2.10.5': resolution: {integrity: sha512-eifa0o+i8dERnngJwKrfp3dEq7ia5XFyoqB17S4gK8GhsQE4/P8nxOfQSE0zQHxzzLo/cmF+7+ywEQ7wK7Fb+w==} engines: {node: '>=18'} @@ -3470,12 +3081,6 @@ packages: resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} - '@sinonjs/commons@3.0.1': - resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - - '@sinonjs/fake-timers@10.3.0': - resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} - '@smithy/abort-controller@2.2.0': resolution: {integrity: sha512-wRlta7GuLWpTqtFfGo+nZyOO1vEvewdNR1R4rTxpC8XU6vG/NDyrFBhwLZsqg1NUoR1noVaXJPC/7ZK47QCySw==} engines: {node: '>=14.0.0'} @@ -4022,10 +3627,6 @@ packages: peerDependencies: '@testing-library/dom': '>=7.21.4' - '@tootallnate/once@2.0.0': - resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} - engines: {node: '>= 10'} - '@tootallnate/quickjs-emscripten@0.23.0': resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} @@ -4173,9 +3774,6 @@ packages: '@types/glob@8.1.0': resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==} - '@types/graceful-fs@4.1.9': - resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} - '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} @@ -4194,12 +3792,12 @@ packages: '@types/js-cookie@2.2.7': resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==} - '@types/jsdom@20.0.1': - resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} - '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/katex@0.16.7': + resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==} + '@types/lodash.debounce@4.0.9': resolution: {integrity: sha512-Ma5JcgTREwpLRwMM+XwBR7DaWe96nC38uCBDFKZWbNKD+osjVzdpnUSwBcqCptrp16sSOLBAUb50Car5I0TCsQ==} @@ -4246,15 +3844,12 @@ packages: '@types/node@20.17.57': resolution: {integrity: sha512-f3T4y6VU4fVQDKVqJV4Uppy8c1p/sVvS3peyqxyWnzkqXFJLRU7Y1Bl7rMS1Qe9z0v4M6McY0Fp9yBsgHJUsWQ==} - '@types/node@20.19.0': - resolution: {integrity: sha512-hfrc+1tud1xcdVTABC2JiomZJEklMcXYNTVtZLAeqTVWD+qL5jkHKT+1lOtqDdGxt+mB53DTtiz673vfjU8D1Q==} + '@types/node@20.19.1': + resolution: {integrity: sha512-jJD50LtlD2dodAEO653i3YF04NWak6jN3ky+Ri3Em3mGR39/glWiboM/IePaRbgwSfqM1TpGXfAg8ohn/4dTgA==} '@types/node@22.15.29': resolution: {integrity: sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==} - '@types/parse-json@4.0.2': - resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - '@types/prop-types@15.7.14': resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} @@ -4281,15 +3876,9 @@ packages: '@types/stylis@4.2.5': resolution: {integrity: sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==} - '@types/testing-library__jest-dom@5.14.9': - resolution: {integrity: sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==} - '@types/tmp@0.2.6': resolution: {integrity: sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==} - '@types/tough-cookie@4.0.5': - resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} - '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -4383,11 +3972,11 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 - '@vitest/expect@3.2.3': - resolution: {integrity: sha512-W2RH2TPWVHA1o7UmaFKISPvdicFJH+mjykctJFoAkUw+SPTJTGjUNdKscFBrqM7IPnCVu6zihtKYa7TkZS1dkQ==} + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} - '@vitest/mocker@3.2.3': - resolution: {integrity: sha512-cP6fIun+Zx8he4rbWvi+Oya6goKQDZK+Yq4hhlggwQBbrlOQ4qtZ+G4nxB6ZnzI9lyIb+JnvyiJnPC2AGbKSPA==} + '@vitest/mocker@3.2.4': + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} peerDependencies: msw: ^2.4.9 vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 @@ -4397,20 +3986,25 @@ packages: vite: optional: true - '@vitest/pretty-format@3.2.3': - resolution: {integrity: sha512-yFglXGkr9hW/yEXngO+IKMhP0jxyFw2/qys/CK4fFUZnSltD+MU7dVYGrH8rvPcK/O6feXQA+EU33gjaBBbAng==} + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} - '@vitest/runner@3.2.3': - resolution: {integrity: sha512-83HWYisT3IpMaU9LN+VN+/nLHVBCSIUKJzGxC5RWUOsK1h3USg7ojL+UXQR3b4o4UBIWCYdD2fxuzM7PQQ1u8w==} + '@vitest/runner@3.2.4': + resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} - '@vitest/snapshot@3.2.3': - resolution: {integrity: sha512-9gIVWx2+tysDqUmmM1L0hwadyumqssOL1r8KJipwLx5JVYyxvVRfxvMq7DaWbZZsCqZnu/dZedaZQh4iYTtneA==} + '@vitest/snapshot@3.2.4': + resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} - '@vitest/spy@3.2.3': - resolution: {integrity: sha512-JHu9Wl+7bf6FEejTCREy+DmgWe+rQKbK+y32C/k5f4TBIAlijhJbRBIRIOCEpVevgRsCQR2iHRUH2/qKVM/plw==} + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} - '@vitest/utils@3.2.3': - resolution: {integrity: sha512-4zFBCU5Pf+4Z6v+rwnZ1HU1yzOKKvDkMXZrymE2PBlbjKJRlrOxbvpfPSvJTGRIwGoahaOGvp+kbCoxifhzJ1Q==} + '@vitest/ui@3.2.4': + resolution: {integrity: sha512-hGISOaP18plkzbWEcP/QvtRW1xDXF2+96HbEX6byqQhAUbiS5oH6/9JwW+QsQCIYON2bI6QZBF+2PvOmrRZ9wA==} + peerDependencies: + vitest: 3.2.4 + + '@vitest/utils@3.2.4': + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} '@vscode/codicons@0.0.36': resolution: {integrity: sha512-wsNOvNMMJ2BY8rC2N2MNBG7yOowV3ov8KlvUE/AiVUlHKTfWsw3OgAOQduX7h0Un6GssKD3aoTVH+TF3DSQwKQ==} @@ -4490,10 +4084,6 @@ packages: '@xobotyi/scrollbar-width@1.9.5': resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==} - abab@2.0.6: - resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} - deprecated: Use your platform's native atob() and btoa() methods instead - abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -4502,18 +4092,11 @@ packages: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} - acorn-globals@7.0.1: - resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} - acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn-walk@8.3.4: - resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} - engines: {node: '>=0.4.0'} - acorn@8.14.1: resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} engines: {node: '>=0.4.0'} @@ -4524,10 +4107,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - agent-base@7.1.3: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} @@ -4543,10 +4122,6 @@ packages: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} - ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - ansi-escapes@7.0.0: resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} engines: {node: '>=18'} @@ -4690,43 +4265,15 @@ packages: b4a@1.6.7: resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} - babel-jest@29.7.0: - resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.8.0 - - babel-plugin-istanbul@6.1.1: - resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} - engines: {node: '>=8'} - - babel-plugin-jest-hoist@29.6.3: - resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - babel-plugin-macros@3.1.0: - resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} - engines: {node: '>=10', npm: '>=6'} - - babel-preset-current-node-syntax@1.1.0: - resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} - peerDependencies: - '@babel/core': ^7.0.0 - - babel-preset-jest@29.6.3: - resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.0.0 - bail@1.0.5: resolution: {integrity: sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==} bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@3.0.1: + resolution: {integrity: sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==} + engines: {node: '>= 16'} bare-events@2.5.4: resolution: {integrity: sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==} @@ -4805,11 +4352,9 @@ packages: bowser@2.11.0: resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@4.0.1: + resolution: {integrity: sha512-YClrbvTCXGe70pU2JiEiPLYXO9gQkyxYeKpJIQHVS/gOs6EWMQP2RYBwjFLNT322Ji8TOC3IMPfsYCedNpzKfA==} + engines: {node: '>= 18'} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -4823,13 +4368,6 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - bs-logger@0.2.6: - resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} - engines: {node: '>= 6'} - - bser@2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} @@ -4858,7 +4396,7 @@ packages: resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} peerDependencies: - esbuild: '>=0.18' + esbuild: '>=0.25.0' busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} @@ -4897,10 +4435,6 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} - camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} @@ -4937,10 +4471,6 @@ packages: resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - char-regex@1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} - character-entities-html4@2.1.0: resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} @@ -5001,6 +4531,11 @@ packages: peerDependencies: devtools-protocol: '*' + chromium-bidi@5.1.0: + resolution: {integrity: sha512-9MSRhWRVoRPDG0TgzkHrshFSJJNZzfY5UFqUMuksg7zL1yoZIZ3jLB0YAgHclbiAxPI86pBnwDX1tbzoiV8aFw==} + peerDependencies: + devtools-protocol: '*' + ci-info@2.0.0: resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} @@ -5008,9 +4543,6 @@ packages: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} - cjs-module-lexer@1.4.3: - resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} - class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} @@ -5061,17 +4593,10 @@ packages: react: ^18 || ^19 || ^19.0.0-rc react-dom: ^18 || ^19 || ^19.0.0-rc - co@4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - cockatiel@3.2.1: resolution: {integrity: sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==} engines: {node: '>=16'} - collect-v8-coverage@1.0.2: - resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} - color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -5141,9 +4666,6 @@ packages: resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} engines: {node: '>= 10'} - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - confbox@0.1.8: resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} @@ -5199,10 +4721,6 @@ packages: cose-base@2.2.0: resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} - cosmiconfig@7.1.0: - resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} - engines: {node: '>=10'} - crc-32@1.2.2: resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} engines: {node: '>=0.8'} @@ -5212,11 +4730,6 @@ packages: resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==} engines: {node: '>= 10'} - create-jest@29.7.0: - resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - cross-fetch@4.0.0: resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==} @@ -5253,15 +4766,9 @@ packages: engines: {node: '>=4'} hasBin: true - cssom@0.3.8: - resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} - - cssom@0.5.0: - resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} - - cssstyle@2.3.0: - resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} - engines: {node: '>=8'} + cssstyle@4.4.0: + resolution: {integrity: sha512-W0Y2HOXlPkb2yaKrCVRjinYKciu/qSLEmK0K9mcfDei3zwlnHFEHAs/Du3cIRwPqY+J4JsiBzUjoHyc8RsJ03A==} + engines: {node: '>=18'} csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -5430,9 +4937,9 @@ packages: resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} engines: {node: '>= 14'} - data-urls@3.0.2: - resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} - engines: {node: '>=12'} + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} @@ -5490,14 +4997,6 @@ packages: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} - dedent@1.6.0: - resolution: {integrity: sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - deep-eql@5.0.2: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} @@ -5509,10 +5008,6 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - default-browser-id@5.0.0: resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} engines: {node: '>=18'} @@ -5572,10 +5067,6 @@ packages: resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} engines: {node: '>=8'} - detect-newline@3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - detect-node-es@1.1.0: resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} @@ -5585,6 +5076,9 @@ packages: devtools-protocol@0.0.1367902: resolution: {integrity: sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg==} + devtools-protocol@0.0.1452169: + resolution: {integrity: sha512-FOFDVMGrAUNp0dDKsAU1TorWJUx2JOU1k9xdgBKKJF3IBh/Uhl2yswG5r3TEAOrCiGY2QRp1e6LVDQrCsTKO4g==} + didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} @@ -5628,11 +5122,6 @@ packages: domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - domexception@4.0.0: - resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} - engines: {node: '>=12'} - deprecated: Use your platform's native DOMException instead - domhandler@5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} @@ -5780,11 +5269,6 @@ packages: eight-colors@1.3.1: resolution: {integrity: sha512-7nXPYDeKh6DgJDR/mpt2G7N/hCNSGwwoPVmoI3+4TEwOb07VFN1WMPG0DFf6nMEjrkgdj8Og7l7IaEEk3VE6Zg==} - ejs@3.1.10: - resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} - engines: {node: '>=0.10.0'} - hasBin: true - electron-to-chromium@1.5.152: resolution: {integrity: sha512-xBOfg/EBaIlVsHipHl2VdTPJRSvErNUaqW8ejTq5OlOlIYx1wOllCHsAvAIrr55jD1IYEfdR86miUEt8H5IeJg==} @@ -5811,10 +5295,6 @@ packages: embla-carousel@8.6.0: resolution: {integrity: sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==} - emittery@0.13.1: - resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} - engines: {node: '>=12'} - emoji-regex@10.4.0: resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} @@ -5858,9 +5338,6 @@ packages: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} engines: {node: '>=18'} - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - error-stack-parser@2.1.4: resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} @@ -5902,17 +5379,7 @@ packages: esbuild-register@3.6.0: resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} peerDependencies: - esbuild: '>=0.12 <1' - - esbuild@0.18.20: - resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} - engines: {node: '>=12'} - hasBin: true - - esbuild@0.25.4: - resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==} - engines: {node: '>=18'} - hasBin: true + esbuild: '>=0.25.0' esbuild@0.25.5: resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==} @@ -6102,10 +5569,6 @@ packages: exenv-es6@1.1.1: resolution: {integrity: sha512-vlVu3N8d6yEMpMsEm+7sUBAI81aqYYuEvfK0jNqmdb/OPXzzH7QWDDnVjMvDSY47JdHEqx/dfC/q8WkfoTmpGQ==} - exit@0.1.2: - resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} - engines: {node: '>= 0.8.0'} - expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} @@ -6195,9 +5658,6 @@ packages: fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} - fb-watchman@2.0.2: - resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} - fd-package-json@2.0.0: resolution: {integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==} @@ -6227,6 +5687,9 @@ packages: fflate@0.4.8: resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + figures@6.1.0: resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} engines: {node: '>=18'} @@ -6238,9 +5701,6 @@ packages: file-uri-to-path@1.0.0: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -6419,10 +5879,6 @@ packages: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} engines: {node: '>=6'} - get-package-type@0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - get-proto@1.0.1: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} @@ -6567,9 +6023,24 @@ packages: hast-to-hyperscript@9.0.1: resolution: {integrity: sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==} + hast-util-from-dom@5.0.1: + resolution: {integrity: sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==} + + hast-util-from-html-isomorphic@2.0.0: + resolution: {integrity: sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==} + + hast-util-from-html@2.0.3: + resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==} + + hast-util-from-parse5@8.0.3: + resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==} + hast-util-is-element@3.0.0: resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} + hast-util-parse-selector@4.0.0: + resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} + hast-util-to-html@9.0.5: resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} @@ -6582,6 +6053,9 @@ packages: hast-util-whitespace@3.0.0: resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + hastscript@9.0.1: + resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==} + he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true @@ -6597,9 +6071,9 @@ packages: howler@2.2.4: resolution: {integrity: sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==} - html-encoding-sniffer@3.0.0: - resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} - engines: {node: '>=12'} + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -6620,18 +6094,10 @@ packages: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} - http-proxy-agent@5.0.0: - resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} - engines: {node: '>= 6'} - http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} - https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - https-proxy-agent@7.0.6: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} @@ -6708,11 +6174,6 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} - import-local@3.2.0: - resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} - engines: {node: '>=8'} - hasBin: true - imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -6775,9 +6236,6 @@ packages: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} @@ -6852,10 +6310,6 @@ packages: resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} engines: {node: '>=18'} - is-generator-fn@2.1.0: - resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} - engines: {node: '>=6'} - is-generator-function@1.1.0: resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} engines: {node: '>= 0.4'} @@ -7016,22 +6470,10 @@ packages: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} - istanbul-lib-instrument@5.2.1: - resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} - engines: {node: '>=8'} - - istanbul-lib-instrument@6.0.3: - resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} - engines: {node: '>=10'} - istanbul-lib-report@3.0.1: resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} engines: {node: '>=10'} - istanbul-lib-source-maps@4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} - engines: {node: '>=10'} - istanbul-reports@3.1.7: resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} engines: {node: '>=8'} @@ -7047,78 +6489,14 @@ packages: resolution: {integrity: sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==} engines: {node: 20 || >=22} - jake@10.9.2: - resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} - engines: {node: '>=10'} - hasBin: true - - jest-changed-files@29.7.0: - resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-circus@29.7.0: - resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-cli@29.7.0: - resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - jest-config@29.7.0: - resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@types/node': '*' - ts-node: '>=9.0.0' - peerDependenciesMeta: - '@types/node': - optional: true - ts-node: - optional: true - jest-diff@29.7.0: resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-docblock@29.7.0: - resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-each@29.7.0: - resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-environment-jsdom@29.7.0: - resolution: {integrity: sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - - jest-environment-node@29.7.0: - resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-get-type@29.6.3: resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-haste-map@29.7.0: - resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-leak-detector@29.7.0: - resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-matcher-utils@29.7.0: resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7127,72 +6505,10 @@ packages: resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-mock@29.7.0: - resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-pnp-resolver@1.2.3: - resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - - jest-regex-util@29.6.3: - resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-resolve-dependencies@29.7.0: - resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-resolve@29.7.0: - resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-runner@29.7.0: - resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-runtime@29.7.0: - resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-simple-dot-reporter@1.0.5: - resolution: {integrity: sha512-cZLFG/C7k0+WYoIGGuGXKm0vmJiXlWG/m3uCZ4RaMPYxt8lxjdXMLHYkxXaQ7gVWaSPe7uAPCEUcRxthC5xskg==} - - jest-snapshot@29.7.0: - resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-util@29.7.0: resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-validate@29.7.0: - resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-watcher@29.7.0: - resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-worker@29.7.0: - resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest@29.7.0: - resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - jiti@1.21.7: resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} hasBin: true @@ -7236,11 +6552,11 @@ packages: jsbn@1.1.0: resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - jsdom@20.0.3: - resolution: {integrity: sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==} - engines: {node: '>=14'} + jsdom@26.1.0: + resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==} + engines: {node: '>=18'} peerDependencies: - canvas: ^2.5.0 + canvas: ^3.0.0 peerDependenciesMeta: canvas: optional: true @@ -7256,9 +6572,6 @@ packages: json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - json-parse-even-better-errors@4.0.0: resolution: {integrity: sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==} engines: {node: ^18.17.0 || >=20.5.0} @@ -7283,6 +6596,9 @@ packages: jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + jsonschema@1.5.0: + resolution: {integrity: sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw==} + jsonwebtoken@9.0.2: resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} engines: {node: '>=12', npm: '>=6'} @@ -7323,10 +6639,6 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - knip@5.60.2: resolution: {integrity: sha512-TsYqEsoL3802RmhGL5MN7RLI6/03kocMYx/4BpMmwo3dSwEJxmzV7HqRxMVZr6c1llbd25+MqjgA86bv1IwsPA==} engines: {node: '>=18.18.0'} @@ -7592,9 +6904,6 @@ packages: lodash.isundefined@3.0.1: resolution: {integrity: sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==} - lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -7641,6 +6950,9 @@ packages: loupe@3.1.3: resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} + loupe@3.1.4: + resolution: {integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==} + lowlight@3.3.0: resolution: {integrity: sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==} @@ -7662,8 +6974,8 @@ packages: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} - lucide-react@0.513.0: - resolution: {integrity: sha512-CJZKq2g8Y8yN4Aq002GahSXbG2JpFv9kXwyiOAMvUBv7pxeOFHUWKB0mO7MiY4ZVFCV4aNjv2BJFq/z3DgKPQg==} + lucide-react@0.518.0: + resolution: {integrity: sha512-kFg34uQqnVl/7HwAiigxPSpj//43VIVHQbMygQPtS1yT4btMXHCWUipHcgcXHD2pm1Z2nUBA/M+Vnh/YmWXQUw==} peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -7682,12 +6994,6 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - - makeerror@1.0.12: - resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - mammoth@1.9.0: resolution: {integrity: sha512-F+0NxzankQV9XSUAuVKvkdQK0GbtGGuqVnND9aVf9VSeUA82LQa29GjLqYU6Eez8LHqSJG3eGiDW3224OKdpZg==} engines: {node: '>=12.0.0'} @@ -7742,6 +7048,9 @@ packages: mdast-util-gfm@3.1.0: resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==} + mdast-util-math@3.0.0: + resolution: {integrity: sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==} + mdast-util-mdx-expression@2.0.1: resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} @@ -7824,6 +7133,9 @@ packages: micromark-extension-gfm@3.0.0: resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + micromark-extension-math@3.1.0: + resolution: {integrity: sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==} + micromark-factory-destination@2.0.1: resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} @@ -8002,6 +7314,10 @@ packages: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -8103,9 +7419,6 @@ packages: resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - node-int64@0.4.0: - resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - node-ipc@12.0.0: resolution: {integrity: sha512-QHJ2gAJiqA3cM7cQiRjLsfCOBRB0TwQ6axYD4FSllQWipEbP6i7Se1dP8EzPKk5J1nCe27W69eqPmCoKyQ61Vg==} engines: {node: '>=14'} @@ -8223,8 +7536,8 @@ packages: resolution: {integrity: sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==} engines: {node: '>=18'} - openai@4.103.0: - resolution: {integrity: sha512-eWcz9kdurkGOFDtd5ySS5y251H2uBgq9+1a2lTBnjMMzlexJ40Am5t6Mu76SSE87VvitPa0dkIAp75F+dZVC0g==} + openai@5.5.1: + resolution: {integrity: sha512-5i19097mGotHA1eFsM6Tjd/tJ8uo9sa5Ysv4Q6bKJ2vtN6rc0MzMrUefXnLXYAJcmMQrC1Efhj0AvfIkXrQamw==} hasBin: true peerDependencies: ws: ^8.18.0 @@ -8350,10 +7663,6 @@ packages: parse-entities@4.0.2: resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - parse-ms@4.0.0: resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} engines: {node: '>=18'} @@ -8457,18 +7766,10 @@ packages: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} - pkce-challenge@4.1.0: - resolution: {integrity: sha512-ZBmhE1C9LcPoH9XZSdwiPtbPHZROwAnMy+kIFQVrnMCxY4Cudlz3gBOpzilgc0jOgRaiT3sIWfpMomW2ar2orQ==} - engines: {node: '>=16.20.0'} - pkce-challenge@5.0.0: resolution: {integrity: sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==} engines: {node: '>=16.20.0'} - pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} @@ -8586,9 +7887,9 @@ packages: rrweb-snapshot: optional: true - posthog-node@4.17.2: - resolution: {integrity: sha512-bFmwOTk4QdYavopeHVXtyFGQ9vyLMVaNWkWocwjix+0n6sQgv7Zq5nYjYulz7ThmK18zsvNJ337ahuMLv3ulow==} - engines: {node: '>=15.0.0'} + posthog-node@5.1.1: + resolution: {integrity: sha512-6VISkNdxO24ehXiDA4dugyCSIV7lpGVaEu5kn/dlAj+SJ1lgcDru9PQ8p/+GSXsXVxohd1t7kHL2JKc9NoGb0w==} + engines: {node: '>=20'} preact@10.26.6: resolution: {integrity: sha512-5SRRBinwpwkaD+OqlBDeITlRgvd8I8QlxHJw9AxSdMNV6O+LodN9nUyYGpSF7sadHjs6RzeFShMexC6DbtWr9g==} @@ -8612,9 +7913,9 @@ packages: engines: {node: '>=14'} hasBin: true - pretty-bytes@6.1.1: - resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} - engines: {node: ^14.13.1 || >=16.0.0} + pretty-bytes@7.0.0: + resolution: {integrity: sha512-U5otLYPR3L0SVjHGrkEUx5mf7MxV2ceXeE7VwWPk+hyzC5drNohsOGNPDZqxCqyX1lkbEN4kl1LiI8QFd7r0ZA==} + engines: {node: '>=20'} pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} @@ -8638,10 +7939,6 @@ packages: promise-limit@2.7.0: resolution: {integrity: sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==} - prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} @@ -8671,9 +7968,6 @@ packages: engines: {node: '>= 0.10'} hasBin: true - psl@1.15.0: - resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} - pump@3.0.2: resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} @@ -8685,15 +7979,16 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - puppeteer-chromium-resolver@23.0.0: - resolution: {integrity: sha512-PbSXK4ERPwp+eYm+SVY5vMWCxsdeJcddwz4avXvDx7kE9DLE+L86Xg027sypw2oan5yi6557brzVsbajcMmy2g==} + puppeteer-chromium-resolver@24.0.1: + resolution: {integrity: sha512-whu9e5qmnZekCP5hvlYMe7rWe4cU9seCISRlfT0vXGlCsy7psbeXHdGW6QdXrwyadvCTiD1Ft62jPaqia8ZQaA==} puppeteer-core@23.11.1: resolution: {integrity: sha512-3HZ2/7hdDKZvZQ7dhhITOUg4/wOrDRjyK2ZBllRB0ZCOi9u0cwq1ACHDjBB+nX+7+kltHjQvBRdeY7+W0T+7Gg==} engines: {node: '>=18'} - pure-rand@6.1.0: - resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + puppeteer-core@24.10.2: + resolution: {integrity: sha512-CnzhOgrZj8DvkDqI+Yx+9or33i3Y9uUYbKyYpP4C13jWwXx/keQ38RMTMmxuLCWQlxjZrOH0Foq7P2fGP7adDQ==} + engines: {node: '>=18'} qs@6.14.0: resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} @@ -8702,9 +7997,6 @@ packages: quansync@0.2.10: resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==} - querystringify@2.2.0: - resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} - queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -8928,12 +8220,18 @@ packages: rehype-highlight@7.0.2: resolution: {integrity: sha512-k158pK7wdC2qL3M5NcZROZ2tR/l7zOzjxXd5VGdcfIyoijjQqpHd3JKtYSBDpDZ38UI2WJWuFAtkMDxmx5kstA==} + rehype-katex@7.0.1: + resolution: {integrity: sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==} + rehype-react@6.2.1: resolution: {integrity: sha512-f9KIrjktvLvmbGc7si25HepocOg4z0MuNOtweigKzBcDjiGSTGhyz6VSgaV5K421Cq1O+z4/oxRJ5G9owo0KVg==} remark-gfm@4.0.1: resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} + remark-math@6.0.0: + resolution: {integrity: sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==} + remark-parse@11.0.0: resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} @@ -8956,16 +8254,9 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - requires-port@1.0.0: - resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - resize-observer-polyfill@1.5.1: resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} - resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -8977,10 +8268,6 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve.exports@2.0.3: - resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} - engines: {node: '>=10'} - resolve@1.22.10: resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} engines: {node: '>= 0.4'} @@ -9026,6 +8313,9 @@ packages: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + rtl-css-js@1.16.1: resolution: {integrity: sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==} @@ -9105,9 +8395,9 @@ packages: resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} engines: {node: '>= 18'} - serialize-error@11.0.3: - resolution: {integrity: sha512-2G2y++21dhj2R7iHAdd0FIzjGwuKZld+7Pl/bTU6YIkrC2ZMbVUjm+luj6A6V34Rv9XfKJDKpTWu9W4Gse1D9g==} - engines: {node: '>=14.16'} + serialize-error@12.0.0: + resolution: {integrity: sha512-ZYkZLAvKTKQXWuh5XpBw7CdbSzagarX39WyZ2H07CDLC5/KfsRGlIXV8d4+tfqX1M7916mRqR1QfNHSij+c9Pw==} + engines: {node: '>=18'} serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} @@ -9210,8 +8500,9 @@ packages: simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} - sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + sirv@3.0.1: + resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==} + engines: {node: '>=18'} slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} @@ -9254,9 +8545,6 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map-support@0.5.13: - resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} - source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -9341,10 +8629,6 @@ packages: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} - string-length@4.0.2: - resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} - engines: {node: '>=10'} - string-similarity@4.0.4: resolution: {integrity: sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==} deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. @@ -9401,10 +8685,6 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - strip-bom@4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} - engines: {node: '>=8'} - strip-bom@5.0.0: resolution: {integrity: sha512-p+byADHF7SzEcVnLvc/r3uognM1hUhObuHXxJcgLCfD194XAkaLbjq3Wzb0N5G2tgIjH0dgT708Z51QxMeu60A==} engines: {node: '>=12'} @@ -9520,9 +8800,6 @@ packages: tabbable@5.3.3: resolution: {integrity: sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==} - tailwind-merge@2.6.0: - resolution: {integrity: sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==} - tailwind-merge@3.3.0: resolution: {integrity: sha512-fyW/pEfcQSiigd5SNn0nApUOxx0zB/dm6UDU/rEwc2c3sX2smWUNbapHv+QRqLGVp9GWX3THIa7MUGPo+YkDzQ==} @@ -9611,8 +8888,8 @@ packages: resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} engines: {node: '>=12.0.0'} - tinypool@1.1.0: - resolution: {integrity: sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==} + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} engines: {node: ^18.0.0 || >=20.0.0} tinyrainbow@2.0.0: @@ -9623,6 +8900,13 @@ packages: resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==} engines: {node: '>=14.0.0'} + tldts-core@6.1.86: + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} + + tldts@6.1.86: + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} + hasBin: true + tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -9631,9 +8915,6 @@ packages: resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} engines: {node: '>=14.14'} - tmpl@1.0.5: - resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -9645,19 +8926,23 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} - tough-cookie@4.1.4: - resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + tough-cookie@5.1.2: + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} + engines: {node: '>=16'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} - tr46@3.0.0: - resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} - engines: {node: '>=12'} + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} traverse@0.3.9: resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==} @@ -9697,30 +8982,6 @@ packages: ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - ts-jest@29.3.3: - resolution: {integrity: sha512-y6jLm19SL4GroiBmHwFK4dSHUfDNmOrJbRfp6QmDIlI9p5tT5Q8ItccB4pTIslCIqOZuQnBwpTR0bQ5eUMYwkw==} - engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@babel/core': '>=7.0.0-beta.0 <8' - '@jest/transform': ^29.0.0 - '@jest/types': ^29.0.0 - babel-jest: ^29.0.0 - esbuild: '*' - jest: ^29.0.0 - typescript: '>=4.3 <6' - peerDependenciesMeta: - '@babel/core': - optional: true - '@jest/transform': - optional: true - '@jest/types': - optional: true - babel-jest: - optional: true - esbuild: - optional: true - tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} @@ -9802,18 +9063,6 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - - type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - - type-fest@2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} - type-fest@4.41.0: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} @@ -9881,10 +9130,6 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - undici@5.28.5: - resolution: {integrity: sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==} - engines: {node: '>=14.0'} - undici@6.21.3: resolution: {integrity: sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==} engines: {node: '>=18.17'} @@ -9923,6 +9168,9 @@ packages: unist-util-position@5.0.0: resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + unist-util-remove-position@5.0.0: + resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + unist-util-stringify-position@2.0.3: resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} @@ -9951,10 +9199,6 @@ packages: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} - universalify@0.2.0: - resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} - engines: {node: '>= 4.0.0'} - unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} @@ -9978,9 +9222,6 @@ packages: url-join@4.0.1: resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} - url-parse@1.5.10: - resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} - use-callback-ref@1.3.3: resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} engines: {node: '>=10'} @@ -10065,6 +9306,9 @@ packages: react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc + vfile-location@5.0.3: + resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} + vfile-message@2.0.4: resolution: {integrity: sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==} @@ -10080,8 +9324,8 @@ packages: victory-vendor@36.9.2: resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==} - vite-node@3.2.3: - resolution: {integrity: sha512-gc8aAifGuDIpZHrPjuHyP4dpQmYXqWw7D1GmDnWeNWP654UEXzVfQ5IHPSK5HaHkwB/+p1atpYpSdw/2kOv8iQ==} + vite-node@3.2.4: + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true @@ -10125,16 +9369,16 @@ packages: yaml: optional: true - vitest@3.2.3: - resolution: {integrity: sha512-E6U2ZFXe3N/t4f5BwUaVCKRLHqUpk1CBWeMh78UT4VaTPH/2dyvH6ALl29JTovEPu9dVKr/K/J4PkXgrMbw4Ww==} + vitest@3.2.4: + resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/debug': ^4.1.12 '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.2.3 - '@vitest/ui': 3.2.3 + '@vitest/browser': 3.2.4 + '@vitest/ui': 3.2.4 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -10186,20 +9430,20 @@ packages: '@types/react': '*' react: ^17 || ^18 || ^19 - w3c-xmlserializer@4.0.0: - resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} - engines: {node: '>=14'} + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} walk-up-path@4.0.0: resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==} engines: {node: 20 || >=22} - walker@1.0.8: - resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} - web-namespaces@1.1.4: resolution: {integrity: sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==} + web-namespaces@2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} @@ -10224,25 +9468,17 @@ packages: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} - whatwg-encoding@2.0.0: - resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} - engines: {node: '>=12'} - whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} - whatwg-mimetype@3.0.0: - resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} - engines: {node: '>=12'} - whatwg-mimetype@4.0.0: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} engines: {node: '>=18'} - whatwg-url@11.0.0: - resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} - engines: {node: '>=12'} + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -10322,10 +9558,6 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - write-file-atomic@4.0.2: - resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - ws@8.18.2: resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==} engines: {node: '>=10.0.0'} @@ -10338,9 +9570,9 @@ packages: utf-8-validate: optional: true - xml-name-validator@4.0.0: - resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} - engines: {node: '>=12'} + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} xml2js@0.5.0: resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} @@ -10375,10 +9607,6 @@ packages: resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} engines: {node: '>=18'} - yaml@1.10.2: - resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} - engines: {node: '>= 6'} - yaml@2.8.0: resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==} engines: {node: '>= 14.6'} @@ -10511,6 +9739,14 @@ snapshots: - encoding - supports-color + '@asamuzakjp/css-color@3.2.0': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 10.4.3 + '@aws-crypto/crc32@3.0.0': dependencies: '@aws-crypto/util': 3.0.0 @@ -11146,91 +10382,6 @@ snapshots: dependencies: '@babel/types': 7.27.1 - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.27.1)': dependencies: '@babel/core': 7.27.1 @@ -11433,6 +10584,26 @@ snapshots: '@chevrotain/utils@11.0.3': {} + '@csstools/color-helpers@5.0.2': {} + + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-color-parser@3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.0.2 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-tokenizer@3.0.4': {} + '@dotenvx/dotenvx@1.44.2': dependencies: commander: 11.1.0 @@ -11477,7 +10648,7 @@ snapshots: '@esbuild-kit/core-utils@3.3.2': dependencies: - esbuild: 0.18.20 + esbuild: 0.25.5 source-map-support: 0.5.21 '@esbuild-kit/esm-loader@2.6.5': @@ -11485,219 +10656,78 @@ snapshots: '@esbuild-kit/core-utils': 3.3.2 get-tsconfig: 4.10.0 - '@esbuild/aix-ppc64@0.25.4': - optional: true - '@esbuild/aix-ppc64@0.25.5': optional: true - '@esbuild/android-arm64@0.18.20': - optional: true - - '@esbuild/android-arm64@0.25.4': - optional: true - '@esbuild/android-arm64@0.25.5': optional: true - '@esbuild/android-arm@0.18.20': - optional: true - - '@esbuild/android-arm@0.25.4': - optional: true - '@esbuild/android-arm@0.25.5': optional: true - '@esbuild/android-x64@0.18.20': - optional: true - - '@esbuild/android-x64@0.25.4': - optional: true - '@esbuild/android-x64@0.25.5': optional: true - '@esbuild/darwin-arm64@0.18.20': - optional: true - - '@esbuild/darwin-arm64@0.25.4': - optional: true - '@esbuild/darwin-arm64@0.25.5': optional: true - '@esbuild/darwin-x64@0.18.20': - optional: true - - '@esbuild/darwin-x64@0.25.4': - optional: true - '@esbuild/darwin-x64@0.25.5': optional: true - '@esbuild/freebsd-arm64@0.18.20': - optional: true - - '@esbuild/freebsd-arm64@0.25.4': - optional: true - '@esbuild/freebsd-arm64@0.25.5': optional: true - '@esbuild/freebsd-x64@0.18.20': - optional: true - - '@esbuild/freebsd-x64@0.25.4': - optional: true - '@esbuild/freebsd-x64@0.25.5': optional: true - '@esbuild/linux-arm64@0.18.20': - optional: true - - '@esbuild/linux-arm64@0.25.4': - optional: true - '@esbuild/linux-arm64@0.25.5': optional: true - '@esbuild/linux-arm@0.18.20': - optional: true - - '@esbuild/linux-arm@0.25.4': - optional: true - '@esbuild/linux-arm@0.25.5': optional: true - '@esbuild/linux-ia32@0.18.20': - optional: true - - '@esbuild/linux-ia32@0.25.4': - optional: true - '@esbuild/linux-ia32@0.25.5': optional: true - '@esbuild/linux-loong64@0.18.20': - optional: true - - '@esbuild/linux-loong64@0.25.4': - optional: true - '@esbuild/linux-loong64@0.25.5': optional: true - '@esbuild/linux-mips64el@0.18.20': - optional: true - - '@esbuild/linux-mips64el@0.25.4': - optional: true - '@esbuild/linux-mips64el@0.25.5': optional: true - '@esbuild/linux-ppc64@0.18.20': - optional: true - - '@esbuild/linux-ppc64@0.25.4': - optional: true - '@esbuild/linux-ppc64@0.25.5': optional: true - '@esbuild/linux-riscv64@0.18.20': - optional: true - - '@esbuild/linux-riscv64@0.25.4': - optional: true - '@esbuild/linux-riscv64@0.25.5': optional: true - '@esbuild/linux-s390x@0.18.20': - optional: true - - '@esbuild/linux-s390x@0.25.4': - optional: true - '@esbuild/linux-s390x@0.25.5': optional: true - '@esbuild/linux-x64@0.18.20': - optional: true - - '@esbuild/linux-x64@0.25.4': - optional: true - '@esbuild/linux-x64@0.25.5': optional: true - '@esbuild/netbsd-arm64@0.25.4': - optional: true - '@esbuild/netbsd-arm64@0.25.5': optional: true - '@esbuild/netbsd-x64@0.18.20': - optional: true - - '@esbuild/netbsd-x64@0.25.4': - optional: true - '@esbuild/netbsd-x64@0.25.5': optional: true - '@esbuild/openbsd-arm64@0.25.4': - optional: true - '@esbuild/openbsd-arm64@0.25.5': optional: true - '@esbuild/openbsd-x64@0.18.20': - optional: true - - '@esbuild/openbsd-x64@0.25.4': - optional: true - '@esbuild/openbsd-x64@0.25.5': optional: true - '@esbuild/sunos-x64@0.18.20': - optional: true - - '@esbuild/sunos-x64@0.25.4': - optional: true - '@esbuild/sunos-x64@0.25.5': optional: true - '@esbuild/win32-arm64@0.18.20': - optional: true - - '@esbuild/win32-arm64@0.25.4': - optional: true - '@esbuild/win32-arm64@0.25.5': optional: true - '@esbuild/win32-ia32@0.18.20': - optional: true - - '@esbuild/win32-ia32@0.25.4': - optional: true - '@esbuild/win32-ia32@0.25.5': optional: true - '@esbuild/win32-x64@0.18.20': - optional: true - - '@esbuild/win32-x64@0.25.4': - optional: true - '@esbuild/win32-x64@0.25.5': optional: true @@ -11771,8 +10801,6 @@ snapshots: lodash.isundefined: 3.0.1 lodash.uniq: 4.5.0 - '@fastify/busboy@2.1.1': {} - '@floating-ui/core@1.7.0': dependencies: '@floating-ui/utils': 0.2.9 @@ -11924,169 +10952,16 @@ snapshots: dependencies: minipass: 7.1.2 - '@istanbuljs/load-nyc-config@1.1.0': - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.1 - resolve-from: 5.0.0 - '@istanbuljs/schema@0.1.3': {} - '@jest/console@29.7.0': - dependencies: - '@jest/types': 29.6.3 - '@types/node': 20.17.57 - chalk: 4.1.2 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - - '@jest/core@29.7.0(babel-plugin-macros@3.1.0)': - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.17.57 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.9.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.17.57)(babel-plugin-macros@3.1.0) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - - '@jest/environment@29.7.0': - dependencies: - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.17.57 - jest-mock: 29.7.0 - '@jest/expect-utils@29.7.0': dependencies: jest-get-type: 29.6.3 - '@jest/expect@29.7.0': - dependencies: - expect: 29.7.0 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - '@jest/fake-timers@29.7.0': - dependencies: - '@jest/types': 29.6.3 - '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.17.57 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - - '@jest/globals@29.7.0': - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/types': 29.6.3 - jest-mock: 29.7.0 - transitivePeerDependencies: - - supports-color - - '@jest/reporters@29.7.0': - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.17.57 - chalk: 4.1.2 - collect-v8-coverage: 1.0.2 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.3 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.7 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - jest-worker: 29.7.0 - slash: 3.0.0 - string-length: 4.0.2 - strip-ansi: 6.0.1 - v8-to-istanbul: 9.3.0 - transitivePeerDependencies: - - supports-color - '@jest/schemas@29.6.3': dependencies: '@sinclair/typebox': 0.27.8 - '@jest/source-map@29.6.3': - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - callsites: 3.1.0 - graceful-fs: 4.2.11 - - '@jest/test-result@29.7.0': - dependencies: - '@jest/console': 29.7.0 - '@jest/types': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - collect-v8-coverage: 1.0.2 - - '@jest/test-sequencer@29.7.0': - dependencies: - '@jest/test-result': 29.7.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - slash: 3.0.0 - - '@jest/transform@29.7.0': - dependencies: - '@babel/core': 7.27.1 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - micromatch: 4.0.8 - pirates: 4.0.7 - slash: 3.0.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color - '@jest/types@29.6.3': dependencies: '@jest/schemas': 29.6.3 @@ -12188,6 +11063,24 @@ snapshots: '@libsql/win32-x64-msvc@0.5.13': optional: true + '@lmstudio/lms-isomorphic@0.4.5': + dependencies: + ws: 8.18.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@lmstudio/sdk@1.2.0': + dependencies: + '@lmstudio/lms-isomorphic': 0.4.5 + chalk: 4.1.2 + jsonschema: 1.5.0 + zod: 3.25.61 + zod-to-json-schema: 3.24.5(zod@3.25.61) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.27.4 @@ -12447,6 +11340,8 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true + '@polka/url@1.0.0-next.29': {} + '@puppeteer/browsers@2.10.5': dependencies: debug: 4.4.1(supports-color@8.1.1) @@ -12479,7 +11374,7 @@ snapshots: '@qdrant/openapi-typescript-fetch': 1.2.6 '@sevinf/maybe': 0.5.0 typescript: 5.8.3 - undici: 5.28.5 + undici: 6.21.3 '@qdrant/openapi-typescript-fetch@1.2.6': {} @@ -13186,14 +12081,6 @@ snapshots: '@sindresorhus/merge-streams@4.0.0': {} - '@sinonjs/commons@3.0.1': - dependencies: - type-detect: 4.0.8 - - '@sinonjs/fake-timers@10.3.0': - dependencies: - '@sinonjs/commons': 3.0.1 - '@smithy/abort-controller@2.2.0': dependencies: '@smithy/types': 2.12.0 @@ -13883,8 +12770,6 @@ snapshots: dependencies: '@testing-library/dom': 10.4.0 - '@tootallnate/once@2.0.0': {} - '@tootallnate/quickjs-emscripten@0.23.0': {} '@tybys/wasm-util@0.9.0': @@ -14063,10 +12948,6 @@ snapshots: '@types/minimatch': 5.1.2 '@types/node': 20.17.57 - '@types/graceful-fs@4.1.9': - dependencies: - '@types/node': 20.17.57 - '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.3 @@ -14088,14 +12969,10 @@ snapshots: '@types/js-cookie@2.2.7': {} - '@types/jsdom@20.0.1': - dependencies: - '@types/node': 20.17.57 - '@types/tough-cookie': 4.0.5 - parse5: 7.3.0 - '@types/json-schema@7.0.15': {} + '@types/katex@0.16.7': {} + '@types/lodash.debounce@4.0.9': dependencies: '@types/lodash': 4.17.17 @@ -14145,7 +13022,7 @@ snapshots: dependencies: undici-types: 6.19.8 - '@types/node@20.19.0': + '@types/node@20.19.1': dependencies: undici-types: 6.21.0 optional: true @@ -14154,9 +13031,6 @@ snapshots: dependencies: undici-types: 6.21.0 - '@types/parse-json@4.0.2': - optional: true - '@types/prop-types@15.7.14': {} '@types/ps-tree@1.1.6': {} @@ -14178,14 +13052,8 @@ snapshots: '@types/stylis@4.2.5': {} - '@types/testing-library__jest-dom@5.14.9': - dependencies: - '@types/jest': 29.5.14 - '@types/tmp@0.2.6': {} - '@types/tough-cookie@4.0.5': {} - '@types/trusted-types@2.0.7': optional: true @@ -14203,7 +13071,7 @@ snapshots: '@types/ws@8.18.1': dependencies: - '@types/node': 20.19.0 + '@types/node': 20.19.1 optional: true '@types/yargs-parser@21.0.3': {} @@ -14315,62 +13183,73 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitest/expect@3.2.3': + '@vitest/expect@3.2.4': dependencies: '@types/chai': 5.2.2 - '@vitest/spy': 3.2.3 - '@vitest/utils': 3.2.3 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.3(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))': + '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))': dependencies: - '@vitest/spy': 3.2.3 + '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: vite: 6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) - '@vitest/mocker@3.2.3(vite@6.3.5(@types/node@20.17.57)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))': + '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@20.17.57)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))': dependencies: - '@vitest/spy': 3.2.3 + '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: vite: 6.3.5(@types/node@20.17.57)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) - '@vitest/mocker@3.2.3(vite@6.3.5(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))': + '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0))': dependencies: - '@vitest/spy': 3.2.3 + '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: vite: 6.3.5(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) - '@vitest/pretty-format@3.2.3': + '@vitest/pretty-format@3.2.4': dependencies: tinyrainbow: 2.0.0 - '@vitest/runner@3.2.3': + '@vitest/runner@3.2.4': dependencies: - '@vitest/utils': 3.2.3 + '@vitest/utils': 3.2.4 pathe: 2.0.3 strip-literal: 3.0.0 - '@vitest/snapshot@3.2.3': + '@vitest/snapshot@3.2.4': dependencies: - '@vitest/pretty-format': 3.2.3 + '@vitest/pretty-format': 3.2.4 magic-string: 0.30.17 pathe: 2.0.3 - '@vitest/spy@3.2.3': + '@vitest/spy@3.2.4': dependencies: tinyspy: 4.0.3 - '@vitest/utils@3.2.3': + '@vitest/ui@3.2.4(vitest@3.2.4)': dependencies: - '@vitest/pretty-format': 3.2.3 - loupe: 3.1.3 + '@vitest/utils': 3.2.4 + fflate: 0.8.2 + flatted: 3.3.3 + pathe: 2.0.3 + sirv: 3.0.1 + tinyglobby: 0.2.14 + tinyrainbow: 2.0.0 + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.15.29)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + + '@vitest/utils@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + loupe: 3.1.4 tinyrainbow: 2.0.0 '@vscode/codicons@0.0.36': {} @@ -14480,8 +13359,6 @@ snapshots: '@xobotyi/scrollbar-width@1.9.5': {} - abab@2.0.6: {} - abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -14491,11 +13368,6 @@ snapshots: mime-types: 3.0.1 negotiator: 1.0.0 - acorn-globals@7.0.1: - dependencies: - acorn: 8.14.1 - acorn-walk: 8.3.4 - acorn-jsx@5.3.2(acorn@8.14.1): dependencies: acorn: 8.14.1 @@ -14504,20 +13376,10 @@ snapshots: dependencies: acorn: 8.15.0 - acorn-walk@8.3.4: - dependencies: - acorn: 8.14.1 - acorn@8.14.1: {} acorn@8.15.0: {} - agent-base@6.0.2: - dependencies: - debug: 4.4.1(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - agent-base@7.1.3: {} agentkeepalive@4.6.0: @@ -14533,10 +13395,6 @@ snapshots: ansi-colors@4.1.3: {} - ansi-escapes@4.3.2: - dependencies: - type-fest: 0.21.3 - ansi-escapes@7.0.0: dependencies: environment: 1.1.0 @@ -14722,73 +13580,11 @@ snapshots: b4a@1.6.7: {} - babel-jest@29.7.0(@babel/core@7.27.1): - dependencies: - '@babel/core': 7.27.1 - '@jest/transform': 29.7.0 - '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.27.1) - chalk: 4.1.2 - graceful-fs: 4.2.11 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-istanbul@6.1.1: - dependencies: - '@babel/helper-plugin-utils': 7.27.1 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.1 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-jest-hoist@29.6.3: - dependencies: - '@babel/template': 7.27.2 - '@babel/types': 7.27.1 - '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.7 - - babel-plugin-macros@3.1.0: - dependencies: - '@babel/runtime': 7.27.6 - cosmiconfig: 7.1.0 - resolve: 1.22.10 - optional: true - - babel-preset-current-node-syntax@1.1.0(@babel/core@7.27.1): - dependencies: - '@babel/core': 7.27.1 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.27.1) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.27.1) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.27.1) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.27.1) - '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.27.1) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.27.1) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.27.1) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.27.1) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.27.1) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.27.1) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.27.1) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.27.1) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.27.1) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.27.1) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.27.1) - - babel-preset-jest@29.6.3(@babel/core@7.27.1): - dependencies: - '@babel/core': 7.27.1 - babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.27.1) - bail@1.0.5: {} bail@2.0.2: {} - balanced-match@1.0.2: {} + balanced-match@3.0.1: {} bare-events@2.5.4: optional: true @@ -14873,14 +13669,9 @@ snapshots: bowser@2.11.0: {} - brace-expansion@1.1.11: + brace-expansion@4.0.1: dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.0.1: - dependencies: - balanced-match: 1.0.2 + balanced-match: 3.0.1 braces@3.0.3: dependencies: @@ -14895,14 +13686,6 @@ snapshots: node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.24.5) - bs-logger@0.2.6: - dependencies: - fast-json-stable-stringify: 2.1.0 - - bser@2.1.1: - dependencies: - node-int64: 0.4.0 - buffer-crc32@0.2.13: {} buffer-equal-constant-time@1.0.1: {} @@ -14970,8 +13753,6 @@ snapshots: camelcase-css@2.0.1: {} - camelcase@5.3.1: {} - camelcase@6.3.0: {} camelize@1.0.1: {} @@ -15010,8 +13791,6 @@ snapshots: chalk@5.4.1: {} - char-regex@1.0.2: {} - character-entities-html4@2.1.0: {} character-entities-legacy@1.1.4: {} @@ -15091,12 +13870,16 @@ snapshots: mitt: 3.0.1 zod: 3.23.8 + chromium-bidi@5.1.0(devtools-protocol@0.0.1452169): + dependencies: + devtools-protocol: 0.0.1452169 + mitt: 3.0.1 + zod: 3.25.61 + ci-info@2.0.0: {} ci-info@3.9.0: {} - cjs-module-lexer@1.4.3: {} - class-variance-authority@0.7.1: dependencies: clsx: 2.1.1 @@ -15159,12 +13942,8 @@ snapshots: - '@types/react' - '@types/react-dom' - co@4.6.0: {} - cockatiel@3.2.1: {} - collect-v8-coverage@1.0.2: {} - color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -15222,8 +14001,6 @@ snapshots: normalize-path: 3.0.0 readable-stream: 3.6.2 - concat-map@0.0.1: {} - confbox@0.1.8: {} confbox@0.2.2: {} @@ -15275,15 +14052,6 @@ snapshots: dependencies: layout-base: 2.0.1 - cosmiconfig@7.1.0: - dependencies: - '@types/parse-json': 4.0.2 - import-fresh: 3.3.1 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 1.10.2 - optional: true - crc-32@1.2.2: {} crc32-stream@4.0.3: @@ -15291,21 +14059,6 @@ snapshots: crc-32: 1.2.2 readable-stream: 3.6.2 - create-jest@29.7.0(@types/node@20.17.57)(babel-plugin-macros@3.1.0): - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.17.57)(babel-plugin-macros@3.1.0) - jest-util: 29.7.0 - prompts: 2.4.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - cross-fetch@4.0.0: dependencies: node-fetch: 2.7.0 @@ -15349,13 +14102,10 @@ snapshots: cssesc@3.0.0: {} - cssom@0.3.8: {} - - cssom@0.5.0: {} - - cssstyle@2.3.0: + cssstyle@4.4.0: dependencies: - cssom: 0.3.8 + '@asamuzakjp/css-color': 3.2.0 + rrweb-cssom: 0.8.0 csstype@3.1.3: {} @@ -15548,11 +14298,10 @@ snapshots: data-uri-to-buffer@6.0.2: {} - data-urls@3.0.2: + data-urls@5.0.0: dependencies: - abab: 2.0.6 - whatwg-mimetype: 3.0.0 - whatwg-url: 11.0.0 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 data-view-buffer@1.0.2: dependencies: @@ -15603,10 +14352,6 @@ snapshots: mimic-response: 3.1.0 optional: true - dedent@1.6.0(babel-plugin-macros@3.1.0): - optionalDependencies: - babel-plugin-macros: 3.1.0 - deep-eql@5.0.2: {} deep-extend@0.6.0: @@ -15614,8 +14359,6 @@ snapshots: deep-is@0.1.4: {} - deepmerge@4.3.1: {} - default-browser-id@5.0.0: {} default-browser@5.2.1: @@ -15664,8 +14407,6 @@ snapshots: detect-libc@2.0.4: {} - detect-newline@3.1.0: {} - detect-node-es@1.1.0: {} devlop@1.1.0: @@ -15674,6 +14415,8 @@ snapshots: devtools-protocol@0.0.1367902: {} + devtools-protocol@0.0.1452169: {} + didyoumean@1.2.2: {} diff-match-patch@1.0.5: {} @@ -15711,10 +14454,6 @@ snapshots: domelementtype@2.3.0: {} - domexception@4.0.0: - dependencies: - webidl-conversions: 7.0.0 - domhandler@5.0.3: dependencies: domelementtype: 2.3.0 @@ -15784,10 +14523,6 @@ snapshots: eight-colors@1.3.1: {} - ejs@3.1.10: - dependencies: - jake: 10.9.2 - electron-to-chromium@1.5.152: {} embla-carousel-auto-scroll@8.6.0(embla-carousel@8.6.0): @@ -15810,8 +14545,6 @@ snapshots: embla-carousel@8.6.0: {} - emittery@0.13.1: {} - emoji-regex@10.4.0: {} emoji-regex@8.0.0: {} @@ -15848,10 +14581,6 @@ snapshots: environment@1.1.0: {} - error-ex@1.3.2: - dependencies: - is-arrayish: 0.2.1 - error-stack-parser@2.1.4: dependencies: stackframe: 1.3.4 @@ -15963,59 +14692,6 @@ snapshots: transitivePeerDependencies: - supports-color - esbuild@0.18.20: - optionalDependencies: - '@esbuild/android-arm': 0.18.20 - '@esbuild/android-arm64': 0.18.20 - '@esbuild/android-x64': 0.18.20 - '@esbuild/darwin-arm64': 0.18.20 - '@esbuild/darwin-x64': 0.18.20 - '@esbuild/freebsd-arm64': 0.18.20 - '@esbuild/freebsd-x64': 0.18.20 - '@esbuild/linux-arm': 0.18.20 - '@esbuild/linux-arm64': 0.18.20 - '@esbuild/linux-ia32': 0.18.20 - '@esbuild/linux-loong64': 0.18.20 - '@esbuild/linux-mips64el': 0.18.20 - '@esbuild/linux-ppc64': 0.18.20 - '@esbuild/linux-riscv64': 0.18.20 - '@esbuild/linux-s390x': 0.18.20 - '@esbuild/linux-x64': 0.18.20 - '@esbuild/netbsd-x64': 0.18.20 - '@esbuild/openbsd-x64': 0.18.20 - '@esbuild/sunos-x64': 0.18.20 - '@esbuild/win32-arm64': 0.18.20 - '@esbuild/win32-ia32': 0.18.20 - '@esbuild/win32-x64': 0.18.20 - - esbuild@0.25.4: - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.4 - '@esbuild/android-arm': 0.25.4 - '@esbuild/android-arm64': 0.25.4 - '@esbuild/android-x64': 0.25.4 - '@esbuild/darwin-arm64': 0.25.4 - '@esbuild/darwin-x64': 0.25.4 - '@esbuild/freebsd-arm64': 0.25.4 - '@esbuild/freebsd-x64': 0.25.4 - '@esbuild/linux-arm': 0.25.4 - '@esbuild/linux-arm64': 0.25.4 - '@esbuild/linux-ia32': 0.25.4 - '@esbuild/linux-loong64': 0.25.4 - '@esbuild/linux-mips64el': 0.25.4 - '@esbuild/linux-ppc64': 0.25.4 - '@esbuild/linux-riscv64': 0.25.4 - '@esbuild/linux-s390x': 0.25.4 - '@esbuild/linux-x64': 0.25.4 - '@esbuild/netbsd-arm64': 0.25.4 - '@esbuild/netbsd-x64': 0.25.4 - '@esbuild/openbsd-arm64': 0.25.4 - '@esbuild/openbsd-x64': 0.25.4 - '@esbuild/sunos-x64': 0.25.4 - '@esbuild/win32-arm64': 0.25.4 - '@esbuild/win32-ia32': 0.25.4 - '@esbuild/win32-x64': 0.25.4 - esbuild@0.25.5: optionalDependencies: '@esbuild/aix-ppc64': 0.25.5 @@ -16331,8 +15007,6 @@ snapshots: exenv-es6@1.1.1: {} - exit@0.1.2: {} - expand-template@2.0.3: optional: true @@ -16453,10 +15127,6 @@ snapshots: dependencies: reusify: 1.1.0 - fb-watchman@2.0.2: - dependencies: - bser: 2.1.1 - fd-package-json@2.0.0: dependencies: walk-up-path: 4.0.0 @@ -16481,6 +15151,8 @@ snapshots: fflate@0.4.8: {} + fflate@0.8.2: {} + figures@6.1.0: dependencies: is-unicode-supported: 2.1.0 @@ -16492,10 +15164,6 @@ snapshots: file-uri-to-path@1.0.0: optional: true - filelist@1.0.4: - dependencies: - minimatch: 5.1.6 - fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -16697,8 +15365,6 @@ snapshots: get-nonce@1.0.1: {} - get-package-type@0.1.0: {} - get-proto@1.0.1: dependencies: dunder-proto: 1.0.1 @@ -16863,10 +15529,47 @@ snapshots: unist-util-is: 4.1.0 web-namespaces: 1.1.4 + hast-util-from-dom@5.0.1: + dependencies: + '@types/hast': 3.0.4 + hastscript: 9.0.1 + web-namespaces: 2.0.1 + + hast-util-from-html-isomorphic@2.0.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-from-dom: 5.0.1 + hast-util-from-html: 2.0.3 + unist-util-remove-position: 5.0.0 + + hast-util-from-html@2.0.3: + dependencies: + '@types/hast': 3.0.4 + devlop: 1.1.0 + hast-util-from-parse5: 8.0.3 + parse5: 7.3.0 + vfile: 6.0.3 + vfile-message: 4.0.2 + + hast-util-from-parse5@8.0.3: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + devlop: 1.1.0 + hastscript: 9.0.1 + property-information: 7.1.0 + vfile: 6.0.3 + vfile-location: 5.0.3 + web-namespaces: 2.0.1 + hast-util-is-element@3.0.0: dependencies: '@types/hast': 3.0.4 + hast-util-parse-selector@4.0.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-to-html@9.0.5: dependencies: '@types/hast': 3.0.4 @@ -16912,6 +15615,14 @@ snapshots: dependencies: '@types/hast': 3.0.4 + hastscript@9.0.1: + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 4.0.0 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + he@1.2.0: {} highlight.js@11.11.1: {} @@ -16922,9 +15633,9 @@ snapshots: howler@2.2.4: {} - html-encoding-sniffer@3.0.0: + html-encoding-sniffer@4.0.0: dependencies: - whatwg-encoding: 2.0.0 + whatwg-encoding: 3.1.1 html-escaper@2.0.2: {} @@ -16951,14 +15662,6 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 - http-proxy-agent@5.0.0: - dependencies: - '@tootallnate/once': 2.0.0 - agent-base: 6.0.2 - debug: 4.4.1(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 @@ -16966,13 +15669,6 @@ snapshots: transitivePeerDependencies: - supports-color - https-proxy-agent@5.0.1: - dependencies: - agent-base: 6.0.2 - debug: 4.4.1(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.3 @@ -17035,11 +15731,6 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 - import-local@3.2.0: - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - imurmurhash@0.1.4: {} indent-string@4.0.0: {} @@ -17099,8 +15790,6 @@ snapshots: call-bound: 1.0.4 get-intrinsic: 1.3.0 - is-arrayish@0.2.1: {} - is-arrayish@0.3.2: optional: true @@ -17168,8 +15857,6 @@ snapshots: dependencies: get-east-asian-width: 1.3.0 - is-generator-fn@2.1.0: {} - is-generator-function@1.1.0: dependencies: call-bound: 1.0.4 @@ -17296,40 +15983,12 @@ snapshots: istanbul-lib-coverage@3.2.2: {} - istanbul-lib-instrument@5.2.1: - dependencies: - '@babel/core': 7.27.1 - '@babel/parser': 7.27.2 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - istanbul-lib-instrument@6.0.3: - dependencies: - '@babel/core': 7.27.1 - '@babel/parser': 7.27.2 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 7.7.2 - transitivePeerDependencies: - - supports-color - istanbul-lib-report@3.0.1: dependencies: istanbul-lib-coverage: 3.2.2 make-dir: 4.0.0 supports-color: 7.2.0 - istanbul-lib-source-maps@4.0.1: - dependencies: - debug: 4.4.1(supports-color@8.1.1) - istanbul-lib-coverage: 3.2.2 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - istanbul-reports@3.1.7: dependencies: html-escaper: 2.0.2 @@ -17354,94 +16013,6 @@ snapshots: dependencies: '@isaacs/cliui': 8.0.2 - jake@10.9.2: - dependencies: - async: 3.2.6 - chalk: 4.1.2 - filelist: 1.0.4 - minimatch: 3.1.2 - - jest-changed-files@29.7.0: - dependencies: - execa: 5.1.1 - jest-util: 29.7.0 - p-limit: 3.1.0 - - jest-circus@29.7.0(babel-plugin-macros@3.1.0): - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.17.57 - chalk: 4.1.2 - co: 4.6.0 - dedent: 1.6.0(babel-plugin-macros@3.1.0) - is-generator-fn: 2.1.0 - jest-each: 29.7.0 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - p-limit: 3.1.0 - pretty-format: 29.7.0 - pure-rand: 6.1.0 - slash: 3.0.0 - stack-utils: 2.0.6 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-cli@29.7.0(@types/node@20.17.57)(babel-plugin-macros@3.1.0): - dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0) - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.17.57)(babel-plugin-macros@3.1.0) - exit: 0.1.2 - import-local: 3.2.0 - jest-config: 29.7.0(@types/node@20.17.57)(babel-plugin-macros@3.1.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - jest-config@29.7.0(@types/node@20.17.57)(babel-plugin-macros@3.1.0): - dependencies: - '@babel/core': 7.27.1 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.27.1) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0(babel-plugin-macros@3.1.0) - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 20.17.57 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - jest-diff@29.7.0: dependencies: chalk: 4.1.2 @@ -17449,65 +16020,8 @@ snapshots: jest-get-type: 29.6.3 pretty-format: 29.7.0 - jest-docblock@29.7.0: - dependencies: - detect-newline: 3.1.0 - - jest-each@29.7.0: - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - jest-get-type: 29.6.3 - jest-util: 29.7.0 - pretty-format: 29.7.0 - - jest-environment-jsdom@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/jsdom': 20.0.1 - '@types/node': 20.17.57 - jest-mock: 29.7.0 - jest-util: 29.7.0 - jsdom: 20.0.3 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - jest-environment-node@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.17.57 - jest-mock: 29.7.0 - jest-util: 29.7.0 - jest-get-type@29.6.3: {} - jest-haste-map@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/graceful-fs': 4.1.9 - '@types/node': 20.17.57 - anymatch: 3.1.3 - fb-watchman: 2.0.2 - graceful-fs: 4.2.11 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - jest-worker: 29.7.0 - micromatch: 4.0.8 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.3 - - jest-leak-detector@29.7.0: - dependencies: - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - jest-matcher-utils@29.7.0: dependencies: chalk: 4.1.2 @@ -17527,117 +16041,6 @@ snapshots: slash: 3.0.0 stack-utils: 2.0.6 - jest-mock@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/node': 20.17.57 - jest-util: 29.7.0 - - jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): - optionalDependencies: - jest-resolve: 29.7.0 - - jest-regex-util@29.6.3: {} - - jest-resolve-dependencies@29.7.0: - dependencies: - jest-regex-util: 29.6.3 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - jest-resolve@29.7.0: - dependencies: - chalk: 4.1.2 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - resolve: 1.22.10 - resolve.exports: 2.0.3 - slash: 3.0.0 - - jest-runner@29.7.0: - dependencies: - '@jest/console': 29.7.0 - '@jest/environment': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.17.57 - chalk: 4.1.2 - emittery: 0.13.1 - graceful-fs: 4.2.11 - jest-docblock: 29.7.0 - jest-environment-node: 29.7.0 - jest-haste-map: 29.7.0 - jest-leak-detector: 29.7.0 - jest-message-util: 29.7.0 - jest-resolve: 29.7.0 - jest-runtime: 29.7.0 - jest-util: 29.7.0 - jest-watcher: 29.7.0 - jest-worker: 29.7.0 - p-limit: 3.1.0 - source-map-support: 0.5.13 - transitivePeerDependencies: - - supports-color - - jest-runtime@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/globals': 29.7.0 - '@jest/source-map': 29.6.3 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.17.57 - chalk: 4.1.2 - cjs-module-lexer: 1.4.3 - collect-v8-coverage: 1.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - strip-bom: 4.0.0 - transitivePeerDependencies: - - supports-color - - jest-simple-dot-reporter@1.0.5: {} - - jest-snapshot@29.7.0: - dependencies: - '@babel/core': 7.27.1 - '@babel/generator': 7.27.1 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.1) - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.1) - '@babel/types': 7.27.1 - '@jest/expect-utils': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.27.1) - chalk: 4.1.2 - expect: 29.7.0 - graceful-fs: 4.2.11 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - natural-compare: 1.4.0 - pretty-format: 29.7.0 - semver: 7.7.2 - transitivePeerDependencies: - - supports-color - jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 @@ -17647,45 +16050,6 @@ snapshots: graceful-fs: 4.2.11 picomatch: 2.3.1 - jest-validate@29.7.0: - dependencies: - '@jest/types': 29.6.3 - camelcase: 6.3.0 - chalk: 4.1.2 - jest-get-type: 29.6.3 - leven: 3.1.0 - pretty-format: 29.7.0 - - jest-watcher@29.7.0: - dependencies: - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.17.57 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 29.7.0 - string-length: 4.0.2 - - jest-worker@29.7.0: - dependencies: - '@types/node': 20.17.57 - jest-util: 29.7.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - - jest@29.7.0(@types/node@20.17.57)(babel-plugin-macros@3.1.0): - dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0) - '@jest/types': 29.6.3 - import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@20.17.57)(babel-plugin-macros@3.1.0) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - jiti@1.21.7: {} jiti@2.4.2: {} @@ -17718,34 +16082,28 @@ snapshots: jsbn@1.1.0: {} - jsdom@20.0.3: + jsdom@26.1.0: dependencies: - abab: 2.0.6 - acorn: 8.14.1 - acorn-globals: 7.0.1 - cssom: 0.5.0 - cssstyle: 2.3.0 - data-urls: 3.0.2 + cssstyle: 4.4.0 + data-urls: 5.0.0 decimal.js: 10.5.0 - domexception: 4.0.0 - escodegen: 2.1.0 - form-data: 4.0.2 - html-encoding-sniffer: 3.0.0 - http-proxy-agent: 5.0.0 - https-proxy-agent: 5.0.1 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 is-potential-custom-element-name: 1.0.1 nwsapi: 2.2.20 parse5: 7.3.0 + rrweb-cssom: 0.8.0 saxes: 6.0.0 symbol-tree: 3.2.4 - tough-cookie: 4.1.4 - w3c-xmlserializer: 4.0.0 + tough-cookie: 5.1.2 + w3c-xmlserializer: 5.0.0 webidl-conversions: 7.0.0 - whatwg-encoding: 2.0.0 - whatwg-mimetype: 3.0.0 - whatwg-url: 11.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 ws: 8.18.2 - xml-name-validator: 4.0.0 + xml-name-validator: 5.0.0 transitivePeerDependencies: - bufferutil - supports-color @@ -17759,8 +16117,6 @@ snapshots: json-buffer@3.0.1: {} - json-parse-even-better-errors@2.3.1: {} - json-parse-even-better-errors@4.0.0: {} json-schema-traverse@0.4.1: {} @@ -17777,6 +16133,8 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + jsonschema@1.5.0: {} + jsonwebtoken@9.0.2: dependencies: jws: 3.2.2 @@ -17846,8 +16204,6 @@ snapshots: kind-of@6.0.3: {} - kleur@3.0.3: {} - knip@5.60.2(@types/node@22.15.29)(typescript@5.8.3): dependencies: '@nodelib/fs.walk': 1.2.8 @@ -18091,8 +16447,6 @@ snapshots: lodash.isundefined@3.0.1: {} - lodash.memoize@4.1.2: {} - lodash.merge@4.6.2: {} lodash.once@4.1.1: {} @@ -18139,6 +16493,8 @@ snapshots: loupe@3.1.3: {} + loupe@3.1.4: {} + lowlight@3.3.0: dependencies: '@types/hast': 3.0.4 @@ -18159,7 +16515,7 @@ snapshots: lru-cache@7.18.3: {} - lucide-react@0.513.0(react@18.3.1): + lucide-react@0.518.0(react@18.3.1): dependencies: react: 18.3.1 @@ -18175,12 +16531,6 @@ snapshots: dependencies: semver: 7.7.2 - make-error@1.3.6: {} - - makeerror@1.0.12: - dependencies: - tmpl: 1.0.5 - mammoth@1.9.0: dependencies: '@xmldom/xmldom': 0.8.10 @@ -18306,6 +16656,18 @@ snapshots: transitivePeerDependencies: - supports-color + mdast-util-math@3.0.0: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + longest-streak: 3.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + unist-util-remove-position: 5.0.0 + transitivePeerDependencies: + - supports-color + mdast-util-mdx-expression@2.0.1: dependencies: '@types/estree-jsx': 1.0.5 @@ -18509,6 +16871,16 @@ snapshots: micromark-util-combine-extensions: 2.0.1 micromark-util-types: 2.0.2 + micromark-extension-math@3.1.0: + dependencies: + '@types/katex': 0.16.7 + devlop: 1.1.0 + katex: 0.16.22 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + micromark-factory-destination@2.0.1: dependencies: micromark-util-character: 2.1.1 @@ -18662,19 +17034,19 @@ snapshots: minimatch@10.0.1: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 4.0.1 minimatch@3.1.2: dependencies: - brace-expansion: 1.1.11 + brace-expansion: 4.0.1 minimatch@5.1.6: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 4.0.1 minimatch@9.0.5: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 4.0.1 minimist@1.2.8: {} @@ -18741,6 +17113,8 @@ snapshots: mri@1.2.0: {} + mrmime@2.0.1: {} + ms@2.1.3: {} mute-stream@0.0.8: {} @@ -18840,8 +17214,6 @@ snapshots: formdata-polyfill: 4.0.10 optional: true - node-int64@0.4.0: {} - node-ipc@12.0.0: dependencies: event-pubsub: 5.0.3 @@ -18973,20 +17345,10 @@ snapshots: is-inside-container: 1.0.0 is-wsl: 3.1.0 - openai@4.103.0(ws@8.18.2)(zod@3.25.61): - dependencies: - '@types/node': 18.19.100 - '@types/node-fetch': 2.6.12 - abort-controller: 3.0.0 - agentkeepalive: 4.6.0 - form-data-encoder: 1.7.2 - formdata-node: 4.4.1 - node-fetch: 2.7.0 + openai@5.5.1(ws@8.18.2)(zod@3.25.61): optionalDependencies: ws: 8.18.2 zod: 3.25.61 - transitivePeerDependencies: - - encoding option@0.2.4: {} @@ -19151,13 +17513,6 @@ snapshots: is-decimal: 2.0.1 is-hexadecimal: 2.0.1 - parse-json@5.2.0: - dependencies: - '@babel/code-frame': 7.27.1 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - parse-ms@4.0.0: {} parse-semver@1.1.1: @@ -19236,14 +17591,8 @@ snapshots: pirates@4.0.7: {} - pkce-challenge@4.1.0: {} - pkce-challenge@5.0.0: {} - pkg-dir@4.2.0: - dependencies: - find-up: 4.1.0 - pkg-types@1.3.1: dependencies: confbox: 0.1.8 @@ -19350,11 +17699,7 @@ snapshots: preact: 10.26.6 web-vitals: 4.2.4 - posthog-node@4.17.2: - dependencies: - axios: 1.9.0 - transitivePeerDependencies: - - debug + posthog-node@5.1.1: {} preact@10.26.6: {} @@ -19382,7 +17727,7 @@ snapshots: prettier@3.5.3: {} - pretty-bytes@6.1.1: {} + pretty-bytes@7.0.0: {} pretty-format@27.5.1: dependencies: @@ -19407,11 +17752,6 @@ snapshots: promise-limit@2.7.0: optional: true - prompts@2.4.2: - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - prop-types@15.8.1: dependencies: loose-envify: 1.4.0 @@ -19450,10 +17790,6 @@ snapshots: dependencies: event-stream: 3.3.4 - psl@1.15.0: - dependencies: - punycode: 2.3.1 - pump@3.0.2: dependencies: end-of-stream: 1.4.4 @@ -19463,12 +17799,12 @@ snapshots: punycode@2.3.1: {} - puppeteer-chromium-resolver@23.0.0: + puppeteer-chromium-resolver@24.0.1: dependencies: '@puppeteer/browsers': 2.10.5 eight-colors: 1.3.1 gauge: 5.0.2 - puppeteer-core: 23.11.1 + puppeteer-core: 24.10.2 transitivePeerDependencies: - bare-buffer - bufferutil @@ -19489,7 +17825,19 @@ snapshots: - supports-color - utf-8-validate - pure-rand@6.1.0: {} + puppeteer-core@24.10.2: + dependencies: + '@puppeteer/browsers': 2.10.5 + chromium-bidi: 5.1.0(devtools-protocol@0.0.1452169) + debug: 4.4.1(supports-color@8.1.1) + devtools-protocol: 0.0.1452169 + typed-query-selector: 2.12.0 + ws: 8.18.2 + transitivePeerDependencies: + - bare-buffer + - bufferutil + - supports-color + - utf-8-validate qs@6.14.0: dependencies: @@ -19497,8 +17845,6 @@ snapshots: quansync@0.2.10: {} - querystringify@2.2.0: {} - queue-microtask@1.2.3: {} randombytes@2.1.0: @@ -19791,6 +18137,16 @@ snapshots: unist-util-visit: 5.0.0 vfile: 6.0.3 + rehype-katex@7.0.1: + dependencies: + '@types/hast': 3.0.4 + '@types/katex': 0.16.7 + hast-util-from-html-isomorphic: 2.0.0 + hast-util-to-text: 4.0.2 + katex: 0.16.22 + unist-util-visit-parents: 6.0.1 + vfile: 6.0.3 + rehype-react@6.2.1: dependencies: '@mapbox/hast-util-table-cell-style': 0.2.1 @@ -19807,6 +18163,15 @@ snapshots: transitivePeerDependencies: - supports-color + remark-math@6.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-math: 3.0.0 + micromark-extension-math: 3.1.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + remark-parse@11.0.0: dependencies: '@types/mdast': 4.0.4 @@ -19844,22 +18209,14 @@ snapshots: require-directory@2.1.1: {} - requires-port@1.0.0: {} - resize-observer-polyfill@1.5.1: {} - resolve-cwd@3.0.0: - dependencies: - resolve-from: 5.0.0 - resolve-from@4.0.0: {} resolve-from@5.0.0: {} resolve-pkg-maps@1.0.0: {} - resolve.exports@2.0.3: {} - resolve@1.22.10: dependencies: is-core-module: 2.16.1 @@ -19935,6 +18292,8 @@ snapshots: transitivePeerDependencies: - supports-color + rrweb-cssom@0.8.0: {} + rtl-css-js@1.16.1: dependencies: '@babel/runtime': 7.27.4 @@ -20020,9 +18379,9 @@ snapshots: transitivePeerDependencies: - supports-color - serialize-error@11.0.3: + serialize-error@12.0.0: dependencies: - type-fest: 2.19.0 + type-fest: 4.41.0 serialize-javascript@6.0.2: dependencies: @@ -20179,7 +18538,11 @@ snapshots: is-arrayish: 0.3.2 optional: true - sisteransi@1.0.5: {} + sirv@3.0.1: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 slash@3.0.0: {} @@ -20219,11 +18582,6 @@ snapshots: source-map-js@1.2.1: {} - source-map-support@0.5.13: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 @@ -20302,11 +18660,6 @@ snapshots: string-argv@0.3.2: {} - string-length@4.0.2: - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 - string-similarity@4.0.4: {} string-width@4.2.3: @@ -20392,8 +18745,6 @@ snapshots: strip-bom@3.0.0: {} - strip-bom@4.0.0: {} - strip-bom@5.0.0: {} strip-final-newline@2.0.0: {} @@ -20490,8 +18841,6 @@ snapshots: tabbable@5.3.3: {} - tailwind-merge@2.6.0: {} - tailwind-merge@3.3.0: {} tailwindcss-animate@1.0.7(tailwindcss@3.4.17): @@ -20617,20 +18966,24 @@ snapshots: fdir: 6.4.6(picomatch@4.0.2) picomatch: 4.0.2 - tinypool@1.1.0: {} + tinypool@1.1.1: {} tinyrainbow@2.0.0: {} tinyspy@4.0.3: {} + tldts-core@6.1.86: {} + + tldts@6.1.86: + dependencies: + tldts-core: 6.1.86 + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 tmp@0.2.3: {} - tmpl@1.0.5: {} - to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -20639,12 +18992,11 @@ snapshots: toidentifier@1.0.1: {} - tough-cookie@4.1.4: + totalist@3.0.1: {} + + tough-cookie@5.1.2: dependencies: - psl: 1.15.0 - punycode: 2.3.1 - universalify: 0.2.0 - url-parse: 1.5.10 + tldts: 6.1.86 tr46@0.0.3: {} @@ -20652,7 +19004,7 @@ snapshots: dependencies: punycode: 2.3.1 - tr46@3.0.0: + tr46@5.1.1: dependencies: punycode: 2.3.1 @@ -20682,27 +19034,6 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.3.3(@babel/core@7.27.1)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.1))(esbuild@0.25.5)(jest@29.7.0(@types/node@20.17.57)(babel-plugin-macros@3.1.0))(typescript@5.8.3): - dependencies: - bs-logger: 0.2.6 - ejs: 3.1.10 - fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.17.57)(babel-plugin-macros@3.1.0) - jest-util: 29.7.0 - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.7.2 - type-fest: 4.41.0 - typescript: 5.8.3 - yargs-parser: 21.1.1 - optionalDependencies: - '@babel/core': 7.27.1 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.27.1) - esbuild: 0.25.5 - tslib@1.14.1: {} tslib@2.6.2: {} @@ -20739,7 +19070,7 @@ snapshots: tsx@4.19.4: dependencies: - esbuild: 0.25.4 + esbuild: 0.25.5 get-tsconfig: 4.10.0 optionalDependencies: fsevents: 2.3.3 @@ -20786,12 +19117,6 @@ snapshots: dependencies: prelude-ls: 1.2.1 - type-detect@4.0.8: {} - - type-fest@0.21.3: {} - - type-fest@2.19.0: {} - type-fest@4.41.0: {} type-is@2.0.1: @@ -20877,10 +19202,6 @@ snapshots: undici-types@6.21.0: {} - undici@5.28.5: - dependencies: - '@fastify/busboy': 2.1.1 - undici@6.21.3: {} unicorn-magic@0.3.0: {} @@ -20928,6 +19249,11 @@ snapshots: dependencies: '@types/unist': 3.0.3 + unist-util-remove-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-visit: 5.0.0 + unist-util-stringify-position@2.0.3: dependencies: '@types/unist': 2.0.11 @@ -20968,8 +19294,6 @@ snapshots: universalify@0.1.2: {} - universalify@0.2.0: {} - unpipe@1.0.0: {} untildify@4.0.0: {} @@ -20999,11 +19323,6 @@ snapshots: url-join@4.0.1: {} - url-parse@1.5.10: - dependencies: - querystringify: 2.2.0 - requires-port: 1.0.0 - use-callback-ref@1.3.3(@types/react@18.3.23)(react@18.3.1): dependencies: react: 18.3.1 @@ -21070,6 +19389,11 @@ snapshots: - '@types/react' - '@types/react-dom' + vfile-location@5.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile: 6.0.3 + vfile-message@2.0.4: dependencies: '@types/unist': 2.0.11 @@ -21109,7 +19433,7 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite-node@3.2.3(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0): + vite-node@3.2.4(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0): dependencies: cac: 6.7.14 debug: 4.4.1(supports-color@8.1.1) @@ -21130,7 +19454,7 @@ snapshots: - tsx - yaml - vite-node@3.2.3(@types/node@20.17.57)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0): + vite-node@3.2.4(@types/node@20.17.57)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0): dependencies: cac: 6.7.14 debug: 4.4.1(supports-color@8.1.1) @@ -21151,7 +19475,7 @@ snapshots: - tsx - yaml - vite-node@3.2.3(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0): + vite-node@3.2.4(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0): dependencies: cac: 6.7.14 debug: 4.4.1(supports-color@8.1.1) @@ -21220,16 +19544,16 @@ snapshots: tsx: 4.19.4 yaml: 2.8.0 - vitest@3.2.3(@types/debug@4.1.12)(@types/node@20.17.50)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.17.50)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0): dependencies: '@types/chai': 5.2.2 - '@vitest/expect': 3.2.3 - '@vitest/mocker': 3.2.3(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)) - '@vitest/pretty-format': 3.2.3 - '@vitest/runner': 3.2.3 - '@vitest/snapshot': 3.2.3 - '@vitest/spy': 3.2.3 - '@vitest/utils': 3.2.3 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 chai: 5.2.0 debug: 4.4.1(supports-color@8.1.1) expect-type: 1.2.1 @@ -21240,15 +19564,16 @@ snapshots: tinybench: 2.9.0 tinyexec: 0.3.2 tinyglobby: 0.2.14 - tinypool: 1.1.0 + tinypool: 1.1.1 tinyrainbow: 2.0.0 vite: 6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) - vite-node: 3.2.3(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + vite-node: 3.2.4(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 '@types/node': 20.17.50 - jsdom: 20.0.3 + '@vitest/ui': 3.2.4(vitest@3.2.4) + jsdom: 26.1.0 transitivePeerDependencies: - jiti - less @@ -21263,16 +19588,16 @@ snapshots: - tsx - yaml - vitest@3.2.3(@types/debug@4.1.12)(@types/node@20.17.57)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.17.57)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0): dependencies: '@types/chai': 5.2.2 - '@vitest/expect': 3.2.3 - '@vitest/mocker': 3.2.3(vite@6.3.5(@types/node@20.17.57)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)) - '@vitest/pretty-format': 3.2.3 - '@vitest/runner': 3.2.3 - '@vitest/snapshot': 3.2.3 - '@vitest/spy': 3.2.3 - '@vitest/utils': 3.2.3 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@20.17.57)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 chai: 5.2.0 debug: 4.4.1(supports-color@8.1.1) expect-type: 1.2.1 @@ -21283,15 +19608,16 @@ snapshots: tinybench: 2.9.0 tinyexec: 0.3.2 tinyglobby: 0.2.14 - tinypool: 1.1.0 + tinypool: 1.1.1 tinyrainbow: 2.0.0 vite: 6.3.5(@types/node@20.17.57)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) - vite-node: 3.2.3(@types/node@20.17.57)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + vite-node: 3.2.4(@types/node@20.17.57)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 '@types/node': 20.17.57 - jsdom: 20.0.3 + '@vitest/ui': 3.2.4(vitest@3.2.4) + jsdom: 26.1.0 transitivePeerDependencies: - jiti - less @@ -21306,16 +19632,16 @@ snapshots: - tsx - yaml - vitest@3.2.3(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(jsdom@20.0.3)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.15.29)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0): dependencies: '@types/chai': 5.2.2 - '@vitest/expect': 3.2.3 - '@vitest/mocker': 3.2.3(vite@6.3.5(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)) - '@vitest/pretty-format': 3.2.3 - '@vitest/runner': 3.2.3 - '@vitest/snapshot': 3.2.3 - '@vitest/spy': 3.2.3 - '@vitest/utils': 3.2.3 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 chai: 5.2.0 debug: 4.4.1(supports-color@8.1.1) expect-type: 1.2.1 @@ -21326,15 +19652,16 @@ snapshots: tinybench: 2.9.0 tinyexec: 0.3.2 tinyglobby: 0.2.14 - tinypool: 1.1.0 + tinypool: 1.1.1 tinyrainbow: 2.0.0 vite: 6.3.5(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) - vite-node: 3.2.3(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) + vite-node: 3.2.4(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.4)(yaml@2.8.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 '@types/node': 22.15.29 - jsdom: 20.0.3 + '@vitest/ui': 3.2.4(vitest@3.2.4) + jsdom: 26.1.0 transitivePeerDependencies: - jiti - less @@ -21375,18 +19702,16 @@ snapshots: '@types/react': 18.3.23 react: 18.3.1 - w3c-xmlserializer@4.0.0: + w3c-xmlserializer@5.0.0: dependencies: - xml-name-validator: 4.0.0 + xml-name-validator: 5.0.0 walk-up-path@4.0.0: {} - walker@1.0.8: - dependencies: - makeerror: 1.0.12 - web-namespaces@1.1.4: {} + web-namespaces@2.0.1: {} + web-streams-polyfill@3.3.3: optional: true @@ -21402,21 +19727,15 @@ snapshots: webidl-conversions@7.0.0: {} - whatwg-encoding@2.0.0: - dependencies: - iconv-lite: 0.6.3 - whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 - whatwg-mimetype@3.0.0: {} - whatwg-mimetype@4.0.0: {} - whatwg-url@11.0.0: + whatwg-url@14.2.0: dependencies: - tr46: 3.0.0 + tr46: 5.1.1 webidl-conversions: 7.0.0 whatwg-url@5.0.0: @@ -21524,14 +19843,9 @@ snapshots: wrappy@1.0.2: {} - write-file-atomic@4.0.2: - dependencies: - imurmurhash: 0.1.4 - signal-exit: 3.0.7 - ws@8.18.2: {} - xml-name-validator@4.0.0: {} + xml-name-validator@5.0.0: {} xml2js@0.5.0: dependencies: @@ -21554,9 +19868,6 @@ snapshots: yallist@5.0.0: {} - yaml@1.10.2: - optional: true - yaml@2.8.0: {} yargs-parser@20.2.9: {} diff --git a/scripts/update-contributors.js b/scripts/update-contributors.js old mode 100755 new mode 100644 index 32fd645f68..6bd4c35f0c --- a/scripts/update-contributors.js +++ b/scripts/update-contributors.js @@ -183,9 +183,15 @@ async function readReadme() { * @param {Array} contributors Array of contributor objects from GitHub API * @returns {string} HTML for contributors section */ +const EXCLUDED_LOGIN_SUBSTRINGS = ['[bot]', 'R00-B0T']; +const EXCLUDED_LOGIN_EXACTS = ['cursor', 'roomote']; + function formatContributorsSection(contributors) { - // Filter out GitHub Actions bot - const filteredContributors = contributors.filter((c) => !c.login.includes("[bot]") && !c.login.includes("R00-B0T")) + // Filter out GitHub Actions bot, cursor, and roomote + const filteredContributors = contributors.filter((c) => + !EXCLUDED_LOGIN_SUBSTRINGS.some(sub => c.login.includes(sub)) && + !EXCLUDED_LOGIN_EXACTS.includes(c.login) + ) // Start building with Markdown table format let markdown = `${START_MARKER} diff --git a/src/.vscodeignore b/src/.vscodeignore index 3aaf4b677b..8eed90df07 100644 --- a/src/.vscodeignore +++ b/src/.vscodeignore @@ -19,6 +19,9 @@ !webview-ui/build/assets/*.js !webview-ui/build/assets/*.ttf !webview-ui/build/assets/*.css +!webview-ui/build/assets/fonts/*.woff +!webview-ui/build/assets/fonts/*.woff2 +!webview-ui/build/assets/fonts/*.ttf # Include default themes JSON files used in getTheme !integrations/theme/default-themes/** diff --git a/src/__mocks__/fs/promises.ts b/src/__mocks__/fs/promises.ts index 91e686fb70..daed479d4a 100644 --- a/src/__mocks__/fs/promises.ts +++ b/src/__mocks__/fs/promises.ts @@ -168,6 +168,7 @@ const mockFs = { args: ["test.js"], disabled: false, alwaysAllow: ["existing-tool"], + disabledTools: [], }, }, }), diff --git a/src/activate/registerCommands.ts b/src/activate/registerCommands.ts index 3ec5d151e1..fc30878c7b 100644 --- a/src/activate/registerCommands.ts +++ b/src/activate/registerCommands.ts @@ -8,6 +8,7 @@ import { Package } from "../shared/package" import { getCommand } from "../utils/commands" import { ClineProvider } from "../core/webview/ClineProvider" import { ContextProxy } from "../core/config/ContextProxy" +import { focusPanel } from "../utils/focusPanel" import { registerHumanRelayCallback, unregisterHumanRelayCallback, handleHumanRelayResponse } from "./humanRelay" import { handleNewTask } from "./handleTask" @@ -172,20 +173,23 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt }, focusInput: async () => { try { - const panel = getPanel() + await focusPanel(tabPanel, sidebarPanel) - if (!panel) { - await vscode.commands.executeCommand(`workbench.view.extension.${Package.name}-ActivityBar`) - } else if (panel === tabPanel) { - panel.reveal(vscode.ViewColumn.Active, false) - } else if (panel === sidebarPanel) { - await vscode.commands.executeCommand(`${ClineProvider.sideBarId}.focus`) + // Send focus input message only for sidebar panels + if (sidebarPanel && getPanel() === sidebarPanel) { provider.postMessageToWebview({ type: "action", action: "focusInput" }) } } catch (error) { outputChannel.appendLine(`Error focusing input: ${error}`) } }, + focusPanel: async () => { + try { + await focusPanel(tabPanel, sidebarPanel) + } catch (error) { + outputChannel.appendLine(`Error focusing panel: ${error}`) + } + }, acceptInput: () => { const visibleProvider = getVisibleProviderOrLog(outputChannel) diff --git a/src/api/index.ts b/src/api/index.ts index 8b09bf4cf9..960209f714 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -27,6 +27,7 @@ import { GroqHandler, ChutesHandler, LiteLLMHandler, + ClaudeCodeHandler, } from "./providers" export interface SingleCompletionHandler { @@ -64,6 +65,8 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler { switch (apiProvider) { case "anthropic": return new AnthropicHandler(options) + case "claude-code": + return new ClaudeCodeHandler(options) case "glama": return new GlamaHandler(options) case "openrouter": diff --git a/src/api/providers/anthropic.ts b/src/api/providers/anthropic.ts index 412f5de621..52dec1ae55 100644 --- a/src/api/providers/anthropic.ts +++ b/src/api/providers/anthropic.ts @@ -17,6 +17,7 @@ import { getModelParams } from "../transform/model-params" import { BaseProvider } from "./base-provider" import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index" +import { calculateApiCostAnthropic } from "../../shared/cost" export class AnthropicHandler extends BaseProvider implements SingleCompletionHandler { private options: ApiHandlerOptions @@ -132,20 +133,35 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa } } + let inputTokens = 0 + let outputTokens = 0 + let cacheWriteTokens = 0 + let cacheReadTokens = 0 + for await (const chunk of stream) { switch (chunk.type) { case "message_start": { // Tells us cache reads/writes/input/output. - const usage = chunk.message.usage + const { + input_tokens = 0, + output_tokens = 0, + cache_creation_input_tokens, + cache_read_input_tokens, + } = chunk.message.usage yield { type: "usage", - inputTokens: usage.input_tokens || 0, - outputTokens: usage.output_tokens || 0, - cacheWriteTokens: usage.cache_creation_input_tokens || undefined, - cacheReadTokens: usage.cache_read_input_tokens || undefined, + inputTokens: input_tokens, + outputTokens: output_tokens, + cacheWriteTokens: cache_creation_input_tokens || undefined, + cacheReadTokens: cache_read_input_tokens || undefined, } + inputTokens += input_tokens + outputTokens += output_tokens + cacheWriteTokens += cache_creation_input_tokens || 0 + cacheReadTokens += cache_read_input_tokens || 0 + break } case "message_delta": @@ -198,6 +214,21 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa break } } + + if (inputTokens > 0 || outputTokens > 0 || cacheWriteTokens > 0 || cacheReadTokens > 0) { + yield { + type: "usage", + inputTokens: 0, + outputTokens: 0, + totalCost: calculateApiCostAnthropic( + this.getModel().info, + inputTokens, + outputTokens, + cacheWriteTokens, + cacheReadTokens, + ), + } + } } getModel() { diff --git a/src/api/providers/claude-code.ts b/src/api/providers/claude-code.ts new file mode 100644 index 0000000000..f3e66604e4 --- /dev/null +++ b/src/api/providers/claude-code.ts @@ -0,0 +1,171 @@ +import type { Anthropic } from "@anthropic-ai/sdk" +import { claudeCodeDefaultModelId, type ClaudeCodeModelId, claudeCodeModels } from "@roo-code/types" +import { type ApiHandler } from ".." +import { ApiStreamUsageChunk, type ApiStream } from "../transform/stream" +import { runClaudeCode } from "../../integrations/claude-code/run" +import { ClaudeCodeMessage } from "../../integrations/claude-code/types" +import { BaseProvider } from "./base-provider" +import { t } from "../../i18n" +import { ApiHandlerOptions } from "../../shared/api" + +export class ClaudeCodeHandler extends BaseProvider implements ApiHandler { + private options: ApiHandlerOptions + + constructor(options: ApiHandlerOptions) { + super() + this.options = options + } + + override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream { + const claudeProcess = runClaudeCode({ + systemPrompt, + messages, + path: this.options.claudeCodePath, + modelId: this.getModel().id, + }) + + const dataQueue: string[] = [] + let processError = null + let errorOutput = "" + let exitCode: number | null = null + + claudeProcess.stdout.on("data", (data) => { + const output = data.toString() + const lines = output.split("\n").filter((line: string) => line.trim() !== "") + + for (const line of lines) { + dataQueue.push(line) + } + }) + + claudeProcess.stderr.on("data", (data) => { + errorOutput += data.toString() + }) + + claudeProcess.on("close", (code) => { + exitCode = code + }) + + claudeProcess.on("error", (error) => { + processError = error + }) + + // Usage is included with assistant messages, + // but cost is included in the result chunk + let usage: ApiStreamUsageChunk = { + type: "usage", + inputTokens: 0, + outputTokens: 0, + cacheReadTokens: 0, + cacheWriteTokens: 0, + } + + while (exitCode !== 0 || dataQueue.length > 0) { + if (dataQueue.length === 0) { + await new Promise((resolve) => setImmediate(resolve)) + } + + if (exitCode !== null && exitCode !== 0) { + if (errorOutput) { + throw new Error( + t("common:errors.claudeCode.processExitedWithError", { + exitCode, + output: errorOutput.trim(), + }), + ) + } + throw new Error(t("common:errors.claudeCode.processExited", { exitCode })) + } + + const data = dataQueue.shift() + if (!data) { + continue + } + + const chunk = this.attemptParseChunk(data) + + if (!chunk) { + yield { + type: "text", + text: data || "", + } + + continue + } + + if (chunk.type === "system" && chunk.subtype === "init") { + continue + } + + if (chunk.type === "assistant" && "message" in chunk) { + const message = chunk.message + + if (message.stop_reason !== null && message.stop_reason !== "tool_use") { + const errorMessage = + message.content[0]?.text || + t("common:errors.claudeCode.stoppedWithReason", { reason: message.stop_reason }) + + if (errorMessage.includes("Invalid model name")) { + throw new Error(errorMessage + `\n\n${t("common:errors.claudeCode.apiKeyModelPlanMismatch")}`) + } + + throw new Error(errorMessage) + } + + for (const content of message.content) { + if (content.type === "text") { + yield { + type: "text", + text: content.text, + } + } else { + console.warn("Unsupported content type:", content.type) + } + } + + usage.inputTokens += message.usage.input_tokens + usage.outputTokens += message.usage.output_tokens + usage.cacheReadTokens = (usage.cacheReadTokens || 0) + (message.usage.cache_read_input_tokens || 0) + usage.cacheWriteTokens = + (usage.cacheWriteTokens || 0) + (message.usage.cache_creation_input_tokens || 0) + + continue + } + + if (chunk.type === "result" && "result" in chunk) { + // Only use the cost from the CLI if provided + // Don't calculate cost as it may be $0 for subscription users + usage.totalCost = chunk.cost_usd ?? 0 + + yield usage + } + + if (processError) { + throw processError + } + } + } + + getModel() { + const modelId = this.options.apiModelId + if (modelId && modelId in claudeCodeModels) { + const id = modelId as ClaudeCodeModelId + return { id, info: claudeCodeModels[id] } + } + + return { + id: claudeCodeDefaultModelId, + info: claudeCodeModels[claudeCodeDefaultModelId], + } + } + + // TODO: Validate instead of parsing + private attemptParseChunk(data: string): ClaudeCodeMessage | null { + try { + return JSON.parse(data) + } catch (error) { + console.error("Error parsing chunk:", error) + return null + } + } +} diff --git a/src/api/providers/fetchers/__tests__/fixtures/lmstudio-model-details.json b/src/api/providers/fetchers/__tests__/fixtures/lmstudio-model-details.json new file mode 100644 index 0000000000..43f5505710 --- /dev/null +++ b/src/api/providers/fetchers/__tests__/fixtures/lmstudio-model-details.json @@ -0,0 +1,14 @@ +{ + "mistralai/devstral-small-2505": { + "type": "llm", + "modelKey": "mistralai/devstral-small-2505", + "format": "safetensors", + "displayName": "Devstral Small 2505", + "path": "mistralai/devstral-small-2505", + "sizeBytes": 13277565112, + "architecture": "mistral", + "vision": false, + "trainedForToolUse": false, + "maxContextLength": 131072 + } +} diff --git a/src/api/providers/fetchers/__tests__/fixtures/ollama-model-details.json b/src/api/providers/fetchers/__tests__/fixtures/ollama-model-details.json new file mode 100644 index 0000000000..e0b6ac03d9 --- /dev/null +++ b/src/api/providers/fetchers/__tests__/fixtures/ollama-model-details.json @@ -0,0 +1,58 @@ +{ + "qwen3-2to16:latest": { + "license": " Apache License\\n Version 2.0, January 2004\\n...", + "modelfile": "model.modelfile,# To build a new Modelfile based on this, replace FROM with:...", + "parameters": "repeat_penalty 1\\nstop \\\\nstop...", + "template": "{{- if .Messages }}\\n{{- if or .System .Tools }}<|im_start|>system...", + "details": { + "parent_model": "/Users/brad/.ollama/models/blobs/sha256-3291abe70f16ee9682de7bfae08db5373ea9d6497e614aaad63340ad421d6312", + "format": "gguf", + "family": "qwen3", + "families": ["qwen3"], + "parameter_size": "32.8B", + "quantization_level": "Q4_K_M" + }, + "model_info": { + "general.architecture": "qwen3", + "general.basename": "Qwen3", + "general.file_type": 15, + "general.parameter_count": 32762123264, + "general.quantization_version": 2, + "general.size_label": "32B", + "general.type": "model", + "qwen3.attention.head_count": 64, + "qwen3.attention.head_count_kv": 8, + "qwen3.attention.key_length": 128, + "qwen3.attention.layer_norm_rms_epsilon": 0.000001, + "qwen3.attention.value_length": 128, + "qwen3.block_count": 64, + "qwen3.context_length": 40960, + "qwen3.embedding_length": 5120, + "qwen3.feed_forward_length": 25600, + "qwen3.rope.freq_base": 1000000, + "tokenizer.ggml.add_bos_token": false, + "tokenizer.ggml.bos_token_id": 151643, + "tokenizer.ggml.eos_token_id": 151645, + "tokenizer.ggml.merges": null, + "tokenizer.ggml.model": "gpt2", + "tokenizer.ggml.padding_token_id": 151643, + "tokenizer.ggml.pre": "qwen2", + "tokenizer.ggml.token_type": null, + "tokenizer.ggml.tokens": null + }, + "tensors": [ + { + "name": "output.weight", + "type": "Q6_K", + "shape": [5120, 151936] + }, + { + "name": "output_norm.weight", + "type": "F32", + "shape": [5120] + } + ], + "capabilities": ["completion", "tools"], + "modified_at": "2025-06-02T22:16:13.644123606-04:00" + } +} diff --git a/src/api/providers/fetchers/__tests__/lmstudio.test.ts b/src/api/providers/fetchers/__tests__/lmstudio.test.ts new file mode 100644 index 0000000000..59b4388785 --- /dev/null +++ b/src/api/providers/fetchers/__tests__/lmstudio.test.ts @@ -0,0 +1,197 @@ +import axios from "axios" +import { vi, describe, it, expect, beforeEach } from "vitest" +import { LMStudioClient, LLM, LLMInstanceInfo } from "@lmstudio/sdk" // LLMInfo is a type +import { getLMStudioModels, parseLMStudioModel } from "../lmstudio" +import { ModelInfo, lMStudioDefaultModelInfo } from "@roo-code/types" // ModelInfo is a type + +// Mock axios +vi.mock("axios") +const mockedAxios = axios as any + +// Mock @lmstudio/sdk +const mockGetModelInfo = vi.fn() +const mockListLoaded = vi.fn() +vi.mock("@lmstudio/sdk", () => { + return { + LMStudioClient: vi.fn().mockImplementation(() => ({ + llm: { + listLoaded: mockListLoaded, + }, + })), + } +}) +const MockedLMStudioClientConstructor = LMStudioClient as any + +describe("LMStudio Fetcher", () => { + beforeEach(() => { + vi.clearAllMocks() + MockedLMStudioClientConstructor.mockClear() + mockListLoaded.mockClear() + mockGetModelInfo.mockClear() + }) + + describe("parseLMStudioModel", () => { + it("should correctly parse raw LLMInfo to ModelInfo", () => { + const rawModel: LLMInstanceInfo = { + type: "llm", + modelKey: "mistralai/devstral-small-2505", + format: "safetensors", + displayName: "Devstral Small 2505", + path: "mistralai/devstral-small-2505", + sizeBytes: 13277565112, + architecture: "mistral", + identifier: "mistralai/devstral-small-2505", + instanceReference: "RAP5qbeHVjJgBiGFQ6STCuTJ", + vision: false, + trainedForToolUse: false, + maxContextLength: 131072, + contextLength: 7161, + } + + const expectedModelInfo: ModelInfo = { + ...lMStudioDefaultModelInfo, + description: `${rawModel.displayName} - ${rawModel.path}`, + contextWindow: rawModel.contextLength, + supportsPromptCache: true, + supportsImages: rawModel.vision, + supportsComputerUse: false, + maxTokens: rawModel.contextLength, + inputPrice: 0, + outputPrice: 0, + cacheWritesPrice: 0, + cacheReadsPrice: 0, + } + + const result = parseLMStudioModel(rawModel) + expect(result).toEqual(expectedModelInfo) + }) + }) + + describe("getLMStudioModels", () => { + const baseUrl = "http://localhost:1234" + const lmsUrl = "ws://localhost:1234" + + const mockRawModel: LLMInstanceInfo = { + architecture: "test-arch", + identifier: "mistralai/devstral-small-2505", + instanceReference: "RAP5qbeHVjJgBiGFQ6STCuTJ", + modelKey: "test-model-key-1", + path: "/path/to/test-model-1", + type: "llm", + displayName: "Test Model One", + maxContextLength: 2048, + contextLength: 7161, + paramsString: "1B params, 2k context", + vision: true, + format: "gguf", + sizeBytes: 1000000000, + trainedForToolUse: false, // Added + } + + it("should fetch and parse models successfully", async () => { + mockedAxios.get.mockResolvedValueOnce({ data: { status: "ok" } }) + mockListLoaded.mockResolvedValueOnce([{ getModelInfo: mockGetModelInfo }]) + mockGetModelInfo.mockResolvedValueOnce(mockRawModel) + + const result = await getLMStudioModels(baseUrl) + + expect(mockedAxios.get).toHaveBeenCalledTimes(1) + expect(mockedAxios.get).toHaveBeenCalledWith(`${baseUrl}/v1/models`) + expect(MockedLMStudioClientConstructor).toHaveBeenCalledTimes(1) + expect(MockedLMStudioClientConstructor).toHaveBeenCalledWith({ baseUrl: lmsUrl }) + expect(mockListLoaded).toHaveBeenCalledTimes(1) + + const expectedParsedModel = parseLMStudioModel(mockRawModel) + expect(result).toEqual({ [mockRawModel.modelKey]: expectedParsedModel }) + }) + + it("should use default baseUrl if an empty string is provided", async () => { + const defaultBaseUrl = "http://localhost:1234" + const defaultLmsUrl = "ws://localhost:1234" + mockedAxios.get.mockResolvedValueOnce({ data: {} }) + mockListLoaded.mockResolvedValueOnce([]) + + await getLMStudioModels("") + + expect(mockedAxios.get).toHaveBeenCalledWith(`${defaultBaseUrl}/v1/models`) + expect(MockedLMStudioClientConstructor).toHaveBeenCalledWith({ baseUrl: defaultLmsUrl }) + }) + + it("should transform https baseUrl to wss for LMStudioClient", async () => { + const httpsBaseUrl = "https://securehost:4321" + const wssLmsUrl = "wss://securehost:4321" + mockedAxios.get.mockResolvedValueOnce({ data: {} }) + mockListLoaded.mockResolvedValueOnce([]) + + await getLMStudioModels(httpsBaseUrl) + + expect(mockedAxios.get).toHaveBeenCalledWith(`${httpsBaseUrl}/v1/models`) + expect(MockedLMStudioClientConstructor).toHaveBeenCalledWith({ baseUrl: wssLmsUrl }) + }) + + it("should return an empty object if lmsUrl is unparsable", async () => { + const unparsableBaseUrl = "http://localhost:invalid:port" // Leads to ws://localhost:invalid:port + + const result = await getLMStudioModels(unparsableBaseUrl) + + expect(result).toEqual({}) + expect(mockedAxios.get).not.toHaveBeenCalled() + expect(MockedLMStudioClientConstructor).not.toHaveBeenCalled() + }) + + it("should return an empty object and log error if axios.get fails with a generic error", async () => { + const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {}) + const networkError = new Error("Network connection failed") + mockedAxios.get.mockRejectedValueOnce(networkError) + + const result = await getLMStudioModels(baseUrl) + + expect(mockedAxios.get).toHaveBeenCalledTimes(1) + expect(mockedAxios.get).toHaveBeenCalledWith(`${baseUrl}/v1/models`) + expect(MockedLMStudioClientConstructor).not.toHaveBeenCalled() + expect(mockListLoaded).not.toHaveBeenCalled() + expect(consoleErrorSpy).toHaveBeenCalledWith( + `Error fetching LMStudio models: ${JSON.stringify(networkError, Object.getOwnPropertyNames(networkError), 2)}`, + ) + expect(result).toEqual({}) + consoleErrorSpy.mockRestore() + }) + + it("should return an empty object and log info if axios.get fails with ECONNREFUSED", async () => { + const consoleInfoSpy = vi.spyOn(console, "warn").mockImplementation(() => {}) + const econnrefusedError = new Error("Connection refused") + ;(econnrefusedError as any).code = "ECONNREFUSED" + mockedAxios.get.mockRejectedValueOnce(econnrefusedError) + + const result = await getLMStudioModels(baseUrl) + + expect(mockedAxios.get).toHaveBeenCalledTimes(1) + expect(mockedAxios.get).toHaveBeenCalledWith(`${baseUrl}/v1/models`) + expect(MockedLMStudioClientConstructor).not.toHaveBeenCalled() + expect(mockListLoaded).not.toHaveBeenCalled() + expect(consoleInfoSpy).toHaveBeenCalledWith(`Error connecting to LMStudio at ${baseUrl}`) + expect(result).toEqual({}) + consoleInfoSpy.mockRestore() + }) + + it("should return an empty object and log error if listDownloadedModels fails", async () => { + const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {}) + const listError = new Error("LMStudio SDK internal error") + + mockedAxios.get.mockResolvedValueOnce({ data: {} }) + mockListLoaded.mockRejectedValueOnce(listError) + + const result = await getLMStudioModels(baseUrl) + + expect(mockedAxios.get).toHaveBeenCalledTimes(1) + expect(MockedLMStudioClientConstructor).toHaveBeenCalledTimes(1) + expect(MockedLMStudioClientConstructor).toHaveBeenCalledWith({ baseUrl: lmsUrl }) + expect(mockListLoaded).toHaveBeenCalledTimes(1) + expect(consoleErrorSpy).toHaveBeenCalledWith( + `Error fetching LMStudio models: ${JSON.stringify(listError, Object.getOwnPropertyNames(listError), 2)}`, + ) + expect(result).toEqual({}) + consoleErrorSpy.mockRestore() + }) + }) +}) diff --git a/src/api/providers/fetchers/__tests__/ollama.test.ts b/src/api/providers/fetchers/__tests__/ollama.test.ts new file mode 100644 index 0000000000..bf1bf3c6b2 --- /dev/null +++ b/src/api/providers/fetchers/__tests__/ollama.test.ts @@ -0,0 +1,222 @@ +import axios from "axios" +import path from "path" +import { vi, describe, it, expect, beforeEach } from "vitest" +import { getOllamaModels, parseOllamaModel } from "../ollama" +import ollamaModelsData from "./fixtures/ollama-model-details.json" + +// Mock axios +vi.mock("axios") +const mockedAxios = axios as any + +describe("Ollama Fetcher", () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + describe("parseOllamaModel", () => { + it("should correctly parse Ollama model info", () => { + const modelData = ollamaModelsData["qwen3-2to16:latest"] + const parsedModel = parseOllamaModel(modelData) + + expect(parsedModel).toEqual({ + maxTokens: 40960, + contextWindow: 40960, + supportsImages: false, + supportsComputerUse: false, + supportsPromptCache: true, + inputPrice: 0, + outputPrice: 0, + cacheWritesPrice: 0, + cacheReadsPrice: 0, + description: "Family: qwen3, Context: 40960, Size: 32.8B", + }) + }) + + it("should handle models with null families field", () => { + const modelDataWithNullFamilies = { + ...ollamaModelsData["qwen3-2to16:latest"], + details: { + ...ollamaModelsData["qwen3-2to16:latest"].details, + families: null, + }, + } + + const parsedModel = parseOllamaModel(modelDataWithNullFamilies as any) + + expect(parsedModel).toEqual({ + maxTokens: 40960, + contextWindow: 40960, + supportsImages: false, + supportsComputerUse: false, + supportsPromptCache: true, + inputPrice: 0, + outputPrice: 0, + cacheWritesPrice: 0, + cacheReadsPrice: 0, + description: "Family: qwen3, Context: 40960, Size: 32.8B", + }) + }) + }) + + describe("getOllamaModels", () => { + it("should fetch model list from /api/tags and details for each model from /api/show", async () => { + const baseUrl = "http://localhost:11434" + const modelName = "devstral2to16:latest" + + const mockApiTagsResponse = { + models: [ + { + name: modelName, + model: modelName, + modified_at: "2025-06-03T09:23:22.610222878-04:00", + size: 14333928010, + digest: "6a5f0c01d2c96c687d79e32fdd25b87087feb376bf9838f854d10be8cf3c10a5", + details: { + family: "llama", + families: ["llama"], + format: "gguf", + parameter_size: "23.6B", + parent_model: "", + quantization_level: "Q4_K_M", + }, + }, + ], + } + const mockApiShowResponse = { + license: "Mock License", + modelfile: "FROM /path/to/blob\nTEMPLATE {{ .Prompt }}", + parameters: "num_ctx 4096\nstop_token ", + template: "{{ .System }}USER: {{ .Prompt }}ASSISTANT:", + modified_at: "2025-06-03T09:23:22.610222878-04:00", + details: { + parent_model: "", + format: "gguf", + family: "llama", + families: ["llama"], + parameter_size: "23.6B", + quantization_level: "Q4_K_M", + }, + model_info: { + "ollama.context_length": 4096, + "some.other.info": "value", + }, + capabilities: ["completion"], + } + + mockedAxios.get.mockResolvedValueOnce({ data: mockApiTagsResponse }) + mockedAxios.post.mockResolvedValueOnce({ data: mockApiShowResponse }) + + const result = await getOllamaModels(baseUrl) + + expect(mockedAxios.get).toHaveBeenCalledTimes(1) + expect(mockedAxios.get).toHaveBeenCalledWith(`${baseUrl}/api/tags`) + + expect(mockedAxios.post).toHaveBeenCalledTimes(1) + expect(mockedAxios.post).toHaveBeenCalledWith(`${baseUrl}/api/show`, { model: modelName }) + + expect(typeof result).toBe("object") + expect(result).not.toBeInstanceOf(Array) + expect(Object.keys(result).length).toBe(1) + expect(result[modelName]).toBeDefined() + + const expectedParsedDetails = parseOllamaModel(mockApiShowResponse as any) + expect(result[modelName]).toEqual(expectedParsedDetails) + }) + + it("should return an empty list if the initial /api/tags call fails", async () => { + const baseUrl = "http://localhost:11434" + mockedAxios.get.mockRejectedValueOnce(new Error("Network error")) + const consoleInfoSpy = vi.spyOn(console, "error").mockImplementation(() => {}) // Spy and suppress output + + const result = await getOllamaModels(baseUrl) + + expect(mockedAxios.get).toHaveBeenCalledTimes(1) + expect(mockedAxios.get).toHaveBeenCalledWith(`${baseUrl}/api/tags`) + expect(mockedAxios.post).not.toHaveBeenCalled() + expect(result).toEqual({}) + }) + + it("should log an info message and return an empty object on ECONNREFUSED", async () => { + const baseUrl = "http://localhost:11434" + const consoleInfoSpy = vi.spyOn(console, "warn").mockImplementation(() => {}) // Spy and suppress output + + const econnrefusedError = new Error("Connection refused") as any + econnrefusedError.code = "ECONNREFUSED" + mockedAxios.get.mockRejectedValueOnce(econnrefusedError) + + const result = await getOllamaModels(baseUrl) + + expect(mockedAxios.get).toHaveBeenCalledTimes(1) + expect(mockedAxios.get).toHaveBeenCalledWith(`${baseUrl}/api/tags`) + expect(mockedAxios.post).not.toHaveBeenCalled() + expect(consoleInfoSpy).toHaveBeenCalledWith(`Failed connecting to Ollama at ${baseUrl}`) + expect(result).toEqual({}) + + consoleInfoSpy.mockRestore() // Restore original console.info + }) + + it("should handle models with null families field in API response", async () => { + const baseUrl = "http://localhost:11434" + const modelName = "test-model:latest" + + const mockApiTagsResponse = { + models: [ + { + name: modelName, + model: modelName, + modified_at: "2025-06-03T09:23:22.610222878-04:00", + size: 14333928010, + digest: "6a5f0c01d2c96c687d79e32fdd25b87087feb376bf9838f854d10be8cf3c10a5", + details: { + family: "llama", + families: null, // This is the case we're testing + format: "gguf", + parameter_size: "23.6B", + parent_model: "", + quantization_level: "Q4_K_M", + }, + }, + ], + } + const mockApiShowResponse = { + license: "Mock License", + modelfile: "FROM /path/to/blob\nTEMPLATE {{ .Prompt }}", + parameters: "num_ctx 4096\nstop_token ", + template: "{{ .System }}USER: {{ .Prompt }}ASSISTANT:", + modified_at: "2025-06-03T09:23:22.610222878-04:00", + details: { + parent_model: "", + format: "gguf", + family: "llama", + families: null, // This is the case we're testing + parameter_size: "23.6B", + quantization_level: "Q4_K_M", + }, + model_info: { + "ollama.context_length": 4096, + "some.other.info": "value", + }, + capabilities: ["completion"], + } + + mockedAxios.get.mockResolvedValueOnce({ data: mockApiTagsResponse }) + mockedAxios.post.mockResolvedValueOnce({ data: mockApiShowResponse }) + + const result = await getOllamaModels(baseUrl) + + expect(mockedAxios.get).toHaveBeenCalledTimes(1) + expect(mockedAxios.get).toHaveBeenCalledWith(`${baseUrl}/api/tags`) + + expect(mockedAxios.post).toHaveBeenCalledTimes(1) + expect(mockedAxios.post).toHaveBeenCalledWith(`${baseUrl}/api/show`, { model: modelName }) + + expect(typeof result).toBe("object") + expect(result).not.toBeInstanceOf(Array) + expect(Object.keys(result).length).toBe(1) + expect(result[modelName]).toBeDefined() + + // Verify the model was parsed correctly despite null families + expect(result[modelName].description).toBe("Family: llama, Context: 4096, Size: 23.6B") + }) + }) +}) diff --git a/src/api/providers/fetchers/lmstudio.ts b/src/api/providers/fetchers/lmstudio.ts new file mode 100644 index 0000000000..ea1a590f1e --- /dev/null +++ b/src/api/providers/fetchers/lmstudio.ts @@ -0,0 +1,54 @@ +import { ModelInfo, lMStudioDefaultModelInfo } from "@roo-code/types" +import { LLM, LLMInfo, LLMInstanceInfo, LMStudioClient } from "@lmstudio/sdk" +import axios from "axios" + +export const parseLMStudioModel = (rawModel: LLMInstanceInfo): ModelInfo => { + const modelInfo: ModelInfo = Object.assign({}, lMStudioDefaultModelInfo, { + description: `${rawModel.displayName} - ${rawModel.path}`, + contextWindow: rawModel.contextLength, + supportsPromptCache: true, + supportsImages: rawModel.vision, + supportsComputerUse: false, + maxTokens: rawModel.contextLength, + }) + + return modelInfo +} + +export async function getLMStudioModels(baseUrl = "http://localhost:1234"): Promise> { + // clearing the input can leave an empty string; use the default in that case + baseUrl = baseUrl === "" ? "http://localhost:1234" : baseUrl + + const models: Record = {} + // ws is required to connect using the LMStudio library + const lmsUrl = baseUrl.replace(/^http:\/\//, "ws://").replace(/^https:\/\//, "wss://") + + try { + if (!URL.canParse(lmsUrl)) { + return models + } + + // test the connection to LM Studio first + // errors will be caught further down + await axios.get(`${baseUrl}/v1/models`) + + const client = new LMStudioClient({ baseUrl: lmsUrl }) + const response = (await client.llm.listLoaded().then((models: LLM[]) => { + return Promise.all(models.map((m) => m.getModelInfo())) + })) as Array + + for (const lmstudioModel of response) { + models[lmstudioModel.modelKey] = parseLMStudioModel(lmstudioModel) + } + } catch (error) { + if (error.code === "ECONNREFUSED") { + console.warn(`Error connecting to LMStudio at ${baseUrl}`) + } else { + console.error( + `Error fetching LMStudio models: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`, + ) + } + } + + return models +} diff --git a/src/api/providers/fetchers/modelCache.ts b/src/api/providers/fetchers/modelCache.ts index 12d636bc46..5956187e41 100644 --- a/src/api/providers/fetchers/modelCache.ts +++ b/src/api/providers/fetchers/modelCache.ts @@ -14,6 +14,9 @@ import { getGlamaModels } from "./glama" import { getUnboundModels } from "./unbound" import { getLiteLLMModels } from "./litellm" import { GetModelsOptions } from "../../../shared/api" +import { getOllamaModels } from "./ollama" +import { getLMStudioModels } from "./lmstudio" + const memoryCache = new NodeCache({ stdTTL: 5 * 60, checkperiod: 5 * 60 }) async function writeModels(router: RouterName, data: ModelRecord) { @@ -68,6 +71,12 @@ export const getModels = async (options: GetModelsOptions): Promise // Type safety ensures apiKey and baseUrl are always provided for litellm models = await getLiteLLMModels(options.apiKey, options.baseUrl) break + case "ollama": + models = await getOllamaModels(options.baseUrl) + break + case "lmstudio": + models = await getLMStudioModels(options.baseUrl) + break default: { // Ensures router is exhaustively checked if RouterName is a strict union const exhaustiveCheck: never = provider diff --git a/src/api/providers/fetchers/ollama.ts b/src/api/providers/fetchers/ollama.ts new file mode 100644 index 0000000000..8e1e3f7f07 --- /dev/null +++ b/src/api/providers/fetchers/ollama.ts @@ -0,0 +1,100 @@ +import axios from "axios" +import { ModelInfo, ollamaDefaultModelInfo } from "@roo-code/types" +import { z } from "zod" + +const OllamaModelDetailsSchema = z.object({ + family: z.string(), + families: z.array(z.string()).nullable().optional(), + format: z.string().optional(), + parameter_size: z.string(), + parent_model: z.string().optional(), + quantization_level: z.string().optional(), +}) + +const OllamaModelSchema = z.object({ + details: OllamaModelDetailsSchema, + digest: z.string().optional(), + model: z.string(), + modified_at: z.string().optional(), + name: z.string(), + size: z.number().optional(), +}) + +const OllamaModelInfoResponseSchema = z.object({ + modelfile: z.string().optional(), + parameters: z.string().optional(), + template: z.string().optional(), + details: OllamaModelDetailsSchema, + model_info: z.record(z.string(), z.any()), + capabilities: z.array(z.string()).optional(), +}) + +const OllamaModelsResponseSchema = z.object({ + models: z.array(OllamaModelSchema), +}) + +type OllamaModelsResponse = z.infer + +type OllamaModelInfoResponse = z.infer + +export const parseOllamaModel = (rawModel: OllamaModelInfoResponse): ModelInfo => { + const contextKey = Object.keys(rawModel.model_info).find((k) => k.includes("context_length")) + const contextWindow = + contextKey && typeof rawModel.model_info[contextKey] === "number" ? rawModel.model_info[contextKey] : undefined + + const modelInfo: ModelInfo = Object.assign({}, ollamaDefaultModelInfo, { + description: `Family: ${rawModel.details.family}, Context: ${contextWindow}, Size: ${rawModel.details.parameter_size}`, + contextWindow: contextWindow || ollamaDefaultModelInfo.contextWindow, + supportsPromptCache: true, + supportsImages: rawModel.capabilities?.includes("vision"), + supportsComputerUse: false, + maxTokens: contextWindow || ollamaDefaultModelInfo.contextWindow, + }) + + return modelInfo +} + +export async function getOllamaModels(baseUrl = "http://localhost:11434"): Promise> { + const models: Record = {} + + // clearing the input can leave an empty string; use the default in that case + baseUrl = baseUrl === "" ? "http://localhost:11434" : baseUrl + + try { + if (!URL.canParse(baseUrl)) { + return models + } + + const response = await axios.get(`${baseUrl}/api/tags`) + const parsedResponse = OllamaModelsResponseSchema.safeParse(response.data) + let modelInfoPromises = [] + + if (parsedResponse.success) { + for (const ollamaModel of parsedResponse.data.models) { + modelInfoPromises.push( + axios + .post(`${baseUrl}/api/show`, { + model: ollamaModel.model, + }) + .then((ollamaModelInfo) => { + models[ollamaModel.name] = parseOllamaModel(ollamaModelInfo.data) + }), + ) + } + + await Promise.all(modelInfoPromises) + } else { + console.error(`Error parsing Ollama models response: ${JSON.stringify(parsedResponse.error, null, 2)}`) + } + } catch (error) { + if (error.code === "ECONNREFUSED") { + console.warn(`Failed connecting to Ollama at ${baseUrl}`) + } else { + console.error( + `Error fetching Ollama models: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`, + ) + } + } + + return models +} diff --git a/src/api/providers/index.ts b/src/api/providers/index.ts index b305118188..93df5c58ff 100644 --- a/src/api/providers/index.ts +++ b/src/api/providers/index.ts @@ -2,6 +2,7 @@ export { AnthropicVertexHandler } from "./anthropic-vertex" export { AnthropicHandler } from "./anthropic" export { AwsBedrockHandler } from "./bedrock" export { ChutesHandler } from "./chutes" +export { ClaudeCodeHandler } from "./claude-code" export { DeepSeekHandler } from "./deepseek" export { FakeAIHandler } from "./fake-ai" export { GeminiHandler } from "./gemini" diff --git a/src/api/providers/ollama.ts b/src/api/providers/ollama.ts index 7f384e9a98..a7713ba421 100644 --- a/src/api/providers/ollama.ts +++ b/src/api/providers/ollama.ts @@ -1,6 +1,5 @@ import { Anthropic } from "@anthropic-ai/sdk" import OpenAI from "openai" -import axios from "axios" import { type ModelInfo, openAiModelInfoSaneDefaults, DEEP_SEEK_DEFAULT_TEMPERATURE } from "@roo-code/types" @@ -111,17 +110,3 @@ export class OllamaHandler extends BaseProvider implements SingleCompletionHandl } } } - -export async function getOllamaModels(baseUrl = "http://localhost:11434") { - try { - if (!URL.canParse(baseUrl)) { - return [] - } - - const response = await axios.get(`${baseUrl}/api/tags`) - const modelsArray = response.data?.models?.map((model: any) => model.name) || [] - return [...new Set(modelsArray)] - } catch (error) { - return [] - } -} diff --git a/src/api/transform/stream.ts b/src/api/transform/stream.ts index caa69a09fe..89655a3f56 100644 --- a/src/api/transform/stream.ts +++ b/src/api/transform/stream.ts @@ -1,6 +1,12 @@ export type ApiStream = AsyncGenerator -export type ApiStreamChunk = ApiStreamTextChunk | ApiStreamUsageChunk | ApiStreamReasoningChunk +export type ApiStreamChunk = ApiStreamTextChunk | ApiStreamUsageChunk | ApiStreamReasoningChunk | ApiStreamError + +export interface ApiStreamError { + type: "error" + error: string + message: string +} export interface ApiStreamTextChunk { type: "text" diff --git a/src/core/condense/index.ts b/src/core/condense/index.ts index 8a8b57bb0c..3b73b1915c 100644 --- a/src/core/condense/index.ts +++ b/src/core/condense/index.ts @@ -8,6 +8,8 @@ import { ApiMessage } from "../task-persistence/apiMessages" import { maybeRemoveImageBlocks } from "../../api/transform/image-cleaning" export const N_MESSAGES_TO_KEEP = 3 +export const MIN_CONDENSE_THRESHOLD = 5 // Minimum percentage of context window to trigger condensing +export const MAX_CONDENSE_THRESHOLD = 100 // Maximum percentage of context window to trigger condensing const SUMMARY_PROMPT = `\ Your task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions. diff --git a/src/core/diff/strategies/multi-file-search-replace.ts b/src/core/diff/strategies/multi-file-search-replace.ts index 3450ae56bc..1554201675 100644 --- a/src/core/diff/strategies/multi-file-search-replace.ts +++ b/src/core/diff/strategies/multi-file-search-replace.ts @@ -485,7 +485,7 @@ Each file requires its own path, start_line, and diff elements. const replacements = matches .map((match) => ({ - startLine: Number(match[2] ?? 0), + startLine: _paramStartLine ?? Number(match[2] ?? 0), searchContent: match[6], replaceContent: match[7], })) diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/architect-mode-prompt.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/architect-mode-prompt.snap index 4041e031f9..dd621b34b8 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/architect-mode-prompt.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/architect-mode-prompt.snap @@ -298,25 +298,22 @@ Example: Requesting to ask the user for the path to the frontend-config.json fil ## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. +Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. Parameters: - result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -- command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use `open index.html` to display a created html website, or `open localhost:3000` to display a locally running development server. But DO NOT use commands like `echo` or `cat` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions. Usage: Your final result description here -Command to demonstrate result (optional) -Example: Requesting to attempt completion with a result and command +Example: Requesting to attempt completion with a result I've updated the CSS -open index.html ## switch_mode @@ -449,7 +446,7 @@ You accomplish a given task iteratively, breaking it down into clear steps and w 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order. 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go. 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Next, think about which of the provided tools is the most relevant tool to accomplish the user's task. Go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided. -4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. `open index.html` to show the website you've built. +4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance. diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/ask-mode-prompt.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/ask-mode-prompt.snap index 68c240c7c3..3b8f357e8c 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/ask-mode-prompt.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/ask-mode-prompt.snap @@ -195,25 +195,22 @@ Example: Requesting to ask the user for the path to the frontend-config.json fil ## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. +Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. Parameters: - result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -- command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use `open index.html` to display a created html website, or `open localhost:3000` to display a locally running development server. But DO NOT use commands like `echo` or `cat` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions. Usage: Your final result description here -Command to demonstrate result (optional) -Example: Requesting to attempt completion with a result and command +Example: Requesting to attempt completion with a result I've updated the CSS -open index.html ## switch_mode @@ -346,7 +343,7 @@ You accomplish a given task iteratively, breaking it down into clear steps and w 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order. 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go. 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Next, think about which of the provided tools is the most relevant tool to accomplish the user's task. Go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided. -4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. `open index.html` to show the website you've built. +4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance. diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-disabled.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-disabled.snap index 749d4ec32b..719e7f0ea7 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-disabled.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-disabled.snap @@ -369,25 +369,22 @@ Example: Requesting to ask the user for the path to the frontend-config.json fil ## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. +Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. Parameters: - result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -- command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use `open index.html` to display a created html website, or `open localhost:3000` to display a locally running development server. But DO NOT use commands like `echo` or `cat` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions. Usage: Your final result description here -Command to demonstrate result (optional) -Example: Requesting to attempt completion with a result and command +Example: Requesting to attempt completion with a result I've updated the CSS -open index.html ## switch_mode @@ -533,7 +530,7 @@ You accomplish a given task iteratively, breaking it down into clear steps and w 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order. 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go. 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Next, think about which of the provided tools is the most relevant tool to accomplish the user's task. Go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided. -4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. `open index.html` to show the website you've built. +4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance. diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap index 298f6473c4..9f3ad102e8 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/mcp-server-creation-enabled.snap @@ -369,25 +369,22 @@ Example: Requesting to ask the user for the path to the frontend-config.json fil ## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. +Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. Parameters: - result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -- command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use `open index.html` to display a created html website, or `open localhost:3000` to display a locally running development server. But DO NOT use commands like `echo` or `cat` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions. Usage: Your final result description here -Command to demonstrate result (optional) -Example: Requesting to attempt completion with a result and command +Example: Requesting to attempt completion with a result I've updated the CSS -open index.html ## switch_mode @@ -539,7 +536,7 @@ You accomplish a given task iteratively, breaking it down into clear steps and w 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order. 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go. 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Next, think about which of the provided tools is the most relevant tool to accomplish the user's task. Go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided. -4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. `open index.html` to show the website you've built. +4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance. diff --git a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/partial-reads-enabled.snap b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/partial-reads-enabled.snap index 645e79ba22..2c7e9ec165 100644 --- a/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/partial-reads-enabled.snap +++ b/src/core/prompts/__tests__/__snapshots__/add-custom-instructions/partial-reads-enabled.snap @@ -325,25 +325,22 @@ Example: Requesting to ask the user for the path to the frontend-config.json fil ## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. +Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. Parameters: - result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -- command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use `open index.html` to display a created html website, or `open localhost:3000` to display a locally running development server. But DO NOT use commands like `echo` or `cat` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions. Usage: Your final result description here -Command to demonstrate result (optional) -Example: Requesting to attempt completion with a result and command +Example: Requesting to attempt completion with a result I've updated the CSS -open index.html ## switch_mode @@ -476,7 +473,7 @@ You accomplish a given task iteratively, breaking it down into clear steps and w 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order. 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go. 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Next, think about which of the provided tools is the most relevant tool to accomplish the user's task. Go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided. -4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. `open index.html` to show the website you've built. +4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/consistent-system-prompt.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/consistent-system-prompt.snap index f983669ffb..b4220ce2e8 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/consistent-system-prompt.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/consistent-system-prompt.snap @@ -320,25 +320,22 @@ Example: Requesting to ask the user for the path to the frontend-config.json fil ## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. +Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. Parameters: - result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -- command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use `open index.html` to display a created html website, or `open localhost:3000` to display a locally running development server. But DO NOT use commands like `echo` or `cat` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions. Usage: Your final result description here -Command to demonstrate result (optional) -Example: Requesting to attempt completion with a result and command +Example: Requesting to attempt completion with a result I've updated the CSS -open index.html ## switch_mode @@ -471,7 +468,7 @@ You accomplish a given task iteratively, breaking it down into clear steps and w 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order. 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go. 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Next, think about which of the provided tools is the most relevant tool to accomplish the user's task. Go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided. -4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. `open index.html` to show the website you've built. +4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-computer-use-support.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-computer-use-support.snap index 55045311c2..6248770325 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-computer-use-support.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-computer-use-support.snap @@ -373,25 +373,22 @@ Example: Requesting to ask the user for the path to the frontend-config.json fil ## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. +Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. Parameters: - result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -- command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use `open index.html` to display a created html website, or `open localhost:3000` to display a locally running development server. But DO NOT use commands like `echo` or `cat` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions. Usage: Your final result description here -Command to demonstrate result (optional) -Example: Requesting to attempt completion with a result and command +Example: Requesting to attempt completion with a result I've updated the CSS -open index.html ## switch_mode @@ -527,7 +524,7 @@ You accomplish a given task iteratively, breaking it down into clear steps and w 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order. 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go. 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Next, think about which of the provided tools is the most relevant tool to accomplish the user's task. Go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided. -4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. `open index.html` to show the website you've built. +4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-false.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-false.snap index f983669ffb..b4220ce2e8 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-false.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-false.snap @@ -320,25 +320,22 @@ Example: Requesting to ask the user for the path to the frontend-config.json fil ## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. +Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. Parameters: - result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -- command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use `open index.html` to display a created html website, or `open localhost:3000` to display a locally running development server. But DO NOT use commands like `echo` or `cat` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions. Usage: Your final result description here -Command to demonstrate result (optional) -Example: Requesting to attempt completion with a result and command +Example: Requesting to attempt completion with a result I've updated the CSS -open index.html ## switch_mode @@ -471,7 +468,7 @@ You accomplish a given task iteratively, breaking it down into clear steps and w 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order. 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go. 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Next, think about which of the provided tools is the most relevant tool to accomplish the user's task. Go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided. -4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. `open index.html` to show the website you've built. +4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-true.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-true.snap index 6ca41856cf..1fce8bf785 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-true.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-true.snap @@ -408,25 +408,22 @@ Example: Requesting to ask the user for the path to the frontend-config.json fil ## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. +Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. Parameters: - result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -- command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use `open index.html` to display a created html website, or `open localhost:3000` to display a locally running development server. But DO NOT use commands like `echo` or `cat` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions. Usage: Your final result description here -Command to demonstrate result (optional) -Example: Requesting to attempt completion with a result and command +Example: Requesting to attempt completion with a result I've updated the CSS -open index.html ## switch_mode @@ -559,7 +556,7 @@ You accomplish a given task iteratively, breaking it down into clear steps and w 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order. 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go. 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Next, think about which of the provided tools is the most relevant tool to accomplish the user's task. Go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided. -4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. `open index.html` to show the website you've built. +4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-undefined.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-undefined.snap index f983669ffb..b4220ce2e8 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-undefined.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-diff-enabled-undefined.snap @@ -320,25 +320,22 @@ Example: Requesting to ask the user for the path to the frontend-config.json fil ## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. +Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. Parameters: - result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -- command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use `open index.html` to display a created html website, or `open localhost:3000` to display a locally running development server. But DO NOT use commands like `echo` or `cat` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions. Usage: Your final result description here -Command to demonstrate result (optional) -Example: Requesting to attempt completion with a result and command +Example: Requesting to attempt completion with a result I've updated the CSS -open index.html ## switch_mode @@ -471,7 +468,7 @@ You accomplish a given task iteratively, breaking it down into clear steps and w 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order. 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go. 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Next, think about which of the provided tools is the most relevant tool to accomplish the user's task. Go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided. -4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. `open index.html` to show the website you've built. +4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-different-viewport-size.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-different-viewport-size.snap index 20d6ee8c78..d07dc1d874 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-different-viewport-size.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-different-viewport-size.snap @@ -373,25 +373,22 @@ Example: Requesting to ask the user for the path to the frontend-config.json fil ## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. +Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. Parameters: - result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -- command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use `open index.html` to display a created html website, or `open localhost:3000` to display a locally running development server. But DO NOT use commands like `echo` or `cat` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions. Usage: Your final result description here -Command to demonstrate result (optional) -Example: Requesting to attempt completion with a result and command +Example: Requesting to attempt completion with a result I've updated the CSS -open index.html ## switch_mode @@ -527,7 +524,7 @@ You accomplish a given task iteratively, breaking it down into clear steps and w 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order. 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go. 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Next, think about which of the provided tools is the most relevant tool to accomplish the user's task. Go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided. -4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. `open index.html` to show the website you've built. +4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap index 298f6473c4..9f3ad102e8 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-mcp-hub-provided.snap @@ -369,25 +369,22 @@ Example: Requesting to ask the user for the path to the frontend-config.json fil ## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. +Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. Parameters: - result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -- command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use `open index.html` to display a created html website, or `open localhost:3000` to display a locally running development server. But DO NOT use commands like `echo` or `cat` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions. Usage: Your final result description here -Command to demonstrate result (optional) -Example: Requesting to attempt completion with a result and command +Example: Requesting to attempt completion with a result I've updated the CSS -open index.html ## switch_mode @@ -539,7 +536,7 @@ You accomplish a given task iteratively, breaking it down into clear steps and w 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order. 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go. 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Next, think about which of the provided tools is the most relevant tool to accomplish the user's task. Go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided. -4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. `open index.html` to show the website you've built. +4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance. diff --git a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-undefined-mcp-hub.snap b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-undefined-mcp-hub.snap index f983669ffb..b4220ce2e8 100644 --- a/src/core/prompts/__tests__/__snapshots__/system-prompt/with-undefined-mcp-hub.snap +++ b/src/core/prompts/__tests__/__snapshots__/system-prompt/with-undefined-mcp-hub.snap @@ -320,25 +320,22 @@ Example: Requesting to ask the user for the path to the frontend-config.json fil ## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. +Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. Parameters: - result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. -- command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use `open index.html` to display a created html website, or `open localhost:3000` to display a locally running development server. But DO NOT use commands like `echo` or `cat` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions. Usage: Your final result description here -Command to demonstrate result (optional) -Example: Requesting to attempt completion with a result and command +Example: Requesting to attempt completion with a result I've updated the CSS -open index.html ## switch_mode @@ -471,7 +468,7 @@ You accomplish a given task iteratively, breaking it down into clear steps and w 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order. 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go. 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Next, think about which of the provided tools is the most relevant tool to accomplish the user's task. Go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided. -4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. `open index.html` to show the website you've built. +4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance. diff --git a/src/core/prompts/instructions/create-mcp-server.ts b/src/core/prompts/instructions/create-mcp-server.ts index 3d1d2a20cf..a63fad1de5 100644 --- a/src/core/prompts/instructions/create-mcp-server.ts +++ b/src/core/prompts/instructions/create-mcp-server.ts @@ -50,6 +50,7 @@ Common configuration options for both types: - \`disabled\`: (optional) Set to true to temporarily disable the server - \`timeout\`: (optional) Maximum time in seconds to wait for server responses (default: 60) - \`alwaysAllow\`: (optional) Array of tool names that don't require user confirmation +- \`disabledTools\`: (optional) Array of tool names that are not included in the system prompt and won't be used ### Example Local MCP Server @@ -276,7 +277,7 @@ npm run build 5. Install the MCP Server by adding the MCP server configuration to the settings file located at '${await mcpHub.getMcpSettingsFilePath()}'. The settings file may have other MCP servers already configured, so you would read it first and then add your new server to the existing \`mcpServers\` object. -IMPORTANT: Regardless of what else you see in the MCP settings file, you must default any new MCP servers you create to disabled=false and alwaysAllow=[]. +IMPORTANT: Regardless of what else you see in the MCP settings file, you must default any new MCP servers you create to disabled=false, alwaysAllow=[] and disabledTools=[]. \`\`\`json { diff --git a/src/core/prompts/sections/mcp-servers.ts b/src/core/prompts/sections/mcp-servers.ts index 2a9b6d148a..0af850cbb1 100644 --- a/src/core/prompts/sections/mcp-servers.ts +++ b/src/core/prompts/sections/mcp-servers.ts @@ -17,6 +17,7 @@ export async function getMcpServersSection( .filter((server) => server.status === "connected") .map((server) => { const tools = server.tools + ?.filter((tool) => tool.enabledForPrompt !== false) ?.map((tool) => { const schemaStr = tool.inputSchema ? ` Input Schema: diff --git a/src/core/prompts/sections/objective.ts b/src/core/prompts/sections/objective.ts index db37495086..845db046a0 100644 --- a/src/core/prompts/sections/objective.ts +++ b/src/core/prompts/sections/objective.ts @@ -1,4 +1,3 @@ -import { EXPERIMENT_IDS, experiments } from "../../../shared/experiments" import { CodeIndexManager } from "../../../services/code-index/manager" export function getObjectiveSection( @@ -15,13 +14,6 @@ export function getObjectiveSection( ? "First, if the task involves understanding existing code or functionality, you MUST use the `codebase_search` tool to search for relevant code based on the task's intent BEFORE using any other search or file exploration tools. Then, " : "First, " - // Check if command execution is disabled via experiment - const isCommandDisabled = experimentsConfig && experimentsConfig[EXPERIMENT_IDS.DISABLE_COMPLETION_COMMAND] - - const commandInstruction = !isCommandDisabled - ? " You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. \`open index.html\` to show the website you've built." - : "" - return `==== OBJECTIVE @@ -31,6 +23,6 @@ You accomplish a given task iteratively, breaking it down into clear steps and w 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order. 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go. 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within tags. ${codebaseSearchInstruction}analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Next, think about which of the provided tools is the most relevant tool to accomplish the user's task. Go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided. -4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user.${commandInstruction} +4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance.` } diff --git a/src/core/prompts/tools/__tests__/attempt-completion.spec.ts b/src/core/prompts/tools/__tests__/attempt-completion.spec.ts index fe2d2c7225..026d73789f 100644 --- a/src/core/prompts/tools/__tests__/attempt-completion.spec.ts +++ b/src/core/prompts/tools/__tests__/attempt-completion.spec.ts @@ -1,129 +1,69 @@ import { getAttemptCompletionDescription } from "../attempt-completion" -import { EXPERIMENT_IDS } from "../../../../shared/experiments" -describe("getAttemptCompletionDescription - DISABLE_COMPLETION_COMMAND experiment", () => { - describe("when experiment is disabled (default)", () => { - it("should include command parameter in the description", () => { - const args = { - cwd: "/test/path", - supportsComputerUse: false, - experiments: { - [EXPERIMENT_IDS.DISABLE_COMPLETION_COMMAND]: false, - }, - } +describe("getAttemptCompletionDescription", () => { + it("should NOT include command parameter in the description", () => { + const args = { + cwd: "/test/path", + supportsComputerUse: false, + } - const description = getAttemptCompletionDescription(args) + const description = getAttemptCompletionDescription(args) - // Check that command parameter is included - expect(description).toContain("- command: (optional)") - expect(description).toContain("A CLI command to execute to show a live demo") - expect(description).toContain("Command to demonstrate result (optional)") - expect(description).toContain("open index.html") - }) + // Check that command parameter is NOT included (permanently disabled) + expect(description).not.toContain("- command: (optional)") + expect(description).not.toContain("A CLI command to execute to show a live demo") + expect(description).not.toContain("Command to demonstrate result (optional)") + expect(description).not.toContain("open index.html") - it("should include command parameter when experiments is undefined", () => { - const args = { - cwd: "/test/path", - supportsComputerUse: false, - } - - const description = getAttemptCompletionDescription(args) - - // Check that command parameter is included - expect(description).toContain("- command: (optional)") - expect(description).toContain("A CLI command to execute to show a live demo") - expect(description).toContain("Command to demonstrate result (optional)") - expect(description).toContain("open index.html") - }) - - it("should include command parameter when no args provided", () => { - const description = getAttemptCompletionDescription() - - // Check that command parameter is included - expect(description).toContain("- command: (optional)") - expect(description).toContain("A CLI command to execute to show a live demo") - expect(description).toContain("Command to demonstrate result (optional)") - expect(description).toContain("open index.html") - }) + // But should still have the basic structure + expect(description).toContain("## attempt_completion") + expect(description).toContain("- result: (required)") + expect(description).toContain("") + expect(description).toContain("") }) - describe("when experiment is enabled", () => { - it("should NOT include command parameter in the description", () => { - const args = { - cwd: "/test/path", - supportsComputerUse: false, - experiments: { - [EXPERIMENT_IDS.DISABLE_COMPLETION_COMMAND]: true, - }, - } + it("should work when no args provided", () => { + const description = getAttemptCompletionDescription() - const description = getAttemptCompletionDescription(args) + // Check that command parameter is NOT included (permanently disabled) + expect(description).not.toContain("- command: (optional)") + expect(description).not.toContain("A CLI command to execute to show a live demo") + expect(description).not.toContain("Command to demonstrate result (optional)") + expect(description).not.toContain("open index.html") - // Check that command parameter is NOT included - expect(description).not.toContain("- command: (optional)") - expect(description).not.toContain("A CLI command to execute to show a live demo") - expect(description).not.toContain("Command to demonstrate result (optional)") - expect(description).not.toContain("open index.html") - - // But should still have the basic structure - expect(description).toContain("## attempt_completion") - expect(description).toContain("- result: (required)") - expect(description).toContain("") - expect(description).toContain("") - }) - - it("should show example without command", () => { - const args = { - cwd: "/test/path", - supportsComputerUse: false, - experiments: { - [EXPERIMENT_IDS.DISABLE_COMPLETION_COMMAND]: true, - }, - } - - const description = getAttemptCompletionDescription(args) - - // Check example format - expect(description).toContain("Example: Requesting to attempt completion with a result") - expect(description).toContain("I've updated the CSS") - expect(description).not.toContain("Example: Requesting to attempt completion with a result and command") - }) + // But should still have the basic structure + expect(description).toContain("## attempt_completion") + expect(description).toContain("- result: (required)") + expect(description).toContain("") + expect(description).toContain("") }) - describe("description content", () => { - it("should maintain core functionality description regardless of experiment", () => { - const argsWithExperimentDisabled = { - cwd: "/test/path", - supportsComputerUse: false, - experiments: { - [EXPERIMENT_IDS.DISABLE_COMPLETION_COMMAND]: false, - }, - } + it("should show example without command", () => { + const args = { + cwd: "/test/path", + supportsComputerUse: false, + } - const argsWithExperimentEnabled = { - cwd: "/test/path", - supportsComputerUse: false, - experiments: { - [EXPERIMENT_IDS.DISABLE_COMPLETION_COMMAND]: true, - }, - } + const description = getAttemptCompletionDescription(args) - const descriptionDisabled = getAttemptCompletionDescription(argsWithExperimentDisabled) - const descriptionEnabled = getAttemptCompletionDescription(argsWithExperimentEnabled) + // Check example format + expect(description).toContain("Example: Requesting to attempt completion with a result") + expect(description).toContain("I've updated the CSS") + expect(description).not.toContain("Example: Requesting to attempt completion with a result and command") + }) - // Both should contain core functionality - const coreText = "After each tool use, the user will respond with the result of that tool use" - expect(descriptionDisabled).toContain(coreText) - expect(descriptionEnabled).toContain(coreText) + it("should contain core functionality description", () => { + const description = getAttemptCompletionDescription() - // Both should contain the important note - const importantNote = "IMPORTANT NOTE: This tool CANNOT be used until you've confirmed" - expect(descriptionDisabled).toContain(importantNote) - expect(descriptionEnabled).toContain(importantNote) + // Should contain core functionality + const coreText = "After each tool use, the user will respond with the result of that tool use" + expect(description).toContain(coreText) - // Both should contain result parameter - expect(descriptionDisabled).toContain("- result: (required)") - expect(descriptionEnabled).toContain("- result: (required)") - }) + // Should contain the important note + const importantNote = "IMPORTANT NOTE: This tool CANNOT be used until you've confirmed" + expect(description).toContain(importantNote) + + // Should contain result parameter + expect(description).toContain("- result: (required)") }) }) diff --git a/src/core/prompts/tools/attempt-completion.ts b/src/core/prompts/tools/attempt-completion.ts index ef0f3b9dfd..904f9899e6 100644 --- a/src/core/prompts/tools/attempt-completion.ts +++ b/src/core/prompts/tools/attempt-completion.ts @@ -1,41 +1,17 @@ -import { EXPERIMENT_IDS, experiments } from "../../../shared/experiments" import { ToolArgs } from "./types" export function getAttemptCompletionDescription(args?: ToolArgs): string { - // Check if command execution is disabled via experiment - const isCommandDisabled = - args?.experiments && experiments.isEnabled(args.experiments, EXPERIMENT_IDS.DISABLE_COMPLETION_COMMAND) - - const baseDescription = `## attempt_completion -Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user.${!isCommandDisabled ? " Optionally you may provide a CLI command to showcase the result of your work." : ""} The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. + return `## attempt_completion +Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. Parameters: -- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance.` - - const commandParameter = !isCommandDisabled - ? ` -- command: (optional) A CLI command to execute to show a live demo of the result to the user. For example, use \`open index.html\` to display a created html website, or \`open localhost:3000\` to display a locally running development server. But DO NOT use commands like \`echo\` or \`cat\` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.` - : "" - - const usage = ` +- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance. Usage: Your final result description here -${!isCommandDisabled ? "\nCommand to demonstrate result (optional)" : ""} -` - - const example = !isCommandDisabled - ? ` - -Example: Requesting to attempt completion with a result and command - - -I've updated the CSS -open index.html -` - : ` + Example: Requesting to attempt completion with a result @@ -43,6 +19,4 @@ Example: Requesting to attempt completion with a result I've updated the CSS ` - - return baseDescription + commandParameter + usage + example } diff --git a/src/core/sliding-window/__tests__/sliding-window.spec.ts b/src/core/sliding-window/__tests__/sliding-window.spec.ts index 0f41942547..3bda5351d4 100644 --- a/src/core/sliding-window/__tests__/sliding-window.spec.ts +++ b/src/core/sliding-window/__tests__/sliding-window.spec.ts @@ -19,7 +19,14 @@ import { // Create a mock ApiHandler for testing class MockApiHandler extends BaseProvider { createMessage(): any { - throw new Error("Method not implemented.") + // Mock implementation for testing - returns an async iterable stream + const mockStream = { + async *[Symbol.asyncIterator]() { + yield { type: "text", text: "Mock summary content" } + yield { type: "usage", inputTokens: 100, outputTokens: 50 } + }, + } + return mockStream } getModel(): { id: string; info: ModelInfo } { @@ -265,6 +272,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) // Check the new return type @@ -304,6 +313,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(result).toEqual({ @@ -337,6 +348,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) const result2 = await truncateConversationIfNeeded({ @@ -349,6 +362,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(result1.messages).toEqual(result2.messages) @@ -368,6 +383,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) const result4 = await truncateConversationIfNeeded({ @@ -380,6 +397,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(result3.messages).toEqual(result4.messages) @@ -414,6 +433,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(resultWithSmall).toEqual({ messages: messagesWithSmallContent, @@ -447,6 +468,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(resultWithLarge.messages).not.toEqual(messagesWithLargeContent) // Should truncate expect(resultWithLarge.summary).toBe("") @@ -473,6 +496,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(resultWithVeryLarge.messages).not.toEqual(messagesWithVeryLargeContent) // Should truncate expect(resultWithVeryLarge.summary).toBe("") @@ -509,6 +534,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(result).toEqual({ messages: expectedResult, @@ -554,6 +581,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) // Verify summarizeConversation was called with the right parameters @@ -619,6 +648,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) // Verify summarizeConversation was called @@ -664,6 +695,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 50, // This shouldn't matter since autoCondenseContext is false systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) // Verify summarizeConversation was not called @@ -719,6 +752,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 50, // Set threshold to 50% - our tokens are at 60% systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) // Verify summarizeConversation was called with the right parameters @@ -769,6 +804,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 50, // Set threshold to 50% - our tokens are at 40% systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) // Verify summarizeConversation was not called @@ -787,6 +824,212 @@ describe("Sliding Window", () => { }) }) + /** + * Tests for profile-specific thresholds functionality + */ + describe("profile-specific thresholds", () => { + const createModelInfo = (contextWindow: number, maxTokens?: number): ModelInfo => ({ + contextWindow, + supportsPromptCache: true, + maxTokens, + }) + + const messages: ApiMessage[] = [ + { role: "user", content: "First message" }, + { role: "assistant", content: "Second message" }, + { role: "user", content: "Third message" }, + { role: "assistant", content: "Fourth message" }, + { role: "user", content: "Fifth message" }, + ] + + /** + * Test that a profile's specific threshold is correctly used instead of the global threshold + * when defined in profileThresholds + */ + it("should use profile-specific threshold when enabled and profile has specific threshold", async () => { + const modelInfo = createModelInfo(100000, 30000) + const profileThresholds = { + "test-profile": 60, // Profile-specific threshold of 60% + } + const currentProfileId = "test-profile" + const contextWindow = modelInfo.contextWindow + + // Set tokens to 65% of context window - above profile threshold (60%) but below global default (100%) + const totalTokens = Math.floor(contextWindow * 0.65) // 65000 tokens + + // Create messages with very small content in the last one to avoid token overflow + const messagesWithSmallContent = [ + ...messages.slice(0, -1), + { ...messages[messages.length - 1], content: "" }, + ] + + // Mock the summarizeConversation function + const mockSummary = "Profile-specific threshold summary" + const mockCost = 0.03 + const mockSummarizeResponse: condenseModule.SummarizeResponse = { + messages: [ + { role: "user", content: "First message" }, + { role: "assistant", content: mockSummary, isSummary: true }, + { role: "user", content: "Last message" }, + ], + summary: mockSummary, + cost: mockCost, + newContextTokens: 100, + } + + const summarizeSpy = vi + .spyOn(condenseModule, "summarizeConversation") + .mockResolvedValue(mockSummarizeResponse) + + const result = await truncateConversationIfNeeded({ + messages: messagesWithSmallContent, + totalTokens, + contextWindow, + maxTokens: modelInfo.maxTokens, + apiHandler: mockApiHandler, + autoCondenseContext: true, + autoCondenseContextPercent: 100, // Global threshold of 100% + systemPrompt: "System prompt", + taskId, + profileThresholds, + currentProfileId, + }) + + // Should use summarization because 65% > 60% (profile threshold) + expect(summarizeSpy).toHaveBeenCalled() + expect(result).toMatchObject({ + messages: mockSummarizeResponse.messages, + summary: mockSummary, + cost: mockCost, + prevContextTokens: totalTokens, + }) + + // Clean up + summarizeSpy.mockRestore() + }) + + /** + * Test that when a profile's threshold is set to -1, + * the function correctly falls back to using the global autoCondenseContextPercent + */ + it("should fall back to global threshold when profile threshold is -1", async () => { + const modelInfo = createModelInfo(100000, 30000) + const profileThresholds = { + "test-profile": -1, // Profile threshold set to -1 (use global) + } + const currentProfileId = "test-profile" + const contextWindow = modelInfo.contextWindow + + // Set tokens to 80% of context window - above global threshold (75%) but would be below if profile had its own + const totalTokens = Math.floor(contextWindow * 0.8) // 80000 tokens + + // Create messages with very small content in the last one to avoid token overflow + const messagesWithSmallContent = [ + ...messages.slice(0, -1), + { ...messages[messages.length - 1], content: "" }, + ] + + // Mock the summarizeConversation function + const mockSummary = "Global threshold fallback summary" + const mockCost = 0.04 + const mockSummarizeResponse: condenseModule.SummarizeResponse = { + messages: [ + { role: "user", content: "First message" }, + { role: "assistant", content: mockSummary, isSummary: true }, + { role: "user", content: "Last message" }, + ], + summary: mockSummary, + cost: mockCost, + newContextTokens: 120, + } + + const summarizeSpy = vi + .spyOn(condenseModule, "summarizeConversation") + .mockResolvedValue(mockSummarizeResponse) + + const result = await truncateConversationIfNeeded({ + messages: messagesWithSmallContent, + totalTokens, + contextWindow, + maxTokens: modelInfo.maxTokens, + apiHandler: mockApiHandler, + autoCondenseContext: true, + autoCondenseContextPercent: 75, // Global threshold of 75% + systemPrompt: "System prompt", + taskId, + profileThresholds, + currentProfileId, + }) + + // Should use summarization because 80% > 75% (global threshold, since profile is -1) + expect(summarizeSpy).toHaveBeenCalled() + expect(result).toMatchObject({ + messages: mockSummarizeResponse.messages, + summary: mockSummary, + cost: mockCost, + prevContextTokens: totalTokens, + }) + + // Clean up + summarizeSpy.mockRestore() + }) + + /** + * Test that when a profile does not have a specific threshold defined, + * the function correctly falls back to the global default + */ + it("should fall back to global threshold when profile has no specific threshold", async () => { + const modelInfo = createModelInfo(100000, 30000) + const profileThresholds = { + "other-profile": 50, // Different profile has a threshold + } + const currentProfileId = "test-profile" // This profile is not in profileThresholds + const contextWindow = modelInfo.contextWindow + + // Calculate allowedTokens: contextWindow * (1 - TOKEN_BUFFER_PERCENTAGE) - reservedTokens + // allowedTokens = 100000 * 0.9 - 30000 = 60000 + // Set tokens to be below both the global threshold (80%) and allowedTokens + const totalTokens = 50000 // 50% of context window, well below 60000 allowedTokens and 80% threshold + + // Create messages with very small content in the last one to avoid token overflow + const messagesWithSmallContent = [ + ...messages.slice(0, -1), + { ...messages[messages.length - 1], content: "" }, + ] + + // Reset any previous mock calls + vi.clearAllMocks() + const summarizeSpy = vi.spyOn(condenseModule, "summarizeConversation") + + const result = await truncateConversationIfNeeded({ + messages: messagesWithSmallContent, + totalTokens, + contextWindow, + maxTokens: modelInfo.maxTokens, + apiHandler: mockApiHandler, + autoCondenseContext: true, + autoCondenseContextPercent: 80, // Global threshold of 80% + systemPrompt: "System prompt", + taskId, + profileThresholds, + currentProfileId, + }) + + // Should NOT use summarization because 50% < 80% (global threshold, since profile has no specific threshold) + // and totalTokens (50000) < allowedTokens (60000) + expect(summarizeSpy).not.toHaveBeenCalled() + expect(result).toEqual({ + messages: messagesWithSmallContent, + summary: "", + cost: 0, + prevContextTokens: totalTokens, + }) + + // Clean up + summarizeSpy.mockRestore() + }) + }) + /** * Tests for the getMaxTokens function (private but tested through truncateConversationIfNeeded) */ @@ -829,6 +1072,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(result1).toEqual({ messages: messagesWithSmallContent, @@ -848,6 +1093,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(result2.messages).not.toEqual(messagesWithSmallContent) expect(result2.messages.length).toBe(3) // Truncated with 0.5 fraction @@ -878,6 +1125,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(result1).toEqual({ messages: messagesWithSmallContent, @@ -897,6 +1146,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(result2.messages).not.toEqual(messagesWithSmallContent) expect(result2.messages.length).toBe(3) // Truncated with 0.5 fraction @@ -926,6 +1177,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(result1.messages).toEqual(messagesWithSmallContent) @@ -940,6 +1193,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(result2).not.toEqual(messagesWithSmallContent) expect(result2.messages.length).toBe(3) // Truncated with 0.5 fraction @@ -967,6 +1222,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(result1.messages).toEqual(messagesWithSmallContent) @@ -981,6 +1238,8 @@ describe("Sliding Window", () => { autoCondenseContextPercent: 100, systemPrompt: "System prompt", taskId, + profileThresholds: {}, + currentProfileId: "default", }) expect(result2).not.toEqual(messagesWithSmallContent) expect(result2.messages.length).toBe(3) // Truncated with 0.5 fraction diff --git a/src/core/sliding-window/index.ts b/src/core/sliding-window/index.ts index dc9eaf718d..ae26f51a52 100644 --- a/src/core/sliding-window/index.ts +++ b/src/core/sliding-window/index.ts @@ -3,7 +3,7 @@ import { Anthropic } from "@anthropic-ai/sdk" import { TelemetryService } from "@roo-code/telemetry" import { ApiHandler } from "../../api" -import { summarizeConversation, SummarizeResponse } from "../condense" +import { MAX_CONDENSE_THRESHOLD, MIN_CONDENSE_THRESHOLD, summarizeConversation, SummarizeResponse } from "../condense" import { ApiMessage } from "../task-persistence/apiMessages" /** @@ -74,6 +74,8 @@ type TruncateOptions = { taskId: string customCondensingPrompt?: string condensingApiHandler?: ApiHandler + profileThresholds: Record + currentProfileId: string } type TruncateResponse = SummarizeResponse & { prevContextTokens: number } @@ -97,6 +99,8 @@ export async function truncateConversationIfNeeded({ taskId, customCondensingPrompt, condensingApiHandler, + profileThresholds, + currentProfileId, }: TruncateOptions): Promise { let error: string | undefined let cost = 0 @@ -117,9 +121,29 @@ export async function truncateConversationIfNeeded({ // Truncate if we're within TOKEN_BUFFER_PERCENTAGE of the context window const allowedTokens = contextWindow * (1 - TOKEN_BUFFER_PERCENTAGE) - reservedTokens + // Determine the effective threshold to use + let effectiveThreshold = autoCondenseContextPercent + const profileThreshold = profileThresholds[currentProfileId] + if (profileThreshold !== undefined) { + if (profileThreshold === -1) { + // Special case: -1 means inherit from global setting + effectiveThreshold = autoCondenseContextPercent + } else if (profileThreshold >= MIN_CONDENSE_THRESHOLD && profileThreshold <= MAX_CONDENSE_THRESHOLD) { + // Valid custom threshold + effectiveThreshold = profileThreshold + } else { + // Invalid threshold value, fall back to global setting + console.warn( + `Invalid profile threshold ${profileThreshold} for profile "${currentProfileId}". Using global default of ${autoCondenseContextPercent}%`, + ) + effectiveThreshold = autoCondenseContextPercent + } + } + // If no specific threshold is found for the profile, fall back to global setting + if (autoCondenseContext) { const contextPercent = (100 * prevContextTokens) / contextWindow - if (contextPercent >= autoCondenseContextPercent || prevContextTokens > allowedTokens) { + if (contextPercent >= effectiveThreshold || prevContextTokens > allowedTokens) { // Attempt to intelligently condense the context const result = await summarizeConversation( messages, diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts index a6a9d89986..46da7485ed 100644 --- a/src/core/task/Task.ts +++ b/src/core/task/Task.ts @@ -140,9 +140,17 @@ export class Task extends EventEmitter { // API readonly apiConfiguration: ProviderSettings api: ApiHandler - private lastApiRequestTime?: number + private static lastGlobalApiRequestTime?: number private consecutiveAutoApprovedRequestsCount: number = 0 + /** + * Reset the global API request timestamp. This should only be used for testing. + * @internal + */ + static resetGlobalApiRequestTime(): void { + Task.lastGlobalApiRequestTime = undefined + } + toolRepetitionDetector: ToolRepetitionDetector rooIgnoreController?: RooIgnoreController rooProtectedController?: RooProtectedController @@ -1431,19 +1439,22 @@ export class Task extends EventEmitter { } finally { this.isStreaming = false } - if ( - inputTokens > 0 || - outputTokens > 0 || - cacheWriteTokens > 0 || - cacheReadTokens > 0 || - typeof totalCost !== "undefined" - ) { + + if (inputTokens > 0 || outputTokens > 0 || cacheWriteTokens > 0 || cacheReadTokens > 0) { TelemetryService.instance.captureLlmCompletion(this.taskId, { inputTokens, outputTokens, cacheWriteTokens, cacheReadTokens, - cost: totalCost, + cost: + totalCost ?? + calculateApiCostAnthropic( + this.api.getModel().info, + inputTokens, + outputTokens, + cacheWriteTokens, + cacheReadTokens, + ), }) } @@ -1632,6 +1643,7 @@ export class Task extends EventEmitter { mode, autoCondenseContext = true, autoCondenseContextPercent = 100, + profileThresholds = {}, } = state ?? {} // Get condensing configuration for automatic triggers @@ -1657,10 +1669,11 @@ export class Task extends EventEmitter { let rateLimitDelay = 0 - // Only apply rate limiting if this isn't the first request - if (this.lastApiRequestTime) { + // Use the shared timestamp so that subtasks respect the same rate-limit + // window as their parent tasks. + if (Task.lastGlobalApiRequestTime) { const now = Date.now() - const timeSinceLastRequest = now - this.lastApiRequestTime + const timeSinceLastRequest = now - Task.lastGlobalApiRequestTime const rateLimit = apiConfiguration?.rateLimitSeconds || 0 rateLimitDelay = Math.ceil(Math.max(0, rateLimit * 1000 - timeSinceLastRequest) / 1000) } @@ -1675,8 +1688,9 @@ export class Task extends EventEmitter { } } - // Update last request time before making the request - this.lastApiRequestTime = Date.now() + // Update last request time before making the request so that subsequent + // requests — even from new subtasks — will honour the provider's rate-limit. + Task.lastGlobalApiRequestTime = Date.now() const systemPrompt = await this.getSystemPrompt() const { contextTokens } = this.getTokenUsage() @@ -1706,6 +1720,8 @@ export class Task extends EventEmitter { taskId: this.taskId, customCondensingPrompt, condensingApiHandler, + profileThresholds, + currentProfileId: state?.currentApiConfigName || "default", }) if (truncateResult.messages !== this.apiConversationHistory) { await this.overwriteApiConversationHistory(truncateResult.messages) diff --git a/src/core/task/__tests__/Task.spec.ts b/src/core/task/__tests__/Task.spec.ts index 5798a0bacd..693f72d1c7 100644 --- a/src/core/task/__tests__/Task.spec.ts +++ b/src/core/task/__tests__/Task.spec.ts @@ -18,38 +18,55 @@ import { MultiSearchReplaceDiffStrategy } from "../../diff/strategies/multi-sear import { MultiFileSearchReplaceDiffStrategy } from "../../diff/strategies/multi-file-search-replace" import { EXPERIMENT_IDS } from "../../../shared/experiments" +// Mock delay before any imports that might use it +vi.mock("delay", () => ({ + __esModule: true, + default: vi.fn().mockResolvedValue(undefined), +})) + +import delay from "delay" + vi.mock("execa", () => ({ execa: vi.fn(), })) -vi.mock("fs/promises", () => ({ - mkdir: vi.fn().mockResolvedValue(undefined), - writeFile: vi.fn().mockResolvedValue(undefined), - readFile: vi.fn().mockImplementation((filePath) => { - if (filePath.includes("ui_messages.json")) { - return Promise.resolve(JSON.stringify(mockMessages)) - } - if (filePath.includes("api_conversation_history.json")) { - return Promise.resolve( - JSON.stringify([ - { - role: "user", - content: [{ type: "text", text: "historical task" }], - ts: Date.now(), - }, - { - role: "assistant", - content: [{ type: "text", text: "I'll help you with that task." }], - ts: Date.now(), - }, - ]), - ) - } - return Promise.resolve("[]") - }), - unlink: vi.fn().mockResolvedValue(undefined), - rmdir: vi.fn().mockResolvedValue(undefined), -})) +vi.mock("fs/promises", async (importOriginal) => { + const actual = (await importOriginal()) as Record + const mockFunctions = { + mkdir: vi.fn().mockResolvedValue(undefined), + writeFile: vi.fn().mockResolvedValue(undefined), + readFile: vi.fn().mockImplementation((filePath) => { + if (filePath.includes("ui_messages.json")) { + return Promise.resolve(JSON.stringify(mockMessages)) + } + if (filePath.includes("api_conversation_history.json")) { + return Promise.resolve( + JSON.stringify([ + { + role: "user", + content: [{ type: "text", text: "historical task" }], + ts: Date.now(), + }, + { + role: "assistant", + content: [{ type: "text", text: "I'll help you with that task." }], + ts: Date.now(), + }, + ]), + ) + } + return Promise.resolve("[]") + }), + unlink: vi.fn().mockResolvedValue(undefined), + rmdir: vi.fn().mockResolvedValue(undefined), + } + + return { + ...actual, + ...mockFunctions, + default: mockFunctions, + } +}) vi.mock("p-wait-for", () => ({ default: vi.fn().mockImplementation(async () => Promise.resolve()), @@ -869,6 +886,353 @@ describe("Cline", () => { }) }) + describe("Subtask Rate Limiting", () => { + let mockProvider: any + let mockApiConfig: any + let mockDelay: ReturnType + + beforeEach(() => { + vi.clearAllMocks() + // Reset the global timestamp before each test + Task.resetGlobalApiRequestTime() + + mockApiConfig = { + apiProvider: "anthropic", + apiKey: "test-key", + rateLimitSeconds: 5, + } + + mockProvider = { + context: { + globalStorageUri: { fsPath: "/test/storage" }, + }, + getState: vi.fn().mockResolvedValue({ + apiConfiguration: mockApiConfig, + }), + say: vi.fn(), + postStateToWebview: vi.fn().mockResolvedValue(undefined), + postMessageToWebview: vi.fn().mockResolvedValue(undefined), + updateTaskHistory: vi.fn().mockResolvedValue(undefined), + } + + // Get the mocked delay function + mockDelay = delay as ReturnType + mockDelay.mockClear() + }) + + afterEach(() => { + // Clean up the global state after each test + Task.resetGlobalApiRequestTime() + }) + + it("should enforce rate limiting across parent and subtask", async () => { + // Add a spy to track getState calls + const getStateSpy = vi.spyOn(mockProvider, "getState") + + // Create parent task + const parent = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "parent task", + startTask: false, + }) + + // Mock the API stream response + const mockStream = { + async *[Symbol.asyncIterator]() { + yield { type: "text", text: "parent response" } + }, + async next() { + return { done: true, value: { type: "text", text: "parent response" } } + }, + async return() { + return { done: true, value: undefined } + }, + async throw(e: any) { + throw e + }, + [Symbol.asyncDispose]: async () => {}, + } as AsyncGenerator + + vi.spyOn(parent.api, "createMessage").mockReturnValue(mockStream) + + // Make an API request with the parent task + const parentIterator = parent.attemptApiRequest(0) + await parentIterator.next() + + // Verify no delay was applied for the first request + expect(mockDelay).not.toHaveBeenCalled() + + // Create a subtask immediately after + const child = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "child task", + parentTask: parent, + rootTask: parent, + startTask: false, + }) + + // Mock the child's API stream + const childMockStream = { + async *[Symbol.asyncIterator]() { + yield { type: "text", text: "child response" } + }, + async next() { + return { done: true, value: { type: "text", text: "child response" } } + }, + async return() { + return { done: true, value: undefined } + }, + async throw(e: any) { + throw e + }, + [Symbol.asyncDispose]: async () => {}, + } as AsyncGenerator + + vi.spyOn(child.api, "createMessage").mockReturnValue(childMockStream) + + // Make an API request with the child task + const childIterator = child.attemptApiRequest(0) + await childIterator.next() + + // Verify rate limiting was applied + expect(mockDelay).toHaveBeenCalledTimes(mockApiConfig.rateLimitSeconds) + expect(mockDelay).toHaveBeenCalledWith(1000) + }, 10000) // Increase timeout to 10 seconds + + it("should not apply rate limiting if enough time has passed", async () => { + // Create parent task + const parent = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "parent task", + startTask: false, + }) + + // Mock the API stream response + const mockStream = { + async *[Symbol.asyncIterator]() { + yield { type: "text", text: "response" } + }, + async next() { + return { done: true, value: { type: "text", text: "response" } } + }, + async return() { + return { done: true, value: undefined } + }, + async throw(e: any) { + throw e + }, + [Symbol.asyncDispose]: async () => {}, + } as AsyncGenerator + + vi.spyOn(parent.api, "createMessage").mockReturnValue(mockStream) + + // Make an API request with the parent task + const parentIterator = parent.attemptApiRequest(0) + await parentIterator.next() + + // Simulate time passing (more than rate limit) + const originalDateNow = Date.now + const mockTime = Date.now() + (mockApiConfig.rateLimitSeconds + 1) * 1000 + Date.now = vi.fn(() => mockTime) + + // Create a subtask after time has passed + const child = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "child task", + parentTask: parent, + rootTask: parent, + startTask: false, + }) + + vi.spyOn(child.api, "createMessage").mockReturnValue(mockStream) + + // Make an API request with the child task + const childIterator = child.attemptApiRequest(0) + await childIterator.next() + + // Verify no rate limiting was applied + expect(mockDelay).not.toHaveBeenCalled() + + // Restore Date.now + Date.now = originalDateNow + }) + + it("should share rate limiting across multiple subtasks", async () => { + // Create parent task + const parent = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "parent task", + startTask: false, + }) + + // Mock the API stream response + const mockStream = { + async *[Symbol.asyncIterator]() { + yield { type: "text", text: "response" } + }, + async next() { + return { done: true, value: { type: "text", text: "response" } } + }, + async return() { + return { done: true, value: undefined } + }, + async throw(e: any) { + throw e + }, + [Symbol.asyncDispose]: async () => {}, + } as AsyncGenerator + + vi.spyOn(parent.api, "createMessage").mockReturnValue(mockStream) + + // Make an API request with the parent task + const parentIterator = parent.attemptApiRequest(0) + await parentIterator.next() + + // Create first subtask + const child1 = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "child task 1", + parentTask: parent, + rootTask: parent, + startTask: false, + }) + + vi.spyOn(child1.api, "createMessage").mockReturnValue(mockStream) + + // Make an API request with the first child task + const child1Iterator = child1.attemptApiRequest(0) + await child1Iterator.next() + + // Verify rate limiting was applied + const firstDelayCount = mockDelay.mock.calls.length + expect(firstDelayCount).toBe(mockApiConfig.rateLimitSeconds) + + // Clear the mock to count new delays + mockDelay.mockClear() + + // Create second subtask immediately after + const child2 = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "child task 2", + parentTask: parent, + rootTask: parent, + startTask: false, + }) + + vi.spyOn(child2.api, "createMessage").mockReturnValue(mockStream) + + // Make an API request with the second child task + const child2Iterator = child2.attemptApiRequest(0) + await child2Iterator.next() + + // Verify rate limiting was applied again + expect(mockDelay).toHaveBeenCalledTimes(mockApiConfig.rateLimitSeconds) + }, 15000) // Increase timeout to 15 seconds + + it("should handle rate limiting with zero rate limit", async () => { + // Update config to have zero rate limit + mockApiConfig.rateLimitSeconds = 0 + mockProvider.getState.mockResolvedValue({ + apiConfiguration: mockApiConfig, + }) + + // Create parent task + const parent = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "parent task", + startTask: false, + }) + + // Mock the API stream response + const mockStream = { + async *[Symbol.asyncIterator]() { + yield { type: "text", text: "response" } + }, + async next() { + return { done: true, value: { type: "text", text: "response" } } + }, + async return() { + return { done: true, value: undefined } + }, + async throw(e: any) { + throw e + }, + [Symbol.asyncDispose]: async () => {}, + } as AsyncGenerator + + vi.spyOn(parent.api, "createMessage").mockReturnValue(mockStream) + + // Make an API request with the parent task + const parentIterator = parent.attemptApiRequest(0) + await parentIterator.next() + + // Create a subtask + const child = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "child task", + parentTask: parent, + rootTask: parent, + startTask: false, + }) + + vi.spyOn(child.api, "createMessage").mockReturnValue(mockStream) + + // Make an API request with the child task + const childIterator = child.attemptApiRequest(0) + await childIterator.next() + + // Verify no delay was applied + expect(mockDelay).not.toHaveBeenCalled() + }) + + it("should update global timestamp even when no rate limiting is needed", async () => { + // Create task + const task = new Task({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "test task", + startTask: false, + }) + + // Mock the API stream response + const mockStream = { + async *[Symbol.asyncIterator]() { + yield { type: "text", text: "response" } + }, + async next() { + return { done: true, value: { type: "text", text: "response" } } + }, + async return() { + return { done: true, value: undefined } + }, + async throw(e: any) { + throw e + }, + [Symbol.asyncDispose]: async () => {}, + } as AsyncGenerator + + vi.spyOn(task.api, "createMessage").mockReturnValue(mockStream) + + // Make an API request + const iterator = task.attemptApiRequest(0) + await iterator.next() + + // Access the private static property via reflection for testing + const globalTimestamp = (Task as any).lastGlobalApiRequestTime + expect(globalTimestamp).toBeDefined() + expect(globalTimestamp).toBeGreaterThan(0) + }) + }) + describe("Dynamic Strategy Selection", () => { let mockProvider: any let mockApiConfig: any diff --git a/src/core/tools/__tests__/attemptCompletionTool.experiment.spec.ts b/src/core/tools/__tests__/attemptCompletionTool.experiment.spec.ts deleted file mode 100644 index 9ed8f22019..0000000000 --- a/src/core/tools/__tests__/attemptCompletionTool.experiment.spec.ts +++ /dev/null @@ -1,356 +0,0 @@ -// Mocks must come first, before imports -vi.mock("../executeCommandTool", () => ({ - executeCommand: vi.fn(), -})) - -vi.mock("@roo-code/telemetry", () => ({ - TelemetryService: { - instance: { - captureTaskCompleted: vi.fn(), - }, - }, -})) - -// Then imports -import type { Mock } from "vitest" -import { attemptCompletionTool } from "../attemptCompletionTool" -import { EXPERIMENT_IDS } from "../../../shared/experiments" -import { executeCommand } from "../executeCommandTool" - -describe("attemptCompletionTool - DISABLE_COMPLETION_COMMAND experiment", () => { - let mockCline: any - let mockAskApproval: Mock - let mockHandleError: Mock - let mockPushToolResult: Mock - let mockRemoveClosingTag: Mock - let mockToolDescription: Mock - let mockAskFinishSubTaskApproval: Mock - - beforeEach(() => { - vi.clearAllMocks() - - mockAskApproval = vi.fn().mockResolvedValue(true) - mockHandleError = vi.fn() - mockPushToolResult = vi.fn() - mockRemoveClosingTag = vi.fn((tag, content) => content) - mockToolDescription = vi.fn().mockReturnValue("attempt_completion") - mockAskFinishSubTaskApproval = vi.fn() - - mockCline = { - say: vi.fn(), - ask: vi.fn().mockResolvedValue({ response: "yesButtonClicked", text: "", images: [] }), - clineMessages: [], - lastMessageTs: Date.now(), - consecutiveMistakeCount: 0, - sayAndCreateMissingParamError: vi.fn(), - recordToolError: vi.fn(), - emit: vi.fn(), - getTokenUsage: vi.fn().mockReturnValue({}), - toolUsage: {}, - userMessageContent: [], - taskId: "test-task-id", - providerRef: { - deref: vi.fn().mockReturnValue({ - getState: vi.fn().mockResolvedValue({ - experiments: {}, - }), - }), - }, - } - }) - - describe("when experiment is disabled (default)", () => { - beforeEach(() => { - mockCline.providerRef.deref().getState.mockResolvedValue({ - experiments: { - [EXPERIMENT_IDS.DISABLE_COMPLETION_COMMAND]: false, - }, - }) - }) - - it("should execute command when provided", async () => { - const mockExecuteCommand = executeCommand as Mock - mockExecuteCommand.mockResolvedValue([false, "Command executed successfully"]) - - // Mock clineMessages with a previous message that's not a command ask - mockCline.clineMessages = [{ say: "previous_message", text: "Previous message" }] - - const block = { - params: { - result: "Task completed successfully", - command: "npm test", - }, - partial: false, - } - - await attemptCompletionTool( - mockCline, - block as any, - mockAskApproval, - mockHandleError, - mockPushToolResult, - mockRemoveClosingTag, - mockToolDescription, - mockAskFinishSubTaskApproval, - ) - - // When there's a lastMessage that's not a command ask, it should say completion_result first - expect(mockCline.say).toHaveBeenCalledWith( - "completion_result", - "Task completed successfully", - undefined, - false, - ) - expect(mockCline.emit).toHaveBeenCalledWith( - "taskCompleted", - mockCline.taskId, - expect.any(Object), - expect.any(Object), - ) - expect(mockAskApproval).toHaveBeenCalledWith("command", "npm test") - expect(mockExecuteCommand).toHaveBeenCalled() - }) - - it("should not execute command when user rejects", async () => { - mockAskApproval.mockResolvedValue(false) - const mockExecuteCommand = executeCommand as Mock - - // Mock clineMessages with a previous message that's not a command ask - mockCline.clineMessages = [{ say: "previous_message", text: "Previous message" }] - - const block = { - params: { - result: "Task completed successfully", - command: "npm test", - }, - partial: false, - } - - await attemptCompletionTool( - mockCline, - block as any, - mockAskApproval, - mockHandleError, - mockPushToolResult, - mockRemoveClosingTag, - mockToolDescription, - mockAskFinishSubTaskApproval, - ) - - // Should say completion_result and emit before asking for approval - expect(mockCline.say).toHaveBeenCalledWith( - "completion_result", - "Task completed successfully", - undefined, - false, - ) - expect(mockCline.emit).toHaveBeenCalledWith( - "taskCompleted", - mockCline.taskId, - expect.any(Object), - expect.any(Object), - ) - expect(mockAskApproval).toHaveBeenCalledWith("command", "npm test") - expect(mockExecuteCommand).not.toHaveBeenCalled() - }) - }) - - describe("when experiment is enabled", () => { - beforeEach(() => { - mockCline.providerRef.deref().getState.mockResolvedValue({ - experiments: { - [EXPERIMENT_IDS.DISABLE_COMPLETION_COMMAND]: true, - }, - }) - }) - - it("should NOT execute command even when provided", async () => { - const mockExecuteCommand = executeCommand as Mock - - const block = { - params: { - result: "Task completed successfully", - command: "npm test", - }, - partial: false, - } - - await attemptCompletionTool( - mockCline, - block as any, - mockAskApproval, - mockHandleError, - mockPushToolResult, - mockRemoveClosingTag, - mockToolDescription, - mockAskFinishSubTaskApproval, - ) - - expect(mockCline.say).toHaveBeenCalledWith( - "completion_result", - "Task completed successfully", - undefined, - false, - ) - expect(mockAskApproval).not.toHaveBeenCalled() - expect(mockExecuteCommand).not.toHaveBeenCalled() - }) - - it("should complete normally without command execution", async () => { - const block = { - params: { - result: "Task completed successfully", - command: "npm test", - }, - partial: false, - } - - await attemptCompletionTool( - mockCline, - block as any, - mockAskApproval, - mockHandleError, - mockPushToolResult, - mockRemoveClosingTag, - mockToolDescription, - mockAskFinishSubTaskApproval, - ) - - expect(mockCline.say).toHaveBeenCalledWith( - "completion_result", - "Task completed successfully", - undefined, - false, - ) - expect(mockCline.emit).toHaveBeenCalledWith( - "taskCompleted", - mockCline.taskId, - expect.any(Object), - expect.any(Object), - ) - expect(mockAskApproval).not.toHaveBeenCalled() - }) - }) - - describe("when no command is provided", () => { - it("should work the same regardless of experiment state", async () => { - const block = { - params: { - result: "Task completed successfully", - }, - partial: false, - } - - // Test with experiment disabled - mockCline.providerRef.deref().getState.mockResolvedValue({ - experiments: { - [EXPERIMENT_IDS.DISABLE_COMPLETION_COMMAND]: false, - }, - }) - - await attemptCompletionTool( - mockCline, - block as any, - mockAskApproval, - mockHandleError, - mockPushToolResult, - mockRemoveClosingTag, - mockToolDescription, - mockAskFinishSubTaskApproval, - ) - - expect(mockCline.say).toHaveBeenCalledWith( - "completion_result", - "Task completed successfully", - undefined, - false, - ) - expect(mockAskApproval).not.toHaveBeenCalled() - - // Reset mocks - vi.clearAllMocks() - - // Test with experiment enabled - mockCline.providerRef.deref().getState.mockResolvedValue({ - experiments: { - [EXPERIMENT_IDS.DISABLE_COMPLETION_COMMAND]: true, - }, - }) - - await attemptCompletionTool( - mockCline, - block as any, - mockAskApproval, - mockHandleError, - mockPushToolResult, - mockRemoveClosingTag, - mockToolDescription, - mockAskFinishSubTaskApproval, - ) - - expect(mockCline.say).toHaveBeenCalledWith( - "completion_result", - "Task completed successfully", - undefined, - false, - ) - expect(mockAskApproval).not.toHaveBeenCalled() - }) - }) - - describe("error handling", () => { - it("should handle missing result parameter", async () => { - const block = { - params: {}, - partial: false, - } - - await attemptCompletionTool( - mockCline, - block as any, - mockAskApproval, - mockHandleError, - mockPushToolResult, - mockRemoveClosingTag, - mockToolDescription, - mockAskFinishSubTaskApproval, - ) - - expect(mockCline.consecutiveMistakeCount).toBe(1) - expect(mockCline.recordToolError).toHaveBeenCalledWith("attempt_completion") - expect(mockCline.sayAndCreateMissingParamError).toHaveBeenCalledWith("attempt_completion", "result") - }) - - it("should handle state retrieval errors gracefully", async () => { - // Mock provider ref to return null - mockCline.providerRef.deref.mockReturnValue(null) - - // Mock clineMessages to simulate no previous messages - mockCline.clineMessages = [] - - const block = { - params: { - result: "Task completed successfully", - command: "npm test", - }, - partial: false, - } - - await attemptCompletionTool( - mockCline, - block as any, - mockAskApproval, - mockHandleError, - mockPushToolResult, - mockRemoveClosingTag, - mockToolDescription, - mockAskFinishSubTaskApproval, - ) - - // When state retrieval fails, it defaults to not disabled (false), so it will try to execute command - // Since there's no lastMessage, it goes directly to askApproval - expect(mockAskApproval).toHaveBeenCalledWith("command", "npm test") - expect(mockCline.say).not.toHaveBeenCalled() - }) - }) -}) diff --git a/src/core/tools/__tests__/writeToFileTool.spec.ts b/src/core/tools/__tests__/writeToFileTool.spec.ts index 47a674cdfb..f223d4b0fc 100644 --- a/src/core/tools/__tests__/writeToFileTool.spec.ts +++ b/src/core/tools/__tests__/writeToFileTool.spec.ts @@ -243,14 +243,14 @@ describe("writeToFileTool", () => { }) describe("file existence detection", () => { - it("detects existing file and sets editType to modify", async () => { + it.skipIf(process.platform === "win32")("detects existing file and sets editType to modify", async () => { await executeWriteFileTool({}, { fileExists: true }) expect(mockedFileExistsAtPath).toHaveBeenCalledWith(absoluteFilePath) expect(mockCline.diffViewProvider.editType).toBe("modify") }) - it("detects new file and sets editType to create", async () => { + it.skipIf(process.platform === "win32")("detects new file and sets editType to create", async () => { await executeWriteFileTool({}, { fileExists: false }) expect(mockedFileExistsAtPath).toHaveBeenCalledWith(absoluteFilePath) diff --git a/src/core/tools/attemptCompletionTool.ts b/src/core/tools/attemptCompletionTool.ts index d45ce0f65c..57f5870022 100644 --- a/src/core/tools/attemptCompletionTool.ts +++ b/src/core/tools/attemptCompletionTool.ts @@ -14,8 +14,6 @@ import { AskFinishSubTaskApproval, } from "../../shared/tools" import { formatResponse } from "../prompts/responses" -import { type ExecuteCommandOptions, executeCommand } from "./executeCommandTool" -import { EXPERIMENT_IDS, experiments, experimentDefault } from "../../shared/experiments" export async function attemptCompletionTool( cline: Task, @@ -67,48 +65,11 @@ export async function attemptCompletionTool( cline.consecutiveMistakeCount = 0 - let commandResult: ToolResponse | undefined - - // Check if command execution is disabled via experiment - const state = await cline.providerRef.deref()?.getState() - const experimentsConfig = state?.experiments ?? experimentDefault - const isCommandDisabled = experiments.isEnabled( - experimentsConfig, - EXPERIMENT_IDS.DISABLE_COMPLETION_COMMAND, - ) - - if (command && !isCommandDisabled) { - if (lastMessage && lastMessage.ask !== "command") { - // Haven't sent a command message yet so first send completion_result then command. - await cline.say("completion_result", result, undefined, false) - TelemetryService.instance.captureTaskCompleted(cline.taskId) - cline.emit("taskCompleted", cline.taskId, cline.getTokenUsage(), cline.toolUsage) - } - - // Complete command message. - const didApprove = await askApproval("command", command) - - if (!didApprove) { - return - } - - const executionId = cline.lastMessageTs?.toString() ?? Date.now().toString() - const options: ExecuteCommandOptions = { executionId, command } - const [userRejected, execCommandResult] = await executeCommand(cline, options) - - if (userRejected) { - cline.didRejectTool = true - pushToolResult(execCommandResult) - return - } - - // User didn't reject, but the command may have output. - commandResult = execCommandResult - } else { - await cline.say("completion_result", result, undefined, false) - TelemetryService.instance.captureTaskCompleted(cline.taskId) - cline.emit("taskCompleted", cline.taskId, cline.getTokenUsage(), cline.toolUsage) - } + // Command execution is permanently disabled in attempt_completion + // Users must use execute_command tool separately before attempt_completion + await cline.say("completion_result", result, undefined, false) + TelemetryService.instance.captureTaskCompleted(cline.taskId) + cline.emit("taskCompleted", cline.taskId, cline.getTokenUsage(), cline.toolUsage) if (cline.parentTask) { const didApprove = await askFinishSubTaskApproval() @@ -138,14 +99,6 @@ export async function attemptCompletionTool( await cline.say("user_feedback", text ?? "", images) const toolResults: (Anthropic.TextBlockParam | Anthropic.ImageBlockParam)[] = [] - if (commandResult) { - if (typeof commandResult === "string") { - toolResults.push({ type: "text", text: commandResult }) - } else if (Array.isArray(commandResult)) { - toolResults.push(...commandResult) - } - } - toolResults.push({ type: "text", text: `The user has provided feedback on the results. Consider their input to continue the task, and then attempt completion again.\n\n${text}\n`, diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 94264ba0de..dff2263a06 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -23,6 +23,7 @@ import { type TerminalActionPromptType, type HistoryItem, type CloudUserInfo, + type MarketplaceItem, requestyDefaultModelId, openRouterDefaultModelId, glamaDefaultModelId, @@ -37,7 +38,7 @@ import { Package } from "../../shared/package" import { findLast } from "../../shared/array" import { supportPrompt } from "../../shared/support-prompt" import { GlobalFileNames } from "../../shared/globalFileNames" -import { ExtensionMessage } from "../../shared/ExtensionMessage" +import { ExtensionMessage, MarketplaceInstalledMetadata } from "../../shared/ExtensionMessage" import { Mode, defaultModeSlug } from "../../shared/modes" import { experimentDefault, experiments, EXPERIMENT_IDS } from "../../shared/experiments" import { formatLanguage } from "../../shared/language" @@ -108,7 +109,7 @@ export class ClineProvider public isViewLaunched = false public settingsImportedAt?: number - public readonly latestAnnouncementId = "dec-12-2025-3-20" // Update for v3.20.0 announcement + public readonly latestAnnouncementId = "jun-17-2025-3-21" // Update for v3.21.0 announcement public readonly providerSettingsManager: ProviderSettingsManager public readonly customModesManager: CustomModesManager @@ -232,6 +233,12 @@ export class ClineProvider await this.getCurrentCline()?.resumePausedTask(lastMessage) } + // Clear the current task without treating it as a subtask + // This is used when the user cancels a task that is not a subtask + async clearTask() { + await this.removeClineFromStack() + } + /* VSCode extensions use the disposable pattern to clean up resources when the sidebar/editor tab is closed by the user or system. This applies to event listening, commands, interacting with the UI, etc. - https://vscode-docs.readthedocs.io/en/stable/extensions/patterns-and-principles/ @@ -665,7 +672,7 @@ export class ClineProvider const csp = [ "default-src 'none'", - `font-src ${webview.cspSource}`, + `font-src ${webview.cspSource} data:`, `style-src ${webview.cspSource} 'unsafe-inline' https://* http://${localServerUrl} http://0.0.0.0:${localPort}`, `img-src ${webview.cspSource} https://storage.googleapis.com https://img.clerk.com data:`, `media-src ${webview.cspSource}`, @@ -752,7 +759,7 @@ export class ClineProvider - +