Compare commits

...
Author SHA1 Message Date
Andrei Eternal 2e530b1271 cleanup 2025-05-22 16:42:13 -07:00
Andrei Edell f6e481baf9 memory leak console boys 2025-05-22 16:42:13 -07:00
Andrei Edell 77128afa20 Revert "fix: Address memory leak by bypassing subscribeToState gRPC stream for state updates (#3597)"
This reverts commit 8ab35a5b06.
2025-05-22 16:42:13 -07:00
Sarah Fortune 2cedcc5a58 Add vscode CSS properties to the script get-vscode-usages.sh (#3752)
The script will report which vscode CSS vars are being used in the webview, as well the uses of the vscode SDK.
2025-05-22 16:18:08 -07:00
limitx0 14a0c60550 Fix the Syntax in zh-tw/README.md to Improve Text Rendering (#3724)
* Update zh-tw/README.md

Correct the Markdown syntax to properly display bold text.

* Update zh-tw/README.md

Insert line breaks for each item listed under ### 新增上下文.
2025-05-22 15:53:15 -07:00
github-actions[bot] cdf368c21c v3.17.2 Release Notes
v3.17.2 Release Notes
2025-05-22 15:43:07 -07:00
Toshii f3ae1340cf global workflows (#3709)
* backend global workflows

* base

* nit

* protos

* base 2

* ui

* Delete proto file

* changeset
2025-05-22 15:34:51 -07:00
David Nanyan 624fb8c8a1 [ISSUE-3707] Fix issue with process env (#3741)
* [ISSUE-3707] Fix issue with process env

* Add tests
2025-05-22 15:33:05 -07:00
EvanandElephant Lumps dbb5ac265d Claude 4 rest of updates (#3749)
* add protos files (#3736)

Co-authored-by: Elephant Lumps <celestial_vault@Elephants-MacBook-Pro.local>

* change package script

* rest of updates for vertex / bedrock

---------

Co-authored-by: Elephant Lumps <celestial_vault@Elephants-MacBook-Pro.local>
2025-05-22 15:20:54 -07:00
pashpashpashandCline Evaluation 1fd137b684 z-index-fix on settings page (#3748)
Co-authored-by: Cline Evaluation <cline@example.com>
2025-05-22 15:20:54 -07:00
github-actions[bot] a718cc950e v3.17.1 Release Notes
v3.17.1 Release Notes
2025-05-22 15:20:26 -07:00
EvanandElephant Lumps cea93d9e98 Update package script (#3738)
* add protos files (#3736)

Co-authored-by: Elephant Lumps <celestial_vault@Elephants-MacBook-Pro.local>

* change package script

---------

Co-authored-by: Elephant Lumps <celestial_vault@Elephants-MacBook-Pro.local>
2025-05-22 12:56:27 -07:00
EvanandElephant Lumps 346c1f7eff Opus 4 max tokens (#3735)
* anthropic opus max tokens increased

* changeset

---------

Co-authored-by: Elephant Lumps <celestial_vault@Elephants-MacBook-Pro.local>
2025-05-22 12:47:23 -07:00
EvanandElephant Lumps 32f200e837 Prompt caching Claude 4 Openrouter/Cline (#3722)
* add prompt caching and suggested models

* wording

* change wording again

* remove opus recommended

---------

Co-authored-by: Elephant Lumps <celestial_vault@Elephants-MacBook-Pro.local>
2025-05-22 12:44:33 -07:00
EvanandElephant Lumps 07a2daa827 Put protos back in gitignore (#3739)
* put protos back in gitignore

* changeset

---------

Co-authored-by: Elephant Lumps <celestial_vault@Elephants-MacBook-Pro.local>
2025-05-23 00:33:21 +05:30
github-actions[bot] a22fc10a72 v3.17.0 Release Notes
v3.17.0 Release Notes
2025-05-22 11:02:17 -07:00
EvanandElephant Lumps 0c306121aa Migrate didShowAnnouncement protobus (#3699)
* migrate didShowAnnouncement

* changeset

* remove comment

* make variable public

---------

Co-authored-by: Elephant Lumps <celestial_vault@Elephants-MacBook-Pro.local>
2025-05-22 10:36:31 -07:00
pashpashpashandCline Evaluation 97139f713b settings cancel (#3734)
* settings cancel

* settings cancel

---------

Co-authored-by: Cline Evaluation <cline@example.com>
2025-05-22 10:04:19 -07:00
Tomás Barreiro 77a877c6d3 fix: Replace the togglePlanActMode call with protobuf (#3730)
* Add togglePlanActMode to the WebviewMessage type

* replace the service call with a protobus client call
2025-05-22 09:56:43 -07:00
EvanandElephant Lumps 627590ff2a anthropic support (#3733)
Co-authored-by: Elephant Lumps <celestial_vault@Elephants-MacBook-Pro.local>
2025-05-22 09:56:32 -07:00
88 changed files with 10329 additions and 333 deletions
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
when the assistant says to act mode we render a custom highlight with hotkey suggestion
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
New settings page split into tabs
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
no longer requires `transportType` property to be set in MCP Server configuration.
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
autoApprovalSettings protobus migration
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Remove advanced settings banner
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": minor
---
Sonnet 4 UI copy updates
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": minor
---
integration with nebius ai studio
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": minor
---
remove proto file
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Fix model listing for Requesty
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Change the extension title name wording
+22
View File
@@ -1,5 +1,27 @@
# Changelog
## [3.17.2]
- Add support for Claude 4 models (Sonnet 4 and Opus 4) in AWS Bedrock and Vertex AI providers
- Add support for global workflows, allowing workflows to be shared across workspaces with local workflows taking precedence
- Fix settings page z-index UI issues that caused display problems
- Fix AWS Bedrock environment variable handling to properly restore process.env after API calls (Thanks @DaveFres!)
## [3.17.1]
- Add prompt caching for Claude 4 models on Cline and OpenRouter providers
- Increase max tokens for Claude Opus 4 from 4096 to 8192
## [3.17.0]
- Add support for Anthropic Claude Sonnet 4 and Claude Opus 4 in both Anthropic and Vertex providers
- Add integration with Nebius AI Studio as a new provider (Thanks @Aktsvigun!)
- Add custom highlight and hotkey suggestion when the assistant prompts to switch to Act mode
- Update settings page design, now split into tabs for easier navigation (Thanks Yellow Bat @dlab-anton, and Roo Team!)
- Fix MCP Server configuration bug
- Fix model listing for Requesty provider
- Move all advanced settings to settings page
## [3.16.3]
- Add devstral-small-2505 to the Mistral model list, a new specialized coding model from Mistral AI (Thanks @BarreiroT!)
+7 -4
View File
@@ -108,10 +108,13 @@ Cline 可以直接在您的編輯器中建立和編輯檔案,並顯示變更
### 新增上下文
**`@url`**貼上網址讓擴充套件擷取並轉換為 Markdown,當您想給 Cline 最新文件時很有用
**`@problems`:**新增工作區的錯誤和警告(「問題」面板)給 Cline 修正
**`@file`**新增檔案內容,讓您不必浪費 API 請求來核准讀取檔案(+ 輸入以搜尋檔案)
**`@folder`:**一次新增整個資料夾的檔案,讓您的工作流程更快速
**`@url`**貼上網址讓擴充套件擷取並轉換為 Markdown,當您想給 Cline 最新文件時很有用
**`@problems`**新增工作區的錯誤和警告(「問題」面板)給 Cline 修正
**`@file`**:新增檔案內容,讓您不必浪費 API 請求來核准讀取檔案(+ 輸入以搜尋檔案)
**`@folder`**:一次新增整個資料夾的檔案,讓您的工作流程更快速
<!-- 透明像素用於浮動圖片後的換行 -->
<img width="2000" height="0" src="https://github.com/user-attachments/assets/ee14e6f7-20b8-4391-9091-8e8e25561929"><br>
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "claude-dev",
"version": "3.16.3",
"version": "3.17.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "claude-dev",
"version": "3.16.3",
"version": "3.17.2",
"license": "Apache-2.0",
"dependencies": {
"@anthropic-ai/bedrock-sdk": "^0.12.4",
+2 -2
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.16.3",
"version": "3.17.2",
"icon": "assets/icons/icon.png",
"engines": {
"vscode": "^1.84.0"
@@ -278,7 +278,7 @@
"watch": "npm-run-all -p watch:*",
"watch:esbuild": "node esbuild.js --watch",
"watch:tsc": "tsc --noEmit --watch --project tsconfig.json",
"package": "npm run build:webview && npm run check-types && npm run lint && node esbuild.js --production",
"package": "npm run check-types && npm run build:webview && npm run lint && node esbuild.js --production",
"protos": "node proto/build-proto.js && node scripts/generate-server-setup.mjs",
"postprotos": "prettier src/shared/proto src/core/controller webview-ui/src/services src/standalone/server-setup.ts --write --log-level silent",
"compile-tests": "node ./scripts/build-tests.js",
+2 -1
View File
@@ -57,7 +57,8 @@ message RefreshedRules {
ClineRulesToggles local_cline_rules_toggles = 2;
ClineRulesToggles local_cursor_rules_toggles = 3;
ClineRulesToggles local_windsurf_rules_toggles = 4;
ClineRulesToggles workflow_toggles = 5;
ClineRulesToggles local_workflow_toggles = 5;
ClineRulesToggles global_workflow_toggles = 6;
}
// Request to toggle a Windsurf rule
+3 -1
View File
@@ -10,5 +10,7 @@ import "common.proto";
service UiService {
// Scrolls to a specific settings section in the settings view
rpc scrollToSettings(StringRequest) returns (Empty);
// Marks the current announcement as shown and returns whether an announcement should still be shown
rpc onDidShowAnnouncement(EmptyRequest) returns (Boolean);
}
+12 -3
View File
@@ -3,7 +3,8 @@ set -eu
DIR=${1:-src/}
DEST_DIR=dist-standalone
DEST=dist-standalone/vscode-uses.txt
SDK_DEST=$DEST_DIR/vscode-sdk-uses.txt
CSS_DEST=$DEST_DIR/vscode-css-uses.txt
mkdir -p $DEST_DIR
{
@@ -11,8 +12,16 @@ git grep -h 'vscode\.' $DIR |
grep -Ev '//.*vscode' | # remove commented out code
sed 's|.*vscode\.|vscode.|'| # remove everything before vscode.
sed 's/[^a-zA-Z0-9_.].*$//' | # remove everything after last identifier
sort | uniq > $DEST
sort | uniq > $SDK_DEST
}
echo Wrote uses of the vscode SDK to $(realpath $SDK_DEST)
echo Done, wrote uses of the vscode SDK to $(realpath $DEST)
{
grep -rh -- --vscode- webview-ui/build/ |
sed 's/--vscode/\n--vscode/g' | # One var per line
grep -- --vscode | # Remove lines that don't have vars.
sed 's/[),"\\].*$//' | # remove from the end of the var name to the end of the line.
sort | uniq > $CSS_DEST
}
echo Wrote vscode vars used to $(realpath $CSS_DEST)
+145
View File
@@ -0,0 +1,145 @@
import "should"
import { AwsBedrockHandler } from "../bedrock"
import { ApiHandlerOptions } from "@shared/api"
describe("AwsBedrockHandler", () => {
describe("withTempEnv", () => {
// Store original env vars for cleanup
const originalEnv: Record<string, string | undefined> = {}
beforeEach(() => {
// Store original values before each test
originalEnv.TEST_VAR = process.env.TEST_VAR
originalEnv.ANOTHER_VAR = process.env.ANOTHER_VAR
originalEnv.VAR1 = process.env.VAR1
originalEnv.VAR2 = process.env.VAR2
originalEnv.VAR3 = process.env.VAR3
originalEnv.UNDEFINED_VAR = process.env.UNDEFINED_VAR
})
afterEach(() => {
// Restore original values after each test
Object.entries(originalEnv).forEach(([key, value]) => {
if (value === undefined) {
delete process.env[key]
} else {
process.env[key] = value
}
})
})
it("should restore original environment variables after operation", async () => {
// Set initial environment
process.env.TEST_VAR = "original"
process.env.ANOTHER_VAR = "another"
// Store original values
const originalTestVar = process.env.TEST_VAR
const originalAnotherVar = process.env.ANOTHER_VAR
await AwsBedrockHandler["withTempEnv"](
() => {
process.env.TEST_VAR = "modified"
delete process.env.ANOTHER_VAR
},
async () => {
// Verify environment is modified
process.env.TEST_VAR!.should.equal("modified")
should.not.exist(process.env.ANOTHER_VAR)
return "test"
},
)
// Verify environment is restored
process.env.TEST_VAR!.should.equal(originalTestVar)
process.env.ANOTHER_VAR!.should.equal(originalAnotherVar)
})
it("should handle undefined environment variables", async () => {
await AwsBedrockHandler["withTempEnv"](
() => {
delete process.env.UNDEFINED_VAR
},
async () => {
should.not.exist(process.env.UNDEFINED_VAR)
return "test"
},
)
// Verify undefined variable is not present
should.not.exist(process.env.UNDEFINED_VAR)
})
it("should handle errors and still restore environment", async () => {
// Set initial environment
process.env.TEST_VAR = "original"
try {
await AwsBedrockHandler["withTempEnv"](
() => {
process.env.TEST_VAR = "modified"
},
async () => {
throw new Error("Test error")
},
)
should.fail(null, null, "Expected error was not thrown", "throw")
} catch (error) {
;(error as Error).message.should.equal("Test error")
}
// Verify environment is restored even after error
process.env.TEST_VAR!.should.equal("original")
})
it("should handle multiple environment variable changes", async () => {
// Set initial environment
process.env.VAR1 = "original1"
process.env.VAR2 = "original2"
process.env.VAR3 = "original3"
// Store original values
const originalVar1 = process.env.VAR1
const originalVar2 = process.env.VAR2
const originalVar3 = process.env.VAR3
await AwsBedrockHandler["withTempEnv"](
() => {
process.env.VAR1 = "modified1"
process.env.VAR2 = "modified2"
delete process.env.VAR3
},
async () => {
// Verify environment is modified
process.env.VAR1!.should.equal("modified1")
process.env.VAR2!.should.equal("modified2")
should.not.exist(process.env.VAR3)
return "test"
},
)
// Verify environment is restored
process.env.VAR1!.should.equal(originalVar1)
process.env.VAR2!.should.equal(originalVar2)
process.env.VAR3!.should.equal(originalVar3)
})
it("should work with AWS_PROFILE", async () => {
process.env["AWS_PROFILE"] = "test-profile"
const preAWSProfile = process.env["AWS_PROFILE"]
await AwsBedrockHandler["withTempEnv"](
() => {
delete process.env["AWS_PROFILE"]
},
async () => {
should.not.exist(process.env["AWS_PROFILE"])
return "test"
},
)
process.env["AWS_PROFILE"]!.should.equal(preAWSProfile)
})
})
})
+5 -1
View File
@@ -24,13 +24,15 @@ export class AnthropicHandler implements ApiHandler {
const modelId = model.id
const budget_tokens = this.options.thinkingBudgetTokens || 0
const reasoningOn = modelId.includes("3-7") && budget_tokens !== 0 ? true : false
const reasoningOn = (modelId.includes("3-7") || modelId.includes("4-")) && budget_tokens !== 0 ? true : false
switch (modelId) {
// 'latest' alias does not support cache_control
case "claude-sonnet-4-20250514":
case "claude-3-7-sonnet-20250219":
case "claude-3-5-sonnet-20241022":
case "claude-3-5-haiku-20241022":
case "claude-opus-4-20250514":
case "claude-3-opus-20240229":
case "claude-3-haiku-20240307": {
/*
@@ -96,6 +98,8 @@ export class AnthropicHandler implements ApiHandler {
// https://github.com/anthropics/anthropic-sdk-typescript?tab=readme-ov-file#default-headers
// https://github.com/anthropics/anthropic-sdk-typescript/commit/c920b77fc67bd839bfeb6716ceab9d7c9bbe7393
switch (modelId) {
case "claude-sonnet-4-20250514":
case "claude-opus-4-20250514":
case "claude-3-7-sonnet-20250219":
case "claude-3-5-sonnet-20241022":
case "claude-3-5-haiku-20241022":
+70 -50
View File
@@ -47,7 +47,11 @@ export class AwsBedrockHandler implements ApiHandler {
}
const budget_tokens = this.options.thinkingBudgetTokens || 0
const reasoningOn = baseModelId.includes("3-7") && budget_tokens !== 0 ? true : false
const reasoningOn =
(baseModelId.includes("3-7") || baseModelId.includes("sonnet-4") || baseModelId.includes("opus-4")) &&
budget_tokens !== 0
? true
: false
// Get model info and message indices for caching
const userMsgIndices = messages.reduce((acc, msg, index) => (msg.role === "user" ? [...acc, index] : acc), [] as number[])
@@ -58,56 +62,62 @@ export class AwsBedrockHandler implements ApiHandler {
// initialization, and allowing for session renewal if necessary as well
const client = await this.getAnthropicClient()
// AWS SDK prioritizes AWS_PROFILE over AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY pair
// If this is set as an env variable already (ie. from ~/.zshrc) it will override credentials configured by Cline
const previousEnv = process.env
delete process.env["AWS_PROFILE"]
const stream = await client.messages.create({
model: modelId,
max_tokens: model.info.maxTokens || 8192,
thinking: reasoningOn ? { type: "enabled", budget_tokens: budget_tokens } : undefined,
temperature: reasoningOn ? undefined : 0,
system: [
{
text: systemPrompt,
type: "text",
...(this.options.awsBedrockUsePromptCache === true && {
cache_control: { type: "ephemeral" },
}),
},
],
messages: messages.map((message, index) => {
if (index === lastUserMsgIndex || index === secondLastMsgUserIndex) {
return {
...message,
content:
typeof message.content === "string"
? [
{
type: "text",
text: message.content,
...(this.options.awsBedrockUsePromptCache === true && {
cache_control: { type: "ephemeral" },
}),
},
]
: message.content.map((content, contentIndex) =>
contentIndex === message.content.length - 1
? {
...content,
// Use withTempEnv to ensure environment variables are properly restored
const stream = await AwsBedrockHandler.withTempEnv(
() => {
// AWS SDK prioritizes AWS_PROFILE over AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY pair
// If this is set as an env variable already (ie. from ~/.zshrc) it will override credentials configured by Cline
// Temporarily remove AWS_PROFILE to ensure our credentials are used
delete process.env["AWS_PROFILE"]
},
async () => {
return await client.messages.create({
model: modelId,
max_tokens: model.info.maxTokens || 8192,
thinking: reasoningOn ? { type: "enabled", budget_tokens: budget_tokens } : undefined,
temperature: reasoningOn ? undefined : 0,
system: [
{
text: systemPrompt,
type: "text",
...(this.options.awsBedrockUsePromptCache === true && {
cache_control: { type: "ephemeral" },
}),
},
],
messages: messages.map((message, index) => {
if (index === lastUserMsgIndex || index === secondLastMsgUserIndex) {
return {
...message,
content:
typeof message.content === "string"
? [
{
type: "text",
text: message.content,
...(this.options.awsBedrockUsePromptCache === true && {
cache_control: { type: "ephemeral" },
}),
}
: content,
),
}
}
return message
}),
stream: true,
})
process.env = previousEnv
},
]
: message.content.map((content, contentIndex) =>
contentIndex === message.content.length - 1
? {
...content,
...(this.options.awsBedrockUsePromptCache === true && {
cache_control: { type: "ephemeral" },
}),
}
: content,
),
}
}
return message
}),
stream: true,
})
},
)
for await (const chunk of stream) {
switch (chunk.type) {
@@ -297,13 +307,23 @@ export class AwsBedrockHandler implements ApiHandler {
}
private static async withTempEnv<R>(updateEnv: () => void, fn: () => Promise<R>): Promise<R> {
const previousEnv = { ...process.env }
const previousEnv = Object.assign({}, process.env)
try {
updateEnv()
return await fn()
} finally {
process.env = previousEnv
// Restore the previous environment
// First clear any new variables that might have been added
for (const key in process.env) {
if (!(key in previousEnv)) {
delete process.env[key]
}
}
// Then restore all previous values
for (const key in previousEnv) {
process.env[key] = previousEnv[key]
}
}
}
+4 -1
View File
@@ -51,7 +51,10 @@ export class RequestyHandler implements ApiHandler {
thinkingBudget > 0
? { thinking: { type: "enabled", budget_tokens: thinkingBudget } }
: { thinking: { type: "disabled" } }
const thinkingArgs = model.id.includes("claude-3-7-sonnet") ? thinking : {}
const thinkingArgs =
model.id.includes("claude-3-7-sonnet") || model.id.includes("claude-sonnet-4") || model.id.includes("claude-opus-4")
? thinking
: {}
// @ts-ignore-next-line
const stream = await this.client.chat.completions.create({
+6 -1
View File
@@ -41,10 +41,15 @@ export class VertexHandler implements ApiHandler {
// Claude implementation
let budget_tokens = this.options.thinkingBudgetTokens || 0
const reasoningOn = modelId.includes("3-7") && budget_tokens !== 0 ? true : false
const reasoningOn =
(modelId.includes("3-7") || modelId.includes("sonnet-4") || modelId.includes("opus-4")) && budget_tokens !== 0
? true
: false
let stream
switch (modelId) {
case "claude-sonnet-4@20250514":
case "claude-opus-4@20250514":
case "claude-3-7-sonnet@20250219":
case "claude-3-5-sonnet-v2@20241022":
case "claude-3-5-sonnet@20240620":
+6
View File
@@ -23,6 +23,8 @@ export async function createOpenRouterStream(
// this was initially specifically for claude models (some models may 'support prompt caching' automatically without this)
// handles direct model.id match logic
switch (model.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:thinking":
@@ -79,6 +81,8 @@ export async function createOpenRouterStream(
// (models usually default to max tokens allowed)
let maxTokens: number | undefined
switch (model.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:thinking":
@@ -112,6 +116,8 @@ export async function createOpenRouterStream(
let reasoning: { max_tokens: number } | undefined = undefined
switch (model.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:thinking":
@@ -1,5 +1,5 @@
import { fileExistsAtPath, isDirectory, readDirectory } from "@utils/fs"
import { ensureRulesDirectoryExists, GlobalFileNames } from "@core/storage/disk"
import { ensureRulesDirectoryExists, ensureWorkflowsDirectoryExists, GlobalFileNames } from "@core/storage/disk"
import { getGlobalState, getWorkspaceState, updateGlobalState, updateWorkspaceState } from "@core/storage/state"
import * as path from "path"
import fs from "fs/promises"
@@ -172,9 +172,13 @@ export const createRuleFile = async (isGlobal: boolean, filename: string, cwd: s
try {
let filePath: string
if (isGlobal) {
// global means its implicitly clinerules
const globalClineRulesFilePath = await ensureRulesDirectoryExists()
filePath = path.join(globalClineRulesFilePath, filename)
if (type === "workflow") {
const globalClineWorkflowFilePath = await ensureWorkflowsDirectoryExists()
filePath = path.join(globalClineWorkflowFilePath, filename)
} else {
const globalClineRulesFilePath = await ensureRulesDirectoryExists()
filePath = path.join(globalClineRulesFilePath, filename)
}
} else {
const localClineRulesFilePath = path.resolve(cwd, GlobalFileNames.clineRules)
@@ -243,9 +247,15 @@ export async function deleteRuleFile(
// Update the appropriate toggles
if (isGlobal) {
const toggles = ((await getGlobalState(context, "globalClineRulesToggles")) as ClineRulesToggles) || {}
delete toggles[rulePath]
await updateGlobalState(context, "globalClineRulesToggles", toggles)
if (type === "workflow") {
const toggles = ((await getGlobalState(context, "globalWorkflowToggles")) as ClineRulesToggles) || {}
delete toggles[rulePath]
await updateGlobalState(context, "globalWorkflowToggles", toggles)
} else {
const toggles = ((await getGlobalState(context, "globalClineRulesToggles")) as ClineRulesToggles) || {}
delete toggles[rulePath]
await updateGlobalState(context, "globalClineRulesToggles", toggles)
}
} else {
if (type === "workflow") {
const toggles = ((await getWorkspaceState(context, "workflowToggles")) as ClineRulesToggles) || {}
@@ -1,7 +1,7 @@
import path from "path"
import { GlobalFileNames } from "@core/storage/disk"
import { GlobalFileNames, ensureWorkflowsDirectoryExists } from "@core/storage/disk"
import { ClineRulesToggles } from "@shared/cline-rules"
import { getWorkspaceState, updateWorkspaceState } from "@core/storage/state"
import { getWorkspaceState, updateWorkspaceState, getGlobalState, updateGlobalState } from "@core/storage/state"
import * as vscode from "vscode"
import { synchronizeRuleToggles } from "@core/context/instructions/user-instructions/rule-helpers"
@@ -11,10 +11,23 @@ import { synchronizeRuleToggles } from "@core/context/instructions/user-instruct
export async function refreshWorkflowToggles(
context: vscode.ExtensionContext,
workingDirectory: string,
): Promise<ClineRulesToggles> {
): Promise<{
globalWorkflowToggles: ClineRulesToggles
localWorkflowToggles: ClineRulesToggles
}> {
// Global workflows
const globalWorkflowToggles = ((await getGlobalState(context, "globalWorkflowToggles")) as ClineRulesToggles) || {}
const globalClineWorkflowsFilePath = await ensureWorkflowsDirectoryExists()
const updatedGlobalWorkflowToggles = await synchronizeRuleToggles(globalClineWorkflowsFilePath, globalWorkflowToggles)
await updateGlobalState(context, "globalWorkflowToggles", updatedGlobalWorkflowToggles)
const workflowRulesToggles = ((await getWorkspaceState(context, "workflowToggles")) as ClineRulesToggles) || {}
const workflowsDirPath = path.resolve(workingDirectory, GlobalFileNames.workflows)
const updatedWorkflowToggles = await synchronizeRuleToggles(workflowsDirPath, workflowRulesToggles)
await updateWorkspaceState(context, "workflowToggles", updatedWorkflowToggles)
return updatedWorkflowToggles
return {
globalWorkflowToggles: updatedGlobalWorkflowToggles,
localWorkflowToggles: updatedWorkflowToggles,
}
}
+22
View File
@@ -0,0 +1,22 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
import { createServiceRegistry, ServiceMethodHandler, StreamingMethodHandler } from "../grpc-service"
import { StreamingResponseHandler } from "../grpc-handler"
import { registerAllMethods } from "./methods"
// Create account service registry
const accountService = createServiceRegistry("account")
// Export the method handler types and registration function
export type AccountMethodHandler = ServiceMethodHandler
export type AccountStreamingMethodHandler = StreamingMethodHandler
export const registerMethod = accountService.registerMethod
// Export the request handlers
export const handleAccountServiceRequest = accountService.handleRequest
export const handleAccountServiceStreamingRequest = accountService.handleStreamingRequest
export const isStreamingMethod = accountService.isStreamingMethod
// Register all account methods
registerAllMethods()
+14
View File
@@ -0,0 +1,14 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
// Import all method implementations
import { registerMethod } from "./index"
import { accountLoginClicked } from "./accountLoginClicked"
import { accountLogoutClicked } from "./accountLogoutClicked"
// Register all account service methods
export function registerAllMethods(): void {
// Register each method with the registry
registerMethod("accountLoginClicked", accountLoginClicked)
registerMethod("accountLogoutClicked", accountLogoutClicked)
}
+22
View File
@@ -0,0 +1,22 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
import { createServiceRegistry, ServiceMethodHandler, StreamingMethodHandler } from "../grpc-service"
import { StreamingResponseHandler } from "../grpc-handler"
import { registerAllMethods } from "./methods"
// Create browser service registry
const browserService = createServiceRegistry("browser")
// Export the method handler types and registration function
export type BrowserMethodHandler = ServiceMethodHandler
export type BrowserStreamingMethodHandler = StreamingMethodHandler
export const registerMethod = browserService.registerMethod
// Export the request handlers
export const handleBrowserServiceRequest = browserService.handleRequest
export const handleBrowserServiceStreamingRequest = browserService.handleStreamingRequest
export const isStreamingMethod = browserService.isStreamingMethod
// Register all browser methods
registerAllMethods()
+22
View File
@@ -0,0 +1,22 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
// Import all method implementations
import { registerMethod } from "./index"
import { discoverBrowser } from "./discoverBrowser"
import { getBrowserConnectionInfo } from "./getBrowserConnectionInfo"
import { getDetectedChromePath } from "./getDetectedChromePath"
import { relaunchChromeDebugMode } from "./relaunchChromeDebugMode"
import { testBrowserConnection } from "./testBrowserConnection"
import { updateBrowserSettings } from "./updateBrowserSettings"
// Register all browser service methods
export function registerAllMethods(): void {
// Register each method with the registry
registerMethod("discoverBrowser", discoverBrowser)
registerMethod("getBrowserConnectionInfo", getBrowserConnectionInfo)
registerMethod("getDetectedChromePath", getDetectedChromePath)
registerMethod("relaunchChromeDebugMode", relaunchChromeDebugMode)
registerMethod("testBrowserConnection", testBrowserConnection)
registerMethod("updateBrowserSettings", updateBrowserSettings)
}
+22
View File
@@ -0,0 +1,22 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
import { createServiceRegistry, ServiceMethodHandler, StreamingMethodHandler } from "../grpc-service"
import { StreamingResponseHandler } from "../grpc-handler"
import { registerAllMethods } from "./methods"
// Create checkpoints service registry
const checkpointsService = createServiceRegistry("checkpoints")
// Export the method handler types and registration function
export type CheckpointsMethodHandler = ServiceMethodHandler
export type CheckpointsStreamingMethodHandler = StreamingMethodHandler
export const registerMethod = checkpointsService.registerMethod
// Export the request handlers
export const handleCheckpointsServiceRequest = checkpointsService.handleRequest
export const handleCheckpointsServiceStreamingRequest = checkpointsService.handleStreamingRequest
export const isStreamingMethod = checkpointsService.isStreamingMethod
// Register all checkpoints methods
registerAllMethods()
@@ -0,0 +1,14 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
// Import all method implementations
import { registerMethod } from "./index"
import { checkpointDiff } from "./checkpointDiff"
import { checkpointRestore } from "./checkpointRestore"
// Register all checkpoints service methods
export function registerAllMethods(): void {
// Register each method with the registry
registerMethod("checkpointDiff", checkpointDiff)
registerMethod("checkpointRestore", checkpointRestore)
}
+22
View File
@@ -0,0 +1,22 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
import { createServiceRegistry, ServiceMethodHandler, StreamingMethodHandler } from "../grpc-service"
import { StreamingResponseHandler } from "../grpc-handler"
import { registerAllMethods } from "./methods"
// Create file service registry
const fileService = createServiceRegistry("file")
// Export the method handler types and registration function
export type FileMethodHandler = ServiceMethodHandler
export type FileStreamingMethodHandler = StreamingMethodHandler
export const registerMethod = fileService.registerMethod
// Export the request handlers
export const handleFileServiceRequest = fileService.handleRequest
export const handleFileServiceStreamingRequest = fileService.handleStreamingRequest
export const isStreamingMethod = fileService.isStreamingMethod
// Register all file methods
registerAllMethods()
+38
View File
@@ -0,0 +1,38 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
// Import all method implementations
import { registerMethod } from "./index"
import { copyToClipboard } from "./copyToClipboard"
import { createRuleFile } from "./createRuleFile"
import { deleteRuleFile } from "./deleteRuleFile"
import { getRelativePaths } from "./getRelativePaths"
import { openFile } from "./openFile"
import { openImage } from "./openImage"
import { openMention } from "./openMention"
import { refreshRules } from "./refreshRules"
import { searchCommits } from "./searchCommits"
import { searchFiles } from "./searchFiles"
import { selectImages } from "./selectImages"
import { toggleClineRule } from "./toggleClineRule"
import { toggleCursorRule } from "./toggleCursorRule"
import { toggleWindsurfRule } from "./toggleWindsurfRule"
// Register all file service methods
export function registerAllMethods(): void {
// Register each method with the registry
registerMethod("copyToClipboard", copyToClipboard)
registerMethod("createRuleFile", createRuleFile)
registerMethod("deleteRuleFile", deleteRuleFile)
registerMethod("getRelativePaths", getRelativePaths)
registerMethod("openFile", openFile)
registerMethod("openImage", openImage)
registerMethod("openMention", openMention)
registerMethod("refreshRules", refreshRules)
registerMethod("searchCommits", searchCommits)
registerMethod("searchFiles", searchFiles)
registerMethod("selectImages", selectImages)
registerMethod("toggleClineRule", toggleClineRule)
registerMethod("toggleCursorRule", toggleCursorRule)
registerMethod("toggleWindsurfRule", toggleWindsurfRule)
}
+3 -2
View File
@@ -16,14 +16,15 @@ export async function refreshRules(controller: Controller, _request: EmptyReques
try {
const { globalToggles, localToggles } = await refreshClineRulesToggles(controller.context, cwd)
const { cursorLocalToggles, windsurfLocalToggles } = await refreshExternalRulesToggles(controller.context, cwd)
const workflowToggles = await refreshWorkflowToggles(controller.context, cwd)
const { localWorkflowToggles, globalWorkflowToggles } = await refreshWorkflowToggles(controller.context, cwd)
return {
globalClineRulesToggles: { toggles: globalToggles },
localClineRulesToggles: { toggles: localToggles },
localCursorRulesToggles: { toggles: cursorLocalToggles },
localWindsurfRulesToggles: { toggles: windsurfLocalToggles },
workflowToggles: { toggles: workflowToggles },
localWorkflowToggles: { toggles: localWorkflowToggles },
globalWorkflowToggles: { toggles: globalWorkflowToggles },
}
} catch (error) {
console.error("Failed to refresh rules:", error)
@@ -0,0 +1,80 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
import { Controller } from "./index"
import { StreamingResponseHandler } from "./grpc-handler"
import { handleAccountServiceRequest, handleAccountServiceStreamingRequest } from "./account/index"
import { handleBrowserServiceRequest, handleBrowserServiceStreamingRequest } from "./browser/index"
import { handleCheckpointsServiceRequest, handleCheckpointsServiceStreamingRequest } from "./checkpoints/index"
import { handleFileServiceRequest, handleFileServiceStreamingRequest } from "./file/index"
import { handleMcpServiceRequest, handleMcpServiceStreamingRequest } from "./mcp/index"
import { handleStateServiceRequest, handleStateServiceStreamingRequest } from "./state/index"
import { handleTaskServiceRequest, handleTaskServiceStreamingRequest } from "./task/index"
import { handleWebServiceRequest, handleWebServiceStreamingRequest } from "./web/index"
import { handleModelsServiceRequest, handleModelsServiceStreamingRequest } from "./models/index"
import { handleSlashServiceRequest, handleSlashServiceStreamingRequest } from "./slash/index"
import { handleUiServiceRequest, handleUiServiceStreamingRequest } from "./ui/index"
/**
* Configuration for a service handler
*/
export interface ServiceHandlerConfig {
requestHandler: (controller: Controller, method: string, message: any) => Promise<any>
streamingHandler: (
controller: Controller,
method: string,
message: any,
responseStream: StreamingResponseHandler,
requestId?: string,
) => Promise<void>
}
/**
* Map of service names to their handler configurations
*/
export const serviceHandlers: Record<string, ServiceHandlerConfig> = {
"cline.AccountService": {
requestHandler: handleAccountServiceRequest,
streamingHandler: handleAccountServiceStreamingRequest,
},
"cline.BrowserService": {
requestHandler: handleBrowserServiceRequest,
streamingHandler: handleBrowserServiceStreamingRequest,
},
"cline.CheckpointsService": {
requestHandler: handleCheckpointsServiceRequest,
streamingHandler: handleCheckpointsServiceStreamingRequest,
},
"cline.FileService": {
requestHandler: handleFileServiceRequest,
streamingHandler: handleFileServiceStreamingRequest,
},
"cline.McpService": {
requestHandler: handleMcpServiceRequest,
streamingHandler: handleMcpServiceStreamingRequest,
},
"cline.StateService": {
requestHandler: handleStateServiceRequest,
streamingHandler: handleStateServiceStreamingRequest,
},
"cline.TaskService": {
requestHandler: handleTaskServiceRequest,
streamingHandler: handleTaskServiceStreamingRequest,
},
"cline.WebService": {
requestHandler: handleWebServiceRequest,
streamingHandler: handleWebServiceStreamingRequest,
},
"cline.ModelsService": {
requestHandler: handleModelsServiceRequest,
streamingHandler: handleModelsServiceStreamingRequest,
},
"cline.SlashService": {
requestHandler: handleSlashServiceRequest,
streamingHandler: handleSlashServiceStreamingRequest,
},
"cline.UiService": {
requestHandler: handleUiServiceRequest,
streamingHandler: handleUiServiceStreamingRequest,
},
}
+26 -18
View File
@@ -32,7 +32,12 @@ import { fileExistsAtPath } from "@utils/fs"
import { getWorkingState } from "@utils/git"
import { extractCommitMessage } from "@integrations/git/commit-message-generator"
import { getTotalTasksSize } from "@utils/storage"
import { ensureMcpServersDirectoryExists, ensureSettingsDirectoryExists, GlobalFileNames } from "../storage/disk"
import {
ensureMcpServersDirectoryExists,
ensureSettingsDirectoryExists,
GlobalFileNames,
ensureWorkflowsDirectoryExists,
} from "../storage/disk"
import {
getAllExtensionState,
getGlobalState,
@@ -65,7 +70,7 @@ export class Controller {
workspaceTracker: WorkspaceTracker
mcpHub: McpHub
accountService: ClineAccountService
private latestAnnouncementId = "may-16-2025_16:11:00" // update to some unique identifier when we add a new announcement
latestAnnouncementId = "may-22-2025_16:11:00" // update to some unique identifier when we add a new announcement
constructor(
readonly context: vscode.ExtensionContext,
@@ -298,10 +303,6 @@ export class Controller {
text: message.text,
})
break
case "didShowAnnouncement":
await updateGlobalState(this.context, "lastShownAnnouncementId", this.latestAnnouncementId)
await this.postStateToWebview()
break
case "openInBrowser":
if (message.url) {
vscode.env.openExternal(vscode.Uri.parse(message.url))
@@ -362,12 +363,20 @@ export class Controller {
// break
// }
case "toggleWorkflow": {
const { workflowPath, enabled } = message
if (workflowPath && typeof enabled === "boolean") {
const toggles = ((await getWorkspaceState(this.context, "workflowToggles")) as ClineRulesToggles) || {}
toggles[workflowPath] = enabled
await updateWorkspaceState(this.context, "workflowToggles", toggles)
await this.postStateToWebview()
const { workflowPath, enabled, isGlobal } = message
if (workflowPath && typeof enabled === "boolean" && typeof isGlobal === "boolean") {
if (isGlobal) {
const globalWorkflowToggles =
((await getGlobalState(this.context, "globalWorkflowToggles")) as ClineRulesToggles) || {}
globalWorkflowToggles[workflowPath] = enabled
await updateGlobalState(this.context, "globalWorkflowToggles", globalWorkflowToggles)
await this.postStateToWebview()
} else {
const toggles = ((await getWorkspaceState(this.context, "workflowToggles")) as ClineRulesToggles) || {}
toggles[workflowPath] = enabled
await updateWorkspaceState(this.context, "workflowToggles", toggles)
await this.postStateToWebview()
}
}
break
}
@@ -1219,10 +1228,7 @@ export class Controller {
async postStateToWebview() {
const state = await this.getStateToPostToWebview()
// For testing: Bypass gRPC stream and send state directly
console.log("[Controller Test Revert] Posting full state via direct 'state' message.")
await this.postMessageToWebview({ type: "state", state: state })
// await sendStateUpdate(state) // Original line for the GrPC stream
await sendStateUpdate(state)
}
async getStateToPostToWebview(): Promise<ExtensionState> {
@@ -1240,6 +1246,7 @@ export class Controller {
planActSeparateModelsSetting,
enableCheckpointsSetting,
globalClineRulesToggles,
globalWorkflowToggles,
shellIntegrationTimeout,
isNewUser,
} = await getAllExtensionState(this.context)
@@ -1253,7 +1260,7 @@ export class Controller {
const localCursorRulesToggles =
((await getWorkspaceState(this.context, "localCursorRulesToggles")) as ClineRulesToggles) || {}
const workflowToggles = ((await getWorkspaceState(this.context, "workflowToggles")) as ClineRulesToggles) || {}
const localWorkflowToggles = ((await getWorkspaceState(this.context, "workflowToggles")) as ClineRulesToggles) || {}
return {
version: this.context.extension?.packageJSON?.version ?? "",
@@ -1282,7 +1289,8 @@ export class Controller {
localClineRulesToggles: localClineRulesToggles || {},
localWindsurfRulesToggles: localWindsurfRulesToggles || {},
localCursorRulesToggles: localCursorRulesToggles || {},
workflowToggles: workflowToggles || {},
localWorkflowToggles: localWorkflowToggles || {},
globalWorkflowToggles: globalWorkflowToggles || {},
shellIntegrationTimeout,
isNewUser,
}
+22
View File
@@ -0,0 +1,22 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
import { createServiceRegistry, ServiceMethodHandler, StreamingMethodHandler } from "../grpc-service"
import { StreamingResponseHandler } from "../grpc-handler"
import { registerAllMethods } from "./methods"
// Create mcp service registry
const mcpService = createServiceRegistry("mcp")
// Export the method handler types and registration function
export type McpMethodHandler = ServiceMethodHandler
export type McpStreamingMethodHandler = StreamingMethodHandler
export const registerMethod = mcpService.registerMethod
// Export the request handlers
export const handleMcpServiceRequest = mcpService.handleRequest
export const handleMcpServiceStreamingRequest = mcpService.handleStreamingRequest
export const isStreamingMethod = mcpService.isStreamingMethod
// Register all mcp methods
registerAllMethods()
+26
View File
@@ -0,0 +1,26 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
// Import all method implementations
import { registerMethod } from "./index"
import { addRemoteMcpServer } from "./addRemoteMcpServer"
import { deleteMcpServer } from "./deleteMcpServer"
import { downloadMcp } from "./downloadMcp"
import { refreshMcpMarketplace } from "./refreshMcpMarketplace"
import { restartMcpServer } from "./restartMcpServer"
import { toggleMcpServer } from "./toggleMcpServer"
import { toggleToolAutoApprove } from "./toggleToolAutoApprove"
import { updateMcpTimeout } from "./updateMcpTimeout"
// Register all mcp service methods
export function registerAllMethods(): void {
// Register each method with the registry
registerMethod("addRemoteMcpServer", addRemoteMcpServer)
registerMethod("deleteMcpServer", deleteMcpServer)
registerMethod("downloadMcp", downloadMcp)
registerMethod("refreshMcpMarketplace", refreshMcpMarketplace)
registerMethod("restartMcpServer", restartMcpServer)
registerMethod("toggleMcpServer", toggleMcpServer)
registerMethod("toggleToolAutoApprove", toggleToolAutoApprove)
registerMethod("updateMcpTimeout", updateMcpTimeout)
}
+22
View File
@@ -0,0 +1,22 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
import { createServiceRegistry, ServiceMethodHandler, StreamingMethodHandler } from "../grpc-service"
import { StreamingResponseHandler } from "../grpc-handler"
import { registerAllMethods } from "./methods"
// Create models service registry
const modelsService = createServiceRegistry("models")
// Export the method handler types and registration function
export type ModelsMethodHandler = ServiceMethodHandler
export type ModelsStreamingMethodHandler = StreamingMethodHandler
export const registerMethod = modelsService.registerMethod
// Export the request handlers
export const handleModelsServiceRequest = modelsService.handleRequest
export const handleModelsServiceStreamingRequest = modelsService.handleStreamingRequest
export const isStreamingMethod = modelsService.isStreamingMethod
// Register all models methods
registerAllMethods()
+22
View File
@@ -0,0 +1,22 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
// Import all method implementations
import { registerMethod } from "./index"
import { getLmStudioModels } from "./getLmStudioModels"
import { getOllamaModels } from "./getOllamaModels"
import { getVsCodeLmModels } from "./getVsCodeLmModels"
import { refreshOpenAiModels } from "./refreshOpenAiModels"
import { refreshOpenRouterModels } from "./refreshOpenRouterModels"
import { refreshRequestyModels } from "./refreshRequestyModels"
// Register all models service methods
export function registerAllMethods(): void {
// Register each method with the registry
registerMethod("getLmStudioModels", getLmStudioModels)
registerMethod("getOllamaModels", getOllamaModels)
registerMethod("getVsCodeLmModels", getVsCodeLmModels)
registerMethod("refreshOpenAiModels", refreshOpenAiModels)
registerMethod("refreshOpenRouterModels", refreshOpenRouterModels)
registerMethod("refreshRequestyModels", refreshRequestyModels)
}
@@ -43,6 +43,8 @@ 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":
+22
View File
@@ -0,0 +1,22 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
import { createServiceRegistry, ServiceMethodHandler, StreamingMethodHandler } from "../grpc-service"
import { StreamingResponseHandler } from "../grpc-handler"
import { registerAllMethods } from "./methods"
// Create slash service registry
const slashService = createServiceRegistry("slash")
// Export the method handler types and registration function
export type SlashMethodHandler = ServiceMethodHandler
export type SlashStreamingMethodHandler = StreamingMethodHandler
export const registerMethod = slashService.registerMethod
// Export the request handlers
export const handleSlashServiceRequest = slashService.handleRequest
export const handleSlashServiceStreamingRequest = slashService.handleStreamingRequest
export const isStreamingMethod = slashService.isStreamingMethod
// Register all slash methods
registerAllMethods()
+14
View File
@@ -0,0 +1,14 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
// Import all method implementations
import { registerMethod } from "./index"
import { condense } from "./condense"
import { reportBug } from "./reportBug"
// Register all slash service methods
export function registerAllMethods(): void {
// Register each method with the registry
registerMethod("condense", condense)
registerMethod("reportBug", reportBug)
}
+22
View File
@@ -0,0 +1,22 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
import { createServiceRegistry, ServiceMethodHandler, StreamingMethodHandler } from "../grpc-service"
import { StreamingResponseHandler } from "../grpc-handler"
import { registerAllMethods } from "./methods"
// Create state service registry
const stateService = createServiceRegistry("state")
// Export the method handler types and registration function
export type StateMethodHandler = ServiceMethodHandler
export type StateStreamingMethodHandler = StreamingMethodHandler
export const registerMethod = stateService.registerMethod
// Export the request handlers
export const handleStateServiceRequest = stateService.handleRequest
export const handleStateServiceStreamingRequest = stateService.handleStreamingRequest
export const isStreamingMethod = stateService.isStreamingMethod
// Register all state methods
registerAllMethods()
+27
View File
@@ -0,0 +1,27 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
// Import all method implementations
import { registerMethod } from "./index"
import { getLatestState } from "./getLatestState"
import { resetState } from "./resetState"
import { subscribeToState } from "./subscribeToState"
import { toggleFavoriteModel } from "./toggleFavoriteModel"
import { togglePlanActMode } from "./togglePlanActMode"
import { updateAutoApprovalSettings } from "./updateAutoApprovalSettings"
import { updateTerminalConnectionTimeout } from "./updateTerminalConnectionTimeout"
// Streaming methods for this service
export const streamingMethods = ["subscribeToState"]
// Register all state service methods
export function registerAllMethods(): void {
// Register each method with the registry
registerMethod("getLatestState", getLatestState)
registerMethod("resetState", resetState)
registerMethod("subscribeToState", subscribeToState, { isStreaming: true })
registerMethod("toggleFavoriteModel", toggleFavoriteModel)
registerMethod("togglePlanActMode", togglePlanActMode)
registerMethod("updateAutoApprovalSettings", updateAutoApprovalSettings)
registerMethod("updateTerminalConnectionTimeout", updateTerminalConnectionTimeout)
}
+22
View File
@@ -0,0 +1,22 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
import { createServiceRegistry, ServiceMethodHandler, StreamingMethodHandler } from "../grpc-service"
import { StreamingResponseHandler } from "../grpc-handler"
import { registerAllMethods } from "./methods"
// Create task service registry
const taskService = createServiceRegistry("task")
// Export the method handler types and registration function
export type TaskMethodHandler = ServiceMethodHandler
export type TaskStreamingMethodHandler = StreamingMethodHandler
export const registerMethod = taskService.registerMethod
// Export the request handlers
export const handleTaskServiceRequest = taskService.handleRequest
export const handleTaskServiceStreamingRequest = taskService.handleStreamingRequest
export const isStreamingMethod = taskService.isStreamingMethod
// Register all task methods
registerAllMethods()
+34
View File
@@ -0,0 +1,34 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
// Import all method implementations
import { registerMethod } from "./index"
import { askResponse } from "./askResponse"
import { cancelTask } from "./cancelTask"
import { clearTask } from "./clearTask"
import { deleteNonFavoritedTasks } from "./deleteNonFavoritedTasks"
import { deleteTasksWithIds } from "./deleteTasksWithIds"
import { exportTaskWithId } from "./exportTaskWithId"
import { getTaskHistory } from "./getTaskHistory"
import { newTask } from "./newTask"
import { showTaskWithId } from "./showTaskWithId"
import { taskCompletionViewChanges } from "./taskCompletionViewChanges"
import { taskFeedback } from "./taskFeedback"
import { toggleTaskFavorite } from "./toggleTaskFavorite"
// Register all task service methods
export function registerAllMethods(): void {
// Register each method with the registry
registerMethod("askResponse", askResponse)
registerMethod("cancelTask", cancelTask)
registerMethod("clearTask", clearTask)
registerMethod("deleteNonFavoritedTasks", deleteNonFavoritedTasks)
registerMethod("deleteTasksWithIds", deleteTasksWithIds)
registerMethod("exportTaskWithId", exportTaskWithId)
registerMethod("getTaskHistory", getTaskHistory)
registerMethod("newTask", newTask)
registerMethod("showTaskWithId", showTaskWithId)
registerMethod("taskCompletionViewChanges", taskCompletionViewChanges)
registerMethod("taskFeedback", taskFeedback)
registerMethod("toggleTaskFavorite", toggleTaskFavorite)
}
+1 -1
View File
@@ -19,4 +19,4 @@ export const handleUiServiceStreamingRequest = uiService.handleStreamingRequest
export const isStreamingMethod = uiService.isStreamingMethod
// Register all ui methods
registerAllMethods()
registerAllMethods()
+3 -1
View File
@@ -3,10 +3,12 @@
// Import all method implementations
import { registerMethod } from "./index"
import { onDidShowAnnouncement } from "./onDidShowAnnouncement"
import { scrollToSettings } from "./scrollToSettings"
// Register all ui service methods
export function registerAllMethods(): void {
// Register each method with the registry
registerMethod("onDidShowAnnouncement", onDidShowAnnouncement)
registerMethod("scrollToSettings", scrollToSettings)
}
}
@@ -0,0 +1,29 @@
import type { EmptyRequest, Boolean } from "../../../shared/proto/common"
import type { Controller } from "../index"
import { getGlobalState, updateGlobalState } from "../../storage/state"
/**
* Marks the current announcement as shown and returns the updated shouldShowAnnouncement value
*
* @param controller The controller instance
* @param _request The empty request (not used)
* @returns Boolean indicating whether an announcement should be shown
*/
export async function onDidShowAnnouncement(controller: Controller, _request: EmptyRequest): Promise<Boolean> {
try {
// Update the lastShownAnnouncementId to the current latestAnnouncementId
await updateGlobalState(controller.context, "lastShownAnnouncementId", controller.latestAnnouncementId)
// Get the updated lastShownAnnouncementId value after the update
const lastShownAnnouncementId = await getGlobalState(controller.context, "lastShownAnnouncementId")
// Calculate the new shouldShowAnnouncement value
// This replicates the same logic used in getStateToPostToWebview()
const shouldShowAnnouncement = lastShownAnnouncementId !== controller.latestAnnouncementId
return { value: shouldShowAnnouncement }
} catch (error) {
console.error("Failed to acknowledge announcement:", error)
return { value: false }
}
}
+22
View File
@@ -0,0 +1,22 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
import { createServiceRegistry, ServiceMethodHandler, StreamingMethodHandler } from "../grpc-service"
import { StreamingResponseHandler } from "../grpc-handler"
import { registerAllMethods } from "./methods"
// Create web service registry
const webService = createServiceRegistry("web")
// Export the method handler types and registration function
export type WebMethodHandler = ServiceMethodHandler
export type WebStreamingMethodHandler = StreamingMethodHandler
export const registerMethod = webService.registerMethod
// Export the request handlers
export const handleWebServiceRequest = webService.handleRequest
export const handleWebServiceStreamingRequest = webService.handleStreamingRequest
export const isStreamingMethod = webService.isStreamingMethod
// Register all web methods
registerAllMethods()
+14
View File
@@ -0,0 +1,14 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
// Import all method implementations
import { registerMethod } from "./index"
import { checkIsImageUrl } from "./checkIsImageUrl"
import { fetchOpenGraphData } from "./fetchOpenGraphData"
// Register all web service methods
export function registerAllMethods(): void {
// Register each method with the registry
registerMethod("checkIsImageUrl", checkIsImageUrl)
registerMethod("fetchOpenGraphData", fetchOpenGraphData)
}
+16 -4
View File
@@ -8,7 +8,8 @@ import fs from "fs/promises"
*/
export async function parseSlashCommands(
text: string,
workflowToggles: ClineRulesToggles,
localWorkflowToggles: ClineRulesToggles,
globalWorkflowToggles: ClineRulesToggles,
): Promise<{ processedText: string; needsClinerulesFileCheck: boolean }> {
const SUPPORTED_DEFAULT_COMMANDS = ["newtask", "smol", "compact", "newrule", "reportbug"]
@@ -58,18 +59,29 @@ export async function parseSlashCommands(
return { processedText: processedText, needsClinerulesFileCheck: commandName === "newrule" ? true : false }
}
// in practice we want to minimize this work, so we only do it if theres a possible match
const enabledWorkflows = Object.entries(workflowToggles)
const globalWorkflows = Object.entries(globalWorkflowToggles)
.filter(([_, enabled]) => enabled)
.map(([filePath, _]) => {
const fileName = filePath.replace(/^.*[/\\]/, "")
return {
fullPath: filePath,
fileName: fileName,
}
})
const localWorkflows = Object.entries(localWorkflowToggles)
.filter(([_, enabled]) => enabled)
.map(([filePath, _]) => {
const fileName = filePath.replace(/^.*[/\\]/, "")
return {
fullPath: filePath,
fileName: fileName,
}
})
// local workflows have precedence over global workflows
const enabledWorkflows = [...localWorkflows, ...globalWorkflows]
// Then check if the command matches any enabled workflow filename
const matchingWorkflow = enabledWorkflows.find((workflow) => workflow.fileName === commandName)
+11
View File
@@ -76,6 +76,17 @@ export async function ensureRulesDirectoryExists(): Promise<string> {
return clineRulesDir
}
export async function ensureWorkflowsDirectoryExists(): Promise<string> {
const userDocumentsPath = await getDocumentsPath()
const clineWorkflowsDir = path.join(userDocumentsPath, "Cline", "Workflows")
try {
await fs.mkdir(clineWorkflowsDir, { recursive: true })
} catch (error) {
return path.join(os.homedir(), "Documents", "Cline", "Workflows") // in case creating a directory in documents fails for whatever reason (e.g. permissions) - this is fine because we will fail gracefully with a path that does not exist
}
return clineWorkflowsDir
}
export async function ensureMcpServersDirectoryExists(): Promise<string> {
const userDocumentsPath = await getDocumentsPath()
const mcpServersDir = path.join(userDocumentsPath, "Cline", "MCP")
+1
View File
@@ -55,6 +55,7 @@ export type GlobalStateKey =
| "openRouterProviderSorting"
| "autoApprovalSettings"
| "globalClineRulesToggles"
| "globalWorkflowToggles"
| "browserSettings"
| "chatSettings"
| "vsCodeLmModelSelector"
+3
View File
@@ -163,6 +163,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
shellIntegrationTimeout,
enableCheckpointsSettingRaw,
mcpMarketplaceEnabledRaw,
globalWorkflowToggles,
] = await Promise.all([
getGlobalState(context, "isNewUser") as Promise<boolean | undefined>,
getGlobalState(context, "apiProvider") as Promise<ApiProvider | undefined>,
@@ -251,6 +252,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
getGlobalState(context, "shellIntegrationTimeout") as Promise<number | undefined>,
getGlobalState(context, "enableCheckpointsSetting") as Promise<boolean | undefined>,
getGlobalState(context, "mcpMarketplaceEnabled") as Promise<boolean | undefined>,
getGlobalState(context, "globalWorkflowToggles") as Promise<ClineRulesToggles | undefined>,
fetch,
])
@@ -385,6 +387,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
planActSeparateModelsSetting,
enableCheckpointsSetting: enableCheckpointsSetting,
shellIntegrationTimeout: shellIntegrationTimeout || 4000,
globalWorkflowToggles: globalWorkflowToggles || {},
}
}
+3 -2
View File
@@ -4117,7 +4117,7 @@ export class Task {
// Track if we need to check clinerulesFile
let needsClinerulesFileCheck = false
const workflowToggles = await refreshWorkflowToggles(this.getContext(), cwd)
const { localWorkflowToggles, globalWorkflowToggles } = await refreshWorkflowToggles(this.getContext(), cwd)
const processUserContent = async () => {
// This is a temporary solution to dynamically load context mentions from tool results. It checks for the presence of tags that indicate that the tool was rejected and feedback was provided (see formatToolDeniedFeedback, attemptCompletion, executeCommand, and consecutiveMistakeCount >= 3) or "<answer>" (see askFollowupQuestion), we place all user generated content in these tags so they can effectively be used as markers for when we should parse mentions). However if we allow multiple tools responses in the future, we will need to parse mentions specifically within the user content tags.
@@ -4143,7 +4143,8 @@ export class Task {
// when parsing slash commands, we still want to allow the user to provide their desired context
const { processedText, needsClinerulesFileCheck: needsCheck } = await parseSlashCommands(
parsedText,
workflowToggles,
localWorkflowToggles,
globalWorkflowToggles,
)
if (needsCheck) {
+2 -1
View File
@@ -140,7 +140,8 @@ export interface ExtensionState {
vscMachineId: string
globalClineRulesToggles: ClineRulesToggles
localClineRulesToggles: ClineRulesToggles
workflowToggles: ClineRulesToggles
localWorkflowToggles: ClineRulesToggles
globalWorkflowToggles: ClineRulesToggles
localCursorRulesToggles: ClineRulesToggles
localWindsurfRulesToggles: ClineRulesToggles
}
-1
View File
@@ -13,7 +13,6 @@ export interface WebviewMessage {
| "newTask"
| "condense"
| "reportBug"
| "didShowAnnouncement"
| "openInBrowser"
| "showChatView"
| "openMcpSettings"
+66 -5
View File
@@ -138,8 +138,29 @@ export interface OpenAiCompatibleModelInfo extends ModelInfo {
// Anthropic
// https://docs.anthropic.com/en/docs/about-claude/models // prices updated 2025-01-02
export type AnthropicModelId = keyof typeof anthropicModels
export const anthropicDefaultModelId: AnthropicModelId = "claude-3-7-sonnet-20250219"
export const anthropicDefaultModelId: AnthropicModelId = "claude-sonnet-4-20250514"
export const anthropicModels = {
"claude-sonnet-4-20250514": {
maxTokens: 8192,
contextWindow: 200_000,
supportsImages: true,
supportsPromptCache: true,
inputPrice: 3.0,
outputPrice: 15.0,
cacheWritesPrice: 3.75,
cacheReadsPrice: 0.3,
},
"claude-opus-4-20250514": {
maxTokens: 8192,
contextWindow: 200_000,
supportsImages: true,
supportsPromptCache: true,
inputPrice: 15.0,
outputPrice: 75.0,
cacheWritesPrice: 18.75,
cacheReadsPrice: 1.5,
},
"claude-3-7-sonnet-20250219": {
maxTokens: 8192,
contextWindow: 200_000,
@@ -197,8 +218,28 @@ export const anthropicModels = {
// AWS Bedrock
// https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html
export type BedrockModelId = keyof typeof bedrockModels
export const bedrockDefaultModelId: BedrockModelId = "anthropic.claude-3-7-sonnet-20250219-v1:0"
export const bedrockDefaultModelId: BedrockModelId = "anthropic.claude-sonnet-4-20250514-v1:0"
export const bedrockModels = {
"anthropic.claude-sonnet-4-20250514-v1:0": {
maxTokens: 8192,
contextWindow: 200_000,
supportsImages: true,
supportsPromptCache: true,
inputPrice: 3.0,
outputPrice: 15.0,
cacheWritesPrice: 3.75,
cacheReadsPrice: 0.3,
},
"anthropic.claude-opus-4-20250514-v1:0": {
maxTokens: 8192,
contextWindow: 200_000,
supportsImages: true,
supportsPromptCache: true,
inputPrice: 15.0,
outputPrice: 75.0,
cacheWritesPrice: 18.75,
cacheReadsPrice: 1.5,
},
"amazon.nova-premier-v1:0": {
maxTokens: 10_000,
contextWindow: 1_000_000,
@@ -317,7 +358,7 @@ export const bedrockModels = {
// OpenRouter
// https://openrouter.ai/models?order=newest&supported_parameters=tools
export const openRouterDefaultModelId = "anthropic/claude-3.7-sonnet" // will always exist in openRouterModels
export const openRouterDefaultModelId = "anthropic/claude-sonnet-4" // will always exist in openRouterModels
export const openRouterDefaultModelInfo: ModelInfo = {
maxTokens: 8192,
contextWindow: 200_000,
@@ -329,14 +370,34 @@ export const openRouterDefaultModelInfo: ModelInfo = {
cacheWritesPrice: 3.75,
cacheReadsPrice: 0.3,
description:
"Claude 3.7 Sonnet is an advanced large language model with improved reasoning, coding, and problem-solving capabilities. It introduces a hybrid reasoning approach, allowing users to choose between rapid responses and extended, step-by-step processing for complex tasks. The model demonstrates notable improvements in coding, particularly in front-end development and full-stack updates, and excels in agentic workflows, where it can autonomously navigate multi-step processes. \n\nClaude 3.7 Sonnet maintains performance parity with its predecessor in standard mode while offering an extended reasoning mode for enhanced accuracy in math, coding, and instruction-following tasks.\n\nRead more at the [blog post here](https://www.anthropic.com/news/claude-3-7-sonnet)",
"Claude 4 Sonnet is an advanced large language model with improved reasoning, coding, and problem-solving capabilities. It introduces a hybrid reasoning approach, allowing users to choose between rapid responses and extended, step-by-step processing for complex tasks. The model demonstrates notable improvements in coding, particularly in front-end development and full-stack updates, and excels in agentic workflows, where it can autonomously navigate multi-step processes. \n\nClaude 4 Sonnet maintains performance parity with its predecessor in standard mode while offering an extended reasoning mode for enhanced accuracy in math, coding, and instruction-following tasks.\n\nRead more at the [blog post here](https://www.anthropic.com/news/claude-4)",
}
// Vertex AI
// https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-claude
// https://cloud.google.com/vertex-ai/generative-ai/pricing#partner-models
export type VertexModelId = keyof typeof vertexModels
export const vertexDefaultModelId: VertexModelId = "claude-3-7-sonnet@20250219"
export const vertexDefaultModelId: VertexModelId = "claude-sonnet-4@20250514"
export const vertexModels = {
"claude-sonnet-4@20250514": {
maxTokens: 8192,
contextWindow: 200_000,
supportsImages: true,
supportsPromptCache: true,
inputPrice: 3.0,
outputPrice: 15.0,
cacheWritesPrice: 3.75,
cacheReadsPrice: 0.3,
},
"claude-opus-4@20250514": {
maxTokens: 8192,
contextWindow: 200_000,
supportsImages: true,
supportsPromptCache: true,
inputPrice: 15.0,
outputPrice: 75.0,
cacheWritesPrice: 18.75,
cacheReadsPrice: 1.5,
},
"claude-3-7-sonnet@20250219": {
maxTokens: 8192,
contextWindow: 200_000,
+44
View File
@@ -0,0 +1,44 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.0
// protoc v3.19.1
// source: account.proto
/* eslint-disable */
import { Empty, EmptyRequest, String } from "./common"
export const protobufPackage = "cline"
/** Service for account-related operations */
export type AccountServiceDefinition = typeof AccountServiceDefinition
export const AccountServiceDefinition = {
name: "AccountService",
fullName: "cline.AccountService",
methods: {
/**
* Handles the user clicking the login link in the UI.
* Generates a secure nonce for state validation, stores it in secrets,
* and opens the authentication URL in the external browser.
*/
accountLoginClicked: {
name: "accountLoginClicked",
requestType: EmptyRequest,
requestStream: false,
responseType: String,
responseStream: false,
options: {},
},
/**
* Handles the user clicking the logout button in the UI.
* Clears API keys and user state.
*/
accountLogoutClicked: {
name: "accountLogoutClicked",
requestType: EmptyRequest,
requestStream: false,
responseType: Empty,
responseStream: false,
options: {},
},
},
} as const
+756
View File
@@ -0,0 +1,756 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.0
// protoc v3.19.1
// source: browser.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"
import { Boolean, EmptyRequest, Metadata, String, StringRequest } from "./common"
export const protobufPackage = "cline"
export interface BrowserConnectionInfo {
isConnected: boolean
isRemote: boolean
host?: string | undefined
}
export interface BrowserConnection {
success: boolean
message: string
endpoint?: string | undefined
}
export interface ChromePath {
path: string
isBundled: boolean
}
export interface Viewport {
width: number
height: number
}
export interface BrowserSettings {
viewport?: Viewport | undefined
remoteBrowserHost?: string | undefined
remoteBrowserEnabled?: boolean | undefined
chromeExecutablePath?: string | undefined
disableToolUse?: boolean | undefined
}
export interface UpdateBrowserSettingsRequest {
metadata?: Metadata | undefined
viewport?: Viewport | undefined
remoteBrowserHost?: string | undefined
remoteBrowserEnabled?: boolean | undefined
chromeExecutablePath?: string | undefined
disableToolUse?: boolean | undefined
}
function createBaseBrowserConnectionInfo(): BrowserConnectionInfo {
return { isConnected: false, isRemote: false, host: undefined }
}
export const BrowserConnectionInfo: MessageFns<BrowserConnectionInfo> = {
encode(message: BrowserConnectionInfo, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.isConnected !== false) {
writer.uint32(8).bool(message.isConnected)
}
if (message.isRemote !== false) {
writer.uint32(16).bool(message.isRemote)
}
if (message.host !== undefined) {
writer.uint32(26).string(message.host)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): BrowserConnectionInfo {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseBrowserConnectionInfo()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break
}
message.isConnected = reader.bool()
continue
}
case 2: {
if (tag !== 16) {
break
}
message.isRemote = reader.bool()
continue
}
case 3: {
if (tag !== 26) {
break
}
message.host = reader.string()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): BrowserConnectionInfo {
return {
isConnected: isSet(object.isConnected) ? globalThis.Boolean(object.isConnected) : false,
isRemote: isSet(object.isRemote) ? globalThis.Boolean(object.isRemote) : false,
host: isSet(object.host) ? globalThis.String(object.host) : undefined,
}
},
toJSON(message: BrowserConnectionInfo): unknown {
const obj: any = {}
if (message.isConnected !== false) {
obj.isConnected = message.isConnected
}
if (message.isRemote !== false) {
obj.isRemote = message.isRemote
}
if (message.host !== undefined) {
obj.host = message.host
}
return obj
},
create<I extends Exact<DeepPartial<BrowserConnectionInfo>, I>>(base?: I): BrowserConnectionInfo {
return BrowserConnectionInfo.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<BrowserConnectionInfo>, I>>(object: I): BrowserConnectionInfo {
const message = createBaseBrowserConnectionInfo()
message.isConnected = object.isConnected ?? false
message.isRemote = object.isRemote ?? false
message.host = object.host ?? undefined
return message
},
}
function createBaseBrowserConnection(): BrowserConnection {
return { success: false, message: "", endpoint: undefined }
}
export const BrowserConnection: MessageFns<BrowserConnection> = {
encode(message: BrowserConnection, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.success !== false) {
writer.uint32(8).bool(message.success)
}
if (message.message !== "") {
writer.uint32(18).string(message.message)
}
if (message.endpoint !== undefined) {
writer.uint32(26).string(message.endpoint)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): BrowserConnection {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseBrowserConnection()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break
}
message.success = reader.bool()
continue
}
case 2: {
if (tag !== 18) {
break
}
message.message = reader.string()
continue
}
case 3: {
if (tag !== 26) {
break
}
message.endpoint = reader.string()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): BrowserConnection {
return {
success: isSet(object.success) ? globalThis.Boolean(object.success) : false,
message: isSet(object.message) ? globalThis.String(object.message) : "",
endpoint: isSet(object.endpoint) ? globalThis.String(object.endpoint) : undefined,
}
},
toJSON(message: BrowserConnection): unknown {
const obj: any = {}
if (message.success !== false) {
obj.success = message.success
}
if (message.message !== "") {
obj.message = message.message
}
if (message.endpoint !== undefined) {
obj.endpoint = message.endpoint
}
return obj
},
create<I extends Exact<DeepPartial<BrowserConnection>, I>>(base?: I): BrowserConnection {
return BrowserConnection.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<BrowserConnection>, I>>(object: I): BrowserConnection {
const message = createBaseBrowserConnection()
message.success = object.success ?? false
message.message = object.message ?? ""
message.endpoint = object.endpoint ?? undefined
return message
},
}
function createBaseChromePath(): ChromePath {
return { path: "", isBundled: false }
}
export const ChromePath: MessageFns<ChromePath> = {
encode(message: ChromePath, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.path !== "") {
writer.uint32(10).string(message.path)
}
if (message.isBundled !== false) {
writer.uint32(16).bool(message.isBundled)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): ChromePath {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseChromePath()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.path = reader.string()
continue
}
case 2: {
if (tag !== 16) {
break
}
message.isBundled = reader.bool()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): ChromePath {
return {
path: isSet(object.path) ? globalThis.String(object.path) : "",
isBundled: isSet(object.isBundled) ? globalThis.Boolean(object.isBundled) : false,
}
},
toJSON(message: ChromePath): unknown {
const obj: any = {}
if (message.path !== "") {
obj.path = message.path
}
if (message.isBundled !== false) {
obj.isBundled = message.isBundled
}
return obj
},
create<I extends Exact<DeepPartial<ChromePath>, I>>(base?: I): ChromePath {
return ChromePath.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<ChromePath>, I>>(object: I): ChromePath {
const message = createBaseChromePath()
message.path = object.path ?? ""
message.isBundled = object.isBundled ?? false
return message
},
}
function createBaseViewport(): Viewport {
return { width: 0, height: 0 }
}
export const Viewport: MessageFns<Viewport> = {
encode(message: Viewport, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.width !== 0) {
writer.uint32(8).int32(message.width)
}
if (message.height !== 0) {
writer.uint32(16).int32(message.height)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): Viewport {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseViewport()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break
}
message.width = reader.int32()
continue
}
case 2: {
if (tag !== 16) {
break
}
message.height = reader.int32()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): Viewport {
return {
width: isSet(object.width) ? globalThis.Number(object.width) : 0,
height: isSet(object.height) ? globalThis.Number(object.height) : 0,
}
},
toJSON(message: Viewport): unknown {
const obj: any = {}
if (message.width !== 0) {
obj.width = Math.round(message.width)
}
if (message.height !== 0) {
obj.height = Math.round(message.height)
}
return obj
},
create<I extends Exact<DeepPartial<Viewport>, I>>(base?: I): Viewport {
return Viewport.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<Viewport>, I>>(object: I): Viewport {
const message = createBaseViewport()
message.width = object.width ?? 0
message.height = object.height ?? 0
return message
},
}
function createBaseBrowserSettings(): BrowserSettings {
return {
viewport: undefined,
remoteBrowserHost: undefined,
remoteBrowserEnabled: undefined,
chromeExecutablePath: undefined,
disableToolUse: undefined,
}
}
export const BrowserSettings: MessageFns<BrowserSettings> = {
encode(message: BrowserSettings, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.viewport !== undefined) {
Viewport.encode(message.viewport, writer.uint32(10).fork()).join()
}
if (message.remoteBrowserHost !== undefined) {
writer.uint32(18).string(message.remoteBrowserHost)
}
if (message.remoteBrowserEnabled !== undefined) {
writer.uint32(24).bool(message.remoteBrowserEnabled)
}
if (message.chromeExecutablePath !== undefined) {
writer.uint32(34).string(message.chromeExecutablePath)
}
if (message.disableToolUse !== undefined) {
writer.uint32(40).bool(message.disableToolUse)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): BrowserSettings {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseBrowserSettings()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.viewport = Viewport.decode(reader, reader.uint32())
continue
}
case 2: {
if (tag !== 18) {
break
}
message.remoteBrowserHost = reader.string()
continue
}
case 3: {
if (tag !== 24) {
break
}
message.remoteBrowserEnabled = reader.bool()
continue
}
case 4: {
if (tag !== 34) {
break
}
message.chromeExecutablePath = reader.string()
continue
}
case 5: {
if (tag !== 40) {
break
}
message.disableToolUse = reader.bool()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): BrowserSettings {
return {
viewport: isSet(object.viewport) ? Viewport.fromJSON(object.viewport) : undefined,
remoteBrowserHost: isSet(object.remoteBrowserHost) ? globalThis.String(object.remoteBrowserHost) : undefined,
remoteBrowserEnabled: isSet(object.remoteBrowserEnabled)
? globalThis.Boolean(object.remoteBrowserEnabled)
: undefined,
chromeExecutablePath: isSet(object.chromeExecutablePath) ? globalThis.String(object.chromeExecutablePath) : undefined,
disableToolUse: isSet(object.disableToolUse) ? globalThis.Boolean(object.disableToolUse) : undefined,
}
},
toJSON(message: BrowserSettings): unknown {
const obj: any = {}
if (message.viewport !== undefined) {
obj.viewport = Viewport.toJSON(message.viewport)
}
if (message.remoteBrowserHost !== undefined) {
obj.remoteBrowserHost = message.remoteBrowserHost
}
if (message.remoteBrowserEnabled !== undefined) {
obj.remoteBrowserEnabled = message.remoteBrowserEnabled
}
if (message.chromeExecutablePath !== undefined) {
obj.chromeExecutablePath = message.chromeExecutablePath
}
if (message.disableToolUse !== undefined) {
obj.disableToolUse = message.disableToolUse
}
return obj
},
create<I extends Exact<DeepPartial<BrowserSettings>, I>>(base?: I): BrowserSettings {
return BrowserSettings.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<BrowserSettings>, I>>(object: I): BrowserSettings {
const message = createBaseBrowserSettings()
message.viewport =
object.viewport !== undefined && object.viewport !== null ? Viewport.fromPartial(object.viewport) : undefined
message.remoteBrowserHost = object.remoteBrowserHost ?? undefined
message.remoteBrowserEnabled = object.remoteBrowserEnabled ?? undefined
message.chromeExecutablePath = object.chromeExecutablePath ?? undefined
message.disableToolUse = object.disableToolUse ?? undefined
return message
},
}
function createBaseUpdateBrowserSettingsRequest(): UpdateBrowserSettingsRequest {
return {
metadata: undefined,
viewport: undefined,
remoteBrowserHost: undefined,
remoteBrowserEnabled: undefined,
chromeExecutablePath: undefined,
disableToolUse: undefined,
}
}
export const UpdateBrowserSettingsRequest: MessageFns<UpdateBrowserSettingsRequest> = {
encode(message: UpdateBrowserSettingsRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.metadata !== undefined) {
Metadata.encode(message.metadata, writer.uint32(10).fork()).join()
}
if (message.viewport !== undefined) {
Viewport.encode(message.viewport, writer.uint32(18).fork()).join()
}
if (message.remoteBrowserHost !== undefined) {
writer.uint32(26).string(message.remoteBrowserHost)
}
if (message.remoteBrowserEnabled !== undefined) {
writer.uint32(32).bool(message.remoteBrowserEnabled)
}
if (message.chromeExecutablePath !== undefined) {
writer.uint32(42).string(message.chromeExecutablePath)
}
if (message.disableToolUse !== undefined) {
writer.uint32(48).bool(message.disableToolUse)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): UpdateBrowserSettingsRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseUpdateBrowserSettingsRequest()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.metadata = Metadata.decode(reader, reader.uint32())
continue
}
case 2: {
if (tag !== 18) {
break
}
message.viewport = Viewport.decode(reader, reader.uint32())
continue
}
case 3: {
if (tag !== 26) {
break
}
message.remoteBrowserHost = reader.string()
continue
}
case 4: {
if (tag !== 32) {
break
}
message.remoteBrowserEnabled = reader.bool()
continue
}
case 5: {
if (tag !== 42) {
break
}
message.chromeExecutablePath = reader.string()
continue
}
case 6: {
if (tag !== 48) {
break
}
message.disableToolUse = reader.bool()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): UpdateBrowserSettingsRequest {
return {
metadata: isSet(object.metadata) ? Metadata.fromJSON(object.metadata) : undefined,
viewport: isSet(object.viewport) ? Viewport.fromJSON(object.viewport) : undefined,
remoteBrowserHost: isSet(object.remoteBrowserHost) ? globalThis.String(object.remoteBrowserHost) : undefined,
remoteBrowserEnabled: isSet(object.remoteBrowserEnabled)
? globalThis.Boolean(object.remoteBrowserEnabled)
: undefined,
chromeExecutablePath: isSet(object.chromeExecutablePath) ? globalThis.String(object.chromeExecutablePath) : undefined,
disableToolUse: isSet(object.disableToolUse) ? globalThis.Boolean(object.disableToolUse) : undefined,
}
},
toJSON(message: UpdateBrowserSettingsRequest): unknown {
const obj: any = {}
if (message.metadata !== undefined) {
obj.metadata = Metadata.toJSON(message.metadata)
}
if (message.viewport !== undefined) {
obj.viewport = Viewport.toJSON(message.viewport)
}
if (message.remoteBrowserHost !== undefined) {
obj.remoteBrowserHost = message.remoteBrowserHost
}
if (message.remoteBrowserEnabled !== undefined) {
obj.remoteBrowserEnabled = message.remoteBrowserEnabled
}
if (message.chromeExecutablePath !== undefined) {
obj.chromeExecutablePath = message.chromeExecutablePath
}
if (message.disableToolUse !== undefined) {
obj.disableToolUse = message.disableToolUse
}
return obj
},
create<I extends Exact<DeepPartial<UpdateBrowserSettingsRequest>, I>>(base?: I): UpdateBrowserSettingsRequest {
return UpdateBrowserSettingsRequest.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<UpdateBrowserSettingsRequest>, I>>(object: I): UpdateBrowserSettingsRequest {
const message = createBaseUpdateBrowserSettingsRequest()
message.metadata =
object.metadata !== undefined && object.metadata !== null ? Metadata.fromPartial(object.metadata) : undefined
message.viewport =
object.viewport !== undefined && object.viewport !== null ? Viewport.fromPartial(object.viewport) : undefined
message.remoteBrowserHost = object.remoteBrowserHost ?? undefined
message.remoteBrowserEnabled = object.remoteBrowserEnabled ?? undefined
message.chromeExecutablePath = object.chromeExecutablePath ?? undefined
message.disableToolUse = object.disableToolUse ?? undefined
return message
},
}
export type BrowserServiceDefinition = typeof BrowserServiceDefinition
export const BrowserServiceDefinition = {
name: "BrowserService",
fullName: "cline.BrowserService",
methods: {
getBrowserConnectionInfo: {
name: "getBrowserConnectionInfo",
requestType: EmptyRequest,
requestStream: false,
responseType: BrowserConnectionInfo,
responseStream: false,
options: {},
},
testBrowserConnection: {
name: "testBrowserConnection",
requestType: StringRequest,
requestStream: false,
responseType: BrowserConnection,
responseStream: false,
options: {},
},
discoverBrowser: {
name: "discoverBrowser",
requestType: EmptyRequest,
requestStream: false,
responseType: BrowserConnection,
responseStream: false,
options: {},
},
getDetectedChromePath: {
name: "getDetectedChromePath",
requestType: EmptyRequest,
requestStream: false,
responseType: ChromePath,
responseStream: false,
options: {},
},
updateBrowserSettings: {
name: "updateBrowserSettings",
requestType: UpdateBrowserSettingsRequest,
requestStream: false,
responseType: Boolean,
responseStream: false,
options: {},
},
relaunchChromeDebugMode: {
name: "relaunchChromeDebugMode",
requestType: EmptyRequest,
requestStream: false,
responseType: String,
responseStream: false,
options: {},
},
},
} as const
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined
export type DeepPartial<T> = T extends Builtin
? T
: T extends globalThis.Array<infer U>
? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>
type KeysOfUnion<T> = T extends T ? keyof T : never
export type Exact<P, I extends P> = P extends Builtin
? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never }
function isSet(value: any): boolean {
return value !== null && value !== undefined
}
export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter
decode(input: BinaryReader | Uint8Array, length?: number): T
fromJSON(object: any): T
toJSON(message: T): unknown
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T
}
+192
View File
@@ -0,0 +1,192 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.0
// protoc v3.19.1
// source: checkpoints.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"
import { Empty, Int64Request, Metadata } from "./common"
export const protobufPackage = "cline"
export interface CheckpointRestoreRequest {
metadata?: Metadata | undefined
number: number
restoreType: string
offset?: number | undefined
}
function createBaseCheckpointRestoreRequest(): CheckpointRestoreRequest {
return { metadata: undefined, number: 0, restoreType: "", offset: undefined }
}
export const CheckpointRestoreRequest: MessageFns<CheckpointRestoreRequest> = {
encode(message: CheckpointRestoreRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.metadata !== undefined) {
Metadata.encode(message.metadata, writer.uint32(10).fork()).join()
}
if (message.number !== 0) {
writer.uint32(16).int64(message.number)
}
if (message.restoreType !== "") {
writer.uint32(26).string(message.restoreType)
}
if (message.offset !== undefined) {
writer.uint32(32).int64(message.offset)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): CheckpointRestoreRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseCheckpointRestoreRequest()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.metadata = Metadata.decode(reader, reader.uint32())
continue
}
case 2: {
if (tag !== 16) {
break
}
message.number = longToNumber(reader.int64())
continue
}
case 3: {
if (tag !== 26) {
break
}
message.restoreType = reader.string()
continue
}
case 4: {
if (tag !== 32) {
break
}
message.offset = longToNumber(reader.int64())
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): CheckpointRestoreRequest {
return {
metadata: isSet(object.metadata) ? Metadata.fromJSON(object.metadata) : undefined,
number: isSet(object.number) ? globalThis.Number(object.number) : 0,
restoreType: isSet(object.restoreType) ? globalThis.String(object.restoreType) : "",
offset: isSet(object.offset) ? globalThis.Number(object.offset) : undefined,
}
},
toJSON(message: CheckpointRestoreRequest): unknown {
const obj: any = {}
if (message.metadata !== undefined) {
obj.metadata = Metadata.toJSON(message.metadata)
}
if (message.number !== 0) {
obj.number = Math.round(message.number)
}
if (message.restoreType !== "") {
obj.restoreType = message.restoreType
}
if (message.offset !== undefined) {
obj.offset = Math.round(message.offset)
}
return obj
},
create<I extends Exact<DeepPartial<CheckpointRestoreRequest>, I>>(base?: I): CheckpointRestoreRequest {
return CheckpointRestoreRequest.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<CheckpointRestoreRequest>, I>>(object: I): CheckpointRestoreRequest {
const message = createBaseCheckpointRestoreRequest()
message.metadata =
object.metadata !== undefined && object.metadata !== null ? Metadata.fromPartial(object.metadata) : undefined
message.number = object.number ?? 0
message.restoreType = object.restoreType ?? ""
message.offset = object.offset ?? undefined
return message
},
}
export type CheckpointsServiceDefinition = typeof CheckpointsServiceDefinition
export const CheckpointsServiceDefinition = {
name: "CheckpointsService",
fullName: "cline.CheckpointsService",
methods: {
checkpointDiff: {
name: "checkpointDiff",
requestType: Int64Request,
requestStream: false,
responseType: Empty,
responseStream: false,
options: {},
},
checkpointRestore: {
name: "checkpointRestore",
requestType: CheckpointRestoreRequest,
requestStream: false,
responseType: Empty,
responseStream: false,
options: {},
},
},
} as const
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined
export type DeepPartial<T> = T extends Builtin
? T
: T extends globalThis.Array<infer U>
? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>
type KeysOfUnion<T> = T extends T ? keyof T : never
export type Exact<P, I extends P> = P extends Builtin
? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never }
function longToNumber(int64: { toString(): string }): number {
const num = globalThis.Number(int64.toString())
if (num > globalThis.Number.MAX_SAFE_INTEGER) {
throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER")
}
if (num < globalThis.Number.MIN_SAFE_INTEGER) {
throw new globalThis.Error("Value is smaller than Number.MIN_SAFE_INTEGER")
}
return num
}
function isSet(value: any): boolean {
return value !== null && value !== undefined
}
export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter
decode(input: BinaryReader | Uint8Array, length?: number): T
fromJSON(object: any): T
toJSON(message: T): unknown
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T
}
+934
View File
@@ -0,0 +1,934 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.0
// protoc v3.19.1
// source: common.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"
export const protobufPackage = "cline"
export interface Metadata {}
export interface EmptyRequest {
metadata?: Metadata | undefined
}
export interface Empty {}
export interface StringRequest {
metadata?: Metadata | undefined
value: string
}
export interface StringArrayRequest {
metadata?: Metadata | undefined
value: string[]
}
export interface String {
value: string
}
export interface Int64Request {
metadata?: Metadata | undefined
value: number
}
export interface Int64 {
value: number
}
export interface BytesRequest {
metadata?: Metadata | undefined
value: Buffer
}
export interface Bytes {
value: Buffer
}
export interface BooleanRequest {
metadata?: Metadata | undefined
value: boolean
}
export interface Boolean {
value: boolean
}
export interface StringArray {
values: string[]
}
function createBaseMetadata(): Metadata {
return {}
}
export const Metadata: MessageFns<Metadata> = {
encode(_: Metadata, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): Metadata {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseMetadata()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(_: any): Metadata {
return {}
},
toJSON(_: Metadata): unknown {
const obj: any = {}
return obj
},
create<I extends Exact<DeepPartial<Metadata>, I>>(base?: I): Metadata {
return Metadata.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<Metadata>, I>>(_: I): Metadata {
const message = createBaseMetadata()
return message
},
}
function createBaseEmptyRequest(): EmptyRequest {
return { metadata: undefined }
}
export const EmptyRequest: MessageFns<EmptyRequest> = {
encode(message: EmptyRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.metadata !== undefined) {
Metadata.encode(message.metadata, writer.uint32(10).fork()).join()
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): EmptyRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseEmptyRequest()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.metadata = Metadata.decode(reader, reader.uint32())
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): EmptyRequest {
return { metadata: isSet(object.metadata) ? Metadata.fromJSON(object.metadata) : undefined }
},
toJSON(message: EmptyRequest): unknown {
const obj: any = {}
if (message.metadata !== undefined) {
obj.metadata = Metadata.toJSON(message.metadata)
}
return obj
},
create<I extends Exact<DeepPartial<EmptyRequest>, I>>(base?: I): EmptyRequest {
return EmptyRequest.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<EmptyRequest>, I>>(object: I): EmptyRequest {
const message = createBaseEmptyRequest()
message.metadata =
object.metadata !== undefined && object.metadata !== null ? Metadata.fromPartial(object.metadata) : undefined
return message
},
}
function createBaseEmpty(): Empty {
return {}
}
export const Empty: MessageFns<Empty> = {
encode(_: Empty, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): Empty {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseEmpty()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(_: any): Empty {
return {}
},
toJSON(_: Empty): unknown {
const obj: any = {}
return obj
},
create<I extends Exact<DeepPartial<Empty>, I>>(base?: I): Empty {
return Empty.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<Empty>, I>>(_: I): Empty {
const message = createBaseEmpty()
return message
},
}
function createBaseStringRequest(): StringRequest {
return { metadata: undefined, value: "" }
}
export const StringRequest: MessageFns<StringRequest> = {
encode(message: StringRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.metadata !== undefined) {
Metadata.encode(message.metadata, writer.uint32(10).fork()).join()
}
if (message.value !== "") {
writer.uint32(18).string(message.value)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): StringRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseStringRequest()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.metadata = Metadata.decode(reader, reader.uint32())
continue
}
case 2: {
if (tag !== 18) {
break
}
message.value = reader.string()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): StringRequest {
return {
metadata: isSet(object.metadata) ? Metadata.fromJSON(object.metadata) : undefined,
value: isSet(object.value) ? globalThis.String(object.value) : "",
}
},
toJSON(message: StringRequest): unknown {
const obj: any = {}
if (message.metadata !== undefined) {
obj.metadata = Metadata.toJSON(message.metadata)
}
if (message.value !== "") {
obj.value = message.value
}
return obj
},
create<I extends Exact<DeepPartial<StringRequest>, I>>(base?: I): StringRequest {
return StringRequest.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<StringRequest>, I>>(object: I): StringRequest {
const message = createBaseStringRequest()
message.metadata =
object.metadata !== undefined && object.metadata !== null ? Metadata.fromPartial(object.metadata) : undefined
message.value = object.value ?? ""
return message
},
}
function createBaseStringArrayRequest(): StringArrayRequest {
return { metadata: undefined, value: [] }
}
export const StringArrayRequest: MessageFns<StringArrayRequest> = {
encode(message: StringArrayRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.metadata !== undefined) {
Metadata.encode(message.metadata, writer.uint32(10).fork()).join()
}
for (const v of message.value) {
writer.uint32(18).string(v!)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): StringArrayRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseStringArrayRequest()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.metadata = Metadata.decode(reader, reader.uint32())
continue
}
case 2: {
if (tag !== 18) {
break
}
message.value.push(reader.string())
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): StringArrayRequest {
return {
metadata: isSet(object.metadata) ? Metadata.fromJSON(object.metadata) : undefined,
value: globalThis.Array.isArray(object?.value) ? object.value.map((e: any) => globalThis.String(e)) : [],
}
},
toJSON(message: StringArrayRequest): unknown {
const obj: any = {}
if (message.metadata !== undefined) {
obj.metadata = Metadata.toJSON(message.metadata)
}
if (message.value?.length) {
obj.value = message.value
}
return obj
},
create<I extends Exact<DeepPartial<StringArrayRequest>, I>>(base?: I): StringArrayRequest {
return StringArrayRequest.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<StringArrayRequest>, I>>(object: I): StringArrayRequest {
const message = createBaseStringArrayRequest()
message.metadata =
object.metadata !== undefined && object.metadata !== null ? Metadata.fromPartial(object.metadata) : undefined
message.value = object.value?.map((e) => e) || []
return message
},
}
function createBaseString(): String {
return { value: "" }
}
export const String: MessageFns<String> = {
encode(message: String, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.value !== "") {
writer.uint32(10).string(message.value)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): String {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseString()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.value = reader.string()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): String {
return { value: isSet(object.value) ? globalThis.String(object.value) : "" }
},
toJSON(message: String): unknown {
const obj: any = {}
if (message.value !== "") {
obj.value = message.value
}
return obj
},
create<I extends Exact<DeepPartial<String>, I>>(base?: I): String {
return String.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<String>, I>>(object: I): String {
const message = createBaseString()
message.value = object.value ?? ""
return message
},
}
function createBaseInt64Request(): Int64Request {
return { metadata: undefined, value: 0 }
}
export const Int64Request: MessageFns<Int64Request> = {
encode(message: Int64Request, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.metadata !== undefined) {
Metadata.encode(message.metadata, writer.uint32(10).fork()).join()
}
if (message.value !== 0) {
writer.uint32(16).int64(message.value)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): Int64Request {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseInt64Request()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.metadata = Metadata.decode(reader, reader.uint32())
continue
}
case 2: {
if (tag !== 16) {
break
}
message.value = longToNumber(reader.int64())
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): Int64Request {
return {
metadata: isSet(object.metadata) ? Metadata.fromJSON(object.metadata) : undefined,
value: isSet(object.value) ? globalThis.Number(object.value) : 0,
}
},
toJSON(message: Int64Request): unknown {
const obj: any = {}
if (message.metadata !== undefined) {
obj.metadata = Metadata.toJSON(message.metadata)
}
if (message.value !== 0) {
obj.value = Math.round(message.value)
}
return obj
},
create<I extends Exact<DeepPartial<Int64Request>, I>>(base?: I): Int64Request {
return Int64Request.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<Int64Request>, I>>(object: I): Int64Request {
const message = createBaseInt64Request()
message.metadata =
object.metadata !== undefined && object.metadata !== null ? Metadata.fromPartial(object.metadata) : undefined
message.value = object.value ?? 0
return message
},
}
function createBaseInt64(): Int64 {
return { value: 0 }
}
export const Int64: MessageFns<Int64> = {
encode(message: Int64, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.value !== 0) {
writer.uint32(8).int64(message.value)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): Int64 {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseInt64()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break
}
message.value = longToNumber(reader.int64())
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): Int64 {
return { value: isSet(object.value) ? globalThis.Number(object.value) : 0 }
},
toJSON(message: Int64): unknown {
const obj: any = {}
if (message.value !== 0) {
obj.value = Math.round(message.value)
}
return obj
},
create<I extends Exact<DeepPartial<Int64>, I>>(base?: I): Int64 {
return Int64.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<Int64>, I>>(object: I): Int64 {
const message = createBaseInt64()
message.value = object.value ?? 0
return message
},
}
function createBaseBytesRequest(): BytesRequest {
return { metadata: undefined, value: Buffer.alloc(0) }
}
export const BytesRequest: MessageFns<BytesRequest> = {
encode(message: BytesRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.metadata !== undefined) {
Metadata.encode(message.metadata, writer.uint32(10).fork()).join()
}
if (message.value.length !== 0) {
writer.uint32(18).bytes(message.value)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): BytesRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseBytesRequest()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.metadata = Metadata.decode(reader, reader.uint32())
continue
}
case 2: {
if (tag !== 18) {
break
}
message.value = Buffer.from(reader.bytes())
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): BytesRequest {
return {
metadata: isSet(object.metadata) ? Metadata.fromJSON(object.metadata) : undefined,
value: isSet(object.value) ? Buffer.from(bytesFromBase64(object.value)) : Buffer.alloc(0),
}
},
toJSON(message: BytesRequest): unknown {
const obj: any = {}
if (message.metadata !== undefined) {
obj.metadata = Metadata.toJSON(message.metadata)
}
if (message.value.length !== 0) {
obj.value = base64FromBytes(message.value)
}
return obj
},
create<I extends Exact<DeepPartial<BytesRequest>, I>>(base?: I): BytesRequest {
return BytesRequest.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<BytesRequest>, I>>(object: I): BytesRequest {
const message = createBaseBytesRequest()
message.metadata =
object.metadata !== undefined && object.metadata !== null ? Metadata.fromPartial(object.metadata) : undefined
message.value = object.value ?? Buffer.alloc(0)
return message
},
}
function createBaseBytes(): Bytes {
return { value: Buffer.alloc(0) }
}
export const Bytes: MessageFns<Bytes> = {
encode(message: Bytes, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.value.length !== 0) {
writer.uint32(10).bytes(message.value)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): Bytes {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseBytes()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.value = Buffer.from(reader.bytes())
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): Bytes {
return { value: isSet(object.value) ? Buffer.from(bytesFromBase64(object.value)) : Buffer.alloc(0) }
},
toJSON(message: Bytes): unknown {
const obj: any = {}
if (message.value.length !== 0) {
obj.value = base64FromBytes(message.value)
}
return obj
},
create<I extends Exact<DeepPartial<Bytes>, I>>(base?: I): Bytes {
return Bytes.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<Bytes>, I>>(object: I): Bytes {
const message = createBaseBytes()
message.value = object.value ?? Buffer.alloc(0)
return message
},
}
function createBaseBooleanRequest(): BooleanRequest {
return { metadata: undefined, value: false }
}
export const BooleanRequest: MessageFns<BooleanRequest> = {
encode(message: BooleanRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.metadata !== undefined) {
Metadata.encode(message.metadata, writer.uint32(10).fork()).join()
}
if (message.value !== false) {
writer.uint32(16).bool(message.value)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): BooleanRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseBooleanRequest()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.metadata = Metadata.decode(reader, reader.uint32())
continue
}
case 2: {
if (tag !== 16) {
break
}
message.value = reader.bool()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): BooleanRequest {
return {
metadata: isSet(object.metadata) ? Metadata.fromJSON(object.metadata) : undefined,
value: isSet(object.value) ? globalThis.Boolean(object.value) : false,
}
},
toJSON(message: BooleanRequest): unknown {
const obj: any = {}
if (message.metadata !== undefined) {
obj.metadata = Metadata.toJSON(message.metadata)
}
if (message.value !== false) {
obj.value = message.value
}
return obj
},
create<I extends Exact<DeepPartial<BooleanRequest>, I>>(base?: I): BooleanRequest {
return BooleanRequest.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<BooleanRequest>, I>>(object: I): BooleanRequest {
const message = createBaseBooleanRequest()
message.metadata =
object.metadata !== undefined && object.metadata !== null ? Metadata.fromPartial(object.metadata) : undefined
message.value = object.value ?? false
return message
},
}
function createBaseBoolean(): Boolean {
return { value: false }
}
export const Boolean: MessageFns<Boolean> = {
encode(message: Boolean, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.value !== false) {
writer.uint32(8).bool(message.value)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): Boolean {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseBoolean()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break
}
message.value = reader.bool()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): Boolean {
return { value: isSet(object.value) ? globalThis.Boolean(object.value) : false }
},
toJSON(message: Boolean): unknown {
const obj: any = {}
if (message.value !== false) {
obj.value = message.value
}
return obj
},
create<I extends Exact<DeepPartial<Boolean>, I>>(base?: I): Boolean {
return Boolean.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<Boolean>, I>>(object: I): Boolean {
const message = createBaseBoolean()
message.value = object.value ?? false
return message
},
}
function createBaseStringArray(): StringArray {
return { values: [] }
}
export const StringArray: MessageFns<StringArray> = {
encode(message: StringArray, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
for (const v of message.values) {
writer.uint32(10).string(v!)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): StringArray {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseStringArray()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.values.push(reader.string())
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): StringArray {
return {
values: globalThis.Array.isArray(object?.values) ? object.values.map((e: any) => globalThis.String(e)) : [],
}
},
toJSON(message: StringArray): unknown {
const obj: any = {}
if (message.values?.length) {
obj.values = message.values
}
return obj
},
create<I extends Exact<DeepPartial<StringArray>, I>>(base?: I): StringArray {
return StringArray.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<StringArray>, I>>(object: I): StringArray {
const message = createBaseStringArray()
message.values = object.values?.map((e) => e) || []
return message
},
}
function bytesFromBase64(b64: string): Uint8Array {
return Uint8Array.from(globalThis.Buffer.from(b64, "base64"))
}
function base64FromBytes(arr: Uint8Array): string {
return globalThis.Buffer.from(arr).toString("base64")
}
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined
export type DeepPartial<T> = T extends Builtin
? T
: T extends globalThis.Array<infer U>
? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>
type KeysOfUnion<T> = T extends T ? keyof T : never
export type Exact<P, I extends P> = P extends Builtin
? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never }
function longToNumber(int64: { toString(): string }): number {
const num = globalThis.Number(int64.toString())
if (num > globalThis.Number.MAX_SAFE_INTEGER) {
throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER")
}
if (num < globalThis.Number.MIN_SAFE_INTEGER) {
throw new globalThis.Error("Value is smaller than Number.MIN_SAFE_INTEGER")
}
return num
}
function isSet(value: any): boolean {
return value !== null && value !== undefined
}
export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter
decode(input: BinaryReader | Uint8Array, length?: number): T
fromJSON(object: any): T
toJSON(message: T): unknown
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+773
View File
@@ -0,0 +1,773 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.0
// protoc v3.19.1
// source: models.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"
import { EmptyRequest, Metadata, StringArray, StringRequest } from "./common"
export const protobufPackage = "cline"
/** List of VS Code LM models */
export interface VsCodeLmModelsArray {
models: VsCodeLmModel[]
}
/** Structure representing a VS Code LM model */
export interface VsCodeLmModel {
vendor: string
family: string
version: string
id: string
}
/** For OpenRouterCompatibleModelInfo structure in OpenRouterModels */
export interface OpenRouterModelInfo {
maxTokens: number
contextWindow: number
supportsImages: boolean
supportsPromptCache: boolean
inputPrice: number
outputPrice: number
cacheWritesPrice: number
cacheReadsPrice: number
description: string
}
/** Shared response message for model information */
export interface OpenRouterCompatibleModelInfo {
models: { [key: string]: OpenRouterModelInfo }
}
export interface OpenRouterCompatibleModelInfo_ModelsEntry {
key: string
value?: OpenRouterModelInfo | undefined
}
/** Request for fetching OpenAI models */
export interface OpenAiModelsRequest {
metadata?: Metadata | undefined
baseUrl: string
apiKey: string
}
function createBaseVsCodeLmModelsArray(): VsCodeLmModelsArray {
return { models: [] }
}
export const VsCodeLmModelsArray: MessageFns<VsCodeLmModelsArray> = {
encode(message: VsCodeLmModelsArray, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
for (const v of message.models) {
VsCodeLmModel.encode(v!, writer.uint32(10).fork()).join()
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): VsCodeLmModelsArray {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseVsCodeLmModelsArray()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.models.push(VsCodeLmModel.decode(reader, reader.uint32()))
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): VsCodeLmModelsArray {
return {
models: globalThis.Array.isArray(object?.models) ? object.models.map((e: any) => VsCodeLmModel.fromJSON(e)) : [],
}
},
toJSON(message: VsCodeLmModelsArray): unknown {
const obj: any = {}
if (message.models?.length) {
obj.models = message.models.map((e) => VsCodeLmModel.toJSON(e))
}
return obj
},
create<I extends Exact<DeepPartial<VsCodeLmModelsArray>, I>>(base?: I): VsCodeLmModelsArray {
return VsCodeLmModelsArray.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<VsCodeLmModelsArray>, I>>(object: I): VsCodeLmModelsArray {
const message = createBaseVsCodeLmModelsArray()
message.models = object.models?.map((e) => VsCodeLmModel.fromPartial(e)) || []
return message
},
}
function createBaseVsCodeLmModel(): VsCodeLmModel {
return { vendor: "", family: "", version: "", id: "" }
}
export const VsCodeLmModel: MessageFns<VsCodeLmModel> = {
encode(message: VsCodeLmModel, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.vendor !== "") {
writer.uint32(10).string(message.vendor)
}
if (message.family !== "") {
writer.uint32(18).string(message.family)
}
if (message.version !== "") {
writer.uint32(26).string(message.version)
}
if (message.id !== "") {
writer.uint32(34).string(message.id)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): VsCodeLmModel {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseVsCodeLmModel()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.vendor = reader.string()
continue
}
case 2: {
if (tag !== 18) {
break
}
message.family = reader.string()
continue
}
case 3: {
if (tag !== 26) {
break
}
message.version = reader.string()
continue
}
case 4: {
if (tag !== 34) {
break
}
message.id = reader.string()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): VsCodeLmModel {
return {
vendor: isSet(object.vendor) ? globalThis.String(object.vendor) : "",
family: isSet(object.family) ? globalThis.String(object.family) : "",
version: isSet(object.version) ? globalThis.String(object.version) : "",
id: isSet(object.id) ? globalThis.String(object.id) : "",
}
},
toJSON(message: VsCodeLmModel): unknown {
const obj: any = {}
if (message.vendor !== "") {
obj.vendor = message.vendor
}
if (message.family !== "") {
obj.family = message.family
}
if (message.version !== "") {
obj.version = message.version
}
if (message.id !== "") {
obj.id = message.id
}
return obj
},
create<I extends Exact<DeepPartial<VsCodeLmModel>, I>>(base?: I): VsCodeLmModel {
return VsCodeLmModel.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<VsCodeLmModel>, I>>(object: I): VsCodeLmModel {
const message = createBaseVsCodeLmModel()
message.vendor = object.vendor ?? ""
message.family = object.family ?? ""
message.version = object.version ?? ""
message.id = object.id ?? ""
return message
},
}
function createBaseOpenRouterModelInfo(): OpenRouterModelInfo {
return {
maxTokens: 0,
contextWindow: 0,
supportsImages: false,
supportsPromptCache: false,
inputPrice: 0,
outputPrice: 0,
cacheWritesPrice: 0,
cacheReadsPrice: 0,
description: "",
}
}
export const OpenRouterModelInfo: MessageFns<OpenRouterModelInfo> = {
encode(message: OpenRouterModelInfo, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.maxTokens !== 0) {
writer.uint32(8).int32(message.maxTokens)
}
if (message.contextWindow !== 0) {
writer.uint32(16).int32(message.contextWindow)
}
if (message.supportsImages !== false) {
writer.uint32(24).bool(message.supportsImages)
}
if (message.supportsPromptCache !== false) {
writer.uint32(32).bool(message.supportsPromptCache)
}
if (message.inputPrice !== 0) {
writer.uint32(41).double(message.inputPrice)
}
if (message.outputPrice !== 0) {
writer.uint32(49).double(message.outputPrice)
}
if (message.cacheWritesPrice !== 0) {
writer.uint32(57).double(message.cacheWritesPrice)
}
if (message.cacheReadsPrice !== 0) {
writer.uint32(65).double(message.cacheReadsPrice)
}
if (message.description !== "") {
writer.uint32(74).string(message.description)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): OpenRouterModelInfo {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseOpenRouterModelInfo()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break
}
message.maxTokens = reader.int32()
continue
}
case 2: {
if (tag !== 16) {
break
}
message.contextWindow = reader.int32()
continue
}
case 3: {
if (tag !== 24) {
break
}
message.supportsImages = reader.bool()
continue
}
case 4: {
if (tag !== 32) {
break
}
message.supportsPromptCache = reader.bool()
continue
}
case 5: {
if (tag !== 41) {
break
}
message.inputPrice = reader.double()
continue
}
case 6: {
if (tag !== 49) {
break
}
message.outputPrice = reader.double()
continue
}
case 7: {
if (tag !== 57) {
break
}
message.cacheWritesPrice = reader.double()
continue
}
case 8: {
if (tag !== 65) {
break
}
message.cacheReadsPrice = reader.double()
continue
}
case 9: {
if (tag !== 74) {
break
}
message.description = reader.string()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): OpenRouterModelInfo {
return {
maxTokens: isSet(object.maxTokens) ? globalThis.Number(object.maxTokens) : 0,
contextWindow: isSet(object.contextWindow) ? globalThis.Number(object.contextWindow) : 0,
supportsImages: isSet(object.supportsImages) ? globalThis.Boolean(object.supportsImages) : false,
supportsPromptCache: isSet(object.supportsPromptCache) ? globalThis.Boolean(object.supportsPromptCache) : false,
inputPrice: isSet(object.inputPrice) ? globalThis.Number(object.inputPrice) : 0,
outputPrice: isSet(object.outputPrice) ? globalThis.Number(object.outputPrice) : 0,
cacheWritesPrice: isSet(object.cacheWritesPrice) ? globalThis.Number(object.cacheWritesPrice) : 0,
cacheReadsPrice: isSet(object.cacheReadsPrice) ? globalThis.Number(object.cacheReadsPrice) : 0,
description: isSet(object.description) ? globalThis.String(object.description) : "",
}
},
toJSON(message: OpenRouterModelInfo): unknown {
const obj: any = {}
if (message.maxTokens !== 0) {
obj.maxTokens = Math.round(message.maxTokens)
}
if (message.contextWindow !== 0) {
obj.contextWindow = Math.round(message.contextWindow)
}
if (message.supportsImages !== false) {
obj.supportsImages = message.supportsImages
}
if (message.supportsPromptCache !== false) {
obj.supportsPromptCache = message.supportsPromptCache
}
if (message.inputPrice !== 0) {
obj.inputPrice = message.inputPrice
}
if (message.outputPrice !== 0) {
obj.outputPrice = message.outputPrice
}
if (message.cacheWritesPrice !== 0) {
obj.cacheWritesPrice = message.cacheWritesPrice
}
if (message.cacheReadsPrice !== 0) {
obj.cacheReadsPrice = message.cacheReadsPrice
}
if (message.description !== "") {
obj.description = message.description
}
return obj
},
create<I extends Exact<DeepPartial<OpenRouterModelInfo>, I>>(base?: I): OpenRouterModelInfo {
return OpenRouterModelInfo.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<OpenRouterModelInfo>, I>>(object: I): OpenRouterModelInfo {
const message = createBaseOpenRouterModelInfo()
message.maxTokens = object.maxTokens ?? 0
message.contextWindow = object.contextWindow ?? 0
message.supportsImages = object.supportsImages ?? false
message.supportsPromptCache = object.supportsPromptCache ?? false
message.inputPrice = object.inputPrice ?? 0
message.outputPrice = object.outputPrice ?? 0
message.cacheWritesPrice = object.cacheWritesPrice ?? 0
message.cacheReadsPrice = object.cacheReadsPrice ?? 0
message.description = object.description ?? ""
return message
},
}
function createBaseOpenRouterCompatibleModelInfo(): OpenRouterCompatibleModelInfo {
return { models: {} }
}
export const OpenRouterCompatibleModelInfo: MessageFns<OpenRouterCompatibleModelInfo> = {
encode(message: OpenRouterCompatibleModelInfo, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
Object.entries(message.models).forEach(([key, value]) => {
OpenRouterCompatibleModelInfo_ModelsEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join()
})
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): OpenRouterCompatibleModelInfo {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseOpenRouterCompatibleModelInfo()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
const entry1 = OpenRouterCompatibleModelInfo_ModelsEntry.decode(reader, reader.uint32())
if (entry1.value !== undefined) {
message.models[entry1.key] = entry1.value
}
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): OpenRouterCompatibleModelInfo {
return {
models: isObject(object.models)
? Object.entries(object.models).reduce<{ [key: string]: OpenRouterModelInfo }>((acc, [key, value]) => {
acc[key] = OpenRouterModelInfo.fromJSON(value)
return acc
}, {})
: {},
}
},
toJSON(message: OpenRouterCompatibleModelInfo): unknown {
const obj: any = {}
if (message.models) {
const entries = Object.entries(message.models)
if (entries.length > 0) {
obj.models = {}
entries.forEach(([k, v]) => {
obj.models[k] = OpenRouterModelInfo.toJSON(v)
})
}
}
return obj
},
create<I extends Exact<DeepPartial<OpenRouterCompatibleModelInfo>, I>>(base?: I): OpenRouterCompatibleModelInfo {
return OpenRouterCompatibleModelInfo.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<OpenRouterCompatibleModelInfo>, I>>(object: I): OpenRouterCompatibleModelInfo {
const message = createBaseOpenRouterCompatibleModelInfo()
message.models = Object.entries(object.models ?? {}).reduce<{ [key: string]: OpenRouterModelInfo }>(
(acc, [key, value]) => {
if (value !== undefined) {
acc[key] = OpenRouterModelInfo.fromPartial(value)
}
return acc
},
{},
)
return message
},
}
function createBaseOpenRouterCompatibleModelInfo_ModelsEntry(): OpenRouterCompatibleModelInfo_ModelsEntry {
return { key: "", value: undefined }
}
export const OpenRouterCompatibleModelInfo_ModelsEntry: MessageFns<OpenRouterCompatibleModelInfo_ModelsEntry> = {
encode(message: OpenRouterCompatibleModelInfo_ModelsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.key !== "") {
writer.uint32(10).string(message.key)
}
if (message.value !== undefined) {
OpenRouterModelInfo.encode(message.value, writer.uint32(18).fork()).join()
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): OpenRouterCompatibleModelInfo_ModelsEntry {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseOpenRouterCompatibleModelInfo_ModelsEntry()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.key = reader.string()
continue
}
case 2: {
if (tag !== 18) {
break
}
message.value = OpenRouterModelInfo.decode(reader, reader.uint32())
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): OpenRouterCompatibleModelInfo_ModelsEntry {
return {
key: isSet(object.key) ? globalThis.String(object.key) : "",
value: isSet(object.value) ? OpenRouterModelInfo.fromJSON(object.value) : undefined,
}
},
toJSON(message: OpenRouterCompatibleModelInfo_ModelsEntry): unknown {
const obj: any = {}
if (message.key !== "") {
obj.key = message.key
}
if (message.value !== undefined) {
obj.value = OpenRouterModelInfo.toJSON(message.value)
}
return obj
},
create<I extends Exact<DeepPartial<OpenRouterCompatibleModelInfo_ModelsEntry>, I>>(
base?: I,
): OpenRouterCompatibleModelInfo_ModelsEntry {
return OpenRouterCompatibleModelInfo_ModelsEntry.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<OpenRouterCompatibleModelInfo_ModelsEntry>, I>>(
object: I,
): OpenRouterCompatibleModelInfo_ModelsEntry {
const message = createBaseOpenRouterCompatibleModelInfo_ModelsEntry()
message.key = object.key ?? ""
message.value =
object.value !== undefined && object.value !== null ? OpenRouterModelInfo.fromPartial(object.value) : undefined
return message
},
}
function createBaseOpenAiModelsRequest(): OpenAiModelsRequest {
return { metadata: undefined, baseUrl: "", apiKey: "" }
}
export const OpenAiModelsRequest: MessageFns<OpenAiModelsRequest> = {
encode(message: OpenAiModelsRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.metadata !== undefined) {
Metadata.encode(message.metadata, writer.uint32(10).fork()).join()
}
if (message.baseUrl !== "") {
writer.uint32(18).string(message.baseUrl)
}
if (message.apiKey !== "") {
writer.uint32(26).string(message.apiKey)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): OpenAiModelsRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseOpenAiModelsRequest()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.metadata = Metadata.decode(reader, reader.uint32())
continue
}
case 2: {
if (tag !== 18) {
break
}
message.baseUrl = reader.string()
continue
}
case 3: {
if (tag !== 26) {
break
}
message.apiKey = reader.string()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): OpenAiModelsRequest {
return {
metadata: isSet(object.metadata) ? Metadata.fromJSON(object.metadata) : undefined,
baseUrl: isSet(object.baseUrl) ? globalThis.String(object.baseUrl) : "",
apiKey: isSet(object.apiKey) ? globalThis.String(object.apiKey) : "",
}
},
toJSON(message: OpenAiModelsRequest): unknown {
const obj: any = {}
if (message.metadata !== undefined) {
obj.metadata = Metadata.toJSON(message.metadata)
}
if (message.baseUrl !== "") {
obj.baseUrl = message.baseUrl
}
if (message.apiKey !== "") {
obj.apiKey = message.apiKey
}
return obj
},
create<I extends Exact<DeepPartial<OpenAiModelsRequest>, I>>(base?: I): OpenAiModelsRequest {
return OpenAiModelsRequest.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<OpenAiModelsRequest>, I>>(object: I): OpenAiModelsRequest {
const message = createBaseOpenAiModelsRequest()
message.metadata =
object.metadata !== undefined && object.metadata !== null ? Metadata.fromPartial(object.metadata) : undefined
message.baseUrl = object.baseUrl ?? ""
message.apiKey = object.apiKey ?? ""
return message
},
}
/** Service for model-related operations */
export type ModelsServiceDefinition = typeof ModelsServiceDefinition
export const ModelsServiceDefinition = {
name: "ModelsService",
fullName: "cline.ModelsService",
methods: {
/** Fetches available models from Ollama */
getOllamaModels: {
name: "getOllamaModels",
requestType: StringRequest,
requestStream: false,
responseType: StringArray,
responseStream: false,
options: {},
},
/** Fetches available models from LM Studio */
getLmStudioModels: {
name: "getLmStudioModels",
requestType: StringRequest,
requestStream: false,
responseType: StringArray,
responseStream: false,
options: {},
},
/** Fetches available models from VS Code LM API */
getVsCodeLmModels: {
name: "getVsCodeLmModels",
requestType: EmptyRequest,
requestStream: false,
responseType: VsCodeLmModelsArray,
responseStream: false,
options: {},
},
/** Refreshes and returns OpenRouter models */
refreshOpenRouterModels: {
name: "refreshOpenRouterModels",
requestType: EmptyRequest,
requestStream: false,
responseType: OpenRouterCompatibleModelInfo,
responseStream: false,
options: {},
},
/** Refreshes and returns OpenAI models */
refreshOpenAiModels: {
name: "refreshOpenAiModels",
requestType: OpenAiModelsRequest,
requestStream: false,
responseType: StringArray,
responseStream: false,
options: {},
},
/** Refreshes and returns Requesty models */
refreshRequestyModels: {
name: "refreshRequestyModels",
requestType: EmptyRequest,
requestStream: false,
responseType: OpenRouterCompatibleModelInfo,
responseStream: false,
options: {},
},
},
} as const
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined
export type DeepPartial<T> = T extends Builtin
? T
: T extends globalThis.Array<infer U>
? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>
type KeysOfUnion<T> = T extends T ? keyof T : never
export type Exact<P, I extends P> = P extends Builtin
? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never }
function isObject(value: any): boolean {
return typeof value === "object" && value !== null
}
function isSet(value: any): boolean {
return value !== null && value !== undefined
}
export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter
decode(input: BinaryReader | Uint8Array, length?: number): T
fromJSON(object: any): T
toJSON(message: T): unknown
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T
}
+36
View File
@@ -0,0 +1,36 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.0
// protoc v3.19.1
// source: slash.proto
/* eslint-disable */
import { Empty, StringRequest } from "./common"
export const protobufPackage = "cline"
/** SlashService provides methods for managing slash */
export type SlashServiceDefinition = typeof SlashServiceDefinition
export const SlashServiceDefinition = {
name: "SlashService",
fullName: "cline.SlashService",
methods: {
/** Sends button click message */
reportBug: {
name: "reportBug",
requestType: StringRequest,
requestStream: false,
responseType: Empty,
responseStream: false,
options: {},
},
condense: {
name: "condense",
requestType: StringRequest,
requestStream: false,
responseType: Empty,
responseStream: false,
options: {},
},
},
} as const
+859
View File
@@ -0,0 +1,859 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.0
// protoc v3.19.1
// source: state.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"
import { Empty, EmptyRequest, Int64, Int64Request, Metadata, StringRequest } from "./common"
export const protobufPackage = "cline"
export enum PlanActMode {
PLAN = 0,
ACT = 1,
UNRECOGNIZED = -1,
}
export function planActModeFromJSON(object: any): PlanActMode {
switch (object) {
case 0:
case "PLAN":
return PlanActMode.PLAN
case 1:
case "ACT":
return PlanActMode.ACT
case -1:
case "UNRECOGNIZED":
default:
return PlanActMode.UNRECOGNIZED
}
}
export function planActModeToJSON(object: PlanActMode): string {
switch (object) {
case PlanActMode.PLAN:
return "PLAN"
case PlanActMode.ACT:
return "ACT"
case PlanActMode.UNRECOGNIZED:
default:
return "UNRECOGNIZED"
}
}
export interface State {
stateJson: string
}
export interface TogglePlanActModeRequest {
metadata?: Metadata | undefined
chatSettings?: ChatSettings | undefined
chatContent?: ChatContent | undefined
}
export interface ChatSettings {
mode: PlanActMode
preferredLanguage?: string | undefined
openAiReasoningEffort?: string | undefined
}
export interface ChatContent {
message?: string | undefined
images: string[]
}
/** Message for auto approval settings */
export interface AutoApprovalSettingsRequest {
metadata?: Metadata | undefined
version: number
enabled: boolean
actions?: AutoApprovalSettingsRequest_Actions | undefined
maxRequests: number
enableNotifications: boolean
favorites: string[]
}
export interface AutoApprovalSettingsRequest_Actions {
readFiles: boolean
readFilesExternally: boolean
editFiles: boolean
editFilesExternally: boolean
executeSafeCommands: boolean
executeAllCommands: boolean
useBrowser: boolean
useMcp: boolean
}
function createBaseState(): State {
return { stateJson: "" }
}
export const State: MessageFns<State> = {
encode(message: State, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.stateJson !== "") {
writer.uint32(10).string(message.stateJson)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): State {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseState()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.stateJson = reader.string()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): State {
return { stateJson: isSet(object.stateJson) ? globalThis.String(object.stateJson) : "" }
},
toJSON(message: State): unknown {
const obj: any = {}
if (message.stateJson !== "") {
obj.stateJson = message.stateJson
}
return obj
},
create<I extends Exact<DeepPartial<State>, I>>(base?: I): State {
return State.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<State>, I>>(object: I): State {
const message = createBaseState()
message.stateJson = object.stateJson ?? ""
return message
},
}
function createBaseTogglePlanActModeRequest(): TogglePlanActModeRequest {
return { metadata: undefined, chatSettings: undefined, chatContent: undefined }
}
export const TogglePlanActModeRequest: MessageFns<TogglePlanActModeRequest> = {
encode(message: TogglePlanActModeRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.metadata !== undefined) {
Metadata.encode(message.metadata, writer.uint32(10).fork()).join()
}
if (message.chatSettings !== undefined) {
ChatSettings.encode(message.chatSettings, writer.uint32(18).fork()).join()
}
if (message.chatContent !== undefined) {
ChatContent.encode(message.chatContent, writer.uint32(26).fork()).join()
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): TogglePlanActModeRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseTogglePlanActModeRequest()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.metadata = Metadata.decode(reader, reader.uint32())
continue
}
case 2: {
if (tag !== 18) {
break
}
message.chatSettings = ChatSettings.decode(reader, reader.uint32())
continue
}
case 3: {
if (tag !== 26) {
break
}
message.chatContent = ChatContent.decode(reader, reader.uint32())
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): TogglePlanActModeRequest {
return {
metadata: isSet(object.metadata) ? Metadata.fromJSON(object.metadata) : undefined,
chatSettings: isSet(object.chatSettings) ? ChatSettings.fromJSON(object.chatSettings) : undefined,
chatContent: isSet(object.chatContent) ? ChatContent.fromJSON(object.chatContent) : undefined,
}
},
toJSON(message: TogglePlanActModeRequest): unknown {
const obj: any = {}
if (message.metadata !== undefined) {
obj.metadata = Metadata.toJSON(message.metadata)
}
if (message.chatSettings !== undefined) {
obj.chatSettings = ChatSettings.toJSON(message.chatSettings)
}
if (message.chatContent !== undefined) {
obj.chatContent = ChatContent.toJSON(message.chatContent)
}
return obj
},
create<I extends Exact<DeepPartial<TogglePlanActModeRequest>, I>>(base?: I): TogglePlanActModeRequest {
return TogglePlanActModeRequest.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<TogglePlanActModeRequest>, I>>(object: I): TogglePlanActModeRequest {
const message = createBaseTogglePlanActModeRequest()
message.metadata =
object.metadata !== undefined && object.metadata !== null ? Metadata.fromPartial(object.metadata) : undefined
message.chatSettings =
object.chatSettings !== undefined && object.chatSettings !== null
? ChatSettings.fromPartial(object.chatSettings)
: undefined
message.chatContent =
object.chatContent !== undefined && object.chatContent !== null
? ChatContent.fromPartial(object.chatContent)
: undefined
return message
},
}
function createBaseChatSettings(): ChatSettings {
return { mode: 0, preferredLanguage: undefined, openAiReasoningEffort: undefined }
}
export const ChatSettings: MessageFns<ChatSettings> = {
encode(message: ChatSettings, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.mode !== 0) {
writer.uint32(8).int32(message.mode)
}
if (message.preferredLanguage !== undefined) {
writer.uint32(18).string(message.preferredLanguage)
}
if (message.openAiReasoningEffort !== undefined) {
writer.uint32(26).string(message.openAiReasoningEffort)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): ChatSettings {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseChatSettings()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break
}
message.mode = reader.int32() as any
continue
}
case 2: {
if (tag !== 18) {
break
}
message.preferredLanguage = reader.string()
continue
}
case 3: {
if (tag !== 26) {
break
}
message.openAiReasoningEffort = reader.string()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): ChatSettings {
return {
mode: isSet(object.mode) ? planActModeFromJSON(object.mode) : 0,
preferredLanguage: isSet(object.preferredLanguage) ? globalThis.String(object.preferredLanguage) : undefined,
openAiReasoningEffort: isSet(object.openAiReasoningEffort)
? globalThis.String(object.openAiReasoningEffort)
: undefined,
}
},
toJSON(message: ChatSettings): unknown {
const obj: any = {}
if (message.mode !== 0) {
obj.mode = planActModeToJSON(message.mode)
}
if (message.preferredLanguage !== undefined) {
obj.preferredLanguage = message.preferredLanguage
}
if (message.openAiReasoningEffort !== undefined) {
obj.openAiReasoningEffort = message.openAiReasoningEffort
}
return obj
},
create<I extends Exact<DeepPartial<ChatSettings>, I>>(base?: I): ChatSettings {
return ChatSettings.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<ChatSettings>, I>>(object: I): ChatSettings {
const message = createBaseChatSettings()
message.mode = object.mode ?? 0
message.preferredLanguage = object.preferredLanguage ?? undefined
message.openAiReasoningEffort = object.openAiReasoningEffort ?? undefined
return message
},
}
function createBaseChatContent(): ChatContent {
return { message: undefined, images: [] }
}
export const ChatContent: MessageFns<ChatContent> = {
encode(message: ChatContent, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.message !== undefined) {
writer.uint32(10).string(message.message)
}
for (const v of message.images) {
writer.uint32(18).string(v!)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): ChatContent {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseChatContent()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.message = reader.string()
continue
}
case 2: {
if (tag !== 18) {
break
}
message.images.push(reader.string())
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): ChatContent {
return {
message: isSet(object.message) ? globalThis.String(object.message) : undefined,
images: globalThis.Array.isArray(object?.images) ? object.images.map((e: any) => globalThis.String(e)) : [],
}
},
toJSON(message: ChatContent): unknown {
const obj: any = {}
if (message.message !== undefined) {
obj.message = message.message
}
if (message.images?.length) {
obj.images = message.images
}
return obj
},
create<I extends Exact<DeepPartial<ChatContent>, I>>(base?: I): ChatContent {
return ChatContent.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<ChatContent>, I>>(object: I): ChatContent {
const message = createBaseChatContent()
message.message = object.message ?? undefined
message.images = object.images?.map((e) => e) || []
return message
},
}
function createBaseAutoApprovalSettingsRequest(): AutoApprovalSettingsRequest {
return {
metadata: undefined,
version: 0,
enabled: false,
actions: undefined,
maxRequests: 0,
enableNotifications: false,
favorites: [],
}
}
export const AutoApprovalSettingsRequest: MessageFns<AutoApprovalSettingsRequest> = {
encode(message: AutoApprovalSettingsRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.metadata !== undefined) {
Metadata.encode(message.metadata, writer.uint32(10).fork()).join()
}
if (message.version !== 0) {
writer.uint32(16).int32(message.version)
}
if (message.enabled !== false) {
writer.uint32(24).bool(message.enabled)
}
if (message.actions !== undefined) {
AutoApprovalSettingsRequest_Actions.encode(message.actions, writer.uint32(34).fork()).join()
}
if (message.maxRequests !== 0) {
writer.uint32(40).int32(message.maxRequests)
}
if (message.enableNotifications !== false) {
writer.uint32(48).bool(message.enableNotifications)
}
for (const v of message.favorites) {
writer.uint32(58).string(v!)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): AutoApprovalSettingsRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseAutoApprovalSettingsRequest()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.metadata = Metadata.decode(reader, reader.uint32())
continue
}
case 2: {
if (tag !== 16) {
break
}
message.version = reader.int32()
continue
}
case 3: {
if (tag !== 24) {
break
}
message.enabled = reader.bool()
continue
}
case 4: {
if (tag !== 34) {
break
}
message.actions = AutoApprovalSettingsRequest_Actions.decode(reader, reader.uint32())
continue
}
case 5: {
if (tag !== 40) {
break
}
message.maxRequests = reader.int32()
continue
}
case 6: {
if (tag !== 48) {
break
}
message.enableNotifications = reader.bool()
continue
}
case 7: {
if (tag !== 58) {
break
}
message.favorites.push(reader.string())
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): AutoApprovalSettingsRequest {
return {
metadata: isSet(object.metadata) ? Metadata.fromJSON(object.metadata) : undefined,
version: isSet(object.version) ? globalThis.Number(object.version) : 0,
enabled: isSet(object.enabled) ? globalThis.Boolean(object.enabled) : false,
actions: isSet(object.actions) ? AutoApprovalSettingsRequest_Actions.fromJSON(object.actions) : undefined,
maxRequests: isSet(object.maxRequests) ? globalThis.Number(object.maxRequests) : 0,
enableNotifications: isSet(object.enableNotifications) ? globalThis.Boolean(object.enableNotifications) : false,
favorites: globalThis.Array.isArray(object?.favorites) ? object.favorites.map((e: any) => globalThis.String(e)) : [],
}
},
toJSON(message: AutoApprovalSettingsRequest): unknown {
const obj: any = {}
if (message.metadata !== undefined) {
obj.metadata = Metadata.toJSON(message.metadata)
}
if (message.version !== 0) {
obj.version = Math.round(message.version)
}
if (message.enabled !== false) {
obj.enabled = message.enabled
}
if (message.actions !== undefined) {
obj.actions = AutoApprovalSettingsRequest_Actions.toJSON(message.actions)
}
if (message.maxRequests !== 0) {
obj.maxRequests = Math.round(message.maxRequests)
}
if (message.enableNotifications !== false) {
obj.enableNotifications = message.enableNotifications
}
if (message.favorites?.length) {
obj.favorites = message.favorites
}
return obj
},
create<I extends Exact<DeepPartial<AutoApprovalSettingsRequest>, I>>(base?: I): AutoApprovalSettingsRequest {
return AutoApprovalSettingsRequest.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<AutoApprovalSettingsRequest>, I>>(object: I): AutoApprovalSettingsRequest {
const message = createBaseAutoApprovalSettingsRequest()
message.metadata =
object.metadata !== undefined && object.metadata !== null ? Metadata.fromPartial(object.metadata) : undefined
message.version = object.version ?? 0
message.enabled = object.enabled ?? false
message.actions =
object.actions !== undefined && object.actions !== null
? AutoApprovalSettingsRequest_Actions.fromPartial(object.actions)
: undefined
message.maxRequests = object.maxRequests ?? 0
message.enableNotifications = object.enableNotifications ?? false
message.favorites = object.favorites?.map((e) => e) || []
return message
},
}
function createBaseAutoApprovalSettingsRequest_Actions(): AutoApprovalSettingsRequest_Actions {
return {
readFiles: false,
readFilesExternally: false,
editFiles: false,
editFilesExternally: false,
executeSafeCommands: false,
executeAllCommands: false,
useBrowser: false,
useMcp: false,
}
}
export const AutoApprovalSettingsRequest_Actions: MessageFns<AutoApprovalSettingsRequest_Actions> = {
encode(message: AutoApprovalSettingsRequest_Actions, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.readFiles !== false) {
writer.uint32(8).bool(message.readFiles)
}
if (message.readFilesExternally !== false) {
writer.uint32(16).bool(message.readFilesExternally)
}
if (message.editFiles !== false) {
writer.uint32(24).bool(message.editFiles)
}
if (message.editFilesExternally !== false) {
writer.uint32(32).bool(message.editFilesExternally)
}
if (message.executeSafeCommands !== false) {
writer.uint32(40).bool(message.executeSafeCommands)
}
if (message.executeAllCommands !== false) {
writer.uint32(48).bool(message.executeAllCommands)
}
if (message.useBrowser !== false) {
writer.uint32(56).bool(message.useBrowser)
}
if (message.useMcp !== false) {
writer.uint32(64).bool(message.useMcp)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): AutoApprovalSettingsRequest_Actions {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseAutoApprovalSettingsRequest_Actions()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break
}
message.readFiles = reader.bool()
continue
}
case 2: {
if (tag !== 16) {
break
}
message.readFilesExternally = reader.bool()
continue
}
case 3: {
if (tag !== 24) {
break
}
message.editFiles = reader.bool()
continue
}
case 4: {
if (tag !== 32) {
break
}
message.editFilesExternally = reader.bool()
continue
}
case 5: {
if (tag !== 40) {
break
}
message.executeSafeCommands = reader.bool()
continue
}
case 6: {
if (tag !== 48) {
break
}
message.executeAllCommands = reader.bool()
continue
}
case 7: {
if (tag !== 56) {
break
}
message.useBrowser = reader.bool()
continue
}
case 8: {
if (tag !== 64) {
break
}
message.useMcp = reader.bool()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): AutoApprovalSettingsRequest_Actions {
return {
readFiles: isSet(object.readFiles) ? globalThis.Boolean(object.readFiles) : false,
readFilesExternally: isSet(object.readFilesExternally) ? globalThis.Boolean(object.readFilesExternally) : false,
editFiles: isSet(object.editFiles) ? globalThis.Boolean(object.editFiles) : false,
editFilesExternally: isSet(object.editFilesExternally) ? globalThis.Boolean(object.editFilesExternally) : false,
executeSafeCommands: isSet(object.executeSafeCommands) ? globalThis.Boolean(object.executeSafeCommands) : false,
executeAllCommands: isSet(object.executeAllCommands) ? globalThis.Boolean(object.executeAllCommands) : false,
useBrowser: isSet(object.useBrowser) ? globalThis.Boolean(object.useBrowser) : false,
useMcp: isSet(object.useMcp) ? globalThis.Boolean(object.useMcp) : false,
}
},
toJSON(message: AutoApprovalSettingsRequest_Actions): unknown {
const obj: any = {}
if (message.readFiles !== false) {
obj.readFiles = message.readFiles
}
if (message.readFilesExternally !== false) {
obj.readFilesExternally = message.readFilesExternally
}
if (message.editFiles !== false) {
obj.editFiles = message.editFiles
}
if (message.editFilesExternally !== false) {
obj.editFilesExternally = message.editFilesExternally
}
if (message.executeSafeCommands !== false) {
obj.executeSafeCommands = message.executeSafeCommands
}
if (message.executeAllCommands !== false) {
obj.executeAllCommands = message.executeAllCommands
}
if (message.useBrowser !== false) {
obj.useBrowser = message.useBrowser
}
if (message.useMcp !== false) {
obj.useMcp = message.useMcp
}
return obj
},
create<I extends Exact<DeepPartial<AutoApprovalSettingsRequest_Actions>, I>>(base?: I): AutoApprovalSettingsRequest_Actions {
return AutoApprovalSettingsRequest_Actions.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<AutoApprovalSettingsRequest_Actions>, I>>(
object: I,
): AutoApprovalSettingsRequest_Actions {
const message = createBaseAutoApprovalSettingsRequest_Actions()
message.readFiles = object.readFiles ?? false
message.readFilesExternally = object.readFilesExternally ?? false
message.editFiles = object.editFiles ?? false
message.editFilesExternally = object.editFilesExternally ?? false
message.executeSafeCommands = object.executeSafeCommands ?? false
message.executeAllCommands = object.executeAllCommands ?? false
message.useBrowser = object.useBrowser ?? false
message.useMcp = object.useMcp ?? false
return message
},
}
export type StateServiceDefinition = typeof StateServiceDefinition
export const StateServiceDefinition = {
name: "StateService",
fullName: "cline.StateService",
methods: {
getLatestState: {
name: "getLatestState",
requestType: EmptyRequest,
requestStream: false,
responseType: State,
responseStream: false,
options: {},
},
subscribeToState: {
name: "subscribeToState",
requestType: EmptyRequest,
requestStream: false,
responseType: State,
responseStream: true,
options: {},
},
toggleFavoriteModel: {
name: "toggleFavoriteModel",
requestType: StringRequest,
requestStream: false,
responseType: Empty,
responseStream: false,
options: {},
},
resetState: {
name: "resetState",
requestType: EmptyRequest,
requestStream: false,
responseType: Empty,
responseStream: false,
options: {},
},
togglePlanActMode: {
name: "togglePlanActMode",
requestType: TogglePlanActModeRequest,
requestStream: false,
responseType: Empty,
responseStream: false,
options: {},
},
updateTerminalConnectionTimeout: {
name: "updateTerminalConnectionTimeout",
requestType: Int64Request,
requestStream: false,
responseType: Int64,
responseStream: false,
options: {},
},
updateAutoApprovalSettings: {
name: "updateAutoApprovalSettings",
requestType: AutoApprovalSettingsRequest,
requestStream: false,
responseType: Empty,
responseStream: false,
options: {},
},
},
} as const
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined
export type DeepPartial<T> = T extends Builtin
? T
: T extends globalThis.Array<infer U>
? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>
type KeysOfUnion<T> = T extends T ? keyof T : never
export type Exact<P, I extends P> = P extends Builtin
? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never }
function isSet(value: any): boolean {
return value !== null && value !== undefined
}
export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter
decode(input: BinaryReader | Uint8Array, length?: number): T
fromJSON(object: any): T
toJSON(message: T): unknown
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T
}
File diff suppressed because it is too large Load Diff
+37
View File
@@ -0,0 +1,37 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.0
// protoc v3.19.1
// source: ui.proto
/* eslint-disable */
import { Boolean, Empty, EmptyRequest, StringRequest } from "./common"
export const protobufPackage = "cline"
/** UiService provides methods for managing UI interactions */
export type UiServiceDefinition = typeof UiServiceDefinition
export const UiServiceDefinition = {
name: "UiService",
fullName: "cline.UiService",
methods: {
/** Scrolls to a specific settings section in the settings view */
scrollToSettings: {
name: "scrollToSettings",
requestType: StringRequest,
requestStream: false,
responseType: Empty,
responseStream: false,
options: {},
},
/** Marks the current announcement as shown and returns whether an announcement should still be shown */
onDidShowAnnouncement: {
name: "onDidShowAnnouncement",
requestType: EmptyRequest,
requestStream: false,
responseType: Boolean,
responseStream: false,
options: {},
},
},
} as const
+295
View File
@@ -0,0 +1,295 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.0
// protoc v3.19.1
// source: web.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"
import { StringRequest } from "./common"
export const protobufPackage = "cline"
export interface IsImageUrl {
isImage: boolean
url: string
}
export interface OpenGraphData {
title: string
description: string
image: string
url: string
siteName: string
type: string
}
function createBaseIsImageUrl(): IsImageUrl {
return { isImage: false, url: "" }
}
export const IsImageUrl: MessageFns<IsImageUrl> = {
encode(message: IsImageUrl, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.isImage !== false) {
writer.uint32(8).bool(message.isImage)
}
if (message.url !== "") {
writer.uint32(18).string(message.url)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): IsImageUrl {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseIsImageUrl()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break
}
message.isImage = reader.bool()
continue
}
case 2: {
if (tag !== 18) {
break
}
message.url = reader.string()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): IsImageUrl {
return {
isImage: isSet(object.isImage) ? globalThis.Boolean(object.isImage) : false,
url: isSet(object.url) ? globalThis.String(object.url) : "",
}
},
toJSON(message: IsImageUrl): unknown {
const obj: any = {}
if (message.isImage !== false) {
obj.isImage = message.isImage
}
if (message.url !== "") {
obj.url = message.url
}
return obj
},
create<I extends Exact<DeepPartial<IsImageUrl>, I>>(base?: I): IsImageUrl {
return IsImageUrl.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<IsImageUrl>, I>>(object: I): IsImageUrl {
const message = createBaseIsImageUrl()
message.isImage = object.isImage ?? false
message.url = object.url ?? ""
return message
},
}
function createBaseOpenGraphData(): OpenGraphData {
return { title: "", description: "", image: "", url: "", siteName: "", type: "" }
}
export const OpenGraphData: MessageFns<OpenGraphData> = {
encode(message: OpenGraphData, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.title !== "") {
writer.uint32(10).string(message.title)
}
if (message.description !== "") {
writer.uint32(18).string(message.description)
}
if (message.image !== "") {
writer.uint32(26).string(message.image)
}
if (message.url !== "") {
writer.uint32(34).string(message.url)
}
if (message.siteName !== "") {
writer.uint32(42).string(message.siteName)
}
if (message.type !== "") {
writer.uint32(50).string(message.type)
}
return writer
},
decode(input: BinaryReader | Uint8Array, length?: number): OpenGraphData {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
let end = length === undefined ? reader.len : reader.pos + length
const message = createBaseOpenGraphData()
while (reader.pos < end) {
const tag = reader.uint32()
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break
}
message.title = reader.string()
continue
}
case 2: {
if (tag !== 18) {
break
}
message.description = reader.string()
continue
}
case 3: {
if (tag !== 26) {
break
}
message.image = reader.string()
continue
}
case 4: {
if (tag !== 34) {
break
}
message.url = reader.string()
continue
}
case 5: {
if (tag !== 42) {
break
}
message.siteName = reader.string()
continue
}
case 6: {
if (tag !== 50) {
break
}
message.type = reader.string()
continue
}
}
if ((tag & 7) === 4 || tag === 0) {
break
}
reader.skip(tag & 7)
}
return message
},
fromJSON(object: any): OpenGraphData {
return {
title: isSet(object.title) ? globalThis.String(object.title) : "",
description: isSet(object.description) ? globalThis.String(object.description) : "",
image: isSet(object.image) ? globalThis.String(object.image) : "",
url: isSet(object.url) ? globalThis.String(object.url) : "",
siteName: isSet(object.siteName) ? globalThis.String(object.siteName) : "",
type: isSet(object.type) ? globalThis.String(object.type) : "",
}
},
toJSON(message: OpenGraphData): unknown {
const obj: any = {}
if (message.title !== "") {
obj.title = message.title
}
if (message.description !== "") {
obj.description = message.description
}
if (message.image !== "") {
obj.image = message.image
}
if (message.url !== "") {
obj.url = message.url
}
if (message.siteName !== "") {
obj.siteName = message.siteName
}
if (message.type !== "") {
obj.type = message.type
}
return obj
},
create<I extends Exact<DeepPartial<OpenGraphData>, I>>(base?: I): OpenGraphData {
return OpenGraphData.fromPartial(base ?? ({} as any))
},
fromPartial<I extends Exact<DeepPartial<OpenGraphData>, I>>(object: I): OpenGraphData {
const message = createBaseOpenGraphData()
message.title = object.title ?? ""
message.description = object.description ?? ""
message.image = object.image ?? ""
message.url = object.url ?? ""
message.siteName = object.siteName ?? ""
message.type = object.type ?? ""
return message
},
}
export type WebServiceDefinition = typeof WebServiceDefinition
export const WebServiceDefinition = {
name: "WebService",
fullName: "cline.WebService",
methods: {
checkIsImageUrl: {
name: "checkIsImageUrl",
requestType: StringRequest,
requestStream: false,
responseType: IsImageUrl,
responseStream: false,
options: {},
},
fetchOpenGraphData: {
name: "fetchOpenGraphData",
requestType: StringRequest,
requestStream: false,
responseType: OpenGraphData,
responseStream: false,
options: {},
},
},
} as const
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined
export type DeepPartial<T> = T extends Builtin
? T
: T extends globalThis.Array<infer U>
? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>
type KeysOfUnion<T> = T extends T ? keyof T : never
export type Exact<P, I extends P> = P extends Builtin
? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never }
function isSet(value: any): boolean {
return value !== null && value !== undefined
}
export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter
decode(input: BinaryReader | Uint8Array, length?: number): T
fromJSON(object: any): T
toJSON(message: T): unknown
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T
}
+205
View File
@@ -0,0 +1,205 @@
// GENERATED CODE -- DO NOT EDIT!
// Generated by generate-server-setup.mjs
import * as grpc from "@grpc/grpc-js"
import { Controller } from "../core/controller"
import { GrpcHandlerWrapper, GrpcStreamingResponseHandlerWrapper } from "./grpc-types"
// Account Service
import { accountLoginClicked } from "../core/controller/account/accountLoginClicked"
import { accountLogoutClicked } from "../core/controller/account/accountLogoutClicked"
// Browser Service
import { getBrowserConnectionInfo } from "../core/controller/browser/getBrowserConnectionInfo"
import { testBrowserConnection } from "../core/controller/browser/testBrowserConnection"
import { discoverBrowser } from "../core/controller/browser/discoverBrowser"
import { getDetectedChromePath } from "../core/controller/browser/getDetectedChromePath"
import { updateBrowserSettings } from "../core/controller/browser/updateBrowserSettings"
import { relaunchChromeDebugMode } from "../core/controller/browser/relaunchChromeDebugMode"
// Checkpoints Service
import { checkpointDiff } from "../core/controller/checkpoints/checkpointDiff"
import { checkpointRestore } from "../core/controller/checkpoints/checkpointRestore"
// File Service
import { copyToClipboard } from "../core/controller/file/copyToClipboard"
import { openFile } from "../core/controller/file/openFile"
import { openImage } from "../core/controller/file/openImage"
import { openMention } from "../core/controller/file/openMention"
import { deleteRuleFile } from "../core/controller/file/deleteRuleFile"
import { createRuleFile } from "../core/controller/file/createRuleFile"
import { searchCommits } from "../core/controller/file/searchCommits"
import { selectImages } from "../core/controller/file/selectImages"
import { getRelativePaths } from "../core/controller/file/getRelativePaths"
import { searchFiles } from "../core/controller/file/searchFiles"
import { toggleClineRule } from "../core/controller/file/toggleClineRule"
import { toggleCursorRule } from "../core/controller/file/toggleCursorRule"
import { toggleWindsurfRule } from "../core/controller/file/toggleWindsurfRule"
import { refreshRules } from "../core/controller/file/refreshRules"
// Mcp Service
import { toggleMcpServer } from "../core/controller/mcp/toggleMcpServer"
import { updateMcpTimeout } from "../core/controller/mcp/updateMcpTimeout"
import { addRemoteMcpServer } from "../core/controller/mcp/addRemoteMcpServer"
import { downloadMcp } from "../core/controller/mcp/downloadMcp"
import { restartMcpServer } from "../core/controller/mcp/restartMcpServer"
import { deleteMcpServer } from "../core/controller/mcp/deleteMcpServer"
import { toggleToolAutoApprove } from "../core/controller/mcp/toggleToolAutoApprove"
import { refreshMcpMarketplace } from "../core/controller/mcp/refreshMcpMarketplace"
// Models Service
import { getOllamaModels } from "../core/controller/models/getOllamaModels"
import { getLmStudioModels } from "../core/controller/models/getLmStudioModels"
import { getVsCodeLmModels } from "../core/controller/models/getVsCodeLmModels"
import { refreshOpenRouterModels } from "../core/controller/models/refreshOpenRouterModels"
import { refreshOpenAiModels } from "../core/controller/models/refreshOpenAiModels"
import { refreshRequestyModels } from "../core/controller/models/refreshRequestyModels"
// Slash Service
import { reportBug } from "../core/controller/slash/reportBug"
import { condense } from "../core/controller/slash/condense"
// State Service
import { getLatestState } from "../core/controller/state/getLatestState"
import { subscribeToState } from "../core/controller/state/subscribeToState"
import { toggleFavoriteModel } from "../core/controller/state/toggleFavoriteModel"
import { resetState } from "../core/controller/state/resetState"
import { togglePlanActMode } from "../core/controller/state/togglePlanActMode"
import { updateTerminalConnectionTimeout } from "../core/controller/state/updateTerminalConnectionTimeout"
import { updateAutoApprovalSettings } from "../core/controller/state/updateAutoApprovalSettings"
// Task Service
import { cancelTask } from "../core/controller/task/cancelTask"
import { clearTask } from "../core/controller/task/clearTask"
import { deleteTasksWithIds } from "../core/controller/task/deleteTasksWithIds"
import { newTask } from "../core/controller/task/newTask"
import { showTaskWithId } from "../core/controller/task/showTaskWithId"
import { exportTaskWithId } from "../core/controller/task/exportTaskWithId"
import { toggleTaskFavorite } from "../core/controller/task/toggleTaskFavorite"
import { deleteNonFavoritedTasks } from "../core/controller/task/deleteNonFavoritedTasks"
import { getTaskHistory } from "../core/controller/task/getTaskHistory"
import { askResponse } from "../core/controller/task/askResponse"
import { taskFeedback } from "../core/controller/task/taskFeedback"
import { taskCompletionViewChanges } from "../core/controller/task/taskCompletionViewChanges"
// Ui Service
import { scrollToSettings } from "../core/controller/ui/scrollToSettings"
import { onDidShowAnnouncement } from "../core/controller/ui/onDidShowAnnouncement"
// Web Service
import { checkIsImageUrl } from "../core/controller/web/checkIsImageUrl"
import { fetchOpenGraphData } from "../core/controller/web/fetchOpenGraphData"
export function addServices(
server: grpc.Server,
proto: any,
controller: Controller,
wrapper: GrpcHandlerWrapper,
wrapStreamingResponse: GrpcStreamingResponseHandlerWrapper,
): void {
// Account Service
server.addService(proto.cline.AccountService.service, {
accountLoginClicked: wrapper(accountLoginClicked, controller),
accountLogoutClicked: wrapper(accountLogoutClicked, controller),
})
// Browser Service
server.addService(proto.cline.BrowserService.service, {
getBrowserConnectionInfo: wrapper(getBrowserConnectionInfo, controller),
testBrowserConnection: wrapper(testBrowserConnection, controller),
discoverBrowser: wrapper(discoverBrowser, controller),
getDetectedChromePath: wrapper(getDetectedChromePath, controller),
updateBrowserSettings: wrapper(updateBrowserSettings, controller),
relaunchChromeDebugMode: wrapper(relaunchChromeDebugMode, controller),
})
// Checkpoints Service
server.addService(proto.cline.CheckpointsService.service, {
checkpointDiff: wrapper(checkpointDiff, controller),
checkpointRestore: wrapper(checkpointRestore, controller),
})
// File Service
server.addService(proto.cline.FileService.service, {
copyToClipboard: wrapper(copyToClipboard, controller),
openFile: wrapper(openFile, controller),
openImage: wrapper(openImage, controller),
openMention: wrapper(openMention, controller),
deleteRuleFile: wrapper(deleteRuleFile, controller),
createRuleFile: wrapper(createRuleFile, controller),
searchCommits: wrapper(searchCommits, controller),
selectImages: wrapper(selectImages, controller),
getRelativePaths: wrapper(getRelativePaths, controller),
searchFiles: wrapper(searchFiles, controller),
toggleClineRule: wrapper(toggleClineRule, controller),
toggleCursorRule: wrapper(toggleCursorRule, controller),
toggleWindsurfRule: wrapper(toggleWindsurfRule, controller),
refreshRules: wrapper(refreshRules, controller),
})
// Mcp Service
server.addService(proto.cline.McpService.service, {
toggleMcpServer: wrapper(toggleMcpServer, controller),
updateMcpTimeout: wrapper(updateMcpTimeout, controller),
addRemoteMcpServer: wrapper(addRemoteMcpServer, controller),
downloadMcp: wrapper(downloadMcp, controller),
restartMcpServer: wrapper(restartMcpServer, controller),
deleteMcpServer: wrapper(deleteMcpServer, controller),
toggleToolAutoApprove: wrapper(toggleToolAutoApprove, controller),
refreshMcpMarketplace: wrapper(refreshMcpMarketplace, controller),
})
// Models Service
server.addService(proto.cline.ModelsService.service, {
getOllamaModels: wrapper(getOllamaModels, controller),
getLmStudioModels: wrapper(getLmStudioModels, controller),
getVsCodeLmModels: wrapper(getVsCodeLmModels, controller),
refreshOpenRouterModels: wrapper(refreshOpenRouterModels, controller),
refreshOpenAiModels: wrapper(refreshOpenAiModels, controller),
refreshRequestyModels: wrapper(refreshRequestyModels, controller),
})
// Slash Service
server.addService(proto.cline.SlashService.service, {
reportBug: wrapper(reportBug, controller),
condense: wrapper(condense, controller),
})
// State Service
server.addService(proto.cline.StateService.service, {
getLatestState: wrapper(getLatestState, controller),
subscribeToState: wrapStreamingResponse(subscribeToState, controller),
toggleFavoriteModel: wrapper(toggleFavoriteModel, controller),
resetState: wrapper(resetState, controller),
togglePlanActMode: wrapper(togglePlanActMode, controller),
updateTerminalConnectionTimeout: wrapper(updateTerminalConnectionTimeout, controller),
updateAutoApprovalSettings: wrapper(updateAutoApprovalSettings, controller),
})
// Task Service
server.addService(proto.cline.TaskService.service, {
cancelTask: wrapper(cancelTask, controller),
clearTask: wrapper(clearTask, controller),
deleteTasksWithIds: wrapper(deleteTasksWithIds, controller),
newTask: wrapper(newTask, controller),
showTaskWithId: wrapper(showTaskWithId, controller),
exportTaskWithId: wrapper(exportTaskWithId, controller),
toggleTaskFavorite: wrapper(toggleTaskFavorite, controller),
deleteNonFavoritedTasks: wrapper(deleteNonFavoritedTasks, controller),
getTaskHistory: wrapper(getTaskHistory, controller),
askResponse: wrapper(askResponse, controller),
taskFeedback: wrapper(taskFeedback, controller),
taskCompletionViewChanges: wrapper(taskCompletionViewChanges, controller),
})
// Ui Service
server.addService(proto.cline.UiService.service, {
scrollToSettings: wrapper(scrollToSettings, controller),
onDidShowAnnouncement: wrapper(onDidShowAnnouncement, controller),
})
// Web Service
server.addService(proto.cline.WebService.service, {
checkIsImageUrl: wrapper(checkIsImageUrl, controller),
fetchOpenGraphData: wrapper(fetchOpenGraphData, controller),
})
}
+12 -2
View File
@@ -5,9 +5,10 @@ import SettingsView from "./components/settings/SettingsView"
import WelcomeView from "./components/welcome/WelcomeView"
import AccountView from "./components/account/AccountView"
import { useExtensionState } from "./context/ExtensionStateContext"
import { vscode } from "./utils/vscode"
import { UiServiceClient } from "./services/grpc-client"
import McpView from "./components/mcp/configuration/McpConfigurationView"
import { Providers } from "./Providers"
import { Boolean, EmptyRequest } from "@shared/proto/common"
const AppContent = () => {
const {
@@ -21,6 +22,7 @@ const AppContent = () => {
showAccount,
showAnnouncement,
setShowAnnouncement,
setShouldShowAnnouncement,
closeMcpView,
navigateToHistory,
hideSettings,
@@ -32,7 +34,15 @@ const AppContent = () => {
useEffect(() => {
if (shouldShowAnnouncement) {
setShowAnnouncement(true)
vscode.postMessage({ type: "didShowAnnouncement" })
// Use the gRPC client instead of direct WebviewMessage
UiServiceClient.onDidShowAnnouncement({} as EmptyRequest)
.then((response: Boolean) => {
setShouldShowAnnouncement(response.value)
})
.catch((error) => {
console.error("Failed to acknowledge announcement:", error)
})
}
}, [shouldShowAnnouncement])
+25 -11
View File
@@ -44,21 +44,15 @@ const Announcement = ({ version, hideAnnouncement }: AnnouncementProps) => {
</h3>
<ul style={ulStyle}>
<li>
<b>Workflows:</b> Create and manage workflow files that can be injected into conversations via slash commands,
making it easy to automate repetitive tasks.
<b>Claude 4 Models:</b> Now with support for Anthropic Claude Sonnet 4 and Claude Opus 4 in both Anthropic and
Vertex providers.
</li>
<li>
<b>Collapsible Task List:</b> Hide your recent tasks when sharing your screen to keep your prompts private.
<b>New Settings Page:</b> Redesigned settings, now split into tabs for easier navigation and a cleaner
experience.
</li>
<li>
<b>Global Endpoint for Vertex AI:</b> Improved availability and reduced rate limiting errors for Vertex AI
users.
</li>
<li>
<b>New User Experience:</b> Special components and guidance for new users to help them get started with Cline.
</li>
<li>
<b>UI Improvements:</b> Fixed loading states and improved settings organization for a smoother experience.
<b>Nebius AI Studio:</b> Added Nebius AI Studio as a new provider. (Thanks @Aktsvigun!)
</li>
</ul>
<Accordion isCompact className="pl-0">
@@ -73,6 +67,26 @@ const Announcement = ({ version, hideAnnouncement }: AnnouncementProps) => {
"text-[var(--vscode-foreground)] mb-0.5 -rotate-180 data-[open=true]:-rotate-90 rtl:rotate-0 rtl:data-[open=true]:-rotate-90",
}}>
<ul style={ulStyle}>
<li>
<b>Workflows:</b> Create and manage workflow files that can be injected into conversations via slash
commands, making it easy to automate repetitive tasks.
</li>
<li>
<b>Collapsible Task List:</b> Hide your recent tasks when sharing your screen to keep your prompts
private.
</li>
<li>
<b>Global Endpoint for Vertex AI:</b> Improved availability and reduced rate limiting errors for
Vertex AI users.
</li>
<li>
<b>New User Experience:</b> Special components and guidance for new users to help them get started
with Cline.
</li>
<li>
<b>UI Improvements:</b> Fixed loading states and improved settings organization for a smoother
experience.
</li>
<li>
<b>Task Timeline:</b> See the history of your coding journey with a visual timeline of checkpoints.
</li>
@@ -260,7 +260,15 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
},
ref,
) => {
const { filePaths, chatSettings, apiConfiguration, openRouterModels, platform, workflowToggles } = useExtensionState()
const {
filePaths,
chatSettings,
apiConfiguration,
openRouterModels,
platform,
localWorkflowToggles,
globalWorkflowToggles,
} = useExtensionState()
const [isTextAreaFocused, setIsTextAreaFocused] = useState(false)
const [isDraggingOver, setIsDraggingOver] = useState(false)
const [gitCommits, setGitCommits] = useState<GitCommit[]>([])
@@ -484,7 +492,11 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
setSelectedSlashCommandsIndex((prevIndex) => {
const direction = event.key === "ArrowUp" ? -1 : 1
// Get commands with workflow toggles
const allCommands = getMatchingSlashCommands(slashCommandsQuery, workflowToggles)
const allCommands = getMatchingSlashCommands(
slashCommandsQuery,
localWorkflowToggles,
globalWorkflowToggles,
)
if (allCommands.length === 0) {
return prevIndex
@@ -502,7 +514,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
if ((event.key === "Enter" || event.key === "Tab") && selectedSlashCommandsIndex !== -1) {
event.preventDefault()
const commands = getMatchingSlashCommands(slashCommandsQuery, workflowToggles)
const commands = getMatchingSlashCommands(slashCommandsQuery, localWorkflowToggles, globalWorkflowToggles)
if (commands.length > 0) {
handleSlashCommandsSelect(commands[selectedSlashCommandsIndex])
}
@@ -905,7 +917,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
// extract and validate the exact command text
const commandText = processedText.substring(slashIndex + 1, endIndex)
const isValidCommand = validateSlashCommand(commandText, workflowToggles)
const isValidCommand = validateSlashCommand(commandText, localWorkflowToggles, globalWorkflowToggles)
if (isValidCommand) {
const fullCommand = processedText.substring(slashIndex, endIndex) // includes slash
@@ -918,7 +930,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
highlightLayerRef.current.innerHTML = processedText
highlightLayerRef.current.scrollTop = textAreaRef.current.scrollTop
highlightLayerRef.current.scrollLeft = textAreaRef.current.scrollLeft
}, [workflowToggles])
}, [localWorkflowToggles, globalWorkflowToggles])
useLayoutEffect(() => {
updateHighlights()
@@ -1400,7 +1412,8 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
setSelectedIndex={setSelectedSlashCommandsIndex}
onMouseDown={handleMenuMouseDown}
query={slashCommandsQuery}
workflowToggles={workflowToggles}
localWorkflowToggles={localWorkflowToggles}
globalWorkflowToggles={globalWorkflowToggles}
/>
</div>
)}
@@ -7,7 +7,8 @@ interface SlashCommandMenuProps {
setSelectedIndex: (index: number) => void
onMouseDown: () => void
query: string
workflowToggles?: Record<string, boolean>
localWorkflowToggles?: Record<string, boolean>
globalWorkflowToggles?: Record<string, boolean>
}
const SlashCommandMenu: React.FC<SlashCommandMenuProps> = ({
@@ -16,7 +17,8 @@ const SlashCommandMenu: React.FC<SlashCommandMenuProps> = ({
setSelectedIndex,
onMouseDown,
query,
workflowToggles = {},
localWorkflowToggles = {},
globalWorkflowToggles = {},
}) => {
const menuRef = useRef<HTMLDivElement>(null)
@@ -44,7 +46,7 @@ const SlashCommandMenu: React.FC<SlashCommandMenuProps> = ({
}, [selectedIndex])
// Filter commands based on query
const filteredCommands = getMatchingSlashCommands(query, workflowToggles)
const filteredCommands = getMatchingSlashCommands(query, localWorkflowToggles, globalWorkflowToggles)
const defaultCommands = filteredCommands.filter((cmd) => cmd.section === "default" || !cmd.section)
const workflowCommands = filteredCommands.filter((cmd) => cmd.section === "custom")
@@ -17,12 +17,14 @@ const ClineRulesToggleModal: React.FC = () => {
localClineRulesToggles = {},
localCursorRulesToggles = {},
localWindsurfRulesToggles = {},
workflowToggles = {},
localWorkflowToggles = {},
globalWorkflowToggles = {},
setGlobalClineRulesToggles,
setLocalClineRulesToggles,
setLocalCursorRulesToggles,
setLocalWindsurfRulesToggles,
setWorkflowToggles,
setLocalWorkflowToggles,
setGlobalWorkflowToggles,
} = useExtensionState()
const [isVisible, setIsVisible] = useState(false)
const buttonRef = useRef<HTMLDivElement>(null)
@@ -49,8 +51,11 @@ const ClineRulesToggleModal: React.FC = () => {
if (response.localWindsurfRulesToggles?.toggles) {
setLocalWindsurfRulesToggles(response.localWindsurfRulesToggles.toggles)
}
if (response.workflowToggles?.toggles) {
setWorkflowToggles(response.workflowToggles.toggles)
if (response.localWorkflowToggles?.toggles) {
setLocalWorkflowToggles(response.localWorkflowToggles.toggles)
}
if (response.globalWorkflowToggles?.toggles) {
setGlobalWorkflowToggles(response.globalWorkflowToggles.toggles)
}
})
.catch((error) => {
@@ -77,7 +82,11 @@ const ClineRulesToggleModal: React.FC = () => {
.map(([path, enabled]): [string, boolean] => [path, enabled as boolean])
.sort(([a], [b]) => a.localeCompare(b))
const workflows = Object.entries(workflowToggles || {})
const localWorkflows = Object.entries(localWorkflowToggles || {})
.map(([path, enabled]): [string, boolean] => [path, enabled as boolean])
.sort(([a], [b]) => a.localeCompare(b))
const globalWorkflows = Object.entries(globalWorkflowToggles || {})
.map(([path, enabled]): [string, boolean] => [path, enabled as boolean])
.sort(([a], [b]) => a.localeCompare(b))
@@ -133,11 +142,12 @@ const ClineRulesToggleModal: React.FC = () => {
})
}
const toggleWorkflow = (workflowPath: string, enabled: boolean) => {
const toggleWorkflow = (isGlobal: boolean, workflowPath: string, enabled: boolean) => {
vscode.postMessage({
type: "toggleWorkflow",
workflowPath,
enabled,
isGlobal,
})
}
@@ -299,19 +309,35 @@ const ClineRulesToggleModal: React.FC = () => {
</div>
</>
) : (
/* Workflows section */
<div style={{ marginBottom: -10 }}>
<div className="text-sm font-normal mb-2">Workspace Workflows</div>
<RulesToggleList
rules={workflows}
toggleRule={toggleWorkflow}
listGap="small"
isGlobal={false}
ruleType={"workflow"}
showNewRule={true}
showNoRules={false}
/>
</div>
<>
{/* Global Workflows Section */}
<div className="mb-3">
<div className="text-sm font-normal mb-2">Global Workflows</div>
<RulesToggleList
rules={globalWorkflows}
toggleRule={(rulePath, enabled) => toggleWorkflow(true, rulePath, enabled)}
listGap="small"
isGlobal={true}
ruleType={"workflow"}
showNewRule={true}
showNoRules={false}
/>
</div>
{/* Local Workflows Section */}
<div style={{ marginBottom: -10 }}>
<div className="text-sm font-normal mb-2">Workspace Workflows</div>
<RulesToggleList
rules={localWorkflows}
toggleRule={(rulePath, enabled) => toggleWorkflow(false, rulePath, enabled)}
listGap="small"
isGlobal={false}
ruleType={"workflow"}
showNewRule={true}
showNoRules={false}
/>
</div>
</>
)}
</div>
)}
@@ -0,0 +1,111 @@
import React, { ReactNode } from "react"
import { cn } from "@/utils/cn"
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
import { AlertTriangle } from "lucide-react"
import { OPENROUTER_MODEL_PICKER_Z_INDEX } from "../settings/OpenRouterModelPicker"
interface AlertDialogProps {
open: boolean
onOpenChange: (open: boolean) => void
children: ReactNode
}
export function AlertDialog({ open, onOpenChange, children }: AlertDialogProps) {
if (!open) return null
// Close the dialog when clicking on the backdrop
const handleBackdropClick = (e: React.MouseEvent) => {
if (e.target === e.currentTarget) {
onOpenChange(false)
}
}
return (
<div
className={cn(`fixed inset-0 bg-black/50 flex items-center justify-center`)}
onClick={handleBackdropClick}
style={{ zIndex: OPENROUTER_MODEL_PICKER_Z_INDEX + 50 }}>
{children}
</div>
)
}
export function AlertDialogContent({ className, children, ...props }: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
className={cn(
`fixed top-[50%] left-[50%] grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%]`,
className,
)}
onClick={(e) => e.stopPropagation()}
{...props}>
<div className="bg-[var(--vscode-editor-background)] rounded-sm gap-3 border border-[var(--vscode-panel-border)] p-4 shadow-lg sm:max-w-md">
{children}
</div>
</div>
)
}
export function AlertDialogHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
return <div className={cn("flex flex-col gap-1 text-left", className)} {...props} />
}
export function AlertDialogFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
return <div className={cn("flex flex-row justify-end gap-2 mt-4", className)} {...props} />
}
export function AlertDialogTitle({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) {
return (
<h2
className={cn(
"text-base font-medium text-[var(--vscode-editor-foreground)] flex items-center gap-2 text-left",
className,
)}
{...props}
/>
)
}
export function AlertDialogDescription({ className, ...props }: React.HTMLAttributes<HTMLParagraphElement>) {
return <p className={cn("text-[var(--vscode-descriptionForeground)] text-sm text-left", className)} {...props} />
}
export function AlertDialogAction({ className, ...props }: React.ComponentProps<typeof VSCodeButton>) {
return <VSCodeButton appearance="primary" {...props} />
}
export function AlertDialogCancel({ className, ...props }: React.ComponentProps<typeof VSCodeButton>) {
return <VSCodeButton appearance="secondary" {...props} />
}
export function UnsavedChangesDialog({
open,
onOpenChange,
onConfirm,
onCancel,
}: {
open: boolean
onOpenChange: (open: boolean) => void
onConfirm: () => void
onCancel: () => void
}) {
return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>
<AlertTriangle className="w-5 h-5 text-[var(--vscode-errorForeground)]" />
Unsaved Changes
</AlertDialogTitle>
<AlertDialogDescription>
You have unsaved changes. Are you sure you want to discard them?
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel onClick={onCancel}>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={onConfirm}>Discard Changes</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
)
}
@@ -10,16 +10,16 @@ import type { Node } from "unist"
import { useExtensionState } from "@/context/ExtensionStateContext"
import { CODE_BLOCK_BG_COLOR } from "@/components/common/CodeBlock"
import MermaidBlock from "@/components/common/MermaidBlock"
import { vscode } from "@/utils/vscode"
import { StateServiceClient } from "@/services/grpc-client"
import { PlanActMode } from "@shared/proto/state"
// Styled component for Act Mode text with more specific styling
const ActModeHighlight: React.FC = () => (
<span
onClick={() => {
vscode.postMessage({
type: "togglePlanActMode",
StateServiceClient.togglePlanActMode({
chatSettings: {
mode: "act",
mode: PlanActMode.ACT,
},
})
}}
@@ -55,7 +55,6 @@ import {
doubaoDefaultModelId,
liteLlmModelInfoSaneDefaults,
} from "@shared/api"
import { ExtensionMessage } from "@shared/ExtensionMessage"
import { useExtensionState } from "@/context/ExtensionStateContext"
import { vscode } from "@/utils/vscode"
import { ModelsServiceClient } from "@/services/grpc-client"
@@ -894,8 +893,14 @@ const ApiOptions = ({
</div>
)}
{(selectedModelId === "anthropic.claude-3-7-sonnet-20250219-v1:0" ||
selectedModelId === "anthropic.claude-sonnet-4-20250514-v1:0" ||
selectedModelId === "anthropic.claude-opus-4-20250514-v1:0" ||
(apiConfiguration?.awsBedrockCustomSelected &&
apiConfiguration?.awsBedrockCustomModelBaseId === "anthropic.claude-3-7-sonnet-20250219-v1:0")) && (
apiConfiguration?.awsBedrockCustomModelBaseId === "anthropic.claude-3-7-sonnet-20250219-v1:0") ||
(apiConfiguration?.awsBedrockCustomSelected &&
apiConfiguration?.awsBedrockCustomModelBaseId === "anthropic.claude-sonnet-4-20250514-v1:0") ||
(apiConfiguration?.awsBedrockCustomSelected &&
apiConfiguration?.awsBedrockCustomModelBaseId === "anthropic.claude-opus-4-20250514-v1:0")) && (
<ThinkingBudgetSlider apiConfiguration={apiConfiguration} setApiConfiguration={setApiConfiguration} />
)}
<ModelInfoView
@@ -1648,7 +1653,7 @@ const ApiOptions = ({
value={apiConfiguration?.liteLlmModelId || ""}
style={{ width: "100%" }}
onInput={handleInputChange("liteLlmModelId")}
placeholder={"e.g. anthropic/claude-3-7-sonnet-20250219"}>
placeholder={"e.g. anthropic/claude-sonnet-4-20250514"}>
<span style={{ fontWeight: 500 }}>Model ID</span>
</VSCodeTextField>
@@ -1682,7 +1687,7 @@ const ApiOptions = ({
marginTop: "5px",
color: "var(--vscode-descriptionForeground)",
}}>
Extended thinking is available for models as Sonnet-3-7, o3-mini, Deepseek R1, etc. More info on{" "}
Extended thinking is available for models such as Sonnet-4, o3-mini, Deepseek R1, etc. More info on{" "}
<VSCodeLink
href="https://docs.litellm.ai/docs/reasoning_content"
style={{ display: "inline", fontSize: "inherit" }}>
@@ -2128,10 +2133,19 @@ const ApiOptions = ({
{selectedProvider === "nebius" && createDropdown(nebiusModels)}
</DropdownContainer>
{((selectedProvider === "anthropic" && selectedModelId === "claude-3-7-sonnet-20250219") ||
(selectedProvider === "vertex" && selectedModelId === "claude-3-7-sonnet@20250219")) && (
<ThinkingBudgetSlider apiConfiguration={apiConfiguration} setApiConfiguration={setApiConfiguration} />
)}
{(selectedProvider === "anthropic" &&
(selectedModelId === "claude-3-7-sonnet-20250219" ||
selectedModelId === "claude-sonnet-4-20250514" ||
selectedModelId === "claude-opus-4-20250514")) ||
(selectedProvider === "vertex" &&
(selectedModelId === "claude-3-7-sonnet@20250219" ||
selectedModelId === "claude-sonnet-4@20250514" ||
selectedModelId === "claude-opus-4@20250514") && (
<ThinkingBudgetSlider
apiConfiguration={apiConfiguration}
setApiConfiguration={setApiConfiguration}
/>
))}
{selectedProvider === "xai" && selectedModelId.includes("3-mini") && (
<>
@@ -7,7 +7,6 @@ import styled from "styled-components"
import { openRouterDefaultModelId } from "@shared/api"
import { useExtensionState } from "@/context/ExtensionStateContext"
import { ModelsServiceClient, StateServiceClient } from "@/services/grpc-client"
import { vscode } from "@/utils/vscode"
import { highlight } from "../history/HistoryView"
import { ModelInfoView, normalizeApiConfiguration } from "./ApiOptions"
import { CODE_BLOCK_BG_COLOR } from "@/components/common/CodeBlock"
@@ -42,8 +41,8 @@ export interface OpenRouterModelPickerProps {
// Featured models for Cline provider
const featuredModels = [
{
id: "anthropic/claude-3.7-sonnet",
description: "Leading model for agentic coding",
id: "anthropic/claude-sonnet-4",
description: "Best model for agentic coding",
label: "Best",
},
{
@@ -199,6 +198,8 @@ const OpenRouterModelPicker: React.FC<OpenRouterModelPickerProps> = ({ isPopup }
const showBudgetSlider = useMemo(() => {
return (
selectedModelId?.toLowerCase().includes("claude-sonnet-4") ||
selectedModelId?.toLowerCase().includes("claude-opus-4") ||
selectedModelId?.toLowerCase().includes("claude-3-7-sonnet") ||
selectedModelId?.toLowerCase().includes("claude-3.7-sonnet") ||
selectedModelId?.toLowerCase().includes("claude-3.7-sonnet:thinking")
@@ -335,8 +336,8 @@ const OpenRouterModelPicker: React.FC<OpenRouterModelPickerProps> = ({ isPopup }
If you're unsure which model to choose, Cline works best with{" "}
<VSCodeLink
style={{ display: "inline", fontSize: "inherit" }}
onClick={() => handleModelChange("anthropic/claude-3.7-sonnet")}>
anthropic/claude-3.7-sonnet.
onClick={() => handleModelChange("anthropic/claude-sonnet-4")}>
anthropic/claude-sonnet-4.
</VSCodeLink>
You can also try searching "free" for no-cost options currently available.
</>
@@ -12,10 +12,11 @@ export const SectionHeader = ({ description, children, className, ...props }: Se
return (
<div
className={cn(
`sticky top-0 z-${OPENROUTER_MODEL_PICKER_Z_INDEX + 20} text-[var(--vscode-foreground)] bg-[var(--vscode-panel-background)] px-5 py-3`,
`sticky top-0 text-[var(--vscode-foreground)] bg-[var(--vscode-panel-background)] px-5 py-3`,
className,
)}
{...props}>
{...props}
style={{ zIndex: OPENROUTER_MODEL_PICKER_Z_INDEX + 20 }}>
<h4 className="m-0">{children}</h4>
{description && <p className="text-[var(--vscode-descriptionForeground)] text-sm mt-2 mb-0">{description}</p>}
</div>
@@ -22,6 +22,7 @@ import {
LucideIcon,
} from "lucide-react"
import HeroTooltip from "@/components/common/HeroTooltip"
import { UnsavedChangesDialog } from "@/components/common/AlertDialog"
import SectionHeader from "./SectionHeader"
import Section from "./Section"
import PreferredLanguageSetting from "./PreferredLanguageSetting" // Added import
@@ -125,6 +126,12 @@ type SettingsViewProps = {
}
const SettingsView = ({ onDone, targetSection }: SettingsViewProps) => {
// Track if there are unsaved changes
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false)
// State for the unsaved changes dialog
const [isUnsavedChangesDialogOpen, setIsUnsavedChangesDialogOpen] = useState(false)
// Store the action to perform after confirmation
const pendingAction = useRef<() => void>()
const {
apiConfiguration,
version,
@@ -138,8 +145,22 @@ const SettingsView = ({ onDone, targetSection }: SettingsViewProps) => {
planActSeparateModelsSetting,
setPlanActSeparateModelsSetting,
enableCheckpointsSetting,
setEnableCheckpointsSetting,
mcpMarketplaceEnabled,
setMcpMarketplaceEnabled,
setApiConfiguration,
} = useExtensionState()
// Store the original state to detect changes
const originalState = useRef({
apiConfiguration,
customInstructions,
telemetrySetting,
planActSeparateModelsSetting,
enableCheckpointsSetting,
mcpMarketplaceEnabled,
chatSettings,
})
const [apiErrorMessage, setApiErrorMessage] = useState<string | undefined>(undefined)
const [modelIdErrorMessage, setModelIdErrorMessage] = useState<string | undefined>(undefined)
const [pendingTabChange, setPendingTabChange] = useState<"plan" | "act" | null>(null)
@@ -192,6 +213,89 @@ const SettingsView = ({ onDone, targetSection }: SettingsViewProps) => {
setModelIdErrorMessage(undefined)
}, [apiConfiguration])
// Check for unsaved changes by comparing current state with original state
useEffect(() => {
const hasChanges =
JSON.stringify(apiConfiguration) !== JSON.stringify(originalState.current.apiConfiguration) ||
customInstructions !== originalState.current.customInstructions ||
telemetrySetting !== originalState.current.telemetrySetting ||
planActSeparateModelsSetting !== originalState.current.planActSeparateModelsSetting ||
enableCheckpointsSetting !== originalState.current.enableCheckpointsSetting ||
mcpMarketplaceEnabled !== originalState.current.mcpMarketplaceEnabled ||
JSON.stringify(chatSettings) !== JSON.stringify(originalState.current.chatSettings)
setHasUnsavedChanges(hasChanges)
}, [
apiConfiguration,
customInstructions,
telemetrySetting,
planActSeparateModelsSetting,
enableCheckpointsSetting,
mcpMarketplaceEnabled,
chatSettings,
])
// Handle cancel button click
const handleCancel = useCallback(() => {
if (hasUnsavedChanges) {
// Show confirmation dialog
setIsUnsavedChangesDialogOpen(true)
pendingAction.current = () => {
// Reset all tracked state to original values
setCustomInstructions(originalState.current.customInstructions)
setTelemetrySetting(originalState.current.telemetrySetting)
setPlanActSeparateModelsSetting(originalState.current.planActSeparateModelsSetting)
setChatSettings(originalState.current.chatSettings)
if (typeof setApiConfiguration === "function") {
setApiConfiguration(originalState.current.apiConfiguration ?? {})
}
if (typeof setEnableCheckpointsSetting === "function") {
setEnableCheckpointsSetting(
typeof originalState.current.enableCheckpointsSetting === "boolean"
? originalState.current.enableCheckpointsSetting
: false,
)
}
if (typeof setMcpMarketplaceEnabled === "function") {
setMcpMarketplaceEnabled(
typeof originalState.current.mcpMarketplaceEnabled === "boolean"
? originalState.current.mcpMarketplaceEnabled
: false,
)
}
// Close settings view
onDone()
}
} else {
// No changes, just close
onDone()
}
}, [
hasUnsavedChanges,
onDone,
setCustomInstructions,
setTelemetrySetting,
setPlanActSeparateModelsSetting,
setChatSettings,
setApiConfiguration,
setEnableCheckpointsSetting,
setMcpMarketplaceEnabled,
])
// Handle confirmation dialog actions
const handleConfirmDiscard = useCallback(() => {
setIsUnsavedChangesDialogOpen(false)
if (pendingAction.current) {
pendingAction.current()
pendingAction.current = undefined
}
}, [])
const handleCancelDiscard = useCallback(() => {
setIsUnsavedChangesDialogOpen(false)
pendingAction.current = undefined
}, [])
// validate as soon as the component is mounted
/*
useEffect will use stale values of variables if they are not included in the dependency array.
@@ -328,7 +432,12 @@ const SettingsView = ({ onDone, targetSection }: SettingsViewProps) => {
<h3 className="text-[var(--vscode-foreground)] m-0">Settings</h3>
</div>
<div className="flex gap-2">
<VSCodeButton onClick={() => handleSubmit(false)}>Save</VSCodeButton>
<VSCodeButton appearance="secondary" onClick={handleCancel}>
Cancel
</VSCodeButton>
<VSCodeButton onClick={() => handleSubmit(false)} disabled={!hasUnsavedChanges}>
Save
</VSCodeButton>
</div>
</TabHeader>
@@ -593,6 +702,14 @@ const SettingsView = ({ onDone, targetSection }: SettingsViewProps) => {
)
})()}
</div>
{/* Unsaved Changes Dialog */}
<UnsavedChangesDialog
open={isUnsavedChangesDialogOpen}
onOpenChange={setIsUnsavedChangesDialogOpen}
onConfirm={handleConfirmDiscard}
onCancel={handleCancelDiscard}
/>
</Tab>
)
}
@@ -45,6 +45,7 @@ interface ExtensionStateContextType extends ExtensionState {
setCustomInstructions: (value?: string) => void
setTelemetrySetting: (value: TelemetrySetting) => void
setShowAnnouncement: (value: boolean) => void
setShouldShowAnnouncement: (value: boolean) => void
setPlanActSeparateModelsSetting: (value: boolean) => void
setEnableCheckpointsSetting: (value: boolean) => void
setMcpMarketplaceEnabled: (value: boolean) => void
@@ -55,7 +56,8 @@ interface ExtensionStateContextType extends ExtensionState {
setLocalClineRulesToggles: (toggles: Record<string, boolean>) => void
setLocalCursorRulesToggles: (toggles: Record<string, boolean>) => void
setLocalWindsurfRulesToggles: (toggles: Record<string, boolean>) => void
setWorkflowToggles: (toggles: Record<string, boolean>) => void
setLocalWorkflowToggles: (toggles: Record<string, boolean>) => void
setGlobalWorkflowToggles: (toggles: Record<string, boolean>) => void
setMcpMarketplaceCatalog: (value: McpMarketplaceCatalog) => void
// Navigation state setters
@@ -161,7 +163,8 @@ export const ExtensionStateContextProvider: React.FC<{
localClineRulesToggles: {},
localCursorRulesToggles: {},
localWindsurfRulesToggles: {},
workflowToggles: {},
localWorkflowToggles: {},
globalWorkflowToggles: {},
shellIntegrationTimeout: 4000, // default timeout for shell integration
isNewUser: false,
})
@@ -203,60 +206,6 @@ export const ExtensionStateContextProvider: React.FC<{
}
break
}
case "state": {
// Handler for direct state messages
if (message.state) {
const stateData = message.state as ExtensionState
console.log("[Webview Context Test Revert] Received direct 'state' message, updating state.")
setState((prevState) => {
// Versioning logic for autoApprovalSettings (copied from original onResponse)
const incomingVersion = stateData.autoApprovalSettings?.version ?? 1
const currentVersion = prevState.autoApprovalSettings?.version ?? 1
const shouldUpdateAutoApproval = incomingVersion > currentVersion
const newState = {
...stateData,
autoApprovalSettings: shouldUpdateAutoApproval
? stateData.autoApprovalSettings
: prevState.autoApprovalSettings,
}
// Update welcome screen state based on API configuration (copied from original onResponse)
const config = stateData.apiConfiguration
const hasKey = config
? [
config.apiKey,
config.openRouterApiKey,
config.awsRegion,
config.vertexProjectId,
config.openAiApiKey,
config.ollamaModelId,
config.lmStudioModelId,
config.liteLlmApiKey,
config.geminiApiKey,
config.openAiNativeApiKey,
config.deepSeekApiKey,
config.requestyApiKey,
config.togetherApiKey,
config.qwenApiKey,
config.doubaoApiKey,
config.mistralApiKey,
config.vsCodeLmModelSelector,
config.clineApiKey,
config.asksageApiKey,
config.xaiApiKey,
config.sambanovaApiKey,
config.nebiusApiKey,
].some((key) => key !== undefined)
: false
setShowWelcome(!hasKey)
setDidHydrateState(true)
return newState
})
}
break
}
case "theme": {
if (message.text) {
setTheme(convertTextMateToHljs(JSON.parse(message.text)))
@@ -326,33 +275,31 @@ export const ExtensionStateContextProvider: React.FC<{
const stateSubscriptionRef = useRef<(() => void) | null>(null)
// Subscribe to state updates using the new gRPC streaming API
/* // TEST REVERT: Commenting out gRPC state subscription
useEffect(() => {
// Set up state subscription
stateSubscriptionRef.current = StateServiceClient.subscribeToState(
{},
{
onResponse: (response) => {
console.log("[DEBUG] got state update via subscription", response);
if (response.stateJson) {
try {
const stateData = JSON.parse(response.stateJson) as ExtensionState;
console.log("[DEBUG] parsed state JSON, updating state");
const stateData = JSON.parse(response.stateJson) as ExtensionState
console.log("[DEBUG] parsed state JSON, updating state")
setState((prevState) => {
// Versioning logic for autoApprovalSettings
const incomingVersion = stateData.autoApprovalSettings?.version ?? 1;
const currentVersion = prevState.autoApprovalSettings?.version ?? 1;
const shouldUpdateAutoApproval = incomingVersion > currentVersion;
const incomingVersion = stateData.autoApprovalSettings?.version ?? 1
const currentVersion = prevState.autoApprovalSettings?.version ?? 1
const shouldUpdateAutoApproval = incomingVersion > currentVersion
const newState = {
...stateData,
autoApprovalSettings: shouldUpdateAutoApproval
? stateData.autoApprovalSettings
: prevState.autoApprovalSettings,
};
}
// Update welcome screen state based on API configuration
const config = stateData.apiConfiguration;
const config = stateData.apiConfiguration
const hasKey = config
? [
config.apiKey,
@@ -377,52 +324,41 @@ export const ExtensionStateContextProvider: React.FC<{
config.xaiApiKey,
config.sambanovaApiKey,
].some((key) => key !== undefined)
: false;
: false
setShowWelcome(!hasKey);
setDidHydrateState(true);
setShowWelcome(!hasKey)
setDidHydrateState(true)
console.log("[DEBUG] returning new state in ESC");
console.log("[DEBUG] returning new state in ESC")
return newState;
});
return newState
})
} catch (error) {
console.error("Error parsing state JSON:", error);
console.log("[DEBUG] ERR getting state", error);
console.error("Error parsing state JSON:", error)
console.log("[DEBUG] ERR getting state", error)
}
}
console.log('[DEBUG] ended "got subscribed state"');
console.log('[DEBUG] ended "got subscribed state"')
},
onError: (error) => {
console.error("Error in state subscription:", error);
console.error("Error in state subscription:", error)
},
onComplete: () => {
console.log("State subscription completed");
console.log("State subscription completed")
},
},
);
)
// Still send the webviewDidLaunch message for other initialization
vscode.postMessage({ type: "webviewDidLaunch" });
vscode.postMessage({ type: "webviewDidLaunch" })
// Clean up subscription when component unmounts
return () => {
if (stateSubscriptionRef.current) {
stateSubscriptionRef.current();
stateSubscriptionRef.current = null;
stateSubscriptionRef.current()
stateSubscriptionRef.current = null
}
};
}, []);
*/ // END TEST REVERT
// For the test revert, ensure webviewDidLaunch is still sent if not done by the above useEffect
useEffect(() => {
// This effect now only sends webviewDidLaunch if the gRPC subscription is commented out.
// If the gRPC subscription is active, it sends webviewDidLaunch.
// To avoid sending it twice if you uncomment the above, you might add a flag.
// For this specific test (gRPC sub commented out), this is fine.
console.log("[Webview Context Test Revert] Sending webviewDidLaunch from separate useEffect.")
vscode.postMessage({ type: "webviewDidLaunch" })
}
}, [])
const contextValue: ExtensionStateContextType = {
@@ -447,7 +383,8 @@ export const ExtensionStateContextProvider: React.FC<{
localClineRulesToggles: state.localClineRulesToggles || {},
localCursorRulesToggles: state.localCursorRulesToggles || {},
localWindsurfRulesToggles: state.localWindsurfRulesToggles || {},
workflowToggles: state.workflowToggles || {},
localWorkflowToggles: state.localWorkflowToggles || {},
globalWorkflowToggles: state.globalWorkflowToggles || {},
enableCheckpointsSetting: state.enableCheckpointsSetting,
// Navigation functions
@@ -492,7 +429,8 @@ export const ExtensionStateContextProvider: React.FC<{
...prevState,
mcpMarketplaceEnabled: value,
})),
setShowAnnouncement: (value) =>
setShowAnnouncement,
setShouldShowAnnouncement: (value) =>
setState((prevState) => ({
...prevState,
shouldShowAnnouncement: value,
@@ -542,10 +480,15 @@ export const ExtensionStateContextProvider: React.FC<{
...prevState,
localWindsurfRulesToggles: toggles,
})),
setWorkflowToggles: (toggles) =>
setLocalWorkflowToggles: (toggles) =>
setState((prevState) => ({
...prevState,
workflowToggles: toggles,
localWorkflowToggles: toggles,
})),
setGlobalWorkflowToggles: (toggles) =>
setState((prevState) => ({
...prevState,
globalWorkflowToggles: toggles,
})),
setMcpTab,
}
@@ -94,7 +94,6 @@ export function createGrpcClient<T extends ProtoService>(service: T): GrpcClient
if (message.grpc_response.message) {
const responseType = method.responseType
const response = responseType.fromJSON(message.grpc_response.message)
console.log("[DEBUG] Received streaming response:", message.grpc_response.message)
options.onResponse(response)
}
}
@@ -149,7 +148,6 @@ export function createGrpcClient<T extends ProtoService>(service: T): GrpcClient
// Convert JSON back to protobuf message
const responseType = method.responseType
const response = responseType.fromJSON(message.grpc_response.message)
console.log("[DEBUG] grpc-client sending response:", response)
resolve(response)
}
}
+41
View File
@@ -0,0 +1,41 @@
// AUTO-GENERATED FILE - DO NOT MODIFY DIRECTLY
// Generated by proto/build-proto.js
import { createGrpcClient } from "./grpc-client-base"
import { AccountServiceDefinition } from "@shared/proto/account"
import { BrowserServiceDefinition } from "@shared/proto/browser"
import { CheckpointsServiceDefinition } from "@shared/proto/checkpoints"
import { FileServiceDefinition } from "@shared/proto/file"
import { McpServiceDefinition } from "@shared/proto/mcp"
import { StateServiceDefinition } from "@shared/proto/state"
import { TaskServiceDefinition } from "@shared/proto/task"
import { WebServiceDefinition } from "@shared/proto/web"
import { ModelsServiceDefinition } from "@shared/proto/models"
import { SlashServiceDefinition } from "@shared/proto/slash"
import { UiServiceDefinition } from "@shared/proto/ui"
const AccountServiceClient = createGrpcClient(AccountServiceDefinition)
const BrowserServiceClient = createGrpcClient(BrowserServiceDefinition)
const CheckpointsServiceClient = createGrpcClient(CheckpointsServiceDefinition)
const FileServiceClient = createGrpcClient(FileServiceDefinition)
const McpServiceClient = createGrpcClient(McpServiceDefinition)
const StateServiceClient = createGrpcClient(StateServiceDefinition)
const TaskServiceClient = createGrpcClient(TaskServiceDefinition)
const WebServiceClient = createGrpcClient(WebServiceDefinition)
const ModelsServiceClient = createGrpcClient(ModelsServiceDefinition)
const SlashServiceClient = createGrpcClient(SlashServiceDefinition)
const UiServiceClient = createGrpcClient(UiServiceDefinition)
export {
AccountServiceClient,
BrowserServiceClient,
CheckpointsServiceClient,
FileServiceClient,
McpServiceClient,
StateServiceClient,
TaskServiceClient,
WebServiceClient,
ModelsServiceClient,
SlashServiceClient,
UiServiceClient,
}
+51 -12
View File
@@ -27,19 +27,50 @@ export const DEFAULT_SLASH_COMMANDS: SlashCommand[] = [
},
]
export function getWorkflowCommands(workflowToggles: Record<string, boolean>): SlashCommand[] {
return Object.entries(workflowToggles)
export function getWorkflowCommands(
localWorkflowToggles: Record<string, boolean>,
globalWorkflowToggles: Record<string, boolean>,
): SlashCommand[] {
const { workflows: localWorkflows, nameSet: localWorkflowNames } = Object.entries(localWorkflowToggles)
.filter(([_, enabled]) => enabled)
.map(([filePath, _]) => {
// potentially remove the file extension if there is one, but this would then require
// that we prevent users from having the same fname with different extensions
.reduce(
(acc, [filePath, _]) => {
const fileName = filePath.replace(/^.*[/\\]/, "")
// Add to array of workflows
acc.workflows.push({
name: fileName,
section: "custom",
} as SlashCommand)
// Add to set of names
acc.nameSet.add(fileName)
return acc
},
{ workflows: [] as SlashCommand[], nameSet: new Set<string>() },
)
const globalWorkflows = Object.entries(globalWorkflowToggles)
.filter(([_, enabled]) => enabled)
.flatMap(([filePath, _]) => {
const fileName = filePath.replace(/^.*[/\\]/, "")
return {
name: fileName,
section: "custom",
// skip if a local workflow with the same name exists
if (localWorkflowNames.has(fileName)) {
return []
}
return [
{
name: fileName,
section: "custom",
},
] as SlashCommand[]
})
const workflows = [...localWorkflows, ...globalWorkflows]
return workflows
}
// Regex for detecting slash commands in text
@@ -102,8 +133,12 @@ export function shouldShowSlashCommandsMenu(text: string, cursorPosition: number
/**
* Gets filtered slash commands that match the current input
*/
export function getMatchingSlashCommands(query: string, workflowToggles: Record<string, boolean> = {}): SlashCommand[] {
const workflowCommands = getWorkflowCommands(workflowToggles)
export function getMatchingSlashCommands(
query: string,
localWorkflowToggles: Record<string, boolean> = {},
globalWorkflowToggles: Record<string, boolean> = {},
): SlashCommand[] {
const workflowCommands = getWorkflowCommands(localWorkflowToggles, globalWorkflowToggles)
const allCommands = [...DEFAULT_SLASH_COMMANDS, ...workflowCommands]
if (!query) {
@@ -134,12 +169,16 @@ export function insertSlashCommand(text: string, commandName: string): { newValu
* Determines the validation state of a slash command
* Returns partial if we have a partial match against valid commands, or full for full match
*/
export function validateSlashCommand(command: string, workflowToggles: Record<string, boolean> = {}): "full" | "partial" | null {
export function validateSlashCommand(
command: string,
localWorkflowToggles: Record<string, boolean> = {},
globalWorkflowToggles: Record<string, boolean> = {},
): "full" | "partial" | null {
if (!command) {
return null
}
const workflowCommands = getWorkflowCommands(workflowToggles)
const workflowCommands = getWorkflowCommands(localWorkflowToggles, globalWorkflowToggles)
const allCommands = [...DEFAULT_SLASH_COMMANDS, ...workflowCommands]
// case sensitive matching