Compare commits

..
Author SHA1 Message Date
Saoud Rizwan 3b47e515ef Update api.ts 2025-09-25 15:53:23 -07:00
Saoud Rizwan fd8f9eb12c Add gpt-5-codex 2025-09-25 15:50:08 -07:00
Saoud Rizwan d3cff6ac47 fix: search tool long regex string causing overflow in chatview 2025-09-24 23:38:25 -07:00
13af435103 v3.31.1 Release Notes (#6451)
* changeset version bump

* Updating CHANGELOG.md format

* Update changelog for version 3.31.1

Added details about installed CLI tools and renamed MCP tab.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
2025-09-24 23:08:59 -07:00
Saoud Rizwan 3b1477bc24 Rename MCP tab 'Installed' to 'Configure' (#5966)
* Rename MCP tab 'Installed' to 'Configure'

* Fix component name

* Fix errors; update docs

* Create green-wasps-brush.md
2025-09-24 23:05:23 -07:00
Saoud Rizwan 688f93db6d Show ToS update for cline account users 2025-09-24 23:00:41 -07:00
Saoud Rizwan a702270e85 Fix import linter error 2025-09-24 21:57:30 -07:00
Saoud Rizwan 03acada1b9 Fix padding in checkpoints error 2025-09-24 21:56:43 -07:00
adam jonesandSaoud Rizwan 95cca05f5e Add CLI tools detection to environment details (#5471)
- Auto-detect available CLI tools in system PATH
- Add detected tools to environment context for AI models
- Include comprehensive list of common developer tools (gh, docker, aws, etc.)
- Cross-platform support using 'which' on Unix and 'where' on Windows

---------

Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
2025-09-24 21:49:25 -07:00
Saoud Rizwan 33d77eb095 Copy changes 2025-09-24 21:16:25 -07:00
3e0c39acbb v3.31.0 Release Notes (#6379)
* changeset version bump

* Updating CHANGELOG.md format

* Update package.json

* Update changelog for version 3.31.0

Updated version to 3.31.0 and added new features and improvements.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
2025-09-24 18:33:47 -07:00
Saoud Rizwan 366d8a5411 Fix failing integration test due to duplicate test id 2025-09-24 18:25:13 -07:00
Saoud Rizwan d22596e5c2 Update announcement banner content (#6448) 2025-09-24 18:06:25 -07:00
Saoud Rizwan 7cc612dbce Fix right sidebar banner and docs (#6446) 2025-09-24 18:02:44 -07:00
Araandfrostbournesb f0cab63a43 Fixing icons and positioning for UI for voice mode (#6445)
* Minor UX fixes for voice mode

* Minor UX fixes for voice mode

* Minor UX fixes for voice mode

* Fix alignment of stop icon

---------

Co-authored-by: frostbournesb <frostbournesb@protonmail.com>
2025-09-24 16:20:27 -07:00
Saoud Rizwan 3c1b670b73 fix: cline not knowing plan/act mode if compact mode is enabled (#6443) 2025-09-24 15:31:42 -07:00
Ara 5de05d68ef Restricting voice mode to mac os only (#6442) 2025-09-24 15:15:44 -07:00
Saoud Rizwan 9b6b1c376c Revert focus chain design changes (#6441)
This reverts commit e5e26f45fa.

Revert "Update colors and width of focus chain (#6437)"

This reverts commit b794583b7a.

Revert "Update task header and focus chain UI design (#6415)"

This reverts commit 011b19225e.

Fix

Fix
2025-09-24 14:50:30 -07:00
Saoud Rizwan e5e26f45fa Decrease focus chain height 2025-09-24 13:55:31 -07:00
Saoud Rizwan b794583b7a Update colors and width of focus chain (#6437) 2025-09-24 13:44:54 -07:00
celestial-vault ca96bd8f62 add infobanner (#6294)
* add infobanner

* fix type and update docs url

* restructure test to not include brittle elements; it is not clear why this banner was even added to auth tests

* move update info banner logic into rpc
2025-09-24 13:37:40 -07:00
Bee 0ecdf8d0cc update CompactTaskButton tooltip content and styling (#6424) 2025-09-24 13:10:44 -07:00
41 changed files with 321 additions and 227 deletions
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Checkpoints multiroot pt.1: Accept array of workspaces when initializting checkpoints
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Support partial response validation via meta.expected
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Run Testing platform within Test workflow
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Refactor Task Header UI with interactive context window management
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
remove temperature settings in z.ai models
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Feature flags are now accessible too all users instead of authenticated users only.
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Update anthropic input token usage calculation
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Support new Cline endpoint auth flow
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Add speech-to-text dictation feature for Cline account users
+12
View File
@@ -1,5 +1,17 @@
# Changelog
## [3.31.1]
- Add installed useful CLI tools to environment details
- Rename MCP tab 'Installed' to 'Configure'
## [3.31.0]
- UI Improvements: New task header and focus chain design to take up less space for a cleaner experience
- Voice Mode: Experimental feature that must be enabled in settings for hands-free coding
- YOLO Mode: Enable in settings to let Cline approve all actions and automatically switch between plan/act mode
- Fix Oracle Code Assist provider issues
## [3.30.3]
- Add Oracle Code Assist provider
@@ -1,8 +1,10 @@
---
title: "Opening Cline in the Sidebar"
title: "Opening Cline in the Right Sidebar"
description: "Learn how to open Cline in the right sidebar in VS Code and Cursor"
---
By default, when you first install Cline, it appears in VS Code's left sidebar alongside your file explorer and other extensions. However, for a better coding experience, we recommend moving Cline to the right sidebar. This allows you to keep your project files visible in the left sidebar while chatting with Cline on the right, giving you full visibility of your codebase as Cline works on your project.
## VS Code
To open Cline in the right sidebar:
@@ -12,7 +14,7 @@ To open Cline in the right sidebar:
Make sure your extension view is aligned vertically to the left
</Step>
<Step title="Open Right Side View">
Click the button that opens the right side view in VS Code (the one VS Code uses for GitHub Copilot)
Click the button that opens the right side panel in VS Code (typically used to open GitHub Copilot chat). Optionally use the `Option + CMD/Ctrl + B` shortcut.
</Step>
<Step title="Drag Cline Icon">
Drag the Cline icon over to the nav panel at the top of that right view
@@ -32,13 +34,19 @@ To open Cline in the right sidebar:
<Steps>
<Step title="Align Extensions">
Make sure your extensions are [aligned vertically](https://cursor.com/docs/configuration/migrations/vscode#activity-bar-orientation) to the left
Cursor uses a horizontal activity bar by default to optimize space for the AI chat interface ([see here for details](https://cursor.com/docs/configuration/migrations/vscode#activity-bar-orientation)). To switch to vertical:
1. Open the Command Palette (`CMD/Ctrl + Shift + P`)
2. Search for "Preferences: Open Settings (UI)"
3. Search for `workbench.activityBar.orientation`
4. Set the value to `vertical`
5. Restart Cursor for the changes to take effect
</Step>
<Step title="Open Agent Panel">
Click the little cube button that opens Cursor's agent (right side view panel)
Click the Cursor cube icon button that opens Cursor's agent (right side view panel)
</Step>
<Step title="Drag to Three Dots">
Drag the Cline icon specifically to the three dots - it doesn't work if you just drag it to the top, it has to be the three dots
Drag the Cline icon directly onto the three dots button - it doesn't work if you just drag it to the top, it has to be the three dots
</Step>
</Steps>
+2 -2
View File
@@ -7,7 +7,7 @@ title: "Configuring MCP Servers"
Utilizing MCP servers will increase your token usage. Cline offers the ability to restrict or disable MCP server functionality as desired.
1. Click the "MCP Servers" icon in the top navigation bar of the Cline extension.
2. Select the "Installed" tab, and then Click the "Advanced MCP Settings" link at the bottom of that pane.
2. Select the "Configure" tab, and then Click the "Advanced MCP Settings" link at the bottom of that pane.
3. Cline will open a new settings window. find `Cline>Mcp:Mode` and make your selection from the dropdown menu.
<Frame>
@@ -56,7 +56,7 @@ To set the maximum time to wait for a response after a tool call to the MCP serv
Settings for all installed MCP servers are located in the `cline_mcp_settings.json` file:
1. Click the MCP Servers icon at the top navigation bar of the Cline pane.
2. Select the "Installed" tab.
2. Select the "Configure" tab.
3. Click the "Configure MCP Servers" button at the bottom of the pane.
The file uses a JSON format with a `mcpServers` object containing named server configurations:
+2 -2
View File
@@ -54,7 +54,7 @@ Please note: Smithery is maintained independently and is not affiliated with our
### Managing Installed MCP Servers
Once added, your MCP servers appear in the "Installed" tab where you can:
Once added, your MCP servers appear in the "Configure" tab where you can:
#### View Server Status
@@ -98,7 +98,7 @@ If a server fails to connect:
For advanced users, Cline stores MCP server configurations in a JSON file that can be modified:
1. In the "Installed" tab, click "Configure MCP Servers" to access the settings file
1. In the "Configure" tab, click "Configure MCP Servers" to access the settings file
2. The configuration for each server follows this format:
```json
+1 -1
View File
@@ -1,4 +1,4 @@
streamlit==1.43.2
streamlit>=1.28.0
plotly>=5.17.0
pandas>=2.0.0
numpy>=1.24.0
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "claude-dev",
"displayName": "Cline",
"description": "Autonomous coding agent right in your IDE, capable of creating/editing files, running commands, using the browser, and more with your permission every step of the way.",
"version": "3.30.3",
"version": "3.31.1",
"icon": "assets/icons/icon.png",
"engines": {
"vscode": "^1.84.0"
+1
View File
@@ -18,6 +18,7 @@ service StateService {
rpc updateSettings(UpdateSettingsRequest) returns (Empty);
rpc updateTelemetrySetting(TelemetrySettingRequest) returns (Empty);
rpc setWelcomeViewCompleted(BooleanRequest) returns (Empty);
rpc updateInfoBannerVersion(Int64Request) returns (Empty);
}
message DictationSettings {
bool feature_enabled = 1;
+4 -2
View File
@@ -719,6 +719,7 @@ export class Controller {
const mcpResponsesCollapsed = this.stateManager.getGlobalStateKey("mcpResponsesCollapsed")
const terminalOutputLineLimit = this.stateManager.getGlobalSettingsKey("terminalOutputLineLimit")
const favoritedModelIds = this.stateManager.getGlobalStateKey("favoritedModelIds")
const lastDismissedInfoBannerVersion = this.stateManager.getGlobalStateKey("lastDismissedInfoBannerVersion") || 0
const localClineRulesToggles = this.stateManager.getWorkspaceStateKey("localClineRulesToggles")
const localWindsurfRulesToggles = this.stateManager.getWorkspaceStateKey("localWindsurfRulesToggles")
@@ -741,10 +742,10 @@ export class Controller {
const distinctId = getDistinctId()
const version = ExtensionRegistryInfo.version
// Set feature flag in dictation settings
// Set feature flag in dictation settings based on platform
const updatedDictationSettings = {
...dictationSettings,
featureEnabled: true, // Currently hardcoded, was: featureFlagsService.getBooleanFlagEnabled(FeatureFlag.DICTATION, true)
featureEnabled: process.platform === "darwin", // Enable dictation only on macOS
}
return {
@@ -798,6 +799,7 @@ export class Controller {
user: this.stateManager.getGlobalStateKey("multiRootEnabled"),
featureFlag: featureFlagsService.getMultiRootEnabled(),
},
lastDismissedInfoBannerVersion,
}
}
@@ -0,0 +1,17 @@
import { Empty, Int64Request } from "@shared/proto/cline/common"
import { Controller } from ".."
/**
* Updates the info banner version to track which version the user has dismissed
* @param controller The controller instance
* @param request The request containing the version number
* @returns Empty response
*/
export async function updateInfoBannerVersion(controller: Controller, request: Int64Request): Promise<Empty> {
const version = Number(request.value)
controller.stateManager.setGlobalState("lastDismissedInfoBannerVersion", version)
await controller.postStateToWebview()
return Empty.create()
}
+1
View File
@@ -40,6 +40,7 @@ export interface GlobalState {
workspaceRoots: WorkspaceRoot[] | undefined
primaryRootIndex: number
multiRootEnabled: boolean
lastDismissedInfoBannerVersion: number
}
export interface Settings {
+3
View File
@@ -236,6 +236,8 @@ export async function readGlobalStateFromDisk(context: ExtensionContext): Promis
const mcpMarketplaceCatalog =
context.globalState.get<GlobalStateAndSettings["mcpMarketplaceCatalog"]>("mcpMarketplaceCatalog")
const lastDismissedInfoBannerVersion =
context.globalState.get<GlobalStateAndSettings["lastDismissedInfoBannerVersion"]>("lastDismissedInfoBannerVersion")
const qwenCodeOauthPath = context.globalState.get<GlobalStateAndSettings["qwenCodeOauthPath"]>("qwenCodeOauthPath")
const customPrompt = context.globalState.get<GlobalStateAndSettings["customPrompt"]>("customPrompt")
const autoCondenseThreshold =
@@ -557,6 +559,7 @@ export async function readGlobalStateFromDisk(context: ExtensionContext): Promis
qwenCodeOauthPath,
customPrompt,
autoCondenseThreshold: autoCondenseThreshold || 0.75, // default to 0.75 if not set
lastDismissedInfoBannerVersion: lastDismissedInfoBannerVersion ?? 0,
// Multi-root workspace support
workspaceRoots,
primaryRootIndex: primaryRootIndex ?? 0,
+11 -7
View File
@@ -56,7 +56,7 @@ import { convertClineMessageToProto } from "@shared/proto-conversions/cline-mess
import { ClineDefaultTool } from "@shared/tools"
import { ClineAskResponse } from "@shared/WebviewMessage"
import { getGitRemoteUrls, getLatestGitCommitHash } from "@utils/git"
import { isNextGenModelFamily } from "@utils/model-utils"
import { isLocalModel, isNextGenModelFamily } from "@utils/model-utils"
import { arePathsEqual, getDesktopDir } from "@utils/path"
import cloneDeep from "clone-deep"
import { execa } from "execa"
@@ -80,7 +80,7 @@ import { FocusChainManager } from "./focus-chain"
import { MessageStateHandler } from "./message-state"
import { TaskState } from "./TaskState"
import { ToolExecutor } from "./ToolExecutor"
import { updateApiReqMsg } from "./utils"
import { detectAvailableCliTools, updateApiReqMsg } from "./utils"
export type ToolResponse = string | Array<Anthropic.TextBlockParam | Anthropic.ImageBlockParam>
type UserContent = Array<Anthropic.ContentBlockParam>
@@ -1861,14 +1861,11 @@ export class Task {
"Issue with processing the /newrule command. Double check that, if '.clinerules' already exists, it's a directory and not a file. Otherwise there was an issue referencing this file/directory.",
)
}
// Compact prompt is tailored for models with small context window where environment details would often
// overflow the context window
const useCompactPrompt = customPrompt === "compact"
userContent = parsedUserContent
// add environment details as its own text block, separate from tool results
// do not add environment details to the message which we are compacting the context window
if (!shouldCompact && !useCompactPrompt) {
if (!shouldCompact) {
userContent.push({ type: "text", text: environmentDetails })
}
@@ -1879,10 +1876,11 @@ export class Task {
})
}
} else {
const useCompactPrompt = customPrompt === "compact" && isLocalModel(this.getCurrentProviderInfo())
const [parsedUserContent, environmentDetails, clinerulesError] = await this.loadContext(
userContent,
includeFileDetails,
customPrompt === "compact",
useCompactPrompt,
)
if (clinerulesError === true) {
@@ -2531,6 +2529,12 @@ export class Task {
if (latestGitHash) {
details += `\n\n# Latest Git Commit Hash\n${latestGitHash}`
}
// Add detected CLI tools
const availableCliTools = await detectAvailableCliTools()
if (availableCliTools.length > 0) {
details += `\n\n# Detected CLI Tools\nThese are some of the tools on the user's machine, and may be useful if needed to accomplish the task: ${availableCliTools.join(", ")}. This list is not exhaustive, and other tools may be available.`
}
}
// Add context window usage information
+73
View File
@@ -3,6 +3,7 @@ import { showSystemNotification } from "@/integrations/notifications"
import { ClineApiReqCancelReason, ClineApiReqInfo } from "@/shared/ExtensionMessage"
import { calculateApiCostAnthropic } from "@/utils/cost"
import { MessageStateHandler } from "./message-state"
import { execSync } from "child_process"
export const showNotificationForApprovalIfAutoApprovalEnabled = (
message: string,
@@ -59,3 +60,75 @@ export const updateApiReqMsg = async (params: UpdateApiReqMsgParams) => {
} satisfies ClineApiReqInfo),
})
}
/**
* Common CLI tools that developers frequently use
*/
const CLI_TOOLS = [
"gh",
"git",
"docker",
"podman",
"kubectl",
"aws",
"gcloud",
"az",
"terraform",
"pulumi",
"npm",
"yarn",
"pnpm",
"pip",
"cargo",
"go",
"curl",
"jq",
"make",
"cmake",
"python",
"node",
"psql",
"mysql",
"redis-cli",
"sqlite3",
"mongosh",
"code",
"grep",
"sed",
"awk",
"brew",
"apt",
"yum",
"gradle",
"mvn",
"bundle",
"dotnet",
"helm",
"ansible",
"wget",
]
/**
* Detect which CLI tools are available in the system PATH
* Uses 'which' command on Unix-like systems and 'where' on Windows
*/
export async function detectAvailableCliTools(): Promise<string[]> {
const availableCommands: string[] = []
const isWindows = process.platform === "win32"
const checkCommand = isWindows ? "where" : "which"
for (const command of CLI_TOOLS) {
try {
// Use execSync to check if the command exists
execSync(`${checkCommand} ${command}`, {
stdio: "ignore", // Don't output to console
timeout: 1000, // 1 second timeout to avoid hanging
})
availableCommands.push(command)
} catch (error) {
// Command not found, skip it
}
}
return availableCommands
}
+1 -1
View File
@@ -5,7 +5,7 @@ export interface DictationSettings {
}
export const DEFAULT_DICTATION_SETTINGS: DictationSettings = {
featureEnabled: true, // Feature flag, currently hardcoded to true
featureEnabled: false, // Feature flag, will be set by the extension based on platform
dictationEnabled: false, // Default is false while this service is in Experimental status
dictationLanguage: "en",
}
+1
View File
@@ -80,6 +80,7 @@ export interface ExtensionState {
primaryRootIndex: number
isMultiRootWorkspace: boolean
multiRootSetting: ClineFeatureSetting
lastDismissedInfoBannerVersion: number
}
export interface ClineMessage {
+9
View File
@@ -1116,6 +1116,15 @@ export const geminiModels = {
export type OpenAiNativeModelId = keyof typeof openAiNativeModels
export const openAiNativeDefaultModelId: OpenAiNativeModelId = "gpt-5-2025-08-07"
export const openAiNativeModels = {
"gpt-5-codex": {
maxTokens: 8_192,
contextWindow: 400000,
supportsImages: true,
supportsPromptCache: true,
inputPrice: 1.25,
outputPrice: 10.0,
cacheReadsPrice: 0.125,
},
"gpt-5-2025-08-07": {
maxTokens: 8_192, // 128000 breaks context window truncation
contextWindow: 272000,
+1 -1
View File
@@ -111,4 +111,4 @@ export interface McpDownloadResponse {
requiresApiKey: boolean
}
export type McpViewTab = "marketplace" | "addRemote" | "installed"
export type McpViewTab = "marketplace" | "addRemote" | "configure"
-14
View File
@@ -48,19 +48,6 @@ e2e("Views - can set up API keys and navigate to Settings from Chat", async ({ s
const chatInputBox = sidebar.getByTestId("chat-input")
await expect(chatInputBox).toBeVisible()
// Verify the help improve banner is visible and can be closed.
const telemetryBanner = sidebar.getByText("Help Improve Cline")
await expect(telemetryBanner).toBeVisible()
await sidebar.getByText("settings").click() // Click on the settings link in the banner
await expect(sidebar.getByText("General Settings")).toBeVisible() // Default view should be set to General tab
await sidebar.getByTestId("tab-api-config").click()
await expect(sidebar.locator("h4").getByText("API Configuration")).toBeVisible()
await sidebar.getByTestId("tab-about").click()
await expect(sidebar.getByRole("heading", { name: "About" }).locator("div").first()).toBeVisible()
// Exit the Settings view by clicking the Done button
await sidebar.getByRole("button", { name: "Done" }).click()
// Verify the release banner is visible for new installs and can be closed.
const releaseBanner = sidebar.getByRole("heading", {
name: /^🎉 New in v\d/,
@@ -68,5 +55,4 @@ e2e("Views - can set up API keys and navigate to Settings from Chat", async ({ s
await expect(releaseBanner).toBeVisible()
await sidebar.getByTestId("close-button").locator("span").first().click()
await expect(releaseBanner).not.toBeVisible()
await expect(telemetryBanner).not.toBeVisible()
})
+50 -30
View File
@@ -104,36 +104,56 @@ const Announcement = ({ version, hideAnnouncement }: AnnouncementProps) => {
<h3 style={h3TitleStyle}>
🎉{" "}New in v{minorVersion}
</h3>
<b>Free Stealth Model 🥷:</b> Try code-supernova, an agentic coding model built for Cline with 200k context window and
multi-modal support!
<div style={{ margin: "8px 0" }} />
{user ? (
!didClickCodeSupernovaButton ? (
<VSCodeButton appearance="primary" onClick={setCodeSupernova}>
Try code-supernova
</VSCodeButton>
) : null
) : null}
<div style={{ margin: "12px 0" }} />
<b>Continued Grok Promotion:</b> Free grok-code-fast-1 access extended!
<div style={{ margin: "10px 0" }} />
{user ? (
!didClickGrokCodeButton ? (
<VSCodeButton appearance="primary" onClick={setGrokCodeFast1}>
Try grok-code-fast-1
</VSCodeButton>
) : null
) : (
<VSCodeButton appearance="primary" onClick={handleShowAccount}>
Sign Up with Cline
</VSCodeButton>
)}
<div style={{ margin: "12px 0" }} />
<b>JetBrains Support is Live!</b>
<br />
Use Cline in IntelliJ IDEA, PyCharm, WebStorm, Android Studio, GoLand, PhpStorm, and all JetBrains IDEs.
<div style={{ margin: "10px 0" }} />
<VSCodeButtonLink href="https://cline.bot/jetbrains">Get Cline for JetBrains!</VSCodeButtonLink>
<ul style={ulStyle}>
<li>
<b>UI Improvements:</b> New task header and focus chain design to take up less space for a cleaner experience
</li>
<li>
<b>Voice Mode:</b> Experimental feature that must be enabled in settings for hands-free coding
</li>
<li>
<b>YOLO Mode:</b> Enable in settings to let Cline approve all actions and automatically switch between
plan/act mode
</li>
<li>
<b>JetBrains Updates:</b> We've brought support to Rider and made tons of improvements thanks to all the
feedback!
<br />
<VSCodeButtonLink href="https://cline.bot/jetbrains" style={{ margin: "5px 0" }}>
Get Cline for JetBrains
</VSCodeButtonLink>
</li>
<li>
<b>Continued Free Models:</b> Try grok-code-fast-1 or code-supernova (stealth model 🥷)!
<br />
{user ? (
<div style={{ display: "flex", gap: "8px", flexWrap: "wrap", margin: "5px 0" }}>
{!didClickGrokCodeButton && (
<VSCodeButton appearance="primary" onClick={setGrokCodeFast1}>
Try grok-code-fast-1
</VSCodeButton>
)}
{!didClickCodeSupernovaButton && (
<VSCodeButton appearance="primary" onClick={setCodeSupernova}>
Try code-supernova
</VSCodeButton>
)}
</div>
) : (
<VSCodeButton appearance="primary" onClick={handleShowAccount} style={{ margin: "5px 0" }}>
Sign Up with Cline
</VSCodeButton>
)}
</li>
{user && (
<li>
Updated the Terms of Service for Cline account users:{" "}
<VSCodeLink href="https://cline.bot/tos" style={linkStyle}>
https://cline.bot/tos
</VSCodeLink>
</li>
)}
</ul>
<div style={{ margin: "12px 0" }} />
<div style={{ margin: "-8px 0 -3px 0" }}>
<Accordion className="pl-0" isCompact>
+2 -1
View File
@@ -586,7 +586,8 @@ export const ChatRowContent = memo(
{tool.operationIsLocatedInWorkspace === false &&
toolIcon("sign-out", "yellow", -90, "This is outside of your workspace")}
<span style={{ fontWeight: "bold" }}>
Cline wants to search this directory for <code>{tool.regex}</code>:
Cline wants to search this directory for{" "}
<code style={{ wordBreak: "break-all" }}>{tool.regex}</code>:
</span>
</div>
<SearchResultsDisplay
@@ -1436,7 +1436,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
{isVoiceRecording && (
<div
className={cn(
"absolute pointer-events-none z-10 overflow-hidden rounded-xs transition-all ease-in-out duration-300 left-2.5 right-2.5 top-2.5 bottom-2.5",
"absolute pointer-events-none z-10 overflow-hidden rounded-xs transition-all ease-in-out duration-300 left-3.5 right-3.5 top-2.5 bottom-2.5",
)}>
<PulsingBorder
bloom={1}
@@ -1458,7 +1458,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
speed={1.5}
spotSize={0.5}
spots={4}
thickness={0.05}
thickness={0.1}
/>
</div>
)}
@@ -95,7 +95,7 @@ const ServersToggleModal: React.FC = () => {
aria-label="Go to MCP server settings"
onClick={() => {
setIsVisible(false)
navigateToMcp("installed")
navigateToMcp("configure")
}}>
<span className="codicon codicon-gear text-[10px]"></span>
</VSCodeButton>
@@ -260,7 +260,7 @@ const VoiceRecorder: React.FC<VoiceRecorderProps> = ({
content={`Stop Recording (${formatSeconds(recordingDuration)}/${formatSeconds(MAX_DURATION)})`}
placement="top">
<div
className={cn("input-icon-button mr-1.5 text-base", iconAdjustment, iconAnimation, {
className={cn("input-icon-button mr-1.5 text-error", iconAdjustment, iconAnimation, {
disabled: disabled || isProcessing,
})}
onClick={handleStopClick}>
@@ -269,7 +269,7 @@ const VoiceRecorder: React.FC<VoiceRecorderProps> = ({
</HeroTooltip>
<HeroTooltip content="Cancel Recording" placement="top">
<div
className={`input-icon-button text-base mt-1 text-foreground ${disabled || isProcessing ? "disabled" : ""}`}
className={`input-icon-button text-base ${isRecording ? "mt-0.5" : "mt-1"} text-foreground ${disabled || isProcessing ? "disabled" : ""}`}
onClick={handleCancelClick}>
<span className="codicon codicon-close" />
</div>
@@ -1,14 +1,15 @@
import React from "react"
import Announcement from "@/components/chat/Announcement"
import TelemetryBanner from "@/components/common/TelemetryBanner"
import InfoBanner, { CURRENT_INFO_BANNER_VERSION } from "@/components/common/InfoBanner"
import HistoryPreview from "@/components/history/HistoryPreview"
import HomeHeader from "@/components/welcome/HomeHeader"
import { SuggestedTasks } from "@/components/welcome/SuggestedTasks"
import { useExtensionState } from "@/context/ExtensionStateContext"
import { WelcomeSectionProps } from "../../types/chatTypes"
/**
* Welcome section shown when there's no active task
* Includes telemetry banner, announcements, home header, and history preview
* Includes info banner, announcements, home header, and history preview
*/
export const WelcomeSection: React.FC<WelcomeSectionProps> = ({
showAnnouncement,
@@ -19,10 +20,14 @@ export const WelcomeSection: React.FC<WelcomeSectionProps> = ({
taskHistory,
shouldShowQuickWins,
}) => {
const { lastDismissedInfoBannerVersion } = useExtensionState()
const shouldShowInfoBanner = lastDismissedInfoBannerVersion < CURRENT_INFO_BANNER_VERSION
return (
<div className="flex flex-col flex-1 w-full h-full p-0 m-0">
<div className="overflow-y-auto flex flex-col pb-2.5">
{telemetrySetting === "unset" && <TelemetryBanner />}
{shouldShowInfoBanner && <InfoBanner />}
{showAnnouncement && <Announcement hideAnnouncement={hideAnnouncement} version={version} />}
<HomeHeader shouldShowQuickWins={shouldShowQuickWins} />
{!shouldShowQuickWins && taskHistory.length > 0 && <HistoryPreview showHistoryView={showHistoryView} />}
@@ -26,7 +26,7 @@ export const CheckpointError: React.FC<CheckpointErrorProps> = ({
return (
<div className="flex items-center justify-center w-full">
<Alert
className="rounded-sm border-0 bg-[var(--vscode-inputValidation-errorBackground)] text-[var(--vscode-inputValidation-errorForeground)] pl-1 pr-1.5 py-0"
className="rounded-sm border-0 bg-[var(--vscode-inputValidation-errorBackground)] text-[var(--vscode-inputValidation-errorForeground)] pl-1 pr-1.5 py-1"
color="warning"
description={
<div className="flex gap-2">
@@ -1,7 +1,7 @@
import { cn } from "@heroui/react"
import { isCompletedFocusChainItem, isFocusChainItem } from "@shared/focus-chain-utils"
import { StringRequest } from "@shared/proto/cline/common"
import { ChevronDownIcon, ChevronRightIcon, PencilIcon } from "lucide-react"
import { ChevronDownIcon, ChevronRightIcon } from "lucide-react"
import React, { memo, useCallback, useMemo, useState } from "react"
import ChecklistRenderer from "@/components/common/ChecklistRenderer"
import { FileServiceClient } from "@/services/grpc-client"
@@ -31,30 +31,46 @@ const ToDoListHeader = memo<{
todoInfo: TodoInfo
isExpanded: boolean
}>(({ todoInfo, isExpanded }) => {
const { currentTodo, currentIndex, totalCount, completedCount } = todoInfo
const { currentTodo, currentIndex, totalCount, completedCount, progressPercentage } = todoInfo
const isCompleted = completedCount === totalCount
// Pre-compute display text
const displayText = isCompleted ? COMPLETED_MESSAGE : currentTodo?.text || TODO_LIST_LABEL
return (
<div className="flex items-center justify-between gap-2 z-10 py-2.5 px-1.5 relative">
<div className="flex items-center gap-1.5 flex-1 min-w-0">
<span
className={cn(
"rounded-lg px-2 py-0.25 text-xs inline-block shrink-0 bg-badge-foreground/20 text-foreground",
{
"bg-success text-black": isCompleted,
},
)}>
{currentIndex}/{totalCount}
</span>
<span className="header-text text-xs font-medium break-words overflow-hidden text-ellipsis whitespace-nowrap">
{displayText}
</span>
</div>
<div className="flex items-center justify-between text-foreground">
{isExpanded ? <ChevronDownIcon className="ml-0.25" size="16" /> : <ChevronRightIcon size="16" />}
<div
className={cn("relative w-full h-full", {
"text-success": isCompleted,
})}>
<div
className={cn(
"absolute bottom-0 left-0 transition-[width] duration-300 ease-in-out pointer-events-none z-1 h-1 bg-success",
{
"opacity-0": progressPercentage === 0 || progressPercentage === 100,
},
)}
style={{
width: `${progressPercentage}%`,
}}
/>
<div className="flex items-center justify-between gap-2 z-10 py-2.5 px-1.5">
<div className="flex items-center gap-1.5 flex-1 min-w-0">
<span
className={cn(
"rounded-lg px-2 py-0.25 text-xs inline-block shrink-0 bg-badge-foreground/20 text-foreground",
{
"bg-success text-black": isCompleted,
},
)}>
{currentIndex}/{totalCount}
</span>
<span className="header-text text-xs font-medium break-words overflow-hidden text-ellipsis whitespace-nowrap max-w-[calc(100%-60px)]">
{displayText}
</span>
</div>
<div className="flex items-center justify-between text-foreground">
{isExpanded ? <ChevronDownIcon className="ml-0.25" size="16" /> : <ChevronRightIcon size="16" />}
</div>
</div>
</div>
)
@@ -142,7 +158,6 @@ const parseCurrentTodoInfo = (text: string): TodoInfo | null => {
export const FocusChain: React.FC<FocusChainProps> = memo(
({ currentTaskItemId, lastProgressMessageText }) => {
const [isExpanded, setIsExpanded] = useState(false)
const [isHoveringList, setIsHoveringList] = useState(false)
// Parse todo info with caching
const todoInfo = useMemo(
@@ -173,78 +188,18 @@ export const FocusChain: React.FC<FocusChainProps> = memo(
return (
<div
className="relative flex flex-col gap-1.5 select-none overflow-hidden transition-[transform,box-shadow] duration-200 cursor-pointer hover:brightness-120"
className="relative rounded-sm bg-toolbar-hover/65 flex flex-col gap-1.5 select-none hover:bg-toolbar-hover overflow-hidden opacity-80 hover:opacity-100 transition-[transform,box-shadow] duration-200 cursor-pointer"
onClick={handleToggle}
style={{
backgroundColor: "color-mix(in srgb, var(--vscode-progressBar-background) 40%, transparent)",
borderTopLeftRadius: 0,
borderTopRightRadius: 0,
borderBottomLeftRadius: "4px",
borderBottomRightRadius: "4px",
borderLeft: "1px solid color-mix(in srgb, var(--vscode-progressBar-background) 50%, transparent)",
borderRight: "1px solid color-mix(in srgb, var(--vscode-progressBar-background) 50%, transparent)",
borderBottom: "1px solid color-mix(in srgb, var(--vscode-progressBar-background) 50%, transparent)",
width: "calc(100% - 14px)",
marginLeft: "7px",
marginTop: "-5.5px",
}}
title={CLICK_TO_EDIT_TITLE}>
{/* Progress bar background */}
<div
className="absolute inset-0 pointer-events-none"
style={{
background: `linear-gradient(to right, var(--vscode-progressBar-background) ${todoInfo.progressPercentage}%, transparent ${todoInfo.progressPercentage}%)`,
opacity: 0.3,
transition: "all 0.3s ease-in-out",
}}
/>
{/* Content with higher z-index */}
<div className="relative z-10">
<ToDoListHeader isExpanded={isExpanded} todoInfo={todoInfo} />
{isExpanded && (
<div
className="mx-1 pb-2 px-1 relative group cursor-pointer"
onClick={handleEditClick}
onMouseEnter={() => setIsHoveringList(true)}
onMouseLeave={() => setIsHoveringList(false)}>
<style>
{`
.focuschain-thin-scrollbar::-webkit-scrollbar {
width: 2px;
}
.focuschain-thin-scrollbar::-webkit-scrollbar-track {
background: transparent;
}
.focuschain-thin-scrollbar::-webkit-scrollbar-thumb {
background: var(--vscode-scrollbarSlider-background);
border-radius: 1px;
}
.focuschain-thin-scrollbar::-webkit-scrollbar-thumb:hover {
background: var(--vscode-scrollbarSlider-hoverBackground);
}
.focuschain-thin-scrollbar {
scrollbar-width: thin;
scrollbar-color: var(--vscode-scrollbarSlider-background) transparent;
}
`}
</style>
<div className="focuschain-thin-scrollbar">
<ChecklistRenderer text={lastProgressMessageText!} />
</div>
{/* {isCompleted && (
<div className="mt-2 text-xs font-semibold text-muted-foreground">{NEW_STEPS_MESSAGE}</div>
)} */}
{/* Pencil icon on hover */}
<div
className={cn("absolute bottom-2 right-2", isHoveringList ? "opacity-60" : "opacity-0")}
style={{
pointerEvents: "none",
}}>
<PencilIcon className="text-foreground" size={14} />
</div>
</div>
)}
</div>
<ToDoListHeader isExpanded={isExpanded} todoInfo={todoInfo} />
{isExpanded && (
<div className="mx-1 pb-2 px-1 relative" onClick={handleEditClick}>
<ChecklistRenderer text={lastProgressMessageText!} />
{isCompleted && (
<div className="mt-2 text-xs font-semibold text-muted-foreground">{NEW_STEPS_MESSAGE}</div>
)}
</div>
)}
</div>
)
},
@@ -9,11 +9,10 @@ const CompactTaskButton: React.FC<{
return (
<Tooltip
content={
<div className="flex flex-col gap-1.5 bg-menu rounded shadow-sm border border-menu-border z-100 max-w-xs p-4">
<div className="text-sm font-medium">Compact Task</div>
<div className="text-sm text-muted-foreground">
Reduces the number of tokens used by summarizing the task. To enable automatic condensing, turn on{" "}
<kbd>Auto Compact</kbd> in the settings and set the threshold by clicking on the context window usage bar.
<div className="flex flex-col gap-1 bg-menu rounded shadow-sm border border-menu-border z-100 max-w-xs py-1 px-2">
<div className="text-xs font-medium">Compact Task</div>
<div className="text-xs text-muted-foreground">
Reduces the number of tokens used by summarizing the task.
</div>
</div>
}
@@ -0,0 +1,41 @@
import { Int64Request } from "@shared/proto/cline/common"
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
import { useCallback } from "react"
import { StateServiceClient } from "@/services/grpc-client"
export const CURRENT_INFO_BANNER_VERSION = 1
export const InfoBanner: React.FC = () => {
const handleClose = useCallback((e: React.MouseEvent) => {
e.preventDefault()
e.stopPropagation()
const request = Int64Request.create({
value: CURRENT_INFO_BANNER_VERSION,
})
StateServiceClient.updateInfoBannerVersion(request).catch(console.error)
}, [])
return (
<a
className="bg-banner-background px-3 py-2 flex flex-col gap-1 shrink-0 mb-1 relative text-sm m-4 no-underline transition-colors hover:brightness-120"
href="https://docs.cline.bot/features/customization/opening-cline-in-sidebar"
rel="noopener noreferrer"
style={{ color: "var(--vscode-foreground)" }}
target="_blank">
<h3 className="m-0">💡 Cline in the Right Sidebar</h3>
<p className="m-0">
Keep your files visible when chatting with Cline. Drag the Cline icon to the right sidebar panel for a better
experience. <span className="text-link cursor-pointer">See how </span>
</p>
{/* Close button */}
<VSCodeButton
appearance="icon"
data-testid="info-banner-close-button"
onClick={handleClose}
style={{ position: "absolute", top: "8px", right: "8px" }}>
<span className="codicon codicon-close"></span>
</VSCodeButton>
</a>
)
}
export default InfoBanner
@@ -8,7 +8,7 @@ import styled from "styled-components"
import { useExtensionState } from "@/context/ExtensionStateContext"
import { McpServiceClient } from "@/services/grpc-client"
import AddRemoteServerForm from "./tabs/add-server/AddRemoteServerForm"
import InstalledServersView from "./tabs/installed/InstalledServersView"
import ConfigureServersView from "./tabs/installed/ConfigureServersView"
import McpMarketplaceView from "./tabs/marketplace/McpMarketplaceView"
type McpViewProps = {
@@ -18,7 +18,7 @@ type McpViewProps = {
const McpConfigurationView = ({ onDone, initialTab }: McpViewProps) => {
const { mcpMarketplaceEnabled, setMcpServers } = useExtensionState()
const [activeTab, setActiveTab] = useState<McpViewTab>(initialTab || (mcpMarketplaceEnabled ? "marketplace" : "installed"))
const [activeTab, setActiveTab] = useState<McpViewTab>(initialTab || (mcpMarketplaceEnabled ? "marketplace" : "configure"))
const handleTabChange = (tab: McpViewTab) => {
setActiveTab(tab)
@@ -26,8 +26,8 @@ const McpConfigurationView = ({ onDone, initialTab }: McpViewProps) => {
useEffect(() => {
if (!mcpMarketplaceEnabled && activeTab === "marketplace") {
// If marketplace is disabled and we're on marketplace tab, switch to installed
setActiveTab("installed")
// If marketplace is disabled and we're on marketplace tab, switch to configure
setActiveTab("configure")
}
}, [mcpMarketplaceEnabled, activeTab])
@@ -96,16 +96,16 @@ const McpConfigurationView = ({ onDone, initialTab }: McpViewProps) => {
<TabButton isActive={activeTab === "addRemote"} onClick={() => handleTabChange("addRemote")}>
Remote Servers
</TabButton>
<TabButton isActive={activeTab === "installed"} onClick={() => handleTabChange("installed")}>
Installed
<TabButton isActive={activeTab === "configure"} onClick={() => handleTabChange("configure")}>
Configure
</TabButton>
</div>
{/* Content container */}
<div style={{ width: "100%" }}>
{mcpMarketplaceEnabled && activeTab === "marketplace" && <McpMarketplaceView />}
{activeTab === "addRemote" && <AddRemoteServerForm onServerAdded={() => handleTabChange("installed")} />}
{activeTab === "installed" && <InstalledServersView />}
{activeTab === "addRemote" && <AddRemoteServerForm onServerAdded={() => handleTabChange("configure")} />}
{activeTab === "configure" && <ConfigureServersView />}
</div>
</div>
</div>
@@ -4,7 +4,7 @@ import { useExtensionState } from "@/context/ExtensionStateContext"
import { McpServiceClient, UiServiceClient } from "@/services/grpc-client"
import ServersToggleList from "./ServersToggleList"
const InstalledServersView = () => {
const ConfigureServersView = () => {
const { mcpServers: servers, navigateToSettings } = useExtensionState()
return (
@@ -71,4 +71,4 @@ const InstalledServersView = () => {
)
}
export default InstalledServersView
export default ConfigureServersView
@@ -255,7 +255,7 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
const checked = e.target.checked === true
updateSetting("yoloModeToggled", checked)
}}>
Enable Yolo Mode
Enable YOLO Mode
</VSCodeCheckbox>
<p className="text-xs text-[var(--vscode-errorForeground)]">
EXPERIMENTAL & DANGEROUS: This mode disables safety checks and user confirmations. Cline will
@@ -214,6 +214,7 @@ export const ExtensionStateContextProvider: React.FC<{
useAutoCondense: false,
autoCondenseThreshold: undefined,
favoritedModelIds: [],
lastDismissedInfoBannerVersion: 0,
// NEW: Add workspace information with defaults
workspaceRoots: [],