Compare commits

..
Author SHA1 Message Date
0xtoshii 92478b823d prompt update 2025-08-06 14:27:26 -07:00
kvyb 1d4cd3187b Hostbridge diff diagnostics (#5368)
* feat: migrate diff edit diagnostics to hostbridge; Migrate diagnostics functionality from direct VS Code API calls to the hostbridge layer to enable multi-host support (VS Code + IntelliJ).

* remove test logging

* refactor: migrate diagnostics to workspace service and host separation
2025-08-06 18:16:17 +03:00
Ara 32f0f9618c Adding UUID to task creation for tracking the metrics of a Task in telemetry (#5379) 2025-08-06 00:14:32 -07:00
Ara 3001f883c2 Add walkthrough button and enable quick wins for new users (#5047)
* Add walkthrough button and enable quick wins for new users

- Add openWalkthrough RPC method to ui.proto
- Enable quick wins display for users with <3 tasks in history
- Add "Take a Tour" button in HomeHeader when quick wins are shown
- Update WelcomeSection to pass shouldShowQuickWins prop to HomeHeader

* Adding Gpt-oss through groq

* Adding Gpt-oss through groq

* Support prompt caching and thinking for Opus 4.1

* Support prompt caching and thinking for Opus 4.1

* Support prompt caching and thinking for Opus 4.1
2025-08-06 00:13:31 -07:00
a64e60b8f6 v3.20.13 Release Notes (#5391)
* changeset version bump

* Updating CHANGELOG.md format

* Update CHANGELOG.md

---------

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-08-06 00:12:50 -07:00
Saoud Rizwan 3a0e6a471b Add prompt caching for Opus 4.1 (#5389)
* Add prompt caching for Opus 4.1

* Create forty-poets-doubt.md
2025-08-06 00:10:50 -07:00
c10f4e0a66 v3.20.12 Release Notes (#5387)
* changeset version bump

* Updating CHANGELOG.md format

* Update CHANGELOG.md for version 3.20.12

---------

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: pashpashpash <nik@cline.bot>
2025-08-05 22:25:33 -07:00
Ara 3e11271cf8 Fix support for prompt caching and thinking for Opus 4.1 (#5386)
* Support prompt caching and thinking for Opus 4.1

* Support prompt caching and thinking for Opus 4.1
2025-08-05 22:12:14 -07:00
30 changed files with 450 additions and 141 deletions
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
feat: Added Claude Opus 4.1 to Bedrock
+9
View File
@@ -1,5 +1,14 @@
# Changelog
## [3.20.13]
- Fix prompt caching support for Opus 4.1 on OpenRouter/Cline
## [3.20.12]
- Add Claude Opus 4.1 model support to AWS Bedrock provider (Thanks @omercelik!)
- Fix prompt caching and extended thinking support for Claude Opus 4.1 in Anthropic provider
## [3.20.11]
Add gpt-oss-120b as a Cerebras model
+1
View File
@@ -16,6 +16,7 @@ description: "Learn how to configure and use Anthropic Claude models with Cline.
Cline supports the following Anthropic Claude models:
- `claude-opus-4-1-20250805`
- `claude-opus-4-20250514`
- `claude-opus-4-20250514:thinking` (Extended Thinking variant)
- `claude-sonnet-4-20250514` (Recommended)
+1
View File
@@ -52,6 +52,7 @@ If you're not sure where Claude Code is installed:
The Claude Code provider supports these models:
- `claude-sonnet-4-20250514` (Recommended)
- `claude-opus-4-1-20250805`
- `claude-opus-4-20250514`
- `claude-3-7-sonnet-20250219`
- `claude-3-5-sonnet-20241022`
+85 -15
View File
@@ -1,12 +1,12 @@
{
"name": "claude-dev",
"version": "3.20.11",
"version": "3.20.12",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "claude-dev",
"version": "3.20.11",
"version": "3.20.12",
"license": "Apache-2.0",
"dependencies": {
"@anthropic-ai/sdk": "^0.37.0",
@@ -30,6 +30,7 @@
"@playwright/test": "^1.53.2",
"@sentry/browser": "^9.12.0",
"@streamparser/json": "^0.0.22",
"@types/uuid": "^10.0.0",
"@vscode/codicons": "^0.0.36",
"archiver": "^7.0.1",
"axios": "^1.8.2",
@@ -74,6 +75,7 @@
"tree-sitter-wasms": "^0.1.11",
"ts-morph": "^25.0.1",
"turndown": "^7.2.0",
"uuid": "^11.1.0",
"vscode-uri": "^3.1.0",
"web-tree-sitter": "^0.22.6",
"zod": "^3.24.2"
@@ -439,12 +441,31 @@
"node": ">=18.0.0"
}
},
"node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@types/uuid": {
"version": "9.0.8",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
"integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
"license": "MIT"
},
"node_modules/@aws-sdk/client-bedrock-runtime/node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
"node_modules/@aws-sdk/client-bedrock-runtime/node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/@aws-sdk/client-cognito-identity": {
"version": "3.840.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.840.0.tgz",
@@ -4981,6 +5002,19 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
"node_modules/@smithy/middleware-retry/node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/@smithy/middleware-serde": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.8.tgz",
@@ -5907,9 +5941,9 @@
"license": "MIT"
},
"node_modules/@types/uuid": {
"version": "9.0.8",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
"integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
"license": "MIT"
},
"node_modules/@types/vscode": {
@@ -11178,6 +11212,19 @@
"node": ">=14"
}
},
"node_modules/gaxios/node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/gcp-metadata": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz",
@@ -18516,15 +18563,16 @@
}
},
"node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
"integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
"uuid": "dist/bin/uuid"
"uuid": "dist/esm/bin/uuid"
}
},
"node_modules/v8-compile-cache-lib": {
@@ -19580,10 +19628,20 @@
"tslib": "^2.6.2"
}
},
"@types/uuid": {
"version": "9.0.8",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
"integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA=="
},
"tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="
}
}
},
@@ -23109,6 +23167,11 @@
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="
}
}
},
@@ -23896,9 +23959,9 @@
"dev": true
},
"@types/uuid": {
"version": "9.0.8",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
"integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA=="
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ=="
},
"@types/vscode": {
"version": "1.84.0",
@@ -27352,6 +27415,13 @@
"is-stream": "^2.0.0",
"node-fetch": "^2.6.9",
"uuid": "^9.0.1"
},
"dependencies": {
"uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="
}
}
},
"gcp-metadata": {
@@ -32295,9 +32365,9 @@
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
},
"uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
"integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="
},
"v8-compile-cache-lib": {
"version": "3.0.1",
+3 -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.20.11",
"version": "3.20.13",
"icon": "assets/icons/icon.png",
"engines": {
"vscode": "^1.84.0"
@@ -447,6 +447,7 @@
"@playwright/test": "^1.53.2",
"@sentry/browser": "^9.12.0",
"@streamparser/json": "^0.0.22",
"@types/uuid": "^10.0.0",
"@vscode/codicons": "^0.0.36",
"archiver": "^7.0.1",
"axios": "^1.8.2",
@@ -491,6 +492,7 @@
"tree-sitter-wasms": "^0.1.11",
"ts-morph": "^25.0.1",
"turndown": "^7.2.0",
"uuid": "^11.1.0",
"vscode-uri": "^3.1.0",
"web-tree-sitter": "^0.22.6",
"zod": "^3.24.2"
+41
View File
@@ -4,6 +4,8 @@ package host;
option java_package = "bot.cline.host.proto";
option java_multiple_files = true;
import "cline/common.proto";
// Provides methods for working with workspaces/projects.
service WorkspaceService {
// Returns a list of the top level directories of the workspace.
@@ -12,6 +14,8 @@ service WorkspaceService {
// Returns true if the document was saved, returns false if the document was not found, or did not
// need to be saved.
rpc saveOpenDocumentIfDirty(SaveOpenDocumentIfDirtyRequest) returns (SaveOpenDocumentIfDirtyResponse);
// Get diagnostics from the workspace.
rpc getDiagnostics(GetDiagnosticsRequest) returns (GetDiagnosticsResponse);
}
message GetWorkspacePathsRequest {
@@ -34,3 +38,40 @@ message SaveOpenDocumentIfDirtyResponse {
// Returns true if the document was saved.
optional bool was_saved = 1;
}
message GetDiagnosticsRequest {
optional cline.Metadata metadata = 1;
}
message GetDiagnosticsResponse {
repeated FileDiagnostics file_diagnostics = 1;
}
message FileDiagnostics {
string file_path = 1;
repeated Diagnostic diagnostics = 2;
}
message Diagnostic {
string message = 1;
DiagnosticRange range = 2;
DiagnosticSeverity severity = 3;
optional string source = 4;
}
message DiagnosticRange {
DiagnosticPosition start = 1;
DiagnosticPosition end = 2;
}
message DiagnosticPosition {
int32 line = 1;
int32 character = 2;
}
enum DiagnosticSeverity {
DIAGNOSTIC_ERROR = 0;
DIAGNOSTIC_WARNING = 1;
DIAGNOSTIC_INFORMATION = 2;
DIAGNOSTIC_HINT = 3;
}
+2
View File
@@ -55,6 +55,7 @@ export class AnthropicHandler implements ApiHandler {
case "claude-3-5-sonnet-20241022":
case "claude-3-5-haiku-20241022":
case "claude-opus-4-20250514":
case "claude-opus-4-1-20250805":
case "claude-3-opus-20240229":
case "claude-3-haiku-20240307": {
/*
@@ -122,6 +123,7 @@ export class AnthropicHandler implements ApiHandler {
switch (modelId) {
case "claude-sonnet-4-20250514":
case "claude-opus-4-20250514":
case "claude-opus-4-1-20250805":
case "claude-3-7-sonnet-20250219":
case "claude-3-5-sonnet-20241022":
case "claude-3-5-haiku-20241022":
+4 -1
View File
@@ -74,7 +74,10 @@ export class RequestyHandler implements ApiHandler {
? { thinking: { type: "enabled", budget_tokens: thinkingBudget } }
: { thinking: { type: "disabled" } }
const thinkingArgs =
model.id.includes("claude-3-7-sonnet") || model.id.includes("claude-sonnet-4") || model.id.includes("claude-opus-4")
model.id.includes("claude-3-7-sonnet") ||
model.id.includes("claude-sonnet-4") ||
model.id.includes("claude-opus-4") ||
model.id.includes("claude-opus-4-1")
? thinking
: {}
+1
View File
@@ -86,6 +86,7 @@ export class VertexHandler implements ApiHandler {
switch (modelId) {
case "claude-sonnet-4@20250514":
case "claude-opus-4-1@20250805":
case "claude-opus-4@20250514":
case "claude-3-7-sonnet@20250219":
case "claude-3-5-sonnet-v2@20241022":
+3
View File
@@ -24,6 +24,7 @@ export async function createOpenRouterStream(
// handles direct model.id match logic
switch (model.id) {
case "anthropic/claude-sonnet-4":
case "anthropic/claude-opus-4.1":
case "anthropic/claude-opus-4":
case "anthropic/claude-3.7-sonnet":
case "anthropic/claude-3.7-sonnet:beta":
@@ -82,6 +83,7 @@ export async function createOpenRouterStream(
let maxTokens: number | undefined
switch (model.id) {
case "anthropic/claude-sonnet-4":
case "anthropic/claude-opus-4.1":
case "anthropic/claude-opus-4":
case "anthropic/claude-3.7-sonnet":
case "anthropic/claude-3.7-sonnet:beta":
@@ -117,6 +119,7 @@ export async function createOpenRouterStream(
let reasoning: { max_tokens: number } | undefined = undefined
switch (model.id) {
case "anthropic/claude-sonnet-4":
case "anthropic/claude-opus-4.1":
case "anthropic/claude-opus-4":
case "anthropic/claude-3.7-sonnet":
case "anthropic/claude-3.7-sonnet:beta":
@@ -114,6 +114,7 @@ export async function refreshGroqModels(controller: Controller, request: EmptyRe
telemetryService.captureProviderApiError({
taskId: controller.task?.taskId || "",
uuid: controller.task?.uuid || "",
errorMessage,
errorStatus: error.status,
model: "groq",
@@ -49,7 +49,6 @@ export async function refreshOpenRouterModels(
switch (rawModel.id) {
case "anthropic/claude-sonnet-4":
case "anthropic/claude-opus-4":
case "anthropic/claude-3-7-sonnet":
case "anthropic/claude-3-7-sonnet:beta":
case "anthropic/claude-3.7-sonnet":
@@ -62,6 +61,12 @@ export async function refreshOpenRouterModels(
modelInfo.cacheWritesPrice = 3.75
modelInfo.cacheReadsPrice = 0.3
break
case "anthropic/claude-opus-4.1":
case "anthropic/claude-opus-4":
modelInfo.supportsPromptCache = true
modelInfo.cacheWritesPrice = 18.75
modelInfo.cacheReadsPrice = 1.5
break
case "anthropic/claude-3.5-sonnet-20240620":
case "anthropic/claude-3.5-sonnet-20240620:beta":
modelInfo.supportsPromptCache = true
+2 -7
View File
@@ -6,7 +6,7 @@ import { mentionRegexGlobal } from "@shared/context-mentions"
import fs from "fs/promises"
import { extractTextFromFile } from "@integrations/misc/extract-text"
import { isBinaryFile } from "isbinaryfile"
import { diagnosticsToProblemsString } from "@integrations/diagnostics"
import { getWorkspaceProblemsString } from "@/integrations/diagnostics"
import { getLatestTerminalOutput } from "@integrations/terminal/get-latest-output"
import { getCommitInfo } from "@utils/git"
import { getWorkingState } from "@utils/git"
@@ -225,12 +225,7 @@ async function getFileOrFolderContent(mentionPath: string, cwd: string): Promise
}
async function getWorkspaceProblems(): Promise<string> {
const diagnostics = vscode.languages.getDiagnostics()
const result = diagnosticsToProblemsString(diagnostics, [vscode.DiagnosticSeverity.Error, vscode.DiagnosticSeverity.Warning])
if (!result) {
return "No errors or warnings detected."
}
return result
return await getWorkspaceProblemsString()
}
function isFileMention(mention: string): boolean {
+1 -1
View File
@@ -51,7 +51,7 @@ Usage:
</execute_command>
## read_file
Description: Request to read the contents of a file at the specified path. Use this when you need to examine the contents of an existing file you do not know the contents of, for example to analyze code, review text files, or extract information from configuration files. Automatically extracts raw text from PDF and DOCX files. May not be suitable for other types of binary files, as it returns the raw content as a string.
Description: Request to read the contents of a file at the specified path. Use this when you need to examine the contents of an existing file you do not know the contents of, for example to analyze code, review text files, or extract information from configuration files. Automatically extracts raw text from PDF and DOCX files. May not be suitable for other types of binary files, as it returns the raw content as a string. Do NOT use this tool to list the contents of a directory. Only use this tool on files.
Parameters:
- path: (required) The path of the file to read (relative to the current working directory ${cwd.toPosix()})
Usage:
+3 -2
View File
@@ -93,6 +93,7 @@ export class ToolExecutor {
private browserSettings: BrowserSettings,
private cwd: string,
private taskId: string,
private uuid: string,
private mode: Mode,
private strictPlanModeEnabled: boolean,
@@ -2342,7 +2343,7 @@ export class ToolExecutor {
await this.say("completion_result", result, undefined, undefined, false)
await this.saveCheckpoint(true)
await addNewChangesFlagToLastCompletionResultMessage()
telemetryService.captureTaskCompleted(this.taskId)
telemetryService.captureTaskCompleted(this.taskId, this.uuid)
} else {
// we already sent a command message, meaning the complete completion message has also been sent
await this.saveCheckpoint(true)
@@ -2367,7 +2368,7 @@ export class ToolExecutor {
await this.say("completion_result", result, undefined, undefined, false)
await this.saveCheckpoint(true)
await addNewChangesFlagToLastCompletionResultMessage()
telemetryService.captureTaskCompleted(this.taskId)
telemetryService.captureTaskCompleted(this.taskId, this.uuid)
}
// we already sent completion_result says, an empty string asks relinquishes control over button and field
+24 -11
View File
@@ -35,6 +35,7 @@ import pTimeout from "p-timeout"
import pWaitFor from "p-wait-for"
import * as path from "path"
import * as vscode from "vscode"
import { v4 as uuidv4 } from "uuid"
import { HostProvider } from "@/hosts/host-provider"
import { ClineErrorType } from "@/services/error/ClineError"
@@ -97,6 +98,7 @@ type UserContent = Array<Anthropic.ContentBlockParam>
export class Task {
// Core task variables
readonly taskId: string
readonly uuid: string
private taskIsFavorited?: boolean
private cwd: string
@@ -219,6 +221,7 @@ export class Task {
// Initialize taskId first
if (historyItem) {
this.taskId = historyItem.id
this.uuid = historyItem.uuid ?? uuidv4()
this.taskIsFavorited = historyItem.isFavorited
this.taskState.conversationHistoryDeletedRange = historyItem.conversationHistoryDeletedRange
if (historyItem.checkpointTrackerErrorMessage) {
@@ -226,6 +229,7 @@ export class Task {
}
} else if (task || images || files) {
this.taskId = Date.now().toString()
this.uuid = uuidv4()
} else {
throw new Error("Either historyItem or task/images must be provided")
}
@@ -233,6 +237,7 @@ export class Task {
this.messageStateHandler = new MessageStateHandler({
context,
taskId: this.taskId,
uuid: this.uuid,
taskState: this.taskState,
taskIsFavorited: this.taskIsFavorited,
updateTaskHistory: this.updateTaskHistory,
@@ -306,10 +311,10 @@ export class Task {
// initialize telemetry
if (historyItem) {
// Open task from history
telemetryService.captureTaskRestarted(this.taskId, currentProvider)
telemetryService.captureTaskRestarted(this.taskId, this.uuid, currentProvider)
} else {
// New task started
telemetryService.captureTaskCreated(this.taskId, currentProvider)
telemetryService.captureTaskCreated(this.taskId, this.uuid, currentProvider)
}
this.toolExecutor = new ToolExecutor(
@@ -330,6 +335,7 @@ export class Task {
this.browserSettings,
cwd,
this.taskId,
this.uuid,
this.mode,
strictPlanModeEnabled,
this.say.bind(this),
@@ -2228,7 +2234,7 @@ export class Task {
content: userContent,
})
telemetryService.captureConversationTurnEvent(this.taskId, providerId, modelId, "user")
telemetryService.captureConversationTurnEvent(this.taskId, this.uuid, providerId, modelId, "user")
// since we sent off a placeholder api_req_started message to update the webview while waiting to actually start the API request (to load potential details for example), we need to update the text of that message
const lastApiReqIndex = findLastIndex(this.messageStateHandler.getClineMessages(), (m) => m.say === "api_req_started")
@@ -2293,13 +2299,20 @@ export class Task {
})
await this.messageStateHandler.saveClineMessagesAndUpdateHistory()
telemetryService.captureConversationTurnEvent(this.taskId, providerId, this.api.getModel().id, "assistant", {
tokensIn: inputTokens,
tokensOut: outputTokens,
cacheWriteTokens,
cacheReadTokens,
totalCost,
})
telemetryService.captureConversationTurnEvent(
this.taskId,
this.uuid,
providerId,
this.api.getModel().id,
"assistant",
{
tokensIn: inputTokens,
tokensOut: outputTokens,
cacheWriteTokens,
cacheReadTokens,
totalCost,
},
)
// signals to provider that it can retrieve the saved messages from disk, as abortTask can not be awaited on in nature
this.taskState.didFinishAbortingStream = true
@@ -2468,7 +2481,7 @@ export class Task {
// need to save assistant responses to file before proceeding to tool use since user can exit at any moment and we wouldn't be able to save the assistant's response
let didEndLoop = false
if (assistantMessage.length > 0) {
telemetryService.captureConversationTurnEvent(this.taskId, providerId, modelId, "assistant", {
telemetryService.captureConversationTurnEvent(this.taskId, this.uuid, providerId, modelId, "assistant", {
tokensIn: inputTokens,
tokensOut: outputTokens,
cacheWriteTokens,
+4
View File
@@ -17,6 +17,7 @@ import { getCwd, getDesktopDir } from "@/utils/path"
interface MessageStateHandlerParams {
context: vscode.ExtensionContext
taskId: string
uuid: string
taskIsFavorited?: boolean
updateTaskHistory: (historyItem: HistoryItem) => Promise<HistoryItem[]>
taskState: TaskState
@@ -32,11 +33,13 @@ export class MessageStateHandler {
private updateTaskHistory: (historyItem: HistoryItem) => Promise<HistoryItem[]>
private context: vscode.ExtensionContext
private taskId: string
private uuid: string
private taskState: TaskState
constructor(params: MessageStateHandlerParams) {
this.context = params.context
this.taskId = params.taskId
this.uuid = params.uuid
this.taskState = params.taskState
this.taskIsFavorited = params.taskIsFavorited ?? false
this.updateTaskHistory = params.updateTaskHistory
@@ -89,6 +92,7 @@ export class MessageStateHandler {
const cwd = await getCwd(getDesktopDir())
await this.updateTaskHistory({
id: this.taskId,
uuid: this.uuid,
ts: lastRelevantMessage.ts,
task: taskMessage.text ?? "",
tokensIn: apiMetrics.totalTokensIn,
+22 -2
View File
@@ -1,5 +1,6 @@
import { HostProvider } from "@/hosts/host-provider"
import { DiffViewProvider } from "@/integrations/editor/DiffViewProvider"
import { DiagnosticSeverity } from "@/shared/proto/host/workspace"
import { status } from "@grpc/grpc-js"
export class ExternalDiffViewProvider extends DiffViewProvider {
@@ -78,8 +79,27 @@ export class ExternalDiffViewProvider extends DiffViewProvider {
}
protected override async getNewDiagnosticProblems(): Promise<string> {
console.log(`Called ExternalDiffViewProvider.getNewDiagnosticProblems() stub`)
return ""
// Get diagnostics using the HostBridge workspace service
const response = await HostProvider.workspace.getDiagnostics({})
if (response.fileDiagnostics.length === 0) {
return ""
}
let result = ""
for (const fileDiagnostics of response.fileDiagnostics) {
const errors = fileDiagnostics.diagnostics.filter((d) => d.severity === DiagnosticSeverity.DIAGNOSTIC_ERROR)
if (errors.length > 0) {
result += `\n\n${fileDiagnostics.filePath}`
for (const diagnostic of errors) {
const line = (diagnostic.range?.start?.line || 0) + 1 // Proto lines are 0-indexed
const source = diagnostic.source ? `${diagnostic.source} ` : ""
result += `\n- [${source}Error] Line ${line}: ${diagnostic.message}`
}
}
}
return result.trim()
}
protected override async closeDiffView(): Promise<void> {
+1 -1
View File
@@ -3,7 +3,7 @@ import * as path from "path"
import * as vscode from "vscode"
import { DecorationController } from "@/hosts/vscode/DecorationController"
import { DiffViewProvider } from "@integrations/editor/DiffViewProvider"
import { diagnosticsToProblemsString, getNewDiagnostics } from "@/integrations/diagnostics"
import { diagnosticsToProblemsString, getNewDiagnostics } from "./diagnostics"
export const DIFF_VIEW_URI_SCHEME = "cline-diff"
+109
View File
@@ -0,0 +1,109 @@
import * as vscode from "vscode"
import * as path from "path"
import deepEqual from "fast-deep-equal"
import { getCwd } from "@/utils/path"
export function getNewDiagnostics(
oldDiagnostics: [vscode.Uri, vscode.Diagnostic[]][],
newDiagnostics: [vscode.Uri, vscode.Diagnostic[]][],
): [vscode.Uri, vscode.Diagnostic[]][] {
const newProblems: [vscode.Uri, vscode.Diagnostic[]][] = []
const oldMap = new Map(oldDiagnostics)
for (const [uri, newDiags] of newDiagnostics) {
const oldDiags = oldMap.get(uri) || []
const newProblemsForUri = newDiags.filter((newDiag) => !oldDiags.some((oldDiag) => deepEqual(oldDiag, newDiag)))
if (newProblemsForUri.length > 0) {
newProblems.push([uri, newProblemsForUri])
}
}
return newProblems
}
// Usage:
// const oldDiagnostics = // ... your old diagnostics array
// const newDiagnostics = // ... your new diagnostics array
// const newProblems = getNewDiagnostics(oldDiagnostics, newDiagnostics);
// Example usage with mocks:
//
// // Mock old diagnostics
// const oldDiagnostics: [vscode.Uri, vscode.Diagnostic[]][] = [
// [vscode.Uri.file("/path/to/file1.ts"), [
// new vscode.Diagnostic(new vscode.Range(0, 0, 0, 10), "Old error in file1", vscode.DiagnosticSeverity.Error)
// ]],
// [vscode.Uri.file("/path/to/file2.ts"), [
// new vscode.Diagnostic(new vscode.Range(5, 5, 5, 15), "Old warning in file2", vscode.DiagnosticSeverity.Warning)
// ]]
// ];
//
// // Mock new diagnostics
// const newDiagnostics: [vscode.Uri, vscode.Diagnostic[]][] = [
// [vscode.Uri.file("/path/to/file1.ts"), [
// new vscode.Diagnostic(new vscode.Range(0, 0, 0, 10), "Old error in file1", vscode.DiagnosticSeverity.Error),
// new vscode.Diagnostic(new vscode.Range(2, 2, 2, 12), "New error in file1", vscode.DiagnosticSeverity.Error)
// ]],
// [vscode.Uri.file("/path/to/file2.ts"), [
// new vscode.Diagnostic(new vscode.Range(5, 5, 5, 15), "Old warning in file2", vscode.DiagnosticSeverity.Warning)
// ]],
// [vscode.Uri.file("/path/to/file3.ts"), [
// new vscode.Diagnostic(new vscode.Range(1, 1, 1, 11), "New error in file3", vscode.DiagnosticSeverity.Error)
// ]]
// ];
//
// const newProblems = getNewDiagnostics(oldDiagnostics, newDiagnostics);
//
// console.log("New problems:");
// for (const [uri, diagnostics] of newProblems) {
// console.log(`File: ${uri.fsPath}`);
// for (const diagnostic of diagnostics) {
// console.log(`- ${diagnostic.message} (${diagnostic.range.start.line}:${diagnostic.range.start.character})`);
// }
// }
//
// // Expected output:
// // New problems:
// // File: /path/to/file1.ts
// // - New error in file1 (2:2)
// // File: /path/to/file3.ts
// // - New error in file3 (1:1)
// will return empty string if no problems with the given severity are found
export async function diagnosticsToProblemsString(
diagnostics: [vscode.Uri, vscode.Diagnostic[]][],
severities: vscode.DiagnosticSeverity[],
): Promise<string> {
const cwd = await getCwd()
let result = ""
for (const [uri, fileDiagnostics] of diagnostics) {
const problems = fileDiagnostics.filter((d) => severities.includes(d.severity))
if (problems.length > 0) {
result += `\n\n${path.relative(cwd, uri.fsPath).toPosix()}`
for (const diagnostic of problems) {
let label: string
switch (diagnostic.severity) {
case vscode.DiagnosticSeverity.Error:
label = "Error"
break
case vscode.DiagnosticSeverity.Warning:
label = "Warning"
break
case vscode.DiagnosticSeverity.Information:
label = "Information"
break
case vscode.DiagnosticSeverity.Hint:
label = "Hint"
break
default:
label = "Diagnostic"
}
const line = diagnostic.range.start.line + 1 // VSCode lines are 0-indexed
const source = diagnostic.source ? `${diagnostic.source} ` : ""
result += `\n- [${source}${label}] Line ${line}: ${diagnostic.message}`
}
}
}
return result.trim()
}
@@ -0,0 +1,69 @@
import * as vscode from "vscode"
import {
GetDiagnosticsRequest,
GetDiagnosticsResponse,
FileDiagnostics,
Diagnostic,
DiagnosticRange,
DiagnosticPosition,
DiagnosticSeverity,
} from "@/shared/proto/host/workspace"
export async function getDiagnostics(request: GetDiagnosticsRequest): Promise<GetDiagnosticsResponse> {
// Get all diagnostics from VS Code
const vscodeAllDiagnostics = vscode.languages.getDiagnostics()
const fileDiagnostics: FileDiagnostics[] = []
for (const [uri, diagnostics] of vscodeAllDiagnostics) {
if (diagnostics.length > 0) {
const convertedDiagnostics: Diagnostic[] = diagnostics.map((vsDiagnostic) => {
// Convert VS Code severity to proto severity
let severity: DiagnosticSeverity
switch (vsDiagnostic.severity) {
case vscode.DiagnosticSeverity.Error:
severity = DiagnosticSeverity.DIAGNOSTIC_ERROR
break
case vscode.DiagnosticSeverity.Warning:
severity = DiagnosticSeverity.DIAGNOSTIC_WARNING
break
case vscode.DiagnosticSeverity.Information:
severity = DiagnosticSeverity.DIAGNOSTIC_INFORMATION
break
case vscode.DiagnosticSeverity.Hint:
severity = DiagnosticSeverity.DIAGNOSTIC_HINT
break
default:
severity = DiagnosticSeverity.DIAGNOSTIC_ERROR
}
return Diagnostic.create({
message: vsDiagnostic.message,
range: DiagnosticRange.create({
start: DiagnosticPosition.create({
line: vsDiagnostic.range.start.line,
character: vsDiagnostic.range.start.character,
}),
end: DiagnosticPosition.create({
line: vsDiagnostic.range.end.line,
character: vsDiagnostic.range.end.character,
}),
}),
severity: severity,
source: vsDiagnostic.source || undefined,
})
})
fileDiagnostics.push(
FileDiagnostics.create({
filePath: uri.fsPath,
diagnostics: convertedDiagnostics,
}),
)
}
}
return GetDiagnosticsResponse.create({
fileDiagnostics: fileDiagnostics,
})
}
+26 -82
View File
@@ -1,105 +1,49 @@
import * as vscode from "vscode"
import * as path from "path"
import deepEqual from "fast-deep-equal"
import { getCwd } from "@/utils/path"
import { HostProvider } from "@/hosts/host-provider"
import { GetDiagnosticsRequest, DiagnosticSeverity } from "@/shared/proto/host/workspace"
import { Metadata } from "@/shared/proto/cline/common"
export function getNewDiagnostics(
oldDiagnostics: [vscode.Uri, vscode.Diagnostic[]][],
newDiagnostics: [vscode.Uri, vscode.Diagnostic[]][],
): [vscode.Uri, vscode.Diagnostic[]][] {
const newProblems: [vscode.Uri, vscode.Diagnostic[]][] = []
const oldMap = new Map(oldDiagnostics)
/**
* Host-agnostic function to get workspace problems as a formatted string
* Used by @problems mention for cross-host compatibility
*/
export async function getWorkspaceProblemsString(): Promise<string> {
const response = await HostProvider.workspace.getDiagnostics(
GetDiagnosticsRequest.create({
metadata: Metadata.create({}),
}),
)
for (const [uri, newDiags] of newDiagnostics) {
const oldDiags = oldMap.get(uri) || []
const newProblemsForUri = newDiags.filter((newDiag) => !oldDiags.some((oldDiag) => deepEqual(oldDiag, newDiag)))
if (newProblemsForUri.length > 0) {
newProblems.push([uri, newProblemsForUri])
}
if (response.fileDiagnostics.length === 0) {
return "No errors or warnings detected."
}
return newProblems
}
// Usage:
// const oldDiagnostics = // ... your old diagnostics array
// const newDiagnostics = // ... your new diagnostics array
// const newProblems = getNewDiagnostics(oldDiagnostics, newDiagnostics);
// Example usage with mocks:
//
// // Mock old diagnostics
// const oldDiagnostics: [vscode.Uri, vscode.Diagnostic[]][] = [
// [vscode.Uri.file("/path/to/file1.ts"), [
// new vscode.Diagnostic(new vscode.Range(0, 0, 0, 10), "Old error in file1", vscode.DiagnosticSeverity.Error)
// ]],
// [vscode.Uri.file("/path/to/file2.ts"), [
// new vscode.Diagnostic(new vscode.Range(5, 5, 5, 15), "Old warning in file2", vscode.DiagnosticSeverity.Warning)
// ]]
// ];
//
// // Mock new diagnostics
// const newDiagnostics: [vscode.Uri, vscode.Diagnostic[]][] = [
// [vscode.Uri.file("/path/to/file1.ts"), [
// new vscode.Diagnostic(new vscode.Range(0, 0, 0, 10), "Old error in file1", vscode.DiagnosticSeverity.Error),
// new vscode.Diagnostic(new vscode.Range(2, 2, 2, 12), "New error in file1", vscode.DiagnosticSeverity.Error)
// ]],
// [vscode.Uri.file("/path/to/file2.ts"), [
// new vscode.Diagnostic(new vscode.Range(5, 5, 5, 15), "Old warning in file2", vscode.DiagnosticSeverity.Warning)
// ]],
// [vscode.Uri.file("/path/to/file3.ts"), [
// new vscode.Diagnostic(new vscode.Range(1, 1, 1, 11), "New error in file3", vscode.DiagnosticSeverity.Error)
// ]]
// ];
//
// const newProblems = getNewProblems(oldDiagnostics, newDiagnostics);
//
// console.log("New problems:");
// for (const [uri, diagnostics] of newProblems) {
// console.log(`File: ${uri.fsPath}`);
// for (const diagnostic of diagnostics) {
// console.log(`- ${diagnostic.message} (${diagnostic.range.start.line}:${diagnostic.range.start.character})`);
// }
// }
//
// // Expected output:
// // New problems:
// // File: /path/to/file1.ts
// // - New error in file1 (2:2)
// // File: /path/to/file3.ts
// // - New error in file3 (1:1)
// will return empty string if no problems with the given severity are found
export async function diagnosticsToProblemsString(
diagnostics: [vscode.Uri, vscode.Diagnostic[]][],
severities: vscode.DiagnosticSeverity[],
): Promise<string> {
const cwd = await getCwd()
let result = ""
for (const [uri, fileDiagnostics] of diagnostics) {
const problems = fileDiagnostics.filter((d) => severities.includes(d.severity))
for (const fileDiagnostics of response.fileDiagnostics) {
const problems = fileDiagnostics.diagnostics.filter(
(d) => d.severity === DiagnosticSeverity.DIAGNOSTIC_ERROR || d.severity === DiagnosticSeverity.DIAGNOSTIC_WARNING,
)
if (problems.length > 0) {
result += `\n\n${path.relative(cwd, uri.fsPath).toPosix()}`
result += `\n\n${fileDiagnostics.filePath}`
for (const diagnostic of problems) {
let label: string
switch (diagnostic.severity) {
case vscode.DiagnosticSeverity.Error:
case DiagnosticSeverity.DIAGNOSTIC_ERROR:
label = "Error"
break
case vscode.DiagnosticSeverity.Warning:
case DiagnosticSeverity.DIAGNOSTIC_WARNING:
label = "Warning"
break
case vscode.DiagnosticSeverity.Information:
case DiagnosticSeverity.DIAGNOSTIC_INFORMATION:
label = "Information"
break
case vscode.DiagnosticSeverity.Hint:
case DiagnosticSeverity.DIAGNOSTIC_HINT:
label = "Hint"
break
default:
label = "Diagnostic"
}
const line = diagnostic.range.start.line + 1 // VSCode lines are 0-indexed
const line = (diagnostic.range?.start?.line || 0) + 1 // Proto lines are 0-indexed
const source = diagnostic.source ? `${diagnostic.source} ` : ""
result += `\n- [${source}${label}] Line ${line}: ${diagnostic.message}`
}
@@ -181,10 +181,10 @@ export class TelemetryService {
* @param taskId Unique identifier for the new task
* @param apiProvider Optional API provider
*/
public captureTaskCreated(taskId: string, apiProvider?: string) {
public captureTaskCreated(taskId: string, uuid: string, apiProvider?: string) {
this.capture({
event: TelemetryService.EVENTS.TASK.CREATED,
properties: { taskId, apiProvider },
properties: { taskId, uuid, apiProvider },
})
}
@@ -193,10 +193,10 @@ export class TelemetryService {
* @param taskId Unique identifier for the new task
* @param apiProvider Optional API provider
*/
public captureTaskRestarted(taskId: string, apiProvider?: string) {
public captureTaskRestarted(taskId: string, uuid: string, apiProvider?: string) {
this.capture({
event: TelemetryService.EVENTS.TASK.RESTARTED,
properties: { taskId, apiProvider },
properties: { taskId, uuid, apiProvider },
})
}
@@ -204,10 +204,10 @@ export class TelemetryService {
* Records when cline calls the task completion_result tool signifying that cline is done with the task
* @param taskId Unique identifier for the task
*/
public captureTaskCompleted(taskId: string) {
public captureTaskCompleted(taskId: string, uuid: string) {
this.capture({
event: TelemetryService.EVENTS.TASK.COMPLETED,
properties: { taskId },
properties: { taskId, uuid },
})
}
@@ -221,6 +221,7 @@ export class TelemetryService {
*/
public captureConversationTurnEvent(
taskId: string,
uuid: string,
provider: string = "unknown",
model: string = "unknown",
source: "user" | "assistant",
@@ -233,13 +234,14 @@ export class TelemetryService {
} = {},
) {
// Ensure required parameters are provided
if (!taskId || !provider || !model || !source) {
if (!taskId || !uuid || !provider || !model || !source) {
console.warn("TelemetryService: Missing required parameters for message capture")
return
}
const properties: Record<string, unknown> = {
taskId,
uuid,
provider,
model,
source,
@@ -598,6 +600,7 @@ export class TelemetryService {
*/
public captureProviderApiError(args: {
taskId: string
uuid: string
model: string
errorMessage: string
errorStatus?: number | undefined
+1
View File
@@ -1,5 +1,6 @@
export type HistoryItem = {
id: string
uuid?: string // UUID for better tracking and metrics
ts: number
task: string
tokensIn: number
+10
View File
@@ -508,6 +508,16 @@ export const vertexModels = {
cacheWritesPrice: 3.75,
cacheReadsPrice: 0.3,
},
"claude-opus-4-1@20250805": {
maxTokens: 8192,
contextWindow: 200_000,
supportsImages: true,
supportsPromptCache: true,
inputPrice: 15.0,
outputPrice: 75.0,
cacheWritesPrice: 18.75,
cacheReadsPrice: 1.5,
},
"claude-opus-4@20250514": {
maxTokens: 8192,
contextWindow: 200_000,
@@ -50,16 +50,16 @@ const featuredModels = [
description: "Recommended for agentic coding in Cline",
label: "Best",
},
{
id: "anthropic/claude-opus-4.1",
description: "Anthropic's newest model topping benchmarks",
label: "New",
},
{
id: "google/gemini-2.5-pro",
description: "Large 1M context window, great value",
label: "Trending",
},
{
id: "moonshotai/kimi-k2",
description: "Open source model topping coding benchmarks",
label: "New",
},
]
const OpenRouterModelPicker: React.FC<OpenRouterModelPickerProps> = ({ isPopup, currentMode }) => {
@@ -211,6 +211,7 @@ const OpenRouterModelPicker: React.FC<OpenRouterModelPickerProps> = ({ isPopup,
const showBudgetSlider = useMemo(() => {
return (
selectedModelId?.toLowerCase().includes("claude-sonnet-4") ||
selectedModelId?.toLowerCase().includes("claude-opus-4.1") ||
selectedModelId?.toLowerCase().includes("claude-opus-4") ||
selectedModelId?.toLowerCase().includes("claude-3-7-sonnet") ||
selectedModelId?.toLowerCase().includes("claude-3.7-sonnet") ||
@@ -14,6 +14,7 @@ export const SUPPORTED_ANTHROPIC_THINKING_MODELS = [
"claude-3-7-sonnet-20250219",
"claude-sonnet-4-20250514",
"claude-opus-4-20250514",
"claude-opus-4-1-20250805",
]
/**
@@ -314,11 +314,14 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
{(selectedModelId === "anthropic.claude-3-7-sonnet-20250219-v1:0" ||
selectedModelId === "anthropic.claude-sonnet-4-20250514-v1:0" ||
selectedModelId === "anthropic.claude-opus-4-1-20250805-v1:0" ||
selectedModelId === "anthropic.claude-opus-4-20250514-v1:0" ||
(modeFields.awsBedrockCustomSelected &&
modeFields.awsBedrockCustomModelBaseId === "anthropic.claude-3-7-sonnet-20250219-v1:0") ||
(modeFields.awsBedrockCustomSelected &&
modeFields.awsBedrockCustomModelBaseId === "anthropic.claude-sonnet-4-20250514-v1:0") ||
(modeFields.awsBedrockCustomSelected &&
modeFields.awsBedrockCustomModelBaseId === "anthropic.claude-opus-4-1-20250805-v1:0") ||
(modeFields.awsBedrockCustomSelected &&
modeFields.awsBedrockCustomModelBaseId === "anthropic.claude-opus-4-20250514-v1:0")) && (
<ThinkingBudgetSlider currentMode={currentMode} />
@@ -23,6 +23,7 @@ const SUPPORTED_THINKING_MODELS = [
"claude-3-7-sonnet@20250219",
"claude-sonnet-4@20250514",
"claude-opus-4@20250514",
"claude-opus-4-1@20250805",
"gemini-2.5-flash",
"gemini-2.5-pro",
"gemini-2.5-flash-lite-preview-06-17",