Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e597921
fix: add image content support to MCP tool responses (#10874)
roomote[bot] Jan 31, 2026
a357c00
fix: transform tool blocks to text before condensing (EXT-624) (#10975)
daniel-lxs Feb 3, 2026
08f2fe2
refactor(read_file): Codex-inspired read_file refactor EXT-617 (#10981)
hannesrudolph Jan 29, 2026
10d9577
feat: allow import settings in initial welcome screen (#10994)
roomote[bot] Jan 31, 2026
db11712
fix(code-index): remove deprecated text-embedding-004 and migrate to …
roomote[bot] Feb 3, 2026
9d2907f
chore: treat extension .env as optional (#11116)
hannesrudolph Jan 30, 2026
fc71291
fix: sanitize tool_use_id in tool_result blocks to match API history …
daniel-lxs Jan 31, 2026
196d0d6
fix: queue messages during command execution instead of losing them (…
mrubens Jan 31, 2026
61edbb3
IPC fixes for task cancellation and queued messages (#11162)
cte Feb 2, 2026
6a562c0
feat: add support for AGENTS.local.md personal override files (#11183)
roomote[bot] Feb 4, 2026
6fbb60c
fix(cli): resolve race condition causing provider switch during mode …
cte Feb 5, 2026
bd3fbe7
chore: remove dead toolFormat code from getEnvironmentDetails (#11207)
roomote[bot] Feb 5, 2026
eae9c96
feat: extract translation and merge resolver modes into reusable skil…
roomote[bot] Feb 13, 2026
a45e9cc
feat: add Claude Opus 4.6 support across all providers (#11224)
hannesrudolph Feb 5, 2026
c24b9b4
feat: add gpt-5.3-codex model to OpenAI Codex provider (#11225)
roomote[bot] Feb 5, 2026
a50adc7
fix: prevent parent task state loss during orchestrator delegation (#…
hannesrudolph Feb 7, 2026
94e1f07
fix: make removeClineFromStack() delegation-aware to prevent orphaned…
roomote[bot] Feb 9, 2026
21f6c31
fix(reliability): prevent webview postMessage crashes and make dispos…
0xMink Feb 9, 2026
87cee09
fix: resolve race condition in new_task delegation that loses parent …
daniel-lxs Feb 9, 2026
761bef4
fix: serialize taskHistory writes and fix delegation status overwrite…
hannesrudolph Feb 9, 2026
b2340d7
Fix task resumption in the API module (#11369)
cte Feb 10, 2026
eb23efd
chore: clean up repo-facing mode rules (#11410)
hannesrudolph Feb 11, 2026
93806b7
fix: add maxReadFileLine to ExtensionState type for webview compatibi…
hannesrudolph Feb 14, 2026
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ bin/

# Local prompts and rules
/local-prompts
AGENTS.local.md

# Test environment
.test_env
Expand Down
12 changes: 8 additions & 4 deletions apps/cli/src/agent/extension-host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,12 +428,16 @@ export class ExtensionHost extends EventEmitter implements ExtensionHostInterfac
public markWebviewReady(): void {
this.isReady = true

// Send initial webview messages to trigger proper extension initialization.
// This is critical for the extension to start sending state updates properly.
this.sendToExtension({ type: "webviewDidLaunch" })

// Apply CLI settings to the runtime config and context proxy BEFORE
// sending webviewDidLaunch. This prevents a race condition where the
// webviewDidLaunch handler's first-time init sync reads default state
// (apiProvider: "anthropic") instead of the CLI-provided settings.
setRuntimeConfigValues("roo-cline", this.initialSettings as Record<string, unknown>)
this.sendToExtension({ type: "updateSettings", updatedSettings: this.initialSettings })

// Now trigger extension initialization. The context proxy should already
// have CLI-provided values when the webviewDidLaunch handler runs.
this.sendToExtension({ type: "webviewDidLaunch" })
}

public isInInitialSetup(): boolean {
Expand Down
7 changes: 3 additions & 4 deletions apps/vscode-e2e/src/suite/tools/read-file.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ suite.skip("Roo Code read_file Tool", function () {
}
})

test("Should read file with line range", async function () {
test("Should read file with slice offset/limit", async function () {
const api = globalThis.api
const messages: ClineMessage[] = []
let taskCompleted = false
Expand Down Expand Up @@ -446,7 +446,7 @@ suite.skip("Roo Code read_file Tool", function () {
alwaysAllowReadOnly: true,
alwaysAllowReadOnlyOutsideWorkspace: true,
},
text: `Use the read_file tool to read the file "${fileName}" and show me what's on lines 2, 3, and 4. The file contains lines like "Line 1", "Line 2", etc. Assume the file exists and you can read it directly.`,
text: `Use the read_file tool to read the file "${fileName}" using slice mode with offset=2 and limit=3 (1-based offset). The file contains lines like "Line 1", "Line 2", etc. After reading, show me the three lines you read.`,
})

// Wait for task completion
Expand All @@ -455,9 +455,8 @@ suite.skip("Roo Code read_file Tool", function () {
// Verify tool was executed
assert.ok(toolExecuted, "The read_file tool should have been executed")

// Verify the tool returned the correct lines (when line range is used)
// Verify the tool returned the correct lines (offset=2, limit=3 -> lines 2-4)
if (toolResult && (toolResult as string).includes(" | ")) {
// The result includes line numbers
assert.ok(
(toolResult as string).includes("2 | Line 2"),
"Tool result should include line 2 with line number",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ describe("CloudSettingsService - Response Parsing", () => {
version: 2,
defaultSettings: {
maxOpenTabsContext: 10,
maxReadFileLine: 1000,
},
allowList: {
allowAll: false,
Expand Down
4 changes: 2 additions & 2 deletions packages/evals/src/cli/runTaskInCli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ export const runTaskWithCli = async ({ run, task, publish, logger, jobToken }: R

if (rooTaskId && !isClientDisconnected) {
logger.info("cancelling task")
client.sendCommand({ commandName: TaskCommandName.CancelTask, data: rooTaskId })
client.sendCommand({ commandName: TaskCommandName.CancelTask })
await new Promise((resolve) => setTimeout(resolve, 5_000))
}

Expand All @@ -288,7 +288,7 @@ export const runTaskWithCli = async ({ run, task, publish, logger, jobToken }: R

if (rooTaskId && !isClientDisconnected) {
logger.info("closing task")
client.sendCommand({ commandName: TaskCommandName.CloseTask, data: rooTaskId })
client.sendCommand({ commandName: TaskCommandName.CloseTask })
await new Promise((resolve) => setTimeout(resolve, 2_000))
}

Expand Down
4 changes: 2 additions & 2 deletions packages/evals/src/cli/runTaskInVscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ export const runTaskInVscode = async ({ run, task, publish, logger, jobToken }:

if (rooTaskId && !isClientDisconnected) {
logger.info("cancelling task")
client.sendCommand({ commandName: TaskCommandName.CancelTask, data: rooTaskId })
client.sendCommand({ commandName: TaskCommandName.CancelTask })
await new Promise((resolve) => setTimeout(resolve, 5_000)) // Allow some time for the task to cancel.
}

Expand All @@ -289,7 +289,7 @@ export const runTaskInVscode = async ({ run, task, publish, logger, jobToken }:

if (rooTaskId && !isClientDisconnected) {
logger.info("closing task")
client.sendCommand({ commandName: TaskCommandName.CloseTask, data: rooTaskId })
client.sendCommand({ commandName: TaskCommandName.CloseTask })
await new Promise((resolve) => setTimeout(resolve, 2_000)) // Allow some time for the window to close.
}

Expand Down
4 changes: 2 additions & 2 deletions packages/types/src/__tests__/ipc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe("IPC Types", () => {
const result = taskCommandSchema.safeParse(resumeTaskCommand)
expect(result.success).toBe(true)

if (result.success) {
if (result.success && result.data.commandName === TaskCommandName.ResumeTask) {
expect(result.data.commandName).toBe("ResumeTask")
expect(result.data.data).toBe("non-existent-task-id")
}
Expand All @@ -45,7 +45,7 @@ describe("IPC Types", () => {
const result = taskCommandSchema.safeParse(resumeTaskCommand)
expect(result.success).toBe(true)

if (result.success) {
if (result.success && result.data.commandName === TaskCommandName.ResumeTask) {
expect(result.data.commandName).toBe("ResumeTask")
expect(result.data.data).toBe("task-123")
}
Expand Down
2 changes: 0 additions & 2 deletions packages/types/src/cloud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ export const organizationDefaultSettingsSchema = globalSettingsSchema
.pick({
enableCheckpoints: true,
maxOpenTabsContext: true,
maxReadFileLine: true,
maxWorkspaceFiles: true,
showRooIgnoredFiles: true,
terminalCommandDelay: true,
Expand All @@ -108,7 +107,6 @@ export const organizationDefaultSettingsSchema = globalSettingsSchema
.merge(
z.object({
maxOpenTabsContext: z.number().int().nonnegative().optional(),
maxReadFileLine: z.number().int().gte(-1).optional(),
maxWorkspaceFiles: z.number().int().nonnegative().optional(),
terminalCommandDelay: z.number().int().nonnegative().optional(),
terminalShellIntegrationTimeout: z.number().int().nonnegative().optional(),
Expand Down
9 changes: 8 additions & 1 deletion packages/types/src/events.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { z } from "zod"

import { clineMessageSchema, tokenUsageSchema } from "./message.js"
import { clineMessageSchema, queuedMessageSchema, tokenUsageSchema } from "./message.js"
import { toolNamesSchema, toolUsageSchema } from "./tool.js"

/**
Expand Down Expand Up @@ -35,6 +35,7 @@ export enum RooCodeEventName {
TaskModeSwitched = "taskModeSwitched",
TaskAskResponded = "taskAskResponded",
TaskUserMessage = "taskUserMessage",
QueuedMessagesUpdated = "queuedMessagesUpdated",

// Task Analytics
TaskTokenUsageUpdated = "taskTokenUsageUpdated",
Expand Down Expand Up @@ -100,6 +101,7 @@ export const rooCodeEventsSchema = z.object({
[RooCodeEventName.TaskModeSwitched]: z.tuple([z.string(), z.string()]),
[RooCodeEventName.TaskAskResponded]: z.tuple([z.string()]),
[RooCodeEventName.TaskUserMessage]: z.tuple([z.string()]),
[RooCodeEventName.QueuedMessagesUpdated]: z.tuple([z.string(), z.array(queuedMessageSchema)]),

[RooCodeEventName.TaskToolFailed]: z.tuple([z.string(), toolNamesSchema, z.string()]),
[RooCodeEventName.TaskTokenUsageUpdated]: z.tuple([z.string(), tokenUsageSchema, toolUsageSchema]),
Expand Down Expand Up @@ -217,6 +219,11 @@ export const taskEventSchema = z.discriminatedUnion("eventName", [
payload: rooCodeEventsSchema.shape[RooCodeEventName.TaskAskResponded],
taskId: z.number().optional(),
}),
z.object({
eventName: z.literal(RooCodeEventName.QueuedMessagesUpdated),
payload: rooCodeEventsSchema.shape[RooCodeEventName.QueuedMessagesUpdated],
taskId: z.number().optional(),
}),

// Task Analytics
z.object({
Expand Down
3 changes: 0 additions & 3 deletions packages/types/src/global-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ export const globalSettingsSchema = z.object({
allowedMaxCost: z.number().nullish(),
autoCondenseContext: z.boolean().optional(),
autoCondenseContextPercent: z.number().optional(),
maxConcurrentFileReads: z.number().optional(),

/**
* Whether to include current time in the environment details
Expand Down Expand Up @@ -173,7 +172,6 @@ export const globalSettingsSchema = z.object({
maxWorkspaceFiles: z.number().optional(),
showRooIgnoredFiles: z.boolean().optional(),
enableSubfolderRules: z.boolean().optional(),
maxReadFileLine: z.number().optional(),
maxImageFileSize: z.number().optional(),
maxTotalImageSize: z.number().optional(),

Expand Down Expand Up @@ -389,7 +387,6 @@ export const EVALS_SETTINGS: RooCodeSettings = {
maxWorkspaceFiles: 200,
maxGitStatusFiles: 20,
showRooIgnoredFiles: true,
maxReadFileLine: -1, // -1 to enable full file reading.

includeDiagnosticMessages: true,
maxDiagnosticMessages: 50,
Expand Down
2 changes: 0 additions & 2 deletions packages/types/src/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,9 @@ export const taskCommandSchema = z.discriminatedUnion("commandName", [
}),
z.object({
commandName: z.literal(TaskCommandName.CancelTask),
data: z.string(),
}),
z.object({
commandName: z.literal(TaskCommandName.CloseTask),
data: z.string(),
}),
z.object({
commandName: z.literal(TaskCommandName.ResumeTask),
Expand Down
22 changes: 22 additions & 0 deletions packages/types/src/providers/anthropic.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ModelInfo } from "../model.js"

// https://docs.anthropic.com/en/docs/about-claude/models
// https://platform.claude.com/docs/en/about-claude/pricing

export type AnthropicModelId = keyof typeof anthropicModels
export const anthropicDefaultModelId: AnthropicModelId = "claude-sonnet-4-5"
Expand Down Expand Up @@ -48,6 +49,27 @@ export const anthropicModels = {
},
],
},
"claude-opus-4-6": {
maxTokens: 128_000, // Overridden to 8k if `enableReasoningEffort` is false.
contextWindow: 200_000, // Default 200K, extendable to 1M with beta flag
supportsImages: true,
supportsPromptCache: true,
inputPrice: 5.0, // $5 per million input tokens (≤200K context)
outputPrice: 25.0, // $25 per million output tokens (≤200K context)
cacheWritesPrice: 6.25, // $6.25 per million tokens
cacheReadsPrice: 0.5, // $0.50 per million tokens
supportsReasoningBudget: true,
// Tiered pricing for extended context (requires beta flag)
tiers: [
{
contextWindow: 1_000_000, // 1M tokens with beta flag
inputPrice: 10.0, // $10 per million input tokens (>200K context)
outputPrice: 37.5, // $37.50 per million output tokens (>200K context)
cacheWritesPrice: 12.5, // $12.50 per million tokens (>200K context)
cacheReadsPrice: 1.0, // $1.00 per million tokens (>200K context)
},
],
},
"claude-opus-4-5-20251101": {
maxTokens: 32_000, // Overridden to 8k if `enableReasoningEffort` is false.
contextWindow: 200_000,
Expand Down
27 changes: 27 additions & 0 deletions packages/types/src/providers/bedrock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,30 @@ export const bedrockModels = {
maxCachePoints: 4,
cachableFields: ["system", "messages", "tools"],
},
"anthropic.claude-opus-4-6-v1:0": {
maxTokens: 8192,
contextWindow: 200_000, // Default 200K, extendable to 1M with beta flag 'context-1m-2025-08-07'
supportsImages: true,
supportsPromptCache: true,
supportsReasoningBudget: true,
inputPrice: 5.0, // $5 per million input tokens (≤200K context)
outputPrice: 25.0, // $25 per million output tokens (≤200K context)
cacheWritesPrice: 6.25, // $6.25 per million tokens
cacheReadsPrice: 0.5, // $0.50 per million tokens
minTokensPerCachePoint: 1024,
maxCachePoints: 4,
cachableFields: ["system", "messages", "tools"],
// Tiered pricing for extended context (requires beta flag 'context-1m-2025-08-07')
tiers: [
{
contextWindow: 1_000_000, // 1M tokens with beta flag
inputPrice: 10.0, // $10 per million input tokens (>200K context)
outputPrice: 37.5, // $37.50 per million output tokens (>200K context)
cacheWritesPrice: 12.5, // $12.50 per million tokens (>200K context)
cacheReadsPrice: 1.0, // $1.00 per million tokens (>200K context)
},
],
},
"anthropic.claude-opus-4-5-20251101-v1:0": {
maxTokens: 8192,
contextWindow: 200_000,
Expand Down Expand Up @@ -475,6 +499,7 @@ export const BEDROCK_REGIONS = [
export const BEDROCK_1M_CONTEXT_MODEL_IDS = [
"anthropic.claude-sonnet-4-20250514-v1:0",
"anthropic.claude-sonnet-4-5-20250929-v1:0",
"anthropic.claude-opus-4-6-v1:0",
] as const

// Amazon Bedrock models that support Global Inference profiles
Expand All @@ -483,11 +508,13 @@ export const BEDROCK_1M_CONTEXT_MODEL_IDS = [
// - Claude Sonnet 4.5
// - Claude Haiku 4.5
// - Claude Opus 4.5
// - Claude Opus 4.6
export const BEDROCK_GLOBAL_INFERENCE_MODEL_IDS = [
"anthropic.claude-sonnet-4-20250514-v1:0",
"anthropic.claude-sonnet-4-5-20250929-v1:0",
"anthropic.claude-haiku-4-5-20251001-v1:0",
"anthropic.claude-opus-4-5-20251101-v1:0",
"anthropic.claude-opus-4-6-v1:0",
] as const

// Amazon Bedrock Service Tier types
Expand Down
16 changes: 15 additions & 1 deletion packages/types/src/providers/openai-codex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type { ModelInfo } from "../model.js"

export type OpenAiCodexModelId = keyof typeof openAiCodexModels

export const openAiCodexDefaultModelId: OpenAiCodexModelId = "gpt-5.2-codex"
export const openAiCodexDefaultModelId: OpenAiCodexModelId = "gpt-5.3-codex"

/**
* Models available through the Codex OAuth flow.
Expand Down Expand Up @@ -54,6 +54,20 @@ export const openAiCodexModels = {
supportsTemperature: false,
description: "GPT-5.1 Codex: GPT-5.1 optimized for agentic coding via ChatGPT subscription",
},
"gpt-5.3-codex": {
maxTokens: 128000,
contextWindow: 400000,
includedTools: ["apply_patch"],
excludedTools: ["apply_diff", "write_to_file"],
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: ["low", "medium", "high", "xhigh"],
reasoningEffort: "medium",
inputPrice: 0,
outputPrice: 0,
supportsTemperature: false,
description: "GPT-5.3 Codex: OpenAI's flagship coding model via ChatGPT subscription",
},
"gpt-5.2-codex": {
maxTokens: 128000,
contextWindow: 400000,
Expand Down
6 changes: 4 additions & 2 deletions packages/types/src/providers/openrouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ export const OPEN_ROUTER_PROMPT_CACHING_MODELS = new Set([
"anthropic/claude-sonnet-4.5",
"anthropic/claude-opus-4",
"anthropic/claude-opus-4.1",
"anthropic/claude-haiku-4.5",
"anthropic/claude-opus-4.5",
"anthropic/claude-opus-4.6",
"anthropic/claude-haiku-4.5",
"google/gemini-2.5-flash-preview",
"google/gemini-2.5-flash-preview:thinking",
"google/gemini-2.5-flash-preview-05-20",
Expand Down Expand Up @@ -70,9 +71,10 @@ export const OPEN_ROUTER_REASONING_BUDGET_MODELS = new Set([
"anthropic/claude-3.7-sonnet:beta",
"anthropic/claude-opus-4",
"anthropic/claude-opus-4.1",
"anthropic/claude-opus-4.5",
"anthropic/claude-opus-4.6",
"anthropic/claude-sonnet-4",
"anthropic/claude-sonnet-4.5",
"anthropic/claude-opus-4.5",
"anthropic/claude-haiku-4.5",
"google/gemini-2.5-pro-preview",
"google/gemini-2.5-pro",
Expand Down
4 changes: 4 additions & 0 deletions packages/types/src/providers/vercel-ai-gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export const VERCEL_AI_GATEWAY_PROMPT_CACHING_MODELS = new Set([
"anthropic/claude-3.7-sonnet",
"anthropic/claude-opus-4",
"anthropic/claude-opus-4.1",
"anthropic/claude-opus-4.5",
"anthropic/claude-opus-4.6",
"anthropic/claude-sonnet-4",
"openai/gpt-4.1",
"openai/gpt-4.1-mini",
Expand Down Expand Up @@ -50,6 +52,8 @@ export const VERCEL_AI_GATEWAY_VISION_AND_TOOLS_MODELS = new Set([
"anthropic/claude-3.7-sonnet",
"anthropic/claude-opus-4",
"anthropic/claude-opus-4.1",
"anthropic/claude-opus-4.5",
"anthropic/claude-opus-4.6",
"anthropic/claude-sonnet-4",
"google/gemini-1.5-flash",
"google/gemini-1.5-pro",
Expand Down
Loading
Loading