diff --git a/.changeset/curly-states-see.md b/.changeset/curly-states-see.md
deleted file mode 100644
index 0d1ff62117..0000000000
--- a/.changeset/curly-states-see.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"roo-cline": patch
----
-
-Close the browsertool properly when a remote browser is configured but a fallback local one is used
diff --git a/CHANGELOG.md b/CHANGELOG.md
index daee785b6d..6d0265bef8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,20 @@
# Roo Code Changelog
+## [3.21.5] - 2025-06-23
+
+- Fix Qdrant URL prefix handling for QdrantClient initialization (thanks @CW-B-W!)
+- Improve LM Studio model detection to show all downloaded models (thanks @daniel-lxs!)
+- Resolve Claude Code provider JSON parsing and reasoning block display
+
+## [3.21.4] - 2025-06-23
+
+- Fix start line not working in multiple apply diff (thanks @samhvw8!)
+- Resolve diff editor issues with markdown preview associations (thanks @daniel-lxs!)
+- Resolve URL port handling bug for HTTPS URLs in Qdrant (thanks @benashby!)
+- Mark unused Ollama schema properties as optional (thanks @daniel-lxs!)
+- Close the local browser when used as fallback for remote (thanks @markijbema!)
+- Add Claude Code provider for local CLI integration (thanks @BarreiroT!)
+
## [3.21.3] - 2025-06-21
- Add profile-specific context condensing thresholds (thanks @SannidhyaSah!)
diff --git a/README.md b/README.md
index e374ea9c3d..f936ac6bc8 100644
--- a/README.md
+++ b/README.md
@@ -176,40 +176,40 @@ Thanks to all our contributors who have helped make Roo Code better!
-| 
mrubens | 
saoudrizwan | 
cte | 
samhvw8 | 
daniel-lxs | 
hannesrudolph |
-| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
-| 
KJ7LNW | 
a8trejo | 
ColemanRoo | 
canrobins13 | 
stea9499 | 
joemanley201 |
-| 
System233 | 
jquanton | 
nissa-seru | 
NyxJae | 
jr | 
MuriloFP |
-| 
elianiva | 
d-oit | 
punkpeye | 
wkordalski | 
sachasayan | 
Smartsheet-JB-Brown |
-| 
monotykamary | 
cannuri | 
xyOz-dev | 
feifei325 | 
zhangtony239 | 
qdaxb |
-| 
shariqriazz | 
pugazhendhi-m | 
vigneshsubbiah16 | 
lloydchang | 
dtrugman | 
Szpadel |
-| 
chrarnoldus | 
diarmidmackenzie | 
olweraltuve | 
psv2522 | 
Premshay | 
lupuletic |
-| 
kiwina | 
aheizi | 
PeterDaveHello | 
afshawnlotfi | 
RaySinner | 
nbihan-mediware |
-| 
ChuKhaLi | 
hassoncs | 
emshvac | 
kyle-apex | 
noritaka1166 | 
pdecat |
-| 
SannidhyaSah | 
StevenTCramer | 
Lunchb0ne | 
SmartManoj | 
vagadiya | 
slytechnical |
-| 
dleffel | 
arthurauffray | 
upamune | 
NamesMT | 
taylorwilsdon | 
sammcj |
-| 
Ruakij | 
p12tic | 
gtaylor | 
aitoroses | 
mr-ryan-james | 
heyseth |
-| 
taisukeoe | 
avtc | 
dlab-anton | 
eonghk | 
kcwhite | 
ronyblum |
-| 
teddyOOXX | 
vincentsong | 
yongjer | 
zeozeozeo | 
ashktn | 
franekp |
-| 
yt3trees | 
benzntech | 
axkirillov | 
anton-otee | 
bramburn | 
olearycrew |
-| 
snoyiatk | 
GitlyHallows | 
jcbdev | 
Chenjiayuan195 | 
julionav | 
SplittyDev |
-| 
mdp | 
napter | 
ross | 
philfung | 
dairui1 | 
dqroid |
-| 
forestyoo | 
GOODBOY008 | 
hatsu38 | 
hongzio | 
im47cn | 
shoopapa |
-| 
jwcraig | 
kinandan | 
nevermorec | 
bannzai | 
axmo | 
asychin |
-| 
amittell | 
Yoshino-Yukitaro | 
Yikai-Liao | 
zxdvd | 
vladstudio | 
tmsjngx0 |
-| 
tgfjt | 
PretzelVector | 
zetaloop | 
cdlliuy | 
user202729 | 
student20880 |
-| 
shohei-ihaya | 
shaybc | 
seedlord | 
samir-nimbly | 
robertheadley | 
refactorthis |
-| 
qingyuan1109 | 
pokutuna | 
philipnext | 
village-way | 
oprstchn | 
nobu007 |
-| 
mosleyit | 
moqimoqidea | 
mlopezr | 
mecab | 
olup | 
lightrabbit |
-| 
kohii | 
linegel | 
edwin-truthsearch-io | 
EamonNerbonne | 
dbasclpy | 
dflatline |
-| 
Deon588 | 
dleen | 
devxpain | 
chadgauth | 
brunobergher | 
thecolorblue |
-| 
bogdan0083 | 
Atlogit | 
atlasgong | 
andreastempsch | 
alasano | 
QuinsZouls |
-| 
HadesArchitect | 
alarno | 
nexon33 | 
adilhafeez | 
adamwlarson | 
adamhill |
-| 
AMHesch | 
maekawataiki | 
AlexandruSmirnov | 
samsilveira | 
01Rian | 
RSO |
-| 
SECKainersdorfer | 
R-omk | 
Sarke | 
kvokka | 
ecmasx | 
mollux |
-| 
marvijo-code | 
mamertofabian | 
monkeyDluffy6017 | 
libertyteeth | 
shtse8 | 
Rexarrior |
-| 
KanTakahiro | 
ksze | 
Jdo300 | 
hesara | 
DeXtroTip | 
pfitz |
-| 
celestial-vault | | | | | |
+| 
mrubens | 
saoudrizwan | 
cte | 
samhvw8 | 
daniel-lxs | 
hannesrudolph |
+| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
+| 
KJ7LNW | 
a8trejo | 
ColemanRoo | 
canrobins13 | 
stea9499 | 
joemanley201 |
+| 
System233 | 
jquanton | 
nissa-seru | 
NyxJae | 
jr | 
MuriloFP |
+| 
elianiva | 
d-oit | 
punkpeye | 
wkordalski | 
sachasayan | 
Smartsheet-JB-Brown |
+| 
monotykamary | 
cannuri | 
xyOz-dev | 
feifei325 | 
zhangtony239 | 
qdaxb |
+| 
shariqriazz | 
pugazhendhi-m | 
vigneshsubbiah16 | 
lloydchang | 
dtrugman | 
Szpadel |
+| 
chrarnoldus | 
diarmidmackenzie | 
olweraltuve | 
psv2522 | 
Premshay | 
lupuletic |
+| 
kiwina | 
aheizi | 
PeterDaveHello | 
afshawnlotfi | 
RaySinner | 
nbihan-mediware |
+| 
ChuKhaLi | 
hassoncs | 
emshvac | 
kyle-apex | 
noritaka1166 | 
pdecat |
+| 
SannidhyaSah | 
StevenTCramer | 
Lunchb0ne | 
SmartManoj | 
vagadiya | 
slytechnical |
+| 
dleffel | 
arthurauffray | 
upamune | 
NamesMT | 
taylorwilsdon | 
sammcj |
+| 
Ruakij | 
p12tic | 
gtaylor | 
aitoroses | 
mr-ryan-james | 
heyseth |
+| 
taisukeoe | 
avtc | 
dlab-anton | 
eonghk | 
kcwhite | 
ronyblum |
+| 
teddyOOXX | 
vincentsong | 
yongjer | 
zeozeozeo | 
ashktn | 
franekp |
+| 
yt3trees | 
anton-otee | 
benzntech | 
axkirillov | 
bramburn | 
olearycrew |
+| 
snoyiatk | 
GitlyHallows | 
ross | 
philfung | 
napter | 
mdp |
+| 
SplittyDev | 
jcbdev | 
julionav | 
Chenjiayuan195 | 
kinandan | 
jwcraig |
+| 
shoopapa | 
im47cn | 
hongzio | 
hatsu38 | 
GOODBOY008 | 
forestyoo |
+| 
dqroid | 
dairui1 | 
bannzai | 
axmo | 
asychin | 
amittell |
+| 
Yoshino-Yukitaro | 
Yikai-Liao | 
zxdvd | 
vladstudio | 
tmsjngx0 | 
tgfjt |
+| 
maekawataiki | 
nevermorec | 
PretzelVector | 
zetaloop | 
cdlliuy | 
user202729 |
+| 
student20880 | 
shohei-ihaya | 
shaybc | 
seedlord | 
samir-nimbly | 
robertheadley |
+| 
refactorthis | 
qingyuan1109 | 
pokutuna | 
philipnext | 
village-way | 
oprstchn |
+| 
nobu007 | 
mosleyit | 
moqimoqidea | 
mlopezr | 
mecab | 
olup |
+| 
lightrabbit | 
kohii | 
AlexandruSmirnov | 
edwin-truthsearch-io | 
EamonNerbonne | 
dbasclpy |
+| 
dflatline | 
Deon588 | 
dleen | 
devxpain | 
chadgauth | 
brunobergher |
+| 
thecolorblue | 
bogdan0083 | 
benashby | 
Atlogit | 
atlasgong | 
andreastempsch |
+| 
alasano | 
QuinsZouls | 
HadesArchitect | 
alarno | 
nexon33 | 
adilhafeez |
+| 
adamwlarson | 
adamhill | 
AMHesch | 
samsilveira | 
01Rian | 
RSO |
+| 
SECKainersdorfer | 
R-omk | 
Sarke | 
kvokka | 
ecmasx | 
mollux |
+| 
marvijo-code | 
markijbema | 
mamertofabian | 
monkeyDluffy6017 | 
libertyteeth | 
shtse8 |
+| 
Rexarrior | 
KanTakahiro | 
ksze | 
Jdo300 | 
hesara | 
DeXtroTip |
+| 
pfitz | 
celestial-vault | 
linegel | | | |
diff --git a/apps/vscode-e2e/src/suite/tools/use-mcp-tool.test.ts b/apps/vscode-e2e/src/suite/tools/use-mcp-tool.test.ts
index df57ae88c6..759033ae35 100644
--- a/apps/vscode-e2e/src/suite/tools/use-mcp-tool.test.ts
+++ b/apps/vscode-e2e/src/suite/tools/use-mcp-tool.test.ts
@@ -767,7 +767,7 @@ suite("Roo Code use_mcp_tool Tool", function () {
}
})
- test("Should validate MCP request message format and complete successfully", async function () {
+ test.skip("Should validate MCP request message format and complete successfully", async function () {
const api = globalThis.api
const messages: ClineMessage[] = []
let _taskCompleted = false
diff --git a/locales/ca/README.md b/locales/ca/README.md
index c653f54fbb..871c295cac 100644
--- a/locales/ca/README.md
+++ b/locales/ca/README.md
@@ -196,25 +196,25 @@ Gràcies a tots els nostres col·laboradors que han ajudat a millorar Roo Code!
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## Llicència
diff --git a/locales/de/README.md b/locales/de/README.md
index 24f1e4d69e..c5b19d46af 100644
--- a/locales/de/README.md
+++ b/locales/de/README.md
@@ -196,25 +196,25 @@ Danke an alle unsere Mitwirkenden, die geholfen haben, Roo Code zu verbessern!
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## Lizenz
diff --git a/locales/es/README.md b/locales/es/README.md
index adeca0a876..efd25ae17d 100644
--- a/locales/es/README.md
+++ b/locales/es/README.md
@@ -196,25 +196,25 @@ Usamos [changesets](https://github.com/changesets/changesets) para versionar y p
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## Licencia
diff --git a/locales/fr/README.md b/locales/fr/README.md
index 80140b85fb..893e73cfa0 100644
--- a/locales/fr/README.md
+++ b/locales/fr/README.md
@@ -196,25 +196,25 @@ Merci à tous nos contributeurs qui ont aidé à améliorer Roo Code !
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## Licence
diff --git a/locales/hi/README.md b/locales/hi/README.md
index 9f20242d89..3b99b0d1bd 100644
--- a/locales/hi/README.md
+++ b/locales/hi/README.md
@@ -196,25 +196,25 @@ Roo Code को बेहतर बनाने में मदद करने
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## लाइसेंस
diff --git a/locales/id/README.md b/locales/id/README.md
index 3381b865b0..dc37028884 100644
--- a/locales/id/README.md
+++ b/locales/id/README.md
@@ -190,25 +190,25 @@ Terima kasih kepada semua kontributor kami yang telah membantu membuat Roo Code
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## License
diff --git a/locales/it/README.md b/locales/it/README.md
index 964db4ff34..e69005f1ca 100644
--- a/locales/it/README.md
+++ b/locales/it/README.md
@@ -196,25 +196,25 @@ Grazie a tutti i nostri contributori che hanno aiutato a migliorare Roo Code!
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## Licenza
diff --git a/locales/ja/README.md b/locales/ja/README.md
index 90c32409fc..4cabfc4a37 100644
--- a/locales/ja/README.md
+++ b/locales/ja/README.md
@@ -196,25 +196,25 @@ Roo Codeの改善に貢献してくれたすべての貢献者に感謝します
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## ライセンス
diff --git a/locales/ko/README.md b/locales/ko/README.md
index dce892ffb9..c86eb7d3cb 100644
--- a/locales/ko/README.md
+++ b/locales/ko/README.md
@@ -196,25 +196,25 @@ Roo Code를 더 좋게 만드는 데 도움을 준 모든 기여자에게 감사
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## 라이선스
diff --git a/locales/nl/README.md b/locales/nl/README.md
index 7ca8251e73..0ccca95ceb 100644
--- a/locales/nl/README.md
+++ b/locales/nl/README.md
@@ -196,25 +196,25 @@ Dank aan alle bijdragers die Roo Code beter hebben gemaakt!
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## Licentie
diff --git a/locales/pl/README.md b/locales/pl/README.md
index 351d755a29..608fd86170 100644
--- a/locales/pl/README.md
+++ b/locales/pl/README.md
@@ -196,25 +196,25 @@ Dziękujemy wszystkim naszym współtwórcom, którzy pomogli ulepszyć Roo Code
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## Licencja
diff --git a/locales/pt-BR/README.md b/locales/pt-BR/README.md
index d773d8fcca..e75746682a 100644
--- a/locales/pt-BR/README.md
+++ b/locales/pt-BR/README.md
@@ -196,25 +196,25 @@ Obrigado a todos os nossos contribuidores que ajudaram a tornar o Roo Code melho
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## Licença
diff --git a/locales/ru/README.md b/locales/ru/README.md
index 368a70a986..fba6d2193a 100644
--- a/locales/ru/README.md
+++ b/locales/ru/README.md
@@ -196,25 +196,25 @@ code --install-extension bin/roo-cline-.vsix
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## Лицензия
diff --git a/locales/tr/README.md b/locales/tr/README.md
index 6a039e79b1..a9cb0b5153 100644
--- a/locales/tr/README.md
+++ b/locales/tr/README.md
@@ -196,25 +196,25 @@ Roo Code'u daha iyi hale getirmeye yardımcı olan tüm katkıda bulunanlara te
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## Lisans
diff --git a/locales/vi/README.md b/locales/vi/README.md
index 2e59bb759f..dceb7c4de1 100644
--- a/locales/vi/README.md
+++ b/locales/vi/README.md
@@ -196,25 +196,25 @@ Cảm ơn tất cả những người đóng góp đã giúp cải thiện Roo C
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## Giấy Phép
diff --git a/locales/zh-CN/README.md b/locales/zh-CN/README.md
index dc8b338941..d2303ef31e 100644
--- a/locales/zh-CN/README.md
+++ b/locales/zh-CN/README.md
@@ -196,25 +196,25 @@ code --install-extension bin/roo-cline-.vsix
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## 许可证
diff --git a/locales/zh-TW/README.md b/locales/zh-TW/README.md
index 85dfce876b..8e709bacb2 100644
--- a/locales/zh-TW/README.md
+++ b/locales/zh-TW/README.md
@@ -197,25 +197,25 @@ code --install-extension bin/roo-cline-.vsix
|
Ruakij|
p12tic|
gtaylor|
aitoroses|
mr-ryan-james|
heyseth|
|
taisukeoe|
avtc|
dlab-anton|
eonghk|
kcwhite|
ronyblum|
|
teddyOOXX|
vincentsong|
yongjer|
zeozeozeo|
ashktn|
franekp|
-|
yt3trees|
benzntech|
axkirillov|
anton-otee|
bramburn|
olearycrew|
-|
snoyiatk|
GitlyHallows|
jcbdev|
Chenjiayuan195|
julionav|
SplittyDev|
-|
mdp|
napter|
ross|
philfung|
dairui1|
dqroid|
-|
forestyoo|
GOODBOY008|
hatsu38|
hongzio|
im47cn|
shoopapa|
-|
jwcraig|
kinandan|
nevermorec|
bannzai|
axmo|
asychin|
-|
amittell|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
-|
tgfjt|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
student20880|
-|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
refactorthis|
-|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
nobu007|
-|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
lightrabbit|
-|
kohii|
linegel|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
dflatline|
-|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
thecolorblue|
-|
bogdan0083|
Atlogit|
atlasgong|
andreastempsch|
alasano|
QuinsZouls|
-|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
adamwlarson|
adamhill|
-|
AMHesch|
maekawataiki|
AlexandruSmirnov|
samsilveira|
01Rian|
RSO|
+|
yt3trees|
anton-otee|
benzntech|
axkirillov|
bramburn|
olearycrew|
+|
snoyiatk|
GitlyHallows|
ross|
philfung|
napter|
mdp|
+|
SplittyDev|
jcbdev|
julionav|
Chenjiayuan195|
kinandan|
jwcraig|
+|
shoopapa|
im47cn|
hongzio|
hatsu38|
GOODBOY008|
forestyoo|
+|
dqroid|
dairui1|
bannzai|
axmo|
asychin|
amittell|
+|
Yoshino-Yukitaro|
Yikai-Liao|
zxdvd|
vladstudio|
tmsjngx0|
tgfjt|
+|
maekawataiki|
nevermorec|
PretzelVector|
zetaloop|
cdlliuy|
user202729|
+|
student20880|
shohei-ihaya|
shaybc|
seedlord|
samir-nimbly|
robertheadley|
+|
refactorthis|
qingyuan1109|
pokutuna|
philipnext|
village-way|
oprstchn|
+|
nobu007|
mosleyit|
moqimoqidea|
mlopezr|
mecab|
olup|
+|
lightrabbit|
kohii|
AlexandruSmirnov|
edwin-truthsearch-io|
EamonNerbonne|
dbasclpy|
+|
dflatline|
Deon588|
dleen|
devxpain|
chadgauth|
brunobergher|
+|
thecolorblue|
bogdan0083|
benashby|
Atlogit|
atlasgong|
andreastempsch|
+|
alasano|
QuinsZouls|
HadesArchitect|
alarno|
nexon33|
adilhafeez|
+|
adamwlarson|
adamhill|
AMHesch|
samsilveira|
01Rian|
RSO|
|
SECKainersdorfer|
R-omk|
Sarke|
kvokka|
ecmasx|
mollux|
-|
marvijo-code|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
Rexarrior|
-|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
pfitz|
-|
celestial-vault| | | | | |
+|
marvijo-code|
markijbema|
mamertofabian|
monkeyDluffy6017|
libertyteeth|
shtse8|
+|
Rexarrior|
KanTakahiro|
ksze|
Jdo300|
hesara|
DeXtroTip|
+|
pfitz|
celestial-vault|
linegel| | | |
## 授權
diff --git a/packages/cloud/src/AuthService.ts b/packages/cloud/src/AuthService.ts
index f64007f0d2..a02bfcc298 100644
--- a/packages/cloud/src/AuthService.ts
+++ b/packages/cloud/src/AuthService.ts
@@ -21,6 +21,7 @@ export interface AuthServiceEvents {
const authCredentialsSchema = z.object({
clientToken: z.string().min(1, "Client token cannot be empty"),
sessionId: z.string().min(1, "Session ID cannot be empty"),
+ organizationId: z.string().nullable().optional(),
})
type AuthCredentials = z.infer
@@ -220,7 +221,16 @@ export class AuthService extends EventEmitter {
try {
const parsedJson = JSON.parse(credentialsJson)
- return authCredentialsSchema.parse(parsedJson)
+ const credentials = authCredentialsSchema.parse(parsedJson)
+
+ // Migration: If no organizationId but we have userInfo, add it
+ if (credentials.organizationId === undefined && this.userInfo?.organizationId) {
+ credentials.organizationId = this.userInfo.organizationId
+ await this.storeCredentials(credentials)
+ this.log("[auth] Migrated credentials with organizationId")
+ }
+
+ return credentials
} catch (error) {
if (error instanceof z.ZodError) {
this.log("[auth] Invalid credentials format:", error.errors)
@@ -269,8 +279,13 @@ export class AuthService extends EventEmitter {
*
* @param code The authorization code from the callback
* @param state The state parameter from the callback
+ * @param organizationId The organization ID from the callback (null for personal accounts)
*/
- public async handleCallback(code: string | null, state: string | null): Promise {
+ public async handleCallback(
+ code: string | null,
+ state: string | null,
+ organizationId?: string | null,
+ ): Promise {
if (!code || !state) {
vscode.window.showInformationMessage("Invalid Roo Code Cloud sign in url")
return
@@ -287,6 +302,9 @@ export class AuthService extends EventEmitter {
const credentials = await this.clerkSignIn(code)
+ // Set organizationId (null for personal accounts)
+ credentials.organizationId = organizationId || null
+
await this.storeCredentials(credentials)
vscode.window.showInformationMessage("Successfully authenticated with Roo Code Cloud")
@@ -417,6 +435,15 @@ export class AuthService extends EventEmitter {
return this.userInfo
}
+ /**
+ * Get the stored organization ID from credentials
+ *
+ * @returns The stored organization ID, null for personal accounts or if no credentials exist
+ */
+ public getStoredOrganizationId(): string | null {
+ return this.credentials?.organizationId || null
+ }
+
private async clerkSignIn(ticket: string): Promise {
const formData = new URLSearchParams()
formData.append("strategy", "ticket")
@@ -454,6 +481,17 @@ export class AuthService extends EventEmitter {
const formData = new URLSearchParams()
formData.append("_is_native", "1")
+ // Handle 3 cases for organization_id:
+ // 1. Have an org id: organization_id=THE_ORG_ID
+ // 2. Have a personal account: organization_id= (empty string)
+ // 3. Don't know if you have an org id (old style credentials): don't send organization_id param at all
+ const organizationId = this.getStoredOrganizationId()
+ if (this.credentials?.organizationId !== undefined) {
+ // We have organization context info (either org id or personal account)
+ formData.append("organization_id", organizationId || "")
+ }
+ // If organizationId is undefined, don't send the param at all (old credentials)
+
const response = await fetch(`${getClerkBaseUrl()}/v1/client/sessions/${this.credentials!.sessionId}/tokens`, {
method: "POST",
headers: {
@@ -505,29 +543,74 @@ export class AuthService extends EventEmitter {
userInfo.picture = userData.image_url
- // Fetch organization memberships separately
+ // Fetch organization info if user is in organization context
try {
- const orgMemberships = await this.clerkGetOrganizationMemberships()
- if (orgMemberships && orgMemberships.length > 0) {
- // Get the first (or active) organization membership
- const primaryOrgMembership = orgMemberships[0]
- const organization = primaryOrgMembership?.organization
+ const storedOrgId = this.getStoredOrganizationId()
- if (organization) {
- userInfo.organizationId = organization.id
- userInfo.organizationName = organization.name
- userInfo.organizationRole = primaryOrgMembership.role
- userInfo.organizationImageUrl = organization.image_url
+ if (this.credentials?.organizationId !== undefined) {
+ // We have organization context info
+ if (storedOrgId !== null) {
+ // User is in organization context - fetch user's memberships and filter
+ const orgMemberships = await this.clerkGetOrganizationMemberships()
+ const userMembership = this.findOrganizationMembership(orgMemberships, storedOrgId)
+
+ if (userMembership) {
+ this.setUserOrganizationInfo(userInfo, userMembership)
+ this.log("[auth] User in organization context:", {
+ id: userMembership.organization.id,
+ name: userMembership.organization.name,
+ role: userMembership.role,
+ })
+ } else {
+ this.log("[auth] Warning: User not found in stored organization:", storedOrgId)
+ }
+ } else {
+ this.log("[auth] User in personal account context - not setting organization info")
+ }
+ } else {
+ // Old credentials without organization context - fetch organization info to determine context
+ const orgMemberships = await this.clerkGetOrganizationMemberships()
+ const primaryOrgMembership = this.findPrimaryOrganizationMembership(orgMemberships)
+
+ if (primaryOrgMembership) {
+ this.setUserOrganizationInfo(userInfo, primaryOrgMembership)
+ this.log("[auth] Legacy credentials: Found organization membership:", {
+ id: primaryOrgMembership.organization.id,
+ name: primaryOrgMembership.organization.name,
+ role: primaryOrgMembership.role,
+ })
+ } else {
+ this.log("[auth] Legacy credentials: No organization memberships found")
}
}
} catch (error) {
- this.log("[auth] Failed to fetch organization memberships:", error)
+ this.log("[auth] Failed to fetch organization info:", error)
// Don't throw - organization info is optional
}
return userInfo
}
+ private findOrganizationMembership(
+ memberships: CloudOrganizationMembership[],
+ organizationId: string,
+ ): CloudOrganizationMembership | undefined {
+ return memberships?.find((membership) => membership.organization.id === organizationId)
+ }
+
+ private findPrimaryOrganizationMembership(
+ memberships: CloudOrganizationMembership[],
+ ): CloudOrganizationMembership | undefined {
+ return memberships && memberships.length > 0 ? memberships[0] : undefined
+ }
+
+ private setUserOrganizationInfo(userInfo: CloudUserInfo, membership: CloudOrganizationMembership): void {
+ userInfo.organizationId = membership.organization.id
+ userInfo.organizationName = membership.organization.name
+ userInfo.organizationRole = membership.role
+ userInfo.organizationImageUrl = membership.organization.image_url
+ }
+
private async clerkGetOrganizationMemberships(): Promise {
const response = await fetch(`${getClerkBaseUrl()}/v1/me/organization_memberships`, {
headers: {
diff --git a/packages/cloud/src/CloudService.ts b/packages/cloud/src/CloudService.ts
index c53538f1bc..2ac4a8ca41 100644
--- a/packages/cloud/src/CloudService.ts
+++ b/packages/cloud/src/CloudService.ts
@@ -46,8 +46,11 @@ export class CloudService {
this.authService.on("logged-out", this.authListener)
this.authService.on("user-info", this.authListener)
- this.settingsService = new SettingsService(this.context, this.authService, () =>
- this.callbacks.stateChanged?.(),
+ this.settingsService = new SettingsService(
+ this.context,
+ this.authService,
+ () => this.callbacks.stateChanged?.(),
+ this.log,
)
this.settingsService.initialize()
@@ -118,14 +121,28 @@ export class CloudService {
return userInfo?.organizationRole || null
}
+ public hasStoredOrganizationId(): boolean {
+ this.ensureInitialized()
+ return this.authService!.getStoredOrganizationId() !== null
+ }
+
+ public getStoredOrganizationId(): string | null {
+ this.ensureInitialized()
+ return this.authService!.getStoredOrganizationId()
+ }
+
public getAuthState(): string {
this.ensureInitialized()
return this.authService!.getState()
}
- public async handleAuthCallback(code: string | null, state: string | null): Promise {
+ public async handleAuthCallback(
+ code: string | null,
+ state: string | null,
+ organizationId?: string | null,
+ ): Promise {
this.ensureInitialized()
- return this.authService!.handleCallback(code, state)
+ return this.authService!.handleCallback(code, state, organizationId)
}
// SettingsService
diff --git a/packages/cloud/src/SettingsService.ts b/packages/cloud/src/SettingsService.ts
index 3ee56000e8..68c6f2fe48 100644
--- a/packages/cloud/src/SettingsService.ts
+++ b/packages/cloud/src/SettingsService.ts
@@ -18,15 +18,21 @@ export class SettingsService {
private authService: AuthService
private settings: OrganizationSettings | undefined = undefined
private timer: RefreshTimer
+ private log: (...args: unknown[]) => void
- constructor(context: vscode.ExtensionContext, authService: AuthService, callback: () => void) {
+ constructor(
+ context: vscode.ExtensionContext,
+ authService: AuthService,
+ callback: () => void,
+ log?: (...args: unknown[]) => void,
+ ) {
this.context = context
this.authService = authService
+ this.log = log || console.log
this.timer = new RefreshTimer({
callback: async () => {
- await this.fetchSettings(callback)
- return true
+ return await this.fetchSettings(callback)
},
successInterval: 30000,
initialBackoffMs: 1000,
@@ -42,10 +48,6 @@ export class SettingsService {
this.removeSettings()
}
- this.authService.on("attempting-session", () => {
- this.timer.start()
- })
-
this.authService.on("active-session", () => {
this.timer.start()
})
@@ -55,16 +57,16 @@ export class SettingsService {
this.removeSettings()
})
- if (this.authService.hasOrIsAcquiringActiveSession()) {
+ if (this.authService.hasActiveSession()) {
this.timer.start()
}
}
- private async fetchSettings(callback: () => void): Promise {
+ private async fetchSettings(callback: () => void): Promise {
const token = this.authService.getSessionToken()
if (!token) {
- return
+ return false
}
try {
@@ -75,16 +77,20 @@ export class SettingsService {
})
if (!response.ok) {
- console.error(`Failed to fetch organization settings: ${response.status} ${response.statusText}`)
- return
+ this.log(
+ "[cloud-settings] Failed to fetch organization settings:",
+ response.status,
+ response.statusText,
+ )
+ return false
}
const data = await response.json()
const result = organizationSettingsSchema.safeParse(data)
if (!result.success) {
- console.error("Invalid organization settings format:", result.error)
- return
+ this.log("[cloud-settings] Invalid organization settings format:", result.error)
+ return false
}
const newSettings = result.data
@@ -94,8 +100,11 @@ export class SettingsService {
await this.cacheSettings()
callback()
}
+
+ return true
} catch (error) {
- console.error("Error fetching organization settings:", error)
+ this.log("[cloud-settings] Error fetching organization settings:", error)
+ return false
}
}
diff --git a/packages/cloud/src/__tests__/AuthService.spec.ts b/packages/cloud/src/__tests__/AuthService.spec.ts
index f4d4e98510..944bcd2b24 100644
--- a/packages/cloud/src/__tests__/AuthService.spec.ts
+++ b/packages/cloud/src/__tests__/AuthService.spec.ts
@@ -328,7 +328,7 @@ describe("AuthService", () => {
expect(mockContext.secrets.store).toHaveBeenCalledWith(
"clerk-auth-credentials",
- JSON.stringify({ clientToken: "Bearer token-123", sessionId: "session-123" }),
+ JSON.stringify({ clientToken: "Bearer token-123", sessionId: "session-123", organizationId: null }),
)
expect(mockShowInfo).toHaveBeenCalledWith("Successfully authenticated with Roo Code Cloud")
})
@@ -633,9 +633,55 @@ describe("AuthService", () => {
expect(authService.getUserInfo()).toBeNull()
})
- it("should parse user info correctly", async () => {
- // Set up with credentials
- const credentials = { clientToken: "test-token", sessionId: "test-session" }
+ it("should parse user info correctly for personal accounts", async () => {
+ // Set up with credentials for personal account (no organizationId)
+ const credentials = { clientToken: "test-token", sessionId: "test-session", organizationId: null }
+ mockContext.secrets.get.mockResolvedValue(JSON.stringify(credentials))
+ await authService.initialize()
+
+ // Clear previous mock calls
+ mockFetch.mockClear()
+
+ // Mock successful responses
+ mockFetch
+ .mockResolvedValueOnce({
+ ok: true,
+ json: () => Promise.resolve({ jwt: "jwt-token" }),
+ })
+ .mockResolvedValueOnce({
+ ok: true,
+ json: () =>
+ Promise.resolve({
+ response: {
+ first_name: "Jane",
+ last_name: "Smith",
+ image_url: "https://example.com/jane.jpg",
+ primary_email_address_id: "email-2",
+ email_addresses: [
+ { id: "email-1", email_address: "jane.old@example.com" },
+ { id: "email-2", email_address: "jane@example.com" },
+ ],
+ },
+ }),
+ })
+
+ const timerCallback = vi.mocked(RefreshTimer).mock.calls[0][0].callback
+ await timerCallback()
+
+ // Wait for async operations to complete
+ await new Promise((resolve) => setTimeout(resolve, 0))
+
+ const userInfo = authService.getUserInfo()
+ expect(userInfo).toEqual({
+ name: "Jane Smith",
+ email: "jane@example.com",
+ picture: "https://example.com/jane.jpg",
+ })
+ })
+
+ it("should parse user info correctly for organization accounts", async () => {
+ // Set up with credentials for organization account
+ const credentials = { clientToken: "test-token", sessionId: "test-session", organizationId: "org_1" }
mockContext.secrets.get.mockResolvedValue(JSON.stringify(credentials))
await authService.initialize()
@@ -699,8 +745,8 @@ describe("AuthService", () => {
})
it("should handle missing user info fields", async () => {
- // Set up with credentials
- const credentials = { clientToken: "test-token", sessionId: "test-session" }
+ // Set up with credentials for personal account (no organizationId)
+ const credentials = { clientToken: "test-token", sessionId: "test-session", organizationId: null }
mockContext.secrets.get.mockResolvedValue(JSON.stringify(credentials))
await authService.initialize()
diff --git a/packages/cloud/src/__tests__/CloudService.test.ts b/packages/cloud/src/__tests__/CloudService.test.ts
index c7dc07fcae..869def5945 100644
--- a/packages/cloud/src/__tests__/CloudService.test.ts
+++ b/packages/cloud/src/__tests__/CloudService.test.ts
@@ -40,6 +40,7 @@ describe("CloudService", () => {
getState: ReturnType
getSessionToken: ReturnType
handleCallback: ReturnType
+ getStoredOrganizationId: ReturnType
on: ReturnType
off: ReturnType
once: ReturnType
@@ -88,6 +89,7 @@ describe("CloudService", () => {
getState: vi.fn().mockReturnValue("logged-out"),
getSessionToken: vi.fn(),
handleCallback: vi.fn(),
+ getStoredOrganizationId: vi.fn().mockReturnValue(null),
on: vi.fn(),
off: vi.fn(),
once: vi.fn(),
@@ -133,7 +135,12 @@ describe("CloudService", () => {
expect(cloudService).toBeInstanceOf(CloudService)
expect(AuthService).toHaveBeenCalledWith(mockContext, expect.any(Function))
- expect(SettingsService).toHaveBeenCalledWith(mockContext, mockAuthService, expect.any(Function))
+ expect(SettingsService).toHaveBeenCalledWith(
+ mockContext,
+ mockAuthService,
+ expect.any(Function),
+ expect.any(Function),
+ )
})
it("should throw error if instance already exists", async () => {
@@ -255,7 +262,41 @@ describe("CloudService", () => {
it("should delegate handleAuthCallback to AuthService", async () => {
await cloudService.handleAuthCallback("code", "state")
- expect(mockAuthService.handleCallback).toHaveBeenCalledWith("code", "state")
+ expect(mockAuthService.handleCallback).toHaveBeenCalledWith("code", "state", undefined)
+ })
+
+ it("should delegate handleAuthCallback with organizationId to AuthService", async () => {
+ await cloudService.handleAuthCallback("code", "state", "org_123")
+ expect(mockAuthService.handleCallback).toHaveBeenCalledWith("code", "state", "org_123")
+ })
+
+ it("should return stored organization ID from AuthService", () => {
+ mockAuthService.getStoredOrganizationId.mockReturnValue("org_456")
+
+ const result = cloudService.getStoredOrganizationId()
+ expect(mockAuthService.getStoredOrganizationId).toHaveBeenCalled()
+ expect(result).toBe("org_456")
+ })
+
+ it("should return null when no stored organization ID available", () => {
+ mockAuthService.getStoredOrganizationId.mockReturnValue(null)
+
+ const result = cloudService.getStoredOrganizationId()
+ expect(result).toBe(null)
+ })
+
+ it("should return true when stored organization ID exists", () => {
+ mockAuthService.getStoredOrganizationId.mockReturnValue("org_789")
+
+ const result = cloudService.hasStoredOrganizationId()
+ expect(result).toBe(true)
+ })
+
+ it("should return false when no stored organization ID exists", () => {
+ mockAuthService.getStoredOrganizationId.mockReturnValue(null)
+
+ const result = cloudService.hasStoredOrganizationId()
+ expect(result).toBe(false)
})
})
diff --git a/packages/types/npm/package.json b/packages/types/npm/package.json
index 2e0e33876a..4c5ac24e65 100644
--- a/packages/types/npm/package.json
+++ b/packages/types/npm/package.json
@@ -1,6 +1,6 @@
{
"name": "@roo-code/types",
- "version": "1.27.0",
+ "version": "1.28.0",
"description": "TypeScript type definitions for Roo Code.",
"publishConfig": {
"access": "public",
diff --git a/packages/types/src/cloud.ts b/packages/types/src/cloud.ts
index dc5ef439dc..75ff0b08b9 100644
--- a/packages/types/src/cloud.ts
+++ b/packages/types/src/cloud.ts
@@ -125,6 +125,7 @@ export const ORGANIZATION_ALLOW_ALL: OrganizationAllowList = {
export const ORGANIZATION_DEFAULT: OrganizationSettings = {
version: 0,
cloudSettings: {
+ recordTaskMessages: true,
enableTaskSharing: true,
taskShareExpirationDays: 30,
},
diff --git a/src/activate/handleUri.ts b/src/activate/handleUri.ts
index 106bcdb311..7f0b4c64cc 100644
--- a/src/activate/handleUri.ts
+++ b/src/activate/handleUri.ts
@@ -38,7 +38,13 @@ export const handleUri = async (uri: vscode.Uri) => {
case "/auth/clerk/callback": {
const code = query.get("code")
const state = query.get("state")
- await CloudService.instance.handleAuthCallback(code, state)
+ const organizationId = query.get("organizationId")
+
+ await CloudService.instance.handleAuthCallback(
+ code,
+ state,
+ organizationId === "null" ? null : organizationId,
+ )
break
}
default:
diff --git a/src/api/providers/__tests__/claude-code.spec.ts b/src/api/providers/__tests__/claude-code.spec.ts
new file mode 100644
index 0000000000..406864f917
--- /dev/null
+++ b/src/api/providers/__tests__/claude-code.spec.ts
@@ -0,0 +1,230 @@
+import { describe, test, expect, vi, beforeEach } from "vitest"
+import { ClaudeCodeHandler } from "../claude-code"
+import { ApiHandlerOptions } from "../../../shared/api"
+
+// Mock the runClaudeCode function
+vi.mock("../../../integrations/claude-code/run", () => ({
+ runClaudeCode: vi.fn(),
+}))
+
+const { runClaudeCode } = await import("../../../integrations/claude-code/run")
+const mockRunClaudeCode = vi.mocked(runClaudeCode)
+
+// Mock the EventEmitter for the process
+class MockEventEmitter {
+ private handlers: { [event: string]: ((...args: any[]) => void)[] } = {}
+
+ on(event: string, handler: (...args: any[]) => void) {
+ if (!this.handlers[event]) {
+ this.handlers[event] = []
+ }
+ this.handlers[event].push(handler)
+ }
+
+ emit(event: string, ...args: any[]) {
+ if (this.handlers[event]) {
+ this.handlers[event].forEach((handler) => handler(...args))
+ }
+ }
+}
+
+describe("ClaudeCodeHandler", () => {
+ let handler: ClaudeCodeHandler
+ let mockProcess: any
+
+ beforeEach(() => {
+ const options: ApiHandlerOptions = {
+ claudeCodePath: "claude",
+ apiModelId: "claude-3-5-sonnet-20241022",
+ }
+ handler = new ClaudeCodeHandler(options)
+
+ const mainEmitter = new MockEventEmitter()
+ mockProcess = {
+ stdout: new MockEventEmitter(),
+ stderr: new MockEventEmitter(),
+ on: mainEmitter.on.bind(mainEmitter),
+ emit: mainEmitter.emit.bind(mainEmitter),
+ }
+
+ mockRunClaudeCode.mockReturnValue(mockProcess)
+ })
+
+ test("should handle thinking content properly", async () => {
+ const systemPrompt = "You are a helpful assistant"
+ const messages = [{ role: "user" as const, content: "Hello" }]
+
+ // Start the stream
+ const stream = handler.createMessage(systemPrompt, messages)
+ const streamGenerator = stream[Symbol.asyncIterator]()
+
+ // Simulate thinking content response
+ const thinkingResponse = {
+ type: "assistant",
+ message: {
+ id: "msg_123",
+ type: "message",
+ role: "assistant",
+ model: "claude-3-5-sonnet-20241022",
+ content: [
+ {
+ type: "thinking",
+ thinking: "I need to think about this carefully...",
+ signature: "abc123",
+ },
+ ],
+ stop_reason: null,
+ stop_sequence: null,
+ usage: {
+ input_tokens: 10,
+ output_tokens: 20,
+ service_tier: "standard" as const,
+ },
+ },
+ session_id: "session_123",
+ }
+
+ // Emit the thinking response and wait for processing
+ setImmediate(() => {
+ mockProcess.stdout.emit("data", JSON.stringify(thinkingResponse) + "\n")
+ setImmediate(() => {
+ mockProcess.emit("close", 0)
+ })
+ })
+
+ // Get the result
+ const result = await streamGenerator.next()
+
+ expect(result.done).toBe(false)
+ expect(result.value).toEqual({
+ type: "reasoning",
+ text: "I need to think about this carefully...",
+ })
+ })
+
+ test("should handle mixed content types", async () => {
+ const systemPrompt = "You are a helpful assistant"
+ const messages = [{ role: "user" as const, content: "Hello" }]
+
+ const stream = handler.createMessage(systemPrompt, messages)
+ const streamGenerator = stream[Symbol.asyncIterator]()
+
+ // Simulate mixed content response
+ const mixedResponse = {
+ type: "assistant",
+ message: {
+ id: "msg_123",
+ type: "message",
+ role: "assistant",
+ model: "claude-3-5-sonnet-20241022",
+ content: [
+ {
+ type: "thinking",
+ thinking: "Let me think about this...",
+ },
+ {
+ type: "text",
+ text: "Here's my response!",
+ },
+ ],
+ stop_reason: null,
+ stop_sequence: null,
+ usage: {
+ input_tokens: 10,
+ output_tokens: 20,
+ service_tier: "standard" as const,
+ },
+ },
+ session_id: "session_123",
+ }
+
+ // Emit the mixed response and wait for processing
+ setImmediate(() => {
+ mockProcess.stdout.emit("data", JSON.stringify(mixedResponse) + "\n")
+ setImmediate(() => {
+ mockProcess.emit("close", 0)
+ })
+ })
+
+ // Get the first result (thinking)
+ const thinkingResult = await streamGenerator.next()
+ expect(thinkingResult.done).toBe(false)
+ expect(thinkingResult.value).toEqual({
+ type: "reasoning",
+ text: "Let me think about this...",
+ })
+
+ // Get the second result (text)
+ const textResult = await streamGenerator.next()
+ expect(textResult.done).toBe(false)
+ expect(textResult.value).toEqual({
+ type: "text",
+ text: "Here's my response!",
+ })
+ })
+
+ test("should handle stop_reason with thinking content in error messages", async () => {
+ const systemPrompt = "You are a helpful assistant"
+ const messages = [{ role: "user" as const, content: "Hello" }]
+
+ const stream = handler.createMessage(systemPrompt, messages)
+ const streamGenerator = stream[Symbol.asyncIterator]()
+
+ // Simulate error response with thinking content
+ const errorResponse = {
+ type: "assistant",
+ message: {
+ id: "msg_123",
+ type: "message",
+ role: "assistant",
+ model: "claude-3-5-sonnet-20241022",
+ content: [
+ {
+ type: "thinking",
+ thinking: "This is an error scenario",
+ },
+ ],
+ stop_reason: "max_tokens",
+ stop_sequence: null,
+ usage: {
+ input_tokens: 10,
+ output_tokens: 20,
+ service_tier: "standard" as const,
+ },
+ },
+ session_id: "session_123",
+ }
+
+ // Emit the error response and wait for processing
+ setImmediate(() => {
+ mockProcess.stdout.emit("data", JSON.stringify(errorResponse) + "\n")
+ setImmediate(() => {
+ mockProcess.emit("close", 0)
+ })
+ })
+
+ // Should throw error with thinking content
+ await expect(streamGenerator.next()).rejects.toThrow("This is an error scenario")
+ })
+
+ test("should handle incomplete JSON in buffer on process close", async () => {
+ const systemPrompt = "You are a helpful assistant"
+ const messages = [{ role: "user" as const, content: "Hello" }]
+
+ const stream = handler.createMessage(systemPrompt, messages)
+ const streamGenerator = stream[Symbol.asyncIterator]()
+
+ // Simulate incomplete JSON data followed by process close
+ setImmediate(() => {
+ // Send incomplete JSON (missing closing brace)
+ mockProcess.stdout.emit("data", '{"type":"assistant","message":{"id":"msg_123"')
+ setImmediate(() => {
+ mockProcess.emit("close", 0)
+ })
+ })
+
+ // Should complete without throwing, incomplete JSON should be discarded
+ const result = await streamGenerator.next()
+ expect(result.done).toBe(true)
+ })
+})
diff --git a/src/api/providers/claude-code.ts b/src/api/providers/claude-code.ts
index f3e66604e4..a2551732e5 100644
--- a/src/api/providers/claude-code.ts
+++ b/src/api/providers/claude-code.ts
@@ -28,13 +28,21 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler {
let processError = null
let errorOutput = ""
let exitCode: number | null = null
+ let buffer = ""
claudeProcess.stdout.on("data", (data) => {
- const output = data.toString()
- const lines = output.split("\n").filter((line: string) => line.trim() !== "")
+ buffer += data.toString()
+ const lines = buffer.split("\n")
+ // Keep the last line in buffer as it might be incomplete
+ buffer = lines.pop() || ""
+
+ // Process complete lines
for (const line of lines) {
- dataQueue.push(line)
+ const trimmedLine = line.trim()
+ if (trimmedLine !== "") {
+ dataQueue.push(trimmedLine)
+ }
}
})
@@ -44,6 +52,20 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler {
claudeProcess.on("close", (code) => {
exitCode = code
+ // Process any remaining data in buffer
+ const trimmedBuffer = buffer.trim()
+ if (trimmedBuffer) {
+ // Validate that the remaining buffer looks like valid JSON before processing
+ if (this.isLikelyValidJSON(trimmedBuffer)) {
+ dataQueue.push(trimmedBuffer)
+ } else {
+ console.warn(
+ "Discarding incomplete JSON data on process close:",
+ trimmedBuffer.substring(0, 100) + (trimmedBuffer.length > 100 ? "..." : ""),
+ )
+ }
+ buffer = ""
+ }
})
claudeProcess.on("error", (error) => {
@@ -101,8 +123,9 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler {
const message = chunk.message
if (message.stop_reason !== null && message.stop_reason !== "tool_use") {
+ const firstContent = message.content[0]
const errorMessage =
- message.content[0]?.text ||
+ this.getContentText(firstContent) ||
t("common:errors.claudeCode.stoppedWithReason", { reason: message.stop_reason })
if (errorMessage.includes("Invalid model name")) {
@@ -118,8 +141,13 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler {
type: "text",
text: content.text,
}
+ } else if (content.type === "thinking") {
+ yield {
+ type: "reasoning",
+ text: content.thinking,
+ }
} else {
- console.warn("Unsupported content type:", content.type)
+ console.warn("Unsupported content type:", content)
}
}
@@ -159,12 +187,53 @@ export class ClaudeCodeHandler extends BaseProvider implements ApiHandler {
}
}
+ private getContentText(content: any): string | undefined {
+ if (!content) return undefined
+ switch (content.type) {
+ case "text":
+ return content.text
+ case "thinking":
+ return content.thinking
+ default:
+ return undefined
+ }
+ }
+
+ private isLikelyValidJSON(data: string): boolean {
+ // Basic validation to check if the data looks like it could be valid JSON
+ const trimmed = data.trim()
+ if (!trimmed) return false
+
+ // Must start and end with appropriate JSON delimiters
+ const startsCorrectly = trimmed.startsWith("{") || trimmed.startsWith("[")
+ const endsCorrectly = trimmed.endsWith("}") || trimmed.endsWith("]")
+
+ if (!startsCorrectly || !endsCorrectly) return false
+
+ // Check for balanced braces/brackets (simple heuristic)
+ let braceCount = 0
+ let bracketCount = 0
+ for (const char of trimmed) {
+ if (char === "{") braceCount++
+ else if (char === "}") braceCount--
+ else if (char === "[") bracketCount++
+ else if (char === "]") bracketCount--
+ }
+
+ return braceCount === 0 && bracketCount === 0
+ }
+
// TODO: Validate instead of parsing
private attemptParseChunk(data: string): ClaudeCodeMessage | null {
try {
return JSON.parse(data)
} catch (error) {
- console.error("Error parsing chunk:", error)
+ console.error(
+ "Error parsing chunk:",
+ error,
+ "Data:",
+ data.substring(0, 100) + (data.length > 100 ? "..." : ""),
+ )
return null
}
}
diff --git a/src/api/providers/fetchers/__tests__/lmstudio.test.ts b/src/api/providers/fetchers/__tests__/lmstudio.test.ts
index 59b4388785..98fe5db32e 100644
--- a/src/api/providers/fetchers/__tests__/lmstudio.test.ts
+++ b/src/api/providers/fetchers/__tests__/lmstudio.test.ts
@@ -1,6 +1,6 @@
import axios from "axios"
import { vi, describe, it, expect, beforeEach } from "vitest"
-import { LMStudioClient, LLM, LLMInstanceInfo } from "@lmstudio/sdk" // LLMInfo is a type
+import { LMStudioClient, LLM, LLMInstanceInfo, LLMInfo } from "@lmstudio/sdk"
import { getLMStudioModels, parseLMStudioModel } from "../lmstudio"
import { ModelInfo, lMStudioDefaultModelInfo } from "@roo-code/types" // ModelInfo is a type
@@ -11,12 +11,16 @@ const mockedAxios = axios as any
// Mock @lmstudio/sdk
const mockGetModelInfo = vi.fn()
const mockListLoaded = vi.fn()
+const mockListDownloadedModels = vi.fn()
vi.mock("@lmstudio/sdk", () => {
return {
LMStudioClient: vi.fn().mockImplementation(() => ({
llm: {
listLoaded: mockListLoaded,
},
+ system: {
+ listDownloadedModels: mockListDownloadedModels,
+ },
})),
}
})
@@ -28,6 +32,7 @@ describe("LMStudio Fetcher", () => {
MockedLMStudioClientConstructor.mockClear()
mockListLoaded.mockClear()
mockGetModelInfo.mockClear()
+ mockListDownloadedModels.mockClear()
})
describe("parseLMStudioModel", () => {
@@ -88,8 +93,40 @@ describe("LMStudio Fetcher", () => {
trainedForToolUse: false, // Added
}
- it("should fetch and parse models successfully", async () => {
+ it("should fetch downloaded models using system.listDownloadedModels", async () => {
+ const mockLLMInfo: LLMInfo = {
+ type: "llm" as const,
+ modelKey: "mistralai/devstral-small-2505",
+ format: "safetensors",
+ displayName: "Devstral Small 2505",
+ path: "mistralai/devstral-small-2505",
+ sizeBytes: 13277565112,
+ architecture: "mistral",
+ vision: false,
+ trainedForToolUse: false,
+ maxContextLength: 131072,
+ }
+
mockedAxios.get.mockResolvedValueOnce({ data: { status: "ok" } })
+ mockListDownloadedModels.mockResolvedValueOnce([mockLLMInfo])
+
+ const result = await getLMStudioModels(baseUrl)
+
+ expect(mockedAxios.get).toHaveBeenCalledTimes(1)
+ expect(mockedAxios.get).toHaveBeenCalledWith(`${baseUrl}/v1/models`)
+ expect(MockedLMStudioClientConstructor).toHaveBeenCalledTimes(1)
+ expect(MockedLMStudioClientConstructor).toHaveBeenCalledWith({ baseUrl: lmsUrl })
+ expect(mockListDownloadedModels).toHaveBeenCalledTimes(1)
+ expect(mockListDownloadedModels).toHaveBeenCalledWith("llm")
+ expect(mockListLoaded).not.toHaveBeenCalled()
+
+ const expectedParsedModel = parseLMStudioModel(mockLLMInfo)
+ expect(result).toEqual({ [mockLLMInfo.path]: expectedParsedModel })
+ })
+
+ it("should fall back to listLoaded when listDownloadedModels fails", async () => {
+ mockedAxios.get.mockResolvedValueOnce({ data: { status: "ok" } })
+ mockListDownloadedModels.mockRejectedValueOnce(new Error("Method not available"))
mockListLoaded.mockResolvedValueOnce([{ getModelInfo: mockGetModelInfo }])
mockGetModelInfo.mockResolvedValueOnce(mockRawModel)
@@ -99,6 +136,7 @@ describe("LMStudio Fetcher", () => {
expect(mockedAxios.get).toHaveBeenCalledWith(`${baseUrl}/v1/models`)
expect(MockedLMStudioClientConstructor).toHaveBeenCalledTimes(1)
expect(MockedLMStudioClientConstructor).toHaveBeenCalledWith({ baseUrl: lmsUrl })
+ expect(mockListDownloadedModels).toHaveBeenCalledTimes(1)
expect(mockListLoaded).toHaveBeenCalledTimes(1)
const expectedParsedModel = parseLMStudioModel(mockRawModel)
diff --git a/src/api/providers/fetchers/lmstudio.ts b/src/api/providers/fetchers/lmstudio.ts
index ea1a590f1e..4b7ece71ea 100644
--- a/src/api/providers/fetchers/lmstudio.ts
+++ b/src/api/providers/fetchers/lmstudio.ts
@@ -2,14 +2,17 @@ import { ModelInfo, lMStudioDefaultModelInfo } from "@roo-code/types"
import { LLM, LLMInfo, LLMInstanceInfo, LMStudioClient } from "@lmstudio/sdk"
import axios from "axios"
-export const parseLMStudioModel = (rawModel: LLMInstanceInfo): ModelInfo => {
+export const parseLMStudioModel = (rawModel: LLMInstanceInfo | LLMInfo): ModelInfo => {
+ // Handle both LLMInstanceInfo (from loaded models) and LLMInfo (from downloaded models)
+ const contextLength = "contextLength" in rawModel ? rawModel.contextLength : rawModel.maxContextLength
+
const modelInfo: ModelInfo = Object.assign({}, lMStudioDefaultModelInfo, {
description: `${rawModel.displayName} - ${rawModel.path}`,
- contextWindow: rawModel.contextLength,
+ contextWindow: contextLength,
supportsPromptCache: true,
supportsImages: rawModel.vision,
supportsComputerUse: false,
- maxTokens: rawModel.contextLength,
+ maxTokens: contextLength,
})
return modelInfo
@@ -33,12 +36,25 @@ export async function getLMStudioModels(baseUrl = "http://localhost:1234"): Prom
await axios.get(`${baseUrl}/v1/models`)
const client = new LMStudioClient({ baseUrl: lmsUrl })
- const response = (await client.llm.listLoaded().then((models: LLM[]) => {
- return Promise.all(models.map((m) => m.getModelInfo()))
- })) as Array
- for (const lmstudioModel of response) {
- models[lmstudioModel.modelKey] = parseLMStudioModel(lmstudioModel)
+ // First, try to get all downloaded models
+ try {
+ const downloadedModels = await client.system.listDownloadedModels("llm")
+ for (const model of downloadedModels) {
+ // Use the model path as the key since that's what users select
+ models[model.path] = parseLMStudioModel(model)
+ }
+ } catch (error) {
+ console.warn("Failed to list downloaded models, falling back to loaded models only")
+
+ // Fall back to listing only loaded models
+ const loadedModels = (await client.llm.listLoaded().then((models: LLM[]) => {
+ return Promise.all(models.map((m) => m.getModelInfo()))
+ })) as Array
+
+ for (const lmstudioModel of loadedModels) {
+ models[lmstudioModel.modelKey] = parseLMStudioModel(lmstudioModel)
+ }
}
} catch (error) {
if (error.code === "ECONNREFUSED") {
diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts
index f689196d79..8bf2f6b95a 100644
--- a/src/core/webview/webviewMessageHandler.ts
+++ b/src/core/webview/webviewMessageHandler.ts
@@ -448,6 +448,9 @@ export const webviewMessageHandler = async (
// Specific handler for Ollama models only
const { apiConfiguration: ollamaApiConfig } = await provider.getState()
try {
+ // Flush cache first to ensure fresh models
+ await flushModels("ollama")
+
const ollamaModels = await getModels({
provider: "ollama",
baseUrl: ollamaApiConfig.ollamaBaseUrl,
@@ -469,6 +472,9 @@ export const webviewMessageHandler = async (
// Specific handler for LM Studio models only
const { apiConfiguration: lmStudioApiConfig } = await provider.getState()
try {
+ // Flush cache first to ensure fresh models
+ await flushModels("lmstudio")
+
const lmStudioModels = await getModels({
provider: "lmstudio",
baseUrl: lmStudioApiConfig.lmStudioBaseUrl,
diff --git a/src/integrations/claude-code/types.ts b/src/integrations/claude-code/types.ts
index abac758182..965a1b8469 100644
--- a/src/integrations/claude-code/types.ts
+++ b/src/integrations/claude-code/types.ts
@@ -6,10 +6,16 @@ type InitMessage = {
mcp_servers: string[]
}
-type ClaudeCodeContent = {
- type: "text"
- text: string
-}
+type ClaudeCodeContent =
+ | {
+ type: "text"
+ text: string
+ }
+ | {
+ type: "thinking"
+ thinking: string
+ signature?: string
+ }
type AssistantMessage = {
type: "assistant"
diff --git a/src/package.json b/src/package.json
index bb4a784173..0256de59ad 100644
--- a/src/package.json
+++ b/src/package.json
@@ -3,7 +3,7 @@
"displayName": "%extension.displayName%",
"description": "%extension.description%",
"publisher": "RooVeterinaryInc",
- "version": "3.21.3",
+ "version": "3.21.5",
"icon": "assets/icons/icon.png",
"galleryBanner": {
"color": "#617A91",
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 144571c28c..7ed9afb179 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
@@ -113,6 +113,7 @@ describe("QdrantVectorStore", () => {
host: "qdrant.ashbyfam.com",
https: true,
port: 443,
+ prefix: undefined, // No prefix for root path
apiKey: undefined,
headers: {
"User-Agent": "Roo-Code",
@@ -127,6 +128,7 @@ describe("QdrantVectorStore", () => {
host: "example.com",
https: true,
port: 9000,
+ prefix: undefined, // No prefix for root path
apiKey: undefined,
headers: {
"User-Agent": "Roo-Code",
@@ -145,6 +147,7 @@ describe("QdrantVectorStore", () => {
host: "example.com",
https: true,
port: 443,
+ prefix: "/api/v1", // Should have prefix
apiKey: undefined,
headers: {
"User-Agent": "Roo-Code",
@@ -161,6 +164,7 @@ describe("QdrantVectorStore", () => {
host: "example.com",
https: false,
port: 80,
+ prefix: undefined, // No prefix for root path
apiKey: undefined,
headers: {
"User-Agent": "Roo-Code",
@@ -175,6 +179,7 @@ describe("QdrantVectorStore", () => {
host: "localhost",
https: false,
port: 8080,
+ prefix: undefined, // No prefix for root path
apiKey: undefined,
headers: {
"User-Agent": "Roo-Code",
@@ -193,6 +198,7 @@ describe("QdrantVectorStore", () => {
host: "example.com",
https: false,
port: 80,
+ prefix: "/api/v1", // Should have prefix
apiKey: undefined,
headers: {
"User-Agent": "Roo-Code",
@@ -337,6 +343,159 @@ describe("QdrantVectorStore", () => {
})
})
+ describe("URL Prefix Handling", () => {
+ it("should pass the URL pathname as prefix to QdrantClient if not root", () => {
+ const vectorStoreWithPrefix = new QdrantVectorStore(
+ mockWorkspacePath,
+ "http://localhost:6333/some/path",
+ mockVectorSize,
+ )
+ expect(QdrantClient).toHaveBeenLastCalledWith({
+ host: "localhost",
+ https: false,
+ port: 6333,
+ prefix: "/some/path",
+ apiKey: undefined,
+ headers: {
+ "User-Agent": "Roo-Code",
+ },
+ })
+ expect((vectorStoreWithPrefix as any).qdrantUrl).toBe("http://localhost:6333/some/path")
+ })
+
+ it("should not pass prefix if the URL pathname is root ('/')", () => {
+ const vectorStoreWithoutPrefix = new QdrantVectorStore(
+ mockWorkspacePath,
+ "http://localhost:6333/",
+ mockVectorSize,
+ )
+ expect(QdrantClient).toHaveBeenLastCalledWith({
+ host: "localhost",
+ https: false,
+ port: 6333,
+ prefix: undefined,
+ apiKey: undefined,
+ headers: {
+ "User-Agent": "Roo-Code",
+ },
+ })
+ expect((vectorStoreWithoutPrefix as any).qdrantUrl).toBe("http://localhost:6333/")
+ })
+
+ it("should handle HTTPS URL with path as prefix", () => {
+ const vectorStoreWithHttpsPrefix = new QdrantVectorStore(
+ mockWorkspacePath,
+ "https://qdrant.ashbyfam.com/api",
+ mockVectorSize,
+ )
+ expect(QdrantClient).toHaveBeenLastCalledWith({
+ host: "qdrant.ashbyfam.com",
+ https: true,
+ port: 443,
+ prefix: "/api",
+ apiKey: undefined,
+ headers: {
+ "User-Agent": "Roo-Code",
+ },
+ })
+ expect((vectorStoreWithHttpsPrefix as any).qdrantUrl).toBe("https://qdrant.ashbyfam.com/api")
+ })
+
+ it("should normalize URL pathname by removing trailing slash for prefix", () => {
+ const vectorStoreWithTrailingSlash = new QdrantVectorStore(
+ mockWorkspacePath,
+ "http://localhost:6333/api/",
+ mockVectorSize,
+ )
+ expect(QdrantClient).toHaveBeenLastCalledWith({
+ host: "localhost",
+ https: false,
+ port: 6333,
+ prefix: "/api", // Trailing slash should be removed
+ apiKey: undefined,
+ headers: {
+ "User-Agent": "Roo-Code",
+ },
+ })
+ expect((vectorStoreWithTrailingSlash as any).qdrantUrl).toBe("http://localhost:6333/api/")
+ })
+
+ it("should normalize URL pathname by removing multiple trailing slashes for prefix", () => {
+ const vectorStoreWithMultipleTrailingSlashes = new QdrantVectorStore(
+ mockWorkspacePath,
+ "http://localhost:6333/api///",
+ mockVectorSize,
+ )
+ expect(QdrantClient).toHaveBeenLastCalledWith({
+ host: "localhost",
+ https: false,
+ port: 6333,
+ prefix: "/api", // All trailing slashes should be removed
+ apiKey: undefined,
+ headers: {
+ "User-Agent": "Roo-Code",
+ },
+ })
+ expect((vectorStoreWithMultipleTrailingSlashes as any).qdrantUrl).toBe("http://localhost:6333/api///")
+ })
+
+ it("should handle multiple path segments correctly for prefix", () => {
+ const vectorStoreWithMultiSegment = new QdrantVectorStore(
+ mockWorkspacePath,
+ "http://localhost:6333/api/v1/qdrant",
+ mockVectorSize,
+ )
+ expect(QdrantClient).toHaveBeenLastCalledWith({
+ host: "localhost",
+ https: false,
+ port: 6333,
+ prefix: "/api/v1/qdrant",
+ apiKey: undefined,
+ headers: {
+ "User-Agent": "Roo-Code",
+ },
+ })
+ expect((vectorStoreWithMultiSegment as any).qdrantUrl).toBe("http://localhost:6333/api/v1/qdrant")
+ })
+
+ it("should handle complex URL with multiple segments, multiple trailing slashes, query params, and fragment", () => {
+ const complexUrl = "https://example.com/ollama/api/v1///?key=value#pos"
+ const vectorStoreComplex = new QdrantVectorStore(mockWorkspacePath, complexUrl, mockVectorSize)
+ expect(QdrantClient).toHaveBeenLastCalledWith({
+ host: "example.com",
+ https: true,
+ port: 443,
+ prefix: "/ollama/api/v1", // Trailing slash removed, query/fragment ignored
+ apiKey: undefined,
+ headers: {
+ "User-Agent": "Roo-Code",
+ },
+ })
+ expect((vectorStoreComplex as any).qdrantUrl).toBe(complexUrl)
+ })
+
+ it("should ignore query parameters and fragments when determining prefix", () => {
+ const vectorStoreWithQueryParams = new QdrantVectorStore(
+ mockWorkspacePath,
+ "http://localhost:6333/api/path?key=value#fragment",
+ mockVectorSize,
+ )
+ expect(QdrantClient).toHaveBeenLastCalledWith({
+ host: "localhost",
+ https: false,
+ port: 6333,
+ prefix: "/api/path", // Query params and fragment should be ignored
+ apiKey: undefined,
+ headers: {
+ "User-Agent": "Roo-Code",
+ },
+ })
+ expect((vectorStoreWithQueryParams as any).qdrantUrl).toBe(
+ "http://localhost:6333/api/path?key=value#fragment",
+ )
+ })
+ })
+
describe("initialize", () => {
it("should create a new collection if none exists and return true", async () => {
// Mock getCollection to throw a 404-like error
diff --git a/src/services/code-index/vector-store/qdrant-client.ts b/src/services/code-index/vector-store/qdrant-client.ts
index 7f4a04ed44..c0f19af28b 100644
--- a/src/services/code-index/vector-store/qdrant-client.ts
+++ b/src/services/code-index/vector-store/qdrant-client.ts
@@ -57,6 +57,7 @@ export class QdrantVectorStore implements IVectorStore {
host: urlObj.hostname,
https: useHttps,
port: port,
+ prefix: urlObj.pathname === "/" ? undefined : urlObj.pathname.replace(/\/+$/, ""),
apiKey,
headers: {
"User-Agent": "Roo-Code",
@@ -64,6 +65,7 @@ export class QdrantVectorStore implements IVectorStore {
})
} catch (urlError) {
// If URL parsing fails, fall back to URL-based config
+ // Note: This fallback won't correctly handle prefixes, but it's a last resort for malformed URLs.
this.client = new QdrantClient({
url: parsedUrl,
apiKey,
diff --git a/src/services/mdm/MdmService.ts b/src/services/mdm/MdmService.ts
index e88601dfb3..d0a7bc92ee 100644
--- a/src/services/mdm/MdmService.ts
+++ b/src/services/mdm/MdmService.ts
@@ -6,6 +6,7 @@ import { z } from "zod"
import { CloudService, getClerkBaseUrl, PRODUCTION_CLERK_BASE_URL } from "@roo-code/cloud"
import { Package } from "../../shared/package"
+import { t } from "../../i18n"
// MDM Configuration Schema
const mdmConfigSchema = z.object({
@@ -89,7 +90,7 @@ export class MdmService {
if (!CloudService.hasInstance() || !CloudService.instance.hasOrIsAcquiringActiveSession()) {
return {
compliant: false,
- reason: "Your organization requires Roo Code Cloud authentication. Please sign in to continue.",
+ reason: t("mdm.errors.cloud_auth_required"),
}
}
@@ -97,18 +98,35 @@ export class MdmService {
const requiredOrgId = this.getRequiredOrganizationId()
if (requiredOrgId) {
try {
- const currentOrgId = CloudService.instance.getOrganizationId()
+ // First try to get from active session
+ let currentOrgId = CloudService.instance.getOrganizationId()
+
+ // If no active session, check stored credentials
+ if (!currentOrgId) {
+ const storedOrgId = CloudService.instance.getStoredOrganizationId()
+
+ // null means personal account, which is not compliant for org requirements
+ if (storedOrgId === null || storedOrgId !== requiredOrgId) {
+ return {
+ compliant: false,
+ reason: t("mdm.errors.organization_mismatch"),
+ }
+ }
+
+ currentOrgId = storedOrgId
+ }
+
if (currentOrgId !== requiredOrgId) {
return {
compliant: false,
- reason: "You must be authenticated with your organization's Roo Code Cloud account.",
+ reason: t("mdm.errors.organization_mismatch"),
}
}
} catch (error) {
this.log("[MDM] Error checking organization ID:", error)
return {
compliant: false,
- reason: "Unable to verify organization authentication.",
+ reason: t("mdm.errors.verification_failed"),
}
}
}
diff --git a/src/services/mdm/__tests__/MdmService.spec.ts b/src/services/mdm/__tests__/MdmService.spec.ts
index a7a48a5eb3..a69e74a9b5 100644
--- a/src/services/mdm/__tests__/MdmService.spec.ts
+++ b/src/services/mdm/__tests__/MdmService.spec.ts
@@ -43,6 +43,19 @@ vi.mock("../../../shared/package", () => ({
},
}))
+vi.mock("../../../i18n", () => ({
+ t: vi.fn((key: string) => {
+ const translations: Record = {
+ "mdm.errors.cloud_auth_required":
+ "Your organization requires Roo Code Cloud authentication. Please sign in to continue.",
+ "mdm.errors.organization_mismatch":
+ "You must be authenticated with your organization's Roo Code Cloud account.",
+ "mdm.errors.verification_failed": "Unable to verify organization authentication.",
+ }
+ return translations[key] || key
+ }),
+}))
+
import * as fs from "fs"
import * as os from "os"
import * as vscode from "vscode"
@@ -265,7 +278,7 @@ describe("MdmService", () => {
expect(compliance.compliant).toBe(false)
if (!compliance.compliant) {
- expect(compliance.reason).toContain("requires Roo Code Cloud authentication")
+ expect(compliance.reason).toContain("Your organization requires Roo Code Cloud authentication")
}
})
@@ -287,7 +300,9 @@ describe("MdmService", () => {
expect(compliance.compliant).toBe(false)
if (!compliance.compliant) {
- expect(compliance.reason).toContain("organization's Roo Code Cloud account")
+ expect(compliance.reason).toContain(
+ "You must be authenticated with your organization's Roo Code Cloud account",
+ )
}
})
diff --git a/src/shared/checkExistApiConfig.ts b/src/shared/checkExistApiConfig.ts
index 4093e8541d..eca2dd4fe0 100644
--- a/src/shared/checkExistApiConfig.ts
+++ b/src/shared/checkExistApiConfig.ts
@@ -5,8 +5,8 @@ export function checkExistKey(config: ProviderSettings | undefined) {
return false
}
- // Special case for human-relay and fake-ai providers which don't need any configuration.
- if (config.apiProvider === "human-relay" || config.apiProvider === "fake-ai") {
+ // Special case for human-relay, fake-ai, and claude-code providers which don't need any configuration.
+ if (config.apiProvider && ["human-relay", "fake-ai", "claude-code"].includes(config.apiProvider)) {
return true
}
diff --git a/webview-ui/src/components/settings/__tests__/TemperatureControl.spec.tsx b/webview-ui/src/components/settings/__tests__/TemperatureControl.spec.tsx
index 2c518fcdb1..ad4e352126 100644
--- a/webview-ui/src/components/settings/__tests__/TemperatureControl.spec.tsx
+++ b/webview-ui/src/components/settings/__tests__/TemperatureControl.spec.tsx
@@ -1,6 +1,6 @@
// npx vitest src/components/settings/__tests__/TemperatureControl.spec.tsx
-import { render, screen, fireEvent } from "@testing-library/react"
+import { render, screen, fireEvent, waitFor } from "@testing-library/react"
import { TemperatureControl } from "../TemperatureControl"
@@ -64,16 +64,18 @@ describe("TemperatureControl", () => {
// Uncheck - should clear temperature.
fireEvent.click(checkbox)
- // Waiting for debounce.
- await new Promise((x) => setTimeout(x, 100))
- expect(onChange).toHaveBeenCalledWith(null)
+ // Wait for debounced onChange call.
+ await waitFor(() => {
+ expect(onChange).toHaveBeenCalledWith(null)
+ })
// Check - should restore previous temperature.
fireEvent.click(checkbox)
- // Waiting for debounce.
- await new Promise((x) => setTimeout(x, 100))
- expect(onChange).toHaveBeenCalledWith(0.7)
+ // Wait for debounced onChange call.
+ await waitFor(() => {
+ expect(onChange).toHaveBeenCalledWith(0.7)
+ })
})
it("syncs checkbox state when value prop changes", () => {
diff --git a/webview-ui/src/components/settings/providers/LMStudio.tsx b/webview-ui/src/components/settings/providers/LMStudio.tsx
index 17af44871b..a907e43e1b 100644
--- a/webview-ui/src/components/settings/providers/LMStudio.tsx
+++ b/webview-ui/src/components/settings/providers/LMStudio.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useState, useMemo } from "react"
+import { useCallback, useState, useMemo, useEffect } from "react"
import { useEvent } from "react-use"
import { Trans } from "react-i18next"
import { Checkbox } from "vscrui"
@@ -9,6 +9,7 @@ import type { ProviderSettings } from "@roo-code/types"
import { useAppTranslation } from "@src/i18n/TranslationContext"
import { ExtensionMessage } from "@roo/ExtensionMessage"
import { useRouterModels } from "@src/components/ui/hooks/useRouterModels"
+import { vscode } from "@src/utils/vscode"
import { inputEventTransform } from "../transforms"
@@ -49,6 +50,12 @@ export const LMStudio = ({ apiConfiguration, setApiConfigurationField }: LMStudi
useEvent("message", onMessage)
+ // Refresh models on mount
+ useEffect(() => {
+ // Request fresh models - the handler now flushes cache automatically
+ vscode.postMessage({ type: "requestLmStudioModels" })
+ }, [])
+
// Check if the selected model exists in the fetched models
const modelNotAvailable = useMemo(() => {
const selectedModel = apiConfiguration?.lmStudioModelId
diff --git a/webview-ui/src/components/settings/providers/Ollama.tsx b/webview-ui/src/components/settings/providers/Ollama.tsx
index e118f68b46..263c3892f2 100644
--- a/webview-ui/src/components/settings/providers/Ollama.tsx
+++ b/webview-ui/src/components/settings/providers/Ollama.tsx
@@ -1,4 +1,4 @@
-import { useState, useCallback, useMemo } from "react"
+import { useState, useCallback, useMemo, useEffect } from "react"
import { useEvent } from "react-use"
import { VSCodeTextField, VSCodeRadioGroup, VSCodeRadio } from "@vscode/webview-ui-toolkit/react"
@@ -8,6 +8,7 @@ import { ExtensionMessage } from "@roo/ExtensionMessage"
import { useAppTranslation } from "@src/i18n/TranslationContext"
import { useRouterModels } from "@src/components/ui/hooks/useRouterModels"
+import { vscode } from "@src/utils/vscode"
import { inputEventTransform } from "../transforms"
@@ -48,6 +49,12 @@ export const Ollama = ({ apiConfiguration, setApiConfigurationField }: OllamaPro
useEvent("message", onMessage)
+ // Refresh models on mount
+ useEffect(() => {
+ // Request fresh models - the handler now flushes cache automatically
+ vscode.postMessage({ type: "requestOllamaModels" })
+ }, [])
+
// Check if the selected model exists in the fetched models
const modelNotAvailable = useMemo(() => {
const selectedModel = apiConfiguration?.ollamaModelId