Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e168cbd
Throttle calls to calculate task folder size
cte Apr 22, 2025
e72208f
feat: allow variable interpolation into the custom system prompt (#2863)
daniel-lxs Apr 23, 2025
6f26cb5
fix: allow opening files without workspace root (#1054)
hannesrudolph Apr 23, 2025
92171fe
Fix: Preserve editor state and prevent tab unpinning during diffs (#2…
seedlord Apr 23, 2025
40d1708
Bugfix/fix vscodellm model information (#2832)
QuinsZouls Apr 23, 2025
4563b53
Fix: focusInput open roo code panel (#2626) (#2817)
hongzio Apr 23, 2025
5059636
fix(mention): conditionally remove aftercursor content (#2732)
elianiva Apr 23, 2025
d3d96bc
feat: add `injectEnv` util, support env ref in mcp config (#2679)
NamesMT Apr 23, 2025
fd0fa0a
Update contributors list (#2867)
github-actions[bot] Apr 23, 2025
1ddc426
FakeAI "controller" object must not be copied (#2463)
wkordalski Apr 23, 2025
0570154
Remove unnecessary cost calculation from vscode-lm.ts (#2875)
d-oit Apr 23, 2025
0477226
Allow Amazon Bedrock Marketplace ARNs (#2874)
mlopezr Apr 23, 2025
558925a
OpenRouter Gemini caching (#2847)
cte Apr 23, 2025
95bed9a
v13.3.3 (#2876)
mrubens Apr 23, 2025
2689dbd
fix(chat): better loading feedback (#2750)
elianiva Apr 23, 2025
418e290
feat: add other useful variables to the custom system prompt (#2879)
daniel-lxs Apr 23, 2025
466328e
Use formatLargeNumber on token counts in task header (#2883)
cte Apr 23, 2025
3131a21
Package material icons in vsix (#2882)
cte Apr 23, 2025
9991f42
Gemini prompt caching (#2827)
cte Apr 23, 2025
2028dc7
PR feedback
cte Apr 23, 2025
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
5 changes: 5 additions & 0 deletions .changeset/shiny-wolves-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"roo-cline": patch
---

Use formatLargeNumber on token counts in task header
5 changes: 5 additions & 0 deletions .changeset/spotty-baboons-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"roo-cline": patch
---

13.3.3
5 changes: 5 additions & 0 deletions .changeset/tasty-pants-applaud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"roo-cline": patch
---

Package material icons in vsix
41 changes: 25 additions & 16 deletions .vscodeignore
Original file line number Diff line number Diff line change
@@ -1,38 +1,44 @@
# Default
.changeset/**
.github/**
.husky/**
.vscode/**
.vscode-test/**
out/**
out-integration/**
evals/**
e2e/**
coverage/**
node_modules/**
src/**
scripts/**
.gitignore
.yarnrc
esbuild.js
vsc-extension-quickstart.md
jest.*
**/tsconfig.json
**/.eslintrc.json
.prettierignore
**/*.map
**/*.ts
**/.vscode-test.*
**/.gitignore

# Custom
.nvmrc
.env.sample
.git-blame-ignore-revs
.gitconfig
.gitattributes
.prettierignore
.tool-versions
.vite-port
.nvmrc
.clinerules*
.roomodes
.rooignore
.roo/**
cline_docs/**
coverage/**
e2e/**
evals/**
locales/**
benchmark/**
.direnv/**
out/**
ellipsis.yaml
knip.json

# Ignore all webview-ui files except the build directory (https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/frameworks/hello-world-react-cra/.vscodeignore)
# Ignore all webview-ui files except the build directory.
# https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/frameworks/hello-world-react-cra/.vscodeignore
webview-ui/src/**
webview-ui/public/**
webview-ui/scripts/**
Expand All @@ -41,17 +47,20 @@ webview-ui/README.md
webview-ui/package.json
webview-ui/package-lock.json
webview-ui/node_modules/**
**/.gitignore

# Fix issue where codicons don't get packaged (https://github.com/microsoft/vscode-extension-samples/issues/692)
# Include codicons
!node_modules/@vscode/codicons/dist/codicon.css
!node_modules/@vscode/codicons/dist/codicon.ttf

# Include material icons
!node_modules/vscode-material-icons/generated/**

# Include default themes JSON files used in getTheme
!src/integrations/theme/default-themes/**

# Ignore doc assets
assets/docs/**

# Include icons and images
!assets/icons/**
!assets/images/**
Expand Down
48 changes: 24 additions & 24 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion evals/apps/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ const runExercise = async ({ run, task, server }: { run: Run; task: Task; server
ROO_CODE_IPC_SOCKET_PATH: taskSocketPath,
},
shell: "/bin/bash",
})`code --disable-workspace-trust -n ${workspacePath}`
})`code --disable-workspace-trust -W ${workspacePath}`

// Give VSCode some time to spawn before connecting to its unix socket.
await new Promise((resolve) => setTimeout(resolve, 3_000))
Expand Down
27 changes: 0 additions & 27 deletions flake.lock

This file was deleted.

28 changes: 0 additions & 28 deletions flake.nix

This file was deleted.

28 changes: 14 additions & 14 deletions locales/ca/README.md

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions locales/de/README.md

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions locales/es/README.md

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions locales/fr/README.md

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions locales/hi/README.md

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions locales/it/README.md

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions locales/ja/README.md

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions locales/ko/README.md

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions locales/pl/README.md

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions locales/pt-BR/README.md

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions locales/tr/README.md

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions locales/vi/README.md

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions locales/zh-CN/README.md

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions locales/zh-TW/README.md

Large diffs are not rendered by default.

16 changes: 14 additions & 2 deletions src/activate/registerCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,20 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
const { promptForCustomStoragePath } = await import("../shared/storagePathManager")
await promptForCustomStoragePath()
},
"roo-cline.focusInput": () => {
provider.postMessageToWebview({ type: "action", action: "focusInput" })
"roo-cline.focusInput": async () => {
try {
const panel = getPanel()
if (!panel) {
await vscode.commands.executeCommand("workbench.view.extension.roo-cline-ActivityBar")
} else if (panel === tabPanel) {
panel.reveal(vscode.ViewColumn.Active, false)
} else if (panel === sidebarPanel) {
await vscode.commands.executeCommand(`${ClineProvider.sideBarId}.focus`)
provider.postMessageToWebview({ type: "action", action: "focusInput" })
}
} catch (error) {
outputChannel.appendLine(`Error focusing input: ${error}`)
}
},
"roo.acceptInput": () => {
const visibleProvider = getVisibleProviderOrLog(outputChannel)
Expand Down
3 changes: 2 additions & 1 deletion src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export interface SingleCompletionHandler {
}

export interface ApiHandler {
createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream
createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], cacheKey?: string): ApiStream

getModel(): { id: string; info: ModelInfo }

/**
Expand Down
100 changes: 91 additions & 9 deletions src/api/providers/__tests__/gemini.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { Anthropic } from "@anthropic-ai/sdk"

import { GeminiHandler } from "../gemini"
import { geminiDefaultModelId } from "../../../shared/api"
import { geminiDefaultModelId, type ModelInfo } from "../../../shared/api"

const GEMINI_20_FLASH_THINKING_NAME = "gemini-2.0-flash-thinking-exp-1219"

Expand Down Expand Up @@ -72,18 +72,15 @@ describe("GeminiHandler", () => {

// Should have 3 chunks: 'Hello', ' world!', and usage info
expect(chunks.length).toBe(3)
expect(chunks[0]).toEqual({
type: "text",
text: "Hello",
})
expect(chunks[1]).toEqual({
type: "text",
text: " world!",
})
expect(chunks[0]).toEqual({ type: "text", text: "Hello" })
expect(chunks[1]).toEqual({ type: "text", text: " world!" })
expect(chunks[2]).toEqual({
type: "usage",
inputTokens: 10,
outputTokens: 5,
cacheReadTokens: undefined,
cacheWriteTokens: undefined,
thinkingTokens: undefined,
})

// Verify the call to generateContentStream
Expand Down Expand Up @@ -171,4 +168,89 @@ describe("GeminiHandler", () => {
expect(modelInfo.id).toBe(geminiDefaultModelId) // Default model
})
})

describe("calculateCost", () => {
// Mock ModelInfo based on gemini-1.5-flash-latest pricing (per 1M tokens)
// Removed 'id' and 'name' as they are not part of ModelInfo type directly
const mockInfo: ModelInfo = {
inputPrice: 0.125, // $/1M tokens
outputPrice: 0.375, // $/1M tokens
cacheWritesPrice: 0.125, // Assume same as input for test
cacheReadsPrice: 0.125 * 0.25, // Assume 0.25x input for test
contextWindow: 1_000_000,
maxTokens: 8192,
supportsPromptCache: true, // Enable cache calculations for tests
}

it("should calculate cost correctly based on input and output tokens", () => {
const inputTokens = 10000 // Use larger numbers for per-million pricing
const outputTokens = 20000
// Added non-null assertions (!) as mockInfo guarantees these values
const expectedCost =
(inputTokens / 1_000_000) * mockInfo.inputPrice! + (outputTokens / 1_000_000) * mockInfo.outputPrice!

const cost = handler.calculateCost({ info: mockInfo, inputTokens, outputTokens })
expect(cost).toBeCloseTo(expectedCost)
})

it("should return 0 if token counts are zero", () => {
// Note: The method expects numbers, not undefined. Passing undefined would be a type error.
// The calculateCost method itself returns undefined if prices are missing, but 0 if tokens are 0 and prices exist.
expect(handler.calculateCost({ info: mockInfo, inputTokens: 0, outputTokens: 0 })).toBe(0)
})

it("should handle only input tokens", () => {
const inputTokens = 5000
// Added non-null assertion (!)
const expectedCost = (inputTokens / 1_000_000) * mockInfo.inputPrice!
expect(handler.calculateCost({ info: mockInfo, inputTokens, outputTokens: 0 })).toBeCloseTo(expectedCost)
})

it("should handle only output tokens", () => {
const outputTokens = 15000
// Added non-null assertion (!)
const expectedCost = (outputTokens / 1_000_000) * mockInfo.outputPrice!
expect(handler.calculateCost({ info: mockInfo, inputTokens: 0, outputTokens })).toBeCloseTo(expectedCost)
})

it("should calculate cost with cache write tokens", () => {
const inputTokens = 10000
const outputTokens = 20000
const cacheWriteTokens = 5000
const CACHE_TTL = 5 // Match the constant in gemini.ts

// Added non-null assertions (!)
const expectedInputCost = (inputTokens / 1_000_000) * mockInfo.inputPrice!
const expectedOutputCost = (outputTokens / 1_000_000) * mockInfo.outputPrice!
const expectedCacheWriteCost =
mockInfo.cacheWritesPrice! * (cacheWriteTokens / 1_000_000) * (CACHE_TTL / 60)
const expectedCost = expectedInputCost + expectedOutputCost + expectedCacheWriteCost

const cost = handler.calculateCost({ info: mockInfo, inputTokens, outputTokens, cacheWriteTokens })
expect(cost).toBeCloseTo(expectedCost)
})

it("should calculate cost with cache read tokens", () => {
const inputTokens = 10000 // Total logical input
const outputTokens = 20000
const cacheReadTokens = 8000 // Part of inputTokens read from cache

const uncachedReadTokens = inputTokens - cacheReadTokens
// Added non-null assertions (!)
const expectedInputCost = (uncachedReadTokens / 1_000_000) * mockInfo.inputPrice!
const expectedOutputCost = (outputTokens / 1_000_000) * mockInfo.outputPrice!
const expectedCacheReadCost = mockInfo.cacheReadsPrice! * (cacheReadTokens / 1_000_000)
const expectedCost = expectedInputCost + expectedOutputCost + expectedCacheReadCost

const cost = handler.calculateCost({ info: mockInfo, inputTokens, outputTokens, cacheReadTokens })
expect(cost).toBeCloseTo(expectedCost)
})

it("should return undefined if pricing info is missing", () => {
// Create a copy and explicitly set a price to undefined
const incompleteInfo: ModelInfo = { ...mockInfo, outputPrice: undefined }
const cost = handler.calculateCost({ info: incompleteInfo, inputTokens: 1000, outputTokens: 1000 })
expect(cost).toBeUndefined()
})
})
})
Loading