mirror of
https://github.com/cline/cline.git
synced 2026-09-15 21:04:27 +08:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
535f0b72e2 | ||
|
|
99f8093b81 | ||
|
|
b3ceccbb20 | ||
|
|
1d4cd3187b | ||
|
|
32f0f9618c | ||
|
|
3001f883c2 | ||
|
|
a64e60b8f6 | ||
|
|
3a0e6a471b | ||
|
|
c10f4e0a66 | ||
|
|
3e11271cf8 |
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
feat: Added Claude Opus 4.1 to Bedrock
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Enabling quickwins and adding a button to show that you can do a walkthrough
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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`
|
||||
|
||||
Generated
+85
-15
@@ -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
@@ -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"
|
||||
|
||||
@@ -235,6 +235,7 @@ message ModelsApiConfiguration {
|
||||
optional string hugging_face_api_key = 60;
|
||||
optional string huawei_cloud_maas_api_key = 61;
|
||||
optional string baseten_api_key = 62;
|
||||
optional string ollama_api_key = 63;
|
||||
|
||||
// Plan mode configurations
|
||||
optional ApiProvider plan_mode_api_provider = 100;
|
||||
|
||||
@@ -172,6 +172,7 @@ message ApiConfiguration {
|
||||
optional string moonshot_api_key = 54;
|
||||
optional string moonshot_api_line = 55;
|
||||
optional string huawei_cloud_maas_api_key = 56;
|
||||
optional string ollama_api_key = 57;
|
||||
|
||||
// Plan mode configurations
|
||||
optional string plan_mode_api_provider = 100;
|
||||
|
||||
@@ -267,4 +267,7 @@ service UiService {
|
||||
|
||||
// Opens a URL in the default browser
|
||||
rpc openUrl(StringRequest) returns (Empty);
|
||||
|
||||
// Opens the Cline walkthrough
|
||||
rpc openWalkthrough(EmptyRequest) returns (Empty);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -113,6 +113,7 @@ function createHandlerForProvider(
|
||||
case "ollama":
|
||||
return new OllamaHandler({
|
||||
ollamaBaseUrl: options.ollamaBaseUrl,
|
||||
ollamaApiKey: options.ollamaApiKey,
|
||||
ollamaModelId: mode === "plan" ? options.planModeOllamaModelId : options.actModeOllamaModelId,
|
||||
ollamaApiOptionsCtxNum: options.ollamaApiOptionsCtxNum,
|
||||
requestTimeoutMs: options.requestTimeoutMs,
|
||||
|
||||
@@ -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":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { Message, Ollama } from "ollama"
|
||||
import { Message, Ollama, Config } from "ollama"
|
||||
import { ApiHandler } from "../"
|
||||
import { ApiHandlerOptions, ModelInfo, openAiModelInfoSaneDefaults } from "../../shared/api"
|
||||
import { convertToOllamaMessages } from "../transform/ollama-format"
|
||||
@@ -8,6 +8,7 @@ import { withRetry } from "../retry"
|
||||
|
||||
interface OllamaHandlerOptions {
|
||||
ollamaBaseUrl?: string
|
||||
ollamaApiKey?: string
|
||||
ollamaModelId?: string
|
||||
ollamaApiOptionsCtxNum?: string
|
||||
requestTimeoutMs?: number
|
||||
@@ -24,7 +25,18 @@ export class OllamaHandler implements ApiHandler {
|
||||
private ensureClient(): Ollama {
|
||||
if (!this.client) {
|
||||
try {
|
||||
this.client = new Ollama({ host: this.options.ollamaBaseUrl || "http://localhost:11434" })
|
||||
const clientOptions: Partial<Config> = {
|
||||
host: this.options.ollamaBaseUrl || "http://localhost:11434",
|
||||
}
|
||||
|
||||
// Add API key if provided (for Ollama cloud or authenticated instances)
|
||||
if (this.options.ollamaApiKey) {
|
||||
clientOptions.headers = {
|
||||
Authorization: `Bearer ${this.options.ollamaApiKey}`,
|
||||
}
|
||||
}
|
||||
|
||||
this.client = new Ollama(clientOptions)
|
||||
} catch (error) {
|
||||
throw new Error(`Error creating Ollama client: ${error.message}`)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
: {}
|
||||
|
||||
|
||||
@@ -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":
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -200,6 +200,7 @@ export class CacheService {
|
||||
openAiApiKey,
|
||||
openAiHeaders,
|
||||
ollamaBaseUrl,
|
||||
ollamaApiKey,
|
||||
ollamaApiOptionsCtxNum,
|
||||
lmStudioBaseUrl,
|
||||
anthropicBaseUrl,
|
||||
@@ -399,6 +400,7 @@ export class CacheService {
|
||||
awsSessionToken,
|
||||
awsBedrockApiKey,
|
||||
openAiApiKey,
|
||||
ollamaApiKey,
|
||||
geminiApiKey,
|
||||
openAiNativeApiKey,
|
||||
deepSeekApiKey,
|
||||
@@ -598,6 +600,7 @@ export class CacheService {
|
||||
openAiApiKey,
|
||||
openAiHeaders,
|
||||
ollamaBaseUrl,
|
||||
ollamaApiKey,
|
||||
ollamaApiOptionsCtxNum,
|
||||
lmStudioBaseUrl,
|
||||
anthropicBaseUrl,
|
||||
@@ -802,6 +805,7 @@ export class CacheService {
|
||||
awsSessionToken,
|
||||
awsBedrockApiKey,
|
||||
openAiApiKey,
|
||||
ollamaApiKey,
|
||||
geminiApiKey,
|
||||
openAiNativeApiKey,
|
||||
deepSeekApiKey,
|
||||
@@ -845,6 +849,7 @@ export class CacheService {
|
||||
awsSessionToken: this.secretsCache.get("awsSessionToken"),
|
||||
awsBedrockApiKey: this.secretsCache.get("awsBedrockApiKey"),
|
||||
openAiApiKey: this.secretsCache.get("openAiApiKey"),
|
||||
ollamaApiKey: this.secretsCache.get("ollamaApiKey"),
|
||||
geminiApiKey: this.secretsCache.get("geminiApiKey"),
|
||||
openAiNativeApiKey: this.secretsCache.get("openAiNativeApiKey"),
|
||||
deepSeekApiKey: this.secretsCache.get("deepSeekApiKey"),
|
||||
|
||||
@@ -7,6 +7,7 @@ export type SecretKey =
|
||||
| "awsSessionToken"
|
||||
| "awsBedrockApiKey"
|
||||
| "openAiApiKey"
|
||||
| "ollamaApiKey"
|
||||
| "geminiApiKey"
|
||||
| "openAiNativeApiKey"
|
||||
| "deepSeekApiKey"
|
||||
|
||||
@@ -524,6 +524,7 @@ export async function migrateWelcomeViewCompleted(context: vscode.ExtensionConte
|
||||
config.awsRegion,
|
||||
config.vertexProjectId,
|
||||
config.openAiApiKey,
|
||||
config.ollamaApiKey,
|
||||
config.planModeOllamaModelId,
|
||||
config.planModeLmStudioModelId,
|
||||
config.actModeOllamaModelId,
|
||||
|
||||
@@ -133,6 +133,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
|
||||
openAiApiKey,
|
||||
openAiHeaders,
|
||||
ollamaBaseUrl,
|
||||
ollamaApiKey,
|
||||
ollamaApiOptionsCtxNum,
|
||||
lmStudioBaseUrl,
|
||||
anthropicBaseUrl,
|
||||
@@ -214,6 +215,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
|
||||
getSecret(context, "openAiApiKey") as Promise<string | undefined>,
|
||||
getGlobalState(context, "openAiHeaders") as Promise<Record<string, string> | undefined>,
|
||||
getGlobalState(context, "ollamaBaseUrl") as Promise<string | undefined>,
|
||||
getSecret(context, "ollamaApiKey") as Promise<string | undefined>,
|
||||
getGlobalState(context, "ollamaApiOptionsCtxNum") as Promise<string | undefined>,
|
||||
getGlobalState(context, "lmStudioBaseUrl") as Promise<string | undefined>,
|
||||
getGlobalState(context, "anthropicBaseUrl") as Promise<string | undefined>,
|
||||
@@ -468,6 +470,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
|
||||
openAiApiKey,
|
||||
openAiHeaders: openAiHeaders || {},
|
||||
ollamaBaseUrl,
|
||||
ollamaApiKey,
|
||||
ollamaApiOptionsCtxNum,
|
||||
lmStudioBaseUrl,
|
||||
anthropicBaseUrl,
|
||||
@@ -617,6 +620,7 @@ export async function resetGlobalState(controller: Controller) {
|
||||
"awsSessionToken",
|
||||
"awsBedrockApiKey",
|
||||
"openAiApiKey",
|
||||
"ollamaApiKey",
|
||||
"geminiApiKey",
|
||||
"openAiNativeApiKey",
|
||||
"deepSeekApiKey",
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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
@@ -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> {
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
@@ -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,5 +1,6 @@
|
||||
export type HistoryItem = {
|
||||
id: string
|
||||
uuid?: string // UUID for better tracking and metrics
|
||||
ts: number
|
||||
task: string
|
||||
tokensIn: number
|
||||
|
||||
@@ -62,6 +62,7 @@ export interface ApiHandlerOptions {
|
||||
openAiBaseUrl?: string
|
||||
openAiApiKey?: string
|
||||
ollamaBaseUrl?: string
|
||||
ollamaApiKey?: string
|
||||
ollamaApiOptionsCtxNum?: string
|
||||
lmStudioBaseUrl?: string
|
||||
geminiApiKey?: string
|
||||
@@ -508,6 +509,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,
|
||||
|
||||
@@ -354,6 +354,7 @@ export function convertApiConfigurationToProto(config: ApiConfiguration): ProtoA
|
||||
openAiBaseUrl: config.openAiBaseUrl,
|
||||
openAiApiKey: config.openAiApiKey,
|
||||
ollamaBaseUrl: config.ollamaBaseUrl,
|
||||
ollamaApiKey: config.ollamaApiKey,
|
||||
ollamaApiOptionsCtxNum: config.ollamaApiOptionsCtxNum,
|
||||
lmStudioBaseUrl: config.lmStudioBaseUrl,
|
||||
geminiApiKey: config.geminiApiKey,
|
||||
@@ -485,6 +486,7 @@ export function convertProtoToApiConfiguration(protoConfig: ProtoApiConfiguratio
|
||||
openAiBaseUrl: protoConfig.openAiBaseUrl,
|
||||
openAiApiKey: protoConfig.openAiApiKey,
|
||||
ollamaBaseUrl: protoConfig.ollamaBaseUrl,
|
||||
ollamaApiKey: protoConfig.ollamaApiKey,
|
||||
ollamaApiOptionsCtxNum: protoConfig.ollamaApiOptionsCtxNum,
|
||||
lmStudioBaseUrl: protoConfig.lmStudioBaseUrl,
|
||||
geminiApiKey: protoConfig.geminiApiKey,
|
||||
|
||||
@@ -34,6 +34,7 @@ export function convertApiConfigurationToProtoApiConfiguration(config: ApiConfig
|
||||
openaiBaseUrl: config.openAiBaseUrl,
|
||||
openaiApiKey: config.openAiApiKey,
|
||||
ollamaBaseUrl: config.ollamaBaseUrl,
|
||||
ollamaApiKey: config.ollamaApiKey,
|
||||
ollamaApiOptionsCtxNum: config.ollamaApiOptionsCtxNum,
|
||||
lmStudioBaseUrl: config.lmStudioBaseUrl,
|
||||
geminiApiKey: config.geminiApiKey,
|
||||
@@ -159,6 +160,7 @@ export function convertProtoApiConfigurationToApiConfiguration(protoConfig: Prot
|
||||
openAiBaseUrl: protoConfig.openaiBaseUrl,
|
||||
openAiApiKey: protoConfig.openaiApiKey,
|
||||
ollamaBaseUrl: protoConfig.ollamaBaseUrl,
|
||||
ollamaApiKey: protoConfig.ollamaApiKey,
|
||||
ollamaApiOptionsCtxNum: protoConfig.ollamaApiOptionsCtxNum,
|
||||
lmStudioBaseUrl: protoConfig.lmStudioBaseUrl,
|
||||
geminiApiKey: protoConfig.geminiApiKey,
|
||||
|
||||
@@ -39,6 +39,7 @@ interface ChatViewProps {
|
||||
|
||||
// Use constants from the imported module
|
||||
const MAX_IMAGES_AND_FILES_PER_MESSAGE = CHAT_CONSTANTS.MAX_IMAGES_AND_FILES_PER_MESSAGE
|
||||
const QUICK_WINS_HISTORY_THRESHOLD = 3
|
||||
|
||||
const IS_STANDALONE = window?.__is_standalone__ ?? false
|
||||
|
||||
@@ -51,8 +52,11 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
|
||||
telemetrySetting,
|
||||
navigateToChat,
|
||||
mode,
|
||||
userInfo,
|
||||
} = useExtensionState()
|
||||
const shouldShowQuickWins = false // !taskHistory || taskHistory.length < QUICK_WINS_HISTORY_THRESHOLD
|
||||
const isProdHostedApp = userInfo?.apiBaseUrl === "https://app.cline.bot"
|
||||
const shouldShowQuickWins = isProdHostedApp && (!taskHistory || taskHistory.length < QUICK_WINS_HISTORY_THRESHOLD)
|
||||
|
||||
//const task = messages.length > 0 ? (messages[0].say === "task" ? messages[0] : undefined) : undefined) : undefined
|
||||
const task = useMemo(() => messages.at(0), [messages]) // leaving this less safe version here since if the first message is not a task, then the extension is in a bad state and needs to be debugged (see Cline.abort)
|
||||
const modifiedMessages = useMemo(() => combineApiRequests(combineCommandSequences(messages.slice(1))), [messages])
|
||||
|
||||
@@ -25,7 +25,7 @@ export const WelcomeSection: React.FC<WelcomeSectionProps> = ({
|
||||
<div className="overflow-y-auto flex flex-col pb-2.5">
|
||||
{telemetrySetting === "unset" && <TelemetryBanner />}
|
||||
{showAnnouncement && <Announcement version={version} hideAnnouncement={hideAnnouncement} />}
|
||||
<HomeHeader />
|
||||
<HomeHeader shouldShowQuickWins={shouldShowQuickWins} />
|
||||
{!shouldShowQuickWins && taskHistory.length > 0 && <HistoryPreview showHistoryView={showHistoryView} />}
|
||||
</div>
|
||||
<SuggestedTasks shouldShowQuickWins={shouldShowQuickWins} />
|
||||
|
||||
@@ -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} />
|
||||
|
||||
@@ -2,6 +2,7 @@ import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useState, useCallback, useEffect } from "react"
|
||||
import { useInterval } from "react-use"
|
||||
import { DebouncedTextField } from "../common/DebouncedTextField"
|
||||
import { ApiKeyField } from "../common/ApiKeyField"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { StringRequest } from "@shared/proto/cline/common"
|
||||
import OllamaModelPicker from "../OllamaModelPicker"
|
||||
@@ -62,6 +63,16 @@ export const OllamaProvider = ({ showModelOptions, isPopup, currentMode }: Ollam
|
||||
label="Use custom base URL"
|
||||
/>
|
||||
|
||||
{apiConfiguration?.ollamaBaseUrl && (
|
||||
<ApiKeyField
|
||||
initialValue={apiConfiguration?.ollamaApiKey || ""}
|
||||
onChange={(value) => handleFieldChange("ollamaApiKey", value)}
|
||||
providerName="Ollama"
|
||||
placeholder="Enter API Key (optional)..."
|
||||
helpText="Optional API key for authenticated Ollama instances or cloud services. Leave empty for local installations."
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Model selection - use filterable picker */}
|
||||
<label htmlFor="ollama-model-selection">
|
||||
<span style={{ fontWeight: 500 }}>Model</span>
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
import ClineLogoVariable from "@/assets/ClineLogoVariable"
|
||||
import HeroTooltip from "@/components/common/HeroTooltip"
|
||||
import { UiServiceClient } from "@/services/grpc-client"
|
||||
import { EmptyRequest } from "@shared/proto/cline/common"
|
||||
|
||||
interface HomeHeaderProps {
|
||||
shouldShowQuickWins?: boolean
|
||||
}
|
||||
|
||||
const HomeHeader = ({ shouldShowQuickWins = false }: HomeHeaderProps) => {
|
||||
const handleTakeATour = async () => {
|
||||
try {
|
||||
await UiServiceClient.openWalkthrough(EmptyRequest.create())
|
||||
} catch (error) {
|
||||
console.error("Error opening walkthrough:", error)
|
||||
}
|
||||
}
|
||||
|
||||
const HomeHeader = () => {
|
||||
return (
|
||||
<div className="flex flex-col items-center mb-5">
|
||||
<div className="my-5">
|
||||
@@ -21,6 +35,16 @@ const HomeHeader = () => {
|
||||
/>
|
||||
</HeroTooltip>
|
||||
</div>
|
||||
{shouldShowQuickWins && (
|
||||
<div className="mt-4">
|
||||
<button
|
||||
onClick={handleTakeATour}
|
||||
className="flex items-center gap-2 px-4 py-2 rounded-full border border-[var(--vscode-panel-border)] bg-white/[0.02] hover:bg-[var(--vscode-list-hoverBackground)] transition-colors duration-150 ease-in-out text-[var(--vscode-editor-foreground)] text-sm font-medium cursor-pointer">
|
||||
Take a Tour
|
||||
<span className="codicon codicon-play scale-90"></span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ interface QuickWinCardProps {
|
||||
}
|
||||
|
||||
const renderIcon = (iconName?: string) => {
|
||||
if (!iconName) return <span className="codicon codicon-rocket text-lg"></span>
|
||||
if (!iconName) return <span className="codicon codicon-rocket !text-[28px] !leading-[1]"></span>
|
||||
|
||||
let iconClass = "codicon-rocket"
|
||||
switch (iconName) {
|
||||
@@ -23,21 +23,25 @@ const renderIcon = (iconName?: string) => {
|
||||
default:
|
||||
break
|
||||
}
|
||||
return <span className={`codicon ${iconClass} text-lg`}></span>
|
||||
return <span className={`codicon ${iconClass} !text-[28px] !leading-[1]`}></span>
|
||||
}
|
||||
|
||||
const QuickWinCard: React.FC<QuickWinCardProps> = ({ task, onExecute }) => {
|
||||
return (
|
||||
<div
|
||||
className="flex items-center p-1 space-x-1.5 rounded-full cursor-pointer group transition-colors duration-150 ease-in-out bg-[var(--vscode-sideBar-background)] border border-[var(--vscode-panel-border)] hover:bg-[var(--vscode-list-hoverBackground)]"
|
||||
className="flex items-center mb-2 py-0 px-5 space-x-3 rounded-full cursor-pointer group transition-colors duration-150 ease-in-out bg-white/[0.02] border border-[var(--vscode-panel-border)] hover:bg-[var(--vscode-list-hoverBackground)]"
|
||||
onClick={() => onExecute()}>
|
||||
<div className="flex-shrink-0 flex items-center justify-center w-5 h-5 text-[var(--vscode-icon-foreground)]">
|
||||
<div className="flex-shrink-0 flex items-center justify-center w-6 h-6 text-[var(--vscode-icon-foreground)]">
|
||||
{renderIcon(task.icon)}
|
||||
</div>
|
||||
|
||||
<div className="flex-grow min-w-0">
|
||||
<h3 className="text-xs font-medium truncate text-[var(--vscode-editor-foreground)]">{task.title}</h3>
|
||||
<p className="text-xs truncate text-[var(--vscode-descriptionForeground)]">{task.description}</p>
|
||||
<h3 className="text-sm font-medium truncate text-[var(--vscode-editor-foreground)] leading-tight mb-0 mt-0 pt-3">
|
||||
{task.title}
|
||||
</h3>
|
||||
<p className="text-xs truncate text-[var(--vscode-descriptionForeground)] leading-tight mt-[1px]">
|
||||
{task.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -13,8 +13,8 @@ export const SuggestedTasks: React.FC<{ shouldShowQuickWins: boolean }> = ({ sho
|
||||
return (
|
||||
<div className="px-4 pt-1 pb-3 select-none">
|
||||
{" "}
|
||||
<h2 className="text-sm font-medium mb-2.5 text-center text-[var(--vscode-editor-foreground)]">
|
||||
Quick <span className="text-[var(--vscode-terminal-ansiBrightCyan)]">[Wins]</span> with Cline
|
||||
<h2 className="text-sm font-medium mb-2.5 text-center text-gray">
|
||||
Quick <span className="text-white">[Wins]</span> with Cline
|
||||
</h2>
|
||||
<div className="flex flex-col space-y-1">
|
||||
{" "}
|
||||
|
||||
@@ -12,7 +12,7 @@ export const quickWinTasks: QuickWinTask[] = [
|
||||
{
|
||||
id: "nextjs_notetaking_app",
|
||||
title: "Build a Next.js App",
|
||||
description: "Create a beautiful notetaking application with Next.js and Tailwind CSS.",
|
||||
description: "Create a beautiful notetaking app with Next.js and Tailwind",
|
||||
icon: "WebAppIcon",
|
||||
actionCommand: "cline/createNextJsApp",
|
||||
prompt: "Make a beautiful Next.js notetaking app, using Tailwind CSS for styling. Set up the basic structure and a simple UI for adding and viewing notes.",
|
||||
@@ -21,10 +21,10 @@ export const quickWinTasks: QuickWinTask[] = [
|
||||
{
|
||||
id: "terminal_cli_tool",
|
||||
title: "Craft a CLI Tool",
|
||||
description: "Develop a powerful terminal CLI to automate a cool task.",
|
||||
description: "Develop a powerful terminal CLI to automate a cool task",
|
||||
icon: "TerminalIcon",
|
||||
actionCommand: "cline/createCliTool",
|
||||
prompt: "Make a terminal CLI tool using Node.js that fetches the current weather for a given city using a free weather API and displays it in a user-friendly format.",
|
||||
prompt: "Make a terminal CLI tool using Node.js that organizes files in a directory by type, size, or date. It should have options to sort files into folders, show file statistics, find duplicates, and clean up empty directories. Include colorful output and progress indicators.",
|
||||
buttonText: ">",
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user