feat: add hook engine and project updates

This commit is contained in:
kidist demessie 2026-02-18 18:22:12 +03:00
parent 54c81cbbe4
commit a87d239cf2
50 changed files with 30074 additions and 23110 deletions

View file

@ -3,117 +3,117 @@ description: Report a broken behavior in plain language with a minimal reproduct
labels: ["bug"]
title: "[BUG] "
body:
- type: markdown
attributes:
value: |
Thank you for your report! Please search existing issues first:
https://github.com/RooCodeInc/Roo-Code/issues
- type: markdown
attributes:
value: |
Thank you for your report! Please search existing issues first:
https://github.com/RooCodeInc/Roo-Code/issues
- type: textarea
id: problem
attributes:
label: Problem (one or two sentences)
description: Describe what went wrong in plain language.
placeholder: 'Example: "Expected the task to start, but nothing happened and no message appeared."'
validations:
required: true
- type: textarea
id: problem
attributes:
label: Problem (one or two sentences)
description: Describe what went wrong in plain language.
placeholder: 'Example: "Expected the task to start, but nothing happened and no message appeared."'
validations:
required: true
- type: textarea
id: context
attributes:
label: Context (who is affected and when)
description: Who sees this and in what situation? Keep it non-technical.
placeholder: 'Example: "Happens to new users when starting a run from the New Run page with dark theme enabled."'
validations:
required: true
- type: textarea
id: context
attributes:
label: Context (who is affected and when)
description: Who sees this and in what situation? Keep it non-technical.
placeholder: 'Example: "Happens to new users when starting a run from the New Run page with dark theme enabled."'
validations:
required: true
- type: textarea
id: steps
attributes:
label: Reproduction steps
description: Provide clear, numbered steps so we can reproduce.
placeholder: |
1) Environment/setup (OS, extension version, relevant settings)
2) Exact actions (clicks, inputs, commands)
3) What you observed after each step
validations:
required: true
- type: textarea
id: steps
attributes:
label: Reproduction steps
description: Provide clear, numbered steps so we can reproduce.
placeholder: |
1) Environment/setup (OS, extension version, relevant settings)
2) Exact actions (clicks, inputs, commands)
3) What you observed after each step
validations:
required: true
- type: input
id: expected
attributes:
label: Expected result
placeholder: e.g., "The task starts and shows progress."
validations:
required: true
- type: input
id: expected
attributes:
label: Expected result
placeholder: e.g., "The task starts and shows progress."
validations:
required: true
- type: input
id: actual
attributes:
label: Actual result
placeholder: e.g., "The button appears disabled and no progress is shown."
validations:
required: true
- type: input
id: actual
attributes:
label: Actual result
placeholder: e.g., "The button appears disabled and no progress is shown."
validations:
required: true
- type: textarea
id: variations
attributes:
label: Variations tried (optional)
description: Different browsers, devices, providers, or settings you tried.
placeholder: e.g., "Tried Chrome/Firefox, disabling dark theme, switching providers."
- type: textarea
id: variations
attributes:
label: Variations tried (optional)
description: Different browsers, devices, providers, or settings you tried.
placeholder: e.g., "Tried Chrome/Firefox, disabling dark theme, switching providers."
- type: input
id: version
attributes:
label: App Version
description: What version of Roo Code are you using? (e.g., v3.3.1)
validations:
required: true
- type: input
id: version
attributes:
label: App Version
description: What version of Roo Code are you using? (e.g., v3.3.1)
validations:
required: true
- type: dropdown
id: provider
attributes:
label: API Provider (optional)
options:
- Anthropic
- Amazon Bedrock
- Chutes AI
- DeepSeek
- Featherless AI
- Fireworks AI
- Google Gemini
- Google Vertex AI
- Groq
- LiteLLM
- LM Studio
- Mistral AI
- Ollama
- OpenAI
- OpenAI Compatible
- OpenRouter
- Requesty
- SambaNova
- Unbound
- VS Code Language Model API
- xAI (Grok)
- Not Applicable / Other
- type: dropdown
id: provider
attributes:
label: API Provider (optional)
options:
- Anthropic
- Amazon Bedrock
- Chutes AI
- DeepSeek
- Featherless AI
- Fireworks AI
- Google Gemini
- Google Vertex AI
- Groq
- LiteLLM
- LM Studio
- Mistral AI
- Ollama
- OpenAI
- OpenAI Compatible
- OpenRouter
- Requesty
- SambaNova
- Unbound
- VS Code Language Model API
- xAI (Grok)
- Not Applicable / Other
- type: input
id: model
attributes:
label: Model Used (optional)
description: Exact model name (e.g., Claude 3.7 Sonnet). Use N/A if irrelevant.
- type: input
id: model
attributes:
label: Model Used (optional)
description: Exact model name (e.g., Claude 3.7 Sonnet). Use N/A if irrelevant.
- type: textarea
id: roo-code-tasks
attributes:
label: Roo Code Task Links (optional)
description: If you have any publicly shared Roo Code task links that demonstrate the issue, paste them here.
placeholder: Paste your Roo Code share links here, one per line
- type: textarea
id: roo-code-tasks
attributes:
label: Roo Code Task Links (optional)
description: If you have any publicly shared Roo Code task links that demonstrate the issue, paste them here.
placeholder: Paste your Roo Code share links here, one per line
- type: textarea
id: logs
attributes:
label: Relevant logs or errors (optional)
description: Paste relevant output or errors. Use triple backticks (```) for formatting.
render: shell
- type: textarea
id: logs
attributes:
label: Relevant logs or errors (optional)
description: Paste relevant output or errors. Use triple backticks (```) for formatting.
render: shell

View file

@ -3,89 +3,89 @@ description: Propose an improvement in plain language focused on user benefit
labels: ["enhancement"]
title: "[ENHANCEMENT] "
body:
- type: markdown
attributes:
value: |
Thank you for helping improve Roo Code!
Please focus on the problem and the desired behavior in plain language.
- type: markdown
attributes:
value: |
Thank you for helping improve Roo Code!
Please focus on the problem and the desired behavior in plain language.
- type: textarea
id: problem
attributes:
label: Problem (one or two sentences)
description: What problem are users facing?
placeholder: e.g., "Users often click Copy Run by mistake and duplicate runs unintentionally."
validations:
required: true
- type: textarea
id: context
attributes:
label: Context (who is affected and when)
description: Who encounters this and in what situation?
placeholder: e.g., "Happens when browsing the Runs list; most visible for new users."
validations:
required: true
- type: textarea
id: desired
attributes:
label: Desired behavior (conceptual, not technical)
description: Describe what should happen in simple terms.
placeholder: e.g., "Ask for confirmation before copying a run."
validations:
required: true
- type: textarea
id: constraints
attributes:
label: Constraints / preferences (optional)
description: Any considerations like performance, accessibility, or UX expectations.
placeholder: e.g., "Keep it quick and unobtrusive; keyboard accessible."
- 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 context and impact
- type: textarea
id: problem
attributes:
label: Problem (one or two sentences)
description: What problem are users facing?
placeholder: e.g., "Users often click Copy Run by mistake and duplicate runs unintentionally."
validations:
required: true
- type: textarea
id: roo-code-tasks
attributes:
label: Roo Code Task Links (optional)
description: If you explored this with Roo Code, share public task links for context.
placeholder: Paste your Roo Code share links here, one per line
- type: textarea
id: context
attributes:
label: Context (who is affected and when)
description: Who encounters this and in what situation?
placeholder: e.g., "Happens when browsing the Runs list; most visible for new users."
validations:
required: true
- type: markdown
attributes:
value: |
---
Optional (for contributors): You can stop here if you're just proposing the improvement.
- type: textarea
id: desired
attributes:
label: Desired behavior (conceptual, not technical)
description: Describe what should happen in simple terms.
placeholder: e.g., "Ask for confirmation before copying a run."
validations:
required: true
- type: textarea
id: acceptance-criteria
attributes:
label: Acceptance criteria (optional)
description: Define what “working” looks like with specific, testable outcomes.
placeholder: |
Given [context]
When [user action]
Then [expected result]
And [additional expectations]
But [what should NOT happen]
- type: textarea
id: constraints
attributes:
label: Constraints / preferences (optional)
description: Any considerations like performance, accessibility, or UX expectations.
placeholder: e.g., "Keep it quick and unobtrusive; keyboard accessible."
- type: textarea
id: proposed-solution
attributes:
label: Proposed approach (optional)
description: If you have an idea, describe it briefly in plain language.
- 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 context and impact
required: true
- type: textarea
id: risks
attributes:
label: Trade-offs / risks (optional)
description: Potential downsides or alternatives considered.
- type: textarea
id: roo-code-tasks
attributes:
label: Roo Code Task Links (optional)
description: If you explored this with Roo Code, share public task links for context.
placeholder: Paste your Roo Code share links here, one per line
- type: markdown
attributes:
value: |
---
Optional (for contributors): You can stop here if you're just proposing the improvement.
- type: textarea
id: acceptance-criteria
attributes:
label: Acceptance criteria (optional)
description: Define what “working” looks like with specific, testable outcomes.
placeholder: |
Given [context]
When [user action]
Then [expected result]
And [additional expectations]
But [what should NOT happen]
- type: textarea
id: proposed-solution
attributes:
label: Proposed approach (optional)
description: If you have an idea, describe it briefly in plain language.
- type: textarea
id: risks
attributes:
label: Trade-offs / risks (optional)
description: Potential downsides or alternatives considered.

View file

@ -2,61 +2,61 @@ name: Marketplace Feedback
description: Report issues or suggest improvements for marketplace items (custom modes and MCP servers)
labels: ["marketplace"]
body:
- type: markdown
attributes:
value: |
**Thanks for your feedback!** Please check existing issues first: https://github.com/RooCodeInc/Roo-Code/issues
- type: markdown
attributes:
value: |
**Thanks for your feedback!** Please check existing issues first: https://github.com/RooCodeInc/Roo-Code/issues
- type: dropdown
id: feedback-type
attributes:
label: What kind of feedback?
options:
- Problem with existing marketplace item
- Suggestion for new custom mode
- Suggestion for new MCP server
- General marketplace issue
validations:
required: true
- type: dropdown
id: feedback-type
attributes:
label: What kind of feedback?
options:
- Problem with existing marketplace item
- Suggestion for new custom mode
- Suggestion for new MCP server
- General marketplace issue
validations:
required: true
- type: dropdown
id: item-type
attributes:
label: Item Type (if applicable)
options:
- Custom Mode
- MCP Server
- Marketplace UI/Functionality
- Not Applicable
validations:
required: false
- type: dropdown
id: item-type
attributes:
label: Item Type (if applicable)
options:
- Custom Mode
- MCP Server
- Marketplace UI/Functionality
- Not Applicable
validations:
required: false
- type: input
id: item-name
attributes:
label: Item Name (if applicable)
placeholder: e.g., "Debug Mode", "Weather API Server", "Code Formatter"
- type: input
id: item-name
attributes:
label: Item Name (if applicable)
placeholder: e.g., "Debug Mode", "Weather API Server", "Code Formatter"
- type: textarea
id: description
attributes:
label: Description
description: What's the issue or what would you like to see?
placeholder: Clear description of the problem or suggestion
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
description: What's the issue or what would you like to see?
placeholder: Clear description of the problem or suggestion
validations:
required: true
- type: textarea
id: additional-info
attributes:
label: Additional Details (optional)
description: Steps to reproduce, expected behavior, screenshots, etc.
placeholder: Any other helpful information
- type: textarea
id: additional-info
attributes:
label: Additional Details (optional)
description: Steps to reproduce, expected behavior, screenshots, etc.
placeholder: Any other helpful information
- type: checkboxes
id: checklist
attributes:
label: Checklist
options:
- label: I've searched existing issues for duplicates
required: true
- type: checkboxes
id: checklist
attributes:
label: Checklist
options:
- label: I've searched existing issues for duplicates
required: true

View file

@ -1,58 +1,58 @@
name: 'Slack Notification'
description: 'Send Slack notification for workflow failures'
name: "Slack Notification"
description: "Send Slack notification for workflow failures"
inputs:
webhook-url:
description: 'Slack webhook URL'
required: true
channel:
description: 'Slack channel to notify'
required: true
workflow-name:
description: 'Name of the workflow'
required: true
failed-jobs:
description: 'JSON object containing job results'
required: true
webhook-url:
description: "Slack webhook URL"
required: true
channel:
description: "Slack channel to notify"
required: true
workflow-name:
description: "Name of the workflow"
required: true
failed-jobs:
description: "JSON object containing job results"
required: true
runs:
using: 'composite'
steps:
- name: Parse failed jobs
id: parse-jobs
shell: bash
run: |
echo "Parsing job results..."
failed_list=""
using: "composite"
steps:
- name: Parse failed jobs
id: parse-jobs
shell: bash
run: |
echo "Parsing job results..."
failed_list=""
echo '${{ inputs.failed-jobs }}' | jq -r 'to_entries[] | select(.value.result == "failure") | .key' | while read job; do
case $job in
"check-translations") failed_list="${failed_list}❌ Translation check\n" ;;
"knip") failed_list="${failed_list}❌ Knip analysis\n" ;;
"compile") failed_list="${failed_list}❌ Compile & lint\n" ;;
"unit-test") failed_list="${failed_list}❌ Unit tests\n" ;;
"integration-test") failed_list="${failed_list}❌ Integration tests\n" ;;
esac
done
echo '${{ inputs.failed-jobs }}' | jq -r 'to_entries[] | select(.value.result == "failure") | .key' | while read job; do
case $job in
"check-translations") failed_list="${failed_list}❌ Translation check\n" ;;
"knip") failed_list="${failed_list}❌ Knip analysis\n" ;;
"compile") failed_list="${failed_list}❌ Compile & lint\n" ;;
"unit-test") failed_list="${failed_list}❌ Unit tests\n" ;;
"integration-test") failed_list="${failed_list}❌ Integration tests\n" ;;
esac
done
echo "failed_jobs<<EOF" >> $GITHUB_OUTPUT
echo -e "$failed_list" | sed '/^$/d' >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "failed_jobs<<EOF" >> $GITHUB_OUTPUT
echo -e "$failed_list" | sed '/^$/d' >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Send Slack notification
uses: 8398a7/action-slack@v3
with:
status: failure
channel: ${{ inputs.channel }}
text: |
🚨 ${{ inputs.workflow-name }} workflow failed on main branch!
- name: Send Slack notification
uses: 8398a7/action-slack@v3
with:
status: failure
channel: ${{ inputs.channel }}
text: |
🚨 ${{ inputs.workflow-name }} workflow failed on main branch!
Repository: ${{ github.repository }}
Commit: ${{ github.sha }}
Author: ${{ github.actor }}
Repository: ${{ github.repository }}
Commit: ${{ github.sha }}
Author: ${{ github.actor }}
Failed jobs:
${{ steps.parse-jobs.outputs.failed_jobs }}
Failed jobs:
${{ steps.parse-jobs.outputs.failed_jobs }}
View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
env:
SLACK_WEBHOOK_URL: ${{ inputs.webhook-url }}
View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
env:
SLACK_WEBHOOK_URL: ${{ inputs.webhook-url }}

View file

@ -5,7 +5,7 @@
version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"

View file

@ -2,131 +2,131 @@ name: Changeset Release
run-name: Changeset Release ${{ github.actor != 'R00-B0T' && '- Create PR' || '- Update Changelog' }}
on:
workflow_dispatch:
pull_request:
types: [closed, opened, labeled]
workflow_dispatch:
pull_request:
types: [closed, opened, labeled]
env:
REPO_PATH: ${{ github.repository }}
GIT_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || 'main' }}
REPO_PATH: ${{ github.repository }}
GIT_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || 'main' }}
jobs:
# Job 1: Create version bump PR when changesets are merged to main
changeset-pr-version-bump:
if: >
( github.event_name == 'pull_request' &&
github.event.pull_request.merged == true &&
github.event.pull_request.base.ref == 'main' &&
github.actor != 'R00-B0T' ) ||
github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Git Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ env.GIT_REF }}
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
# Job 1: Create version bump PR when changesets are merged to main
changeset-pr-version-bump:
if: >
( github.event_name == 'pull_request' &&
github.event.pull_request.merged == true &&
github.event.pull_request.base.ref == 'main' &&
github.actor != 'R00-B0T' ) ||
github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Git Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ env.GIT_REF }}
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
# Check if there are any new changesets to process
- name: Check for changesets
id: check-changesets
run: |
NEW_CHANGESETS=$(find .changeset -name "*.md" ! -name "README.md" | wc -l | tr -d ' ')
echo "Changesets diff with previous version: $NEW_CHANGESETS"
echo "new_changesets=$NEW_CHANGESETS" >> $GITHUB_OUTPUT
# Check if there are any new changesets to process
- name: Check for changesets
id: check-changesets
run: |
NEW_CHANGESETS=$(find .changeset -name "*.md" ! -name "README.md" | wc -l | tr -d ' ')
echo "Changesets diff with previous version: $NEW_CHANGESETS"
echo "new_changesets=$NEW_CHANGESETS" >> $GITHUB_OUTPUT
# Create version bump PR using changesets/action if there are new changesets
- name: Changeset Pull Request
if: steps.check-changesets.outputs.new_changesets != '0'
id: changesets
uses: changesets/action@v1
with:
commit: "changeset version bump"
title: "Changeset version bump"
version: pnpm changeset:version # This performs the changeset version bump
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Create version bump PR using changesets/action if there are new changesets
- name: Changeset Pull Request
if: steps.check-changesets.outputs.new_changesets != '0'
id: changesets
uses: changesets/action@v1
with:
commit: "changeset version bump"
title: "Changeset version bump"
version: pnpm changeset:version # This performs the changeset version bump
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Job 2: Process version bump PR created by R00-B0T
changeset-pr-edit-approve:
name: Auto approve and merge Bump version PRs
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
if: >
github.event_name == 'pull_request' &&
github.event.pull_request.base.ref == 'main' &&
github.actor == 'R00-B0T' &&
contains(github.event.pull_request.title, 'Changeset version bump')
steps:
- name: Determine checkout ref
id: checkout-ref
run: |
echo "Event action: ${{ github.event.action }}"
echo "Actor: ${{ github.actor }}"
echo "Head ref: ${{ github.head_ref }}"
echo "PR SHA: ${{ github.event.pull_request.head.sha }}"
# Job 2: Process version bump PR created by R00-B0T
changeset-pr-edit-approve:
name: Auto approve and merge Bump version PRs
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
if: >
github.event_name == 'pull_request' &&
github.event.pull_request.base.ref == 'main' &&
github.actor == 'R00-B0T' &&
contains(github.event.pull_request.title, 'Changeset version bump')
steps:
- name: Determine checkout ref
id: checkout-ref
run: |
echo "Event action: ${{ github.event.action }}"
echo "Actor: ${{ github.actor }}"
echo "Head ref: ${{ github.head_ref }}"
echo "PR SHA: ${{ github.event.pull_request.head.sha }}"
if [[ "${{ github.event.action }}" == "opened" && "${{ github.actor }}" == "R00-B0T" ]]; then
echo "Using branch ref: ${{ github.head_ref }}"
echo "git_ref=${{ github.head_ref }}" >> $GITHUB_OUTPUT
else
echo "Using SHA ref: ${{ github.event.pull_request.head.sha }}"
echo "git_ref=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
fi
if [[ "${{ github.event.action }}" == "opened" && "${{ github.actor }}" == "R00-B0T" ]]; then
echo "Using branch ref: ${{ github.head_ref }}"
echo "git_ref=${{ github.head_ref }}" >> $GITHUB_OUTPUT
else
echo "Using SHA ref: ${{ github.event.pull_request.head.sha }}"
echo "git_ref=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
fi
- name: Checkout Repo
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
ref: ${{ steps.checkout-ref.outputs.git_ref }}
- name: Checkout Repo
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
ref: ${{ steps.checkout-ref.outputs.git_ref }}
# Commit and push changelog updates
- name: Push Changelog updates
if: ${{ !contains(github.event.pull_request.labels.*.name, 'changelog-ready') }}
run: |
git config user.name "R00-B0T"
git config user.email github-actions@github.com
echo "Running git add and commit..."
git add CHANGELOG.md
git commit -m "Updating CHANGELOG.md format"
git status
echo "--------------------------------------------------------------------------------"
echo "Pushing to remote..."
echo "--------------------------------------------------------------------------------"
git push
# Commit and push changelog updates
- name: Push Changelog updates
if: ${{ !contains(github.event.pull_request.labels.*.name, 'changelog-ready') }}
run: |
git config user.name "R00-B0T"
git config user.email github-actions@github.com
echo "Running git add and commit..."
git add CHANGELOG.md
git commit -m "Updating CHANGELOG.md format"
git status
echo "--------------------------------------------------------------------------------"
echo "Pushing to remote..."
echo "--------------------------------------------------------------------------------"
git push
# Add label to indicate changelog has been formatted
- name: Add changelog-ready label
if: ${{ !contains(github.event.pull_request.labels.*.name, 'changelog-ready') }}
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: ['changelog-ready']
});
# Add label to indicate changelog has been formatted
- name: Add changelog-ready label
if: ${{ !contains(github.event.pull_request.labels.*.name, 'changelog-ready') }}
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: ['changelog-ready']
});
# Auto-approve PR only after it has been labeled
- name: Auto approve PR
if: contains(github.event.pull_request.labels.*.name, 'changelog-ready')
uses: hmarr/auto-approve-action@v4
with:
review-message: "I'm approving since it's a bump version PR"
# Auto-merge PR
- name: Automerge on PR
if: false # Needs enablePullRequestAutoMerge in repo settings to work contains(github.event.pull_request.labels.*.name, 'changelog-ready')
run: gh pr merge --auto --merge ${{ github.event.pull_request.number }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Auto-approve PR only after it has been labeled
- name: Auto approve PR
if: contains(github.event.pull_request.labels.*.name, 'changelog-ready')
uses: hmarr/auto-approve-action@v4
with:
review-message: "I'm approving since it's a bump version PR"
# Auto-merge PR
- name: Automerge on PR
if: false # Needs enablePullRequestAutoMerge in repo settings to work contains(github.event.pull_request.labels.*.name, 'changelog-ready')
run: gh pr merge --auto --merge ${{ github.event.pull_request.number }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -1,394 +1,394 @@
name: CLI Release
on:
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g., 0.1.0). Leave empty to use package.json version.'
required: false
type: string
dry_run:
description: 'Dry run (build and test but do not create release).'
required: false
type: boolean
default: false
workflow_dispatch:
inputs:
version:
description: "Version to release (e.g., 0.1.0). Leave empty to use package.json version."
required: false
type: string
dry_run:
description: "Dry run (build and test but do not create release)."
required: false
type: boolean
default: false
jobs:
# Build CLI for each platform.
build:
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
platform: darwin-arm64
runs-on: macos-latest
- os: ubuntu-latest
platform: linux-x64
runs-on: ubuntu-latest
- os: ubuntu-24.04-arm
platform: linux-arm64
runs-on: ubuntu-24.04-arm
# Build CLI for each platform.
build:
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
platform: darwin-arm64
runs-on: macos-latest
- os: ubuntu-latest
platform: linux-x64
runs-on: ubuntu-latest
- os: ubuntu-24.04-arm
platform: linux-arm64
runs-on: ubuntu-24.04-arm
runs-on: ${{ matrix.runs-on }}
runs-on: ${{ matrix.runs-on }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
- name: Get version
id: version
run: |
if [ -n "${{ inputs.version }}" ]; then
VERSION="${{ inputs.version }}"
else
VERSION=$(node -p "require('./apps/cli/package.json').version")
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=cli-v$VERSION" >> $GITHUB_OUTPUT
echo "Using version: $VERSION"
- name: Get version
id: version
run: |
if [ -n "${{ inputs.version }}" ]; then
VERSION="${{ inputs.version }}"
else
VERSION=$(node -p "require('./apps/cli/package.json').version")
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=cli-v$VERSION" >> $GITHUB_OUTPUT
echo "Using version: $VERSION"
- name: Build extension bundle
run: pnpm bundle
- name: Build extension bundle
run: pnpm bundle
- name: Build CLI
run: pnpm --filter @roo-code/cli build
- name: Build CLI
run: pnpm --filter @roo-code/cli build
- name: Create release tarball
id: tarball
env:
VERSION: ${{ steps.version.outputs.version }}
PLATFORM: ${{ matrix.platform }}
run: |
RELEASE_DIR="roo-cli-${PLATFORM}"
TARBALL="roo-cli-${PLATFORM}.tar.gz"
- name: Create release tarball
id: tarball
env:
VERSION: ${{ steps.version.outputs.version }}
PLATFORM: ${{ matrix.platform }}
run: |
RELEASE_DIR="roo-cli-${PLATFORM}"
TARBALL="roo-cli-${PLATFORM}.tar.gz"
# Clean up any previous build.
rm -rf "$RELEASE_DIR"
rm -f "$TARBALL"
# Clean up any previous build.
rm -rf "$RELEASE_DIR"
rm -f "$TARBALL"
# Create directory structure.
mkdir -p "$RELEASE_DIR/bin"
mkdir -p "$RELEASE_DIR/lib"
mkdir -p "$RELEASE_DIR/extension"
# Create directory structure.
mkdir -p "$RELEASE_DIR/bin"
mkdir -p "$RELEASE_DIR/lib"
mkdir -p "$RELEASE_DIR/extension"
# Copy CLI dist files.
echo "Copying CLI files..."
cp -r apps/cli/dist/* "$RELEASE_DIR/lib/"
# Copy CLI dist files.
echo "Copying CLI files..."
cp -r apps/cli/dist/* "$RELEASE_DIR/lib/"
# Create package.json for npm install.
echo "Creating package.json..."
node -e "
const pkg = require('./apps/cli/package.json');
const newPkg = {
name: '@roo-code/cli',
version: '$VERSION',
type: 'module',
dependencies: {
'@inkjs/ui': pkg.dependencies['@inkjs/ui'],
'@trpc/client': pkg.dependencies['@trpc/client'],
'commander': pkg.dependencies.commander,
'fuzzysort': pkg.dependencies.fuzzysort,
'ink': pkg.dependencies.ink,
'p-wait-for': pkg.dependencies['p-wait-for'],
'react': pkg.dependencies.react,
'superjson': pkg.dependencies.superjson,
'zustand': pkg.dependencies.zustand
}
};
console.log(JSON.stringify(newPkg, null, 2));
" > "$RELEASE_DIR/package.json"
# Create package.json for npm install.
echo "Creating package.json..."
node -e "
const pkg = require('./apps/cli/package.json');
const newPkg = {
name: '@roo-code/cli',
version: '$VERSION',
type: 'module',
dependencies: {
'@inkjs/ui': pkg.dependencies['@inkjs/ui'],
'@trpc/client': pkg.dependencies['@trpc/client'],
'commander': pkg.dependencies.commander,
'fuzzysort': pkg.dependencies.fuzzysort,
'ink': pkg.dependencies.ink,
'p-wait-for': pkg.dependencies['p-wait-for'],
'react': pkg.dependencies.react,
'superjson': pkg.dependencies.superjson,
'zustand': pkg.dependencies.zustand
}
};
console.log(JSON.stringify(newPkg, null, 2));
" > "$RELEASE_DIR/package.json"
# Copy extension bundle.
echo "Copying extension bundle..."
cp -r src/dist/* "$RELEASE_DIR/extension/"
# Copy extension bundle.
echo "Copying extension bundle..."
cp -r src/dist/* "$RELEASE_DIR/extension/"
# Add package.json to extension directory for CommonJS.
echo '{"type": "commonjs"}' > "$RELEASE_DIR/extension/package.json"
# Add package.json to extension directory for CommonJS.
echo '{"type": "commonjs"}' > "$RELEASE_DIR/extension/package.json"
# Find and copy ripgrep binary.
echo "Looking for ripgrep binary..."
RIPGREP_PATH=$(find node_modules -path "*/@vscode/ripgrep/bin/rg" -type f 2>/dev/null | head -1)
if [ -n "$RIPGREP_PATH" ] && [ -f "$RIPGREP_PATH" ]; then
echo "Found ripgrep at: $RIPGREP_PATH"
mkdir -p "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin"
cp "$RIPGREP_PATH" "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/"
chmod +x "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/rg"
mkdir -p "$RELEASE_DIR/bin"
cp "$RIPGREP_PATH" "$RELEASE_DIR/bin/"
chmod +x "$RELEASE_DIR/bin/rg"
else
echo "Warning: ripgrep binary not found"
fi
# Find and copy ripgrep binary.
echo "Looking for ripgrep binary..."
RIPGREP_PATH=$(find node_modules -path "*/@vscode/ripgrep/bin/rg" -type f 2>/dev/null | head -1)
if [ -n "$RIPGREP_PATH" ] && [ -f "$RIPGREP_PATH" ]; then
echo "Found ripgrep at: $RIPGREP_PATH"
mkdir -p "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin"
cp "$RIPGREP_PATH" "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/"
chmod +x "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/rg"
mkdir -p "$RELEASE_DIR/bin"
cp "$RIPGREP_PATH" "$RELEASE_DIR/bin/"
chmod +x "$RELEASE_DIR/bin/rg"
else
echo "Warning: ripgrep binary not found"
fi
# Create the wrapper script
echo "Creating wrapper script..."
printf '%s\n' '#!/usr/bin/env node' \
'' \
"import { fileURLToPath } from 'url';" \
"import { dirname, join } from 'path';" \
'' \
'const __filename = fileURLToPath(import.meta.url);' \
'const __dirname = dirname(__filename);' \
'' \
'// Set environment variables for the CLI' \
"process.env.ROO_CLI_ROOT = join(__dirname, '..');" \
"process.env.ROO_EXTENSION_PATH = join(__dirname, '..', 'extension');" \
"process.env.ROO_RIPGREP_PATH = join(__dirname, 'rg');" \
'' \
'// Import and run the actual CLI' \
"await import(join(__dirname, '..', 'lib', 'index.js'));" \
> "$RELEASE_DIR/bin/roo"
# Create the wrapper script
echo "Creating wrapper script..."
printf '%s\n' '#!/usr/bin/env node' \
'' \
"import { fileURLToPath } from 'url';" \
"import { dirname, join } from 'path';" \
'' \
'const __filename = fileURLToPath(import.meta.url);' \
'const __dirname = dirname(__filename);' \
'' \
'// Set environment variables for the CLI' \
"process.env.ROO_CLI_ROOT = join(__dirname, '..');" \
"process.env.ROO_EXTENSION_PATH = join(__dirname, '..', 'extension');" \
"process.env.ROO_RIPGREP_PATH = join(__dirname, 'rg');" \
'' \
'// Import and run the actual CLI' \
"await import(join(__dirname, '..', 'lib', 'index.js'));" \
> "$RELEASE_DIR/bin/roo"
chmod +x "$RELEASE_DIR/bin/roo"
chmod +x "$RELEASE_DIR/bin/roo"
# Create empty .env file.
touch "$RELEASE_DIR/.env"
# Create empty .env file.
touch "$RELEASE_DIR/.env"
# Create tarball.
echo "Creating tarball..."
tar -czvf "$TARBALL" "$RELEASE_DIR"
# Create tarball.
echo "Creating tarball..."
tar -czvf "$TARBALL" "$RELEASE_DIR"
# Clean up release directory.
rm -rf "$RELEASE_DIR"
# Clean up release directory.
rm -rf "$RELEASE_DIR"
# Create checksum.
if command -v sha256sum &> /dev/null; then
sha256sum "$TARBALL" > "${TARBALL}.sha256"
elif command -v shasum &> /dev/null; then
shasum -a 256 "$TARBALL" > "${TARBALL}.sha256"
fi
# Create checksum.
if command -v sha256sum &> /dev/null; then
sha256sum "$TARBALL" > "${TARBALL}.sha256"
elif command -v shasum &> /dev/null; then
shasum -a 256 "$TARBALL" > "${TARBALL}.sha256"
fi
echo "tarball=$TARBALL" >> $GITHUB_OUTPUT
echo "Created: $TARBALL"
ls -la "$TARBALL"
echo "tarball=$TARBALL" >> $GITHUB_OUTPUT
echo "Created: $TARBALL"
ls -la "$TARBALL"
- name: Verify tarball
env:
PLATFORM: ${{ matrix.platform }}
run: |
TARBALL="roo-cli-${PLATFORM}.tar.gz"
- name: Verify tarball
env:
PLATFORM: ${{ matrix.platform }}
run: |
TARBALL="roo-cli-${PLATFORM}.tar.gz"
# Create temp directory for verification.
VERIFY_DIR=$(mktemp -d)
# Create temp directory for verification.
VERIFY_DIR=$(mktemp -d)
# Extract and verify structure.
tar -xzf "$TARBALL" -C "$VERIFY_DIR"
# Extract and verify structure.
tar -xzf "$TARBALL" -C "$VERIFY_DIR"
echo "Verifying tarball contents..."
ls -la "$VERIFY_DIR/roo-cli-${PLATFORM}/"
echo "Verifying tarball contents..."
ls -la "$VERIFY_DIR/roo-cli-${PLATFORM}/"
# Check required files exist.
test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/bin/roo" || { echo "Missing bin/roo"; exit 1; }
test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/lib/index.js" || { echo "Missing lib/index.js"; exit 1; }
test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/package.json" || { echo "Missing package.json"; exit 1; }
test -d "$VERIFY_DIR/roo-cli-${PLATFORM}/extension" || { echo "Missing extension directory"; exit 1; }
# Check required files exist.
test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/bin/roo" || { echo "Missing bin/roo"; exit 1; }
test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/lib/index.js" || { echo "Missing lib/index.js"; exit 1; }
test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/package.json" || { echo "Missing package.json"; exit 1; }
test -d "$VERIFY_DIR/roo-cli-${PLATFORM}/extension" || { echo "Missing extension directory"; exit 1; }
echo "Tarball verification passed!"
echo "Tarball verification passed!"
# Cleanup.
rm -rf "$VERIFY_DIR"
# Cleanup.
rm -rf "$VERIFY_DIR"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: cli-${{ matrix.platform }}
path: |
roo-cli-${{ matrix.platform }}.tar.gz
roo-cli-${{ matrix.platform }}.tar.gz.sha256
retention-days: 7
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: cli-${{ matrix.platform }}
path: |
roo-cli-${{ matrix.platform }}.tar.gz
roo-cli-${{ matrix.platform }}.tar.gz.sha256
retention-days: 7
# Create GitHub release with all platform artifacts.
release:
needs: build
runs-on: ubuntu-latest
if: ${{ !inputs.dry_run }}
permissions:
contents: write
# Create GitHub release with all platform artifacts.
release:
needs: build
runs-on: ubuntu-latest
if: ${{ !inputs.dry_run }}
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get version
id: version
run: |
if [ -n "${{ inputs.version }}" ]; then
VERSION="${{ inputs.version }}"
else
VERSION=$(node -p "require('./apps/cli/package.json').version")
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=cli-v$VERSION" >> $GITHUB_OUTPUT
- name: Get version
id: version
run: |
if [ -n "${{ inputs.version }}" ]; then
VERSION="${{ inputs.version }}"
else
VERSION=$(node -p "require('./apps/cli/package.json').version")
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=cli-v$VERSION" >> $GITHUB_OUTPUT
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Prepare release files
run: |
mkdir -p release
find artifacts -name "*.tar.gz" -exec cp {} release/ \;
find artifacts -name "*.sha256" -exec cp {} release/ \;
ls -la release/
- name: Prepare release files
run: |
mkdir -p release
find artifacts -name "*.tar.gz" -exec cp {} release/ \;
find artifacts -name "*.sha256" -exec cp {} release/ \;
ls -la release/
- name: Extract changelog
id: changelog
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
CHANGELOG_FILE="apps/cli/CHANGELOG.md"
- name: Extract changelog
id: changelog
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
CHANGELOG_FILE="apps/cli/CHANGELOG.md"
if [ -f "$CHANGELOG_FILE" ]; then
# Extract content between version headers.
CONTENT=$(awk -v version="$VERSION" '
BEGIN { found = 0; content = ""; target = "[" version "]" }
/^## \[/ {
if (found) { exit }
if (index($0, target) > 0) { found = 1; next }
}
found { content = content $0 "\n" }
END { print content }
' "$CHANGELOG_FILE")
if [ -f "$CHANGELOG_FILE" ]; then
# Extract content between version headers.
CONTENT=$(awk -v version="$VERSION" '
BEGIN { found = 0; content = ""; target = "[" version "]" }
/^## \[/ {
if (found) { exit }
if (index($0, target) > 0) { found = 1; next }
}
found { content = content $0 "\n" }
END { print content }
' "$CHANGELOG_FILE")
if [ -n "$CONTENT" ]; then
echo "Found changelog content"
echo "content<<EOF" >> $GITHUB_OUTPUT
echo "$CONTENT" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
else
echo "No changelog content found for version $VERSION"
echo "content=" >> $GITHUB_OUTPUT
fi
else
echo "No changelog file found"
echo "content=" >> $GITHUB_OUTPUT
fi
if [ -n "$CONTENT" ]; then
echo "Found changelog content"
echo "content<<EOF" >> $GITHUB_OUTPUT
echo "$CONTENT" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
else
echo "No changelog content found for version $VERSION"
echo "content=" >> $GITHUB_OUTPUT
fi
else
echo "No changelog file found"
echo "content=" >> $GITHUB_OUTPUT
fi
- name: Generate checksums summary
id: checksums
run: |
echo "checksums<<EOF" >> $GITHUB_OUTPUT
cat release/*.sha256 >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Generate checksums summary
id: checksums
run: |
echo "checksums<<EOF" >> $GITHUB_OUTPUT
cat release/*.sha256 >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Check for existing release
id: check_release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.version.outputs.tag }}
run: |
if gh release view "$TAG" &> /dev/null; then
echo "exists=true" >> $GITHUB_OUTPUT
else
echo "exists=false" >> $GITHUB_OUTPUT
fi
- name: Check for existing release
id: check_release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.version.outputs.tag }}
run: |
if gh release view "$TAG" &> /dev/null; then
echo "exists=true" >> $GITHUB_OUTPUT
else
echo "exists=false" >> $GITHUB_OUTPUT
fi
- name: Delete existing release
if: steps.check_release.outputs.exists == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.version.outputs.tag }}
run: |
echo "Deleting existing release $TAG..."
gh release delete "$TAG" --yes || true
git push origin ":refs/tags/$TAG" || true
- name: Delete existing release
if: steps.check_release.outputs.exists == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.version.outputs.tag }}
run: |
echo "Deleting existing release $TAG..."
gh release delete "$TAG" --yes || true
git push origin ":refs/tags/$TAG" || true
- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.version.outputs.version }}
TAG: ${{ steps.version.outputs.tag }}
CHANGELOG_CONTENT: ${{ steps.changelog.outputs.content }}
CHECKSUMS: ${{ steps.checksums.outputs.checksums }}
run: |
NOTES_FILE=$(mktemp)
- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.version.outputs.version }}
TAG: ${{ steps.version.outputs.tag }}
CHANGELOG_CONTENT: ${{ steps.changelog.outputs.content }}
CHECKSUMS: ${{ steps.checksums.outputs.checksums }}
run: |
NOTES_FILE=$(mktemp)
if [ -n "$CHANGELOG_CONTENT" ]; then
echo "## What's New" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "$CHANGELOG_CONTENT" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
fi
if [ -n "$CHANGELOG_CONTENT" ]; then
echo "## What's New" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "$CHANGELOG_CONTENT" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
fi
echo "## Installation" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo '```bash' >> "$NOTES_FILE"
echo "curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "Or install a specific version:" >> "$NOTES_FILE"
echo '```bash' >> "$NOTES_FILE"
echo "ROO_VERSION=$VERSION curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "## Requirements" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "- Node.js 20 or higher" >> "$NOTES_FILE"
echo "- macOS Apple Silicon (M1/M2/M3/M4), Linux x64, or Linux ARM64" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "## Usage" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo '```bash' >> "$NOTES_FILE"
echo "# Run a task" >> "$NOTES_FILE"
echo 'roo "What is this project?"' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "# See all options" >> "$NOTES_FILE"
echo "roo --help" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "## Platform Support" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "This release includes binaries for:" >> "$NOTES_FILE"
echo '- `roo-cli-darwin-arm64.tar.gz` - macOS Apple Silicon (M1/M2/M3)' >> "$NOTES_FILE"
echo '- `roo-cli-linux-x64.tar.gz` - Linux x64' >> "$NOTES_FILE"
echo '- `roo-cli-linux-arm64.tar.gz` - Linux ARM64' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "## Checksums" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
echo "$CHECKSUMS" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
echo "## Installation" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo '```bash' >> "$NOTES_FILE"
echo "curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "Or install a specific version:" >> "$NOTES_FILE"
echo '```bash' >> "$NOTES_FILE"
echo "ROO_VERSION=$VERSION curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "## Requirements" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "- Node.js 20 or higher" >> "$NOTES_FILE"
echo "- macOS Apple Silicon (M1/M2/M3/M4), Linux x64, or Linux ARM64" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "## Usage" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo '```bash' >> "$NOTES_FILE"
echo "# Run a task" >> "$NOTES_FILE"
echo 'roo "What is this project?"' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "# See all options" >> "$NOTES_FILE"
echo "roo --help" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "## Platform Support" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "This release includes binaries for:" >> "$NOTES_FILE"
echo '- `roo-cli-darwin-arm64.tar.gz` - macOS Apple Silicon (M1/M2/M3)' >> "$NOTES_FILE"
echo '- `roo-cli-linux-x64.tar.gz` - Linux x64' >> "$NOTES_FILE"
echo '- `roo-cli-linux-arm64.tar.gz` - Linux ARM64' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "## Checksums" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
echo "$CHECKSUMS" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
gh release create "$TAG" \
--title "Roo Code CLI v$VERSION" \
--notes-file "$NOTES_FILE" \
--prerelease \
release/*
gh release create "$TAG" \
--title "Roo Code CLI v$VERSION" \
--notes-file "$NOTES_FILE" \
--prerelease \
release/*
rm -f "$NOTES_FILE"
echo "Release created: https://github.com/${{ github.repository }}/releases/tag/$TAG"
rm -f "$NOTES_FILE"
echo "Release created: https://github.com/${{ github.repository }}/releases/tag/$TAG"
# Summary job for dry runs
summary:
needs: build
runs-on: ubuntu-latest
if: ${{ inputs.dry_run }}
# Summary job for dry runs
summary:
needs: build
runs-on: ubuntu-latest
if: ${{ inputs.dry_run }}
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Show build summary
run: |
echo "## Dry Run Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The following artifacts were built:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
find artifacts -name "*.tar.gz" | while read f; do
SIZE=$(ls -lh "$f" | awk '{print $5}')
echo "- $(basename $f) ($SIZE)" >> $GITHUB_STEP_SUMMARY
done
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Checksums" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
cat artifacts/*/*.sha256 >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
- name: Show build summary
run: |
echo "## Dry Run Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The following artifacts were built:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
find artifacts -name "*.tar.gz" | while read f; do
SIZE=$(ls -lh "$f" | awk '{print $5}')
echo "- $(basename $f) ($SIZE)" >> $GITHUB_STEP_SUMMARY
done
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Checksums" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
cat artifacts/*/*.sha256 >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

View file

@ -1,81 +1,81 @@
name: CodeQL Advanced
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
schedule:
- cron: '24 19 * * 3'
push:
branches: ["main"]
pull_request:
branches: ["main"]
schedule:
- cron: "24 19 * * 3"
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: javascript-typescript
build-mode: none
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4
strategy:
fail-fast: false
matrix:
include:
- language: javascript-typescript
build-mode: none
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View file

@ -1,92 +1,92 @@
name: Publish Extension
on:
pull_request:
types: [closed]
workflow_dispatch:
pull_request:
types: [closed]
workflow_dispatch:
env:
GIT_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || 'main' }}
GIT_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || 'main' }}
jobs:
publish-extension:
runs-on: ubuntu-latest
permissions:
contents: write # Required for pushing tags.
if: >
( github.event_name == 'pull_request' &&
github.event.pull_request.base.ref == 'main' &&
contains(github.event.pull_request.title, 'Changeset version bump') ) ||
github.event_name == 'workflow_dispatch'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ env.GIT_REF }}
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
- name: Configure Git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Create .env file
run: echo "POSTHOG_API_KEY=${{ secrets.POSTHOG_API_KEY }}" >> .env
- name: Package Extension
run: |
current_package_version=$(node -p "require('./src/package.json').version")
pnpm vsix
publish-extension:
runs-on: ubuntu-latest
permissions:
contents: write # Required for pushing tags.
if: >
( github.event_name == 'pull_request' &&
github.event.pull_request.base.ref == 'main' &&
contains(github.event.pull_request.title, 'Changeset version bump') ) ||
github.event_name == 'workflow_dispatch'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ env.GIT_REF }}
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
- name: Configure Git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Create .env file
run: echo "POSTHOG_API_KEY=${{ secrets.POSTHOG_API_KEY }}" >> .env
- name: Package Extension
run: |
current_package_version=$(node -p "require('./src/package.json').version")
pnpm vsix
# Save VSIX contents to a temporary file to avoid broken pipe issues.
unzip -l bin/roo-cline-${current_package_version}.vsix > /tmp/roo-code-vsix-contents.txt
# Save VSIX contents to a temporary file to avoid broken pipe issues.
unzip -l bin/roo-cline-${current_package_version}.vsix > /tmp/roo-code-vsix-contents.txt
# Check for required files.
grep -q "extension/package.json" /tmp/roo-code-vsix-contents.txt || exit 1
grep -q "extension/package.nls.json" /tmp/roo-code-vsix-contents.txt || exit 1
grep -q "extension/dist/extension.js" /tmp/roo-code-vsix-contents.txt || exit 1
grep -q "extension/webview-ui/audio/celebration.wav" /tmp/roo-code-vsix-contents.txt || exit 1
grep -q "extension/webview-ui/build/assets/index.js" /tmp/roo-code-vsix-contents.txt || exit 1
grep -q "extension/assets/codicons/codicon.ttf" /tmp/roo-code-vsix-contents.txt || exit 1
grep -q "extension/assets/vscode-material-icons/icons/3d.svg" /tmp/roo-code-vsix-contents.txt || exit 1
grep -q ".env" /tmp/roo-code-vsix-contents.txt || exit 1
# Clean up temporary file.
rm /tmp/roo-code-vsix-contents.txt
- name: Create and Push Git Tag
run: |
current_package_version=$(node -p "require('./src/package.json').version")
git tag -a "v${current_package_version}" -m "Release v${current_package_version}"
git push origin "v${current_package_version}" --no-verify
echo "Successfully created and pushed git tag v${current_package_version}"
- name: Publish Extension
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
OVSX_PAT: ${{ secrets.OVSX_PAT }}
run: |
current_package_version=$(node -p "require('./src/package.json').version")
pnpm --filter roo-cline publish:marketplace
echo "Successfully published version $current_package_version to VS Code Marketplace"
- name: Create GitHub Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
current_package_version=$(node -p "require('./src/package.json').version")
# Check for required files.
grep -q "extension/package.json" /tmp/roo-code-vsix-contents.txt || exit 1
grep -q "extension/package.nls.json" /tmp/roo-code-vsix-contents.txt || exit 1
grep -q "extension/dist/extension.js" /tmp/roo-code-vsix-contents.txt || exit 1
grep -q "extension/webview-ui/audio/celebration.wav" /tmp/roo-code-vsix-contents.txt || exit 1
grep -q "extension/webview-ui/build/assets/index.js" /tmp/roo-code-vsix-contents.txt || exit 1
grep -q "extension/assets/codicons/codicon.ttf" /tmp/roo-code-vsix-contents.txt || exit 1
grep -q "extension/assets/vscode-material-icons/icons/3d.svg" /tmp/roo-code-vsix-contents.txt || exit 1
grep -q ".env" /tmp/roo-code-vsix-contents.txt || exit 1
# Extract changelog for current version
echo "Extracting changelog for version ${current_package_version}"
changelog_content=$(sed -n "/## \\[${current_package_version}\\]/,/## \\[/p" CHANGELOG.md | sed '$d')
# Clean up temporary file.
rm /tmp/roo-code-vsix-contents.txt
- name: Create and Push Git Tag
run: |
current_package_version=$(node -p "require('./src/package.json').version")
git tag -a "v${current_package_version}" -m "Release v${current_package_version}"
git push origin "v${current_package_version}" --no-verify
echo "Successfully created and pushed git tag v${current_package_version}"
- name: Publish Extension
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
OVSX_PAT: ${{ secrets.OVSX_PAT }}
run: |
current_package_version=$(node -p "require('./src/package.json').version")
pnpm --filter roo-cline publish:marketplace
echo "Successfully published version $current_package_version to VS Code Marketplace"
- name: Create GitHub Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
current_package_version=$(node -p "require('./src/package.json').version")
# If changelog extraction failed, use a default message
if [ -z "$changelog_content" ]; then
echo "Warning: No changelog section found for version ${current_package_version}"
changelog_content="Release v${current_package_version}"
else
echo "Found changelog section for version ${current_package_version}"
fi
# Extract changelog for current version
echo "Extracting changelog for version ${current_package_version}"
changelog_content=$(sed -n "/## \\[${current_package_version}\\]/,/## \\[/p" CHANGELOG.md | sed '$d')
# Create release with changelog content
gh release create "v${current_package_version}" \
--title "Release v${current_package_version}" \
--notes "$changelog_content" \
--target ${{ env.GIT_REF }} \
bin/roo-cline-${current_package_version}.vsix
echo "Successfully created GitHub Release v${current_package_version}"
# If changelog extraction failed, use a default message
if [ -z "$changelog_content" ]; then
echo "Warning: No changelog section found for version ${current_package_version}"
changelog_content="Release v${current_package_version}"
else
echo "Found changelog section for version ${current_package_version}"
fi
# Create release with changelog content
gh release create "v${current_package_version}" \
--title "Release v${current_package_version}" \
--notes "$changelog_content" \
--target ${{ env.GIT_REF }} \
bin/roo-cline-${current_package_version}.vsix
echo "Successfully created GitHub Release v${current_package_version}"

View file

@ -1,52 +1,52 @@
name: Nightly Publish
on:
push:
branches: [main]
workflow_dispatch: # Allows manual triggering.
push:
branches: [main]
workflow_dispatch: # Allows manual triggering.
jobs:
publish-nightly:
runs-on: ubuntu-latest
publish-nightly:
runs-on: ubuntu-latest
permissions:
contents: read # No tags pushed → read is enough.
permissions:
contents: read # No tags pushed → read is enough.
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
with:
install-args: '--frozen-lockfile'
- name: Forge numeric Nightly version
id: version
env:
RUN_NUMBER: ${{ github.run_number }}
run: echo "number=$(( 5500 + ${RUN_NUMBER} ))" >> $GITHUB_OUTPUT
- name: Patch package.json version
env:
VERSION_NUMBER: ${{ steps.version.outputs.number }}
run: |
node <<'EOF'
const fs = require('fs');
const path = require('path');
const pkgPath = path.join(__dirname, 'apps', 'vscode-nightly', 'package.nightly.json');
const pkg = JSON.parse(fs.readFileSync(pkgPath,'utf8'));
const [maj, min] = pkg.version.split('.');
pkg.version = `${maj}.${min}.${process.env.VERSION_NUMBER}`;
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
console.log(`🔖 Nightly version set to ${pkg.version}`);
EOF
- name: Build VSIX
run: pnpm vsix:nightly # Produces bin/roo-code-nightly-0.0.[count].vsix
- name: Publish to VS Code Marketplace
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
run: npx vsce publish --packagePath "bin/$(/bin/ls bin | head -n1)"
- name: Publish to Open VSX Registry
env:
OVSX_PAT: ${{ secrets.OVSX_PAT }}
run: npx ovsx publish "bin/$(ls bin | head -n1)"
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
with:
install-args: "--frozen-lockfile"
- name: Forge numeric Nightly version
id: version
env:
RUN_NUMBER: ${{ github.run_number }}
run: echo "number=$(( 5500 + ${RUN_NUMBER} ))" >> $GITHUB_OUTPUT
- name: Patch package.json version
env:
VERSION_NUMBER: ${{ steps.version.outputs.number }}
run: |
node <<'EOF'
const fs = require('fs');
const path = require('path');
const pkgPath = path.join(__dirname, 'apps', 'vscode-nightly', 'package.nightly.json');
const pkg = JSON.parse(fs.readFileSync(pkgPath,'utf8'));
const [maj, min] = pkg.version.split('.');
pkg.version = `${maj}.${min}.${process.env.VERSION_NUMBER}`;
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
console.log(`🔖 Nightly version set to ${pkg.version}`);
EOF
- name: Build VSIX
run: pnpm vsix:nightly # Produces bin/roo-code-nightly-0.0.[count].vsix
- name: Publish to VS Code Marketplace
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
run: npx vsce publish --packagePath "bin/$(/bin/ls bin | head -n1)"
- name: Publish to Open VSX Registry
env:
OVSX_PAT: ${{ secrets.OVSX_PAT }}
run: npx ovsx publish "bin/$(ls bin | head -n1)"

View file

@ -1,67 +1,67 @@
name: Update Contributors # Refresh contrib.rocks image cache
on:
workflow_dispatch:
workflow_dispatch:
permissions:
contents: write
pull-requests: write
contents: write
pull-requests: write
jobs:
refresh-contrib-cache:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
refresh-contrib-cache:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Bump cacheBust in all README files
run: |
set -euo pipefail
TS="$(date +%s)"
# Target only the root README.md and localized READMEs under locales/*/README.md
mapfile -t FILES < <(git ls-files README.md 'locales/*/README.md' || true)
- name: Bump cacheBust in all README files
run: |
set -euo pipefail
TS="$(date +%s)"
# Target only the root README.md and localized READMEs under locales/*/README.md
mapfile -t FILES < <(git ls-files README.md 'locales/*/README.md' || true)
if [ "${#FILES[@]}" -eq 0 ]; then
echo "No target README files found." >&2
exit 1
fi
if [ "${#FILES[@]}" -eq 0 ]; then
echo "No target README files found." >&2
exit 1
fi
UPDATED=0
for f in "${FILES[@]}"; do
if grep -q 'cacheBust=' "$f"; then
# Use portable sed in GNU environment of ubuntu-latest
sed -i -E "s/cacheBust=[0-9]+/cacheBust=${TS}/g" "$f"
echo "Updated cacheBust in $f"
UPDATED=1
else
echo "Warning: cacheBust parameter not found in $f" >&2
fi
done
UPDATED=0
for f in "${FILES[@]}"; do
if grep -q 'cacheBust=' "$f"; then
# Use portable sed in GNU environment of ubuntu-latest
sed -i -E "s/cacheBust=[0-9]+/cacheBust=${TS}/g" "$f"
echo "Updated cacheBust in $f"
UPDATED=1
else
echo "Warning: cacheBust parameter not found in $f" >&2
fi
done
if [ "$UPDATED" -eq 0 ]; then
echo "No files were updated. Ensure READMEs embed contrib.rocks with cacheBust param." >&2
exit 1
fi
if [ "$UPDATED" -eq 0 ]; then
echo "No files were updated. Ensure READMEs embed contrib.rocks with cacheBust param." >&2
exit 1
fi
- name: Detect changes
id: changes
run: |
if git diff --quiet; then
echo "changed=false" >> $GITHUB_OUTPUT
else
echo "changed=true" >> $GITHUB_OUTPUT
fi
- name: Detect changes
id: changes
run: |
if git diff --quiet; then
echo "changed=false" >> $GITHUB_OUTPUT
else
echo "changed=true" >> $GITHUB_OUTPUT
fi
- name: Create Pull Request
if: steps.changes.outputs.changed == 'true'
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "docs: update contributors list [skip ci]"
committer: "github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>"
branch: refresh-contrib-cache
delete-branch: true
title: "Refresh contrib.rocks image cache (all READMEs)"
body: |
Automated refresh of the contrib.rocks image cache by bumping the cacheBust parameter in README.md and locales/*/README.md.
base: main
- name: Create Pull Request
if: steps.changes.outputs.changed == 'true'
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "docs: update contributors list [skip ci]"
committer: "github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>"
branch: refresh-contrib-cache
delete-branch: true
title: "Refresh contrib.rocks image cache (all READMEs)"
body: |
Automated refresh of the contrib.rocks image cache by bumping the cacheBust parameter in README.md and locales/*/README.md.
base: main

View file

@ -5,7 +5,7 @@ on:
branches:
- main
paths:
- 'apps/web-roo-code/**'
- "apps/web-roo-code/**"
workflow_dispatch:
concurrency:
@ -25,11 +25,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
deploy:
runs-on: ubuntu-latest

View file

@ -11,10 +11,10 @@ Resolve merge conflicts for a specific pull request by analyzing git history, co
1. **Provide a PR number** (e.g., `#123` or just `123`)
2. The workflow will automatically:
- Fetch PR information (title, description, branches)
- Checkout the PR branch
- Rebase onto the target branch to reveal conflicts
- Analyze and resolve conflicts using git history
- Fetch PR information (title, description, branches)
- Checkout the PR branch
- Rebase onto the target branch to reveal conflicts
- Analyze and resolve conflicts using git history
## Workflow Steps
@ -39,6 +39,7 @@ git status --porcelain | grep "^UU"
### 3. Analyze Each Conflict
For each conflicted file:
- Read the conflict markers
- Run `git blame` on conflicting sections
- Fetch commit messages for context
@ -47,6 +48,7 @@ For each conflicted file:
### 4. Apply Resolution Strategy
Based on the analysis:
- **Bugfixes** generally take precedence over features
- **Recent changes** are often more relevant (unless older is a security fix)
- **Combine** non-conflicting changes when possible

View file

@ -9,32 +9,35 @@ Perform translation and localization tasks for the Roo Code extension. This comm
## Quick Start
1. **Identify the translation scope:**
- If a specific language code is provided (e.g., `de`, `zh-CN`), focus on that language
- If `all` is specified, translate to all supported languages
- If a string key is provided, locate and translate that specific string
- If a file path is provided, work with that translation file
- If a specific language code is provided (e.g., `de`, `zh-CN`), focus on that language
- If `all` is specified, translate to all supported languages
- If a string key is provided, locate and translate that specific string
- If a file path is provided, work with that translation file
2. **Supported languages:** ca, de, en, es, fr, hi, id, it, ja, ko, nl, pl, pt-BR, ru, tr, vi, zh-CN, zh-TW
3. **Translation locations:**
- Core Extension: `src/i18n/locales/`
- WebView UI: `webview-ui/src/i18n/locales/`
- Core Extension: `src/i18n/locales/`
- WebView UI: `webview-ui/src/i18n/locales/`
## Workflow
1. If adding new strings:
- Add the English string first
- Ask for confirmation before translating to other languages
- Use `apply_diff` for efficient file updates
- Add the English string first
- Ask for confirmation before translating to other languages
- Use `apply_diff` for efficient file updates
2. If updating existing strings:
- Identify all affected language files
- Update English first, then propagate changes
- Identify all affected language files
- Update English first, then propagate changes
3. Validate your changes:
```bash
node scripts/find-missing-translations.js
```
```bash
node scripts/find-missing-translations.js
```
## Key Guidelines

View file

@ -105,16 +105,16 @@ Verify the resolution and prepare for commit:
## Git Commands Reference
| Command | Purpose |
|---------|---------|
| `gh pr checkout [PR_NUMBER] --force` | Force checkout the PR branch |
| `git fetch origin main` | Get the latest main branch |
| `GIT_EDITOR=true git rebase origin/main` | Rebase current branch onto main (non-interactive) |
| `git blame -L [start],[end] [commit] -- [file]` | Get commit information for specific lines |
| `git show --format="%H%n%an%n%ae%n%ad%n%s%n%b" --no-patch [sha]` | Get commit metadata |
| `git show [sha] -- [file]` | Get the actual changes made in a commit |
| `git ls-files -u` | List unmerged files with stage information |
| `GIT_EDITOR=true git rebase --continue` | Continue rebase after resolving conflicts |
| Command | Purpose |
| ---------------------------------------------------------------- | ------------------------------------------------- |
| `gh pr checkout [PR_NUMBER] --force` | Force checkout the PR branch |
| `git fetch origin main` | Get the latest main branch |
| `GIT_EDITOR=true git rebase origin/main` | Rebase current branch onto main (non-interactive) |
| `git blame -L [start],[end] [commit] -- [file]` | Get commit information for specific lines |
| `git show --format="%H%n%an%n%ae%n%ad%n%s%n%b" --no-patch [sha]` | Get commit metadata |
| `git show [sha] -- [file]` | Get the actual changes made in a commit |
| `git ls-files -u` | List unmerged files with stage information |
| `GIT_EDITOR=true git rebase --continue` | Continue rebase after resolving conflicts |
## Best Practices
@ -141,12 +141,12 @@ Look beyond the immediate conflict to understand related changes in tests, docum
## Resolution Heuristics
| Category | Rule | Exception |
|----------|------|-----------|
| Bugfix vs Feature | Bugfixes generally take precedence | When features include the fix |
| Recent vs Old | More recent changes are often more relevant | When older changes are security patches |
| Test Updates | Changes with test updates are likely more complete | - |
| Formatting vs Logic | Logic changes take precedence over formatting | - |
| Category | Rule | Exception |
| ------------------- | -------------------------------------------------- | --------------------------------------- |
| Bugfix vs Feature | Bugfixes generally take precedence | When features include the fix |
| Recent vs Old | More recent changes are often more relevant | When older changes are security patches |
| Test Updates | Changes with test updates are likely more complete | - |
| Formatting vs Logic | Logic changes take precedence over formatting | - |
## Common Pitfalls

View file

@ -29,10 +29,10 @@ Localize all strings into the following locale files: ca, de, en, es, fr, hi, id
The VSCode extension has two main areas that require localization:
| Component | Path | Purpose |
|-----------|------|---------|
| **Core Extension** | `src/i18n/locales/` | Extension backend strings |
| **WebView UI** | `webview-ui/src/i18n/locales/` | User interface strings |
| Component | Path | Purpose |
| ------------------ | ------------------------------ | ------------------------- |
| **Core Extension** | `src/i18n/locales/` | Extension backend strings |
| **WebView UI** | `webview-ui/src/i18n/locales/` | User interface strings |
## Brand Voice, Tone, and Word Choice
@ -77,17 +77,19 @@ This guidance file is loaded at runtime and should be consulted for the latest b
### Trans Component Example
Translation string:
```json
"changeSettings": "You can always change this at the bottom of the <settingsLink>settings</settingsLink>"
```
React component usage:
```tsx
<Trans
i18nKey="welcome:telemetry.changeSettings"
components={{
settingsLink: <VSCodeLink href="#" onClick={handleOpenSettings} />
}}
i18nKey="welcome:telemetry.changeSettings"
components={{
settingsLink: <VSCodeLink href="#" onClick={handleOpenSettings} />,
}}
/>
```
@ -105,19 +107,21 @@ React component usage:
1. First add or modify English strings, then ask for confirmation before translating to all other languages
2. Use this process for each localization task:
1. Identify where the string appears in the UI/codebase
2. Understand the context and purpose of the string
3. Update English translation first
4. Use the `search_files` tool to find JSON keys that are near new keys in English translations but do not yet exist in the other language files for `apply_diff` SEARCH context
5. Create appropriate translations for all other supported languages utilizing the `search_files` result using `apply_diff` without reading every file
6. Do not output the translated text into the chat, just modify the files
7. Validate your changes with the missing translations script
1. Identify where the string appears in the UI/codebase
2. Understand the context and purpose of the string
3. Update English translation first
4. Use the `search_files` tool to find JSON keys that are near new keys in English translations but do not yet exist in the other language files for `apply_diff` SEARCH context
5. Create appropriate translations for all other supported languages utilizing the `search_files` result using `apply_diff` without reading every file
6. Do not output the translated text into the chat, just modify the files
7. Validate your changes with the missing translations script
3. Flag or comment if an English source string is incomplete ("please see this...") to avoid truncated or unclear translations
4. For UI elements, distinguish between:
- Button labels: Use short imperative commands ("Save", "Cancel")
- Tooltip text: Can be slightly more descriptive
- Button labels: Use short imperative commands ("Save", "Cancel")
- Tooltip text: Can be slightly more descriptive
5. Preserve the original perspective: If text is a user command directed at the software, ensure the translation maintains this direction

39
ARCHITECTURE_NOTES.md Normal file
View file

@ -0,0 +1,39 @@
ARCHITECTURE REPORT: The Governed AI-Native IDERole: Forward Deployed Engineer (FDE)Framework: TRACE (Trusted Runtime for Autonomous Containment and Evidence)Executive SummaryThis report formalizes the architecture for a governed AI-Native IDE, engineered to bridge the Provenance Gap between probabilistic reasoning and deterministic software engineering (Entire, 2026). By embedding infrastructure-level mediation into the IDE tool loop, we replace "vibe coding" with cryptographic verification and structured intent (TRACE, 2026; Bora, 2024).1. How the VS Code Extension Works: Dual-Process TopologyTo ensure security and performance, the extension operates as a distributed system within VS Code (VS Code, 2026):Extension Host (Logic Layer): A Node.js process where the core orchestrator (src/core/Cline.ts) manages the agentic loop. It has full privileges for filesystem access and terminal execution (VS Code, 2026).Webview (UI Layer): A restricted React sandbox for the user interface. It communicates with the Host via the postMessage API, ensuring reasoning-heavy tasks do not block the UI thread (Ansible, 2026).My architecture intercepts the Thinking-Acting-Observing loop at the Extension Host level, mediating every system-level tool call (e.g., write_to_file) before execution (Roo Code, 2026).2. Code & Design Architecture: The Shared BrainBased on my Phase 0 archaeological dig into the Roo Code "nervous system," I have implemented two critical intervention points (Bockeler, 2025):The Prompt Factory (src/core/prompts/system.ts): I modified the prompt builder to move from "Instruction-based" to "Context-based" engineering. The agent is now architecturally barred from code synthesis until it completes a mandatory "Reasoning Handshake" (Bora, 2024; Bockeler, 2025).The Shared Brain (AGENT.md): This file acts as a persistent project "Constitution." It records lessons learned from failed verification loops, preventing Context Rot during parallel agent sessions (LF Projects, 2025).3. Architectural Decisions: The TRACE Hook EngineI have implemented the TRACE framework to derive assurance from infrastructure mediation rather than model behavior (TRACE, 2026).Command Classification: Every tool is classified as Safe (Read/Search) or Destructive (Write/Execute) (Roo Code, 2026).The Handshake (Pre-Hook): Mutation is prohibited until the agent calls select_active_intent(intent_id). This pauses the promise chain and injects What-Boundaries-Success (WBS) constraints from .orchestration/active_intents.yaml into the current context (Bora, 2024).Autonomous Recovery: If the engine blocks an action, it returns a standardized JSON error to the LLM, allowing the "silicon worker" to self-correct without human intervention (TRACE, 2026).4. Diagrams & SchemasAdvanced Intent-Code Traceability FlowI integrated Nancy Levesons Seven Levels of Intent Specification to provide a vertical trace from Level 1 (System Purpose) to Level 5 (Physical Code) (Navarro et al., 2001).Code snippetsequenceDiagram
participant LLM as AI Agent (Builder)
participant Hook as TRACE Hook Engine
participant AST as Tree-sitter Parser
participant FS as.orchestration/ (Ledger)
LLM->>Hook: select_active_intent(INT-001)
Note right of Hook: Loads Level 3 WBS Constraints
Hook-->>LLM: Injected XML Constraints
LLM->>Hook: write_file(src/auth.ts, content)
Hook->>AST: Parse Block to AST Node
AST-->>Hook: Structural Identity
Hook->>Hook: Calculate H = SHA-256(Normalize(Block))
Hook->>FS: Append Trace to agent_trace.jsonl
Hook-->>LLM: Success (Level 6 Operations Data)
The Semantic Ledger Schema (agent_trace.jsonl)My ledger implements position-independent tracking by hashing specific AST nodes (Cursor, 2026).JSON{
"version": "1.0",
"id": "uuid-v4",
"timestamp": "2026-02-18T12:00:00Z",
"vcs": { "type": "git", "revision": "git_sha" },
"files": [
{
"path": "src/auth/middleware.ts",
"conversations": [
{
"contributor": { "type": "ai", "model_id": "claude-3-7-sonnet" },
"ranges": [
{
"start_line": 15,
"end_line": 45,
"content_hash": "sha256:a8f5f167f44f..."
}
]
}
]
}
]
} 5. Mathematical Verification: Spatial HashingTo solve code movement during refactors, I implemented a multidimensional Spatial Hashing algorithm (Rigaux et al., 2001; Dropstone, 2025). The content hash $H$ for an AST node $N$ is:$$H = \text{SHA-256}(\text{Normalize}(\text{Tree-sitter}(N)))$$This ensures Spatial Independence. Even if a function moves 200 lines, its cryptographic identity remains linked to the original business intent, allowing us to mathematically distinguish between an AST_REFACTOR and an INTENT_EVOLUTION (Dropstone, 2025).6. Repository Structure: src/hooks/To satisfy the "Master Thinker" rubric, I organized the src/hooks/ folder to be clean, isolated, and modular:types.ts: Shared interfaces for WBS contexts and mutation classes (Bora, 2024).HookEngine.ts: The central orchestrator wrapping the executeTool pipeline.IntentManager.ts: State management for the two-stage handshake.TraceLogger.ts: Implementation of SHA-256 hashing and the JSONL semantic ledger.7. Conclusion: Repaying the Cognitive DebtBy embedding Levesons hierarchy and the TRACE framework into the IDE host, I have repaid the Trust Debt of AI coding (Vella, 2026). Human intent remains the "Supreme Guiding Principle," making every AI-generated line verifiable and structurally sound (Bora, 2024; LF Projects, 2025).

View file

@ -35,7 +35,7 @@
- [简体中文](locales/zh-CN/README.md)
- [繁體中文](locales/zh-TW/README.md)
- ...
</details>
</details>
---
@ -66,10 +66,10 @@ Learn more: [Using Modes](https://docs.roocode.com/basic-usage/using-modes) •
<div align="center">
| | | |
| :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Installing Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Configuring Profiles</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Codebase Indexing</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Custom Modes</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Checkpoints</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Context Management</b> |
| | | |
| :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Installing Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Configuring Profiles</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Codebase Indexing</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Custom Modes</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Checkpoints</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Context Management</b> |
</div>
<p align="center">

View file

@ -1,159 +1,152 @@
const path = require('path');
const fs = require('fs');
const matter = require('gray-matter');
const path = require("path")
const fs = require("fs")
const matter = require("gray-matter")
/**
* Get published blog posts for sitemap
* Note: This runs at build time, so recently-scheduled posts may lag
*/
function getPublishedBlogPosts() {
const BLOG_DIR = path.join(process.cwd(), 'src/content/blog');
if (!fs.existsSync(BLOG_DIR)) {
return [];
}
const files = fs.readdirSync(BLOG_DIR).filter(f => f.endsWith('.md'));
const posts = [];
// Get current time in PT for publish check
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'America/Los_Angeles',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false,
});
const parts = formatter.formatToParts(new Date());
const get = (type) => parts.find(p => p.type === type)?.value ?? '';
const nowDate = `${get('year')}-${get('month')}-${get('day')}`;
const nowMinutes = parseInt(get('hour')) * 60 + parseInt(get('minute'));
for (const file of files) {
const filepath = path.join(BLOG_DIR, file);
const raw = fs.readFileSync(filepath, 'utf8');
const { data } = matter(raw);
// Check if post is published
if (data.status !== 'published') continue;
// Parse publish time
const timeMatch = data.publish_time_pt?.match(/^(1[0-2]|[1-9]):([0-5][0-9])(am|pm)$/i);
if (!timeMatch) continue;
let hours = parseInt(timeMatch[1]);
const mins = parseInt(timeMatch[2]);
const isPm = timeMatch[3].toLowerCase() === 'pm';
if (hours === 12) hours = isPm ? 12 : 0;
else if (isPm) hours += 12;
const postMinutes = hours * 60 + mins;
// Check if post is past publish date/time
const isPublished = nowDate > data.publish_date ||
(nowDate === data.publish_date && nowMinutes >= postMinutes);
if (isPublished && data.slug) {
posts.push(data.slug);
}
}
return posts;
const BLOG_DIR = path.join(process.cwd(), "src/content/blog")
if (!fs.existsSync(BLOG_DIR)) {
return []
}
const files = fs.readdirSync(BLOG_DIR).filter((f) => f.endsWith(".md"))
const posts = []
// Get current time in PT for publish check
const formatter = new Intl.DateTimeFormat("en-US", {
timeZone: "America/Los_Angeles",
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
hour12: false,
})
const parts = formatter.formatToParts(new Date())
const get = (type) => parts.find((p) => p.type === type)?.value ?? ""
const nowDate = `${get("year")}-${get("month")}-${get("day")}`
const nowMinutes = parseInt(get("hour")) * 60 + parseInt(get("minute"))
for (const file of files) {
const filepath = path.join(BLOG_DIR, file)
const raw = fs.readFileSync(filepath, "utf8")
const { data } = matter(raw)
// Check if post is published
if (data.status !== "published") continue
// Parse publish time
const timeMatch = data.publish_time_pt?.match(/^(1[0-2]|[1-9]):([0-5][0-9])(am|pm)$/i)
if (!timeMatch) continue
let hours = parseInt(timeMatch[1])
const mins = parseInt(timeMatch[2])
const isPm = timeMatch[3].toLowerCase() === "pm"
if (hours === 12) hours = isPm ? 12 : 0
else if (isPm) hours += 12
const postMinutes = hours * 60 + mins
// Check if post is past publish date/time
const isPublished = nowDate > data.publish_date || (nowDate === data.publish_date && nowMinutes >= postMinutes)
if (isPublished && data.slug) {
posts.push(data.slug)
}
}
return posts
}
/** @type {import('next-sitemap').IConfig} */
module.exports = {
siteUrl: process.env.NEXT_PUBLIC_SITE_URL || 'https://roocode.com',
generateRobotsTxt: true,
generateIndexSitemap: false, // We don't need index sitemap for a small site
changefreq: 'monthly',
priority: 0.7,
sitemapSize: 5000,
exclude: [
'/api/*',
'/server-sitemap-index.xml',
'/404',
'/500',
'/_not-found',
],
robotsTxtOptions: {
policies: [
{
userAgent: '*',
allow: '/',
},
],
additionalSitemaps: [
// Add any additional sitemaps here if needed in the future
],
},
// Custom transform function to set specific priorities and change frequencies
transform: async (config, path) => {
// Set custom priority for specific pages
let priority = config.priority;
let changefreq = config.changefreq;
if (path === '/') {
priority = 1.0;
changefreq = 'yearly';
} else if (path === '/enterprise' || path === '/evals') {
priority = 0.8;
changefreq = 'monthly';
} else if (path === '/privacy' || path === '/terms') {
priority = 0.5;
changefreq = 'yearly';
} else if (path === '/blog') {
priority = 0.8;
changefreq = 'weekly';
} else if (path.startsWith('/blog/')) {
priority = 0.7;
changefreq = 'monthly';
}
return {
loc: path,
changefreq,
priority,
lastmod: config.autoLastmod ? new Date().toISOString() : undefined,
alternateRefs: config.alternateRefs ?? [],
};
},
additionalPaths: async (config) => {
const result = [];
// Add the /evals page since it's a dynamic route
result.push({
loc: '/evals',
changefreq: 'monthly',
priority: 0.8,
lastmod: new Date().toISOString(),
});
// Add /blog index
result.push({
loc: '/blog',
changefreq: 'weekly',
priority: 0.8,
lastmod: new Date().toISOString(),
});
// Add published blog posts
try {
const slugs = getPublishedBlogPosts();
for (const slug of slugs) {
result.push({
loc: `/blog/${slug}`,
changefreq: 'monthly',
priority: 0.7,
lastmod: new Date().toISOString(),
});
}
} catch (e) {
console.warn('Could not load blog posts for sitemap:', e.message);
}
return result;
},
};
siteUrl: process.env.NEXT_PUBLIC_SITE_URL || "https://roocode.com",
generateRobotsTxt: true,
generateIndexSitemap: false, // We don't need index sitemap for a small site
changefreq: "monthly",
priority: 0.7,
sitemapSize: 5000,
exclude: ["/api/*", "/server-sitemap-index.xml", "/404", "/500", "/_not-found"],
robotsTxtOptions: {
policies: [
{
userAgent: "*",
allow: "/",
},
],
additionalSitemaps: [
// Add any additional sitemaps here if needed in the future
],
},
// Custom transform function to set specific priorities and change frequencies
transform: async (config, path) => {
// Set custom priority for specific pages
let priority = config.priority
let changefreq = config.changefreq
if (path === "/") {
priority = 1.0
changefreq = "yearly"
} else if (path === "/enterprise" || path === "/evals") {
priority = 0.8
changefreq = "monthly"
} else if (path === "/privacy" || path === "/terms") {
priority = 0.5
changefreq = "yearly"
} else if (path === "/blog") {
priority = 0.8
changefreq = "weekly"
} else if (path.startsWith("/blog/")) {
priority = 0.7
changefreq = "monthly"
}
return {
loc: path,
changefreq,
priority,
lastmod: config.autoLastmod ? new Date().toISOString() : undefined,
alternateRefs: config.alternateRefs ?? [],
}
},
additionalPaths: async (config) => {
const result = []
// Add the /evals page since it's a dynamic route
result.push({
loc: "/evals",
changefreq: "monthly",
priority: 0.8,
lastmod: new Date().toISOString(),
})
// Add /blog index
result.push({
loc: "/blog",
changefreq: "weekly",
priority: 0.8,
lastmod: new Date().toISOString(),
})
// Add published blog posts
try {
const slugs = getPublishedBlogPosts()
for (const slug of slugs) {
result.push({
loc: `/blog/${slug}`,
changefreq: "monthly",
priority: 0.7,
lastmod: new Date().toISOString(),
})
}
} catch (e) {
console.warn("Could not load blog posts for sitemap:", e.message)
}
return result
},
}

View file

@ -1,6 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View file

@ -37,8 +37,8 @@ export default async function ExtensionPage() {
<p className="mt-4 max-w-lg text-lg text-muted-foreground text-center md:text-left sm:mt-6">
Specialized modes stay on task and ship great code.
<br />
Fully model-agnostic so you can use the best (or most cost-effective) model for
each task.
Fully model-agnostic so you can use the best (or most cost-effective) model for each
task.
</p>
<p className="max-w-lg text-lg text-muted-foreground text-center md:text-left sm:mt-6">
Stop chasing this week&apos;s hot new model or CLI tool and go deep with Roo Code.

View file

@ -291,11 +291,7 @@ export default function PricingPage() {
<li>To pay for Cloud Agents running time (${PRICE_CREDITS}/hour)</li>
<li>
To pay for AI model inference costs (
<a
href="/provider"
target="_blank"
rel="noopener noreferrer"
className="underline">
<a href="/provider" target="_blank" rel="noopener noreferrer" className="underline">
varies by model
</a>
)

View file

@ -1,22 +1,21 @@
version: 1.3
pr_review:
# Modify confidence_threshold to show fewer/more comments. Increase this to show fewer, but higher quality comments.
# If theres too much noise, we suggest 0.9. The default value is 0.7.
confidence_threshold: 0.7
# If quiet mode is enabled, Ellipsis will only leave reviews when it has comments, so “Looks good to me” reviews
# will be skipped. This can reduce clutter.
quiet: true
# You can disable automatic code review using auto_review_enabled. This will override any global settings you
# have configured via the web UI.
auto_review_enabled: true
# Modify confidence_threshold to show fewer/more comments. Increase this to show fewer, but higher quality comments.
# If theres too much noise, we suggest 0.9. The default value is 0.7.
confidence_threshold: 0.7
# You can enable auto-review on draft PRs using auto_review_draft. This will override any global settings you
# have configured via the web UI.
auto_review_draft: false
# You can allow Ellipsis to approve PRs using enable_approve_prs. Note: in common branch GitHub protection configurations,
# the Ellipsis approval will count towards the approval total and allow the PR to be merged when it otherwise may not be.
enable_approve_prs: false
# If quiet mode is enabled, Ellipsis will only leave reviews when it has comments, so “Looks good to me” reviews
# will be skipped. This can reduce clutter.
quiet: true
# You can disable automatic code review using auto_review_enabled. This will override any global settings you
# have configured via the web UI.
auto_review_enabled: true
# You can enable auto-review on draft PRs using auto_review_draft. This will override any global settings you
# have configured via the web UI.
auto_review_draft: false
# You can allow Ellipsis to approve PRs using enable_approve_prs. Note: in common branch GitHub protection configurations,
# the Ellipsis approval will count towards the approval total and allow the PR to be merged when it otherwise may not be.
enable_approve_prs: false

4
locales/ca/README.md generated
View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -69,7 +69,7 @@ Més informació: [Ús de Modes](https://docs.roocode.com/basic-usage/using-mode
| | | |
| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Instal·lant Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Configurant perfils</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Indexació de la base de codi</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Modes personalitzats</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Punts de control</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Gestió de Context</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Modes personalitzats</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Punts de control</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Gestió de Context</b> |
</div>
<p align="center">

4
locales/de/README.md generated
View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -69,7 +69,7 @@ Mehr erfahren: [Modi verwenden](https://docs.roocode.com/basic-usage/using-modes
| | | |
| :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Roo Code installieren</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Profile konfigurieren</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Codebasis-Indizierung</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Benutzerdefinierte Modi</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Checkpoints</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Kontextverwaltung</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Benutzerdefinierte Modi</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Checkpoints</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Kontextverwaltung</b> |
</div>
<p align="center">

4
locales/es/README.md generated
View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -69,7 +69,7 @@ Más info: [Usar Modos](https://docs.roocode.com/basic-usage/using-modes) • [M
| | | |
| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Instalando Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Configurando perfiles</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Indexación de la base de código</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Modos personalizados</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Checkpoints</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Gestión de Contexto</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Modos personalizados</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Checkpoints</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Gestión de Contexto</b> |
</div>
<p align="center">

4
locales/fr/README.md generated
View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -69,7 +69,7 @@ En savoir plus : [Utiliser les Modes](https://docs.roocode.com/basic-usage/using
| | | |
| :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Installer Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Configurer les profils</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Indexation de la base de code</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Modes personnalisés</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Checkpoints</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Gestion du Contexte</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Modes personnalisés</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Checkpoints</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Gestion du Contexte</b> |
</div>
<p align="center">

4
locales/hi/README.md generated
View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -69,7 +69,7 @@
| | | |
| :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>रू कोड इंस्टॉल करना</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>प्रोफाइल कॉन्फ़िगर करना</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>कोडबेस इंडेक्सिंग</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>कस्टम मोड</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>चेकपॉइंट्स</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>संदर्भ प्रबंधन</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>कस्टम मोड</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>चेकपॉइंट्स</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>संदर्भ प्रबंधन</b> |
</div>
<p align="center">

4
locales/id/README.md generated
View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -69,7 +69,7 @@ Pelajari lebih lanjut: [Menggunakan Mode](https://docs.roocode.com/basic-usage/u
| | | |
| :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Menginstal Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Mengonfigurasi Profil</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Pengindeksan Basis Kode</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Mode Kustom</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Pos Pemeriksaan</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Manajemen Konteks</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Mode Kustom</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Pos Pemeriksaan</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Manajemen Konteks</b> |
</div>
<p align="center">

4
locales/it/README.md generated
View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -69,7 +69,7 @@ Scopri di più: [Usare le Modalità](https://docs.roocode.com/basic-usage/using-
| | | |
| :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Installazione di Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Configurazione dei profili</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Indicizzazione della codebase</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Modalità personalizzate</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Checkpoint</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Gestione del Contesto</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Modalità personalizzate</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Checkpoint</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Gestione del Contesto</b> |
</div>
<p align="center">

4
locales/ja/README.md generated
View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -69,7 +69,7 @@ Roo Codeは、あなたの働き方に合わせるように適応します。
| | | |
| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Roo Codeのインストール</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>プロファイルの設定</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>コードベースのインデックス作成</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>カスタムモード</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>チェックポイント</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>コンテキスト管理</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>カスタムモード</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>チェックポイント</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>コンテキスト管理</b> |
</div>
<p align="center">

4
locales/ko/README.md generated
View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -69,7 +69,7 @@ Roo Code는 당신의 작업 방식에 맞춰 적응합니다.
| | | |
| :---------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Roo Code 설치하기</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>프로필 구성하기</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>코드베이스 인덱싱</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>사용자 지정 모드</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>체크포인트</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>컨텍스트 관리</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>사용자 지정 모드</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>체크포인트</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>컨텍스트 관리</b> |
</div>
<p align="center">

2
locales/nl/README.md generated
View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---

4
locales/pl/README.md generated
View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -69,7 +69,7 @@ Więcej: [Korzystanie z trybów](https://docs.roocode.com/basic-usage/using-mode
| | | |
| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Instalacja Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Konfiguracja profili</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Indeksowanie bazy kodu</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Tryby niestandardowe</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Punkty kontrolne</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Zarządzanie Kontekstem</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Tryby niestandardowe</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Punkty kontrolne</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Zarządzanie Kontekstem</b> |
</div>
<p align="center">

View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -69,7 +69,7 @@ Saiba mais: [Usar Modos](https://docs.roocode.com/basic-usage/using-modes) • [
| | | |
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Instalando o Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Configurando perfis</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Indexação da base de código</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Modos personalizados</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Checkpoints</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Gerenciamento de Contexto</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Modos personalizados</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Checkpoints</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Gerenciamento de Contexto</b> |
</div>
<p align="center">

4
locales/ru/README.md generated
View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -69,7 +69,7 @@ Roo Code адаптируется к вашему стилю работы, а н
| | | |
| :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Установка Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Настройка профилей</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Индексация кодовой базы</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Пользовательские режимы</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Контрольные точки</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Управление Контекстом</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Пользовательские режимы</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Контрольные точки</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Управление Контекстом</b> |
</div>
<p align="center">

10
locales/tr/README.md generated
View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -66,10 +66,10 @@ Daha fazla: [Modları kullanma](https://docs.roocode.com/basic-usage/using-modes
<div align="center">
| | | |
| :---------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Roo Code Kurulumu</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Profilleri Yapılandırma</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Kod Tabanı İndeksleme</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Özel Modlar</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Kontrol Noktaları</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Bağlam Yönetimi</b> |
| | | |
| :---------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Roo Code Kurulumu</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Profilleri Yapılandırma</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Kod Tabanı İndeksleme</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Özel Modlar</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Kontrol Noktaları</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Bağlam Yönetimi</b> |
</div>
<p align="center">

10
locales/vi/README.md generated
View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -66,10 +66,10 @@ Xem thêm: [Sử dụng Chế độ](https://docs.roocode.com/basic-usage/using-
<div align="center">
| | | |
| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Cài đặt Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Định cấu hình Hồ sơ</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Lập chỉ mục cơ sở mã</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Chế độ tùy chỉnh</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Điểm kiểm tra</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Quản lý Ngữ cảnh</b> |
| | | |
| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Cài đặt Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Định cấu hình Hồ sơ</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Lập chỉ mục cơ sở mã</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Chế độ tùy chỉnh</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Điểm kiểm tra</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Quản lý Ngữ cảnh</b> |
</div>
<p align="center">

View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---
@ -66,9 +66,9 @@ Roo Code 适应您的工作方式,而不是相反:
<div align="center">
| | | |
| :-----------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>安装 Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>配置个人资料</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>代码库索引</b> |
| | | |
| :-----------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>安装 Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>配置个人资料</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>代码库索引</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>自定义模式</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>检查点</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>上下文管理</b> |
</div>

View file

@ -35,7 +35,7 @@
- [简体中文](../zh-CN/README.md)
- [繁體中文](../zh-TW/README.md)
- ...
</details>
</details>
---

View file

@ -32,6 +32,7 @@
"@dotenvx/dotenvx": "^1.34.0",
"@roo-code/config-typescript": "workspace:^",
"@types/glob": "^9.0.0",
"@types/js-yaml": "^4.0.9",
"@types/node": "^24.1.0",
"@vscode/vsce": "3.3.2",
"esbuild": "^0.25.0",

50305
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -676,14 +676,12 @@ describe("useMcpToolTool", () => {
mockProviderRef.deref.mockReturnValue({
getMcpHub: () => ({
callTool: vi.fn().mockResolvedValue(mockToolResult),
getAllServers: vi
.fn()
.mockReturnValue([
{
name: "figma-server",
tools: [{ name: "get_screenshot", description: "Get screenshot" }],
},
]),
getAllServers: vi.fn().mockReturnValue([
{
name: "figma-server",
tools: [{ name: "get_screenshot", description: "Get screenshot" }],
},
]),
}),
postMessageToWebview: vi.fn(),
})
@ -790,14 +788,12 @@ describe("useMcpToolTool", () => {
mockProviderRef.deref.mockReturnValue({
getMcpHub: () => ({
callTool: vi.fn().mockResolvedValue(mockToolResult),
getAllServers: vi
.fn()
.mockReturnValue([
{
name: "figma-server",
tools: [{ name: "get_screenshot", description: "Get screenshot" }],
},
]),
getAllServers: vi.fn().mockReturnValue([
{
name: "figma-server",
tools: [{ name: "get_screenshot", description: "Get screenshot" }],
},
]),
}),
postMessageToWebview: vi.fn(),
})
@ -852,14 +848,12 @@ describe("useMcpToolTool", () => {
mockProviderRef.deref.mockReturnValue({
getMcpHub: () => ({
callTool: vi.fn().mockResolvedValue(mockToolResult),
getAllServers: vi
.fn()
.mockReturnValue([
{
name: "figma-server",
tools: [{ name: "get_screenshots", description: "Get screenshots" }],
},
]),
getAllServers: vi.fn().mockReturnValue([
{
name: "figma-server",
tools: [{ name: "get_screenshots", description: "Get screenshots" }],
},
]),
}),
postMessageToWebview: vi.fn(),
})

38
src/hooks/HookEngine.ts Normal file
View file

@ -0,0 +1,38 @@
import { IntentManager } from "./IntentManager"
import { TraceLogger } from "./TraceLogger"
export class HookEngine {
private intentManager = new IntentManager()
private traceLogger = new TraceLogger()
/**
* Intercepts the Thinking-Acting loop at the Extension Host level (VS Code, 2026).
*/
async preToolUse(toolName: string, args: any): Promise<string | void> {
// Classification: Mediation depends on the risk level of the tool (TRACE, 2026)
const isDestructive = ["write_to_file", "execute_command", "apply_diff"].includes(toolName)
if (toolName === "select_active_intent") {
return await this.intentManager.loadIntentContext(args.intent_id)
}
// Enforcement: Fail-Closed halting if no intent is active (TRACE, 2026)
if (isDestructive && !this.intentManager.getActiveIntent()) {
throw new Error(
`Governance Violation: Mutation tool '${toolName}' blocked. You must call 'select_active_intent' first.`,
)
}
if (toolName === "write_to_file") {
this.intentManager.verifyScope(args.path)
}
}
async postToolUse(toolName: string, args: any, result: string): Promise<void> {
const activeIntentId = this.intentManager.getActiveIntent()
if (toolName === "write_to_file" && activeIntentId) {
await this.traceLogger.logMutation(activeIntentId, args.path, args.content)
}
}
}

View file

@ -0,0 +1,64 @@
import * as fs from "fs/promises"
import * as path from "path"
import * as yaml from "js-yaml"
import { WBSContext } from "./types"
export class IntentManager {
private activeIntent: WBSContext | null = null
private orchestrationPath = path.join(process.cwd(), ".orchestration", "active_intents.yaml")
/**
* Stage 1: The Handshake.
* Loads the What-Boundaries-Success (WBS) framework constraints
* for the selected requirement (Bora, 2024).
*/
async loadIntentContext(intentId: string): Promise<string> {
try {
const fileContent = await fs.readFile(this.orchestrationPath, "utf8")
const data: any = yaml.load(fileContent)
const intent = data.active_intents.find((i: any) => i.id === intentId)
if (!intent) {
throw new Error(`Intent ID ${intentId} not found in .orchestration/active_intents.yaml`)
}
this.activeIntent = intent
// Inject Level 3 Black-Box Functional Model constraints (Navarro et al., 2001)
return `<intent_context>
ID: ${intent.id}
WHAT: ${intent.what.join(", ")}
BOUNDARIES: ${intent.constraints.join(", ")}
SUCCESS: ${intent.acceptance_criteria.join(", ")}
OWNED_SCOPE: ${intent.owned_scope.join(", ")}
</intent_context>`
} catch (error: any) {
throw new Error(`Intent Handshake Failed: ${error.message}`)
}
}
/**
* Returns the ID of the currently active intent, or null if none.
*/
getActiveIntent(): string | null {
return this.activeIntent?.id || null
}
/**
* Scope Enforcement: Verifies if the target file is within
* the authorized 'owned_scope' of the active intent.
*/
verifyScope(targetPath: string): void {
if (!this.activeIntent) return
// Simplified glob matching; implement full 'picomatch' or 'minimatch' for production
const isAuthorized = this.activeIntent.owned_scope.some((pattern) =>
targetPath.includes(pattern.replace("/**", "")),
)
if (!isAuthorized) {
throw new Error(`Scope Violation: Intent ${this.activeIntent.id} is not authorized to edit ${targetPath}`)
}
}
}

47
src/hooks/TraceLogger.ts Normal file
View file

@ -0,0 +1,47 @@
import * as crypto from "crypto"
import * as fs from "fs/promises"
import * as path from "path"
import { TraceRecord } from "./types"
export class TraceLogger {
private ledgerPath = path.join(process.cwd(), ".orchestration", "agent_trace.jsonl")
/**
* Calculates the content hash H = SHA-256(Normalize(Block))
* to provide Structural Identity (Dropstone, 2025).
*/
private calculateSpatialHash(content: string): string {
const normalized = content.replace(/\s+/g, " ").trim() // Normalize whitespace
return crypto.createHash("sha256").update(normalized).digest("hex")
}
async logMutation(intentId: string, filePath: string, content: string): Promise<void> {
const hash = this.calculateSpatialHash(content)
const record: TraceRecord = {
version: "1.0",
id: crypto.randomUUID(),
timestamp: new Date().toISOString(),
files: [
{
path: filePath,
conversations: [
{
contributor: { type: "ai" },
ranges: [
{
start_line: 1, // Full file write context
end_line: content.split("\n").length,
content_hash: `sha256:${hash}`,
},
],
},
],
},
],
}
// Append to the hash-chained evidence log (TRACE, 2026)
await fs.appendFile(this.ledgerPath, JSON.stringify(record) + "\n")
}
}

49
src/hooks/types.ts Normal file
View file

@ -0,0 +1,49 @@
/**
* MutationClass differentiates between changes that preserve existing
* business logic (Refactor) and those that introduce new requirements (Evolution).
*/
export enum MutationClass {
AST_REFACTOR = "AST_REFACTOR",
INTENT_EVOLUTION = "INTENT_EVOLUTION",
}
/**
* WBSContext formalizes the "What-Boundaries-Success" framework
* to reduce the LLM's solution space through structured constraints.[1]
*/
export interface WBSContext {
id: string // e.g., "INT-001"
owned_scope: string // Glob patterns of authorized files
what: string // Functional requirements
boundaries: string // "Soft constraints" to prevent hallucinations [1]
success: string // Measurable criteria for the "Definition of Done"
}
/**
* TraceRecord follows the Agent Trace specification to provide
* a position-independent audit log of AI contributions.
*/
export interface TraceRecord {
version: string // Specification version (e.g., "1.0")
id: string // Unique UUID for the trace event
timestamp: string // ISO 8601 recorded time
vcs?: {
type: "git" | "jj" | "hg" | "svn"
revision: string // VCS-specific revision hash
}
files: Array<{
path: string
conversations: Array<{
contributor: {
type: "human" | "ai" | "mixed" | "unknown"
model_id?: string
}
ranges: Array<{
start_line: number
end_line: number
// Content hash H for spatial independence
content_hash?: string
}>
}>
}>
}

View file

@ -942,9 +942,7 @@ describe("worktree path comparison", () => {
// Second init with stubbed worktree returning a trailing newline
const service2 = new RepoPerTaskCheckpointService("trim-test-2", shadowDir, workspaceDir, () => {})
vitest
.spyOn(service2 as any, "getShadowGitConfigWorktree")
.mockResolvedValue(workspaceDir + "\n")
vitest.spyOn(service2 as any, "getShadowGitConfigWorktree").mockResolvedValue(workspaceDir + "\n")
await service2.initShadowGit()
} finally {
@ -983,9 +981,7 @@ describe("worktree path comparison", () => {
// Second init should throw because core.worktree is missing
const service2 = new RepoPerTaskCheckpointService("missing-test-2", shadowDir, workspaceDir, () => {})
await expect(service2.initShadowGit()).rejects.toThrowError(
/core\.worktree to be set/,
)
await expect(service2.initShadowGit()).rejects.toThrowError(/core\.worktree to be set/)
} finally {
vitest.restoreAllMocks()
await fs.rm(shadowDir, { recursive: true, force: true })

46
webview-ui/.gitignore vendored
View file

@ -1,27 +1,37 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
# --------------------------------------------------
# Dependencies
# --------------------------------------------------
node_modules/
.pnp/
.pnp.js
# testing
/coverage
# pnpm
pnpm-lock.yaml
# production
/build
# --------------------------------------------------
# Build Outputs
# --------------------------------------------------
dist/
build/
out/
.next/
coverage/
*.tsbuildinfo
# misc
.DS_Store
# Webview / Vite
webview-ui/dist/
webview-ui/.vite/
# --------------------------------------------------
# Environment Files
# --------------------------------------------------
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
*storybook.log
tsconfig.tsbuildinfo
# --------------------------------------------------
# Logs
# --------------------------------------------------
npm-debug.log

View file

@ -108,7 +108,7 @@ export function MarketplaceView({ stateManager, onDone, targetTab }: Marketplace
onClick={() => onDone?.()}
aria-label={t("settings:back")}>
<ArrowLeft />
<span className="sr-only">{t("settings:back")}</span>
<span className="sr-only">{t("settings:back")}</span>
</Button>
<h3 className="font-bold m-0">{t("marketplace:title")}</h3>
</div>