mirror of
https://github.com/cline/cline.git
synced 2026-09-17 17:45:33 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b47e515ef | ||
|
|
fd8f9eb12c | ||
|
|
d3cff6ac47 | ||
|
|
13af435103 | ||
|
|
3b1477bc24 | ||
|
|
688f93db6d | ||
|
|
a702270e85 | ||
|
|
03acada1b9 | ||
|
|
95cca05f5e | ||
|
|
33d77eb095 | ||
|
|
3e0c39acbb | ||
|
|
366d8a5411 | ||
|
|
d22596e5c2 | ||
|
|
7cc612dbce | ||
|
|
f0cab63a43 | ||
|
|
3c1b670b73 | ||
|
|
5de05d68ef | ||
|
|
9b6b1c376c | ||
|
|
e5e26f45fa | ||
|
|
b794583b7a | ||
|
|
ca96bd8f62 | ||
|
|
0ecdf8d0cc |
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Checkpoints multiroot pt.1: Accept array of workspaces when initializting checkpoints
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Support partial response validation via meta.expected
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Run Testing platform within Test workflow
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Refactor Task Header UI with interactive context window management
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
remove temperature settings in z.ai models
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Feature flags are now accessible too all users instead of authenticated users only.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Update anthropic input token usage calculation
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Support new Cline endpoint auth flow
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Add speech-to-text dictation feature for Cline account users
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,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
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
@@ -40,6 +40,7 @@ export interface GlobalState {
|
||||
workspaceRoots: WorkspaceRoot[] | undefined
|
||||
primaryRootIndex: number
|
||||
multiRootEnabled: boolean
|
||||
lastDismissedInfoBannerVersion: number
|
||||
}
|
||||
|
||||
export interface Settings {
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ export interface ExtensionState {
|
||||
primaryRootIndex: number
|
||||
isMultiRootWorkspace: boolean
|
||||
multiRootSetting: ClineFeatureSetting
|
||||
lastDismissedInfoBannerVersion: number
|
||||
}
|
||||
|
||||
export interface ClineMessage {
|
||||
|
||||
@@ -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
@@ -111,4 +111,4 @@ export interface McpDownloadResponse {
|
||||
requiresApiKey: boolean
|
||||
}
|
||||
|
||||
export type McpViewTab = "marketplace" | "addRemote" | "installed"
|
||||
export type McpViewTab = "marketplace" | "addRemote" | "configure"
|
||||
|
||||
@@ -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()
|
||||
})
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
+2
-2
@@ -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: [],
|
||||
|
||||
Reference in New Issue
Block a user