diff --git a/.github/workflows/changeset-release.yml b/.github/workflows/changeset-release.yml
index 1b291abcb7..7c274b0639 100644
--- a/.github/workflows/changeset-release.yml
+++ b/.github/workflows/changeset-release.yml
@@ -31,8 +31,6 @@ jobs:
ref: ${{ env.GIT_REF }}
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
- with:
- skip-checkout: 'true'
# Check if there are any new changesets to process
- name: Check for changesets
diff --git a/.github/workflows/marketplace-publish.yml b/.github/workflows/marketplace-publish.yml
index 1aa6815205..aef91b2d32 100644
--- a/.github/workflows/marketplace-publish.yml
+++ b/.github/workflows/marketplace-publish.yml
@@ -25,8 +25,6 @@ jobs:
ref: ${{ env.GIT_REF }}
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
- with:
- skip-checkout: 'true'
- name: Configure Git
run: |
git config user.name "github-actions[bot]"
diff --git a/.github/workflows/nightly-publish.yml b/.github/workflows/nightly-publish.yml
index 8ce4c5ca6a..e25bdba990 100644
--- a/.github/workflows/nightly-publish.yml
+++ b/.github/workflows/nightly-publish.yml
@@ -20,7 +20,6 @@ jobs:
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
with:
- skip-checkout: 'true'
install-args: '--frozen-lockfile'
- name: Forge numeric Nightly version
id: version
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fd742901f4..018b9330da 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,27 @@
# Roo Code Changelog
+## [3.23.12] - 2025-07-15
+
+- Update the max-token calculation in model-params to better support Kimi K2 and others
+
+## [3.23.11] - 2025-07-14
+
+- Add Kimi K2 model to Groq along with fixes to context condensing math
+- Add Cmd+Shift+. keyboard shortcut for previous mode switching
+
+## [3.23.10] - 2025-07-14
+
+- Prioritize built-in model dimensions over custom dimensions (thanks @daniel-lxs!)
+- Add padding to the index model options
+
+## [3.23.9] - 2025-07-14
+
+- Enable Claude Code provider to run natively on Windows (thanks @SannidhyaSah!)
+- Add gemini-embedding-001 model to code-index service (thanks @daniel-lxs!)
+- Resolve vector dimension mismatch error when switching embedding models
+- Return the cwd in the exec tool's response so that the model is not lost after subsequent calls (thanks @chris-garrett!)
+- Add configurable timeout for command execution in VS Code settings
+
## [3.23.8] - 2025-07-13
- Add enable/disable toggle for code indexing (thanks @daniel-lxs!)
diff --git a/README.md b/README.md
index 4a95869dc2..e94f0d884a 100644
--- a/README.md
+++ b/README.md
@@ -207,43 +207,44 @@ Thanks to all our contributors who have helped make Roo Code better!
-| 
mrubens | 
saoudrizwan | 
cte | 
samhvw8 | 
daniel-lxs | 
hannesrudolph |
-| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
-| 
KJ7LNW | 
a8trejo | 
ColemanRoo | 
canrobins13 | 
stea9499 | 
MuriloFP |
-| 
joemanley201 | 
System233 | 
jr | 
nissa-seru | 
jquanton | 
NyxJae |
-| 
elianiva | 
roomote-bot | 
d-oit | 
punkpeye | 
wkordalski | 
qdaxb |
-| 
xyOz-dev | 
feifei325 | 
zhangtony239 | 
sachasayan | 
monotykamary | 
cannuri |
-| 
Smartsheet-JB-Brown | 
shariqriazz | 
vigneshsubbiah16 | 
chrarnoldus | 
pugazhendhi-m | 
lloydchang |
-| 
SannidhyaSah | 
dtrugman | 
Szpadel | 
diarmidmackenzie | 
olweraltuve | 
psv2522 |
-| 
Premshay | 
kiwina | 
lupuletic | 
aheizi | 
liwilliam2021 | 
PeterDaveHello |
-| 
hassoncs | 
ChuKhaLi | 
nbihan-mediware | 
noritaka1166 | 
RaySinner | 
afshawnlotfi |
-| 
dleffel | 
StevenTCramer | 
Ruakij | 
pdecat | 
kyle-apex | 
emshvac |
-| 
Lunchb0ne | 
SmartManoj | 
vagadiya | 
slytechnical | 
dlab-anton | 
arthurauffray |
-| 
upamune | 
NamesMT | 
taylorwilsdon | 
sammcj | 
p12tic | 
gtaylor |
-| 
aitoroses | 
bramburn | 
ross | 
mr-ryan-james | 
heyseth | 
taisukeoe |
-| 
avtc | 
eonghk | 
GOODBOY008 | 
kcwhite | 
ronyblum | 
teddyOOXX |
-| 
vincentsong | 
yongjer | 
zeozeozeo | 
ashktn | 
franekp | 
yt3trees |
-| 
seedlord | 
anton-otee | 
benzntech | 
axkirillov | 
olearycrew | 
brunobergher |
-| 
catrielmuller | 
devxpain | 
snoyiatk | 
GitlyHallows | 
jcbdev | 
Chenjiayuan195 |
-| 
julionav | 
KanTakahiro | 
SplittyDev | 
mdp | 
napter | 
philfung |
-| 
bbenshalom | 
dairui1 | 
dqroid | 
forestyoo | 
hatsu38 | 
hongzio |
-| 
im47cn | 
shoopapa | 
jwcraig | 
kinandan | 
nevermorec | 
bannzai |
-| 
axmo | 
asychin | 
amittell | 
Yoshino-Yukitaro | 
Yikai-Liao | 
zxdvd |
-| 
s97712 | 
vladstudio | 
vivekfyi | 
tmsjngx0 | 
Githubguy132010 | 
tgfjt |
-| 
pfitz | 
PretzelVector | 
zetaloop | 
cdlliuy | 
user202729 | 
takakoutso |
-| 
student20880 | 
shubhamgupta731 | 
shohei-ihaya | 
shivamd1810 | 
shaybc | 
sensei-woo |
-| 
samir-nimbly | 
robertheadley | 
refactorthis | 
qingyuan1109 | 
pokutuna | 
philipnext |
-| 
village-way | 
oprstchn | 
nobu007 | 
mosleyit | 
moqimoqidea | 
mlopezr |
-| 
mecab | 
olup | 
lightrabbit | 
lhish | 
kohii | 
ExactDoug |
-| 
celestial-vault | 
linegel | 
edwin-truthsearch-io | 
EamonNerbonne | 
dbasclpy | 
dflatline |
-| 
Deon588 | 
dleen | 
CW-B-W | 
chadgauth | 
thecolorblue | 
bogdan0083 |
-| 
benashby | 
Atlogit | 
atlasgong | 
andrewshu2000 | 
andreastempsch | 
alasano |
-| 
QuinsZouls | 
HadesArchitect | 
alarno | 
nexon33 | 
adilhafeez | 
adamwlarson |
-| 
adamhill | 
AMHesch | 
maekawataiki | 
AlexandruSmirnov | 
samsilveira | 
01Rian |
-| 
RSO | 
SECKainersdorfer | 
R-omk | 
Sarke | 
PaperBoardOfficial | 
OlegOAndreev |
-| 
kvokka | 
ecmasx | 
mollux | 
marvijo-code | 
markijbema | 
mamertofabian |
-| 
monkeyDluffy6017 | 
libertyteeth | 
shtse8 | 
Rexarrior | 
kevinvandijk | 
KevinZhao |
-| 
ksze | 
Juice10 | 
Fovty | 
Jdo300 | 
hesara | 
DeXtroTip |
+| 
mrubens | 
saoudrizwan | 
cte | 
samhvw8 | 
daniel-lxs | 
hannesrudolph |
+| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
+| 
KJ7LNW | 
a8trejo | 
ColemanRoo | 
canrobins13 | 
stea9499 | 
MuriloFP |
+| 
joemanley201 | 
System233 | 
jr | 
nissa-seru | 
jquanton | 
NyxJae |
+| 
roomote-bot | 
elianiva | 
d-oit | 
punkpeye | 
wkordalski | 
qdaxb |
+| 
xyOz-dev | 
feifei325 | 
zhangtony239 | 
sachasayan | 
monotykamary | 
cannuri |
+| 
Smartsheet-JB-Brown | 
shariqriazz | 
vigneshsubbiah16 | 
chrarnoldus | 
pugazhendhi-m | 
lloydchang |
+| 
SannidhyaSah | 
dtrugman | 
Szpadel | 
diarmidmackenzie | 
olweraltuve | 
psv2522 |
+| 
Premshay | 
kiwina | 
lupuletic | 
aheizi | 
liwilliam2021 | 
PeterDaveHello |
+| 
hassoncs | 
ChuKhaLi | 
nbihan-mediware | 
noritaka1166 | 
RaySinner | 
afshawnlotfi |
+| 
dleffel | 
StevenTCramer | 
Ruakij | 
pdecat | 
kyle-apex | 
emshvac |
+| 
Lunchb0ne | 
SmartManoj | 
vagadiya | 
slytechnical | 
dlab-anton | 
arthurauffray |
+| 
upamune | 
NamesMT | 
taylorwilsdon | 
sammcj | 
p12tic | 
gtaylor |
+| 
aitoroses | 
anton-otee | 
ross | 
mr-ryan-james | 
heyseth | 
taisukeoe |
+| 
avtc | 
eonghk | 
GOODBOY008 | 
kcwhite | 
ronyblum | 
teddyOOXX |
+| 
vincentsong | 
yongjer | 
zeozeozeo | 
ashktn | 
franekp | 
yt3trees |
+| 
seedlord | 
bramburn | 
benzntech | 
axkirillov | 
olearycrew | 
brunobergher |
+| 
catrielmuller | 
devxpain | 
snoyiatk | 
GitlyHallows | 
jcbdev | 
Chenjiayuan195 |
+| 
julionav | 
KanTakahiro | 
SplittyDev | 
mdp | 
napter | 
philfung |
+| 
chris-garrett | 
dairui1 | 
dqroid | 
forestyoo | 
hatsu38 | 
hongzio |
+| 
im47cn | 
shoopapa | 
jwcraig | 
kinandan | 
nevermorec | 
bbenshalom |
+| 
bannzai | 
axmo | 
asychin | 
amittell | 
Yoshino-Yukitaro | 
Yikai-Liao |
+| 
zxdvd | 
s97712 | 
vladstudio | 
vivekfyi | 
tmsjngx0 | 
Githubguy132010 |
+| 
tgfjt | 
PretzelVector | 
zetaloop | 
cdlliuy | 
user202729 | 
takakoutso |
+| 
student20880 | 
shubhamgupta731 | 
shohei-ihaya | 
shivamd1810 | 
shaybc | 
sensei-woo |
+| 
samir-nimbly | 
robertheadley | 
refactorthis | 
qingyuan1109 | 
pokutuna | 
philipnext |
+| 
village-way | 
oprstchn | 
nobu007 | 
mosleyit | 
moqimoqidea | 
mlopezr |
+| 
mecab | 
olup | 
lightrabbit | 
lhish | 
kohii | 
pfitz |
+| 
ExactDoug | 
celestial-vault | 
linegel | 
edwin-truthsearch-io | 
EamonNerbonne | 
dbasclpy |
+| 
dflatline | 
Deon588 | 
dleen | 
CW-B-W | 
chadgauth | 
thecolorblue |
+| 
bogdan0083 | 
benashby | 
Atlogit | 
atlasgong | 
andrewshu2000 | 
andreastempsch |
+| 
alasano | 
QuinsZouls | 
HadesArchitect | 
alarno | 
nexon33 | 
adilhafeez |
+| 
adamwlarson | 
adamhill | 
AMHesch | 
maekawataiki | 
AlexandruSmirnov | 
samsilveira |
+| 
01Rian | 
RSO | 
SECKainersdorfer | 
R-omk | 
Sarke | 
PaperBoardOfficial |
+| 
OlegOAndreev | 
kvokka | 
ecmasx | 
mollux | 
marvijo-code | 
markijbema |
+| 
mamertofabian | 
monkeyDluffy6017 | 
libertyteeth | 
shtse8 | 
Rexarrior | 
kevinvandijk |
+| 
KevinZhao | 
ksze | 
Juice10 | 
Fovty | 
Jdo300 | 
hesara |
+| 
DeXtroTip | | | | | |
diff --git a/locales/ca/README.md b/locales/ca/README.md
index cebd17f3f1..6ea7073db2 100644
--- a/locales/ca/README.md
+++ b/locales/ca/README.md
@@ -184,7 +184,7 @@ Gràcies a tots els nostres col·laboradors que han ajudat a millorar Roo Code!
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ Gràcies a tots els nostres col·laboradors que han ajudat a millorar Roo Code!
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## Llicència
diff --git a/locales/de/README.md b/locales/de/README.md
index d1abfd7cba..95ef8dce48 100644
--- a/locales/de/README.md
+++ b/locales/de/README.md
@@ -184,7 +184,7 @@ Danke an alle unsere Mitwirkenden, die geholfen haben, Roo Code zu verbessern!
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ Danke an alle unsere Mitwirkenden, die geholfen haben, Roo Code zu verbessern!
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## Lizenz
diff --git a/locales/es/README.md b/locales/es/README.md
index 924a3cce64..08e5a721a8 100644
--- a/locales/es/README.md
+++ b/locales/es/README.md
@@ -184,7 +184,7 @@ Usamos [changesets](https://github.com/changesets/changesets) para versionar y p
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ Usamos [changesets](https://github.com/changesets/changesets) para versionar y p
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## Licencia
diff --git a/locales/fr/README.md b/locales/fr/README.md
index 57c1bd83e1..8f726f338a 100644
--- a/locales/fr/README.md
+++ b/locales/fr/README.md
@@ -184,7 +184,7 @@ Merci à tous nos contributeurs qui ont aidé à améliorer Roo Code !
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ Merci à tous nos contributeurs qui ont aidé à améliorer Roo Code !
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## Licence
diff --git a/locales/hi/README.md b/locales/hi/README.md
index 32b6889a34..19e0dc944a 100644
--- a/locales/hi/README.md
+++ b/locales/hi/README.md
@@ -184,7 +184,7 @@ Roo Code को बेहतर बनाने में मदद करने
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ Roo Code को बेहतर बनाने में मदद करने
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## लाइसेंस
diff --git a/locales/id/README.md b/locales/id/README.md
index e9d13d6fa7..4141dede49 100644
--- a/locales/id/README.md
+++ b/locales/id/README.md
@@ -178,7 +178,7 @@ Terima kasih kepada semua kontributor kami yang telah membantu membuat Roo Code
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -187,30 +187,31 @@ Terima kasih kepada semua kontributor kami yang telah membantu membuat Roo Code
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## License
diff --git a/locales/it/README.md b/locales/it/README.md
index b9833c525f..8231f7c630 100644
--- a/locales/it/README.md
+++ b/locales/it/README.md
@@ -184,7 +184,7 @@ Grazie a tutti i nostri contributori che hanno aiutato a migliorare Roo Code!
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ Grazie a tutti i nostri contributori che hanno aiutato a migliorare Roo Code!
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## Licenza
diff --git a/locales/ja/README.md b/locales/ja/README.md
index a3bf15c9f2..5a1ead7bbc 100644
--- a/locales/ja/README.md
+++ b/locales/ja/README.md
@@ -184,7 +184,7 @@ Roo Codeの改善に貢献してくれたすべての貢献者に感謝します
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ Roo Codeの改善に貢献してくれたすべての貢献者に感謝します
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## ライセンス
diff --git a/locales/ko/README.md b/locales/ko/README.md
index b331e471e0..b1160f102c 100644
--- a/locales/ko/README.md
+++ b/locales/ko/README.md
@@ -184,7 +184,7 @@ Roo Code를 더 좋게 만드는 데 도움을 준 모든 기여자에게 감사
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ Roo Code를 더 좋게 만드는 데 도움을 준 모든 기여자에게 감사
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## 라이선스
diff --git a/locales/nl/README.md b/locales/nl/README.md
index 6e83d33095..97f63c555f 100644
--- a/locales/nl/README.md
+++ b/locales/nl/README.md
@@ -184,7 +184,7 @@ Dank aan alle bijdragers die Roo Code beter hebben gemaakt!
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ Dank aan alle bijdragers die Roo Code beter hebben gemaakt!
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## Licentie
diff --git a/locales/pl/README.md b/locales/pl/README.md
index 8112163896..db4addb080 100644
--- a/locales/pl/README.md
+++ b/locales/pl/README.md
@@ -184,7 +184,7 @@ Dziękujemy wszystkim naszym współtwórcom, którzy pomogli ulepszyć Roo Code
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ Dziękujemy wszystkim naszym współtwórcom, którzy pomogli ulepszyć Roo Code
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## Licencja
diff --git a/locales/pt-BR/README.md b/locales/pt-BR/README.md
index d298d0ad4a..d7234a479a 100644
--- a/locales/pt-BR/README.md
+++ b/locales/pt-BR/README.md
@@ -184,7 +184,7 @@ Obrigado a todos os nossos contribuidores que ajudaram a tornar o Roo Code melho
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ Obrigado a todos os nossos contribuidores que ajudaram a tornar o Roo Code melho
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## Licença
diff --git a/locales/ru/README.md b/locales/ru/README.md
index 7a3ed40c60..85ea090fbf 100644
--- a/locales/ru/README.md
+++ b/locales/ru/README.md
@@ -184,7 +184,7 @@ code --install-extension bin/roo-cline-.vsix
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ code --install-extension bin/roo-cline-.vsix
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## Лицензия
diff --git a/locales/tr/README.md b/locales/tr/README.md
index 2834bbd36d..35b5c5a931 100644
--- a/locales/tr/README.md
+++ b/locales/tr/README.md
@@ -184,7 +184,7 @@ Roo Code'u daha iyi hale getirmeye yardımcı olan tüm katkıda bulunanlara te
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ Roo Code'u daha iyi hale getirmeye yardımcı olan tüm katkıda bulunanlara te
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## Lisans
diff --git a/locales/vi/README.md b/locales/vi/README.md
index cf2f4cf9de..7ef33dcfd5 100644
--- a/locales/vi/README.md
+++ b/locales/vi/README.md
@@ -184,7 +184,7 @@ Cảm ơn tất cả những người đóng góp đã giúp cải thiện Roo C
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ Cảm ơn tất cả những người đóng góp đã giúp cải thiện Roo C
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## Giấy Phép
diff --git a/locales/zh-CN/README.md b/locales/zh-CN/README.md
index 4ee7bf67fc..e13c88b3b3 100644
--- a/locales/zh-CN/README.md
+++ b/locales/zh-CN/README.md
@@ -184,7 +184,7 @@ code --install-extension bin/roo-cline-.vsix
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -193,30 +193,31 @@ code --install-extension bin/roo-cline-.vsix
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## 许可证
diff --git a/locales/zh-TW/README.md b/locales/zh-TW/README.md
index 73aea4a0a0..e4ae30ad02 100644
--- a/locales/zh-TW/README.md
+++ b/locales/zh-TW/README.md
@@ -185,7 +185,7 @@ code --install-extension bin/roo-cline-.vsix
|:---:|:---:|:---:|:---:|:---:|:---:|
|
KJ7LNW|
a8trejo|
ColemanRoo|
canrobins13|
stea9499|
MuriloFP|
|
joemanley201|
System233|
jr|
nissa-seru|
jquanton|
NyxJae|
-|
elianiva|
roomote-bot|
d-oit|
punkpeye|
wkordalski|
qdaxb|
+|
roomote-bot|
elianiva|
d-oit|
punkpeye|
wkordalski|
qdaxb|
|
xyOz-dev|
feifei325|
zhangtony239|
sachasayan|
monotykamary|
cannuri|
|
Smartsheet-JB-Brown|
shariqriazz|
vigneshsubbiah16|
chrarnoldus|
pugazhendhi-m|
lloydchang|
|
SannidhyaSah|
dtrugman|
Szpadel|
diarmidmackenzie|
olweraltuve|
psv2522|
@@ -194,30 +194,31 @@ code --install-extension bin/roo-cline-.vsix
|
dleffel|
StevenTCramer|
Ruakij|
pdecat|
kyle-apex|
emshvac|
|
Lunchb0ne|
SmartManoj|
vagadiya|
slytechnical|
dlab-anton|
arthurauffray|
|
upamune|
NamesMT|
taylorwilsdon|
sammcj|
p12tic|
gtaylor|
-|
aitoroses|
bramburn|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
+|
aitoroses|
anton-otee|
ross|
mr-ryan-james|
heyseth|
taisukeoe|
|
avtc|
eonghk|
GOODBOY008|
kcwhite|
ronyblum|
teddyOOXX|
|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
yt3trees|
-|
seedlord|
anton-otee|
benzntech|
axkirillov|
olearycrew|
brunobergher|
+|
seedlord|
bramburn|
benzntech|
axkirillov|
olearycrew|
brunobergher|
|
catrielmuller|
devxpain|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
|
julionav|
KanTakahiro|
SplittyDev|
mdp|
napter|
philfung|
-|
bbenshalom|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
-|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bannzai|
-|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
-|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
tgfjt|
-|
pfitz|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
+|
chris-garrett|
dairui1|
dqroid|
forestyoo|
hatsu38|
hongzio|
+|
im47cn|
shoopapa|
jwcraig|
kinandan|
nevermorec|
bbenshalom|
+|
bannzai|
axmo|
asychin|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
+|
zxdvd|
s97712|
vladstudio|
vivekfyi|
tmsjngx0|
Githubguy132010|
+|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
takakoutso|
|
student20880|
shubhamgupta731|
shohei-ihaya|
shivamd1810|
shaybc|
sensei-woo|
|
samir-nimbly|
robertheadley|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
|
village-way|
oprstchn|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
-|
mecab|
olup|
lightrabbit|
lhish|
kohii|
ExactDoug|
-|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
bogdan0083|
-|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
alasano|
-|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
-|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
-|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
OlegOAndreev|
-|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
mamertofabian|
-|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
KevinZhao|
-|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
DeXtroTip|
+|
mecab|
olup|
lightrabbit|
lhish|
kohii|
pfitz|
+|
ExactDoug|
celestial-vault|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
CW-B-W|
chadgauth|
thecolorblue|
+|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andrewshu2000|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
+|
01Rian|
RSO|
SECKainersdorfer|
R-omk|
Sarke|
PaperBoardOfficial|
+|
OlegOAndreev|
kvokka|
ecmasx|
mollux|
marvijo-code|
markijbema|
+|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
kevinvandijk|
+|
KevinZhao|
ksze|
Juice10|
Fovty|
Jdo300|
hesara|
+|
DeXtroTip| | | | | |
## 授權
diff --git a/packages/types/src/providers/groq.ts b/packages/types/src/providers/groq.ts
index 49667e357e..2eac1f954a 100644
--- a/packages/types/src/providers/groq.ts
+++ b/packages/types/src/providers/groq.ts
@@ -10,13 +10,14 @@ export type GroqModelId =
| "qwen-qwq-32b"
| "qwen/qwen3-32b"
| "deepseek-r1-distill-llama-70b"
+ | "moonshotai/kimi-k2-instruct"
export const groqDefaultModelId: GroqModelId = "llama-3.3-70b-versatile" // Defaulting to Llama3 70B Versatile
export const groqModels = {
// Models based on API response: https://api.groq.com/openai/v1/models
"llama-3.1-8b-instant": {
- maxTokens: 131072,
+ maxTokens: 8192,
contextWindow: 131072,
supportsImages: false,
supportsPromptCache: false,
@@ -25,7 +26,7 @@ export const groqModels = {
description: "Meta Llama 3.1 8B Instant model, 128K context.",
},
"llama-3.3-70b-versatile": {
- maxTokens: 32768,
+ maxTokens: 8192,
contextWindow: 131072,
supportsImages: false,
supportsPromptCache: false,
@@ -52,7 +53,7 @@ export const groqModels = {
description: "Meta Llama 4 Maverick 17B Instruct model, 128K context.",
},
"mistral-saba-24b": {
- maxTokens: 32768,
+ maxTokens: 8192,
contextWindow: 32768,
supportsImages: false,
supportsPromptCache: false,
@@ -61,7 +62,7 @@ export const groqModels = {
description: "Mistral Saba 24B model, 32K context.",
},
"qwen-qwq-32b": {
- maxTokens: 131072,
+ maxTokens: 8192,
contextWindow: 131072,
supportsImages: false,
supportsPromptCache: false,
@@ -70,7 +71,7 @@ export const groqModels = {
description: "Alibaba Qwen QwQ 32B model, 128K context.",
},
"qwen/qwen3-32b": {
- maxTokens: 40960,
+ maxTokens: 8192,
contextWindow: 131072,
supportsImages: false,
supportsPromptCache: false,
@@ -79,7 +80,7 @@ export const groqModels = {
description: "Alibaba Qwen 3 32B model, 128K context.",
},
"deepseek-r1-distill-llama-70b": {
- maxTokens: 131072,
+ maxTokens: 8192,
contextWindow: 131072,
supportsImages: false,
supportsPromptCache: false,
@@ -87,4 +88,13 @@ export const groqModels = {
outputPrice: 0.99,
description: "DeepSeek R1 Distill Llama 70B model, 128K context.",
},
+ "moonshotai/kimi-k2-instruct": {
+ maxTokens: 16384,
+ contextWindow: 131072,
+ supportsImages: false,
+ supportsPromptCache: false,
+ inputPrice: 1.0,
+ outputPrice: 3.0,
+ description: "Moonshot AI Kimi K2 Instruct 1T model, 128K context.",
+ },
} as const satisfies Record
diff --git a/packages/types/src/terminal.ts b/packages/types/src/terminal.ts
index 51d6f252a9..ffa1ffe781 100644
--- a/packages/types/src/terminal.ts
+++ b/packages/types/src/terminal.ts
@@ -25,6 +25,10 @@ export const commandExecutionStatusSchema = z.discriminatedUnion("status", [
executionId: z.string(),
status: z.literal("fallback"),
}),
+ z.object({
+ executionId: z.string(),
+ status: z.literal("timeout"),
+ }),
])
export type CommandExecutionStatus = z.infer
diff --git a/src/api/transform/model-params.ts b/src/api/transform/model-params.ts
index 8b6069666c..6ed975ac5a 100644
--- a/src/api/transform/model-params.ts
+++ b/src/api/transform/model-params.ts
@@ -5,6 +5,7 @@ import {
DEFAULT_HYBRID_REASONING_MODEL_THINKING_TOKENS,
shouldUseReasoningBudget,
shouldUseReasoningEffort,
+ getModelMaxOutputTokens,
} from "../../shared/api"
import {
@@ -76,20 +77,25 @@ export function getModelParams({
reasoningEffort: customReasoningEffort,
} = settings
- let maxTokens = model.maxTokens ?? undefined
+ // Use the centralized logic for computing maxTokens
+ const maxTokens = getModelMaxOutputTokens({
+ modelId,
+ model,
+ settings,
+ format,
+ })
+
let temperature = customTemperature ?? defaultTemperature
let reasoningBudget: ModelParams["reasoningBudget"] = undefined
let reasoningEffort: ModelParams["reasoningEffort"] = undefined
if (shouldUseReasoningBudget({ model, settings })) {
- // If `customMaxTokens` is not specified use the default.
- maxTokens = customMaxTokens ?? DEFAULT_HYBRID_REASONING_MODEL_MAX_TOKENS
-
// If `customMaxThinkingTokens` is not specified use the default.
reasoningBudget = customMaxThinkingTokens ?? DEFAULT_HYBRID_REASONING_MODEL_THINKING_TOKENS
// Reasoning cannot exceed 80% of the `maxTokens` value.
- if (reasoningBudget > Math.floor(maxTokens * 0.8)) {
+ // maxTokens should always be defined for reasoning budget models, but add a guard just in case
+ if (maxTokens && reasoningBudget > Math.floor(maxTokens * 0.8)) {
reasoningBudget = Math.floor(maxTokens * 0.8)
}
@@ -106,24 +112,6 @@ export function getModelParams({
reasoningEffort = customReasoningEffort ?? model.reasoningEffort
}
- // TODO: We should consolidate this logic to compute `maxTokens` with
- // `getModelMaxOutputTokens` in order to maintain a single source of truth.
-
- const isAnthropic = format === "anthropic" || (format === "openrouter" && modelId.startsWith("anthropic/"))
-
- // For "Hybrid" reasoning models, we should discard the model's actual
- // `maxTokens` value if we're not using reasoning. We do this for Anthropic
- // models only for now. Should we do this for Gemini too?
- if (model.supportsReasoningBudget && !reasoningBudget && isAnthropic) {
- maxTokens = ANTHROPIC_DEFAULT_MAX_TOKENS
- }
-
- // For Anthropic models we should always make sure a `maxTokens` value is
- // set.
- if (!maxTokens && isAnthropic) {
- maxTokens = ANTHROPIC_DEFAULT_MAX_TOKENS
- }
-
const params: BaseModelParams = { maxTokens, temperature, reasoningEffort, reasoningBudget }
if (format === "anthropic") {
diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts
index c8553a8fc6..aa0590fedd 100644
--- a/src/core/task/Task.ts
+++ b/src/core/task/Task.ts
@@ -41,6 +41,7 @@ import { ClineAskResponse } from "../../shared/WebviewMessage"
import { defaultModeSlug } from "../../shared/modes"
import { DiffStrategy } from "../../shared/tools"
import { EXPERIMENT_IDS, experiments } from "../../shared/experiments"
+import { getModelMaxOutputTokens } from "../../shared/api"
// services
import { UrlContentFetcher } from "../../services/browser/UrlContentFetcher"
@@ -1716,15 +1717,13 @@ export class Task extends EventEmitter {
const { contextTokens } = this.getTokenUsage()
if (contextTokens) {
- // Default max tokens value for thinking models when no specific
- // value is set.
- const DEFAULT_THINKING_MODEL_MAX_TOKENS = 16_384
-
const modelInfo = this.api.getModel().info
- const maxTokens = modelInfo.supportsReasoningBudget
- ? this.apiConfiguration.modelMaxTokens || DEFAULT_THINKING_MODEL_MAX_TOKENS
- : modelInfo.maxTokens
+ const maxTokens = getModelMaxOutputTokens({
+ modelId: this.api.getModel().id,
+ model: modelInfo,
+ settings: this.apiConfiguration,
+ })
const contextWindow = modelInfo.contextWindow
diff --git a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts
new file mode 100644
index 0000000000..de98c9df20
--- /dev/null
+++ b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts
@@ -0,0 +1,189 @@
+// Integration tests for command execution timeout functionality
+// npx vitest run src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts
+
+import * as vscode from "vscode"
+import * as fs from "fs/promises"
+import { executeCommand, ExecuteCommandOptions } from "../executeCommandTool"
+import { Task } from "../../task/Task"
+import { TerminalRegistry } from "../../../integrations/terminal/TerminalRegistry"
+
+// Mock dependencies
+vitest.mock("vscode", () => ({
+ workspace: {
+ getConfiguration: vitest.fn(),
+ },
+}))
+
+vitest.mock("fs/promises")
+vitest.mock("../../../integrations/terminal/TerminalRegistry")
+vitest.mock("../../task/Task")
+
+describe("Command Execution Timeout Integration", () => {
+ let mockTask: any
+ let mockTerminal: any
+ let mockProcess: any
+
+ beforeEach(() => {
+ vitest.clearAllMocks()
+
+ // Mock fs.access to resolve successfully for working directory
+ ;(fs.access as any).mockResolvedValue(undefined)
+
+ // Mock task
+ mockTask = {
+ cwd: "/test/directory",
+ terminalProcess: undefined,
+ providerRef: {
+ deref: vitest.fn().mockResolvedValue({
+ postMessageToWebview: vitest.fn(),
+ }),
+ },
+ say: vitest.fn().mockResolvedValue(undefined),
+ }
+
+ // Mock terminal process
+ mockProcess = {
+ abort: vitest.fn(),
+ then: vitest.fn(),
+ catch: vitest.fn(),
+ }
+
+ // Mock terminal
+ mockTerminal = {
+ runCommand: vitest.fn().mockReturnValue(mockProcess),
+ getCurrentWorkingDirectory: vitest.fn().mockReturnValue("/test/directory"),
+ }
+
+ // Mock TerminalRegistry
+ ;(TerminalRegistry.getOrCreateTerminal as any).mockResolvedValue(mockTerminal)
+
+ // Mock VSCode configuration
+ const mockGetConfiguration = vitest.fn().mockReturnValue({
+ get: vitest.fn().mockReturnValue(0), // Default 0 (no timeout)
+ })
+ ;(vscode.workspace.getConfiguration as any).mockReturnValue(mockGetConfiguration())
+ })
+
+ it("should pass timeout configuration to executeCommand", async () => {
+ const customTimeoutMs = 15000 // 15 seconds in milliseconds
+ const options: ExecuteCommandOptions = {
+ executionId: "test-execution",
+ command: "echo test",
+ commandExecutionTimeout: customTimeoutMs,
+ }
+
+ // Mock a quick-completing process
+ const quickProcess = Promise.resolve()
+ mockTerminal.runCommand.mockReturnValue(quickProcess)
+
+ await executeCommand(mockTask as Task, options)
+
+ // Verify that the terminal was called with the command
+ expect(mockTerminal.runCommand).toHaveBeenCalledWith("echo test", expect.any(Object))
+ })
+
+ it("should handle timeout scenario", async () => {
+ const shortTimeoutMs = 100 // Very short timeout in milliseconds
+ const options: ExecuteCommandOptions = {
+ executionId: "test-execution",
+ command: "sleep 10",
+ commandExecutionTimeout: shortTimeoutMs,
+ }
+
+ // Create a process that never resolves but has an abort method
+ const longRunningProcess = new Promise(() => {
+ // Never resolves to simulate a hanging command
+ })
+
+ // Add abort method to the promise
+ ;(longRunningProcess as any).abort = vitest.fn()
+
+ mockTerminal.runCommand.mockReturnValue(longRunningProcess)
+
+ // Execute with timeout
+ const result = await executeCommand(mockTask as Task, options)
+
+ // Should return timeout error
+ expect(result[0]).toBe(false) // Not rejected by user
+ expect(result[1]).toContain("terminated after exceeding")
+ expect(result[1]).toContain("0.1s") // Should show seconds in error message
+ }, 10000) // Increase test timeout to 10 seconds
+
+ it("should abort process on timeout", async () => {
+ const shortTimeoutMs = 50 // Short timeout in milliseconds
+ const options: ExecuteCommandOptions = {
+ executionId: "test-execution",
+ command: "sleep 10",
+ commandExecutionTimeout: shortTimeoutMs,
+ }
+
+ // Create a process that can be aborted
+ const abortSpy = vitest.fn()
+
+ // Mock the process to never resolve but be abortable
+ const neverResolvingPromise = new Promise(() => {})
+ ;(neverResolvingPromise as any).abort = abortSpy
+
+ mockTerminal.runCommand.mockReturnValue(neverResolvingPromise)
+
+ await executeCommand(mockTask as Task, options)
+
+ // Verify abort was called
+ expect(abortSpy).toHaveBeenCalled()
+ }, 5000) // Increase test timeout to 5 seconds
+
+ it("should clean up timeout on successful completion", async () => {
+ const options: ExecuteCommandOptions = {
+ executionId: "test-execution",
+ command: "echo test",
+ commandExecutionTimeout: 5000,
+ }
+
+ // Mock a process that completes quickly
+ const quickProcess = Promise.resolve()
+ mockTerminal.runCommand.mockReturnValue(quickProcess)
+
+ const result = await executeCommand(mockTask as Task, options)
+
+ // Should complete successfully without timeout
+ expect(result[0]).toBe(false) // Not rejected
+ expect(result[1]).not.toContain("terminated after exceeding")
+ })
+
+ it("should use default timeout when not specified (0 = no timeout)", async () => {
+ const options: ExecuteCommandOptions = {
+ executionId: "test-execution",
+ command: "echo test",
+ // commandExecutionTimeout not specified, should use default (0)
+ }
+
+ const quickProcess = Promise.resolve()
+ mockTerminal.runCommand.mockReturnValue(quickProcess)
+
+ await executeCommand(mockTask as Task, options)
+
+ // Should complete without issues using default (no timeout)
+ expect(mockTerminal.runCommand).toHaveBeenCalled()
+ })
+
+ it("should not timeout when commandExecutionTimeout is 0", async () => {
+ const options: ExecuteCommandOptions = {
+ executionId: "test-execution",
+ command: "sleep 10",
+ commandExecutionTimeout: 0, // No timeout
+ }
+
+ // Create a process that resolves after a delay to simulate a long-running command
+ const longRunningProcess = new Promise((resolve) => {
+ setTimeout(resolve, 200) // 200ms delay
+ })
+
+ mockTerminal.runCommand.mockReturnValue(longRunningProcess)
+
+ const result = await executeCommand(mockTask as Task, options)
+
+ // Should complete successfully without timeout
+ expect(result[0]).toBe(false) // Not rejected
+ expect(result[1]).not.toContain("terminated after exceeding")
+ })
+})
diff --git a/src/core/tools/__tests__/executeCommandTool.spec.ts b/src/core/tools/__tests__/executeCommandTool.spec.ts
index e1bc90a178..dbb1945177 100644
--- a/src/core/tools/__tests__/executeCommandTool.spec.ts
+++ b/src/core/tools/__tests__/executeCommandTool.spec.ts
@@ -1,6 +1,7 @@
// npx vitest run src/core/tools/__tests__/executeCommandTool.spec.ts
import type { ToolUsage } from "@roo-code/types"
+import * as vscode from "vscode"
import { Task } from "../../task/Task"
import { formatResponse } from "../../prompts/responses"
@@ -12,6 +13,12 @@ vitest.mock("execa", () => ({
execa: vitest.fn(),
}))
+vitest.mock("vscode", () => ({
+ workspace: {
+ getConfiguration: vitest.fn(),
+ },
+}))
+
vitest.mock("../../task/Task")
vitest.mock("../../prompts/responses")
@@ -266,4 +273,40 @@ describe("executeCommandTool", () => {
expect(mockExecuteCommand).not.toHaveBeenCalled()
})
})
+
+ describe("Command execution timeout configuration", () => {
+ it("should include timeout parameter in ExecuteCommandOptions", () => {
+ // This test verifies that the timeout configuration is properly typed
+ // The actual timeout logic is tested in integration tests
+ // Note: timeout is stored internally in milliseconds but configured in seconds
+ const timeoutSeconds = 15
+ const options = {
+ executionId: "test-id",
+ command: "echo test",
+ commandExecutionTimeout: timeoutSeconds * 1000, // Convert to milliseconds
+ }
+
+ // Verify the options object has the expected structure
+ expect(options.commandExecutionTimeout).toBe(15000)
+ expect(typeof options.commandExecutionTimeout).toBe("number")
+ })
+
+ it("should handle timeout parameter in function signature", () => {
+ // Test that the executeCommand function accepts timeout parameter
+ // This is a compile-time check that the types are correct
+ const mockOptions = {
+ executionId: "test-id",
+ command: "echo test",
+ customCwd: undefined,
+ terminalShellIntegrationDisabled: false,
+ terminalOutputLineLimit: 500,
+ commandExecutionTimeout: 0,
+ }
+
+ // Verify all required properties exist
+ expect(mockOptions.executionId).toBeDefined()
+ expect(mockOptions.command).toBeDefined()
+ expect(mockOptions.commandExecutionTimeout).toBeDefined()
+ })
+ })
})
diff --git a/src/core/tools/executeCommandTool.ts b/src/core/tools/executeCommandTool.ts
index dbda68332f..407dc283b5 100644
--- a/src/core/tools/executeCommandTool.ts
+++ b/src/core/tools/executeCommandTool.ts
@@ -1,5 +1,6 @@
import fs from "fs/promises"
import * as path from "path"
+import * as vscode from "vscode"
import delay from "delay"
@@ -14,6 +15,8 @@ import { unescapeHtmlEntities } from "../../utils/text-normalization"
import { ExitCodeDetails, RooTerminalCallbacks, RooTerminalProcess } from "../../integrations/terminal/types"
import { TerminalRegistry } from "../../integrations/terminal/TerminalRegistry"
import { Terminal } from "../../integrations/terminal/Terminal"
+import { Package } from "../../shared/package"
+import { t } from "../../i18n"
class ShellIntegrationError extends Error {}
@@ -62,12 +65,21 @@ export async function executeCommandTool(
const clineProviderState = await clineProvider?.getState()
const { terminalOutputLineLimit = 500, terminalShellIntegrationDisabled = false } = clineProviderState ?? {}
+ // Get command execution timeout from VSCode configuration (in seconds)
+ const commandExecutionTimeoutSeconds = vscode.workspace
+ .getConfiguration(Package.name)
+ .get("commandExecutionTimeout", 0)
+
+ // Convert seconds to milliseconds for internal use
+ const commandExecutionTimeout = commandExecutionTimeoutSeconds * 1000
+
const options: ExecuteCommandOptions = {
executionId,
command,
customCwd,
terminalShellIntegrationDisabled,
terminalOutputLineLimit,
+ commandExecutionTimeout,
}
try {
@@ -113,6 +125,7 @@ export type ExecuteCommandOptions = {
customCwd?: string
terminalShellIntegrationDisabled?: boolean
terminalOutputLineLimit?: number
+ commandExecutionTimeout?: number
}
export async function executeCommand(
@@ -123,8 +136,11 @@ export async function executeCommand(
customCwd,
terminalShellIntegrationDisabled = false,
terminalOutputLineLimit = 500,
+ commandExecutionTimeout = 0,
}: ExecuteCommandOptions,
): Promise<[boolean, ToolResponse]> {
+ // Convert milliseconds back to seconds for display purposes
+ const commandExecutionTimeoutSeconds = commandExecutionTimeout / 1000
let workingDir: string
if (!customCwd) {
@@ -211,8 +227,58 @@ export async function executeCommand(
const process = terminal.runCommand(command, callbacks)
cline.terminalProcess = process
- await process
- cline.terminalProcess = undefined
+ // Implement command execution timeout (skip if timeout is 0)
+ if (commandExecutionTimeout > 0) {
+ let timeoutId: NodeJS.Timeout | undefined
+ let isTimedOut = false
+
+ const timeoutPromise = new Promise((_, reject) => {
+ timeoutId = setTimeout(() => {
+ isTimedOut = true
+ // Try to abort the process
+ if (cline.terminalProcess) {
+ cline.terminalProcess.abort()
+ }
+ reject(new Error(`Command execution timed out after ${commandExecutionTimeout}ms`))
+ }, commandExecutionTimeout)
+ })
+
+ try {
+ await Promise.race([process, timeoutPromise])
+ } catch (error) {
+ if (isTimedOut) {
+ // Handle timeout case
+ const status: CommandExecutionStatus = { executionId, status: "timeout" }
+ clineProvider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) })
+
+ // Add visual feedback for timeout
+ await cline.say(
+ "error",
+ t("common:errors:command_timeout", { seconds: commandExecutionTimeoutSeconds }),
+ )
+
+ cline.terminalProcess = undefined
+
+ return [
+ false,
+ `The command was terminated after exceeding a user-configured ${commandExecutionTimeoutSeconds}s timeout. Do not try to re-run the command.`,
+ ]
+ }
+ throw error
+ } finally {
+ if (timeoutId) {
+ clearTimeout(timeoutId)
+ }
+ cline.terminalProcess = undefined
+ }
+ } else {
+ // No timeout - just wait for the process to complete
+ try {
+ await process
+ } finally {
+ cline.terminalProcess = undefined
+ }
+ }
if (shellIntegrationError) {
throw new ShellIntegrationError(shellIntegrationError)
diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts
index 12fd9dd349..8fa9ceccfa 100644
--- a/src/core/webview/ClineProvider.ts
+++ b/src/core/webview/ClineProvider.ts
@@ -1542,6 +1542,10 @@ export class ClineProvider
codebaseIndexEmbedderProvider: codebaseIndexConfig?.codebaseIndexEmbedderProvider ?? "openai",
codebaseIndexEmbedderBaseUrl: codebaseIndexConfig?.codebaseIndexEmbedderBaseUrl ?? "",
codebaseIndexEmbedderModelId: codebaseIndexConfig?.codebaseIndexEmbedderModelId ?? "",
+ codebaseIndexEmbedderModelDimension: codebaseIndexConfig?.codebaseIndexEmbedderModelDimension ?? 1536,
+ codebaseIndexOpenAiCompatibleBaseUrl: codebaseIndexConfig?.codebaseIndexOpenAiCompatibleBaseUrl,
+ codebaseIndexSearchMaxResults: codebaseIndexConfig?.codebaseIndexSearchMaxResults,
+ codebaseIndexSearchMinScore: codebaseIndexConfig?.codebaseIndexSearchMinScore,
},
mdmCompliant: this.checkMdmCompliance(),
profileThresholds: profileThresholds ?? {},
@@ -1703,6 +1707,12 @@ export class ClineProvider
stateValues.codebaseIndexConfig?.codebaseIndexEmbedderProvider ?? "openai",
codebaseIndexEmbedderBaseUrl: stateValues.codebaseIndexConfig?.codebaseIndexEmbedderBaseUrl ?? "",
codebaseIndexEmbedderModelId: stateValues.codebaseIndexConfig?.codebaseIndexEmbedderModelId ?? "",
+ codebaseIndexEmbedderModelDimension:
+ stateValues.codebaseIndexConfig?.codebaseIndexEmbedderModelDimension,
+ codebaseIndexOpenAiCompatibleBaseUrl:
+ stateValues.codebaseIndexConfig?.codebaseIndexOpenAiCompatibleBaseUrl,
+ codebaseIndexSearchMaxResults: stateValues.codebaseIndexConfig?.codebaseIndexSearchMaxResults,
+ codebaseIndexSearchMinScore: stateValues.codebaseIndexConfig?.codebaseIndexSearchMinScore,
},
profileThresholds: stateValues.profileThresholds ?? {},
}
diff --git a/src/i18n/locales/ca/common.json b/src/i18n/locales/ca/common.json
index 0caa3fca47..7dac4d7431 100644
--- a/src/i18n/locales/ca/common.json
+++ b/src/i18n/locales/ca/common.json
@@ -71,6 +71,7 @@
"url_page_not_found": "No s'ha trobat la pàgina. Comprova si la URL és correcta.",
"url_fetch_failed": "Error en obtenir el contingut de la URL: {{error}}",
"url_fetch_error_with_url": "Error en obtenir contingut per {{url}}: {{error}}",
+ "command_timeout": "L'execució de la comanda ha superat el temps d'espera de {{seconds}} segons",
"share_task_failed": "Ha fallat compartir la tasca. Si us plau, torna-ho a provar.",
"share_no_active_task": "No hi ha cap tasca activa per compartir",
"share_auth_required": "Es requereix autenticació. Si us plau, inicia sessió per compartir tasques.",
diff --git a/src/i18n/locales/de/common.json b/src/i18n/locales/de/common.json
index bf9af547ca..db9ba9b51c 100644
--- a/src/i18n/locales/de/common.json
+++ b/src/i18n/locales/de/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "Die Seite wurde nicht gefunden. Bitte prüfe, ob die URL korrekt ist.",
"url_fetch_failed": "Fehler beim Abrufen des URL-Inhalts: {{error}}",
"url_fetch_error_with_url": "Fehler beim Abrufen des Inhalts für {{url}}: {{error}}",
+ "command_timeout": "Zeitüberschreitung bei der Befehlsausführung nach {{seconds}} Sekunden",
"share_task_failed": "Teilen der Aufgabe fehlgeschlagen. Bitte versuche es erneut.",
"share_no_active_task": "Keine aktive Aufgabe zum Teilen",
"share_auth_required": "Authentifizierung erforderlich. Bitte melde dich an, um Aufgaben zu teilen.",
diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json
index 3004038d42..84d3798519 100644
--- a/src/i18n/locales/en/common.json
+++ b/src/i18n/locales/en/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "The page was not found. Please check if the URL is correct.",
"url_fetch_failed": "Failed to fetch URL content: {{error}}",
"url_fetch_error_with_url": "Error fetching content for {{url}}: {{error}}",
+ "command_timeout": "Command execution timed out after {{seconds}} seconds",
"share_task_failed": "Failed to share task. Please try again.",
"share_no_active_task": "No active task to share",
"share_auth_required": "Authentication required. Please sign in to share tasks.",
diff --git a/src/i18n/locales/es/common.json b/src/i18n/locales/es/common.json
index 1a16dbf1ae..cdd26831a5 100644
--- a/src/i18n/locales/es/common.json
+++ b/src/i18n/locales/es/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "La página no fue encontrada. Por favor verifica si la URL es correcta.",
"url_fetch_failed": "Error al obtener el contenido de la URL: {{error}}",
"url_fetch_error_with_url": "Error al obtener contenido para {{url}}: {{error}}",
+ "command_timeout": "La ejecución del comando superó el tiempo de espera de {{seconds}} segundos",
"share_task_failed": "Error al compartir la tarea. Por favor, inténtalo de nuevo.",
"share_no_active_task": "No hay tarea activa para compartir",
"share_auth_required": "Se requiere autenticación. Por favor, inicia sesión para compartir tareas.",
diff --git a/src/i18n/locales/fr/common.json b/src/i18n/locales/fr/common.json
index 98945f305d..3ddacdda59 100644
--- a/src/i18n/locales/fr/common.json
+++ b/src/i18n/locales/fr/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "La page n'a pas été trouvée. Vérifie si l'URL est correcte.",
"url_fetch_failed": "Échec de récupération du contenu de l'URL : {{error}}",
"url_fetch_error_with_url": "Erreur lors de la récupération du contenu pour {{url}} : {{error}}",
+ "command_timeout": "L'exécution de la commande a expiré après {{seconds}} secondes",
"share_task_failed": "Échec du partage de la tâche. Veuillez réessayer.",
"share_no_active_task": "Aucune tâche active à partager",
"share_auth_required": "Authentification requise. Veuillez vous connecter pour partager des tâches.",
diff --git a/src/i18n/locales/hi/common.json b/src/i18n/locales/hi/common.json
index 7daa0046ec..8637426846 100644
--- a/src/i18n/locales/hi/common.json
+++ b/src/i18n/locales/hi/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "पेज नहीं मिला। कृपया जांचें कि URL सही है।",
"url_fetch_failed": "URL सामग्री प्राप्त करने में त्रुटि: {{error}}",
"url_fetch_error_with_url": "{{url}} के लिए सामग्री प्राप्त करने में त्रुटि: {{error}}",
+ "command_timeout": "कमांड निष्पादन {{seconds}} सेकंड के बाद समय समाप्त हो गया",
"share_task_failed": "कार्य साझा करने में विफल। कृपया पुनः प्रयास करें।",
"share_no_active_task": "साझा करने के लिए कोई सक्रिय कार्य नहीं",
"share_auth_required": "प्रमाणीकरण आवश्यक है। कार्य साझा करने के लिए कृपया साइन इन करें।",
diff --git a/src/i18n/locales/id/common.json b/src/i18n/locales/id/common.json
index c021dab4cd..df3fe2cefb 100644
--- a/src/i18n/locales/id/common.json
+++ b/src/i18n/locales/id/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "Halaman tidak ditemukan. Silakan periksa apakah URL sudah benar.",
"url_fetch_failed": "Gagal mengambil konten URL: {{error}}",
"url_fetch_error_with_url": "Error mengambil konten untuk {{url}}: {{error}}",
+ "command_timeout": "Eksekusi perintah waktu habis setelah {{seconds}} detik",
"share_task_failed": "Gagal membagikan tugas. Silakan coba lagi.",
"share_no_active_task": "Tidak ada tugas aktif untuk dibagikan",
"share_auth_required": "Autentikasi diperlukan. Silakan masuk untuk berbagi tugas.",
diff --git a/src/i18n/locales/it/common.json b/src/i18n/locales/it/common.json
index ff45cd8f1e..d12e376c0c 100644
--- a/src/i18n/locales/it/common.json
+++ b/src/i18n/locales/it/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "La pagina non è stata trovata. Verifica se l'URL è corretto.",
"url_fetch_failed": "Errore nel recupero del contenuto URL: {{error}}",
"url_fetch_error_with_url": "Errore nel recupero del contenuto per {{url}}: {{error}}",
+ "command_timeout": "Esecuzione del comando scaduta dopo {{seconds}} secondi",
"share_task_failed": "Condivisione dell'attività fallita. Riprova.",
"share_no_active_task": "Nessuna attività attiva da condividere",
"share_auth_required": "Autenticazione richiesta. Accedi per condividere le attività.",
diff --git a/src/i18n/locales/ja/common.json b/src/i18n/locales/ja/common.json
index 4d9b88d114..56be64c44c 100644
--- a/src/i18n/locales/ja/common.json
+++ b/src/i18n/locales/ja/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "ページが見つかりませんでした。URLが正しいか確認してください。",
"url_fetch_failed": "URLコンテンツの取得に失敗しました:{{error}}",
"url_fetch_error_with_url": "{{url}} のコンテンツ取得エラー:{{error}}",
+ "command_timeout": "コマンドの実行が{{seconds}}秒後にタイムアウトしました",
"share_task_failed": "タスクの共有に失敗しました",
"share_no_active_task": "共有するアクティブなタスクがありません",
"share_auth_required": "認証が必要です。タスクを共有するにはサインインしてください。",
diff --git a/src/i18n/locales/ko/common.json b/src/i18n/locales/ko/common.json
index 34d9bced71..0b12455c0f 100644
--- a/src/i18n/locales/ko/common.json
+++ b/src/i18n/locales/ko/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "페이지를 찾을 수 없습니다. URL이 올바른지 확인해 주세요.",
"url_fetch_failed": "URL 콘텐츠 가져오기 실패: {{error}}",
"url_fetch_error_with_url": "{{url}} 콘텐츠 가져오기 오류: {{error}}",
+ "command_timeout": "명령 실행 시간이 {{seconds}}초 후 초과되었습니다",
"share_task_failed": "작업 공유에 실패했습니다",
"share_no_active_task": "공유할 활성 작업이 없습니다",
"share_auth_required": "인증이 필요합니다. 작업을 공유하려면 로그인하세요.",
diff --git a/src/i18n/locales/nl/common.json b/src/i18n/locales/nl/common.json
index dff1bb83f7..43fda70dc2 100644
--- a/src/i18n/locales/nl/common.json
+++ b/src/i18n/locales/nl/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "De pagina werd niet gevonden. Controleer of de URL correct is.",
"url_fetch_failed": "Fout bij ophalen van URL-inhoud: {{error}}",
"url_fetch_error_with_url": "Fout bij ophalen van inhoud voor {{url}}: {{error}}",
+ "command_timeout": "Time-out bij uitvoeren van commando na {{seconds}} seconden",
"share_task_failed": "Delen van taak mislukt",
"share_no_active_task": "Geen actieve taak om te delen",
"share_auth_required": "Authenticatie vereist. Log in om taken te delen.",
diff --git a/src/i18n/locales/pl/common.json b/src/i18n/locales/pl/common.json
index 33c58b4752..80a299c7df 100644
--- a/src/i18n/locales/pl/common.json
+++ b/src/i18n/locales/pl/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "Strona nie została znaleziona. Sprawdź, czy URL jest poprawny.",
"url_fetch_failed": "Błąd pobierania zawartości URL: {{error}}",
"url_fetch_error_with_url": "Błąd pobierania zawartości dla {{url}}: {{error}}",
+ "command_timeout": "Przekroczono limit czasu wykonania polecenia po {{seconds}} sekundach",
"share_task_failed": "Nie udało się udostępnić zadania",
"share_no_active_task": "Brak aktywnego zadania do udostępnienia",
"share_auth_required": "Wymagana autoryzacja. Zaloguj się, aby udostępniać zadania.",
diff --git a/src/i18n/locales/pt-BR/common.json b/src/i18n/locales/pt-BR/common.json
index ce9dc113e2..6205a5fb7a 100644
--- a/src/i18n/locales/pt-BR/common.json
+++ b/src/i18n/locales/pt-BR/common.json
@@ -71,6 +71,7 @@
"url_page_not_found": "A página não foi encontrada. Verifique se a URL está correta.",
"url_fetch_failed": "Falha ao buscar conteúdo da URL: {{error}}",
"url_fetch_error_with_url": "Erro ao buscar conteúdo para {{url}}: {{error}}",
+ "command_timeout": "A execução do comando excedeu o tempo limite após {{seconds}} segundos",
"share_task_failed": "Falha ao compartilhar tarefa",
"share_no_active_task": "Nenhuma tarefa ativa para compartilhar",
"share_auth_required": "Autenticação necessária. Faça login para compartilhar tarefas.",
diff --git a/src/i18n/locales/ru/common.json b/src/i18n/locales/ru/common.json
index a3b6c322b2..f537d1a2d3 100644
--- a/src/i18n/locales/ru/common.json
+++ b/src/i18n/locales/ru/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "Страница не найдена. Проверь правильность URL.",
"url_fetch_failed": "Ошибка получения содержимого URL: {{error}}",
"url_fetch_error_with_url": "Ошибка получения содержимого для {{url}}: {{error}}",
+ "command_timeout": "Время выполнения команды истекло через {{seconds}} секунд",
"share_task_failed": "Не удалось поделиться задачей",
"share_no_active_task": "Нет активной задачи для совместного использования",
"share_auth_required": "Требуется аутентификация. Войдите в систему для совместного доступа к задачам.",
diff --git a/src/i18n/locales/tr/common.json b/src/i18n/locales/tr/common.json
index 042fa88d15..61e244186e 100644
--- a/src/i18n/locales/tr/common.json
+++ b/src/i18n/locales/tr/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "Sayfa bulunamadı. URL'nin doğru olup olmadığını kontrol et.",
"url_fetch_failed": "URL içeriği getirme hatası: {{error}}",
"url_fetch_error_with_url": "{{url}} için içerik getirme hatası: {{error}}",
+ "command_timeout": "Komut çalıştırma {{seconds}} saniye sonra zaman aşımına uğradı",
"share_task_failed": "Görev paylaşılamadı",
"share_no_active_task": "Paylaşılacak aktif görev yok",
"share_auth_required": "Kimlik doğrulama gerekli. Görevleri paylaşmak için lütfen giriş yapın.",
diff --git a/src/i18n/locales/vi/common.json b/src/i18n/locales/vi/common.json
index 183ae7b41a..6106f71fa0 100644
--- a/src/i18n/locales/vi/common.json
+++ b/src/i18n/locales/vi/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "Không tìm thấy trang. Vui lòng kiểm tra URL có đúng không.",
"url_fetch_failed": "Lỗi lấy nội dung URL: {{error}}",
"url_fetch_error_with_url": "Lỗi lấy nội dung cho {{url}}: {{error}}",
+ "command_timeout": "Thực thi lệnh đã hết thời gian chờ sau {{seconds}} giây",
"share_task_failed": "Không thể chia sẻ nhiệm vụ",
"share_no_active_task": "Không có nhiệm vụ hoạt động để chia sẻ",
"share_auth_required": "Cần xác thực. Vui lòng đăng nhập để chia sẻ nhiệm vụ.",
diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json
index a45efa4b1c..a629ba6507 100644
--- a/src/i18n/locales/zh-CN/common.json
+++ b/src/i18n/locales/zh-CN/common.json
@@ -72,6 +72,7 @@
"url_page_not_found": "页面未找到。请检查 URL 是否正确。",
"url_fetch_failed": "获取 URL 内容失败:{{error}}",
"url_fetch_error_with_url": "获取 {{url}} 内容时出错:{{error}}",
+ "command_timeout": "命令执行超时,{{seconds}} 秒后",
"share_task_failed": "分享任务失败。请重试。",
"share_no_active_task": "没有活跃任务可分享",
"share_auth_required": "需要身份验证。请登录以分享任务。",
diff --git a/src/i18n/locales/zh-TW/common.json b/src/i18n/locales/zh-TW/common.json
index 3fbbc050f4..48a37c1438 100644
--- a/src/i18n/locales/zh-TW/common.json
+++ b/src/i18n/locales/zh-TW/common.json
@@ -67,6 +67,7 @@
"url_page_not_found": "找不到頁面。請檢查 URL 是否正確。",
"url_fetch_failed": "取得 URL 內容失敗:{{error}}",
"url_fetch_error_with_url": "取得 {{url}} 內容時發生錯誤:{{error}}",
+ "command_timeout": "命令執行超時,{{seconds}} 秒後",
"share_task_failed": "分享工作失敗。請重試。",
"share_no_active_task": "沒有活躍的工作可分享",
"share_auth_required": "需要身份驗證。請登入以分享工作。",
diff --git a/src/integrations/claude-code/__tests__/run.spec.ts b/src/integrations/claude-code/__tests__/run.spec.ts
index d2fda08fc0..27af274447 100644
--- a/src/integrations/claude-code/__tests__/run.spec.ts
+++ b/src/integrations/claude-code/__tests__/run.spec.ts
@@ -1,4 +1,9 @@
-import { describe, test, expect, vi, beforeEach } from "vitest"
+import { describe, test, expect, vi, beforeEach, afterEach } from "vitest"
+
+// Mock os module
+vi.mock("os", () => ({
+ platform: vi.fn(() => "darwin"), // Default to non-Windows
+}))
// Mock vscode workspace
vi.mock("vscode", () => ({
@@ -118,56 +123,53 @@ describe("runClaudeCode", () => {
expect(typeof result[Symbol.asyncIterator]).toBe("function")
})
- test("should use stdin instead of command line arguments for messages", async () => {
+ test("should handle platform-specific stdin behavior", async () => {
const { runClaudeCode } = await import("../run")
const messages = [{ role: "user" as const, content: "Hello world!" }]
+ const systemPrompt = "You are a helpful assistant"
const options = {
- systemPrompt: "You are a helpful assistant",
+ systemPrompt,
messages,
}
- const generator = runClaudeCode(options)
+ // Test on Windows
+ const os = await import("os")
+ vi.mocked(os.platform).mockReturnValue("win32")
- // Consume the generator to completion
+ const generator = runClaudeCode(options)
const results = []
for await (const chunk of generator) {
results.push(chunk)
}
- // Verify execa was called with correct arguments (no JSON.stringify(messages) in args)
- expect(mockExeca).toHaveBeenCalledWith(
- "claude",
- expect.arrayContaining([
- "-p",
- "--system-prompt",
- "You are a helpful assistant",
- "--verbose",
- "--output-format",
- "stream-json",
- "--disallowedTools",
- expect.any(String),
- "--max-turns",
- "1",
- ]),
- expect.objectContaining({
- stdin: "pipe",
- stdout: "pipe",
- stderr: "pipe",
- }),
- )
-
- // Verify the arguments do NOT contain the stringified messages
+ // On Windows, should NOT have --system-prompt in args
const [, args] = mockExeca.mock.calls[0]
- expect(args).not.toContain(JSON.stringify(messages))
+ expect(args).not.toContain("--system-prompt")
- // Verify messages were written to stdin with callback
+ // Should pass both system prompt and messages via stdin
+ const expectedStdinData = JSON.stringify({ systemPrompt, messages })
+ expect(mockStdin.write).toHaveBeenCalledWith(expectedStdinData, "utf8", expect.any(Function))
+
+ // Reset mocks for non-Windows test
+ vi.clearAllMocks()
+ mockExeca.mockReturnValue(createMockProcess())
+
+ // Test on non-Windows
+ vi.mocked(os.platform).mockReturnValue("darwin")
+
+ const generator2 = runClaudeCode(options)
+ const results2 = []
+ for await (const chunk of generator2) {
+ results2.push(chunk)
+ }
+
+ // On non-Windows, should have --system-prompt in args
+ const [, args2] = mockExeca.mock.calls[0]
+ expect(args2).toContain("--system-prompt")
+ expect(args2).toContain(systemPrompt)
+
+ // Should only pass messages via stdin
expect(mockStdin.write).toHaveBeenCalledWith(JSON.stringify(messages), "utf8", expect.any(Function))
- expect(mockStdin.end).toHaveBeenCalled()
-
- // Verify we got the expected mock output
- expect(results).toHaveLength(2)
- expect(results[0]).toEqual({ type: "text", text: "Hello" })
- expect(results[1]).toEqual({ type: "text", text: " world" })
})
test("should include model parameter when provided", async () => {
diff --git a/src/integrations/claude-code/run.ts b/src/integrations/claude-code/run.ts
index 59a5bf701a..65e32bd96f 100644
--- a/src/integrations/claude-code/run.ts
+++ b/src/integrations/claude-code/run.ts
@@ -4,6 +4,7 @@ import { execa } from "execa"
import { ClaudeCodeMessage } from "./types"
import readline from "readline"
import { CLAUDE_CODE_DEFAULT_MAX_OUTPUT_TOKENS } from "@roo-code/types"
+import * as os from "os"
const cwd = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0)
@@ -118,11 +119,17 @@ function runProcess({
maxOutputTokens,
}: ClaudeCodeOptions & { maxOutputTokens?: number }) {
const claudePath = path || "claude"
+ const isWindows = os.platform() === "win32"
- const args = [
- "-p",
- "--system-prompt",
- systemPrompt,
+ // Build args based on platform
+ const args = ["-p"]
+
+ // Pass system prompt as flag on non-Windows, via stdin on Windows (avoids cmd length limits)
+ if (!isWindows) {
+ args.push("--system-prompt", systemPrompt)
+ }
+
+ args.push(
"--verbose",
"--output-format",
"stream-json",
@@ -131,7 +138,7 @@ function runProcess({
// Roo Code will handle recursive calls
"--max-turns",
"1",
- ]
+ )
if (modelId) {
args.push("--model", modelId)
@@ -154,16 +161,22 @@ function runProcess({
timeout: CLAUDE_CODE_TIMEOUT,
})
- // Write messages to stdin after process is spawned
- // This avoids the E2BIG error on Linux when passing large messages as command line arguments
- // Linux has a per-argument limit of ~128KiB for execve() system calls
- const messagesJson = JSON.stringify(messages)
+ // Prepare stdin data: Windows gets both system prompt & messages (avoids 8191 char limit),
+ // other platforms get messages only (avoids Linux E2BIG error from ~128KiB execve limit)
+ let stdinData: string
+ if (isWindows) {
+ stdinData = JSON.stringify({
+ systemPrompt,
+ messages,
+ })
+ } else {
+ stdinData = JSON.stringify(messages)
+ }
- // Use setImmediate to ensure the process has been spawned before writing to stdin
- // This prevents potential race conditions where stdin might not be ready
+ // Use setImmediate to ensure process is spawned before writing (prevents stdin race conditions)
setImmediate(() => {
try {
- child.stdin.write(messagesJson, "utf8", (error) => {
+ child.stdin.write(stdinData, "utf8", (error: Error | null | undefined) => {
if (error) {
console.error("Error writing to Claude Code stdin:", error)
child.kill()
diff --git a/src/package.json b/src/package.json
index e2122a1cdd..7b3c6a26cc 100644
--- a/src/package.json
+++ b/src/package.json
@@ -3,7 +3,7 @@
"displayName": "%extension.displayName%",
"description": "%extension.description%",
"publisher": "RooVeterinaryInc",
- "version": "3.23.8",
+ "version": "3.23.12",
"icon": "assets/icons/icon.png",
"galleryBanner": {
"color": "#617A91",
@@ -338,6 +338,13 @@
"default": [],
"description": "%commands.deniedCommands.description%"
},
+ "roo-cline.commandExecutionTimeout": {
+ "type": "number",
+ "default": 0,
+ "minimum": 0,
+ "maximum": 600,
+ "description": "%commands.commandExecutionTimeout.description%"
+ },
"roo-cline.vsCodeLmModelSelector": {
"type": "object",
"properties": {
diff --git a/src/package.nls.ca.json b/src/package.nls.ca.json
index 0d82f931c4..339e635f0d 100644
--- a/src/package.nls.ca.json
+++ b/src/package.nls.ca.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "Ordres que es poden executar automàticament quan 'Aprova sempre les operacions d'execució' està activat",
"commands.deniedCommands.description": "Prefixos d'ordres que seran automàticament denegats sense demanar aprovació. En cas de conflictes amb ordres permeses, la coincidència de prefix més llarga té prioritat. Afegeix * per denegar totes les ordres.",
+ "commands.commandExecutionTimeout.description": "Temps màxim en segons per esperar que l'execució de l'ordre es completi abans d'esgotar el temps (0 = sense temps límit, 1-600s, per defecte: 0s)",
"settings.vsCodeLmModelSelector.description": "Configuració per a l'API del model de llenguatge VSCode",
"settings.vsCodeLmModelSelector.vendor.description": "El proveïdor del model de llenguatge (p. ex. copilot)",
"settings.vsCodeLmModelSelector.family.description": "La família del model de llenguatge (p. ex. gpt-4)",
diff --git a/src/package.nls.de.json b/src/package.nls.de.json
index 2a04ed5398..5a6fe65b11 100644
--- a/src/package.nls.de.json
+++ b/src/package.nls.de.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "Befehle, die automatisch ausgeführt werden können, wenn 'Ausführungsoperationen immer genehmigen' aktiviert ist",
"commands.deniedCommands.description": "Befehlspräfixe, die automatisch abgelehnt werden, ohne nach Genehmigung zu fragen. Bei Konflikten mit erlaubten Befehlen hat die längste Präfix-Übereinstimmung Vorrang. Füge * hinzu, um alle Befehle abzulehnen.",
+ "commands.commandExecutionTimeout.description": "Maximale Zeit in Sekunden, die auf den Abschluss der Befehlsausführung gewartet wird, bevor ein Timeout auftritt (0 = kein Timeout, 1-600s, Standard: 0s)",
"settings.vsCodeLmModelSelector.description": "Einstellungen für die VSCode-Sprachmodell-API",
"settings.vsCodeLmModelSelector.vendor.description": "Der Anbieter des Sprachmodells (z.B. copilot)",
"settings.vsCodeLmModelSelector.family.description": "Die Familie des Sprachmodells (z.B. gpt-4)",
diff --git a/src/package.nls.es.json b/src/package.nls.es.json
index 1966c4aecb..3e480550d8 100644
--- a/src/package.nls.es.json
+++ b/src/package.nls.es.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "Comandos que pueden ejecutarse automáticamente cuando 'Aprobar siempre operaciones de ejecución' está activado",
"commands.deniedCommands.description": "Prefijos de comandos que serán automáticamente denegados sin solicitar aprobación. En caso de conflictos con comandos permitidos, la coincidencia de prefijo más larga tiene prioridad. Añade * para denegar todos los comandos.",
+ "commands.commandExecutionTimeout.description": "Tiempo máximo en segundos para esperar que se complete la ejecución del comando antes de que expire (0 = sin tiempo límite, 1-600s, predeterminado: 0s)",
"settings.vsCodeLmModelSelector.description": "Configuración para la API del modelo de lenguaje VSCode",
"settings.vsCodeLmModelSelector.vendor.description": "El proveedor del modelo de lenguaje (ej. copilot)",
"settings.vsCodeLmModelSelector.family.description": "La familia del modelo de lenguaje (ej. gpt-4)",
diff --git a/src/package.nls.fr.json b/src/package.nls.fr.json
index 293c87351b..9e8fb83cc3 100644
--- a/src/package.nls.fr.json
+++ b/src/package.nls.fr.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "Commandes pouvant être exécutées automatiquement lorsque 'Toujours approuver les opérations d'exécution' est activé",
"commands.deniedCommands.description": "Préfixes de commandes qui seront automatiquement refusés sans demander d'approbation. En cas de conflit avec les commandes autorisées, la correspondance de préfixe la plus longue a la priorité. Ajouter * pour refuser toutes les commandes.",
+ "commands.commandExecutionTimeout.description": "Temps maximum en secondes pour attendre que l'exécution de la commande se termine avant expiration (0 = pas de délai, 1-600s, défaut : 0s)",
"settings.vsCodeLmModelSelector.description": "Paramètres pour l'API du modèle de langage VSCode",
"settings.vsCodeLmModelSelector.vendor.description": "Le fournisseur du modèle de langage (ex: copilot)",
"settings.vsCodeLmModelSelector.family.description": "La famille du modèle de langage (ex: gpt-4)",
diff --git a/src/package.nls.hi.json b/src/package.nls.hi.json
index 471cbe464e..88bc845969 100644
--- a/src/package.nls.hi.json
+++ b/src/package.nls.hi.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "वे कमांड जो स्वचालित रूप से निष्पादित की जा सकती हैं जब 'हमेशा निष्पादन संचालन को स्वीकृत करें' सक्रिय हो",
"commands.deniedCommands.description": "कमांड प्रीफिक्स जो स्वचालित रूप से अस्वीकार कर दिए जाएंगे बिना अनुमोदन मांगे। अनुमतित कमांड के साथ संघर्ष की स्थिति में, सबसे लंबा प्रीफिक्स मैच प्राथमिकता लेता है। सभी कमांड को अस्वीकार करने के लिए * जोड़ें।",
+ "commands.commandExecutionTimeout.description": "कमांड निष्पादन पूरा होने का इंतजार करने के लिए अधिकतम समय सेकंड में, समय समाप्त होने से पहले (0 = कोई समय सीमा नहीं, 1-600s, डिफ़ॉल्ट: 0s)",
"settings.vsCodeLmModelSelector.description": "VSCode भाषा मॉडल API के लिए सेटिंग्स",
"settings.vsCodeLmModelSelector.vendor.description": "भाषा मॉडल का विक्रेता (उदा. copilot)",
"settings.vsCodeLmModelSelector.family.description": "भाषा मॉडल का परिवार (उदा. gpt-4)",
diff --git a/src/package.nls.id.json b/src/package.nls.id.json
index d2cc5737c8..1a2e038547 100644
--- a/src/package.nls.id.json
+++ b/src/package.nls.id.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "Perintah yang dapat dijalankan secara otomatis ketika 'Selalu setujui operasi eksekusi' diaktifkan",
"commands.deniedCommands.description": "Awalan perintah yang akan otomatis ditolak tanpa meminta persetujuan. Jika terjadi konflik dengan perintah yang diizinkan, pencocokan awalan terpanjang akan diprioritaskan. Tambahkan * untuk menolak semua perintah.",
+ "commands.commandExecutionTimeout.description": "Waktu maksimum dalam detik untuk menunggu eksekusi perintah selesai sebelum timeout (0 = tanpa timeout, 1-600s, default: 0s)",
"settings.vsCodeLmModelSelector.description": "Pengaturan untuk API Model Bahasa VSCode",
"settings.vsCodeLmModelSelector.vendor.description": "Vendor dari model bahasa (misalnya copilot)",
"settings.vsCodeLmModelSelector.family.description": "Keluarga dari model bahasa (misalnya gpt-4)",
diff --git a/src/package.nls.it.json b/src/package.nls.it.json
index c790c27a88..4d5ac4895d 100644
--- a/src/package.nls.it.json
+++ b/src/package.nls.it.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "Comandi che possono essere eseguiti automaticamente quando 'Approva sempre le operazioni di esecuzione' è attivato",
"commands.deniedCommands.description": "Prefissi di comandi che verranno automaticamente rifiutati senza richiedere approvazione. In caso di conflitti con comandi consentiti, la corrispondenza del prefisso più lungo ha la precedenza. Aggiungi * per rifiutare tutti i comandi.",
+ "commands.commandExecutionTimeout.description": "Tempo massimo in secondi per attendere il completamento dell'esecuzione del comando prima del timeout (0 = nessun timeout, 1-600s, predefinito: 0s)",
"settings.vsCodeLmModelSelector.description": "Impostazioni per l'API del modello linguistico VSCode",
"settings.vsCodeLmModelSelector.vendor.description": "Il fornitore del modello linguistico (es. copilot)",
"settings.vsCodeLmModelSelector.family.description": "La famiglia del modello linguistico (es. gpt-4)",
diff --git a/src/package.nls.ja.json b/src/package.nls.ja.json
index eec17d344c..dcbc01d164 100644
--- a/src/package.nls.ja.json
+++ b/src/package.nls.ja.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "'常に実行操作を承認する'が有効な場合に自動実行できるコマンド",
"commands.deniedCommands.description": "承認を求めずに自動的に拒否されるコマンドプレフィックス。許可されたコマンドとの競合がある場合、最長プレフィックスマッチが優先されます。すべてのコマンドを拒否するには * を追加してください。",
+ "commands.commandExecutionTimeout.description": "コマンド実行の完了を待つ最大時間(秒)、タイムアウトまで(0 = タイムアウトなし、1-600秒、デフォルト: 0秒)",
"settings.vsCodeLmModelSelector.description": "VSCode 言語モデル API の設定",
"settings.vsCodeLmModelSelector.vendor.description": "言語モデルのベンダー(例:copilot)",
"settings.vsCodeLmModelSelector.family.description": "言語モデルのファミリー(例:gpt-4)",
diff --git a/src/package.nls.json b/src/package.nls.json
index 2c8908fadb..c5225c45c8 100644
--- a/src/package.nls.json
+++ b/src/package.nls.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "Commands that can be auto-executed when 'Always approve execute operations' is enabled",
"commands.deniedCommands.description": "Command prefixes that will be automatically denied without asking for approval. In case of conflicts with allowed commands, the longest prefix match takes precedence. Add * to deny all commands.",
+ "commands.commandExecutionTimeout.description": "Maximum time in seconds to wait for command execution to complete before timing out (0 = no timeout, 1-600s, default: 0s)",
"settings.vsCodeLmModelSelector.description": "Settings for VSCode Language Model API",
"settings.vsCodeLmModelSelector.vendor.description": "The vendor of the language model (e.g. copilot)",
"settings.vsCodeLmModelSelector.family.description": "The family of the language model (e.g. gpt-4)",
diff --git a/src/package.nls.ko.json b/src/package.nls.ko.json
index 833ef26875..6cb839e793 100644
--- a/src/package.nls.ko.json
+++ b/src/package.nls.ko.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "'항상 실행 작업 승인' 이 활성화되어 있을 때 자동으로 실행할 수 있는 명령어",
"commands.deniedCommands.description": "승인을 요청하지 않고 자동으로 거부될 명령어 접두사. 허용된 명령어와 충돌하는 경우 가장 긴 접두사 일치가 우선됩니다. 모든 명령어를 거부하려면 *를 추가하세요.",
+ "commands.commandExecutionTimeout.description": "명령어 실행이 완료되기를 기다리는 최대 시간(초), 타임아웃 전까지 (0 = 타임아웃 없음, 1-600초, 기본값: 0초)",
"settings.vsCodeLmModelSelector.description": "VSCode 언어 모델 API 설정",
"settings.vsCodeLmModelSelector.vendor.description": "언어 모델 공급자 (예: copilot)",
"settings.vsCodeLmModelSelector.family.description": "언어 모델 계열 (예: gpt-4)",
diff --git a/src/package.nls.nl.json b/src/package.nls.nl.json
index bf74a5d2c6..51b23ec1a6 100644
--- a/src/package.nls.nl.json
+++ b/src/package.nls.nl.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "Commando's die automatisch kunnen worden uitgevoerd wanneer 'Altijd goedkeuren uitvoerbewerkingen' is ingeschakeld",
"commands.deniedCommands.description": "Commando-prefixen die automatisch worden geweigerd zonder om goedkeuring te vragen. Bij conflicten met toegestane commando's heeft de langste prefix-match voorrang. Voeg * toe om alle commando's te weigeren.",
+ "commands.commandExecutionTimeout.description": "Maximale tijd in seconden om te wachten tot commando-uitvoering voltooid is voordat er een timeout optreedt (0 = geen timeout, 1-600s, standaard: 0s)",
"settings.vsCodeLmModelSelector.description": "Instellingen voor VSCode Language Model API",
"settings.vsCodeLmModelSelector.vendor.description": "De leverancier van het taalmodel (bijv. copilot)",
"settings.vsCodeLmModelSelector.family.description": "De familie van het taalmodel (bijv. gpt-4)",
diff --git a/src/package.nls.pl.json b/src/package.nls.pl.json
index de55dd1f21..62daaae24b 100644
--- a/src/package.nls.pl.json
+++ b/src/package.nls.pl.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "Polecenia, które mogą być wykonywane automatycznie, gdy włączona jest opcja 'Zawsze zatwierdzaj operacje wykonania'",
"commands.deniedCommands.description": "Prefiksy poleceń, które będą automatycznie odrzucane bez pytania o zatwierdzenie. W przypadku konfliktów z dozwolonymi poleceniami, najdłuższe dopasowanie prefiksu ma pierwszeństwo. Dodaj * aby odrzucić wszystkie polecenia.",
+ "commands.commandExecutionTimeout.description": "Maksymalny czas w sekundach oczekiwania na zakończenie wykonania polecenia przed przekroczeniem limitu czasu (0 = brak limitu czasu, 1-600s, domyślnie: 0s)",
"settings.vsCodeLmModelSelector.description": "Ustawienia dla API modelu językowego VSCode",
"settings.vsCodeLmModelSelector.vendor.description": "Dostawca modelu językowego (np. copilot)",
"settings.vsCodeLmModelSelector.family.description": "Rodzina modelu językowego (np. gpt-4)",
diff --git a/src/package.nls.pt-BR.json b/src/package.nls.pt-BR.json
index 385e1d88ab..7f3f7aece3 100644
--- a/src/package.nls.pt-BR.json
+++ b/src/package.nls.pt-BR.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "Comandos que podem ser executados automaticamente quando 'Sempre aprovar operações de execução' está ativado",
"commands.deniedCommands.description": "Prefixos de comandos que serão automaticamente negados sem solicitar aprovação. Em caso de conflitos com comandos permitidos, a correspondência de prefixo mais longa tem precedência. Adicione * para negar todos os comandos.",
+ "commands.commandExecutionTimeout.description": "Tempo máximo em segundos para aguardar a conclusão da execução do comando antes do timeout (0 = sem timeout, 1-600s, padrão: 0s)",
"settings.vsCodeLmModelSelector.description": "Configurações para a API do modelo de linguagem do VSCode",
"settings.vsCodeLmModelSelector.vendor.description": "O fornecedor do modelo de linguagem (ex: copilot)",
"settings.vsCodeLmModelSelector.family.description": "A família do modelo de linguagem (ex: gpt-4)",
diff --git a/src/package.nls.ru.json b/src/package.nls.ru.json
index 7367eb4672..c1872a759e 100644
--- a/src/package.nls.ru.json
+++ b/src/package.nls.ru.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "Команды, которые могут быть автоматически выполнены, когда включена опция 'Всегда подтверждать операции выполнения'",
"commands.deniedCommands.description": "Префиксы команд, которые будут автоматически отклонены без запроса подтверждения. В случае конфликтов с разрешенными командами приоритет имеет самое длинное совпадение префикса. Добавьте * чтобы отклонить все команды.",
+ "commands.commandExecutionTimeout.description": "Максимальное время в секундах для ожидания завершения выполнения команды до истечения времени ожидания (0 = без тайм-аута, 1-600с, по умолчанию: 0с)",
"settings.vsCodeLmModelSelector.description": "Настройки для VSCode Language Model API",
"settings.vsCodeLmModelSelector.vendor.description": "Поставщик языковой модели (например, copilot)",
"settings.vsCodeLmModelSelector.family.description": "Семейство языковой модели (например, gpt-4)",
diff --git a/src/package.nls.tr.json b/src/package.nls.tr.json
index d9c040c9ff..589ce61912 100644
--- a/src/package.nls.tr.json
+++ b/src/package.nls.tr.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "'Her zaman yürütme işlemlerini onayla' etkinleştirildiğinde otomatik olarak yürütülebilen komutlar",
"commands.deniedCommands.description": "Onay istenmeden otomatik olarak reddedilecek komut önekleri. İzin verilen komutlarla çakışma durumunda en uzun önek eşleşmesi öncelik alır. Tüm komutları reddetmek için * ekleyin.",
+ "commands.commandExecutionTimeout.description": "Komut yürütmesinin tamamlanmasını beklemek için maksimum süre (saniye), zaman aşımından önce (0 = zaman aşımı yok, 1-600s, varsayılan: 0s)",
"settings.vsCodeLmModelSelector.description": "VSCode dil modeli API'si için ayarlar",
"settings.vsCodeLmModelSelector.vendor.description": "Dil modelinin sağlayıcısı (örn: copilot)",
"settings.vsCodeLmModelSelector.family.description": "Dil modelinin ailesi (örn: gpt-4)",
diff --git a/src/package.nls.vi.json b/src/package.nls.vi.json
index 8d3d76fc82..067738892d 100644
--- a/src/package.nls.vi.json
+++ b/src/package.nls.vi.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "Các lệnh có thể được thực thi tự động khi 'Luôn phê duyệt các thao tác thực thi' được bật",
"commands.deniedCommands.description": "Các tiền tố lệnh sẽ được tự động từ chối mà không yêu cầu phê duyệt. Trong trường hợp xung đột với các lệnh được phép, việc khớp tiền tố dài nhất sẽ được ưu tiên. Thêm * để từ chối tất cả các lệnh.",
+ "commands.commandExecutionTimeout.description": "Thời gian tối đa tính bằng giây để chờ việc thực thi lệnh hoàn thành trước khi hết thời gian chờ (0 = không có thời gian chờ, 1-600s, mặc định: 0s)",
"settings.vsCodeLmModelSelector.description": "Cài đặt cho API mô hình ngôn ngữ VSCode",
"settings.vsCodeLmModelSelector.vendor.description": "Nhà cung cấp mô hình ngôn ngữ (ví dụ: copilot)",
"settings.vsCodeLmModelSelector.family.description": "Họ mô hình ngôn ngữ (ví dụ: gpt-4)",
diff --git a/src/package.nls.zh-CN.json b/src/package.nls.zh-CN.json
index 91f36fb601..3a69340f81 100644
--- a/src/package.nls.zh-CN.json
+++ b/src/package.nls.zh-CN.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "当启用'始终批准执行操作'时可以自动执行的命令",
"commands.deniedCommands.description": "将自动拒绝而无需请求批准的命令前缀。与允许命令冲突时,最长前缀匹配优先。添加 * 拒绝所有命令。",
+ "commands.commandExecutionTimeout.description": "等待命令执行完成的最大时间(秒),超时前(0 = 无超时,1-600秒,默认:0秒)",
"settings.vsCodeLmModelSelector.description": "VSCode 语言模型 API 的设置",
"settings.vsCodeLmModelSelector.vendor.description": "语言模型的供应商(例如:copilot)",
"settings.vsCodeLmModelSelector.family.description": "语言模型的系列(例如:gpt-4)",
diff --git a/src/package.nls.zh-TW.json b/src/package.nls.zh-TW.json
index 6ab074bc4c..d6314420f1 100644
--- a/src/package.nls.zh-TW.json
+++ b/src/package.nls.zh-TW.json
@@ -28,6 +28,7 @@
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "當啟用'始終批准執行操作'時可以自動執行的命令",
"commands.deniedCommands.description": "將自動拒絕而無需請求批准的命令前綴。與允許命令衝突時,最長前綴匹配優先。新增 * 拒絕所有命令。",
+ "commands.commandExecutionTimeout.description": "等待命令執行完成的最大時間(秒),逾時前(0 = 無逾時,1-600秒,預設:0秒)",
"settings.vsCodeLmModelSelector.description": "VSCode 語言模型 API 的設定",
"settings.vsCodeLmModelSelector.vendor.description": "語言模型供應商(例如:copilot)",
"settings.vsCodeLmModelSelector.family.description": "語言模型系列(例如:gpt-4)",
diff --git a/src/services/code-index/__tests__/config-manager.spec.ts b/src/services/code-index/__tests__/config-manager.spec.ts
index 6d0e59e827..2d6e704d76 100644
--- a/src/services/code-index/__tests__/config-manager.spec.ts
+++ b/src/services/code-index/__tests__/config-manager.spec.ts
@@ -8,6 +8,17 @@ import { PreviousConfigSnapshot } from "../interfaces/config"
// Mock ContextProxy
vi.mock("../../../core/config/ContextProxy")
+// Mock embeddingModels module
+vi.mock("../../../shared/embeddingModels")
+
+// Import mocked functions
+import { getDefaultModelId, getModelDimension, getModelScoreThreshold } from "../../../shared/embeddingModels"
+
+// Type the mocked functions
+const mockedGetDefaultModelId = vi.mocked(getDefaultModelId)
+const mockedGetModelDimension = vi.mocked(getModelDimension)
+const mockedGetModelScoreThreshold = vi.mocked(getModelScoreThreshold)
+
describe("CodeIndexConfigManager", () => {
let mockContextProxy: any
let configManager: CodeIndexConfigManager
@@ -339,6 +350,14 @@ describe("CodeIndexConfigManager", () => {
})
it("should NOT require restart when models have same dimensions", async () => {
+ // Mock both models to have same dimension
+ mockedGetModelDimension.mockImplementation((provider, modelId) => {
+ if (modelId === "text-embedding-3-small" || modelId === "text-embedding-ada-002") {
+ return 1536
+ }
+ return undefined
+ })
+
// Initial state with text-embedding-3-small (1536D)
mockContextProxy.getGlobalState.mockReturnValue({
codebaseIndexEnabled: true,
@@ -794,6 +813,14 @@ describe("CodeIndexConfigManager", () => {
})
it("should fall back to model-specific threshold when user setting is undefined", async () => {
+ // Mock the model score threshold
+ mockedGetModelScoreThreshold.mockImplementation((provider, modelId) => {
+ if (provider === "ollama" && modelId === "nomic-embed-code") {
+ return 0.15
+ }
+ return undefined
+ })
+
mockContextProxy.getGlobalState.mockReturnValue({
codebaseIndexEnabled: true,
codebaseIndexQdrantUrl: "http://qdrant.local",
@@ -840,6 +867,14 @@ describe("CodeIndexConfigManager", () => {
})
it("should use model-specific threshold with openai-compatible provider", async () => {
+ // Mock the model score threshold
+ mockedGetModelScoreThreshold.mockImplementation((provider, modelId) => {
+ if (provider === "openai-compatible" && modelId === "nomic-embed-code") {
+ return 0.15
+ }
+ return undefined
+ })
+
mockContextProxy.getGlobalState.mockImplementation((key: string) => {
if (key === "codebaseIndexConfig") {
return {
@@ -882,6 +917,14 @@ describe("CodeIndexConfigManager", () => {
})
it("should handle priority correctly: user > model > default", async () => {
+ // Mock the model score threshold
+ mockedGetModelScoreThreshold.mockImplementation((provider, modelId) => {
+ if (provider === "ollama" && modelId === "nomic-embed-code") {
+ return 0.15
+ }
+ return undefined
+ })
+
// Test 1: User setting takes precedence
mockContextProxy.getGlobalState.mockReturnValue({
codebaseIndexEnabled: true,
@@ -1501,6 +1544,13 @@ describe("CodeIndexConfigManager", () => {
})
describe("loadConfiguration", () => {
+ beforeEach(() => {
+ // Set default mock behaviors
+ mockedGetDefaultModelId.mockReturnValue("text-embedding-3-small")
+ mockedGetModelDimension.mockReturnValue(undefined)
+ mockedGetModelScoreThreshold.mockReturnValue(undefined)
+ })
+
it("should load configuration and return proper structure", async () => {
const mockConfigValues = {
codebaseIndexEnabled: true,
@@ -1634,5 +1684,131 @@ describe("CodeIndexConfigManager", () => {
configManager = new CodeIndexConfigManager(mockContextProxy)
expect(configManager.isConfigured()).toBe(false)
})
+
+ describe("currentModelDimension", () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ })
+
+ it("should return model's built-in dimension when available", async () => {
+ // Mock getModelDimension to return a built-in dimension
+ mockedGetModelDimension.mockReturnValue(1536)
+
+ mockContextProxy.getGlobalState.mockReturnValue({
+ codebaseIndexEnabled: true,
+ codebaseIndexEmbedderProvider: "openai",
+ codebaseIndexEmbedderModelId: "text-embedding-3-small",
+ codebaseIndexEmbedderModelDimension: 2048, // Custom dimension should be ignored
+ codebaseIndexQdrantUrl: "http://localhost:6333",
+ })
+ mockContextProxy.getSecret.mockImplementation((key: string) => {
+ if (key === "codeIndexOpenAiKey") return "test-key"
+ return undefined
+ })
+
+ configManager = new CodeIndexConfigManager(mockContextProxy)
+ await configManager.loadConfiguration()
+
+ // Should return model's built-in dimension, not custom
+ expect(configManager.currentModelDimension).toBe(1536)
+ expect(mockedGetModelDimension).toHaveBeenCalledWith("openai", "text-embedding-3-small")
+ })
+
+ it("should use custom dimension only when model has no built-in dimension", async () => {
+ // Mock getModelDimension to return undefined (no built-in dimension)
+ mockedGetModelDimension.mockReturnValue(undefined)
+
+ mockContextProxy.getGlobalState.mockReturnValue({
+ codebaseIndexEnabled: true,
+ codebaseIndexEmbedderProvider: "openai-compatible",
+ codebaseIndexEmbedderModelId: "custom-model",
+ codebaseIndexEmbedderModelDimension: 2048, // Custom dimension should be used
+ codebaseIndexQdrantUrl: "http://localhost:6333",
+ })
+ mockContextProxy.getSecret.mockImplementation((key: string) => {
+ if (key === "codebaseIndexOpenAiCompatibleApiKey") return "test-key"
+ return undefined
+ })
+
+ configManager = new CodeIndexConfigManager(mockContextProxy)
+ await configManager.loadConfiguration()
+
+ // Should use custom dimension as fallback
+ expect(configManager.currentModelDimension).toBe(2048)
+ expect(mockedGetModelDimension).toHaveBeenCalledWith("openai-compatible", "custom-model")
+ })
+
+ it("should return undefined when neither model dimension nor custom dimension is available", async () => {
+ // Mock getModelDimension to return undefined
+ mockedGetModelDimension.mockReturnValue(undefined)
+
+ mockContextProxy.getGlobalState.mockReturnValue({
+ codebaseIndexEnabled: true,
+ codebaseIndexEmbedderProvider: "openai-compatible",
+ codebaseIndexEmbedderModelId: "unknown-model",
+ // No custom dimension set
+ codebaseIndexQdrantUrl: "http://localhost:6333",
+ })
+ mockContextProxy.getSecret.mockImplementation((key: string) => {
+ if (key === "codebaseIndexOpenAiCompatibleApiKey") return "test-key"
+ return undefined
+ })
+
+ configManager = new CodeIndexConfigManager(mockContextProxy)
+ await configManager.loadConfiguration()
+
+ // Should return undefined
+ expect(configManager.currentModelDimension).toBe(undefined)
+ expect(mockedGetModelDimension).toHaveBeenCalledWith("openai-compatible", "unknown-model")
+ })
+
+ it("should use default model ID when modelId is not specified", async () => {
+ // Mock getDefaultModelId and getModelDimension
+ mockedGetDefaultModelId.mockReturnValue("text-embedding-3-small")
+ mockedGetModelDimension.mockReturnValue(1536)
+
+ mockContextProxy.getGlobalState.mockReturnValue({
+ codebaseIndexEnabled: true,
+ codebaseIndexEmbedderProvider: "openai",
+ // No modelId specified
+ codebaseIndexQdrantUrl: "http://localhost:6333",
+ })
+ mockContextProxy.getSecret.mockImplementation((key: string) => {
+ if (key === "codeIndexOpenAiKey") return "test-key"
+ return undefined
+ })
+
+ configManager = new CodeIndexConfigManager(mockContextProxy)
+ await configManager.loadConfiguration()
+
+ // Should use default model ID
+ expect(configManager.currentModelDimension).toBe(1536)
+ expect(mockedGetDefaultModelId).toHaveBeenCalledWith("openai")
+ expect(mockedGetModelDimension).toHaveBeenCalledWith("openai", "text-embedding-3-small")
+ })
+
+ it("should ignore invalid custom dimension (0 or negative)", async () => {
+ // Mock getModelDimension to return undefined
+ mockedGetModelDimension.mockReturnValue(undefined)
+
+ mockContextProxy.getGlobalState.mockReturnValue({
+ codebaseIndexEnabled: true,
+ codebaseIndexEmbedderProvider: "openai-compatible",
+ codebaseIndexEmbedderModelId: "custom-model",
+ codebaseIndexEmbedderModelDimension: 0, // Invalid dimension
+ codebaseIndexQdrantUrl: "http://localhost:6333",
+ })
+ mockContextProxy.getSecret.mockImplementation((key: string) => {
+ if (key === "codebaseIndexOpenAiCompatibleApiKey") return "test-key"
+ return undefined
+ })
+
+ configManager = new CodeIndexConfigManager(mockContextProxy)
+ await configManager.loadConfiguration()
+
+ // Should return undefined since custom dimension is invalid
+ expect(configManager.currentModelDimension).toBe(undefined)
+ })
+ })
})
})
diff --git a/src/services/code-index/__tests__/service-factory.spec.ts b/src/services/code-index/__tests__/service-factory.spec.ts
index d65d99f623..1d8f7ba478 100644
--- a/src/services/code-index/__tests__/service-factory.spec.ts
+++ b/src/services/code-index/__tests__/service-factory.spec.ts
@@ -265,7 +265,7 @@ describe("CodeIndexServiceFactory", () => {
expect(() => factory.createEmbedder()).toThrow("serviceFactory.openAiCompatibleConfigMissing")
})
- it("should create GeminiEmbedder when using Gemini provider", () => {
+ it("should create GeminiEmbedder with default model when no modelId specified", () => {
// Arrange
const testConfig = {
embedderProvider: "gemini",
@@ -279,7 +279,25 @@ describe("CodeIndexServiceFactory", () => {
factory.createEmbedder()
// Assert
- expect(MockedGeminiEmbedder).toHaveBeenCalledWith("test-gemini-api-key")
+ expect(MockedGeminiEmbedder).toHaveBeenCalledWith("test-gemini-api-key", undefined)
+ })
+
+ it("should create GeminiEmbedder with specified modelId", () => {
+ // Arrange
+ const testConfig = {
+ embedderProvider: "gemini",
+ modelId: "text-embedding-004",
+ geminiOptions: {
+ apiKey: "test-gemini-api-key",
+ },
+ }
+ mockConfigManager.getConfig.mockReturnValue(testConfig as any)
+
+ // Act
+ factory.createEmbedder()
+
+ // Assert
+ expect(MockedGeminiEmbedder).toHaveBeenCalledWith("test-gemini-api-key", "text-embedding-004")
})
it("should throw error when Gemini API key is missing", () => {
@@ -402,10 +420,42 @@ describe("CodeIndexServiceFactory", () => {
)
})
- it("should prioritize manual modelDimension over getModelDimension for OpenAI Compatible provider", () => {
+ it("should prioritize getModelDimension over manual modelDimension for OpenAI Compatible provider", () => {
// Arrange
const testModelId = "custom-model"
const manualDimension = 1024
+ const modelDimension = 768
+ const testConfig = {
+ embedderProvider: "openai-compatible",
+ modelId: testModelId,
+ modelDimension: manualDimension, // This should be ignored when model has built-in dimension
+ openAiCompatibleOptions: {
+ baseUrl: "https://api.example.com/v1",
+ apiKey: "test-api-key",
+ },
+ qdrantUrl: "http://localhost:6333",
+ qdrantApiKey: "test-key",
+ }
+ mockConfigManager.getConfig.mockReturnValue(testConfig as any)
+ mockGetModelDimension.mockReturnValue(modelDimension) // This should be used
+
+ // Act
+ factory.createVectorStore()
+
+ // Assert
+ expect(mockGetModelDimension).toHaveBeenCalledWith("openai-compatible", testModelId)
+ expect(MockedQdrantVectorStore).toHaveBeenCalledWith(
+ "/test/workspace",
+ "http://localhost:6333",
+ modelDimension, // Should use model's built-in dimension, not manual
+ "test-key",
+ )
+ })
+
+ it("should use manual modelDimension only when model has no built-in dimension", () => {
+ // Arrange
+ const testModelId = "unknown-model"
+ const manualDimension = 1024
const testConfig = {
embedderProvider: "openai-compatible",
modelId: testModelId,
@@ -418,17 +468,17 @@ describe("CodeIndexServiceFactory", () => {
qdrantApiKey: "test-key",
}
mockConfigManager.getConfig.mockReturnValue(testConfig as any)
- mockGetModelDimension.mockReturnValue(768) // This should be ignored
+ mockGetModelDimension.mockReturnValue(undefined) // Model has no built-in dimension
// Act
factory.createVectorStore()
// Assert
- expect(mockGetModelDimension).not.toHaveBeenCalled()
+ expect(mockGetModelDimension).toHaveBeenCalledWith("openai-compatible", testModelId)
expect(MockedQdrantVectorStore).toHaveBeenCalledWith(
"/test/workspace",
"http://localhost:6333",
- manualDimension,
+ manualDimension, // Should use manual dimension as fallback
"test-key",
)
})
@@ -507,26 +557,51 @@ describe("CodeIndexServiceFactory", () => {
)
})
- it("should use fixed dimension 768 for Gemini provider", () => {
+ it("should use model-specific dimension for Gemini provider", () => {
// Arrange
const testConfig = {
embedderProvider: "gemini",
- modelId: "text-embedding-004", // This is ignored by Gemini
+ modelId: "gemini-embedding-001",
qdrantUrl: "http://localhost:6333",
qdrantApiKey: "test-key",
}
mockConfigManager.getConfig.mockReturnValue(testConfig as any)
+ mockGetModelDimension.mockReturnValue(3072)
// Act
factory.createVectorStore()
// Assert
- // getModelDimension should not be called for Gemini
- expect(mockGetModelDimension).not.toHaveBeenCalled()
+ expect(mockGetModelDimension).toHaveBeenCalledWith("gemini", "gemini-embedding-001")
expect(MockedQdrantVectorStore).toHaveBeenCalledWith(
"/test/workspace",
"http://localhost:6333",
- 768, // Fixed dimension for Gemini
+ 3072,
+ "test-key",
+ )
+ })
+
+ it("should use default model dimension for Gemini when modelId not specified", () => {
+ // Arrange
+ const testConfig = {
+ embedderProvider: "gemini",
+ qdrantUrl: "http://localhost:6333",
+ qdrantApiKey: "test-key",
+ }
+ mockConfigManager.getConfig.mockReturnValue(testConfig as any)
+ mockGetDefaultModelId.mockReturnValue("gemini-embedding-001")
+ mockGetModelDimension.mockReturnValue(3072)
+
+ // Act
+ factory.createVectorStore()
+
+ // Assert
+ expect(mockGetDefaultModelId).toHaveBeenCalledWith("gemini")
+ expect(mockGetModelDimension).toHaveBeenCalledWith("gemini", "gemini-embedding-001")
+ expect(MockedQdrantVectorStore).toHaveBeenCalledWith(
+ "/test/workspace",
+ "http://localhost:6333",
+ 3072,
"test-key",
)
})
diff --git a/src/services/code-index/config-manager.ts b/src/services/code-index/config-manager.ts
index f022aec780..9958f456c3 100644
--- a/src/services/code-index/config-manager.ts
+++ b/src/services/code-index/config-manager.ts
@@ -398,10 +398,19 @@ export class CodeIndexConfigManager {
/**
* Gets the current model dimension being used for embeddings.
- * Returns the explicitly configured dimension or undefined if not set.
+ * Returns the model's built-in dimension if available, otherwise falls back to custom dimension.
*/
public get currentModelDimension(): number | undefined {
- return this.modelDimension
+ // First try to get the model-specific dimension
+ const modelId = this.modelId ?? getDefaultModelId(this.embedderProvider)
+ const modelDimension = getModelDimension(this.embedderProvider, modelId)
+
+ // Only use custom dimension if model doesn't have a built-in dimension
+ if (!modelDimension && this.modelDimension && this.modelDimension > 0) {
+ return this.modelDimension
+ }
+
+ return modelDimension
}
/**
diff --git a/src/services/code-index/embedders/__tests__/gemini.spec.ts b/src/services/code-index/embedders/__tests__/gemini.spec.ts
index 378e6e7d95..d41a4dc1e9 100644
--- a/src/services/code-index/embedders/__tests__/gemini.spec.ts
+++ b/src/services/code-index/embedders/__tests__/gemini.spec.ts
@@ -25,13 +25,30 @@ describe("GeminiEmbedder", () => {
})
describe("constructor", () => {
- it("should create an instance with correct fixed values passed to OpenAICompatibleEmbedder", () => {
+ it("should create an instance with default model when no model specified", () => {
// Arrange
const apiKey = "test-gemini-api-key"
// Act
embedder = new GeminiEmbedder(apiKey)
+ // Assert
+ expect(MockedOpenAICompatibleEmbedder).toHaveBeenCalledWith(
+ "https://generativelanguage.googleapis.com/v1beta/openai/",
+ apiKey,
+ "gemini-embedding-001",
+ 2048,
+ )
+ })
+
+ it("should create an instance with specified model", () => {
+ // Arrange
+ const apiKey = "test-gemini-api-key"
+ const modelId = "text-embedding-004"
+
+ // Act
+ embedder = new GeminiEmbedder(apiKey, modelId)
+
// Assert
expect(MockedOpenAICompatibleEmbedder).toHaveBeenCalledWith(
"https://generativelanguage.googleapis.com/v1beta/openai/",
@@ -50,7 +67,7 @@ describe("GeminiEmbedder", () => {
})
describe("embedderInfo", () => {
- it("should return correct embedder info with dimension 768", () => {
+ it("should return correct embedder info", () => {
// Arrange
embedder = new GeminiEmbedder("test-api-key")
@@ -61,7 +78,66 @@ describe("GeminiEmbedder", () => {
expect(info).toEqual({
name: "gemini",
})
- expect(GeminiEmbedder.dimension).toBe(768)
+ })
+
+ describe("createEmbeddings", () => {
+ let mockCreateEmbeddings: any
+
+ beforeEach(() => {
+ mockCreateEmbeddings = vitest.fn()
+ MockedOpenAICompatibleEmbedder.prototype.createEmbeddings = mockCreateEmbeddings
+ })
+
+ it("should use instance model when no model parameter provided", async () => {
+ // Arrange
+ embedder = new GeminiEmbedder("test-api-key")
+ const texts = ["test text 1", "test text 2"]
+ const mockResponse = {
+ embeddings: [
+ [0.1, 0.2],
+ [0.3, 0.4],
+ ],
+ }
+ mockCreateEmbeddings.mockResolvedValue(mockResponse)
+
+ // Act
+ const result = await embedder.createEmbeddings(texts)
+
+ // Assert
+ expect(mockCreateEmbeddings).toHaveBeenCalledWith(texts, "gemini-embedding-001")
+ expect(result).toEqual(mockResponse)
+ })
+
+ it("should use provided model parameter when specified", async () => {
+ // Arrange
+ embedder = new GeminiEmbedder("test-api-key", "text-embedding-004")
+ const texts = ["test text 1", "test text 2"]
+ const mockResponse = {
+ embeddings: [
+ [0.1, 0.2],
+ [0.3, 0.4],
+ ],
+ }
+ mockCreateEmbeddings.mockResolvedValue(mockResponse)
+
+ // Act
+ const result = await embedder.createEmbeddings(texts, "gemini-embedding-001")
+
+ // Assert
+ expect(mockCreateEmbeddings).toHaveBeenCalledWith(texts, "gemini-embedding-001")
+ expect(result).toEqual(mockResponse)
+ })
+
+ it("should handle errors from OpenAICompatibleEmbedder", async () => {
+ // Arrange
+ embedder = new GeminiEmbedder("test-api-key")
+ const texts = ["test text"]
+ const error = new Error("Embedding failed")
+ mockCreateEmbeddings.mockRejectedValue(error)
+
+ // Act & Assert
+ await expect(embedder.createEmbeddings(texts)).rejects.toThrow("Embedding failed")
+ })
})
})
diff --git a/src/services/code-index/embedders/gemini.ts b/src/services/code-index/embedders/gemini.ts
index fcca4c0fda..7e795875c9 100644
--- a/src/services/code-index/embedders/gemini.ts
+++ b/src/services/code-index/embedders/gemini.ts
@@ -7,33 +7,36 @@ import { TelemetryService } from "@roo-code/telemetry"
/**
* Gemini embedder implementation that wraps the OpenAI Compatible embedder
- * with fixed configuration for Google's Gemini embedding API.
+ * with configuration for Google's Gemini embedding API.
*
- * Fixed values:
- * - Base URL: https://generativelanguage.googleapis.com/v1beta/openai/
- * - Model: text-embedding-004
- * - Dimension: 768
+ * Supported models:
+ * - text-embedding-004 (dimension: 768)
+ * - gemini-embedding-001 (dimension: 2048)
*/
export class GeminiEmbedder implements IEmbedder {
private readonly openAICompatibleEmbedder: OpenAICompatibleEmbedder
private static readonly GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/"
- private static readonly GEMINI_MODEL = "text-embedding-004"
- private static readonly GEMINI_DIMENSION = 768
+ private static readonly DEFAULT_MODEL = "gemini-embedding-001"
+ private readonly modelId: string
/**
* Creates a new Gemini embedder
* @param apiKey The Gemini API key for authentication
+ * @param modelId The model ID to use (defaults to gemini-embedding-001)
*/
- constructor(apiKey: string) {
+ constructor(apiKey: string, modelId?: string) {
if (!apiKey) {
throw new Error(t("embeddings:validation.apiKeyRequired"))
}
- // Create an OpenAI Compatible embedder with Gemini's fixed configuration
+ // Use provided model or default
+ this.modelId = modelId || GeminiEmbedder.DEFAULT_MODEL
+
+ // Create an OpenAI Compatible embedder with Gemini's configuration
this.openAICompatibleEmbedder = new OpenAICompatibleEmbedder(
GeminiEmbedder.GEMINI_BASE_URL,
apiKey,
- GeminiEmbedder.GEMINI_MODEL,
+ this.modelId,
GEMINI_MAX_ITEM_TOKENS,
)
}
@@ -41,13 +44,14 @@ export class GeminiEmbedder implements IEmbedder {
/**
* Creates embeddings for the given texts using Gemini's embedding API
* @param texts Array of text strings to embed
- * @param model Optional model identifier (ignored - always uses text-embedding-004)
+ * @param model Optional model identifier (uses constructor model if not provided)
* @returns Promise resolving to embedding response
*/
async createEmbeddings(texts: string[], model?: string): Promise {
try {
- // Always use the fixed Gemini model, ignoring any passed model parameter
- return await this.openAICompatibleEmbedder.createEmbeddings(texts, GeminiEmbedder.GEMINI_MODEL)
+ // Use the provided model or fall back to the instance's model
+ const modelToUse = model || this.modelId
+ return await this.openAICompatibleEmbedder.createEmbeddings(texts, modelToUse)
} catch (error) {
TelemetryService.instance.captureEvent(TelemetryEventName.CODE_INDEX_ERROR, {
error: error instanceof Error ? error.message : String(error),
@@ -85,11 +89,4 @@ export class GeminiEmbedder implements IEmbedder {
name: "gemini",
}
}
-
- /**
- * Gets the fixed dimension for Gemini embeddings
- */
- static get dimension(): number {
- return GeminiEmbedder.GEMINI_DIMENSION
- }
}
diff --git a/src/services/code-index/service-factory.ts b/src/services/code-index/service-factory.ts
index a741aaf72a..b7951db7ac 100644
--- a/src/services/code-index/service-factory.ts
+++ b/src/services/code-index/service-factory.ts
@@ -63,7 +63,7 @@ export class CodeIndexServiceFactory {
if (!config.geminiOptions?.apiKey) {
throw new Error(t("embeddings:serviceFactory.geminiConfigMissing"))
}
- return new GeminiEmbedder(config.geminiOptions.apiKey)
+ return new GeminiEmbedder(config.geminiOptions.apiKey, config.modelId)
}
throw new Error(
@@ -108,15 +108,12 @@ export class CodeIndexServiceFactory {
let vectorSize: number | undefined
- // First check if a manual dimension is provided (works for all providers)
- if (config.modelDimension && config.modelDimension > 0) {
+ // First try to get the model-specific dimension from profiles
+ vectorSize = getModelDimension(provider, modelId)
+
+ // Only use manual dimension if model doesn't have a built-in dimension
+ if (!vectorSize && config.modelDimension && config.modelDimension > 0) {
vectorSize = config.modelDimension
- } else if (provider === "gemini") {
- // Gemini's text-embedding-004 has a fixed dimension of 768
- vectorSize = 768
- } else {
- // Fall back to model-specific dimension from profiles
- vectorSize = getModelDimension(provider, modelId)
}
if (vectorSize === undefined || vectorSize <= 0) {
diff --git a/src/services/code-index/vector-store/__tests__/qdrant-client.spec.ts b/src/services/code-index/vector-store/__tests__/qdrant-client.spec.ts
index 8bd145ac40..e539c2edde 100644
--- a/src/services/code-index/vector-store/__tests__/qdrant-client.spec.ts
+++ b/src/services/code-index/vector-store/__tests__/qdrant-client.spec.ts
@@ -10,7 +10,16 @@ vitest.mock("@qdrant/js-client-rest")
vitest.mock("crypto")
vitest.mock("../../../../utils/path")
vitest.mock("../../../../i18n", () => ({
- t: (key: string) => key, // Just return the key for testing
+ t: (key: string, params?: any) => {
+ // Mock translation function that includes parameters for testing
+ if (key === "embeddings:vectorStore.vectorDimensionMismatch" && params?.errorMessage) {
+ return `Failed to update vector index for new model. Please try clearing the index and starting again. Details: ${params.errorMessage}`
+ }
+ if (key === "embeddings:vectorStore.qdrantConnectionFailed" && params?.qdrantUrl && params?.errorMessage) {
+ return `Failed to connect to Qdrant vector database. Please ensure Qdrant is running and accessible at ${params.qdrantUrl}. Error: ${params.errorMessage}`
+ }
+ return key // Just return the key for other cases
+ },
}))
vitest.mock("path", () => ({
...vitest.importActual("path"),
@@ -564,16 +573,22 @@ describe("QdrantVectorStore", () => {
})
it("should recreate collection if it exists but vectorSize mismatches and return true", async () => {
const differentVectorSize = 768
- // Mock getCollection to return existing collection info with different vector size
- mockQdrantClientInstance.getCollection.mockResolvedValue({
- config: {
- params: {
- vectors: {
- size: differentVectorSize, // Mismatching vector size
+ // Mock getCollection to return existing collection info with different vector size first,
+ // then return 404 to confirm deletion
+ mockQdrantClientInstance.getCollection
+ .mockResolvedValueOnce({
+ config: {
+ params: {
+ vectors: {
+ size: differentVectorSize, // Mismatching vector size
+ },
},
},
- },
- } as any)
+ } as any)
+ .mockRejectedValueOnce({
+ response: { status: 404 },
+ message: "Not found",
+ })
mockQdrantClientInstance.deleteCollection.mockResolvedValue(true as any)
mockQdrantClientInstance.createCollection.mockResolvedValue(true as any)
mockQdrantClientInstance.createPayloadIndex.mockResolvedValue({} as any)
@@ -582,7 +597,7 @@ describe("QdrantVectorStore", () => {
const result = await vectorStore.initialize()
expect(result).toBe(true)
- expect(mockQdrantClientInstance.getCollection).toHaveBeenCalledTimes(1)
+ expect(mockQdrantClientInstance.getCollection).toHaveBeenCalledTimes(2) // Once to check, once to verify deletion
expect(mockQdrantClientInstance.getCollection).toHaveBeenCalledWith(expectedCollectionName)
expect(mockQdrantClientInstance.deleteCollection).toHaveBeenCalledTimes(1)
expect(mockQdrantClientInstance.deleteCollection).toHaveBeenCalledWith(expectedCollectionName)
@@ -703,7 +718,7 @@ describe("QdrantVectorStore", () => {
}
expect(caughtError).toBeDefined()
- expect(caughtError.message).toContain("embeddings:vectorStore.vectorDimensionMismatch")
+ expect(caughtError.message).toContain("Failed to update vector index for new model")
expect(caughtError.cause).toBe(deleteError)
expect(mockQdrantClientInstance.getCollection).toHaveBeenCalledTimes(1)
@@ -719,15 +734,21 @@ describe("QdrantVectorStore", () => {
it("should throw vectorDimensionMismatch error when createCollection fails during recreation", async () => {
const differentVectorSize = 768
- mockQdrantClientInstance.getCollection.mockResolvedValue({
- config: {
- params: {
- vectors: {
- size: differentVectorSize,
+ mockQdrantClientInstance.getCollection
+ .mockResolvedValueOnce({
+ config: {
+ params: {
+ vectors: {
+ size: differentVectorSize,
+ },
},
},
- },
- } as any)
+ } as any)
+ // Second call should return 404 to confirm deletion
+ .mockRejectedValueOnce({
+ response: { status: 404 },
+ message: "Not found",
+ })
// Delete succeeds but create fails
mockQdrantClientInstance.deleteCollection.mockResolvedValue(true as any)
@@ -745,10 +766,10 @@ describe("QdrantVectorStore", () => {
}
expect(caughtError).toBeDefined()
- expect(caughtError.message).toContain("embeddings:vectorStore.vectorDimensionMismatch")
+ expect(caughtError.message).toContain("Failed to update vector index for new model")
expect(caughtError.cause).toBe(createError)
- expect(mockQdrantClientInstance.getCollection).toHaveBeenCalledTimes(1)
+ expect(mockQdrantClientInstance.getCollection).toHaveBeenCalledTimes(2)
expect(mockQdrantClientInstance.deleteCollection).toHaveBeenCalledTimes(1)
expect(mockQdrantClientInstance.createCollection).toHaveBeenCalledTimes(1)
expect(mockQdrantClientInstance.createPayloadIndex).not.toHaveBeenCalled()
@@ -758,6 +779,166 @@ describe("QdrantVectorStore", () => {
;(console.error as any).mockRestore()
;(console.warn as any).mockRestore()
})
+
+ it("should verify collection deletion before proceeding with recreation", async () => {
+ const differentVectorSize = 768
+ mockQdrantClientInstance.getCollection
+ .mockResolvedValueOnce({
+ config: {
+ params: {
+ vectors: {
+ size: differentVectorSize,
+ },
+ },
+ },
+ } as any)
+ // Second call should return 404 to confirm deletion
+ .mockRejectedValueOnce({
+ response: { status: 404 },
+ message: "Not found",
+ })
+
+ mockQdrantClientInstance.deleteCollection.mockResolvedValue(true as any)
+ mockQdrantClientInstance.createCollection.mockResolvedValue(true as any)
+ mockQdrantClientInstance.createPayloadIndex.mockResolvedValue({} as any)
+ vitest.spyOn(console, "warn").mockImplementation(() => {})
+
+ const result = await vectorStore.initialize()
+
+ expect(result).toBe(true)
+ // Should call getCollection twice: once to check existing, once to verify deletion
+ expect(mockQdrantClientInstance.getCollection).toHaveBeenCalledTimes(2)
+ expect(mockQdrantClientInstance.deleteCollection).toHaveBeenCalledTimes(1)
+ expect(mockQdrantClientInstance.createCollection).toHaveBeenCalledTimes(1)
+ expect(mockQdrantClientInstance.createPayloadIndex).toHaveBeenCalledTimes(5)
+ ;(console.warn as any).mockRestore()
+ })
+
+ it("should throw error if collection still exists after deletion attempt", async () => {
+ const differentVectorSize = 768
+ mockQdrantClientInstance.getCollection
+ .mockResolvedValueOnce({
+ config: {
+ params: {
+ vectors: {
+ size: differentVectorSize,
+ },
+ },
+ },
+ } as any)
+ // Second call should still return the collection (deletion failed)
+ .mockResolvedValueOnce({
+ config: {
+ params: {
+ vectors: {
+ size: differentVectorSize,
+ },
+ },
+ },
+ } as any)
+
+ mockQdrantClientInstance.deleteCollection.mockResolvedValue(true as any)
+ vitest.spyOn(console, "error").mockImplementation(() => {})
+ vitest.spyOn(console, "warn").mockImplementation(() => {})
+
+ let caughtError: any
+ try {
+ await vectorStore.initialize()
+ } catch (error: any) {
+ caughtError = error
+ }
+
+ expect(caughtError).toBeDefined()
+ expect(caughtError.message).toContain("Failed to update vector index for new model")
+ // The error message should contain the contextual error details
+ expect(caughtError.message).toContain("Deleted existing collection but failed verification step")
+
+ expect(mockQdrantClientInstance.getCollection).toHaveBeenCalledTimes(2)
+ expect(mockQdrantClientInstance.deleteCollection).toHaveBeenCalledTimes(1)
+ expect(mockQdrantClientInstance.createCollection).not.toHaveBeenCalled()
+ expect(mockQdrantClientInstance.createPayloadIndex).not.toHaveBeenCalled()
+ ;(console.error as any).mockRestore()
+ ;(console.warn as any).mockRestore()
+ })
+
+ it("should handle dimension mismatch scenario from 2048 to 768 dimensions", async () => {
+ // Simulate the exact scenario from the issue: switching from 2048 to 768 dimensions
+ const oldVectorSize = 2048
+ const newVectorSize = 768
+
+ // Create a new vector store with the new dimension
+ const newVectorStore = new QdrantVectorStore(mockWorkspacePath, mockQdrantUrl, newVectorSize, mockApiKey)
+
+ mockQdrantClientInstance.getCollection
+ .mockResolvedValueOnce({
+ config: {
+ params: {
+ vectors: {
+ size: oldVectorSize, // Existing collection has 2048 dimensions
+ },
+ },
+ },
+ } as any)
+ // Second call should return 404 to confirm deletion
+ .mockRejectedValueOnce({
+ response: { status: 404 },
+ message: "Not found",
+ })
+
+ mockQdrantClientInstance.deleteCollection.mockResolvedValue(true as any)
+ mockQdrantClientInstance.createCollection.mockResolvedValue(true as any)
+ mockQdrantClientInstance.createPayloadIndex.mockResolvedValue({} as any)
+ vitest.spyOn(console, "warn").mockImplementation(() => {})
+
+ const result = await newVectorStore.initialize()
+
+ expect(result).toBe(true)
+ expect(mockQdrantClientInstance.getCollection).toHaveBeenCalledTimes(2)
+ expect(mockQdrantClientInstance.deleteCollection).toHaveBeenCalledTimes(1)
+ expect(mockQdrantClientInstance.createCollection).toHaveBeenCalledWith(expectedCollectionName, {
+ vectors: {
+ size: newVectorSize, // Should create with new 768 dimensions
+ distance: "Cosine",
+ },
+ })
+ expect(mockQdrantClientInstance.createPayloadIndex).toHaveBeenCalledTimes(5)
+ ;(console.warn as any).mockRestore()
+ })
+
+ it("should provide detailed error context for different failure scenarios", async () => {
+ const differentVectorSize = 768
+ mockQdrantClientInstance.getCollection.mockResolvedValue({
+ config: {
+ params: {
+ vectors: {
+ size: differentVectorSize,
+ },
+ },
+ },
+ } as any)
+
+ // Test deletion failure with specific error message
+ const deleteError = new Error("Qdrant server unavailable")
+ mockQdrantClientInstance.deleteCollection.mockRejectedValue(deleteError)
+ vitest.spyOn(console, "error").mockImplementation(() => {})
+ vitest.spyOn(console, "warn").mockImplementation(() => {})
+
+ let caughtError: any
+ try {
+ await vectorStore.initialize()
+ } catch (error: any) {
+ caughtError = error
+ }
+
+ expect(caughtError).toBeDefined()
+ expect(caughtError.message).toContain("Failed to update vector index for new model")
+ // The error message should contain the contextual error details
+ expect(caughtError.message).toContain("Failed to delete existing collection with vector size")
+ expect(caughtError.message).toContain("Qdrant server unavailable")
+ expect(caughtError.cause).toBe(deleteError)
+ ;(console.error as any).mockRestore()
+ ;(console.warn as any).mockRestore()
+ })
})
it("should return true when collection exists", async () => {
diff --git a/src/services/code-index/vector-store/qdrant-client.ts b/src/services/code-index/vector-store/qdrant-client.ts
index b23f5bca8a..5121d65b97 100644
--- a/src/services/code-index/vector-store/qdrant-client.ts
+++ b/src/services/code-index/vector-store/qdrant-client.ts
@@ -160,58 +160,32 @@ export class QdrantVectorStore implements IVectorStore {
created = true
} else {
// Collection exists, check vector size
- const existingVectorSize = collectionInfo.config?.params?.vectors?.size
+ const vectorsConfig = collectionInfo.config?.params?.vectors
+ let existingVectorSize: number
+
+ if (typeof vectorsConfig === "number") {
+ existingVectorSize = vectorsConfig
+ } else if (
+ vectorsConfig &&
+ typeof vectorsConfig === "object" &&
+ "size" in vectorsConfig &&
+ typeof vectorsConfig.size === "number"
+ ) {
+ existingVectorSize = vectorsConfig.size
+ } else {
+ existingVectorSize = 0 // Fallback for unknown configuration
+ }
+
if (existingVectorSize === this.vectorSize) {
created = false // Exists and correct
} else {
- // Exists but wrong vector size, recreate
- try {
- console.warn(
- `[QdrantVectorStore] Collection ${this.collectionName} exists with vector size ${existingVectorSize}, but expected ${this.vectorSize}. Recreating collection.`,
- )
- await this.client.deleteCollection(this.collectionName)
- await this.client.createCollection(this.collectionName, {
- vectors: {
- size: this.vectorSize,
- distance: this.DISTANCE_METRIC,
- },
- })
- created = true
- } catch (recreationError) {
- const errorMessage =
- recreationError instanceof Error ? recreationError.message : String(recreationError)
- console.error(
- `[QdrantVectorStore] CRITICAL: Failed to recreate collection ${this.collectionName} for new vector size. Error: ${errorMessage}`,
- )
- const dimensionMismatchError = new Error(
- t("embeddings:vectorStore.vectorDimensionMismatch", {
- errorMessage,
- }),
- )
- // Use error.cause to preserve the original error context
- dimensionMismatchError.cause = recreationError
- throw dimensionMismatchError
- }
+ // Exists but wrong vector size, recreate with enhanced error handling
+ created = await this._recreateCollectionWithNewDimension(existingVectorSize)
}
}
// Create payload indexes
- for (let i = 0; i <= 4; i++) {
- try {
- await this.client.createPayloadIndex(this.collectionName, {
- field_name: `pathSegments.${i}`,
- field_schema: "keyword",
- })
- } catch (indexError: any) {
- const errorMessage = (indexError?.message || "").toLowerCase()
- if (!errorMessage.includes("already exists")) {
- console.warn(
- `[QdrantVectorStore] Could not create payload index for pathSegments.${i} on ${this.collectionName}. Details:`,
- indexError?.message || indexError,
- )
- }
- }
- }
+ await this._createPayloadIndexes()
return created
} catch (error: any) {
const errorMessage = error?.message || error
@@ -232,6 +206,100 @@ export class QdrantVectorStore implements IVectorStore {
}
}
+ /**
+ * Recreates the collection with a new vector dimension, handling failures gracefully.
+ * @param existingVectorSize The current vector size of the existing collection
+ * @returns Promise resolving to boolean indicating if a new collection was created
+ */
+ private async _recreateCollectionWithNewDimension(existingVectorSize: number): Promise {
+ console.warn(
+ `[QdrantVectorStore] Collection ${this.collectionName} exists with vector size ${existingVectorSize}, but expected ${this.vectorSize}. Recreating collection.`,
+ )
+
+ let deletionSucceeded = false
+ let recreationAttempted = false
+
+ try {
+ // Step 1: Attempt to delete the existing collection
+ console.log(`[QdrantVectorStore] Deleting existing collection ${this.collectionName}...`)
+ await this.client.deleteCollection(this.collectionName)
+ deletionSucceeded = true
+ console.log(`[QdrantVectorStore] Successfully deleted collection ${this.collectionName}`)
+
+ // Step 2: Wait a brief moment to ensure deletion is processed
+ await new Promise((resolve) => setTimeout(resolve, 100))
+
+ // Step 3: Verify the collection is actually deleted
+ const verificationInfo = await this.getCollectionInfo()
+ if (verificationInfo !== null) {
+ throw new Error("Collection still exists after deletion attempt")
+ }
+
+ // Step 4: Create the new collection with correct dimensions
+ console.log(
+ `[QdrantVectorStore] Creating new collection ${this.collectionName} with vector size ${this.vectorSize}...`,
+ )
+ recreationAttempted = true
+ await this.client.createCollection(this.collectionName, {
+ vectors: {
+ size: this.vectorSize,
+ distance: this.DISTANCE_METRIC,
+ },
+ })
+ console.log(`[QdrantVectorStore] Successfully created new collection ${this.collectionName}`)
+ return true
+ } catch (recreationError) {
+ const errorMessage = recreationError instanceof Error ? recreationError.message : String(recreationError)
+
+ // Provide detailed error context based on what stage failed
+ let contextualErrorMessage: string
+ if (!deletionSucceeded) {
+ contextualErrorMessage = `Failed to delete existing collection with vector size ${existingVectorSize}. ${errorMessage}`
+ } else if (!recreationAttempted) {
+ contextualErrorMessage = `Deleted existing collection but failed verification step. ${errorMessage}`
+ } else {
+ contextualErrorMessage = `Deleted existing collection but failed to create new collection with vector size ${this.vectorSize}. ${errorMessage}`
+ }
+
+ console.error(
+ `[QdrantVectorStore] CRITICAL: Failed to recreate collection ${this.collectionName} for dimension change (${existingVectorSize} -> ${this.vectorSize}). ${contextualErrorMessage}`,
+ )
+
+ // Create a comprehensive error message for the user
+ const dimensionMismatchError = new Error(
+ t("embeddings:vectorStore.vectorDimensionMismatch", {
+ errorMessage: contextualErrorMessage,
+ }),
+ )
+
+ // Preserve the original error context
+ dimensionMismatchError.cause = recreationError
+ throw dimensionMismatchError
+ }
+ }
+
+ /**
+ * Creates payload indexes for the collection, handling errors gracefully.
+ */
+ private async _createPayloadIndexes(): Promise {
+ for (let i = 0; i <= 4; i++) {
+ try {
+ await this.client.createPayloadIndex(this.collectionName, {
+ field_name: `pathSegments.${i}`,
+ field_schema: "keyword",
+ })
+ } catch (indexError: any) {
+ const errorMessage = (indexError?.message || "").toLowerCase()
+ if (!errorMessage.includes("already exists")) {
+ console.warn(
+ `[QdrantVectorStore] Could not create payload index for pathSegments.${i} on ${this.collectionName}. Details:`,
+ indexError?.message || indexError,
+ )
+ }
+ }
+ }
+ }
+
/**
* Upserts points into the vector store
* @param points Array of points to upsert
diff --git a/src/shared/__tests__/api.spec.ts b/src/shared/__tests__/api.spec.ts
index a13e823a90..08d4bdf3bb 100644
--- a/src/shared/__tests__/api.spec.ts
+++ b/src/shared/__tests__/api.spec.ts
@@ -76,7 +76,7 @@ describe("getModelMaxOutputTokens", () => {
expect(result).toBe(32000)
})
- test("should return 20% of context window when maxTokens is undefined", () => {
+ test("should return default of 8192 when maxTokens is undefined", () => {
const modelWithoutMaxTokens: ModelInfo = {
contextWindow: 100000,
supportsPromptCache: true,
@@ -88,7 +88,7 @@ describe("getModelMaxOutputTokens", () => {
settings: {},
})
- expect(result).toBe(20000) // 20% of 100000
+ expect(result).toBe(8192)
})
test("should return ANTHROPIC_DEFAULT_MAX_TOKENS for Anthropic models that support reasoning budget but aren't using it", () => {
diff --git a/src/shared/api.ts b/src/shared/api.ts
index a6199c81aa..8cbfc72133 100644
--- a/src/shared/api.ts
+++ b/src/shared/api.ts
@@ -58,14 +58,15 @@ export const getModelMaxOutputTokens = ({
modelId,
model,
settings,
+ format,
}: {
modelId: string
model: ModelInfo
settings?: ProviderSettings
+ format?: "anthropic" | "openai" | "gemini" | "openrouter"
}): number | undefined => {
// Check for Claude Code specific max output tokens setting
if (settings?.apiProvider === "claude-code") {
- // Return the configured value or default to CLAUDE_CODE_DEFAULT_MAX_OUTPUT_TOKENS
return settings.claudeCodeMaxOutputTokens || CLAUDE_CODE_DEFAULT_MAX_OUTPUT_TOKENS
}
@@ -73,18 +74,33 @@ export const getModelMaxOutputTokens = ({
return settings?.modelMaxTokens || DEFAULT_HYBRID_REASONING_MODEL_MAX_TOKENS
}
- const isAnthropicModel = modelId.includes("claude")
+ const isAnthropicContext =
+ modelId.includes("claude") ||
+ format === "anthropic" ||
+ (format === "openrouter" && modelId.startsWith("anthropic/"))
- // For "Hybrid" reasoning models, we should discard the model's actual
- // `maxTokens` value if we're not using reasoning. We do this for Anthropic
- // models only for now. Should we do this for Gemini too?
- if (model.supportsReasoningBudget && isAnthropicModel) {
+ // For "Hybrid" reasoning models, discard the model's actual maxTokens for Anthropic contexts
+ if (model.supportsReasoningBudget && isAnthropicContext) {
return ANTHROPIC_DEFAULT_MAX_TOKENS
}
- // If maxTokens is 0 or undefined, fall back to 20% of context window
- // This matches the sliding window logic
- return model.maxTokens || Math.ceil(model.contextWindow * 0.2)
+ // For Anthropic contexts, always ensure a maxTokens value is set
+ if (isAnthropicContext && (!model.maxTokens || model.maxTokens === 0)) {
+ return ANTHROPIC_DEFAULT_MAX_TOKENS
+ }
+
+ // If model has explicit maxTokens and it's not the full context window, use it
+ if (model.maxTokens && model.maxTokens !== model.contextWindow) {
+ return model.maxTokens
+ }
+
+ // For non-Anthropic formats without explicit maxTokens, return undefined
+ if (format) {
+ return undefined
+ }
+
+ // Default fallback
+ return ANTHROPIC_DEFAULT_MAX_TOKENS
}
// GetModelsOptions
diff --git a/src/shared/embeddingModels.ts b/src/shared/embeddingModels.ts
index 4c6bc24319..f387480c65 100644
--- a/src/shared/embeddingModels.ts
+++ b/src/shared/embeddingModels.ts
@@ -48,6 +48,7 @@ export const EMBEDDING_MODEL_PROFILES: EmbeddingModelProfiles = {
},
gemini: {
"text-embedding-004": { dimension: 768 },
+ "gemini-embedding-001": { dimension: 3072, scoreThreshold: 0.4 },
},
}
@@ -134,7 +135,7 @@ export function getDefaultModelId(provider: EmbedderProvider): string {
}
case "gemini":
- return "text-embedding-004"
+ return "gemini-embedding-001"
default:
// Fallback for unknown providers
diff --git a/webview-ui/src/__tests__/ContextWindowProgressLogic.spec.ts b/webview-ui/src/__tests__/ContextWindowProgressLogic.spec.ts
index 39c6cd40d5..0f9314218c 100644
--- a/webview-ui/src/__tests__/ContextWindowProgressLogic.spec.ts
+++ b/webview-ui/src/__tests__/ContextWindowProgressLogic.spec.ts
@@ -7,41 +7,41 @@ export {} // This makes the file a proper TypeScript module
describe("ContextWindowProgress Logic", () => {
// Using the shared utility function from model-utils.ts instead of reimplementing it
- test("calculates correct token distribution with default 20% reservation", () => {
- const contextWindow = 4000
+ test("calculates correct token distribution with default 8192 reservation", () => {
+ const contextWindow = 10000
const contextTokens = 1000
const result = calculateTokenDistribution(contextWindow, contextTokens)
// Expected calculations:
- // reservedForOutput = 0.2 * 4000 = 800
- // availableSize = 4000 - 1000 - 800 = 2200
- // total = 1000 + 800 + 2200 = 4000
- expect(result.reservedForOutput).toBe(800)
- expect(result.availableSize).toBe(2200)
+ // reservedForOutput = 8192 (ANTHROPIC_DEFAULT_MAX_TOKENS)
+ // availableSize = 10000 - 1000 - 8192 = 808
+ // total = 1000 + 8192 + 808 = 10000
+ expect(result.reservedForOutput).toBe(8192)
+ expect(result.availableSize).toBe(808)
// Check percentages
- expect(result.currentPercent).toBeCloseTo(25) // 1000/4000 * 100 = 25%
- expect(result.reservedPercent).toBeCloseTo(20) // 800/4000 * 100 = 20%
- expect(result.availablePercent).toBeCloseTo(55) // 2200/4000 * 100 = 55%
+ expect(result.currentPercent).toBeCloseTo(10) // 1000/10000 * 100 = 10%
+ expect(result.reservedPercent).toBeCloseTo(81.92) // 8192/10000 * 100 = 81.92%
+ expect(result.availablePercent).toBeCloseTo(8.08) // 808/10000 * 100 = 8.08%
// Verify percentages sum to 100%
expect(result.currentPercent + result.reservedPercent + result.availablePercent).toBeCloseTo(100)
})
test("uses provided maxTokens when available instead of default calculation", () => {
- const contextWindow = 4000
+ const contextWindow = 10000
const contextTokens = 1000
- // First calculate with default 20% reservation (no maxTokens provided)
+ // First calculate with default 8192 reservation (no maxTokens provided)
const defaultResult = calculateTokenDistribution(contextWindow, contextTokens)
// Then calculate with custom maxTokens value
- const customMaxTokens = 1500 // Custom maxTokens instead of default 20%
+ const customMaxTokens = 1500 // Custom maxTokens instead of default 8192
const customResult = calculateTokenDistribution(contextWindow, contextTokens, customMaxTokens)
- // VERIFY MAXTOKEN PROP EFFECT: Custom maxTokens should be used directly instead of 20% calculation
- const defaultReserved = Math.ceil(contextWindow * 0.2) // 800 tokens (20% of 4000)
+ // VERIFY MAXTOKEN PROP EFFECT: Custom maxTokens should be used directly instead of 8192 calculation
+ const defaultReserved = 8192 // ANTHROPIC_DEFAULT_MAX_TOKENS
expect(defaultResult.reservedForOutput).toBe(defaultReserved)
expect(customResult.reservedForOutput).toBe(customMaxTokens) // Should use exact provided value
@@ -51,13 +51,13 @@ describe("ContextWindowProgress Logic", () => {
expect(defaultTooltip).not.toBe(customTooltip)
// Verify the effect on available space
- expect(customResult.availableSize).toBe(4000 - 1000 - 1500) // 1500 tokens available
- expect(defaultResult.availableSize).toBe(4000 - 1000 - 800) // 2200 tokens available
+ expect(customResult.availableSize).toBe(10000 - 1000 - 1500) // 7500 tokens available
+ expect(defaultResult.availableSize).toBe(10000 - 1000 - 8192) // 808 tokens available
// Verify the effect on percentages
- // With custom maxTokens (1500), the reserved percentage should be higher
- expect(defaultResult.reservedPercent).toBeCloseTo(20) // 800/4000 * 100 = 20%
- expect(customResult.reservedPercent).toBeCloseTo(37.5) // 1500/4000 * 100 = 37.5%
+ // With custom maxTokens (1500), the reserved percentage should be lower than default
+ expect(defaultResult.reservedPercent).toBeCloseTo(81.92) // 8192/10000 * 100 = 81.92%
+ expect(customResult.reservedPercent).toBeCloseTo(15) // 1500/10000 * 100 = 15%
// Verify percentages still sum to 100%
expect(customResult.currentPercent + customResult.reservedPercent + customResult.availablePercent).toBeCloseTo(
@@ -66,19 +66,19 @@ describe("ContextWindowProgress Logic", () => {
})
test("handles negative input values", () => {
- const contextWindow = 4000
+ const contextWindow = 10000
const contextTokens = -500 // Negative tokens should be handled gracefully
const result = calculateTokenDistribution(contextWindow, contextTokens)
// Expected calculations:
// safeContextTokens = Math.max(0, -500) = 0
- // reservedForOutput = 0.2 * 4000 = 800
- // availableSize = 4000 - 0 - 800 = 3200
- // total = 0 + 800 + 3200 = 4000
- expect(result.currentPercent).toBeCloseTo(0) // 0/4000 * 100 = 0%
- expect(result.reservedPercent).toBeCloseTo(20) // 800/4000 * 100 = 20%
- expect(result.availablePercent).toBeCloseTo(80) // 3200/4000 * 100 = 80%
+ // reservedForOutput = 8192 (ANTHROPIC_DEFAULT_MAX_TOKENS)
+ // availableSize = 10000 - 0 - 8192 = 1808
+ // total = 0 + 8192 + 1808 = 10000
+ expect(result.currentPercent).toBeCloseTo(0) // 0/10000 * 100 = 0%
+ expect(result.reservedPercent).toBeCloseTo(81.92) // 8192/10000 * 100 = 81.92%
+ expect(result.availablePercent).toBeCloseTo(18.08) // 1808/10000 * 100 = 18.08%
})
test("handles zero context window gracefully", () => {
@@ -87,9 +87,9 @@ describe("ContextWindowProgress Logic", () => {
const result = calculateTokenDistribution(contextWindow, contextTokens)
- // With zero context window, everything should be zero
- expect(result.reservedForOutput).toBe(0)
- expect(result.availableSize).toBe(0)
+ // With zero context window, the function uses ANTHROPIC_DEFAULT_MAX_TOKENS but available size becomes 0
+ expect(result.reservedForOutput).toBe(8192) // ANTHROPIC_DEFAULT_MAX_TOKENS
+ expect(result.availableSize).toBe(0) // max(0, 0 - 1000 - 8192) = 0
// The percentages maintain total of 100% even with zero context window
// due to how the division handles this edge case
@@ -98,20 +98,20 @@ describe("ContextWindowProgress Logic", () => {
})
test("handles case where tokens exceed context window", () => {
- const contextWindow = 4000
- const contextTokens = 5000 // More tokens than the window size
+ const contextWindow = 10000
+ const contextTokens = 12000 // More tokens than the window size
const result = calculateTokenDistribution(contextWindow, contextTokens)
// Expected calculations:
- // reservedForOutput = 0.2 * 4000 = 800
- // availableSize = Math.max(0, 4000 - 5000 - 800) = 0
- expect(result.reservedForOutput).toBe(800)
+ // reservedForOutput = 8192 (ANTHROPIC_DEFAULT_MAX_TOKENS)
+ // availableSize = Math.max(0, 10000 - 12000 - 8192) = 0
+ expect(result.reservedForOutput).toBe(8192)
expect(result.availableSize).toBe(0)
- // Percentages should be calculated based on total (5000 + 800 + 0 = 5800)
- expect(result.currentPercent).toBeCloseTo((5000 / 5800) * 100)
- expect(result.reservedPercent).toBeCloseTo((800 / 5800) * 100)
+ // Percentages should be calculated based on total (12000 + 8192 + 0 = 20192)
+ expect(result.currentPercent).toBeCloseTo((12000 / 20192) * 100)
+ expect(result.reservedPercent).toBeCloseTo((8192 / 20192) * 100)
expect(result.availablePercent).toBeCloseTo(0)
// Verify percentages sum to 100%
diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx
index fa4d7ec82a..0f0b056f75 100644
--- a/webview-ui/src/components/chat/ChatView.tsx
+++ b/webview-ui/src/components/chat/ChatView.tsx
@@ -79,7 +79,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction {
+ const allModes = getAllModes(customModes)
+ const currentModeIndex = allModes.findIndex((m) => m.slug === mode)
+ const previousModeIndex = (currentModeIndex - 1 + allModes.length) % allModes.length
+ // Update local state and notify extension to sync mode change
+ switchToMode(allModes[previousModeIndex].slug)
+ }, [mode, customModes, switchToMode])
+
// Add keyboard event handler
const handleKeyDown = useCallback(
(event: KeyboardEvent) => {
- // Check for Command + . (period)
- if ((event.metaKey || event.ctrlKey) && event.key === ".") {
+ // Check for Command/Ctrl + Period (with or without Shift)
+ // Using event.code for better cross-platform compatibility
+ if ((event.metaKey || event.ctrlKey) && event.code === "Period") {
event.preventDefault() // Prevent default browser behavior
- switchToNextMode()
+
+ if (event.shiftKey) {
+ // Shift + Period = Previous mode
+ switchToPreviousMode()
+ } else {
+ // Just Period = Next mode
+ switchToNextMode()
+ }
}
},
- [switchToNextMode],
+ [switchToNextMode, switchToPreviousMode],
)
// Add event listener
diff --git a/webview-ui/src/components/chat/CodeIndexPopover.tsx b/webview-ui/src/components/chat/CodeIndexPopover.tsx
index 84703bcae2..b5742cc623 100644
--- a/webview-ui/src/components/chat/CodeIndexPopover.tsx
+++ b/webview-ui/src/components/chat/CodeIndexPopover.tsx
@@ -643,7 +643,7 @@ export const CodeIndexPopover: React.FC = ({
className={cn("w-full", {
"border-red-500": formErrors.codebaseIndexEmbedderModelId,
})}>
-
+
{t("settings:codeIndex.selectModel")}
{getAvailableModels().map((modelId) => {
@@ -652,7 +652,7 @@ export const CodeIndexPopover: React.FC = ({
currentSettings.codebaseIndexEmbedderProvider
]?.[modelId]
return (
-
+
{modelId}{" "}
{model
? t("settings:codeIndex.modelDimensions", {
@@ -717,7 +717,7 @@ export const CodeIndexPopover: React.FC = ({
className={cn("w-full", {
"border-red-500": formErrors.codebaseIndexEmbedderModelId,
})}>
-
+
{t("settings:codeIndex.selectModel")}
{getAvailableModels().map((modelId) => {
@@ -726,7 +726,7 @@ export const CodeIndexPopover: React.FC = ({
currentSettings.codebaseIndexEmbedderProvider
]?.[modelId]
return (
-
+
{modelId}{" "}
{model
? t("settings:codeIndex.modelDimensions", {
@@ -890,7 +890,7 @@ export const CodeIndexPopover: React.FC = ({
className={cn("w-full", {
"border-red-500": formErrors.codebaseIndexEmbedderModelId,
})}>
-
+
{t("settings:codeIndex.selectModel")}
{getAvailableModels().map((modelId) => {
@@ -899,7 +899,7 @@ export const CodeIndexPopover: React.FC = ({
currentSettings.codebaseIndexEmbedderProvider
]?.[modelId]
return (
-
+
{modelId}{" "}
{model
? t("settings:codeIndex.modelDimensions", {
diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json
index ade415a0a0..bcc41d2052 100644
--- a/webview-ui/src/i18n/locales/ca/chat.json
+++ b/webview-ui/src/i18n/locales/ca/chat.json
@@ -123,6 +123,7 @@
"separator": "Separador",
"edit": "Edita...",
"forNextMode": "per al següent mode",
+ "forPreviousMode": "per al mode anterior",
"error": "Error",
"diffError": {
"title": "Edició fallida"
diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json
index 13f0f64e45..2c85048bf0 100644
--- a/webview-ui/src/i18n/locales/de/chat.json
+++ b/webview-ui/src/i18n/locales/de/chat.json
@@ -123,6 +123,7 @@
"separator": "Trennlinie",
"edit": "Bearbeiten...",
"forNextMode": "für nächsten Modus",
+ "forPreviousMode": "für vorherigen Modus",
"error": "Fehler",
"diffError": {
"title": "Bearbeitung fehlgeschlagen"
diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json
index ef40ba854b..a5c8bd8337 100644
--- a/webview-ui/src/i18n/locales/en/chat.json
+++ b/webview-ui/src/i18n/locales/en/chat.json
@@ -131,6 +131,7 @@
"separator": "Separator",
"edit": "Edit...",
"forNextMode": "for next mode",
+ "forPreviousMode": "for previous mode",
"apiRequest": {
"title": "API Request",
"failed": "API Request Failed",
diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json
index 200939d34b..711fe7712b 100644
--- a/webview-ui/src/i18n/locales/es/chat.json
+++ b/webview-ui/src/i18n/locales/es/chat.json
@@ -123,6 +123,7 @@
"separator": "Separador",
"edit": "Editar...",
"forNextMode": "para el siguiente modo",
+ "forPreviousMode": "para el modo anterior",
"error": "Error",
"diffError": {
"title": "Edición fallida"
diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json
index 2858400e78..f3832174e6 100644
--- a/webview-ui/src/i18n/locales/fr/chat.json
+++ b/webview-ui/src/i18n/locales/fr/chat.json
@@ -123,6 +123,7 @@
"separator": "Séparateur",
"edit": "Éditer...",
"forNextMode": "pour le prochain mode",
+ "forPreviousMode": "pour le mode précédent",
"error": "Erreur",
"diffError": {
"title": "Modification échouée"
diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json
index c2db235a6b..34e80597a8 100644
--- a/webview-ui/src/i18n/locales/hi/chat.json
+++ b/webview-ui/src/i18n/locales/hi/chat.json
@@ -123,6 +123,7 @@
"separator": "विभाजक",
"edit": "संपादित करें...",
"forNextMode": "अगले मोड के लिए",
+ "forPreviousMode": "पिछले मोड के लिए",
"error": "त्रुटि",
"diffError": {
"title": "संपादन असफल"
diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json
index dce0426832..c6f9c57644 100644
--- a/webview-ui/src/i18n/locales/id/chat.json
+++ b/webview-ui/src/i18n/locales/id/chat.json
@@ -137,6 +137,7 @@
"separator": "Pemisah",
"edit": "Edit...",
"forNextMode": "untuk mode selanjutnya",
+ "forPreviousMode": "untuk mode sebelumnya",
"apiRequest": {
"title": "Permintaan API",
"failed": "Permintaan API Gagal",
diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json
index 084606605f..080d6883aa 100644
--- a/webview-ui/src/i18n/locales/it/chat.json
+++ b/webview-ui/src/i18n/locales/it/chat.json
@@ -123,6 +123,7 @@
"separator": "Separatore",
"edit": "Modifica...",
"forNextMode": "per la prossima modalità",
+ "forPreviousMode": "per la modalità precedente",
"instructions": {
"wantsToFetch": "Roo vuole recuperare istruzioni dettagliate per aiutare con l'attività corrente"
},
diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json
index dc69fdf742..6bb74ad5e2 100644
--- a/webview-ui/src/i18n/locales/ja/chat.json
+++ b/webview-ui/src/i18n/locales/ja/chat.json
@@ -123,6 +123,7 @@
"separator": "区切り",
"edit": "編集...",
"forNextMode": "次のモード用",
+ "forPreviousMode": "前のモード用",
"error": "エラー",
"diffError": {
"title": "編集に失敗しました"
diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json
index 1be0b4cb1b..812579a850 100644
--- a/webview-ui/src/i18n/locales/ko/chat.json
+++ b/webview-ui/src/i18n/locales/ko/chat.json
@@ -123,6 +123,7 @@
"separator": "구분자",
"edit": "편집...",
"forNextMode": "다음 모드용",
+ "forPreviousMode": "이전 모드용",
"error": "오류",
"diffError": {
"title": "편집 실패"
diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json
index d2834c700f..c0e5e92d66 100644
--- a/webview-ui/src/i18n/locales/nl/chat.json
+++ b/webview-ui/src/i18n/locales/nl/chat.json
@@ -123,6 +123,7 @@
"separator": "Scheidingsteken",
"edit": "Bewerken...",
"forNextMode": "voor volgende modus",
+ "forPreviousMode": "voor vorige modus",
"apiRequest": {
"title": "API-verzoek",
"failed": "API-verzoek mislukt",
diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json
index e8020219c0..3e59b4f981 100644
--- a/webview-ui/src/i18n/locales/pl/chat.json
+++ b/webview-ui/src/i18n/locales/pl/chat.json
@@ -123,6 +123,7 @@
"separator": "Separator",
"edit": "Edytuj...",
"forNextMode": "dla następnego trybu",
+ "forPreviousMode": "dla poprzedniego trybu",
"error": "Błąd",
"diffError": {
"title": "Edycja nieudana"
diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json
index a0b39e6c96..8f7dcd5dcd 100644
--- a/webview-ui/src/i18n/locales/pt-BR/chat.json
+++ b/webview-ui/src/i18n/locales/pt-BR/chat.json
@@ -123,6 +123,7 @@
"separator": "Separador",
"edit": "Editar...",
"forNextMode": "para o próximo modo",
+ "forPreviousMode": "para o modo anterior",
"error": "Erro",
"diffError": {
"title": "Edição mal-sucedida"
diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json
index 9c751fba8c..89502fbc76 100644
--- a/webview-ui/src/i18n/locales/ru/chat.json
+++ b/webview-ui/src/i18n/locales/ru/chat.json
@@ -123,6 +123,7 @@
"separator": "Разделитель",
"edit": "Редактировать...",
"forNextMode": "для следующего режима",
+ "forPreviousMode": "для предыдущего режима",
"apiRequest": {
"title": "API-запрос",
"failed": "API-запрос не выполнен",
diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json
index 951877d65e..94910edf89 100644
--- a/webview-ui/src/i18n/locales/tr/chat.json
+++ b/webview-ui/src/i18n/locales/tr/chat.json
@@ -123,6 +123,7 @@
"separator": "Ayırıcı",
"edit": "Düzenle...",
"forNextMode": "sonraki mod için",
+ "forPreviousMode": "önceki mod için",
"error": "Hata",
"diffError": {
"title": "Düzenleme Başarısız"
diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json
index 7588595280..02f27f9e37 100644
--- a/webview-ui/src/i18n/locales/vi/chat.json
+++ b/webview-ui/src/i18n/locales/vi/chat.json
@@ -123,6 +123,7 @@
"separator": "Dấu phân cách",
"edit": "Chỉnh sửa...",
"forNextMode": "cho chế độ tiếp theo",
+ "forPreviousMode": "cho chế độ trước đó",
"error": "Lỗi",
"diffError": {
"title": "Chỉnh sửa không thành công"
diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json
index 352da4c9d2..370543f294 100644
--- a/webview-ui/src/i18n/locales/zh-CN/chat.json
+++ b/webview-ui/src/i18n/locales/zh-CN/chat.json
@@ -123,6 +123,7 @@
"separator": "分隔符",
"edit": "编辑...",
"forNextMode": "用于下一个模式",
+ "forPreviousMode": "用于上一个模式",
"error": "错误",
"diffError": {
"title": "编辑失败"
diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json
index ff0a541aa1..3b9dcc795c 100644
--- a/webview-ui/src/i18n/locales/zh-TW/chat.json
+++ b/webview-ui/src/i18n/locales/zh-TW/chat.json
@@ -123,6 +123,7 @@
"separator": "分隔符號",
"edit": "編輯...",
"forNextMode": "用於下一個模式",
+ "forPreviousMode": "用於上一個模式",
"error": "錯誤",
"diffError": {
"title": "編輯失敗"
diff --git a/webview-ui/src/utils/__tests__/model-utils.spec.ts b/webview-ui/src/utils/__tests__/model-utils.spec.ts
index 7b630e906e..a8ae33300a 100644
--- a/webview-ui/src/utils/__tests__/model-utils.spec.ts
+++ b/webview-ui/src/utils/__tests__/model-utils.spec.ts
@@ -17,33 +17,33 @@ describe("calculateTokenDistribution", () => {
expect(Math.round(result.currentPercent + result.reservedPercent + result.availablePercent)).toBe(100)
})
- it("should default to 20% of context window when maxTokens not provided", () => {
- const contextWindow = 10000
+ it("should default to 8192 when maxTokens not provided", () => {
+ const contextWindow = 20000
const contextTokens = 5000
const result = calculateTokenDistribution(contextWindow, contextTokens)
- expect(result.reservedForOutput).toBe(2000) // 20% of 10000
- expect(result.availableSize).toBe(3000) // 10000 - 5000 - 2000
+ expect(result.reservedForOutput).toBe(8192)
+ expect(result.availableSize).toBe(6808) // 20000 - 5000 - 8192
})
it("should handle negative or zero inputs by using positive fallbacks", () => {
const result = calculateTokenDistribution(-1000, -500)
expect(result.currentPercent).toBe(0)
- expect(result.reservedPercent).toBe(0)
+ expect(result.reservedPercent).toBe(100) // 8192 / 8192 = 100%
expect(result.availablePercent).toBe(0)
- expect(result.reservedForOutput).toBe(0) // With negative inputs, both context window and tokens become 0, so 20% of 0 is 0
- expect(result.availableSize).toBe(0)
+ expect(result.reservedForOutput).toBe(8192) // Uses ANTHROPIC_DEFAULT_MAX_TOKENS
+ expect(result.availableSize).toBe(0) // max(0, 0 - 0 - 8192) = 0
})
- it("should handle zero total tokens without division by zero errors", () => {
- const result = calculateTokenDistribution(0, 0, 0)
+ it("should handle zero context window without division by zero errors", () => {
+ const result = calculateTokenDistribution(0, 0)
expect(result.currentPercent).toBe(0)
- expect(result.reservedPercent).toBe(0)
+ expect(result.reservedPercent).toBe(100) // When contextWindow is 0, reserved gets 100%
expect(result.availablePercent).toBe(0)
- expect(result.reservedForOutput).toBe(0)
+ expect(result.reservedForOutput).toBe(8192) // Uses ANTHROPIC_DEFAULT_MAX_TOKENS when no maxTokens provided
expect(result.availableSize).toBe(0)
})
})
diff --git a/webview-ui/src/utils/model-utils.ts b/webview-ui/src/utils/model-utils.ts
index 269f9865fb..6ac31f5f11 100644
--- a/webview-ui/src/utils/model-utils.ts
+++ b/webview-ui/src/utils/model-utils.ts
@@ -1,3 +1,5 @@
+import { ANTHROPIC_DEFAULT_MAX_TOKENS } from "@roo-code/types"
+
/**
* Result of token distribution calculation
*/
@@ -34,7 +36,7 @@ export interface TokenDistributionResult {
*
* @param contextWindow The total size of the context window
* @param contextTokens The number of tokens currently used
- * @param maxTokens Optional override for tokens reserved for model output (otherwise uses 20% of window)
+ * @param maxTokens Optional override for tokens reserved for model output (otherwise uses 8192)
* @returns Distribution of tokens with percentages and raw numbers
*/
export const calculateTokenDistribution = (
@@ -47,9 +49,9 @@ export const calculateTokenDistribution = (
const safeContextTokens = Math.max(0, contextTokens)
// Get the actual max tokens value from the model
- // If maxTokens is valid, use it, otherwise reserve 20% of the context window as a default
+ // If maxTokens is valid (positive and not equal to context window), use it, otherwise reserve 8192 tokens as a default
const reservedForOutput =
- maxTokens && maxTokens > 0 && maxTokens !== safeContextWindow ? maxTokens : Math.ceil(safeContextWindow * 0.2)
+ maxTokens && maxTokens > 0 && maxTokens !== safeContextWindow ? maxTokens : ANTHROPIC_DEFAULT_MAX_TOKENS
// Calculate sizes directly without buffer display
const availableSize = Math.max(0, safeContextWindow - safeContextTokens - reservedForOutput)