Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .husky/pre-push
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ fi

# Detect if running on Windows and use pnpm.cmd, otherwise use pnpm.
if [ "$OS" = "Windows_NT" ]; then
pnpm_cmd="pnpm.cmd"
if command -v pnpm.cmd >/dev/null 2>&1; then
pnpm_cmd="pnpm.cmd"
elif command -v pnpm >/dev/null 2>&1; then
pnpm_cmd="pnpm"
else
pnpm_cmd="npx pnpm"
fi
else
if command -v pnpm >/dev/null 2>&1; then
pnpm_cmd="pnpm"
Expand Down
2 changes: 1 addition & 1 deletion apps/vscode-e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@roo-code/vscode-e2e",
"private": true,
"scripts": {
"lint": "eslint src --ext=ts --max-warnings=0",
"lint": "eslint src --max-warnings=0",
"check-types": "tsc -p tsconfig.esm.json --noEmit",
"format": "prettier --write src",
"test:ci": "pnpm -w bundle && pnpm --filter @roo-code/vscode-webview build && pnpm test:run",
Expand Down
2 changes: 1 addition & 1 deletion packages/build/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"main": "./dist/index.js",
"types": "./src/index.ts",
"scripts": {
"lint": "eslint src --ext=ts --max-warnings=0",
"lint": "eslint src --max-warnings=0",
"check-types": "tsc --noEmit",
"test": "vitest run",
"build": "tsc",
Expand Down
2 changes: 1 addition & 1 deletion packages/cloud/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"type": "module",
"exports": "./src/index.ts",
"scripts": {
"lint": "eslint src --ext=ts --max-warnings=0",
"lint": "eslint src --max-warnings=0",
"check-types": "tsc --noEmit",
"test": "vitest run",
"clean": "rimraf dist .turbo"
Expand Down
2 changes: 1 addition & 1 deletion packages/telemetry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"type": "module",
"exports": "./src/index.ts",
"scripts": {
"lint": "eslint src --ext=ts --max-warnings=0",
"lint": "eslint src --max-warnings=0",
"check-types": "tsc --noEmit",
"test": "vitest run",
"clean": "rimraf dist .turbo"
Expand Down
2 changes: 1 addition & 1 deletion packages/types/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
}
},
"scripts": {
"lint": "eslint src --ext=ts --max-warnings=0",
"lint": "eslint src --max-warnings=0",
"check-types": "tsc --noEmit",
"test": "vitest run",
"build": "tsup",
Expand Down
4 changes: 2 additions & 2 deletions packages/types/src/providers/gemini.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const geminiModels = {
outputPrice: 3.5,
maxThinkingTokens: 24_576,
supportsReasoningBudget: true,
requiredReasoningBudget: true,
requiredReasoningBudget: false,
},
"gemini-2.5-flash-preview-04-17": {
maxTokens: 65_535,
Expand All @@ -36,7 +36,7 @@ export const geminiModels = {
cacheWritesPrice: 1.0,
maxThinkingTokens: 24_576,
supportsReasoningBudget: true,
requiredReasoningBudget: true,
requiredReasoningBudget: false,
},
"gemini-2.5-flash-preview-05-20": {
maxTokens: 65_535,
Expand Down
4 changes: 2 additions & 2 deletions packages/types/src/providers/vertex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const vertexModels = {
outputPrice: 3.5,
maxThinkingTokens: 24_576,
supportsReasoningBudget: true,
requiredReasoningBudget: true,
requiredReasoningBudget: false,
},
"gemini-2.5-flash-preview-05-20": {
maxTokens: 65_535,
Expand All @@ -34,7 +34,7 @@ export const vertexModels = {
outputPrice: 3.5,
maxThinkingTokens: 24_576,
supportsReasoningBudget: true,
requiredReasoningBudget: true,
requiredReasoningBudget: false,
},
"gemini-2.5-flash-preview-04-17": {
maxTokens: 65_535,
Expand Down
31 changes: 27 additions & 4 deletions src/api/providers/gemini.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,28 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
let lastUsageMetadata: GenerateContentResponseUsageMetadata | undefined

for await (const chunk of result) {
if (chunk.text) {
// Process candidates and their parts to separate thoughts from content
if (chunk.candidates && chunk.candidates.length > 0) {
const candidate = chunk.candidates[0]
if (candidate.content && candidate.content.parts) {
for (const part of candidate.content.parts) {
if (part.thought) {
// This is a thinking/reasoning part
if (part.text) {
yield { type: "reasoning", text: part.text }
}
} else {
// This is regular content
if (part.text) {
yield { type: "text", text: part.text }
}
}
}
}
}

// Fallback to the original text property if no candidates structure
else if (chunk.text) {
yield { type: "text", text: chunk.text }
}

Expand Down Expand Up @@ -117,12 +138,14 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
if (geminiModels[id as GeminiModelId]) {
info = geminiModels[id as GeminiModelId]

const thinkingConfig = this.options.modelMaxThinkingTokens
? { includeThoughts: true, thinkingBudget: this.options.modelMaxThinkingTokens }
: { includeThoughts: true }

return {
id,
info,
thinkingConfig: this.options.modelMaxThinkingTokens
? { thinkingBudget: this.options.modelMaxThinkingTokens }
: undefined,
thinkingConfig,
maxOutputTokens: this.options.modelMaxTokens ?? info.maxTokens ?? undefined,
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/api/providers/vertex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ export class VertexHandler extends GeminiHandler implements SingleCompletionHand
if (vertexModels[id as VertexModelId]) {
info = vertexModels[id as VertexModelId]

const thinkingConfig = this.options.modelMaxThinkingTokens
? { includeThoughts: true, thinkingBudget: this.options.modelMaxThinkingTokens }
: { includeThoughts: true }

return {
id,
info,
thinkingConfig: this.options.modelMaxThinkingTokens
? { thinkingBudget: this.options.modelMaxThinkingTokens }
: undefined,
thinkingConfig,
maxOutputTokens: this.options.modelMaxTokens ?? info.maxTokens ?? undefined,
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@
}
},
"scripts": {
"lint": "eslint . --ext=ts --max-warnings=0",
"lint": "eslint . --max-warnings=0",
"check-types": "tsc --noEmit",
"pretest": "turbo run bundle --cwd ..",
"test": "jest -w=40% && vitest run",
Expand Down
10 changes: 10 additions & 0 deletions webview-ui/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ export default [
...reactConfig,
{
rules: {
// Disable base ESLint rule to avoid conflicts with TypeScript ESLint version
"no-unused-expressions": "off",
"@typescript-eslint/no-unused-expressions": [
"error",
{
allowShortCircuit: true,
allowTernary: true,
allowTaggedTemplates: true,
},
],
"@typescript-eslint/no-unused-vars": [
"error",
{
Expand Down
2 changes: 1 addition & 1 deletion webview-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"private": true,
"type": "module",
"scripts": {
"lint": "eslint src --ext=ts,tsx --max-warnings=0",
"lint": "eslint src --max-warnings=0",
"check-types": "tsc",
"pretest": "turbo run bundle --cwd ..",
"test": "jest -w=40%",
Expand Down
70 changes: 57 additions & 13 deletions webview-ui/src/components/settings/ThinkingBudget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ export const ThinkingBudget = ({ apiConfiguration, setApiConfigurationField, mod
const isReasoningBudgetRequired = !!modelInfo && modelInfo.requiredReasoningBudget
const isReasoningEffortSupported = !!modelInfo && modelInfo.supportsReasoningEffort

const enableReasoningEffort = apiConfiguration.enableReasoningEffort
// For Gemini Flash thinking models, default to enabling reasoning if not explicitly set
const isGeminiFlashThinking = modelInfo && modelInfo.supportsReasoningBudget && !modelInfo.requiredReasoningBudget
const enableReasoningEffort = apiConfiguration.enableReasoningEffort ?? (isGeminiFlashThinking ? true : false)
const customMaxOutputTokens = apiConfiguration.modelMaxTokens || DEFAULT_HYBRID_REASONING_MODEL_MAX_TOKENS
const customMaxThinkingTokens =
apiConfiguration.modelMaxThinkingTokens || DEFAULT_HYBRID_REASONING_MODEL_THINKING_TOKENS
Expand All @@ -32,6 +34,13 @@ export const ThinkingBudget = ({ apiConfiguration, setApiConfigurationField, mod
? Math.min(modelInfo.maxThinkingTokens, Math.floor(0.8 * customMaxOutputTokens))
: Math.floor(0.8 * customMaxOutputTokens)

// Initialize enableReasoningEffort to true for Gemini Flash thinking models if not set
useEffect(() => {
if (isGeminiFlashThinking && apiConfiguration.enableReasoningEffort === undefined) {
setApiConfigurationField("enableReasoningEffort", true)
}
}, [isGeminiFlashThinking, apiConfiguration.enableReasoningEffort, setApiConfigurationField])

// If the custom max thinking tokens are going to exceed it's limit due
// to the custom max output tokens being reduced then we need to shrink it
// appropriately.
Expand Down Expand Up @@ -73,19 +82,54 @@ export const ThinkingBudget = ({ apiConfiguration, setApiConfigurationField, mod
<div className="w-12 text-sm text-center">{customMaxOutputTokens}</div>
</div>
</div>
<div className="flex flex-col gap-1">
<div className="font-medium">{t("settings:thinkingBudget.maxThinkingTokens")}</div>
<div className="flex items-center gap-1" data-testid="reasoning-budget">
<Slider
min={1024}
max={modelMaxThinkingTokens}
step={1024}
value={[customMaxThinkingTokens]}
onValueChange={([value]) => setApiConfigurationField("modelMaxThinkingTokens", value)}
/>
<div className="w-12 text-sm text-center">{customMaxThinkingTokens}</div>
{isGeminiFlashThinking ? (
<div className="flex flex-col gap-1">
<Checkbox
checked={!!apiConfiguration.modelMaxThinkingTokens}
onChange={(checked: boolean) => {
if (checked) {
setApiConfigurationField(
"modelMaxThinkingTokens",
DEFAULT_HYBRID_REASONING_MODEL_THINKING_TOKENS,
)
} else {
setApiConfigurationField("modelMaxThinkingTokens", undefined)
}
}}>
{t("settings:thinkingBudget.manualThinkingBudget")}
</Checkbox>
{!!apiConfiguration.modelMaxThinkingTokens && (
<div className="flex items-center gap-1" data-testid="reasoning-budget">
<Slider
min={1024}
max={modelMaxThinkingTokens}
step={1024}
value={[customMaxThinkingTokens]}
onValueChange={([value]) =>
setApiConfigurationField("modelMaxThinkingTokens", value)
}
/>
<div className="w-12 text-sm text-center">{customMaxThinkingTokens}</div>
</div>
)}
</div>
</div>
) : (
<div className="flex flex-col gap-1">
<div className="font-medium">{t("settings:thinkingBudget.maxThinkingTokens")}</div>
<div className="flex items-center gap-1" data-testid="reasoning-budget">
<Slider
min={1024}
max={modelMaxThinkingTokens}
step={1024}
value={[customMaxThinkingTokens]}
onValueChange={([value]) =>
setApiConfigurationField("modelMaxThinkingTokens", value)
}
/>
<div className="w-12 text-sm text-center">{customMaxThinkingTokens}</div>
</div>
</div>
)}
</>
)}
</>
Expand Down
3 changes: 2 additions & 1 deletion webview-ui/src/i18n/locales/ca/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@
},
"thinkingBudget": {
"maxTokens": "Tokens màxims",
"maxThinkingTokens": "Tokens de pensament màxims"
"maxThinkingTokens": "Tokens de pensament màxims",
"manualThinkingBudget": "Establir pressupost manual de pensament (si no, el model decideix automàticament)"
},
"validation": {
"apiKey": "Heu de proporcionar una clau API vàlida.",
Expand Down
3 changes: 2 additions & 1 deletion webview-ui/src/i18n/locales/de/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@
},
"thinkingBudget": {
"maxTokens": "Maximale Tokens",
"maxThinkingTokens": "Maximale Thinking-Tokens"
"maxThinkingTokens": "Maximale Thinking-Tokens",
"manualThinkingBudget": "Manuelles Thinking-Budget festlegen (sonst entscheidet das Modell automatisch)"
},
"validation": {
"apiKey": "Du musst einen gültigen API-Schlüssel angeben.",
Expand Down
3 changes: 2 additions & 1 deletion webview-ui/src/i18n/locales/en/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@
},
"thinkingBudget": {
"maxTokens": "Max Tokens",
"maxThinkingTokens": "Max Thinking Tokens"
"maxThinkingTokens": "Max Thinking Tokens",
"manualThinkingBudget": "Set manual thinking budget (otherwise model decides automatically)"
},
"validation": {
"apiKey": "You must provide a valid API key.",
Expand Down
3 changes: 2 additions & 1 deletion webview-ui/src/i18n/locales/es/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@
},
"thinkingBudget": {
"maxTokens": "Tokens máximos",
"maxThinkingTokens": "Tokens máximos de pensamiento"
"maxThinkingTokens": "Tokens máximos de pensamiento",
"manualThinkingBudget": "Establecer presupuesto manual de pensamientos (de lo contrario el modelo decide automáticamente)"
},
"validation": {
"apiKey": "Debe proporcionar una clave API válida.",
Expand Down
3 changes: 2 additions & 1 deletion webview-ui/src/i18n/locales/fr/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@
},
"thinkingBudget": {
"maxTokens": "Tokens maximum",
"maxThinkingTokens": "Tokens de réflexion maximum"
"maxThinkingTokens": "Tokens de réflexion maximum",
"manualThinkingBudget": "Définir un budget manuel de réflexion (sinon le modèle décide automatiquement)"
},
"validation": {
"apiKey": "Vous devez fournir une clé API valide.",
Expand Down
3 changes: 2 additions & 1 deletion webview-ui/src/i18n/locales/hi/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@
},
"thinkingBudget": {
"maxTokens": "अधिकतम tokens",
"maxThinkingTokens": "अधिकतम thinking tokens"
"maxThinkingTokens": "अधिकतम thinking tokens",
"manualThinkingBudget": "मैन्युअल सोच बजट सेट करें (अन्यथा मॉडल अपने आप निर्णय लेता है)"
},
"validation": {
"apiKey": "आपको एक मान्य API कुंजी प्रदान करनी होगी।",
Expand Down
3 changes: 2 additions & 1 deletion webview-ui/src/i18n/locales/it/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@
},
"thinkingBudget": {
"maxTokens": "Token massimi",
"maxThinkingTokens": "Token massimi di pensiero"
"maxThinkingTokens": "Token massimi di pensiero",
"manualThinkingBudget": "Imposta budget manuale di pensiero (altrimenti il modello decide automaticamente)"
},
"validation": {
"apiKey": "È necessario fornire una chiave API valida.",
Expand Down
3 changes: 2 additions & 1 deletion webview-ui/src/i18n/locales/ja/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@
},
"thinkingBudget": {
"maxTokens": "最大 tokens",
"maxThinkingTokens": "最大思考 tokens"
"maxThinkingTokens": "最大思考 tokens",
"manualThinkingBudget": "手動思考予算を設定(そうでなければモデルが自動的に決定)"
},
"validation": {
"apiKey": "有効なAPIキーを入力してください。",
Expand Down
3 changes: 2 additions & 1 deletion webview-ui/src/i18n/locales/ko/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@
},
"thinkingBudget": {
"maxTokens": "최대 tokens",
"maxThinkingTokens": "최대 사고 tokens"
"maxThinkingTokens": "최대 사고 tokens",
"manualThinkingBudget": "수동 사고 예산 설정 (그렇지 않으면 모델이 자동으로 결정)"
},
"validation": {
"apiKey": "유효한 API 키를 입력해야 합니다.",
Expand Down
3 changes: 2 additions & 1 deletion webview-ui/src/i18n/locales/nl/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@
},
"thinkingBudget": {
"maxTokens": "Max tokens",
"maxThinkingTokens": "Max denk-tokens"
"maxThinkingTokens": "Max denk-tokens",
"manualThinkingBudget": "Handmatig denkbudget instellen (anders beslist het model automatisch)"
},
"validation": {
"apiKey": "Je moet een geldige API-sleutel opgeven.",
Expand Down
3 changes: 2 additions & 1 deletion webview-ui/src/i18n/locales/pl/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@
},
"thinkingBudget": {
"maxTokens": "Maksymalna liczba tokenów",
"maxThinkingTokens": "Maksymalna liczba tokenów myślenia"
"maxThinkingTokens": "Maksymalna liczba tokenów myślenia",
"manualThinkingBudget": "Ustaw manualny budżet myślenia (w przeciwnym razie model decyduje automatycznie)"
},
"validation": {
"apiKey": "Musisz podać prawidłowy klucz API.",
Expand Down
Loading