From aa70d755f80955f7bc07694241936f75f87a40f0 Mon Sep 17 00:00:00 2001 From: moqimoqidea <39821951+moqimoqidea@users.noreply.github.com> Date: Fri, 7 Mar 2025 16:28:44 +0800 Subject: [PATCH 01/15] fix claude 3.7 think enhance prompt problem. --- src/api/providers/anthropic.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/providers/anthropic.ts b/src/api/providers/anthropic.ts index 173550dc58..681ef2fc77 100644 --- a/src/api/providers/anthropic.ts +++ b/src/api/providers/anthropic.ts @@ -214,12 +214,12 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa } async completePrompt(prompt: string) { - let { id: modelId, maxTokens, thinking, temperature } = this.getModel() + let { id: modelId, temperature } = this.getModel() const message = await this.client.messages.create({ model: modelId, - max_tokens: maxTokens ?? ANTHROPIC_DEFAULT_MAX_TOKENS, - thinking, + max_tokens: ANTHROPIC_DEFAULT_MAX_TOKENS, + thinking: undefined, temperature, messages: [{ role: "user", content: prompt }], stream: false, From 13563ef0c5f2c3bc205fbd941e7cdfb876d42cdc Mon Sep 17 00:00:00 2001 From: System233 Date: Sat, 8 Mar 2025 04:59:39 +0800 Subject: [PATCH 02/15] Fix: Input/output prices are parsed too early --- webview-ui/src/components/settings/ApiOptions.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index efbe098186..7736046048 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -843,7 +843,7 @@ const ApiOptions = ({ : "var(--vscode-errorForeground)" })(), }} - onInput={handleInputChange("openAiCustomModelInfo", (e) => { + onChange={handleInputChange("openAiCustomModelInfo", (e) => { const value = (e.target as HTMLInputElement).value const parsed = parseFloat(value) return { @@ -881,7 +881,7 @@ const ApiOptions = ({ : "var(--vscode-errorForeground)" })(), }} - onInput={handleInputChange("openAiCustomModelInfo", (e) => { + onChange={handleInputChange("openAiCustomModelInfo", (e) => { const value = (e.target as HTMLInputElement).value const parsed = parseFloat(value) return { From 9ceccdec3203175df08ca6c6c119a8fa784d4786 Mon Sep 17 00:00:00 2001 From: System233 Date: Sat, 8 Mar 2025 05:31:39 +0800 Subject: [PATCH 03/15] Fix: Custom temperature cannot be unchecked --- src/shared/api.ts | 2 +- .../src/components/settings/TemperatureControl.tsx | 10 +++++----- .../settings/__tests__/TemperatureControl.test.tsx | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/shared/api.ts b/src/shared/api.ts index ca12b7ad76..98d595cd03 100644 --- a/src/shared/api.ts +++ b/src/shared/api.ts @@ -70,7 +70,7 @@ export interface ApiHandlerOptions { requestyApiKey?: string requestyModelId?: string requestyModelInfo?: ModelInfo - modelTemperature?: number + modelTemperature?: number | null modelMaxTokens?: number modelMaxThinkingTokens?: number } diff --git a/webview-ui/src/components/settings/TemperatureControl.tsx b/webview-ui/src/components/settings/TemperatureControl.tsx index 2f7dc29f64..7502c3d1f3 100644 --- a/webview-ui/src/components/settings/TemperatureControl.tsx +++ b/webview-ui/src/components/settings/TemperatureControl.tsx @@ -3,8 +3,8 @@ import { useEffect, useState } from "react" import { useDebounce } from "react-use" interface TemperatureControlProps { - value: number | undefined - onChange: (value: number | undefined) => void + value: number | undefined | null + onChange: (value: number | undefined | null) => void maxValue?: number // Some providers like OpenAI use 0-2 range } @@ -14,7 +14,7 @@ export const TemperatureControl = ({ value, onChange, maxValue = 1 }: Temperatur useDebounce(() => onChange(inputValue), 50, [onChange, inputValue]) // Sync internal state with prop changes when switching profiles useEffect(() => { - const hasCustomTemperature = value !== undefined + const hasCustomTemperature = value !== undefined && value !== null setIsCustomTemperature(hasCustomTemperature) setInputValue(value) }, [value]) @@ -28,7 +28,7 @@ export const TemperatureControl = ({ value, onChange, maxValue = 1 }: Temperatur const isChecked = e.target.checked setIsCustomTemperature(isChecked) if (!isChecked) { - setInputValue(undefined) // Unset the temperature + setInputValue(null) // Unset the temperature, note that undefined is unserializable } else { setInputValue(value ?? 0) // Use the value from apiConfiguration, if set } @@ -53,7 +53,7 @@ export const TemperatureControl = ({ value, onChange, maxValue = 1 }: Temperatur min="0" max={maxValue} step="0.01" - value={inputValue} + value={inputValue ?? 0} className="h-2 focus:outline-0 w-4/5 accent-vscode-button-background" onChange={(e) => setInputValue(parseFloat(e.target.value))} /> diff --git a/webview-ui/src/components/settings/__tests__/TemperatureControl.test.tsx b/webview-ui/src/components/settings/__tests__/TemperatureControl.test.tsx index 95d0babfdb..d470c15fb8 100644 --- a/webview-ui/src/components/settings/__tests__/TemperatureControl.test.tsx +++ b/webview-ui/src/components/settings/__tests__/TemperatureControl.test.tsx @@ -33,7 +33,7 @@ describe("TemperatureControl", () => { fireEvent.click(checkbox) // Waiting for debounce await new Promise((x) => setTimeout(x, 100)) - expect(onChange).toHaveBeenCalledWith(undefined) + expect(onChange).toHaveBeenCalledWith(null) // Check - should restore previous temperature fireEvent.click(checkbox) From da286c45ed8ac3f728926f0e7b0e6ce144836ce4 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Fri, 7 Mar 2025 22:33:35 -0500 Subject: [PATCH 04/15] Fix logic for default modelMaxTokens for thinking models --- src/core/Cline.ts | 5 +- webview-ui/package-lock.json | 1 - .../__tests__/getMaxTokensForModel.test.tsx | 6 +- .../src/utils/__tests__/model-utils.test.ts | 134 ++++++++++++++++++ webview-ui/src/utils/model-utils.ts | 7 +- 5 files changed, 147 insertions(+), 6 deletions(-) create mode 100644 webview-ui/src/utils/__tests__/model-utils.test.ts diff --git a/src/core/Cline.ts b/src/core/Cline.ts index 51fb5265d4..870db843b7 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -1124,9 +1124,12 @@ export class Cline { const totalTokens = tokensIn + tokensOut + cacheWrites + cacheReads + // Default max tokens value for thinking models when no specific value is set + const DEFAULT_THINKING_MODEL_MAX_TOKENS = 16_384 + const modelInfo = this.api.getModel().info const maxTokens = modelInfo.thinking - ? this.apiConfiguration.modelMaxTokens || modelInfo.maxTokens + ? this.apiConfiguration.modelMaxTokens || DEFAULT_THINKING_MODEL_MAX_TOKENS : modelInfo.maxTokens const contextWindow = modelInfo.contextWindow const trimmedMessages = await truncateConversationIfNeeded({ diff --git a/webview-ui/package-lock.json b/webview-ui/package-lock.json index 2e765133f3..b52f8ab311 100644 --- a/webview-ui/package-lock.json +++ b/webview-ui/package-lock.json @@ -14151,7 +14151,6 @@ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", "dev": true, - "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", diff --git a/webview-ui/src/__tests__/getMaxTokensForModel.test.tsx b/webview-ui/src/__tests__/getMaxTokensForModel.test.tsx index cf8567bf23..2a55ca9722 100644 --- a/webview-ui/src/__tests__/getMaxTokensForModel.test.tsx +++ b/webview-ui/src/__tests__/getMaxTokensForModel.test.tsx @@ -1,4 +1,4 @@ -import { getMaxTokensForModel } from "@/utils/model-utils" +import { DEFAULT_THINKING_MODEL_MAX_TOKENS, getMaxTokensForModel } from "@/utils/model-utils" describe("getMaxTokensForModel utility from model-utils", () => { test("should return maxTokens from modelInfo when thinking is false", () => { @@ -29,7 +29,7 @@ describe("getMaxTokensForModel utility from model-utils", () => { expect(result).toBe(4096) }) - test("should fallback to modelInfo.maxTokens when thinking is true but apiConfig.modelMaxTokens is not defined", () => { + test("should fallback to DEFAULT_THINKING_MODEL_MAX_TOKENS when thinking is true but apiConfig.modelMaxTokens is not defined", () => { const modelInfo = { maxTokens: 2048, thinking: true, @@ -38,7 +38,7 @@ describe("getMaxTokensForModel utility from model-utils", () => { const apiConfig = {} const result = getMaxTokensForModel(modelInfo, apiConfig) - expect(result).toBe(2048) + expect(result).toBe(DEFAULT_THINKING_MODEL_MAX_TOKENS) }) test("should handle undefined inputs gracefully", () => { diff --git a/webview-ui/src/utils/__tests__/model-utils.test.ts b/webview-ui/src/utils/__tests__/model-utils.test.ts new file mode 100644 index 0000000000..3f667dc961 --- /dev/null +++ b/webview-ui/src/utils/__tests__/model-utils.test.ts @@ -0,0 +1,134 @@ +/** + * @fileoverview Tests for token and model utility functions + */ + +import { + getMaxTokensForModel, + calculateTokenDistribution, + ModelInfo, + ApiConfig, + DEFAULT_THINKING_MODEL_MAX_TOKENS, +} from "../model-utils" + +describe("Model utility functions", () => { + describe("getMaxTokensForModel", () => { + /** + * Testing the specific fix in commit cc79178f: + * For thinking models, use apiConfig.modelMaxTokens if available, + * otherwise fall back to 16_384 (not modelInfo.maxTokens) + */ + + it("should return apiConfig.modelMaxTokens for thinking models when provided", () => { + const modelInfo: ModelInfo = { + thinking: true, + maxTokens: 8000, + } + + const apiConfig: ApiConfig = { + modelMaxTokens: 4000, + } + + expect(getMaxTokensForModel(modelInfo, apiConfig)).toBe(4000) + }) + + it("should return 16_384 for thinking models when modelMaxTokens not provided", () => { + const modelInfo: ModelInfo = { + thinking: true, + maxTokens: 8000, + } + + const apiConfig: ApiConfig = {} + + // This tests the specific fix: now using DEFAULT_THINKING_MODEL_MAX_TOKENS instead of falling back to modelInfo.maxTokens + expect(getMaxTokensForModel(modelInfo, apiConfig)).toBe(DEFAULT_THINKING_MODEL_MAX_TOKENS) + }) + + it("should return 16_384 for thinking models when apiConfig is undefined", () => { + const modelInfo: ModelInfo = { + thinking: true, + maxTokens: 8000, + } + + expect(getMaxTokensForModel(modelInfo, undefined)).toBe(DEFAULT_THINKING_MODEL_MAX_TOKENS) + }) + + it("should return modelInfo.maxTokens for non-thinking models", () => { + const modelInfo: ModelInfo = { + thinking: false, + maxTokens: 8000, + } + + const apiConfig: ApiConfig = { + modelMaxTokens: 4000, + } + + expect(getMaxTokensForModel(modelInfo, apiConfig)).toBe(8000) + }) + + it("should return undefined for non-thinking models with undefined maxTokens", () => { + const modelInfo: ModelInfo = { + thinking: false, + } + + const apiConfig: ApiConfig = { + modelMaxTokens: 4000, + } + + expect(getMaxTokensForModel(modelInfo, apiConfig)).toBeUndefined() + }) + + it("should return undefined when modelInfo is undefined", () => { + const apiConfig: ApiConfig = { + modelMaxTokens: 4000, + } + + expect(getMaxTokensForModel(undefined, apiConfig)).toBeUndefined() + }) + }) + + describe("calculateTokenDistribution", () => { + it("should calculate token distribution correctly", () => { + const contextWindow = 10000 + const contextTokens = 5000 + const maxTokens = 2000 + + const result = calculateTokenDistribution(contextWindow, contextTokens, maxTokens) + + expect(result.reservedForOutput).toBe(maxTokens) + expect(result.availableSize).toBe(3000) // 10000 - 5000 - 2000 + + // Percentages should sum to 100% + expect(Math.round(result.currentPercent + result.reservedPercent + result.availablePercent)).toBe(100) + }) + + it("should default to 20% of context window when maxTokens not provided", () => { + const contextWindow = 10000 + const contextTokens = 5000 + + const result = calculateTokenDistribution(contextWindow, contextTokens) + + expect(result.reservedForOutput).toBe(2000) // 20% of 10000 + expect(result.availableSize).toBe(3000) // 10000 - 5000 - 2000 + }) + + it("should handle negative or zero inputs by using positive fallbacks", () => { + const result = calculateTokenDistribution(-1000, -500) + + expect(result.currentPercent).toBe(0) + expect(result.reservedPercent).toBe(0) + expect(result.availablePercent).toBe(0) + expect(result.reservedForOutput).toBe(0) // With negative inputs, both context window and tokens become 0, so 20% of 0 is 0 + expect(result.availableSize).toBe(0) + }) + + it("should handle zero total tokens without division by zero errors", () => { + const result = calculateTokenDistribution(0, 0, 0) + + expect(result.currentPercent).toBe(0) + expect(result.reservedPercent).toBe(0) + expect(result.availablePercent).toBe(0) + expect(result.reservedForOutput).toBe(0) + expect(result.availableSize).toBe(0) + }) + }) +}) diff --git a/webview-ui/src/utils/model-utils.ts b/webview-ui/src/utils/model-utils.ts index c853bb7950..8380062eef 100644 --- a/webview-ui/src/utils/model-utils.ts +++ b/webview-ui/src/utils/model-utils.ts @@ -2,6 +2,11 @@ * Utility functions for working with language models and tokens */ +/** + * Default maximum tokens for thinking-capable models when no specific value is provided + */ +export const DEFAULT_THINKING_MODEL_MAX_TOKENS = 16_384 + /** * Model information interface with properties used in token calculations */ @@ -70,7 +75,7 @@ export const getMaxTokensForModel = ( apiConfig: ApiConfig | undefined, ): number | undefined => { if (modelInfo?.thinking) { - return apiConfig?.modelMaxTokens || modelInfo?.maxTokens + return apiConfig?.modelMaxTokens || DEFAULT_THINKING_MODEL_MAX_TOKENS } return modelInfo?.maxTokens } From 441f54d79278a2995e52157439d6dbc36f16881f Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Fri, 7 Mar 2025 23:36:46 -0500 Subject: [PATCH 05/15] Turn checkpoints on by default --- src/core/Cline.ts | 2 +- src/core/webview/ClineProvider.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/Cline.ts b/src/core/Cline.ts index 870db843b7..fd8ce3e9a2 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -158,7 +158,7 @@ export class Cline { apiConfiguration, customInstructions, enableDiff, - enableCheckpoints = false, + enableCheckpoints = true, checkpointStorage = "task", fuzzyMatchThreshold, task, diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 70feb45c2f..e1d67b5a28 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -2389,7 +2389,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { allowedCommands: stateValues.allowedCommands, soundEnabled: stateValues.soundEnabled ?? false, diffEnabled: stateValues.diffEnabled ?? true, - enableCheckpoints: stateValues.enableCheckpoints ?? false, + enableCheckpoints: stateValues.enableCheckpoints ?? true, checkpointStorage: stateValues.checkpointStorage ?? "task", soundVolume: stateValues.soundVolume, browserViewportSize: stateValues.browserViewportSize ?? "900x600", From 7f20a95e06ca913753da34027847b0a6c221d77e Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Sat, 8 Mar 2025 00:25:28 -0500 Subject: [PATCH 06/15] v3.8.1 --- .changeset/red-meals-report.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/red-meals-report.md diff --git a/.changeset/red-meals-report.md b/.changeset/red-meals-report.md new file mode 100644 index 0000000000..c9f3ceaef6 --- /dev/null +++ b/.changeset/red-meals-report.md @@ -0,0 +1,5 @@ +--- +"roo-cline": patch +--- + +v3.8.1 From 256f400c5dbb0307f861ba74ec59c0b4fa68d021 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 8 Mar 2025 05:27:04 +0000 Subject: [PATCH 07/15] changeset version bump --- .changeset/red-meals-report.md | 5 ----- CHANGELOG.md | 6 ++++++ package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) delete mode 100644 .changeset/red-meals-report.md diff --git a/.changeset/red-meals-report.md b/.changeset/red-meals-report.md deleted file mode 100644 index c9f3ceaef6..0000000000 --- a/.changeset/red-meals-report.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"roo-cline": patch ---- - -v3.8.1 diff --git a/CHANGELOG.md b/CHANGELOG.md index f3827d5201..cee105dae5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Roo Code Changelog +## 3.8.1 + +### Patch Changes + +- v3.8.1 + ## [3.8.0] - Add opt-in telemetry to help us improve Roo Code faster (thanks Cline!) diff --git a/package-lock.json b/package-lock.json index dfcbca3684..3b8f47c2e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "roo-cline", - "version": "3.8.0", + "version": "3.8.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "roo-cline", - "version": "3.8.0", + "version": "3.8.1", "dependencies": { "@anthropic-ai/bedrock-sdk": "^0.10.2", "@anthropic-ai/sdk": "^0.37.0", diff --git a/package.json b/package.json index 91b94525a1..5ddd9320f1 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "displayName": "Roo Code (prev. Roo Cline)", "description": "A whole dev team of AI agents in your editor.", "publisher": "RooVeterinaryInc", - "version": "3.8.0", + "version": "3.8.1", "icon": "assets/icons/rocket.png", "galleryBanner": { "color": "#617A91", From bb8e12724eb0170575f78ab1cb96f068c85f1e3b Mon Sep 17 00:00:00 2001 From: R00-B0T Date: Sat, 8 Mar 2025 05:27:29 +0000 Subject: [PATCH 08/15] Updating CHANGELOG.md format --- CHANGELOG.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cee105dae5..9f2a964021 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,6 @@ # Roo Code Changelog -## 3.8.1 - -### Patch Changes +## [3.8.1] - v3.8.1 From 8e9110f446ed2ab8452d81c11f4bcef23fe16a54 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Sat, 8 Mar 2025 00:34:01 -0500 Subject: [PATCH 09/15] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f2a964021..2e09b5834b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,13 @@ ## [3.8.1] -- v3.8.1 +- Show the reserved output tokens in the context window visualization +- Improve the UI of the configuration profile dropdown (thanks @DeXtroTip!) +- Fix bug where custom temperature could not be unchecked (thanks @System233!) +- Fix bug where decimal prices could not be entered for OpenAI-compatible providers (thanks @System233!) +- Fix bug with enhance prompt on Sonnet 3.7 with a high thinking budget (thanks @moqimoqidea!) +- Fix bug with the context window management for thinking models (thanks @ReadyPlayerEmma!) +- Fix bug where checkpoints were no longer enabled by default ## [3.8.0] From a74c0f37df7571f84531f98adec81b5bffcdec24 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Sat, 8 Mar 2025 00:35:01 -0500 Subject: [PATCH 10/15] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e09b5834b..73b0052f40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Fix bug with enhance prompt on Sonnet 3.7 with a high thinking budget (thanks @moqimoqidea!) - Fix bug with the context window management for thinking models (thanks @ReadyPlayerEmma!) - Fix bug where checkpoints were no longer enabled by default +- Add extension and VSCode versions to telemetry ## [3.8.0] From ebacc14b480df439caeeff2fe2e4ab6955868c06 Mon Sep 17 00:00:00 2001 From: cte Date: Fri, 7 Mar 2025 21:36:03 -0800 Subject: [PATCH 11/15] Fix settings dropdown issues --- webview-ui/package-lock.json | 224 ++++++++++++++++++ webview-ui/package.json | 1 + .../src/components/settings/ApiOptions.tsx | 124 ++++++---- webview-ui/src/components/ui/index.ts | 3 +- webview-ui/src/components/ui/select.tsx | 144 +++++++++++ 5 files changed, 449 insertions(+), 47 deletions(-) create mode 100644 webview-ui/src/components/ui/select.tsx diff --git a/webview-ui/package-lock.json b/webview-ui/package-lock.json index b52f8ab311..97960851c9 100644 --- a/webview-ui/package-lock.json +++ b/webview-ui/package-lock.json @@ -15,6 +15,7 @@ "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-popover": "^1.1.6", "@radix-ui/react-progress": "^1.1.2", + "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-separator": "^1.1.2", "@radix-ui/react-slider": "^1.2.3", "@radix-ui/react-slot": "^1.1.2", @@ -4688,6 +4689,229 @@ } } }, + "node_modules/@radix-ui/react-select": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.6.tgz", + "integrity": "sha512-T6ajELxRvTuAMWH0YmRJ1qez+x4/7Nq7QIx7zJ0VK3qaEWdnWpNbEDnmWldG1zBDwqrLy5aLMUWcoGirVj5kMg==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.0", + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-collection": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.5", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.2", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.2", + "@radix-ui/react-portal": "1.1.4", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-slot": "1.1.2", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-visually-hidden": "1.1.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-arrow": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.2.tgz", + "integrity": "sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-collection": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.2.tgz", + "integrity": "sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-slot": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz", + "integrity": "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz", + "integrity": "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-popper": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.2.tgz", + "integrity": "sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-rect": "1.1.0", + "@radix-ui/react-use-size": "1.1.0", + "@radix-ui/rect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-portal": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.4.tgz", + "integrity": "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-primitive": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", + "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-separator": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.2.tgz", diff --git a/webview-ui/package.json b/webview-ui/package.json index a178837ee0..589ccbf674 100644 --- a/webview-ui/package.json +++ b/webview-ui/package.json @@ -22,6 +22,7 @@ "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-popover": "^1.1.6", "@radix-ui/react-progress": "^1.1.2", + "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-separator": "^1.1.2", "@radix-ui/react-slider": "^1.2.3", "@radix-ui/react-slot": "^1.1.2", diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index 7736046048..c5a02dc117 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -4,6 +4,8 @@ import { Checkbox, Dropdown, type DropdownOption } from "vscrui" import { VSCodeLink, VSCodeRadio, VSCodeRadioGroup, VSCodeTextField } from "@vscode/webview-ui-toolkit/react" import * as vscodemodels from "vscode" +import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue, Button } from "@/components/ui" + import { ApiConfiguration, ModelInfo, @@ -42,7 +44,6 @@ import { TemperatureControl } from "./TemperatureControl" import { validateApiConfiguration, validateModelId } from "@/utils/validate" import { ApiErrorMessage } from "./ApiErrorMessage" import { ThinkingBudget } from "./ThinkingBudget" -import { Button } from "../ui" const modelsByProvider: Record> = { anthropic: anthropicModels, @@ -54,6 +55,25 @@ const modelsByProvider: Record> = { mistral: mistralModels, } +const providers = [ + { value: "openrouter", label: "OpenRouter" }, + { value: "anthropic", label: "Anthropic" }, + { value: "gemini", label: "Google Gemini" }, + { value: "deepseek", label: "DeepSeek" }, + { value: "openai-native", label: "OpenAI" }, + { value: "openai", label: "OpenAI Compatible" }, + { value: "vertex", label: "GCP Vertex AI" }, + { value: "bedrock", label: "AWS Bedrock" }, + { value: "glama", label: "Glama" }, + { value: "vscode-lm", label: "VS Code LM API" }, + { value: "mistral", label: "Mistral" }, + { value: "lmstudio", label: "LM Studio" }, + { value: "ollama", label: "Ollama" }, + { value: "unbound", label: "Unbound" }, + { value: "requesty", label: "Requesty" }, + { value: "human-relay", label: "Human Relay" }, +] + interface ApiOptionsProps { uriScheme: string | undefined apiConfiguration: ApiConfiguration @@ -238,30 +258,22 @@ const ApiOptions = ({ - + onValueChange={handleInputChange("apiProvider", dropdownEventTransform)}> + + + + + + {providers.map(({ value, label }) => ( + + {label} + + ))} + + + {errorMessage && } @@ -424,10 +436,10 @@ const ApiOptions = ({ <> + placeholder="Enter API Key..." + className="w-full"> Mistral API Key
@@ -575,16 +587,16 @@ const ApiOptions = ({
+ placeholder="Enter Credentials JSON..." + className="w-full"> Google Cloud Credentials + placeholder="Enter Key File Path..." + className="w-full"> Google Cloud Key File Path + placeholder="Enter API Key..." + className="w-full"> Gemini API Key
@@ -713,10 +725,13 @@ const ApiOptions = ({ } type="text" style={{ - width: "100%", borderColor: (() => { const value = apiConfiguration?.openAiCustomModelInfo?.maxTokens - if (!value) return "var(--vscode-input-border)" + + if (!value) { + return "var(--vscode-input-border)" + } + return value > 0 ? "var(--vscode-charts-green)" : "var(--vscode-errorForeground)" @@ -725,12 +740,14 @@ const ApiOptions = ({ title="Maximum number of tokens the model can generate in a single response" onInput={handleInputChange("openAiCustomModelInfo", (e) => { const value = parseInt((e.target as HTMLInputElement).value) + return { ...(apiConfiguration?.openAiCustomModelInfo || openAiModelInfoSaneDefaults), maxTokens: isNaN(value) ? undefined : value, } })} - placeholder="e.g. 4096"> + placeholder="e.g. 4096" + className="w-full"> Max Output Tokens
@@ -748,10 +765,13 @@ const ApiOptions = ({ } type="text" style={{ - width: "100%", borderColor: (() => { const value = apiConfiguration?.openAiCustomModelInfo?.contextWindow - if (!value) return "var(--vscode-input-border)" + + if (!value) { + return "var(--vscode-input-border)" + } + return value > 0 ? "var(--vscode-charts-green)" : "var(--vscode-errorForeground)" @@ -761,6 +781,7 @@ const ApiOptions = ({ onInput={handleInputChange("openAiCustomModelInfo", (e) => { const value = (e.target as HTMLInputElement).value const parsed = parseInt(value) + return { ...(apiConfiguration?.openAiCustomModelInfo || openAiModelInfoSaneDefaults), contextWindow: isNaN(parsed) @@ -768,7 +789,8 @@ const ApiOptions = ({ : parsed, } })} - placeholder="e.g. 128000"> + placeholder="e.g. 128000" + className="w-full"> Context Window Size
@@ -834,10 +856,13 @@ const ApiOptions = ({ } type="text" style={{ - width: "100%", borderColor: (() => { const value = apiConfiguration?.openAiCustomModelInfo?.inputPrice - if (!value && value !== 0) return "var(--vscode-input-border)" + + if (!value && value !== 0) { + return "var(--vscode-input-border)" + } + return value >= 0 ? "var(--vscode-charts-green)" : "var(--vscode-errorForeground)" @@ -846,12 +871,14 @@ const ApiOptions = ({ onChange={handleInputChange("openAiCustomModelInfo", (e) => { const value = (e.target as HTMLInputElement).value const parsed = parseFloat(value) + return { ...(apiConfiguration?.openAiCustomModelInfo ?? openAiModelInfoSaneDefaults), inputPrice: isNaN(parsed) ? openAiModelInfoSaneDefaults.inputPrice : parsed, } })} - placeholder="e.g. 0.0001"> + placeholder="e.g. 0.0001" + className="w-full">
Input Price { const value = apiConfiguration?.openAiCustomModelInfo?.outputPrice - if (!value && value !== 0) return "var(--vscode-input-border)" + + if (!value && value !== 0) { + return "var(--vscode-input-border)" + } + return value >= 0 ? "var(--vscode-charts-green)" : "var(--vscode-errorForeground)" @@ -884,12 +914,14 @@ const ApiOptions = ({ onChange={handleInputChange("openAiCustomModelInfo", (e) => { const value = (e.target as HTMLInputElement).value const parsed = parseFloat(value) + return { ...(apiConfiguration?.openAiCustomModelInfo || openAiModelInfoSaneDefaults), outputPrice: isNaN(parsed) ? openAiModelInfoSaneDefaults.outputPrice : parsed, } })} - placeholder="e.g. 0.0002"> + placeholder="e.g. 0.0002" + className="w-full">
Output Price + placeholder={"e.g. lmstudio-community/llama-3.2-1b-instruct"} + className="w-full"> Draft Model ID
diff --git a/webview-ui/src/components/ui/index.ts b/webview-ui/src/components/ui/index.ts index b444b37788..1a2456a72f 100644 --- a/webview-ui/src/components/ui/index.ts +++ b/webview-ui/src/components/ui/index.ts @@ -11,6 +11,7 @@ export * from "./popover" export * from "./progress" export * from "./separator" export * from "./slider" +export * from "./select-dropdown" +export * from "./select" export * from "./textarea" export * from "./tooltip" -export * from "./select-dropdown" diff --git a/webview-ui/src/components/ui/select.tsx b/webview-ui/src/components/ui/select.tsx new file mode 100644 index 0000000000..50f89b3760 --- /dev/null +++ b/webview-ui/src/components/ui/select.tsx @@ -0,0 +1,144 @@ +import * as React from "react" +import * as SelectPrimitive from "@radix-ui/react-select" +import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react" + +import { cn } from "@/lib/utils" + +function Select({ ...props }: React.ComponentProps) { + return +} + +function SelectGroup({ ...props }: React.ComponentProps) { + return +} + +function SelectValue({ ...props }: React.ComponentProps) { + return +} + +function SelectTrigger({ className, children, ...props }: React.ComponentProps) { + return ( + + {children} + + + + + ) +} + +function SelectContent({ + className, + children, + position = "popper", + ...props +}: React.ComponentProps) { + return ( + + + + + {children} + + + + + ) +} + +function SelectLabel({ className, ...props }: React.ComponentProps) { + return ( + + ) +} + +function SelectItem({ className, children, ...props }: React.ComponentProps) { + return ( + + + + + + + {children} + + ) +} + +function SelectSeparator({ className, ...props }: React.ComponentProps) { + return ( + + ) +} + +function SelectScrollUpButton({ className, ...props }: React.ComponentProps) { + return ( + + + + ) +} + +function SelectScrollDownButton({ + className, + ...props +}: React.ComponentProps) { + return ( + + + + ) +} + +export { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectScrollDownButton, + SelectScrollUpButton, + SelectSeparator, + SelectTrigger, + SelectValue, +} From 998cd3c32e7f32c9e3df8be15c9744b35ca535c0 Mon Sep 17 00:00:00 2001 From: cte Date: Fri, 7 Mar 2025 21:52:11 -0800 Subject: [PATCH 12/15] Fix tests --- .../settings/__tests__/ApiOptions.test.tsx | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/webview-ui/src/components/settings/__tests__/ApiOptions.test.tsx b/webview-ui/src/components/settings/__tests__/ApiOptions.test.tsx index 364e57a715..008c5819db 100644 --- a/webview-ui/src/components/settings/__tests__/ApiOptions.test.tsx +++ b/webview-ui/src/components/settings/__tests__/ApiOptions.test.tsx @@ -35,6 +35,31 @@ jest.mock("vscrui", () => ({ Pane: ({ children }: any) =>
{children}
, })) +// Mock @shadcn/ui components +jest.mock("@/components/ui", () => ({ + Select: ({ children, value, onValueChange }: any) => ( +
+ +
+ ), + SelectTrigger: ({ children }: any) =>
{children}
, + SelectValue: ({ children }: any) =>
{children}
, + SelectContent: ({ children }: any) =>
{children}
, + SelectGroup: ({ children }: any) =>
{children}
, + SelectItem: ({ children, value }: any) => ( + + ), + Button: ({ children, onClick }: any) => ( + + ), +})) + jest.mock("../TemperatureControl", () => ({ TemperatureControl: ({ value, onChange }: any) => (
From 471d832c7a3854c7625e0084e37186cbb6e18750 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Sat, 8 Mar 2025 01:34:23 -0500 Subject: [PATCH 13/15] Update CHANGELOG.md --- CHANGELOG.md | 54 ++++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73b0052f40..ff2aa8de27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Roo Code Changelog -## [3.8.1] +## [3.8.1] - 2025-03-07 - Show the reserved output tokens in the context window visualization - Improve the UI of the configuration profile dropdown (thanks @DeXtroTip!) @@ -11,7 +11,7 @@ - Fix bug where checkpoints were no longer enabled by default - Add extension and VSCode versions to telemetry -## [3.8.0] +## [3.8.0] - 2025-03-07 - Add opt-in telemetry to help us improve Roo Code faster (thanks Cline!) - Fix terminal overload / gray screen of death, and other terminal issues @@ -30,7 +30,7 @@ - Improve styling of the task headers (thanks @monotykamary!) - Improve context mention path handling on Windows (thanks @samhvw8!) -## [3.7.12] +## [3.7.12] - 2025-03-03 - Expand max tokens of thinking models to 128k, and max thinking budget to over 100k (thanks @monotykamary!) - Fix issue where keyboard mode switcher wasn't updating API profile (thanks @aheizi!) @@ -42,19 +42,19 @@ - Update the warning text for the VS LM API - Correctly populate the default OpenRouter model on the welcome screen -## [3.7.11] +## [3.7.11] - 2025-03-02 - Don't honor custom max tokens for non thinking models - Include custom modes in mode switching keyboard shortcut - Support read-only modes that can run commands -## [3.7.10] +## [3.7.10] - 2025-03-01 - Add Gemini models on Vertex AI (thanks @ashktn!) - Keyboard shortcuts to switch modes (thanks @aheizi!) - Add support for Mermaid diagrams (thanks Cline!) -## [3.7.9] +## [3.7.9] - 2025-03-01 - Delete task confirmation enhancements - Smarter context window management @@ -64,19 +64,19 @@ - UI fix to dropdown hover colors (thanks @SamirSaji!) - Add support for Claude Sonnet 3.7 thinking via Vertex AI (thanks @lupuletic!) -## [3.7.8] +## [3.7.8] - 2025-02-27 - Add Vertex AI prompt caching support for Claude models (thanks @aitoroses and @lupuletic!) - Add gpt-4.5-preview - Add an advanced feature to customize the system prompt -## [3.7.7] +## [3.7.7] - 2025-02-27 - Graduate checkpoints out of beta - Fix enhance prompt button when using Thinking Sonnet - Add tooltips to make what buttons do more obvious -## [3.7.6] +## [3.7.6] - 2025-02-26 - Handle really long text better in the in the ChatRow similar to TaskHeader (thanks @joemanley201!) - Support multiple files in drag-and-drop @@ -84,7 +84,7 @@ - Better OpenRouter error handling (no more "Provider Error") - Add slider to control max output tokens for thinking models -## [3.7.5] +## [3.7.5] - 2025-02-26 - Fix context window truncation math (see [#1173](https://github.com/RooVetGit/Roo-Code/issues/1173)) - Fix various issues with the model picker (thanks @System233!) @@ -92,48 +92,48 @@ - Add drag-and-drop for files - Enable the "Thinking Budget" slider for Claude 3.7 Sonnet on OpenRouter -## [3.7.4] +## [3.7.4] - 2025-02-25 - Fix a bug that prevented the "Thinking" setting from properly updating when switching profiles. -## [3.7.3] +## [3.7.3] - 2025-02-25 - Support for ["Thinking"](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking) Sonnet 3.7 when using the Anthropic provider. -## [3.7.2] +## [3.7.2] - 2025-02-24 - Fix computer use and prompt caching for OpenRouter's `anthropic/claude-3.7-sonnet:beta` (thanks @cte!) - Fix sliding window calculations for Sonnet 3.7 that were causing a context window overflow (thanks @cte!) - Encourage diff editing more strongly in the system prompt (thanks @hannesrudolph!) -## [3.7.1] +## [3.7.1] - 2025-02-24 - Add AWS Bedrock support for Sonnet 3.7 and update some defaults to Sonnet 3.7 instead of 3.5 -## [3.7.0] +## [3.7.0] - 2025-02-24 - Introducing Roo Code 3.7, with support for the new Claude Sonnet 3.7. Because who cares about skipping version numbers anymore? Thanks @lupuletic and @cte for the PRs! -## [3.3.26] +## [3.3.26] - 2025-02-27 - Adjust the default prompt for Debug mode to focus more on diagnosis and to require user confirmation before moving on to implementation -## [3.3.25] +## [3.3.25] - 2025-02-21 - Add a "Debug" mode that specializes in debugging tricky problems (thanks [Ted Werbel](https://x.com/tedx_ai/status/1891514191179309457) and [Carlos E. Perez](https://x.com/IntuitMachine/status/1891516362486337739)!) - Add an experimental "Power Steering" option to significantly improve adherence to role definitions and custom instructions -## [3.3.24] +## [3.3.24] - 2025-02-20 - Fixed a bug with region selection preventing AWS Bedrock profiles from being saved (thanks @oprstchn!) - Updated the price of gpt-4o (thanks @marvijo-code!) -## [3.3.23] +## [3.3.23] - 2025-02-20 - Handle errors more gracefully when reading custom instructions from files (thanks @joemanley201!) - Bug fix to hitting "Done" on settings page with unsaved changes (thanks @System233!) -## [3.3.22] +## [3.3.22] - 2025-02-20 - Improve the Provider Settings configuration with clear Save buttons and warnings about unsaved changes (thanks @System233!) - Correctly parse `` reasoning tags from Ollama models (thanks @System233!) @@ -143,7 +143,7 @@ - Fix a bug where the .roomodes file was not automatically created when adding custom modes from the Prompts tab - Allow setting a wildcard (`*`) to auto-approve all command execution (use with caution!) -## [3.3.21] +## [3.3.21] - 2025-02-17 - Fix input box revert issue and configuration loss during profile switch (thanks @System233!) - Fix default preferred language for zh-cn and zh-tw (thanks @System233!) @@ -152,7 +152,7 @@ - Fix system prompt to make sure Roo knows about all available modes - Enable streaming mode for OpenAI o1 -## [3.3.20] +## [3.3.20] - 2025-02-14 - Support project-specific custom modes in a .roomodes file - Add more Mistral models (thanks @d-oit and @bramburn!) @@ -160,7 +160,7 @@ - Add a setting to control the number of open editor tabs to tell the model about (665 is probably too many!) - Fix race condition bug with entering API key on the welcome screen -## [3.3.19] +## [3.3.19] - 2025-02-12 - Fix a bug where aborting in the middle of file writes would not revert the write - Honor the VS Code theme for dialog backgrounds @@ -168,7 +168,7 @@ - Add a help button that links to our new documentation site (which we would love help from the community to improve!) - Switch checkpoints logic to use a shadow git repository to work around issues with hot reloads and polluting existing repositories (thanks Cline for the inspiration!) -## [3.3.18] +## [3.3.18] - 2025-02-11 - Add a per-API-configuration model temperature setting (thanks @joemanley201!) - Add retries for fetching usage stats from OpenRouter (thanks @jcbdev!) @@ -179,18 +179,18 @@ - Fix logic error where automatic retries were waiting twice as long as intended - Rework the checkpoints code to avoid conflicts with file locks on Windows (sorry for the hassle!) -## [3.3.17] +## [3.3.17] - 2025-02-09 - Fix the restore checkpoint popover - Unset git config that was previously set incorrectly by the checkpoints feature -## [3.3.16] +## [3.3.16] - 2025-02-09 - Support Volcano Ark platform through the OpenAI-compatible provider - Fix jumpiness while entering API config by updating on blur instead of input - Add tooltips on checkpoint actions and fix an issue where checkpoints were overwriting existing git name/email settings - thanks for the feedback! -## [3.3.15] +## [3.3.15] - 2025-02-08 - Improvements to MCP initialization and server restarts (thanks @MuriloFP and @hannesrudolph!) - Add a copy button to the recent tasks (thanks @hannesrudolph!) From 9246cf8f6dbe0f2a429872ea16f4ab2666e13d88 Mon Sep 17 00:00:00 2001 From: yt3trees Date: Sat, 8 Mar 2025 20:23:53 +0900 Subject: [PATCH 14/15] Add o3-mini support to openai compatible --- src/api/providers/openai.ts | 68 +++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/api/providers/openai.ts b/src/api/providers/openai.ts index 9262f3b75a..caa99def09 100644 --- a/src/api/providers/openai.ts +++ b/src/api/providers/openai.ts @@ -66,6 +66,11 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl const deepseekReasoner = modelId.includes("deepseek-reasoner") const ark = modelUrl.includes(".volces.com") + if (modelId.startsWith("o3-mini")) { + yield* this.handleO3FamilyMessage(modelId, systemPrompt, messages) + return + } + if (this.options.openAiStreamingEnabled ?? true) { const systemMessage: OpenAI.Chat.ChatCompletionSystemMessageParam = { role: "system", @@ -169,6 +174,69 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl throw error } } + + private async *handleO3FamilyMessage( + modelId: string, + systemPrompt: string, + messages: Anthropic.Messages.MessageParam[], + ): ApiStream { + if (this.options.openAiStreamingEnabled ?? true) { + const stream = await this.client.chat.completions.create({ + model: "o3-mini", + messages: [ + { + role: "developer", + content: `Formatting re-enabled\n${systemPrompt}`, + }, + ...convertToOpenAiMessages(messages), + ], + stream: true, + stream_options: { include_usage: true }, + reasoning_effort: this.getModel().info.reasoningEffort, + }) + + yield* this.handleStreamResponse(stream) + } else { + const requestOptions: OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming = { + model: modelId, + messages: [ + { + role: "developer", + content: `Formatting re-enabled\n${systemPrompt}`, + }, + ...convertToOpenAiMessages(messages), + ], + } + + const response = await this.client.chat.completions.create(requestOptions) + + yield { + type: "text", + text: response.choices[0]?.message.content || "", + } + yield this.processUsageMetrics(response.usage) + } + } + + private async *handleStreamResponse(stream: AsyncIterable): ApiStream { + for await (const chunk of stream) { + const delta = chunk.choices[0]?.delta + if (delta?.content) { + yield { + type: "text", + text: delta.content, + } + } + + if (chunk.usage) { + yield { + type: "usage", + inputTokens: chunk.usage.prompt_tokens || 0, + outputTokens: chunk.usage.completion_tokens || 0, + } + } + } + } } export async function getOpenAiModels(baseUrl?: string, apiKey?: string) { From a186537a7f633d73526457d5ab18683c69bb1cb5 Mon Sep 17 00:00:00 2001 From: Yuto <57471763+yt3trees@users.noreply.github.com> Date: Sat, 8 Mar 2025 20:38:27 +0900 Subject: [PATCH 15/15] Create wild-dragons-leave.md --- .changeset/wild-dragons-leave.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/wild-dragons-leave.md diff --git a/.changeset/wild-dragons-leave.md b/.changeset/wild-dragons-leave.md new file mode 100644 index 0000000000..05320a4aa2 --- /dev/null +++ b/.changeset/wild-dragons-leave.md @@ -0,0 +1,5 @@ +--- +"roo-cline": patch +--- + +Add o3-mini support to openai compatible