mirror of
https://github.com/cline/cline.git
synced 2026-09-02 15:52:29 +08:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6ffba23d3d | |||
| b3abbd886e | |||
| 8cdc4a936d | |||
| ecc58178dc | |||
| ca3f0f1abd | |||
| 987812a886 | |||
| 0e6afd9848 | |||
| 359e0e070d | |||
| b02ad8377d | |||
| 8fdf5ab8c5 | |||
| aceaeb069b | |||
| e39e58b5e2 | |||
| 717be3f026 | |||
| 5595d12dc3 | |||
| c230de0a14 | |||
| 2ecb87ac5a | |||
| 2315fc6769 | |||
| 6449c36849 | |||
| 8f93e9cc40 | |||
| 3a52baac14 | |||
| 35f08731f6 | |||
| 2c866c9265 | |||
| 10cfd8ba1e | |||
| da4d88fd84 | |||
| 889ed95840 | |||
| 716e6cd6ab | |||
| 45871a962e | |||
| c6aa47095e | |||
| 8c1093cfdc | |||
| 31161f894b | |||
| 20e5ae7b23 | |||
| 22f306e79e | |||
| 553b56336c | |||
| a3fa8cf7b9 | |||
| 4628eca3dc | |||
| 518e624086 | |||
| fa4fa01ec3 | |||
| f526317796 | |||
| 550883df6a | |||
| 3d5605f5d7 |
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
fix showing the ai core exisiting models when resource group field is empty (using the default resource group)
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Fix issue on Account view where balance is fetched twice that cause janky UI
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Fixes an issue where thinking text from litellm was not being passed through to Cline thinking UI
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Add search functionality to API provider dropdown
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Improve Gemini Rate Limit handling
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
fix: Support Anthropic Caching when using LiteLLM
|
||||
+2
-1
@@ -10,5 +10,6 @@
|
||||
"source-map-support/register",
|
||||
"./src/test/requires.ts"
|
||||
],
|
||||
"recursive": true
|
||||
"recursive": true,
|
||||
"exit": true
|
||||
}
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# Changelog
|
||||
|
||||
## [3.27.0]
|
||||
|
||||
- Fix `grok-code-fast-1` model information
|
||||
- Add call to action for trying free `grok-code-fast-1` in Announcement banner
|
||||
|
||||
## [3.26.7]
|
||||
|
||||
- Add 200k context window variant for Claude Sonnet 4 to OpenRouter and Cline providers
|
||||
|
||||
## [3.26.6]
|
||||
|
||||
- Add free Grok Coder model to Cline provider for users looking for a fast, free coding model option
|
||||
|
||||
@@ -30,9 +30,9 @@ English | <a href="https://github.com/cline/cline/blob/main/locales/es/README.md
|
||||
</table>
|
||||
</div>
|
||||
|
||||
Meet Cline (pronounced /klaɪn/, like "Klein"), an AI assistant that can use your **CLI** a**N**d **E**ditor.
|
||||
Meet Cline, an AI assistant that can use your **CLI** a**N**d **E**ditor.
|
||||
|
||||
Thanks to [Claude 3.7 Sonnet's agentic coding capabilities](https://www.anthropic.com/claude/sonnet), Cline can handle complex software development tasks step-by-step. With tools that let him create & edit files, explore large projects, use the browser, and execute terminal commands (after you grant permission), he can assist you in ways that go beyond code completion or tech support. Cline can even use the Model Context Protocol (MCP) to create new tools and extend his own capabilities. While autonomous AI scripts traditionally run in sandboxed environments, this extension provides a human-in-the-loop GUI to approve every file change and terminal command, providing a safe and accessible way to explore the potential of agentic AI.
|
||||
Thanks to [Claude Sonnet's agentic coding capabilities](https://www.anthropic.com/claude/sonnet), Cline can handle complex software development tasks step-by-step. With tools that let him create & edit files, explore large projects, use the browser, and execute terminal commands (after you grant permission), he can assist you in ways that go beyond code completion or tech support. Cline can even use the Model Context Protocol (MCP) to create new tools and extend his own capabilities. While autonomous AI scripts traditionally run in sandboxed environments, this extension provides a human-in-the-loop GUI to approve every file change and terminal command, providing a safe and accessible way to explore the potential of agentic AI.
|
||||
|
||||
1. Enter your task and add images to convert mockups into functional apps or fix bugs with screenshots.
|
||||
2. Cline starts by analyzing your file structure & source code ASTs, running regex searches, and reading relevant files to get up to speed in existing projects. By carefully managing what information is added to context, Cline can provide valuable assistance even for large, complex projects without overwhelming the context window.
|
||||
@@ -87,7 +87,7 @@ All changes made by Cline are recorded in your file's Timeline, providing an eas
|
||||
|
||||
### Use the Browser
|
||||
|
||||
With Claude 3.5 Sonnet's new [Computer Use](https://www.anthropic.com/news/3-5-models-and-computer-use) capability, Cline can launch a browser, click elements, type text, and scroll, capturing screenshots and console logs at each step. This allows for interactive debugging, end-to-end testing, and even general web use! This gives him autonomy to fixing visual bugs and runtime issues without you needing to handhold and copy-pasting error logs yourself.
|
||||
With Claude Sonnet's new [Computer Use](https://www.anthropic.com/news/3-5-models-and-computer-use) capability, Cline can launch a browser, click elements, type text, and scroll, capturing screenshots and console logs at each step. This allows for interactive debugging, end-to-end testing, and even general web use! This gives him autonomy to fixing visual bugs and runtime issues without you needing to handhold and copy-pasting error logs yourself.
|
||||
|
||||
Try asking Cline to "test the app", and watch as he runs a command like `npm run dev`, launches your locally running dev server in a browser, and performs a series of tests to confirm that everything works. [See a demo here.](https://x.com/sdrzn/status/1850880547825823989)
|
||||
|
||||
|
||||
+2
-1
@@ -37,7 +37,8 @@
|
||||
"useYield": "off",
|
||||
"noConstructorReturn": "off",
|
||||
"noInvalidPositionAtImportRule": "off",
|
||||
"noSwitchDeclarations": "off"
|
||||
"noSwitchDeclarations": "off",
|
||||
"noUnusedImports": "error"
|
||||
},
|
||||
"a11y": "off",
|
||||
"style": {
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
"getting-started/what-is-cline",
|
||||
"getting-started/model-selection-guide",
|
||||
"getting-started/installing-cline",
|
||||
"getting-started/installing-cline-jetbrains",
|
||||
"getting-started/task-management",
|
||||
"getting-started/understanding-context-management",
|
||||
{
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
---
|
||||
title: "Installing Cline for JetBrains"
|
||||
description: "Get Cline running in your favorite JetBrains IDE with the same powerful AI assistance you know from VSCode."
|
||||
---
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/jetbrains-logo.svg"
|
||||
alt="JetBrains logo"
|
||||
style={{ width: "200px", height: "auto", margin: "0 auto 20px auto", display: "block" }}
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
Cline for JetBrains works almost identically to Cline in VSCode. All the core features work properly: diff editing, using tools, logging in with different providers, MCP servers, Cline rules and workflows, and more.
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/jetbrains-demo-hifi.gif"
|
||||
alt="Cline running in JetBrains IDE showing AI assistance"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
<Note>Cline for JetBrains is currently in alpha. While all core features are functional, you may encounter occasional issues.</Note>
|
||||
|
||||
## Installation
|
||||
|
||||
Since Cline for JetBrains is currently in alpha, it's not yet available on the JetBrains Marketplace. You'll need to install it manually from a downloaded file:
|
||||
|
||||
### Manual Installation from Disk
|
||||
|
||||
1. **Download the Plugin:**
|
||||
- Go to [https://plugins.jetbrains.com/plugin/28247-cline/versions/stable](https://plugins.jetbrains.com/plugin/28247-cline/versions/stable)
|
||||
- Click **Download** to get the `.zip` file
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/cline-jetbrains-marketplace-download.png"
|
||||
alt="JetBrains plugin marketplace showing Cline download page"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
2. **Install from Disk:**
|
||||
- Open your JetBrains IDE
|
||||
- Go to **IntelliJ IDEA** (or whichever IDE you are in) → **Settings**
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/cline-jetbrains-settings.png"
|
||||
alt="JetBrains IDE settings dialog"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
- Select **Plugins** from the left sidebar
|
||||
- Click the gear icon ⚙️ and select **Install Plugin from Disk...**
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/cline-jetbrains-install-disk.png"
|
||||
alt="JetBrains IDE settings showing Install Plugin from Disk option"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
- Select the downloaded `.zip` file
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/cline-jetbrains-zip-file.png"
|
||||
alt="File selection dialog showing Cline plugin zip file"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
- Restart your IDE when prompted
|
||||
|
||||
## Getting Started with Cline
|
||||
|
||||
After installation, you'll find Cline in your IDE:
|
||||
|
||||
1. **Open Cline:**
|
||||
- Look for the Cline tool window (usually on the right side)
|
||||
- Or go to **View** → **Tool Windows** → **Cline**
|
||||
|
||||
2. **Sign In (optional, BYOK is also available):**
|
||||
- Click **Sign In** in the Cline panel
|
||||
- You'll be taken to [app.cline.bot](https://app.cline.bot) to create your account
|
||||
- No credit card needed to get started with free credits
|
||||
|
||||
3. **Start Coding:**
|
||||
- Try this first prompt: "Hey Cline! Can you help me create a simple Hello World program in this project?"
|
||||
|
||||
## Key Differences from VSCode
|
||||
|
||||
While Cline for JetBrains includes all the same powerful features, there's one important difference to be aware of:
|
||||
|
||||
**Terminal Integration:** The terminal inside JetBrains isn't integrated with Cline the same way it is in VSCode. Cline can execute commands, but the output will only appear in the webview if you expand the **Command Output** section.
|
||||
|
||||
This means:
|
||||
- Commands still run successfully
|
||||
- You can see the output by clicking to expand Command Output in the chat
|
||||
- Terminal commands work the same way, just with a different display
|
||||
|
||||
## What Works
|
||||
|
||||
Everything else works exactly like VSCode:
|
||||
|
||||
- **Diff Editing:** Cline can read, write, and edit files with the same precision
|
||||
- **Tool Usage:** All of Cline's tools (file operations, web browsing, etc.) work identically
|
||||
- **API Providers:** Connect to Anthropic, OpenAI, local models, and more
|
||||
- **MCP Servers:** Full support for Model Context Protocol servers
|
||||
- **Cline Rules:** Custom instructions and workflows work the same way
|
||||
- **@ Mentions:** Reference files, folders, problems, and more
|
||||
- **Drag & Drop:** Add files and images to conversations
|
||||
|
||||
## Tips for JetBrains Users
|
||||
|
||||
- **Project Context:** Cline automatically understands your project structure, just like in VSCode
|
||||
- **Language Support:** Cline works with any language your JetBrains IDE supports
|
||||
- **Debugging Help:** Share error messages and stack traces directly in the chat
|
||||
- **Code Review:** Ask Cline to review your code changes before committing
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you don't see the Cline tool window after installation:
|
||||
- Restart your IDE completely
|
||||
- Check **View** → **Tool Windows** → **Cline**
|
||||
- Ensure the plugin is enabled in **Settings** → **Plugins**
|
||||
|
||||
Having other issues? Join our [Discord community](https://discord.gg/cline) for help from the team and other users.
|
||||
|
||||
## Next Steps
|
||||
|
||||
Now that you have Cline installed, you might want to:
|
||||
- Learn about [model selection](/getting-started/model-selection-guide) to choose the best AI provider
|
||||
- Explore [@ mentions](/features/at-mentions/overview) to reference files and context efficiently
|
||||
- Set up [Cline rules](/features/cline-rules) for your specific workflow
|
||||
- Try [MCP servers](/mcp/mcp-overview) to extend Cline's capabilities
|
||||
Generated
+25
-12
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "claude-dev",
|
||||
"version": "3.26.6",
|
||||
"version": "3.27.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "claude-dev",
|
||||
"version": "3.26.6",
|
||||
"version": "3.27.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.37.0",
|
||||
@@ -16,7 +16,7 @@
|
||||
"@bufbuild/protobuf": "^2.2.5",
|
||||
"@cerebras/cerebras_cloud_sdk": "^1.35.0",
|
||||
"@google-cloud/vertexai": "^1.9.3",
|
||||
"@google/genai": "1.0.0",
|
||||
"@google/genai": "^1.11.0",
|
||||
"@grpc/grpc-js": "^1.9.15",
|
||||
"@grpc/reflection": "^1.0.4",
|
||||
"@mistralai/mistralai": "^1.5.0",
|
||||
@@ -66,7 +66,7 @@
|
||||
"p-timeout": "^6.1.4",
|
||||
"p-wait-for": "^5.0.2",
|
||||
"pdf-parse": "^1.1.1",
|
||||
"posthog-node": "^4.8.1",
|
||||
"posthog-node": "^5.8.0",
|
||||
"puppeteer-chromium-resolver": "^23.0.0",
|
||||
"puppeteer-core": "^23.4.0",
|
||||
"reconnecting-eventsource": "^1.6.4",
|
||||
@@ -2531,19 +2531,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@google/genai": {
|
||||
"version": "1.0.0",
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.15.0.tgz",
|
||||
"integrity": "sha512-4CSW+hRTESWl3xVtde7pkQ3E+dDFhDq+m4ztmccRctZfx1gKy3v0M9STIMGk6Nq0s6O2uKMXupOZQ1JGorXVwQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"google-auth-library": "^9.14.2",
|
||||
"ws": "^8.18.0",
|
||||
"zod": "^3.22.4",
|
||||
"zod-to-json-schema": "^3.22.4"
|
||||
"ws": "^8.18.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.11.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@modelcontextprotocol/sdk": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@grpc/grpc-js": {
|
||||
@@ -3685,6 +3690,12 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@posthog/core": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.0.1.tgz",
|
||||
"integrity": "sha512-bwXUeHe+MLgENm8+/FxEbiNocOw1Vjewmm+HEUaYQe6frq8OhZnrvtnzZU3Q3DF6N0UbAmD/q+iNfNgyx8mozg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@protobufjs/aspromise": {
|
||||
"version": "1.1.2",
|
||||
"license": "BSD-3-Clause"
|
||||
@@ -12387,13 +12398,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/posthog-node": {
|
||||
"version": "4.8.1",
|
||||
"version": "5.8.0",
|
||||
"resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-5.8.0.tgz",
|
||||
"integrity": "sha512-Idj6TgjYN0POXvrGK97ZKTLbLEY7sUjsaeMaquKt9UlK3Z9ps0nj0wRkFYKEYvfQ8OMwTwgKaze+5hXgmudwdw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"axios": "^1.7.4"
|
||||
"@posthog/core": "1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=15.0.0"
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/prebuild-install": {
|
||||
|
||||
+5
-12
@@ -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.26.6",
|
||||
"version": "3.27.0",
|
||||
"icon": "assets/icons/icon.png",
|
||||
"engines": {
|
||||
"vscode": "^1.84.0"
|
||||
@@ -102,15 +102,8 @@
|
||||
"activitybar": [
|
||||
{
|
||||
"id": "claude-dev-ActivityBar",
|
||||
"title": "Cline (⌘+')",
|
||||
"icon": "assets/icons/icon.svg",
|
||||
"when": "isMac"
|
||||
},
|
||||
{
|
||||
"id": "claude-dev-ActivityBar",
|
||||
"title": "Cline (Ctrl+')",
|
||||
"icon": "assets/icons/icon.svg",
|
||||
"when": "!isMac"
|
||||
"title": "Cline",
|
||||
"icon": "assets/icons/icon.svg"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -431,7 +424,7 @@
|
||||
"@bufbuild/protobuf": "^2.2.5",
|
||||
"@cerebras/cerebras_cloud_sdk": "^1.35.0",
|
||||
"@google-cloud/vertexai": "^1.9.3",
|
||||
"@google/genai": "1.0.0",
|
||||
"@google/genai": "^1.11.0",
|
||||
"@grpc/grpc-js": "^1.9.15",
|
||||
"@grpc/reflection": "^1.0.4",
|
||||
"@mistralai/mistralai": "^1.5.0",
|
||||
@@ -479,7 +472,7 @@
|
||||
"p-timeout": "^6.1.4",
|
||||
"p-wait-for": "^5.0.2",
|
||||
"pdf-parse": "^1.1.1",
|
||||
"posthog-node": "^4.8.1",
|
||||
"posthog-node": "^5.8.0",
|
||||
"puppeteer-chromium-resolver": "^23.0.0",
|
||||
"puppeteer-core": "^23.4.0",
|
||||
"reconnecting-eventsource": "^1.6.4",
|
||||
|
||||
+12
-12
@@ -50,20 +50,20 @@ message LanguageModelChatSelector {
|
||||
|
||||
// Price tier for tiered pricing models
|
||||
message PriceTier {
|
||||
int32 token_limit = 1; // Upper limit (inclusive) of input tokens for this price
|
||||
int64 token_limit = 1; // Upper limit (inclusive) of input tokens for this price
|
||||
double price = 2; // Price per million tokens for this tier
|
||||
}
|
||||
|
||||
// Thinking configuration for models that support thinking/reasoning
|
||||
message ThinkingConfig {
|
||||
optional int32 max_budget = 1; // Max allowed thinking budget tokens
|
||||
optional int64 max_budget = 1; // Max allowed thinking budget tokens
|
||||
optional double output_price = 2; // Output price per million tokens when budget > 0
|
||||
repeated PriceTier output_price_tiers = 3; // Optional: Tiered output price when budget > 0
|
||||
}
|
||||
|
||||
// Model tier for tiered pricing structures
|
||||
message ModelTier {
|
||||
int32 context_window = 1;
|
||||
int64 context_window = 1;
|
||||
optional double input_price = 2;
|
||||
optional double output_price = 3;
|
||||
optional double cache_writes_price = 4;
|
||||
@@ -161,8 +161,8 @@ enum ApiProvider {
|
||||
|
||||
// Model info for OpenAI-compatible models
|
||||
message OpenAiCompatibleModelInfo {
|
||||
optional int32 max_tokens = 1;
|
||||
optional int32 context_window = 2;
|
||||
optional int64 max_tokens = 1;
|
||||
optional int64 context_window = 2;
|
||||
optional bool supports_images = 3;
|
||||
bool supports_prompt_cache = 4;
|
||||
optional double input_price = 5;
|
||||
@@ -179,8 +179,8 @@ message OpenAiCompatibleModelInfo {
|
||||
|
||||
// Model info for LiteLLM models
|
||||
message LiteLLMModelInfo {
|
||||
optional int32 max_tokens = 1;
|
||||
optional int32 context_window = 2;
|
||||
optional int64 max_tokens = 1;
|
||||
optional int64 context_window = 2;
|
||||
optional bool supports_images = 3;
|
||||
bool supports_prompt_cache = 4;
|
||||
optional double input_price = 5;
|
||||
@@ -232,8 +232,8 @@ message ModelsApiConfiguration {
|
||||
optional string requesty_base_url = 33;
|
||||
optional string together_api_key = 34;
|
||||
optional string fireworks_api_key = 35;
|
||||
optional int32 fireworks_model_max_completion_tokens = 36;
|
||||
optional int32 fireworks_model_max_tokens = 37;
|
||||
optional int64 fireworks_model_max_completion_tokens = 36;
|
||||
optional int64 fireworks_model_max_tokens = 37;
|
||||
optional string qwen_api_key = 38;
|
||||
optional string doubao_api_key = 39;
|
||||
optional string mistral_api_key = 40;
|
||||
@@ -245,7 +245,7 @@ message ModelsApiConfiguration {
|
||||
optional string xai_api_key = 46;
|
||||
optional string sambanova_api_key = 47;
|
||||
optional string cerebras_api_key = 48;
|
||||
optional int32 request_timeout_ms = 49;
|
||||
optional int64 request_timeout_ms = 49;
|
||||
optional string sap_ai_core_client_id = 50;
|
||||
optional string sap_ai_core_client_secret = 51;
|
||||
optional string sap_ai_resource_group = 52;
|
||||
@@ -273,7 +273,7 @@ message ModelsApiConfiguration {
|
||||
// Plan mode configurations
|
||||
optional ApiProvider plan_mode_api_provider = 100;
|
||||
optional string plan_mode_api_model_id = 101;
|
||||
optional int32 plan_mode_thinking_budget_tokens = 102;
|
||||
optional int64 plan_mode_thinking_budget_tokens = 102;
|
||||
optional string plan_mode_reasoning_effort = 103;
|
||||
optional LanguageModelChatSelector plan_mode_vs_code_lm_model_selector = 104;
|
||||
optional bool plan_mode_aws_bedrock_custom_selected = 105;
|
||||
@@ -305,7 +305,7 @@ message ModelsApiConfiguration {
|
||||
// Act mode configurations
|
||||
optional ApiProvider act_mode_api_provider = 200;
|
||||
optional string act_mode_api_model_id = 201;
|
||||
optional int32 act_mode_thinking_budget_tokens = 202;
|
||||
optional int64 act_mode_thinking_budget_tokens = 202;
|
||||
optional string act_mode_reasoning_effort = 203;
|
||||
optional LanguageModelChatSelector act_mode_vs_code_lm_model_selector = 204;
|
||||
optional bool act_mode_aws_bedrock_custom_selected = 205;
|
||||
|
||||
@@ -26,6 +26,9 @@ service WorkspaceService {
|
||||
|
||||
// Opens the IDE file explorer panel and selects a file or directory.
|
||||
rpc openInFileExplorerPanel(OpenInFileExplorerPanelRequest) returns (OpenInFileExplorerPanelResponse);
|
||||
|
||||
// Opens and focuses the Cline sidebar panel in the host IDE.
|
||||
rpc openClineSidebarPanel(OpenClineSidebarPanelRequest) returns (OpenClineSidebarPanelResponse);
|
||||
}
|
||||
|
||||
message GetWorkspacePathsRequest {
|
||||
@@ -86,3 +89,7 @@ message OpenInFileExplorerPanelRequest {
|
||||
string path = 1;
|
||||
}
|
||||
message OpenInFileExplorerPanelResponse {}
|
||||
|
||||
// Request/response for opening the Cline sidebar
|
||||
message OpenClineSidebarPanelRequest {}
|
||||
message OpenClineSidebarPanelResponse {}
|
||||
|
||||
+17
-16
@@ -1,19 +1,22 @@
|
||||
import * as vscode from "vscode"
|
||||
import {
|
||||
migrateCustomInstructionsToGlobalRules,
|
||||
migrateTaskHistoryToFile,
|
||||
migrateWelcomeViewCompleted,
|
||||
migrateWorkspaceToGlobalStorage,
|
||||
} from "./core/storage/state-migrations"
|
||||
import { WebviewProvider } from "./core/webview"
|
||||
import { Logger } from "./services/logging/Logger"
|
||||
import { PostHogClientProvider } from "./services/posthog/PostHogClientProvider"
|
||||
import { EmptyRequest } from "./shared/proto/cline/common"
|
||||
import { WebviewProviderType } from "./shared/webview/types"
|
||||
import "./utils/path" // necessary to have access to String.prototype.toPosix
|
||||
|
||||
import { HostProvider } from "@/hosts/host-provider"
|
||||
import { FileContextTracker } from "./core/context/context-tracking/FileContextTracker"
|
||||
import { telemetryService } from "./services/posthog/PostHogClientProvider"
|
||||
import { errorService } from "./services/error"
|
||||
import { featureFlagsService } from "./services/feature-flags"
|
||||
import { initializeDistinctId } from "./services/logging/distinctId"
|
||||
import { PostHogClientProvider } from "./services/posthog/PostHogClientProvider"
|
||||
import { telemetryService } from "./services/telemetry"
|
||||
import { ShowMessageType } from "./shared/proto/host/window"
|
||||
import { getLatestAnnouncementId } from "./utils/announcements"
|
||||
/**
|
||||
@@ -23,18 +26,11 @@ import { getLatestAnnouncementId } from "./utils/announcements"
|
||||
* @returns The webview provider
|
||||
*/
|
||||
export async function initialize(context: vscode.ExtensionContext): Promise<WebviewProvider> {
|
||||
// Set the distinct ID for logging and telemetry
|
||||
await initializeDistinctId(context)
|
||||
|
||||
// Initialize PostHog client provider
|
||||
let distinctId = context.globalState.get<string>("cline.distinctId")
|
||||
if (!distinctId) {
|
||||
try {
|
||||
const response = await HostProvider.env.getMachineId(EmptyRequest.create({}))
|
||||
distinctId = response.value
|
||||
} catch (e) {
|
||||
Logger.warn(`Failed to get machine ID: ${e instanceof Error ? e.message : String(e)}`)
|
||||
// PostHogProvider will fall back to uuid
|
||||
}
|
||||
}
|
||||
PostHogClientProvider.getInstance(distinctId)
|
||||
PostHogClientProvider.getInstance()
|
||||
|
||||
// Migrate custom instructions to global Cline rules (one-time cleanup)
|
||||
await migrateCustomInstructionsToGlobalRules(context)
|
||||
@@ -45,6 +41,9 @@ export async function initialize(context: vscode.ExtensionContext): Promise<Webv
|
||||
// Migrate workspace storage values back to global storage (reverting previous migration)
|
||||
await migrateWorkspaceToGlobalStorage(context)
|
||||
|
||||
// Ensure taskHistory.json exists and migrate legacy state (runs once)
|
||||
await migrateTaskHistoryToFile(context)
|
||||
|
||||
// Clean up orphaned file context warnings (startup cleanup)
|
||||
await FileContextTracker.cleanupOrphanedWarnings(context)
|
||||
|
||||
@@ -75,7 +74,7 @@ async function showVersionUpdateAnnouncement(context: vscode.ExtensionContext) {
|
||||
const message = previousVersion
|
||||
? `Cline has been updated to v${currentVersion}`
|
||||
: `Welcome to Cline v${currentVersion}`
|
||||
await vscode.commands.executeCommand("claude-dev.SidebarProvider.focus")
|
||||
await HostProvider.workspace.openClineSidebarPanel({})
|
||||
await new Promise((resolve) => setTimeout(resolve, 200))
|
||||
HostProvider.window.showMessage({
|
||||
type: ShowMessageType.INFORMATION,
|
||||
@@ -96,7 +95,9 @@ async function showVersionUpdateAnnouncement(context: vscode.ExtensionContext) {
|
||||
*/
|
||||
export async function tearDown(): Promise<void> {
|
||||
PostHogClientProvider.getInstance().dispose()
|
||||
|
||||
telemetryService.dispose()
|
||||
errorService.dispose()
|
||||
featureFlagsService.dispose()
|
||||
// Dispose all webview instances
|
||||
await WebviewProvider.disposeAllInstances()
|
||||
}
|
||||
|
||||
@@ -210,6 +210,7 @@ function createHandlerForProvider(
|
||||
})
|
||||
case "qwen-code":
|
||||
return new QwenCodeHandler({
|
||||
onRetryAttempt: options.onRetryAttempt,
|
||||
qwenCodeOauthPath: options.qwenCodeOauthPath,
|
||||
apiModelId: mode === "plan" ? options.planModeApiModelId : options.actModeApiModelId,
|
||||
})
|
||||
@@ -312,6 +313,7 @@ function createHandlerForProvider(
|
||||
})
|
||||
case "baseten":
|
||||
return new BasetenHandler({
|
||||
onRetryAttempt: options.onRetryAttempt,
|
||||
basetenApiKey: options.basetenApiKey,
|
||||
basetenModelId: mode === "plan" ? options.planModeBasetenModelId : options.actModeBasetenModelId,
|
||||
basetenModelInfo: mode === "plan" ? options.planModeBasetenModelInfo : options.actModeBasetenModelInfo,
|
||||
@@ -341,6 +343,7 @@ function createHandlerForProvider(
|
||||
})
|
||||
case "huawei-cloud-maas":
|
||||
return new HuaweiCloudMaaSHandler({
|
||||
onRetryAttempt: options.onRetryAttempt,
|
||||
huaweiCloudMaasApiKey: options.huaweiCloudMaasApiKey,
|
||||
huaweiCloudMaasModelId:
|
||||
mode === "plan" ? options.planModeHuaweiCloudMaasModelId : options.actModeHuaweiCloudMaasModelId,
|
||||
@@ -358,6 +361,7 @@ function createHandlerForProvider(
|
||||
})
|
||||
case "vercel-ai-gateway":
|
||||
return new VercelAIGatewayHandler({
|
||||
onRetryAttempt: options.onRetryAttempt,
|
||||
vercelAiGatewayApiKey: options.vercelAiGatewayApiKey,
|
||||
vercelAiGatewayModelId:
|
||||
mode === "plan" ? options.planModeVercelAiGatewayModelId : options.actModeVercelAiGatewayModelId,
|
||||
@@ -366,6 +370,7 @@ function createHandlerForProvider(
|
||||
})
|
||||
case "zai":
|
||||
return new ZAiHandler({
|
||||
onRetryAttempt: options.onRetryAttempt,
|
||||
zaiApiLine: options.zaiApiLine,
|
||||
zaiApiKey: options.zaiApiKey,
|
||||
apiModelId: mode === "plan" ? options.planModeApiModelId : options.actModeApiModelId,
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
import Anthropic from "@anthropic-ai/sdk"
|
||||
import { LiteLlmHandler, type LiteLlmModelInfoResponse } from "@core/api/providers/litellm"
|
||||
import { convertToOpenAiMessages } from "@core/api/transform/openai-format"
|
||||
import { expect } from "chai"
|
||||
import sinon from "sinon"
|
||||
|
||||
const fakeClient = {
|
||||
chat: {
|
||||
completions: {
|
||||
create: sinon.stub(),
|
||||
},
|
||||
},
|
||||
baseURL: "fake",
|
||||
}
|
||||
|
||||
describe("LiteLlmHandler", () => {
|
||||
const originalFetch = global.fetch
|
||||
const mockFetch = sinon.stub()
|
||||
|
||||
const mockModelFetch = (modelInfo: LiteLlmModelInfoResponse["data"][number]) => {
|
||||
mockFetch.resolves({
|
||||
ok: true,
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
data: [modelInfo],
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
let handler: LiteLlmHandler
|
||||
|
||||
const mockHandlerChat = () => {
|
||||
sinon.stub(handler, "ensureClient" as any).returns(fakeClient)
|
||||
}
|
||||
|
||||
const initializeHandler = (model: string) => {
|
||||
handler = new LiteLlmHandler({
|
||||
liteLlmApiKey: "test-api-key",
|
||||
liteLlmBaseUrl: "http://localhost:4000",
|
||||
liteLlmUsePromptCache: true,
|
||||
liteLlmModelId: model,
|
||||
})
|
||||
|
||||
mockHandlerChat()
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
global.fetch = mockFetch
|
||||
|
||||
// Configure the stub to return a stream that closes immediately with usage data
|
||||
fakeClient.chat.completions.create.resolves(
|
||||
createAsyncIterable([
|
||||
{
|
||||
choices: [{ delta: { content: "test response" } }],
|
||||
},
|
||||
{
|
||||
choices: [{}],
|
||||
usage: {
|
||||
prompt_tokens: 100,
|
||||
completion_tokens: 50,
|
||||
cache_creation_input_tokens: 20,
|
||||
cache_read_input_tokens: 10,
|
||||
},
|
||||
},
|
||||
]),
|
||||
)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
sinon.reset()
|
||||
|
||||
global.fetch = originalFetch
|
||||
})
|
||||
|
||||
const createAsyncIterable = (data: any[] = []) => {
|
||||
return {
|
||||
[Symbol.asyncIterator]: async function* () {
|
||||
yield* data
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
describe("prompt cache", () => {
|
||||
const setModelData = (model: string, supportsPromptCaching: boolean) => {
|
||||
mockModelFetch({
|
||||
model_name: model,
|
||||
litellm_params: {
|
||||
model,
|
||||
},
|
||||
model_info: {
|
||||
supports_prompt_caching: supportsPromptCaching,
|
||||
input_cost_per_token: 0.01,
|
||||
output_cost_per_token: 0.02,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
describe("when the model doesn't support prompt caching", () => {
|
||||
const model = "openai/gpt-5"
|
||||
|
||||
beforeEach(() => {
|
||||
initializeHandler(model)
|
||||
setModelData(model, false)
|
||||
})
|
||||
|
||||
it("sends the system prompt and messages with the openai format", async () => {
|
||||
const systemPrompt = "Test System Prompt"
|
||||
const messages: Anthropic.Messages.MessageParam[] = [
|
||||
{
|
||||
role: "user",
|
||||
content: "first message",
|
||||
},
|
||||
{
|
||||
role: "assistant",
|
||||
content: "first response",
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: "test",
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
text: "second message",
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
for await (const _ of handler.createMessage(systemPrompt, messages)) {
|
||||
}
|
||||
|
||||
sinon.assert.calledOnce(fakeClient.chat.completions.create)
|
||||
|
||||
const callArgs = fakeClient.chat.completions.create.getCall(0).args[0]
|
||||
|
||||
const systemPromptMessage = callArgs.messages.shift()
|
||||
expect(systemPromptMessage).to.deep.equal({
|
||||
role: "system",
|
||||
content: systemPrompt,
|
||||
})
|
||||
|
||||
expect(callArgs.messages).to.deep.equal(convertToOpenAiMessages(messages))
|
||||
})
|
||||
})
|
||||
|
||||
describe("when the model supports prompt caching", () => {
|
||||
const model = "anthropic/claude-sonnet-4-20250514"
|
||||
|
||||
beforeEach(() => {
|
||||
initializeHandler(model)
|
||||
|
||||
setModelData(model, true)
|
||||
})
|
||||
|
||||
it("inserts the cache control in the system prompt and the last two user messages", async () => {
|
||||
const systemPrompt = "Test System Prompt"
|
||||
const messages: Anthropic.Messages.MessageParam[] = [
|
||||
{
|
||||
role: "user",
|
||||
content: "first message",
|
||||
},
|
||||
{
|
||||
role: "assistant",
|
||||
content: "first response",
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: "test",
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
text: "second message",
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
for await (const _ of handler.createMessage(systemPrompt, messages)) {
|
||||
}
|
||||
|
||||
sinon.assert.calledOnce(fakeClient.chat.completions.create)
|
||||
|
||||
const callArgs = fakeClient.chat.completions.create.getCall(0).args[0]
|
||||
|
||||
expect(callArgs.messages[0]).to.deep.equal({
|
||||
role: "system",
|
||||
content: [
|
||||
{
|
||||
text: systemPrompt,
|
||||
type: "text",
|
||||
cache_control: {
|
||||
type: "ephemeral",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const sentMessages = callArgs.messages
|
||||
expect(sentMessages.length).to.equal(4)
|
||||
|
||||
const firstUserMessage = sentMessages[1]
|
||||
|
||||
expect(firstUserMessage).to.deep.equal({
|
||||
role: "user",
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: "first message",
|
||||
cache_control: {
|
||||
type: "ephemeral",
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const lastUserMessage = sentMessages[3]
|
||||
expect(lastUserMessage.content[0]).to.deep.equal({
|
||||
type: "text",
|
||||
text: "test",
|
||||
})
|
||||
|
||||
const lastContentBlock = lastUserMessage.content[lastUserMessage.content.length - 1]
|
||||
expect(lastContentBlock).to.deep.equal({
|
||||
type: "text",
|
||||
text: "second message",
|
||||
cache_control: {
|
||||
type: "ephemeral",
|
||||
},
|
||||
})
|
||||
|
||||
expect(callArgs.model).to.be.a("string")
|
||||
expect(callArgs.stream).to.equal(true)
|
||||
expect(callArgs.stream_options).to.deep.equal({ include_usage: true })
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -2,12 +2,12 @@ import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { BasetenModelId, basetenDefaultModelId, basetenModels, ModelInfo } from "@shared/api"
|
||||
import { calculateApiCostOpenAI } from "@utils/cost"
|
||||
import OpenAI from "openai"
|
||||
import { ApiHandler } from "../"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
import { convertToOpenAiMessages } from "../transform/openai-format"
|
||||
import { ApiStream } from "../transform/stream"
|
||||
|
||||
interface BasetenHandlerOptions {
|
||||
interface BasetenHandlerOptions extends CommonApiHandlerOptions {
|
||||
basetenApiKey?: string
|
||||
basetenModelId?: string
|
||||
basetenModelInfo?: ModelInfo
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import type { Anthropic } from "@anthropic-ai/sdk"
|
||||
// Restore GenerateContentConfig import and add GenerateContentResponseUsageMetadata
|
||||
import { type GenerateContentConfig, type GenerateContentResponseUsageMetadata, GoogleGenAI, Part } from "@google/genai"
|
||||
import { telemetryService } from "@services/posthog/PostHogClientProvider"
|
||||
import { ApiError, type GenerateContentConfig, type GenerateContentResponseUsageMetadata, GoogleGenAI, Part } from "@google/genai"
|
||||
import { GeminiModelId, geminiDefaultModelId, geminiModels, ModelInfo } from "@shared/api"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
import { RetriableError, withRetry } from "../retry"
|
||||
import { convertAnthropicMessageToGemini } from "../transform/gemini-format"
|
||||
import { ApiStream } from "../transform/stream"
|
||||
|
||||
// Define a default TTL for the cache (e.g., 15 minutes in seconds)
|
||||
const _DEFAULT_CACHE_TTL_SECONDS = 900
|
||||
|
||||
const rateLimitPatterns = [/got status: 429/i, /429 Too Many Requests/i, /rate limit exceeded/i, /too many requests/i]
|
||||
|
||||
interface GeminiHandlerOptions extends CommonApiHandlerOptions {
|
||||
isVertex?: boolean
|
||||
vertexProjectId?: string
|
||||
@@ -222,24 +224,40 @@ export class GeminiHandler implements ApiHandler {
|
||||
if (error instanceof Error) {
|
||||
apiError = error.message
|
||||
|
||||
// Gemini doesn't include status codes in their errors
|
||||
// https://github.com/googleapis/js-genai/blob/61f7f27b866c74333ca6331883882489bcb708b9/src/_api_client.ts#L569
|
||||
const rateLimitPatterns = [
|
||||
/got status: 429/i,
|
||||
/429 Too Many Requests/i,
|
||||
/rate limit exceeded/i,
|
||||
/too many requests/i,
|
||||
]
|
||||
if (error instanceof ApiError) {
|
||||
if (error.status === 429) {
|
||||
// The API includes more details in the message
|
||||
// https://github.com/googleapis/js-genai/blob/v1.11.0/src/_api_client.ts#L758
|
||||
const response = this.attemptParse(error.message)
|
||||
|
||||
const isRateLimit =
|
||||
error.name === "ClientError" && rateLimitPatterns.some((pattern) => pattern.test(error.message))
|
||||
if (response && response.error) {
|
||||
const responseBody = this.attemptParse(response.error.message)
|
||||
|
||||
if (isRateLimit) {
|
||||
const rateLimitError = Object.assign(new Error(error.message), {
|
||||
...error,
|
||||
status: 429,
|
||||
})
|
||||
throw rateLimitError
|
||||
if (responseBody.error) {
|
||||
const detail = responseBody.error.details?.find(
|
||||
(d: any) => d["@type"] === "type.googleapis.com/google.rpc.RetryInfo",
|
||||
)
|
||||
|
||||
const detailedError = new RetriableError(
|
||||
apiError,
|
||||
this.parseRetryDelay(detail?.retryDelay) || undefined,
|
||||
{
|
||||
cause: error,
|
||||
},
|
||||
)
|
||||
throw detailedError
|
||||
}
|
||||
}
|
||||
|
||||
throw new RetriableError(apiError, undefined, { cause: error })
|
||||
}
|
||||
|
||||
// Fallback in case Gemini throws a rate limit error without a 429 status code
|
||||
// https://github.com/cline/cline/pull/5205#discussion_r2311761559
|
||||
const isRateLimit = rateLimitPatterns.some((pattern) => pattern.test(error.message))
|
||||
if (isRateLimit) {
|
||||
throw new RetriableError(apiError, undefined, { cause: error })
|
||||
}
|
||||
}
|
||||
} else {
|
||||
apiError = String(error)
|
||||
@@ -420,4 +438,35 @@ export class GeminiHandler implements ApiHandler {
|
||||
|
||||
return Math.ceil(totalChars / 4)
|
||||
}
|
||||
|
||||
private parseRetryDelay(retryAfter?: string): number {
|
||||
if (!retryAfter) {
|
||||
return 0
|
||||
}
|
||||
|
||||
const unit = retryAfter.at(-1)
|
||||
const value = parseInt(retryAfter, 10)
|
||||
|
||||
if (Number.isNaN(value)) {
|
||||
return 0
|
||||
}
|
||||
|
||||
if (unit === "s") {
|
||||
return value
|
||||
} else if (unit === "m") {
|
||||
return value * 60 // Convert minutes to seconds
|
||||
} else if (unit === "h") {
|
||||
return value * 60 * 60 // Convert hours to seconds
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
private attemptParse(str: string) {
|
||||
try {
|
||||
return JSON.parse(str)
|
||||
} catch (_) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { HuaweiCloudMaasModelId, huaweiCloudMaasDefaultModelId, huaweiCloudMaasModels, ModelInfo } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import { ApiHandler } from ".."
|
||||
import { ApiHandler, CommonApiHandlerOptions } from ".."
|
||||
import { withRetry } from "../retry"
|
||||
import { convertToOpenAiMessages } from "../transform/openai-format"
|
||||
import { ApiStream } from "../transform/stream"
|
||||
|
||||
interface HuaweiCloudMaaSHandlerOptions {
|
||||
interface HuaweiCloudMaaSHandlerOptions extends CommonApiHandlerOptions {
|
||||
huaweiCloudMaasApiKey?: string
|
||||
huaweiCloudMaasModelId?: string
|
||||
huaweiCloudMaasModelInfo?: ModelInfo
|
||||
|
||||
@@ -16,7 +16,7 @@ interface LiteLlmHandlerOptions extends CommonApiHandlerOptions {
|
||||
ulid?: string
|
||||
}
|
||||
|
||||
interface LiteLlmModelInfoResponse {
|
||||
export interface LiteLlmModelInfoResponse {
|
||||
data: Array<{
|
||||
model_name: string
|
||||
litellm_params: {
|
||||
@@ -28,6 +28,7 @@ interface LiteLlmModelInfoResponse {
|
||||
output_cost_per_token: number
|
||||
cache_creation_input_token_cost?: number
|
||||
cache_read_input_token_cost?: number
|
||||
supports_prompt_caching?: boolean
|
||||
[key: string]: any
|
||||
}
|
||||
}>
|
||||
@@ -61,7 +62,17 @@ export class LiteLlmHandler implements ApiHandler {
|
||||
return this.client
|
||||
}
|
||||
|
||||
private async fetchModelInfo(): Promise<LiteLlmModelInfoResponse | undefined> {
|
||||
private async modelInfo(publicModelName: string): Promise<LiteLlmModelInfoResponse["data"][number] | undefined> {
|
||||
const modelInfo = await this.fetchModelsInfo()
|
||||
|
||||
if (!modelInfo?.data) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return modelInfo.data.find((model) => model.model_name === publicModelName)
|
||||
}
|
||||
|
||||
private async fetchModelsInfo(): Promise<LiteLlmModelInfoResponse | undefined> {
|
||||
// Check if cache is still valid
|
||||
const now = Date.now()
|
||||
if (this.modelInfoCache && now - this.modelInfoCacheTimestamp < this.modelInfoCacheTTL) {
|
||||
@@ -121,19 +132,14 @@ export class LiteLlmHandler implements ApiHandler {
|
||||
cacheReadCostPerToken?: number
|
||||
}> {
|
||||
try {
|
||||
const modelInfo = await this.fetchModelInfo()
|
||||
const matchingModel = await this.modelInfo(publicModelName)
|
||||
|
||||
if (modelInfo?.data) {
|
||||
// Find the model by public name
|
||||
const matchingModel = modelInfo.data.find((model) => model.model_name === publicModelName)
|
||||
|
||||
if (matchingModel?.model_info) {
|
||||
return {
|
||||
inputCostPerToken: matchingModel.model_info.input_cost_per_token || 0,
|
||||
outputCostPerToken: matchingModel.model_info.output_cost_per_token || 0,
|
||||
cacheCreationCostPerToken: matchingModel.model_info.cache_creation_input_token_cost,
|
||||
cacheReadCostPerToken: matchingModel.model_info.cache_read_input_token_cost,
|
||||
}
|
||||
if (matchingModel) {
|
||||
return {
|
||||
inputCostPerToken: matchingModel.model_info.input_cost_per_token || 0,
|
||||
outputCostPerToken: matchingModel.model_info.output_cost_per_token || 0,
|
||||
cacheCreationCostPerToken: matchingModel.model_info.cache_creation_input_token_cost,
|
||||
cacheReadCostPerToken: matchingModel.model_info.cache_read_input_token_cost,
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -177,7 +183,7 @@ export class LiteLlmHandler implements ApiHandler {
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const formattedMessages = convertToOpenAiMessages(messages)
|
||||
const systemMessage: OpenAI.Chat.ChatCompletionSystemMessageParam = {
|
||||
const systemMessage: OpenAI.Chat.ChatCompletionSystemMessageParam | Anthropic.Messages.TextBlockParam = {
|
||||
role: "system",
|
||||
content: systemPrompt,
|
||||
}
|
||||
@@ -195,13 +201,22 @@ export class LiteLlmHandler implements ApiHandler {
|
||||
temperature = undefined // Thinking mode doesn't support temperature
|
||||
}
|
||||
|
||||
// Define cache control object if prompt caching is enabled
|
||||
const cacheControl = this.options.liteLlmUsePromptCache ? { cache_control: { type: "ephemeral" } } : undefined
|
||||
const modelInfo = await this.modelInfo(modelId)
|
||||
const cacheControl =
|
||||
this.options.liteLlmUsePromptCache && Boolean(modelInfo?.model_info.supports_prompt_caching)
|
||||
? { cache_control: { type: "ephemeral" } }
|
||||
: undefined
|
||||
|
||||
// Add cache_control to system message if enabled
|
||||
const enhancedSystemMessage = {
|
||||
...systemMessage,
|
||||
...(cacheControl && cacheControl),
|
||||
if (cacheControl) {
|
||||
// Add cache_control to system message if enabled
|
||||
// https://docs.litellm.ai/docs/providers/anthropic#caching---large-context-caching
|
||||
systemMessage.content = [
|
||||
{
|
||||
text: systemPrompt,
|
||||
type: "text",
|
||||
...cacheControl,
|
||||
},
|
||||
] as Anthropic.Messages.TextBlockParam[]
|
||||
}
|
||||
|
||||
// Find the last two user messages to apply caching
|
||||
@@ -213,19 +228,49 @@ export class LiteLlmHandler implements ApiHandler {
|
||||
const secondLastUserMsgIndex = userMsgIndices[userMsgIndices.length - 2] ?? -1
|
||||
|
||||
// Apply cache_control to the last two user messages if enabled
|
||||
const enhancedMessages = formattedMessages.map((message, index) => {
|
||||
if ((index === lastUserMsgIndex || index === secondLastUserMsgIndex) && cacheControl) {
|
||||
return {
|
||||
...message,
|
||||
...cacheControl,
|
||||
// https://docs.litellm.ai/docs/providers/anthropic#caching---large-context-caching
|
||||
const enhancedMessages: OpenAI.Chat.ChatCompletionMessageParam[] = formattedMessages.map(
|
||||
(message, index): OpenAI.Chat.ChatCompletionMessageParam => {
|
||||
if ((index === lastUserMsgIndex || index === secondLastUserMsgIndex) && cacheControl) {
|
||||
// Handle both string and array content types
|
||||
if (typeof message.content === "string") {
|
||||
return {
|
||||
...message,
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: message.content,
|
||||
...cacheControl,
|
||||
},
|
||||
] as any,
|
||||
}
|
||||
} else if (Array.isArray(message.content)) {
|
||||
// Apply cache control to the last content item in the array
|
||||
return {
|
||||
...message,
|
||||
content: message.content.map((item, contentIndex) =>
|
||||
contentIndex === (message.content?.length || 0) - 1
|
||||
? {
|
||||
...item,
|
||||
...cacheControl,
|
||||
}
|
||||
: item,
|
||||
) as any,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...message,
|
||||
...cacheControl,
|
||||
}
|
||||
}
|
||||
}
|
||||
return message
|
||||
})
|
||||
return message
|
||||
},
|
||||
)
|
||||
|
||||
const stream = await client.chat.completions.create({
|
||||
model: this.options.liteLlmModelId || liteLlmDefaultModelId,
|
||||
messages: [enhancedSystemMessage, ...enhancedMessages],
|
||||
messages: [systemMessage, ...enhancedMessages],
|
||||
temperature,
|
||||
stream: true,
|
||||
stream_options: { include_usage: true },
|
||||
@@ -244,16 +289,16 @@ export class LiteLlmHandler implements ApiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle reasoning events (thinking)
|
||||
// Thinking is not in the standard types but may be in the response
|
||||
// Handle reasoning events
|
||||
// This is not in the standard types but may be in the response
|
||||
interface ThinkingDelta {
|
||||
thinking?: string
|
||||
reasoning_content?: string
|
||||
}
|
||||
|
||||
if ((delta as ThinkingDelta)?.thinking) {
|
||||
if ((delta as ThinkingDelta)?.reasoning_content) {
|
||||
yield {
|
||||
type: "reasoning",
|
||||
reasoning: (delta as ThinkingDelta).thinking || "",
|
||||
reasoning: (delta as ThinkingDelta).reasoning_content || "",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ModelInfo, QwenCodeModelId, qwenCodeDefaultModelId, qwenCodeModels } fr
|
||||
import OpenAI from "openai"
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
import { ApiHandler } from "../"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
import { convertToOpenAiMessages } from "../transform/openai-format"
|
||||
import { ApiStream } from "../transform/stream"
|
||||
@@ -24,7 +24,7 @@ interface QwenOAuthCredentials {
|
||||
resource_url?: string
|
||||
}
|
||||
|
||||
interface QwenCodeHandlerOptions {
|
||||
interface QwenCodeHandlerOptions extends CommonApiHandlerOptions {
|
||||
qwenCodeOauthPath?: string
|
||||
apiModelId?: string
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ModelInfo, vercelAiGatewayDefaultModelId, vercelAiGatewayDefaultModelInfo } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import { ApiHandler } from "../index"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../index"
|
||||
import { withRetry } from "../retry"
|
||||
import { ApiStream } from "../transform/stream"
|
||||
import { createVercelAIGatewayStream } from "../transform/vercel-ai-gateway-stream"
|
||||
|
||||
interface VercelAIGatewayHandlerOptions {
|
||||
interface VercelAIGatewayHandlerOptions extends CommonApiHandlerOptions {
|
||||
vercelAiGatewayApiKey?: string
|
||||
vercelAiGatewayModelId?: string
|
||||
vercelAiGatewayModelInfo?: ModelInfo
|
||||
|
||||
@@ -10,12 +10,12 @@ import {
|
||||
} from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import { version as extensionVersion } from "../../../../package.json"
|
||||
import { ApiHandler } from ".."
|
||||
import { ApiHandler, CommonApiHandlerOptions } from ".."
|
||||
import { withRetry } from "../retry"
|
||||
import { convertToOpenAiMessages } from "../transform/openai-format"
|
||||
import { ApiStream } from "../transform/stream"
|
||||
|
||||
interface ZAiHandlerOptions {
|
||||
interface ZAiHandlerOptions extends CommonApiHandlerOptions {
|
||||
zaiApiLine?: string
|
||||
zaiApiKey?: string
|
||||
apiModelId?: string
|
||||
|
||||
+15
-2
@@ -12,6 +12,18 @@ const DEFAULT_OPTIONS: Required<RetryOptions> = {
|
||||
retryAllErrors: false,
|
||||
}
|
||||
|
||||
export class RetriableError extends Error {
|
||||
status: number = 429
|
||||
retryAfter?: number
|
||||
|
||||
constructor(message: string, retryAfter?: number, options?: ErrorOptions) {
|
||||
super(message, options)
|
||||
this.name = "RetriableError"
|
||||
|
||||
this.retryAfter = retryAfter
|
||||
}
|
||||
}
|
||||
|
||||
export function withRetry(options: RetryOptions = {}) {
|
||||
const { maxRetries, baseDelay, maxDelay, retryAllErrors } = { ...DEFAULT_OPTIONS, ...options }
|
||||
|
||||
@@ -24,7 +36,7 @@ export function withRetry(options: RetryOptions = {}) {
|
||||
yield* originalMethod.apply(this, args)
|
||||
return
|
||||
} catch (error: any) {
|
||||
const isRateLimit = error?.status === 429
|
||||
const isRateLimit = error?.status === 429 || error instanceof RetriableError
|
||||
const isLastAttempt = attempt === maxRetries - 1
|
||||
|
||||
if ((!isRateLimit && !retryAllErrors) || isLastAttempt) {
|
||||
@@ -36,7 +48,8 @@ export function withRetry(options: RetryOptions = {}) {
|
||||
const retryAfter =
|
||||
error.headers?.["retry-after"] ||
|
||||
error.headers?.["x-ratelimit-reset"] ||
|
||||
error.headers?.["ratelimit-reset"]
|
||||
error.headers?.["ratelimit-reset"] ||
|
||||
error.retryAfter
|
||||
|
||||
let delay: number
|
||||
if (retryAfter) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { CLAUDE_SONNET_4_1M_SUFFIX, ModelInfo, openRouterClaudeSonnet41mModelId } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import { isGPT5ModelFamily } from "../../prompts/system-prompt/utils"
|
||||
import { convertToOpenAiMessages } from "./openai-format"
|
||||
import { convertToR1Format } from "./r1-format"
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { getTaskMetadata, saveTaskMetadata } from "@core/storage/disk"
|
||||
import { getTaskMetadata, readTaskHistoryFromState, saveTaskMetadata } from "@core/storage/disk"
|
||||
import type { ClineMessage } from "@shared/ExtensionMessage"
|
||||
import chokidar, { FSWatcher } from "chokidar"
|
||||
import * as path from "path"
|
||||
import * as vscode from "vscode"
|
||||
import { Controller } from "@/core/controller"
|
||||
import { HistoryItem } from "@/shared/HistoryItem"
|
||||
import { getCwd } from "@/utils/path"
|
||||
import type { FileMetadataEntry } from "./ContextTrackerTypes"
|
||||
|
||||
@@ -286,8 +285,7 @@ export class FileContextTracker {
|
||||
static async cleanupOrphanedWarnings(context: vscode.ExtensionContext): Promise<void> {
|
||||
const startTime = Date.now()
|
||||
try {
|
||||
// eslint-disable-next-line eslint-rules/no-direct-vscode-state-api
|
||||
const taskHistory = (context.globalState.get("taskHistory") as HistoryItem[]) || []
|
||||
const taskHistory = await readTaskHistoryFromState(context)
|
||||
const existingTaskIds = new Set(taskHistory.map((task) => task.id))
|
||||
const allStateKeys = context.workspaceState.keys()
|
||||
const pendingWarningKeys = allStateKeys.filter((key) => key.startsWith("pendingFileContextWarning_"))
|
||||
@@ -312,7 +310,7 @@ export class FileContextTracker {
|
||||
`FileContextTracker: Processed ${existingTaskIds.size} tasks, found ${pendingWarningKeys.length} pending warnings, ${orphanedPendingContextTasks.length} orphaned, deleted ${orphanedPendingContextTasks.length}, took ${duration}ms`,
|
||||
)
|
||||
} catch (error) {
|
||||
console.error("Error cleaning up orphaned file context warnings:", error)
|
||||
console.error("[FileContextTracker] Error cleaning up orphaned file context warnings:", error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { getFileMentionFromPath } from "@/core/mentions"
|
||||
import { WebviewProvider } from "@/core/webview"
|
||||
import { singleFileDiagnosticsToProblemsString } from "@/integrations/diagnostics"
|
||||
import { telemetryService } from "@/services/posthog/PostHogClientProvider"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import { CommandContext, Empty } from "@/shared/proto/index.cline"
|
||||
import { Controller } from "../index"
|
||||
import { sendAddToInputEventToClient } from "../ui/subscribeToAddToInput"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getFileMentionFromPath } from "@/core/mentions"
|
||||
import { HostProvider } from "@/hosts/host-provider"
|
||||
import { telemetryService } from "@/services/posthog/PostHogClientProvider"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import { CommandContext, Empty } from "@/shared/proto/index.cline"
|
||||
import { ShowMessageType } from "@/shared/proto/index.host"
|
||||
import { Controller } from "../index"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getFileMentionFromPath } from "@/core/mentions"
|
||||
import { singleFileDiagnosticsToProblemsString } from "@/integrations/diagnostics"
|
||||
import { telemetryService } from "@/services/posthog/PostHogClientProvider"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import { CommandContext, Empty } from "@/shared/proto/index.cline"
|
||||
import { Controller } from "../index"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getFileMentionFromPath } from "@/core/mentions"
|
||||
import { HostProvider } from "@/hosts/host-provider"
|
||||
import { telemetryService } from "@/services/posthog/PostHogClientProvider"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import { CommandContext, Empty } from "@/shared/proto/index.cline"
|
||||
import { ShowMessageType } from "@/shared/proto/index.host"
|
||||
import { Controller } from "../index"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { openFile as openFileIntegration } from "@integrations/misc/open-file"
|
||||
import { telemetryService } from "../../../services/posthog/PostHogClientProvider"
|
||||
import { telemetryService } from "../../../services/telemetry"
|
||||
import { Empty, StringRequest } from "../../../shared/proto/cline/common"
|
||||
import { ensureFocusChainFile, extractFocusChainListFromText } from "../../task/focus-chain/file-utils"
|
||||
import { Controller } from ".."
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import path from "node:path"
|
||||
import { telemetryService } from "@services/posthog/PostHogClientProvider"
|
||||
import type { ToggleClineRuleRequest } from "@shared/proto/cline/file"
|
||||
import { ToggleClineRules } from "@shared/proto/cline/file"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import type { Controller } from "../index"
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { ClineRulesToggles as AppClineRulesToggles } from "@shared/cline-rules"
|
||||
import type { ToggleWindsurfRuleRequest } from "@shared/proto/cline/file"
|
||||
import { ClineRulesToggles } from "@shared/proto/cline/file"
|
||||
import type { Controller } from "../index"
|
||||
|
||||
@@ -21,7 +21,8 @@ import * as vscode from "vscode"
|
||||
import { clineEnvConfig } from "@/config"
|
||||
import { HostProvider } from "@/hosts/host-provider"
|
||||
import { AuthService } from "@/services/auth/AuthService"
|
||||
import { PostHogClientProvider, telemetryService } from "@/services/posthog/PostHogClientProvider"
|
||||
import { getDistinctId } from "@/services/logging/distinctId"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import { ShowMessageType } from "@/shared/proto/host/window"
|
||||
import { getLatestAnnouncementId } from "@/utils/announcements"
|
||||
import { getCwd, getDesktopDir } from "@/utils/path"
|
||||
@@ -65,12 +66,15 @@ export class Controller {
|
||||
this.authService.restoreRefreshTokenAndRetrieveAuthInfo()
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("CRITICAL: Failed to initialize StateManager - extension may not function properly:", error)
|
||||
console.error(
|
||||
"[Controller] CRITICAL: Failed to initialize StateManager - extension may not function properly:",
|
||||
error,
|
||||
)
|
||||
})
|
||||
|
||||
// Set up persistence error recovery
|
||||
this.stateManager.onPersistenceError = async ({ error }: PersistenceErrorEvent) => {
|
||||
console.error("Cache persistence failed, recovering:", error)
|
||||
console.error("[Controller] Cache persistence failed, recovering:", error)
|
||||
try {
|
||||
await this.stateManager.reInitialize()
|
||||
await this.postStateToWebview()
|
||||
@@ -79,7 +83,7 @@ export class Controller {
|
||||
message: "Saving settings to storage failed.",
|
||||
})
|
||||
} catch (recoveryError) {
|
||||
console.error("Cache recovery failed:", recoveryError)
|
||||
console.error("[Controller] Cache recovery failed:", recoveryError)
|
||||
HostProvider.window.showMessage({
|
||||
type: ShowMessageType.ERROR,
|
||||
message: "Failed to save settings. Please restart the extension.",
|
||||
@@ -212,7 +216,7 @@ export class Controller {
|
||||
openaiReasoningEffort,
|
||||
mode,
|
||||
strictPlanModeEnabled ?? true,
|
||||
useAutoCondense ?? true,
|
||||
useAutoCondense ?? false,
|
||||
shellIntegrationTimeout,
|
||||
terminalReuseEnabled ?? true,
|
||||
terminalOutputLineLimit ?? 500,
|
||||
@@ -636,7 +640,7 @@ export class Controller {
|
||||
const latestAnnouncementId = getLatestAnnouncementId(this.context)
|
||||
const shouldShowAnnouncement = lastShownAnnouncementId !== latestAnnouncementId
|
||||
const platform = process.platform as Platform
|
||||
const distinctId = PostHogClientProvider.getInstance().distinctId
|
||||
const distinctId = getDistinctId()
|
||||
const version = this.context.extension?.packageJSON?.version ?? ""
|
||||
const uriScheme = vscode.env.uriScheme
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { fileExistsAtPath } from "@utils/fs"
|
||||
import axios from "axios"
|
||||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
import { telemetryService } from "@/services/posthog/PostHogClientProvider"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import { groqModels } from "../../../shared/api"
|
||||
import { Controller } from ".."
|
||||
|
||||
|
||||
@@ -110,6 +110,12 @@ export async function refreshOpenRouterModels(
|
||||
|
||||
switch (rawModel.id) {
|
||||
case "anthropic/claude-sonnet-4":
|
||||
// NOTE: we artificially restrict the context window to 200k to keep costs low for users, and have a :1m model variant created below for users that want to use the full 1m.
|
||||
modelInfo.contextWindow = 200_000
|
||||
modelInfo.supportsPromptCache = true
|
||||
modelInfo.cacheWritesPrice = 3.75
|
||||
modelInfo.cacheReadsPrice = 0.3
|
||||
break
|
||||
case "anthropic/claude-3-7-sonnet":
|
||||
case "anthropic/claude-3-7-sonnet:beta":
|
||||
case "anthropic/claude-3.7-sonnet":
|
||||
@@ -183,6 +189,10 @@ export async function refreshOpenRouterModels(
|
||||
modelInfo.maxTokens = 8_192 // 128000 breaks context window truncation
|
||||
modelInfo.contextWindow = 272_000 // openrouter reports 400k but the input limit is actually 400k-128k
|
||||
break
|
||||
case "x-ai/grok-code-fast-1":
|
||||
modelInfo.supportsPromptCache = true
|
||||
modelInfo.cacheReadsPrice = 0.02
|
||||
break
|
||||
default:
|
||||
if (rawModel.id.startsWith("openai/")) {
|
||||
modelInfo.cacheReadsPrice = parsePrice(rawModel.pricing?.input_cache_read)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { telemetryService } from "@services/posthog/PostHogClientProvider"
|
||||
import { Empty, StringRequest } from "@shared/proto/cline/common"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import { Controller } from ".."
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,7 @@ import { convertProtoApiConfigurationToApiConfiguration } from "@shared/proto-co
|
||||
import { OpenaiReasoningEffort } from "@shared/storage/types"
|
||||
import { TelemetrySetting } from "@shared/TelemetrySetting"
|
||||
import { McpDisplayMode } from "@/shared/McpDisplayMode"
|
||||
import { telemetryService } from "../../../services/posthog/PostHogClientProvider"
|
||||
import { telemetryService } from "../../../services/telemetry"
|
||||
import { Controller } from ".."
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { telemetryService } from "@services/posthog/PostHogClientProvider"
|
||||
import { Empty, StringRequest } from "@shared/proto/cline/common"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import { Controller } from ".."
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { McpMarketplaceCatalog } from "@shared/mcp"
|
||||
import { Empty, EmptyRequest } from "@shared/proto/cline/common"
|
||||
import { OpenRouterCompatibleModelInfo } from "@shared/proto/cline/models"
|
||||
import { featureFlagsService, telemetryService } from "@/services/posthog/PostHogClientProvider"
|
||||
import { featureFlagsService } from "@/services/feature-flags"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import type { Controller } from "../index"
|
||||
import { sendMcpMarketplaceCatalogEvent } from "../mcp/subscribeToMcpMarketplaceCatalog"
|
||||
import { refreshBasetenModels } from "../models/refreshBasetenModels"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { telemetryService } from "@services/posthog/PostHogClientProvider"
|
||||
import type { EmptyRequest } from "@shared/proto/cline/common"
|
||||
import { Empty } from "@shared/proto/cline/common"
|
||||
import * as vscode from "vscode"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import type { Controller } from "../index"
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,8 @@ You have only two options: If you are immediately prepared to call the attempt_c
|
||||
|
||||
You MUST ONLY respond to this message by using either the attempt_completion tool or the summarize_task tool call.
|
||||
|
||||
When responding with the summarize_task tool call, follow these instructions:
|
||||
|
||||
Before providing your final summary, wrap your analysis in <thinking> tags to organize your thoughts and ensure you've covered all necessary points. In your analysis process:
|
||||
1. Chronologically analyze each message and section of the conversation. For each section thoroughly identify:
|
||||
- The user's explicit requests and intents
|
||||
@@ -21,10 +23,14 @@ Your summary should include the following sections:
|
||||
3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.
|
||||
4. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.
|
||||
5. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.
|
||||
6. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.
|
||||
7. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's explicit requests, and the task you were working on immediately before this summary request. If your last task was concluded, then only list next steps if they are explicitly in line with the users request. Do not start on tangential requests without confirming with the user first.
|
||||
6. Task Evolution: If the user provided additional requests or modified the original task during the conversation, document this progression:
|
||||
- Task Modifications: [Chronological list of how the user redirected or modified the work since the original task]
|
||||
- Current Active Task: [What the user most recently asked to work on]
|
||||
- Context for Changes: [Why the task evolved - user feedback, new requirements, etc. (Include direct quotes from user messages that caused task changes to prevent drift after context compacting)]
|
||||
7. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.
|
||||
8. Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's explicit requests, and the task you were working on immediately before this summary request. If your last task was concluded, then only list next steps if they are explicitly in line with the users request. Do not start on tangential requests without confirming with the user first.
|
||||
If there is a next step, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no drift in task interpretation.
|
||||
8. You should pay special attention to the most recent user message, as it indicates the user's most recent intent, if applicable.
|
||||
9. You should pay special attention to the most recent user message, as it indicates the user's most recent intent.
|
||||
|
||||
${
|
||||
focusChainSettings?.enabled
|
||||
|
||||
@@ -9,7 +9,7 @@ export const formatResponse = {
|
||||
`[[NOTE] This file read has been removed to save space in the context window. Refer to the latest file read for the most up to date version of this file.]`,
|
||||
|
||||
contextTruncationNotice: () =>
|
||||
`[NOTE] Some previous conversation history with the user has been removed to maintain optimal context window length. The initial user task has been retained for continuity, while intermediate conversation history has been removed. Please keep this in mind as you continue assisting the user.`,
|
||||
`[NOTE] Some previous conversation history with the user has been removed to maintain optimal context window length. The initial user task has been retained for continuity, while intermediate conversation history has been removed. Keep this in mind as you continue assisting the user. Pay special attention to the user's latest messages.`,
|
||||
|
||||
processFirstUserMessageForTruncation: (originalContent: string) => {
|
||||
const MAX_CHARS = 400_000
|
||||
|
||||
+49
-24
@@ -30,8 +30,8 @@ Always adhere to this format for the tool use to ensure proper parsing and execu
|
||||
## execute_command
|
||||
Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/project
|
||||
Parameters:
|
||||
- command: (required) The CLI command to execute...
|
||||
- requires_approval: (required) A boolean indicating whether...
|
||||
- command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
|
||||
- requires_approval: (required) A boolean indicating whether this command requires explicit user approval before execution in case the user has auto-approve mode enabled. Set to 'true' for potentially impactful operations like installing/uninstalling packages, deleting/overwriting files, system configuration changes, network operations, or any commands that could have unintended side effects. Set to 'false' for safe operations like reading files/directories, running development servers, building projects, and other non-destructive operations.
|
||||
Usage:
|
||||
<execute_command>
|
||||
<command>Your command here</command>
|
||||
@@ -71,7 +71,6 @@ Parameters:
|
||||
------- SEARCH
|
||||
[exact content to find]
|
||||
=======
|
||||
|
||||
[new content to replace with]
|
||||
+++++++ REPLACE
|
||||
```
|
||||
@@ -105,11 +104,13 @@ Parameters:
|
||||
- path: (required) The path of the directory to search in (relative to the current working directory /test/project). This directory will be recursively searched.
|
||||
- regex: (required) The regular expression pattern to search for. Uses Rust regex syntax.
|
||||
- file_pattern: (optional) Glob pattern to filter files (e.g., '*.ts' for TypeScript files). If not provided, it will search all files (*).
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<search_files>
|
||||
<path>Directory path here</path>
|
||||
<regex>Your regex pattern here</regex>
|
||||
<file_pattern>file pattern here (optional)</file_pattern>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</search_files>
|
||||
|
||||
## list_files
|
||||
@@ -117,19 +118,23 @@ Description: Request to list files and directories within the specified director
|
||||
Parameters:
|
||||
- path: (required) The path of the directory to list contents for (relative to the current working directory /test/project)
|
||||
- recursive: (optional) Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<list_files>
|
||||
<path>Directory path here</path>
|
||||
<recursive>true or false (optional)</recursive>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</list_files>
|
||||
|
||||
## list_code_definition_names
|
||||
Description: Request to list definition names (classes, functions, methods, etc.) used in source code files at the top level of the specified directory. This tool provides insights into the codebase structure and important constructs, encapsulating high-level concepts and relationships that are crucial for understanding the overall architecture.
|
||||
Parameters:
|
||||
- path: (required) The path of the directory (relative to the current working directory /test/project) to list top level source code definitions for.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<list_code_definition_names>
|
||||
<path>Directory path here</path>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</list_code_definition_names>
|
||||
|
||||
## browser_action
|
||||
@@ -139,10 +144,25 @@ Description: Request to interact with a Puppeteer-controlled browser. Every acti
|
||||
- The browser window has a resolution of **1280x720** pixels. When performing any click actions, ensure the coordinates are within this resolution range.
|
||||
- Before clicking on any elements such as icons, links, or buttons, you must consult the provided screenshot of the page to determine the coordinates of the element. The click should be targeted at the **center of the element**, not on its edges.
|
||||
Parameters:
|
||||
- action: (required) The action to perform. The available actions are: * launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**. - Use with the `url` parameter to provide the URL. - Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.) * click: Click at a specific x,y coordinate. - Use with the `coordinate` parameter to specify the location. - Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot. * type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text. - Use with the `text` parameter to provide the string to type. * scroll_down: Scroll down the page by one page height. * scroll_up: Scroll up the page by one page height. * close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**. - Example: `<action>close</action>`
|
||||
- url: (optional) Use this for providing the URL for the `launch` action. * Example: <url>https://example.com</url>
|
||||
- coordinate: (optional) The X and Y coordinates for the `click` action. Coordinates should be within the **1280x720** resolution. * Example: <coordinate>450,300</coordinate>
|
||||
- text: (optional) Use this for providing the text for the `type` action. * Example: <text>Hello, world!</text>
|
||||
- action: (required) The action to perform. The available actions are:
|
||||
* launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**.
|
||||
- Use with the `url` parameter to provide the URL.
|
||||
- Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.)
|
||||
* click: Click at a specific x,y coordinate.
|
||||
- Use with the `coordinate` parameter to specify the location.
|
||||
- Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot.
|
||||
* type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text.
|
||||
- Use with the `text` parameter to provide the string to type.
|
||||
* scroll_down: Scroll down the page by one page height.
|
||||
* scroll_up: Scroll up the page by one page height.
|
||||
* close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**.
|
||||
- Example: `<action>close</action>`
|
||||
- url: (optional) Use this for providing the URL for the `launch` action.
|
||||
* Example: <url>https://example.com</url>
|
||||
- coordinate: (optional) The X and Y coordinates for the `click` action. Coordinates should be within the **1280x720** resolution.
|
||||
* Example: <coordinate>450,300</coordinate>
|
||||
- text: (optional) Use this for providing the text for the `type` action.
|
||||
* Example: <text>Hello, world!</text>
|
||||
Usage:
|
||||
<browser_action>
|
||||
<action>Action to perform (e.g., launch, click, type, scroll_down, scroll_up, close)</action>
|
||||
@@ -162,9 +182,11 @@ Description: Fetches content from a specified URL and processes into markdown
|
||||
- This tool is read-only and does not modify any files
|
||||
Parameters:
|
||||
- url: (required) The URL to fetch content from
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<web_fetch>
|
||||
<url>https://example.com/docs</url>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</web_fetch>
|
||||
|
||||
## use_mcp_tool
|
||||
@@ -173,28 +195,30 @@ Parameters:
|
||||
- server_name: (required) The name of the MCP server providing the tool
|
||||
- tool_name: (required) The name of the tool to execute
|
||||
- arguments: (required) A JSON object containing the tool's input parameters, following the tool's input schema
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<use_mcp_tool>
|
||||
<server_name>server name here</server_name>
|
||||
<tool_name>tool name here</tool_name>
|
||||
<arguments>{
|
||||
<arguments>
|
||||
{
|
||||
"param1": "value1",
|
||||
"param2": "value2"
|
||||
}</arguments>
|
||||
}
|
||||
</arguments>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</use_mcp_tool>
|
||||
|
||||
## access_mcp_resource
|
||||
Description: The name of the MCP server providing the resource.
|
||||
Description: Request to access a resource provided by a connected MCP server. Resources represent data sources that can be used as context, such as files, API responses, or system information.
|
||||
Parameters:
|
||||
- server_name: (required) server name here
|
||||
- uri: (required) resource URI here
|
||||
- server_name: (required) The name of the MCP server providing the resource
|
||||
- uri: (required) The URI identifying the specific resource to access
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<access_mcp_resource>
|
||||
<server_name></server_name>
|
||||
<uri></uri>
|
||||
<server_name>server name here</server_name>
|
||||
<uri>resource URI here</uri>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</access_mcp_resource>
|
||||
|
||||
@@ -202,11 +226,13 @@ Usage:
|
||||
Description: Ask the user a question to gather additional information needed to complete the task. This tool should be used when you encounter ambiguities, need clarification, or require more details to proceed effectively. It allows for interactive problem-solving by enabling direct communication with the user. Use this tool judiciously to maintain a balance between gathering necessary information and avoiding excessive back-and-forth.
|
||||
Parameters:
|
||||
- question: (required) The question to ask the user. This should be a clear, specific question that addresses the information you need.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer. You may not always need to provide options, but it may be helpful in many cases where it can save the user from having to type out a response manually. IMPORTANT: NEVER include an option to toggle to Act mode, as this would be something you need to direct the user to do manually themselves if needed.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<ask_followup_question>
|
||||
<question>Your question here</question>
|
||||
<options>Array of options here (optional), e.g. ["Option 1", "Option 2", "Option 3"]</options>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</ask_followup_question>
|
||||
|
||||
## attempt_completion
|
||||
@@ -225,7 +251,7 @@ Usage:
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
@@ -250,11 +276,15 @@ Usage:
|
||||
<plan_mode_respond>
|
||||
<response>Your response here</response>
|
||||
<needs_more_exploration>true or false (optional, but you MUST set to true if in <response> you need to read files or use other exploration tools)</needs_more_exploration>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
<task_progress>Checklist here (If you have presented the user with concrete steps or requirements, you can optionally include a todo list outlining these steps.)</task_progress>
|
||||
</plan_mode_respond>
|
||||
|
||||
## load_mcp_documentation
|
||||
Description: Load documentation about creating MCP servers. This tool should be used when the user requests to create or install an MCP server (the user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. You have the ability to create an MCP server and add it to a configuration file that will then expose the tools and resources for you to use with `use_mcp_tool` and `access_mcp_resource`). The documentation provides detailed information about the MCP server creation process, including setup instructions, best practices, and examples.
|
||||
Parameters: None
|
||||
Usage:
|
||||
<load_mcp_documentation>
|
||||
</load_mcp_documentation>
|
||||
|
||||
# Tool Use Examples
|
||||
|
||||
@@ -337,9 +367,7 @@ Description: Load documentation about creating MCP servers. This tool should be
|
||||
<diff>
|
||||
------- SEARCH
|
||||
import React from 'react';
|
||||
|
||||
=======
|
||||
|
||||
import React, { useState } from 'react';
|
||||
+++++++ REPLACE
|
||||
|
||||
@@ -350,15 +378,12 @@ function handleSubmit() {
|
||||
}
|
||||
|
||||
=======
|
||||
|
||||
+++++++ REPLACE
|
||||
|
||||
------- SEARCH
|
||||
return (
|
||||
<div>
|
||||
|
||||
=======
|
||||
|
||||
function handleSubmit() {
|
||||
saveData();
|
||||
setLoading(false);
|
||||
@@ -396,7 +421,7 @@ return (
|
||||
<tool_name>create_issue</tool_name>
|
||||
<arguments>
|
||||
{
|
||||
"owner": "octocat",
|
||||
"owner": "octocat2",
|
||||
"repo": "hello-world",
|
||||
"title": "Found a bug",
|
||||
"body": "I'm having a problem with this.",
|
||||
|
||||
+30
-20
@@ -30,8 +30,8 @@ Always adhere to this format for the tool use to ensure proper parsing and execu
|
||||
## execute_command
|
||||
Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/project
|
||||
Parameters:
|
||||
- command: (required) The CLI command to execute...
|
||||
- requires_approval: (required) A boolean indicating whether...
|
||||
- command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
|
||||
- requires_approval: (required) A boolean indicating whether this command requires explicit user approval before execution in case the user has auto-approve mode enabled. Set to 'true' for potentially impactful operations like installing/uninstalling packages, deleting/overwriting files, system configuration changes, network operations, or any commands that could have unintended side effects. Set to 'false' for safe operations like reading files/directories, running development servers, building projects, and other non-destructive operations.
|
||||
Usage:
|
||||
<execute_command>
|
||||
<command>Your command here</command>
|
||||
@@ -71,7 +71,6 @@ Parameters:
|
||||
------- SEARCH
|
||||
[exact content to find]
|
||||
=======
|
||||
|
||||
[new content to replace with]
|
||||
+++++++ REPLACE
|
||||
```
|
||||
@@ -105,11 +104,13 @@ Parameters:
|
||||
- path: (required) The path of the directory to search in (relative to the current working directory /test/project). This directory will be recursively searched.
|
||||
- regex: (required) The regular expression pattern to search for. Uses Rust regex syntax.
|
||||
- file_pattern: (optional) Glob pattern to filter files (e.g., '*.ts' for TypeScript files). If not provided, it will search all files (*).
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<search_files>
|
||||
<path>Directory path here</path>
|
||||
<regex>Your regex pattern here</regex>
|
||||
<file_pattern>file pattern here (optional)</file_pattern>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</search_files>
|
||||
|
||||
## list_files
|
||||
@@ -117,19 +118,23 @@ Description: Request to list files and directories within the specified director
|
||||
Parameters:
|
||||
- path: (required) The path of the directory to list contents for (relative to the current working directory /test/project)
|
||||
- recursive: (optional) Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<list_files>
|
||||
<path>Directory path here</path>
|
||||
<recursive>true or false (optional)</recursive>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</list_files>
|
||||
|
||||
## list_code_definition_names
|
||||
Description: Request to list definition names (classes, functions, methods, etc.) used in source code files at the top level of the specified directory. This tool provides insights into the codebase structure and important constructs, encapsulating high-level concepts and relationships that are crucial for understanding the overall architecture.
|
||||
Parameters:
|
||||
- path: (required) The path of the directory (relative to the current working directory /test/project) to list top level source code definitions for.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<list_code_definition_names>
|
||||
<path>Directory path here</path>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</list_code_definition_names>
|
||||
|
||||
## web_fetch
|
||||
@@ -143,9 +148,11 @@ Description: Fetches content from a specified URL and processes into markdown
|
||||
- This tool is read-only and does not modify any files
|
||||
Parameters:
|
||||
- url: (required) The URL to fetch content from
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<web_fetch>
|
||||
<url>https://example.com/docs</url>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</web_fetch>
|
||||
|
||||
## use_mcp_tool
|
||||
@@ -154,28 +161,30 @@ Parameters:
|
||||
- server_name: (required) The name of the MCP server providing the tool
|
||||
- tool_name: (required) The name of the tool to execute
|
||||
- arguments: (required) A JSON object containing the tool's input parameters, following the tool's input schema
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<use_mcp_tool>
|
||||
<server_name>server name here</server_name>
|
||||
<tool_name>tool name here</tool_name>
|
||||
<arguments>{
|
||||
<arguments>
|
||||
{
|
||||
"param1": "value1",
|
||||
"param2": "value2"
|
||||
}</arguments>
|
||||
}
|
||||
</arguments>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</use_mcp_tool>
|
||||
|
||||
## access_mcp_resource
|
||||
Description: The name of the MCP server providing the resource.
|
||||
Description: Request to access a resource provided by a connected MCP server. Resources represent data sources that can be used as context, such as files, API responses, or system information.
|
||||
Parameters:
|
||||
- server_name: (required) server name here
|
||||
- uri: (required) resource URI here
|
||||
- server_name: (required) The name of the MCP server providing the resource
|
||||
- uri: (required) The URI identifying the specific resource to access
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<access_mcp_resource>
|
||||
<server_name></server_name>
|
||||
<uri></uri>
|
||||
<server_name>server name here</server_name>
|
||||
<uri>resource URI here</uri>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</access_mcp_resource>
|
||||
|
||||
@@ -183,11 +192,13 @@ Usage:
|
||||
Description: Ask the user a question to gather additional information needed to complete the task. This tool should be used when you encounter ambiguities, need clarification, or require more details to proceed effectively. It allows for interactive problem-solving by enabling direct communication with the user. Use this tool judiciously to maintain a balance between gathering necessary information and avoiding excessive back-and-forth.
|
||||
Parameters:
|
||||
- question: (required) The question to ask the user. This should be a clear, specific question that addresses the information you need.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer. You may not always need to provide options, but it may be helpful in many cases where it can save the user from having to type out a response manually. IMPORTANT: NEVER include an option to toggle to Act mode, as this would be something you need to direct the user to do manually themselves if needed.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<ask_followup_question>
|
||||
<question>Your question here</question>
|
||||
<options>Array of options here (optional), e.g. ["Option 1", "Option 2", "Option 3"]</options>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</ask_followup_question>
|
||||
|
||||
## attempt_completion
|
||||
@@ -206,7 +217,7 @@ Usage:
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
@@ -231,11 +242,15 @@ Usage:
|
||||
<plan_mode_respond>
|
||||
<response>Your response here</response>
|
||||
<needs_more_exploration>true or false (optional, but you MUST set to true if in <response> you need to read files or use other exploration tools)</needs_more_exploration>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
<task_progress>Checklist here (If you have presented the user with concrete steps or requirements, you can optionally include a todo list outlining these steps.)</task_progress>
|
||||
</plan_mode_respond>
|
||||
|
||||
## load_mcp_documentation
|
||||
Description: Load documentation about creating MCP servers. This tool should be used when the user requests to create or install an MCP server (the user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. You have the ability to create an MCP server and add it to a configuration file that will then expose the tools and resources for you to use with `use_mcp_tool` and `access_mcp_resource`). The documentation provides detailed information about the MCP server creation process, including setup instructions, best practices, and examples.
|
||||
Parameters: None
|
||||
Usage:
|
||||
<load_mcp_documentation>
|
||||
</load_mcp_documentation>
|
||||
|
||||
# Tool Use Examples
|
||||
|
||||
@@ -318,9 +333,7 @@ Description: Load documentation about creating MCP servers. This tool should be
|
||||
<diff>
|
||||
------- SEARCH
|
||||
import React from 'react';
|
||||
|
||||
=======
|
||||
|
||||
import React, { useState } from 'react';
|
||||
+++++++ REPLACE
|
||||
|
||||
@@ -331,15 +344,12 @@ function handleSubmit() {
|
||||
}
|
||||
|
||||
=======
|
||||
|
||||
+++++++ REPLACE
|
||||
|
||||
------- SEARCH
|
||||
return (
|
||||
<div>
|
||||
|
||||
=======
|
||||
|
||||
function handleSubmit() {
|
||||
saveData();
|
||||
setLoading(false);
|
||||
@@ -377,7 +387,7 @@ return (
|
||||
<tool_name>create_issue</tool_name>
|
||||
<arguments>
|
||||
{
|
||||
"owner": "octocat",
|
||||
"owner": "octocat2",
|
||||
"repo": "hello-world",
|
||||
"title": "Found a bug",
|
||||
"body": "I'm having a problem with this.",
|
||||
|
||||
+37
-22
@@ -27,8 +27,8 @@ Always adhere to this format for the tool use to ensure proper parsing and execu
|
||||
## execute_command
|
||||
Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/project
|
||||
Parameters:
|
||||
- command: (required) The CLI command to execute...
|
||||
- requires_approval: (required) A boolean indicating whether...
|
||||
- command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
|
||||
- requires_approval: (required) A boolean indicating whether this command requires explicit user approval before execution in case the user has auto-approve mode enabled. Set to 'true' for potentially impactful operations like installing/uninstalling packages, deleting/overwriting files, system configuration changes, network operations, or any commands that could have unintended side effects. Set to 'false' for safe operations like reading files/directories, running development servers, building projects, and other non-destructive operations.
|
||||
Usage:
|
||||
<execute_command>
|
||||
<command>Your command here</command>
|
||||
@@ -64,7 +64,6 @@ Parameters:
|
||||
------- SEARCH
|
||||
[exact content to find]
|
||||
=======
|
||||
|
||||
[new content to replace with]
|
||||
+++++++ REPLACE
|
||||
```
|
||||
@@ -130,10 +129,25 @@ Description: Request to interact with a Puppeteer-controlled browser. Every acti
|
||||
- The browser window has a resolution of **1280x720** pixels. When performing any click actions, ensure the coordinates are within this resolution range.
|
||||
- Before clicking on any elements such as icons, links, or buttons, you must consult the provided screenshot of the page to determine the coordinates of the element. The click should be targeted at the **center of the element**, not on its edges.
|
||||
Parameters:
|
||||
- action: (required) The action to perform. The available actions are: * launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**. - Use with the `url` parameter to provide the URL. - Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.) * click: Click at a specific x,y coordinate. - Use with the `coordinate` parameter to specify the location. - Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot. * type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text. - Use with the `text` parameter to provide the string to type. * scroll_down: Scroll down the page by one page height. * scroll_up: Scroll up the page by one page height. * close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**. - Example: `<action>close</action>`
|
||||
- url: (optional) Use this for providing the URL for the `launch` action. * Example: <url>https://example.com</url>
|
||||
- coordinate: (optional) The X and Y coordinates for the `click` action. Coordinates should be within the **1280x720** resolution. * Example: <coordinate>450,300</coordinate>
|
||||
- text: (optional) Use this for providing the text for the `type` action. * Example: <text>Hello, world!</text>
|
||||
- action: (required) The action to perform. The available actions are:
|
||||
* launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**.
|
||||
- Use with the `url` parameter to provide the URL.
|
||||
- Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.)
|
||||
* click: Click at a specific x,y coordinate.
|
||||
- Use with the `coordinate` parameter to specify the location.
|
||||
- Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot.
|
||||
* type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text.
|
||||
- Use with the `text` parameter to provide the string to type.
|
||||
* scroll_down: Scroll down the page by one page height.
|
||||
* scroll_up: Scroll up the page by one page height.
|
||||
* close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**.
|
||||
- Example: `<action>close</action>`
|
||||
- url: (optional) Use this for providing the URL for the `launch` action.
|
||||
* Example: <url>https://example.com</url>
|
||||
- coordinate: (optional) The X and Y coordinates for the `click` action. Coordinates should be within the **1280x720** resolution.
|
||||
* Example: <coordinate>450,300</coordinate>
|
||||
- text: (optional) Use this for providing the text for the `type` action.
|
||||
* Example: <text>Hello, world!</text>
|
||||
Usage:
|
||||
<browser_action>
|
||||
<action>Action to perform (e.g., launch, click, type, scroll_down, scroll_up, close)</action>
|
||||
@@ -168,28 +182,30 @@ Usage:
|
||||
<use_mcp_tool>
|
||||
<server_name>server name here</server_name>
|
||||
<tool_name>tool name here</tool_name>
|
||||
<arguments>{
|
||||
<arguments>
|
||||
{
|
||||
"param1": "value1",
|
||||
"param2": "value2"
|
||||
}</arguments>
|
||||
}
|
||||
</arguments>
|
||||
</use_mcp_tool>
|
||||
|
||||
## access_mcp_resource
|
||||
Description: The name of the MCP server providing the resource.
|
||||
Description: Request to access a resource provided by a connected MCP server. Resources represent data sources that can be used as context, such as files, API responses, or system information.
|
||||
Parameters:
|
||||
- server_name: (required) server name here
|
||||
- uri: (required) resource URI here
|
||||
- server_name: (required) The name of the MCP server providing the resource
|
||||
- uri: (required) The URI identifying the specific resource to access
|
||||
Usage:
|
||||
<access_mcp_resource>
|
||||
<server_name></server_name>
|
||||
<uri></uri>
|
||||
<server_name>server name here</server_name>
|
||||
<uri>resource URI here</uri>
|
||||
</access_mcp_resource>
|
||||
|
||||
## ask_followup_question
|
||||
Description: Ask the user a question to gather additional information needed to complete the task. This tool should be used when you encounter ambiguities, need clarification, or require more details to proceed effectively. It allows for interactive problem-solving by enabling direct communication with the user. Use this tool judiciously to maintain a balance between gathering necessary information and avoiding excessive back-and-forth.
|
||||
Parameters:
|
||||
- question: (required) The question to ask the user. This should be a clear, specific question that addresses the information you need.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer. You may not always need to provide options, but it may be helpful in many cases where it can save the user from having to type out a response manually. IMPORTANT: NEVER include an option to toggle to Act mode, as this would be something you need to direct the user to do manually themselves if needed.
|
||||
Usage:
|
||||
<ask_followup_question>
|
||||
<question>Your question here</question>
|
||||
@@ -209,7 +225,7 @@ Usage:
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
@@ -237,6 +253,10 @@ Usage:
|
||||
|
||||
## load_mcp_documentation
|
||||
Description: Load documentation about creating MCP servers. This tool should be used when the user requests to create or install an MCP server (the user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. You have the ability to create an MCP server and add it to a configuration file that will then expose the tools and resources for you to use with `use_mcp_tool` and `access_mcp_resource`). The documentation provides detailed information about the MCP server creation process, including setup instructions, best practices, and examples.
|
||||
Parameters: None
|
||||
Usage:
|
||||
<load_mcp_documentation>
|
||||
</load_mcp_documentation>
|
||||
|
||||
# Tool Use Examples
|
||||
|
||||
@@ -307,9 +327,7 @@ Description: Load documentation about creating MCP servers. This tool should be
|
||||
<diff>
|
||||
------- SEARCH
|
||||
import React from 'react';
|
||||
|
||||
=======
|
||||
|
||||
import React, { useState } from 'react';
|
||||
+++++++ REPLACE
|
||||
|
||||
@@ -320,15 +338,12 @@ function handleSubmit() {
|
||||
}
|
||||
|
||||
=======
|
||||
|
||||
+++++++ REPLACE
|
||||
|
||||
------- SEARCH
|
||||
return (
|
||||
<div>
|
||||
|
||||
=======
|
||||
|
||||
function handleSubmit() {
|
||||
saveData();
|
||||
setLoading(false);
|
||||
@@ -360,7 +375,7 @@ return (
|
||||
<tool_name>create_issue</tool_name>
|
||||
<arguments>
|
||||
{
|
||||
"owner": "octocat",
|
||||
"owner": "octocat2",
|
||||
"repo": "hello-world",
|
||||
"title": "Found a bug",
|
||||
"body": "I'm having a problem with this.",
|
||||
|
||||
+49
-24
@@ -30,8 +30,8 @@ Always adhere to this format for the tool use to ensure proper parsing and execu
|
||||
## execute_command
|
||||
Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/project
|
||||
Parameters:
|
||||
- command: (required) The CLI command to execute...
|
||||
- requires_approval: (required) A boolean indicating whether...
|
||||
- command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
|
||||
- requires_approval: (required) A boolean indicating whether this command requires explicit user approval before execution in case the user has auto-approve mode enabled. Set to 'true' for potentially impactful operations like installing/uninstalling packages, deleting/overwriting files, system configuration changes, network operations, or any commands that could have unintended side effects. Set to 'false' for safe operations like reading files/directories, running development servers, building projects, and other non-destructive operations.
|
||||
Usage:
|
||||
<execute_command>
|
||||
<command>Your command here</command>
|
||||
@@ -71,7 +71,6 @@ Parameters:
|
||||
------- SEARCH
|
||||
[exact content to find]
|
||||
=======
|
||||
|
||||
[new content to replace with]
|
||||
+++++++ REPLACE
|
||||
```
|
||||
@@ -105,11 +104,13 @@ Parameters:
|
||||
- path: (required) The path of the directory to search in (relative to the current working directory /test/project). This directory will be recursively searched.
|
||||
- regex: (required) The regular expression pattern to search for. Uses Rust regex syntax.
|
||||
- file_pattern: (optional) Glob pattern to filter files (e.g., '*.ts' for TypeScript files). If not provided, it will search all files (*).
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<search_files>
|
||||
<path>Directory path here</path>
|
||||
<regex>Your regex pattern here</regex>
|
||||
<file_pattern>file pattern here (optional)</file_pattern>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</search_files>
|
||||
|
||||
## list_files
|
||||
@@ -117,19 +118,23 @@ Description: Request to list files and directories within the specified director
|
||||
Parameters:
|
||||
- path: (required) The path of the directory to list contents for (relative to the current working directory /test/project)
|
||||
- recursive: (optional) Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<list_files>
|
||||
<path>Directory path here</path>
|
||||
<recursive>true or false (optional)</recursive>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</list_files>
|
||||
|
||||
## list_code_definition_names
|
||||
Description: Request to list definition names (classes, functions, methods, etc.) used in source code files at the top level of the specified directory. This tool provides insights into the codebase structure and important constructs, encapsulating high-level concepts and relationships that are crucial for understanding the overall architecture.
|
||||
Parameters:
|
||||
- path: (required) The path of the directory (relative to the current working directory /test/project) to list top level source code definitions for.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<list_code_definition_names>
|
||||
<path>Directory path here</path>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</list_code_definition_names>
|
||||
|
||||
## browser_action
|
||||
@@ -139,10 +144,25 @@ Description: Request to interact with a Puppeteer-controlled browser. Every acti
|
||||
- The browser window has a resolution of **1280x720** pixels. When performing any click actions, ensure the coordinates are within this resolution range.
|
||||
- Before clicking on any elements such as icons, links, or buttons, you must consult the provided screenshot of the page to determine the coordinates of the element. The click should be targeted at the **center of the element**, not on its edges.
|
||||
Parameters:
|
||||
- action: (required) The action to perform. The available actions are: * launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**. - Use with the `url` parameter to provide the URL. - Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.) * click: Click at a specific x,y coordinate. - Use with the `coordinate` parameter to specify the location. - Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot. * type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text. - Use with the `text` parameter to provide the string to type. * scroll_down: Scroll down the page by one page height. * scroll_up: Scroll up the page by one page height. * close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**. - Example: `<action>close</action>`
|
||||
- url: (optional) Use this for providing the URL for the `launch` action. * Example: <url>https://example.com</url>
|
||||
- coordinate: (optional) The X and Y coordinates for the `click` action. Coordinates should be within the **1280x720** resolution. * Example: <coordinate>450,300</coordinate>
|
||||
- text: (optional) Use this for providing the text for the `type` action. * Example: <text>Hello, world!</text>
|
||||
- action: (required) The action to perform. The available actions are:
|
||||
* launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**.
|
||||
- Use with the `url` parameter to provide the URL.
|
||||
- Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.)
|
||||
* click: Click at a specific x,y coordinate.
|
||||
- Use with the `coordinate` parameter to specify the location.
|
||||
- Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot.
|
||||
* type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text.
|
||||
- Use with the `text` parameter to provide the string to type.
|
||||
* scroll_down: Scroll down the page by one page height.
|
||||
* scroll_up: Scroll up the page by one page height.
|
||||
* close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**.
|
||||
- Example: `<action>close</action>`
|
||||
- url: (optional) Use this for providing the URL for the `launch` action.
|
||||
* Example: <url>https://example.com</url>
|
||||
- coordinate: (optional) The X and Y coordinates for the `click` action. Coordinates should be within the **1280x720** resolution.
|
||||
* Example: <coordinate>450,300</coordinate>
|
||||
- text: (optional) Use this for providing the text for the `type` action.
|
||||
* Example: <text>Hello, world!</text>
|
||||
Usage:
|
||||
<browser_action>
|
||||
<action>Action to perform (e.g., launch, click, type, scroll_down, scroll_up, close)</action>
|
||||
@@ -162,9 +182,11 @@ Description: Fetches content from a specified URL and processes into markdown
|
||||
- This tool is read-only and does not modify any files
|
||||
Parameters:
|
||||
- url: (required) The URL to fetch content from
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<web_fetch>
|
||||
<url>https://example.com/docs</url>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</web_fetch>
|
||||
|
||||
## use_mcp_tool
|
||||
@@ -173,28 +195,30 @@ Parameters:
|
||||
- server_name: (required) The name of the MCP server providing the tool
|
||||
- tool_name: (required) The name of the tool to execute
|
||||
- arguments: (required) A JSON object containing the tool's input parameters, following the tool's input schema
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<use_mcp_tool>
|
||||
<server_name>server name here</server_name>
|
||||
<tool_name>tool name here</tool_name>
|
||||
<arguments>{
|
||||
<arguments>
|
||||
{
|
||||
"param1": "value1",
|
||||
"param2": "value2"
|
||||
}</arguments>
|
||||
}
|
||||
</arguments>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</use_mcp_tool>
|
||||
|
||||
## access_mcp_resource
|
||||
Description: The name of the MCP server providing the resource.
|
||||
Description: Request to access a resource provided by a connected MCP server. Resources represent data sources that can be used as context, such as files, API responses, or system information.
|
||||
Parameters:
|
||||
- server_name: (required) server name here
|
||||
- uri: (required) resource URI here
|
||||
- server_name: (required) The name of the MCP server providing the resource
|
||||
- uri: (required) The URI identifying the specific resource to access
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<access_mcp_resource>
|
||||
<server_name></server_name>
|
||||
<uri></uri>
|
||||
<server_name>server name here</server_name>
|
||||
<uri>resource URI here</uri>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</access_mcp_resource>
|
||||
|
||||
@@ -202,11 +226,13 @@ Usage:
|
||||
Description: Ask the user a question to gather additional information needed to complete the task. This tool should be used when you encounter ambiguities, need clarification, or require more details to proceed effectively. It allows for interactive problem-solving by enabling direct communication with the user. Use this tool judiciously to maintain a balance between gathering necessary information and avoiding excessive back-and-forth.
|
||||
Parameters:
|
||||
- question: (required) The question to ask the user. This should be a clear, specific question that addresses the information you need.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer. You may not always need to provide options, but it may be helpful in many cases where it can save the user from having to type out a response manually. IMPORTANT: NEVER include an option to toggle to Act mode, as this would be something you need to direct the user to do manually themselves if needed.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<ask_followup_question>
|
||||
<question>Your question here</question>
|
||||
<options>Array of options here (optional), e.g. ["Option 1", "Option 2", "Option 3"]</options>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</ask_followup_question>
|
||||
|
||||
## attempt_completion
|
||||
@@ -225,7 +251,7 @@ Usage:
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
@@ -250,11 +276,15 @@ Usage:
|
||||
<plan_mode_respond>
|
||||
<response>Your response here</response>
|
||||
<needs_more_exploration>true or false (optional, but you MUST set to true if in <response> you need to read files or use other exploration tools)</needs_more_exploration>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
<task_progress>Checklist here (If you have presented the user with concrete steps or requirements, you can optionally include a todo list outlining these steps.)</task_progress>
|
||||
</plan_mode_respond>
|
||||
|
||||
## load_mcp_documentation
|
||||
Description: Load documentation about creating MCP servers. This tool should be used when the user requests to create or install an MCP server (the user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. You have the ability to create an MCP server and add it to a configuration file that will then expose the tools and resources for you to use with `use_mcp_tool` and `access_mcp_resource`). The documentation provides detailed information about the MCP server creation process, including setup instructions, best practices, and examples.
|
||||
Parameters: None
|
||||
Usage:
|
||||
<load_mcp_documentation>
|
||||
</load_mcp_documentation>
|
||||
|
||||
# Tool Use Examples
|
||||
|
||||
@@ -337,9 +367,7 @@ Description: Load documentation about creating MCP servers. This tool should be
|
||||
<diff>
|
||||
------- SEARCH
|
||||
import React from 'react';
|
||||
|
||||
=======
|
||||
|
||||
import React, { useState } from 'react';
|
||||
+++++++ REPLACE
|
||||
|
||||
@@ -350,15 +378,12 @@ function handleSubmit() {
|
||||
}
|
||||
|
||||
=======
|
||||
|
||||
+++++++ REPLACE
|
||||
|
||||
------- SEARCH
|
||||
return (
|
||||
<div>
|
||||
|
||||
=======
|
||||
|
||||
function handleSubmit() {
|
||||
saveData();
|
||||
setLoading(false);
|
||||
@@ -396,7 +421,7 @@ return (
|
||||
<tool_name>create_issue</tool_name>
|
||||
<arguments>
|
||||
{
|
||||
"owner": "octocat",
|
||||
"owner": "octocat2",
|
||||
"repo": "hello-world",
|
||||
"title": "Found a bug",
|
||||
"body": "I'm having a problem with this.",
|
||||
|
||||
@@ -57,9 +57,7 @@ Key: If output doesn’t stream, assume success unless critical; else ask user t
|
||||
<diff>
|
||||
------- SEARCH
|
||||
console.log('Hi');
|
||||
|
||||
=======
|
||||
|
||||
console.log('Hello');
|
||||
+++++++ REPLACE
|
||||
</diff>
|
||||
|
||||
-2
@@ -57,9 +57,7 @@ Key: If output doesn’t stream, assume success unless critical; else ask user t
|
||||
<diff>
|
||||
------- SEARCH
|
||||
console.log('Hi');
|
||||
|
||||
=======
|
||||
|
||||
console.log('Hello');
|
||||
+++++++ REPLACE
|
||||
</diff>
|
||||
|
||||
-2
@@ -57,9 +57,7 @@ Key: If output doesn’t stream, assume success unless critical; else ask user t
|
||||
<diff>
|
||||
------- SEARCH
|
||||
console.log('Hi');
|
||||
|
||||
=======
|
||||
|
||||
console.log('Hello');
|
||||
+++++++ REPLACE
|
||||
</diff>
|
||||
|
||||
-2
@@ -57,9 +57,7 @@ Key: If output doesn’t stream, assume success unless critical; else ask user t
|
||||
<diff>
|
||||
------- SEARCH
|
||||
console.log('Hi');
|
||||
|
||||
=======
|
||||
|
||||
console.log('Hello');
|
||||
+++++++ REPLACE
|
||||
</diff>
|
||||
|
||||
@@ -30,8 +30,8 @@ Always adhere to this format for the tool use to ensure proper parsing and execu
|
||||
## execute_command
|
||||
Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/project
|
||||
Parameters:
|
||||
- command: (required) The CLI command to execute...
|
||||
- requires_approval: (required) A boolean indicating whether...
|
||||
- command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
|
||||
- requires_approval: (required) A boolean indicating whether this command requires explicit user approval before execution in case the user has auto-approve mode enabled. Set to 'true' for potentially impactful operations like installing/uninstalling packages, deleting/overwriting files, system configuration changes, network operations, or any commands that could have unintended side effects. Set to 'false' for safe operations like reading files/directories, running development servers, building projects, and other non-destructive operations.
|
||||
Usage:
|
||||
<execute_command>
|
||||
<command>Your command here</command>
|
||||
@@ -71,7 +71,6 @@ Parameters:
|
||||
------- SEARCH
|
||||
[exact content to find]
|
||||
=======
|
||||
|
||||
[new content to replace with]
|
||||
+++++++ REPLACE
|
||||
```
|
||||
@@ -105,11 +104,13 @@ Parameters:
|
||||
- path: (required) The path of the directory to search in (relative to the current working directory /test/project). This directory will be recursively searched.
|
||||
- regex: (required) The regular expression pattern to search for. Uses Rust regex syntax.
|
||||
- file_pattern: (optional) Glob pattern to filter files (e.g., '*.ts' for TypeScript files). If not provided, it will search all files (*).
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<search_files>
|
||||
<path>Directory path here</path>
|
||||
<regex>Your regex pattern here</regex>
|
||||
<file_pattern>file pattern here (optional)</file_pattern>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</search_files>
|
||||
|
||||
## list_files
|
||||
@@ -117,19 +118,23 @@ Description: Request to list files and directories within the specified director
|
||||
Parameters:
|
||||
- path: (required) The path of the directory to list contents for (relative to the current working directory /test/project)
|
||||
- recursive: (optional) Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<list_files>
|
||||
<path>Directory path here</path>
|
||||
<recursive>true or false (optional)</recursive>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</list_files>
|
||||
|
||||
## list_code_definition_names
|
||||
Description: Request to list definition names (classes, functions, methods, etc.) used in source code files at the top level of the specified directory. This tool provides insights into the codebase structure and important constructs, encapsulating high-level concepts and relationships that are crucial for understanding the overall architecture.
|
||||
Parameters:
|
||||
- path: (required) The path of the directory (relative to the current working directory /test/project) to list top level source code definitions for.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<list_code_definition_names>
|
||||
<path>Directory path here</path>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</list_code_definition_names>
|
||||
|
||||
## browser_action
|
||||
@@ -139,10 +144,25 @@ Description: Request to interact with a Puppeteer-controlled browser. Every acti
|
||||
- The browser window has a resolution of **1280x720** pixels. When performing any click actions, ensure the coordinates are within this resolution range.
|
||||
- Before clicking on any elements such as icons, links, or buttons, you must consult the provided screenshot of the page to determine the coordinates of the element. The click should be targeted at the **center of the element**, not on its edges.
|
||||
Parameters:
|
||||
- action: (required) The action to perform. The available actions are: * launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**. - Use with the `url` parameter to provide the URL. - Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.) * click: Click at a specific x,y coordinate. - Use with the `coordinate` parameter to specify the location. - Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot. * type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text. - Use with the `text` parameter to provide the string to type. * scroll_down: Scroll down the page by one page height. * scroll_up: Scroll up the page by one page height. * close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**. - Example: `<action>close</action>`
|
||||
- url: (optional) Use this for providing the URL for the `launch` action. * Example: <url>https://example.com</url>
|
||||
- coordinate: (optional) The X and Y coordinates for the `click` action. Coordinates should be within the **1280x720** resolution. * Example: <coordinate>450,300</coordinate>
|
||||
- text: (optional) Use this for providing the text for the `type` action. * Example: <text>Hello, world!</text>
|
||||
- action: (required) The action to perform. The available actions are:
|
||||
* launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**.
|
||||
- Use with the `url` parameter to provide the URL.
|
||||
- Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.)
|
||||
* click: Click at a specific x,y coordinate.
|
||||
- Use with the `coordinate` parameter to specify the location.
|
||||
- Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot.
|
||||
* type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text.
|
||||
- Use with the `text` parameter to provide the string to type.
|
||||
* scroll_down: Scroll down the page by one page height.
|
||||
* scroll_up: Scroll up the page by one page height.
|
||||
* close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**.
|
||||
- Example: `<action>close</action>`
|
||||
- url: (optional) Use this for providing the URL for the `launch` action.
|
||||
* Example: <url>https://example.com</url>
|
||||
- coordinate: (optional) The X and Y coordinates for the `click` action. Coordinates should be within the **1280x720** resolution.
|
||||
* Example: <coordinate>450,300</coordinate>
|
||||
- text: (optional) Use this for providing the text for the `type` action.
|
||||
* Example: <text>Hello, world!</text>
|
||||
Usage:
|
||||
<browser_action>
|
||||
<action>Action to perform (e.g., launch, click, type, scroll_down, scroll_up, close)</action>
|
||||
@@ -157,28 +177,30 @@ Parameters:
|
||||
- server_name: (required) The name of the MCP server providing the tool
|
||||
- tool_name: (required) The name of the tool to execute
|
||||
- arguments: (required) A JSON object containing the tool's input parameters, following the tool's input schema
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<use_mcp_tool>
|
||||
<server_name>server name here</server_name>
|
||||
<tool_name>tool name here</tool_name>
|
||||
<arguments>{
|
||||
<arguments>
|
||||
{
|
||||
"param1": "value1",
|
||||
"param2": "value2"
|
||||
}</arguments>
|
||||
}
|
||||
</arguments>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</use_mcp_tool>
|
||||
|
||||
## access_mcp_resource
|
||||
Description: The name of the MCP server providing the resource.
|
||||
Description: Request to access a resource provided by a connected MCP server. Resources represent data sources that can be used as context, such as files, API responses, or system information.
|
||||
Parameters:
|
||||
- server_name: (required) server name here
|
||||
- uri: (required) resource URI here
|
||||
- server_name: (required) The name of the MCP server providing the resource
|
||||
- uri: (required) The URI identifying the specific resource to access
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<access_mcp_resource>
|
||||
<server_name></server_name>
|
||||
<uri></uri>
|
||||
<server_name>server name here</server_name>
|
||||
<uri>resource URI here</uri>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</access_mcp_resource>
|
||||
|
||||
@@ -186,11 +208,13 @@ Usage:
|
||||
Description: Ask the user a question to gather additional information needed to complete the task. This tool should be used when you encounter ambiguities, need clarification, or require more details to proceed effectively. It allows for interactive problem-solving by enabling direct communication with the user. Use this tool judiciously to maintain a balance between gathering necessary information and avoiding excessive back-and-forth.
|
||||
Parameters:
|
||||
- question: (required) The question to ask the user. This should be a clear, specific question that addresses the information you need.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer. You may not always need to provide options, but it may be helpful in many cases where it can save the user from having to type out a response manually. IMPORTANT: NEVER include an option to toggle to Act mode, as this would be something you need to direct the user to do manually themselves if needed.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<ask_followup_question>
|
||||
<question>Your question here</question>
|
||||
<options>Array of options here (optional), e.g. ["Option 1", "Option 2", "Option 3"]</options>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</ask_followup_question>
|
||||
|
||||
## attempt_completion
|
||||
@@ -209,7 +233,7 @@ Usage:
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
@@ -234,11 +258,15 @@ Usage:
|
||||
<plan_mode_respond>
|
||||
<response>Your response here</response>
|
||||
<needs_more_exploration>true or false (optional, but you MUST set to true if in <response> you need to read files or use other exploration tools)</needs_more_exploration>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
<task_progress>Checklist here (If you have presented the user with concrete steps or requirements, you can optionally include a todo list outlining these steps.)</task_progress>
|
||||
</plan_mode_respond>
|
||||
|
||||
## load_mcp_documentation
|
||||
Description: Load documentation about creating MCP servers. This tool should be used when the user requests to create or install an MCP server (the user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. You have the ability to create an MCP server and add it to a configuration file that will then expose the tools and resources for you to use with `use_mcp_tool` and `access_mcp_resource`). The documentation provides detailed information about the MCP server creation process, including setup instructions, best practices, and examples.
|
||||
Parameters: None
|
||||
Usage:
|
||||
<load_mcp_documentation>
|
||||
</load_mcp_documentation>
|
||||
|
||||
# Tool Use Examples
|
||||
|
||||
@@ -321,9 +349,7 @@ Description: Load documentation about creating MCP servers. This tool should be
|
||||
<diff>
|
||||
------- SEARCH
|
||||
import React from 'react';
|
||||
|
||||
=======
|
||||
|
||||
import React, { useState } from 'react';
|
||||
+++++++ REPLACE
|
||||
|
||||
@@ -334,15 +360,12 @@ function handleSubmit() {
|
||||
}
|
||||
|
||||
=======
|
||||
|
||||
+++++++ REPLACE
|
||||
|
||||
------- SEARCH
|
||||
return (
|
||||
<div>
|
||||
|
||||
=======
|
||||
|
||||
function handleSubmit() {
|
||||
saveData();
|
||||
setLoading(false);
|
||||
@@ -380,7 +403,7 @@ return (
|
||||
<tool_name>create_issue</tool_name>
|
||||
<arguments>
|
||||
{
|
||||
"owner": "octocat",
|
||||
"owner": "octocat2",
|
||||
"repo": "hello-world",
|
||||
"title": "Found a bug",
|
||||
"body": "I'm having a problem with this.",
|
||||
|
||||
+28
-20
@@ -30,8 +30,8 @@ Always adhere to this format for the tool use to ensure proper parsing and execu
|
||||
## execute_command
|
||||
Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/project
|
||||
Parameters:
|
||||
- command: (required) The CLI command to execute...
|
||||
- requires_approval: (required) A boolean indicating whether...
|
||||
- command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
|
||||
- requires_approval: (required) A boolean indicating whether this command requires explicit user approval before execution in case the user has auto-approve mode enabled. Set to 'true' for potentially impactful operations like installing/uninstalling packages, deleting/overwriting files, system configuration changes, network operations, or any commands that could have unintended side effects. Set to 'false' for safe operations like reading files/directories, running development servers, building projects, and other non-destructive operations.
|
||||
Usage:
|
||||
<execute_command>
|
||||
<command>Your command here</command>
|
||||
@@ -71,7 +71,6 @@ Parameters:
|
||||
------- SEARCH
|
||||
[exact content to find]
|
||||
=======
|
||||
|
||||
[new content to replace with]
|
||||
+++++++ REPLACE
|
||||
```
|
||||
@@ -105,11 +104,13 @@ Parameters:
|
||||
- path: (required) The path of the directory to search in (relative to the current working directory /test/project). This directory will be recursively searched.
|
||||
- regex: (required) The regular expression pattern to search for. Uses Rust regex syntax.
|
||||
- file_pattern: (optional) Glob pattern to filter files (e.g., '*.ts' for TypeScript files). If not provided, it will search all files (*).
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<search_files>
|
||||
<path>Directory path here</path>
|
||||
<regex>Your regex pattern here</regex>
|
||||
<file_pattern>file pattern here (optional)</file_pattern>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</search_files>
|
||||
|
||||
## list_files
|
||||
@@ -117,19 +118,23 @@ Description: Request to list files and directories within the specified director
|
||||
Parameters:
|
||||
- path: (required) The path of the directory to list contents for (relative to the current working directory /test/project)
|
||||
- recursive: (optional) Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<list_files>
|
||||
<path>Directory path here</path>
|
||||
<recursive>true or false (optional)</recursive>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</list_files>
|
||||
|
||||
## list_code_definition_names
|
||||
Description: Request to list definition names (classes, functions, methods, etc.) used in source code files at the top level of the specified directory. This tool provides insights into the codebase structure and important constructs, encapsulating high-level concepts and relationships that are crucial for understanding the overall architecture.
|
||||
Parameters:
|
||||
- path: (required) The path of the directory (relative to the current working directory /test/project) to list top level source code definitions for.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<list_code_definition_names>
|
||||
<path>Directory path here</path>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</list_code_definition_names>
|
||||
|
||||
## use_mcp_tool
|
||||
@@ -138,28 +143,30 @@ Parameters:
|
||||
- server_name: (required) The name of the MCP server providing the tool
|
||||
- tool_name: (required) The name of the tool to execute
|
||||
- arguments: (required) A JSON object containing the tool's input parameters, following the tool's input schema
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<use_mcp_tool>
|
||||
<server_name>server name here</server_name>
|
||||
<tool_name>tool name here</tool_name>
|
||||
<arguments>{
|
||||
<arguments>
|
||||
{
|
||||
"param1": "value1",
|
||||
"param2": "value2"
|
||||
}</arguments>
|
||||
}
|
||||
</arguments>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</use_mcp_tool>
|
||||
|
||||
## access_mcp_resource
|
||||
Description: The name of the MCP server providing the resource.
|
||||
Description: Request to access a resource provided by a connected MCP server. Resources represent data sources that can be used as context, such as files, API responses, or system information.
|
||||
Parameters:
|
||||
- server_name: (required) server name here
|
||||
- uri: (required) resource URI here
|
||||
- server_name: (required) The name of the MCP server providing the resource
|
||||
- uri: (required) The URI identifying the specific resource to access
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<access_mcp_resource>
|
||||
<server_name></server_name>
|
||||
<uri></uri>
|
||||
<server_name>server name here</server_name>
|
||||
<uri>resource URI here</uri>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</access_mcp_resource>
|
||||
|
||||
@@ -167,11 +174,13 @@ Usage:
|
||||
Description: Ask the user a question to gather additional information needed to complete the task. This tool should be used when you encounter ambiguities, need clarification, or require more details to proceed effectively. It allows for interactive problem-solving by enabling direct communication with the user. Use this tool judiciously to maintain a balance between gathering necessary information and avoiding excessive back-and-forth.
|
||||
Parameters:
|
||||
- question: (required) The question to ask the user. This should be a clear, specific question that addresses the information you need.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer. You may not always need to provide options, but it may be helpful in many cases where it can save the user from having to type out a response manually. IMPORTANT: NEVER include an option to toggle to Act mode, as this would be something you need to direct the user to do manually themselves if needed.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<ask_followup_question>
|
||||
<question>Your question here</question>
|
||||
<options>Array of options here (optional), e.g. ["Option 1", "Option 2", "Option 3"]</options>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</ask_followup_question>
|
||||
|
||||
## attempt_completion
|
||||
@@ -190,7 +199,7 @@ Usage:
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
@@ -215,11 +224,15 @@ Usage:
|
||||
<plan_mode_respond>
|
||||
<response>Your response here</response>
|
||||
<needs_more_exploration>true or false (optional, but you MUST set to true if in <response> you need to read files or use other exploration tools)</needs_more_exploration>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
<task_progress>Checklist here (If you have presented the user with concrete steps or requirements, you can optionally include a todo list outlining these steps.)</task_progress>
|
||||
</plan_mode_respond>
|
||||
|
||||
## load_mcp_documentation
|
||||
Description: Load documentation about creating MCP servers. This tool should be used when the user requests to create or install an MCP server (the user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. You have the ability to create an MCP server and add it to a configuration file that will then expose the tools and resources for you to use with `use_mcp_tool` and `access_mcp_resource`). The documentation provides detailed information about the MCP server creation process, including setup instructions, best practices, and examples.
|
||||
Parameters: None
|
||||
Usage:
|
||||
<load_mcp_documentation>
|
||||
</load_mcp_documentation>
|
||||
|
||||
# Tool Use Examples
|
||||
|
||||
@@ -302,9 +315,7 @@ Description: Load documentation about creating MCP servers. This tool should be
|
||||
<diff>
|
||||
------- SEARCH
|
||||
import React from 'react';
|
||||
|
||||
=======
|
||||
|
||||
import React, { useState } from 'react';
|
||||
+++++++ REPLACE
|
||||
|
||||
@@ -315,15 +326,12 @@ function handleSubmit() {
|
||||
}
|
||||
|
||||
=======
|
||||
|
||||
+++++++ REPLACE
|
||||
|
||||
------- SEARCH
|
||||
return (
|
||||
<div>
|
||||
|
||||
=======
|
||||
|
||||
function handleSubmit() {
|
||||
saveData();
|
||||
setLoading(false);
|
||||
@@ -361,7 +369,7 @@ return (
|
||||
<tool_name>create_issue</tool_name>
|
||||
<arguments>
|
||||
{
|
||||
"owner": "octocat",
|
||||
"owner": "octocat2",
|
||||
"repo": "hello-world",
|
||||
"title": "Found a bug",
|
||||
"body": "I'm having a problem with this.",
|
||||
|
||||
+37
-22
@@ -27,8 +27,8 @@ Always adhere to this format for the tool use to ensure proper parsing and execu
|
||||
## execute_command
|
||||
Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/project
|
||||
Parameters:
|
||||
- command: (required) The CLI command to execute...
|
||||
- requires_approval: (required) A boolean indicating whether...
|
||||
- command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
|
||||
- requires_approval: (required) A boolean indicating whether this command requires explicit user approval before execution in case the user has auto-approve mode enabled. Set to 'true' for potentially impactful operations like installing/uninstalling packages, deleting/overwriting files, system configuration changes, network operations, or any commands that could have unintended side effects. Set to 'false' for safe operations like reading files/directories, running development servers, building projects, and other non-destructive operations.
|
||||
Usage:
|
||||
<execute_command>
|
||||
<command>Your command here</command>
|
||||
@@ -64,7 +64,6 @@ Parameters:
|
||||
------- SEARCH
|
||||
[exact content to find]
|
||||
=======
|
||||
|
||||
[new content to replace with]
|
||||
+++++++ REPLACE
|
||||
```
|
||||
@@ -130,10 +129,25 @@ Description: Request to interact with a Puppeteer-controlled browser. Every acti
|
||||
- The browser window has a resolution of **1280x720** pixels. When performing any click actions, ensure the coordinates are within this resolution range.
|
||||
- Before clicking on any elements such as icons, links, or buttons, you must consult the provided screenshot of the page to determine the coordinates of the element. The click should be targeted at the **center of the element**, not on its edges.
|
||||
Parameters:
|
||||
- action: (required) The action to perform. The available actions are: * launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**. - Use with the `url` parameter to provide the URL. - Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.) * click: Click at a specific x,y coordinate. - Use with the `coordinate` parameter to specify the location. - Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot. * type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text. - Use with the `text` parameter to provide the string to type. * scroll_down: Scroll down the page by one page height. * scroll_up: Scroll up the page by one page height. * close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**. - Example: `<action>close</action>`
|
||||
- url: (optional) Use this for providing the URL for the `launch` action. * Example: <url>https://example.com</url>
|
||||
- coordinate: (optional) The X and Y coordinates for the `click` action. Coordinates should be within the **1280x720** resolution. * Example: <coordinate>450,300</coordinate>
|
||||
- text: (optional) Use this for providing the text for the `type` action. * Example: <text>Hello, world!</text>
|
||||
- action: (required) The action to perform. The available actions are:
|
||||
* launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**.
|
||||
- Use with the `url` parameter to provide the URL.
|
||||
- Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.)
|
||||
* click: Click at a specific x,y coordinate.
|
||||
- Use with the `coordinate` parameter to specify the location.
|
||||
- Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot.
|
||||
* type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text.
|
||||
- Use with the `text` parameter to provide the string to type.
|
||||
* scroll_down: Scroll down the page by one page height.
|
||||
* scroll_up: Scroll up the page by one page height.
|
||||
* close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**.
|
||||
- Example: `<action>close</action>`
|
||||
- url: (optional) Use this for providing the URL for the `launch` action.
|
||||
* Example: <url>https://example.com</url>
|
||||
- coordinate: (optional) The X and Y coordinates for the `click` action. Coordinates should be within the **1280x720** resolution.
|
||||
* Example: <coordinate>450,300</coordinate>
|
||||
- text: (optional) Use this for providing the text for the `type` action.
|
||||
* Example: <text>Hello, world!</text>
|
||||
Usage:
|
||||
<browser_action>
|
||||
<action>Action to perform (e.g., launch, click, type, scroll_down, scroll_up, close)</action>
|
||||
@@ -152,28 +166,30 @@ Usage:
|
||||
<use_mcp_tool>
|
||||
<server_name>server name here</server_name>
|
||||
<tool_name>tool name here</tool_name>
|
||||
<arguments>{
|
||||
<arguments>
|
||||
{
|
||||
"param1": "value1",
|
||||
"param2": "value2"
|
||||
}</arguments>
|
||||
}
|
||||
</arguments>
|
||||
</use_mcp_tool>
|
||||
|
||||
## access_mcp_resource
|
||||
Description: The name of the MCP server providing the resource.
|
||||
Description: Request to access a resource provided by a connected MCP server. Resources represent data sources that can be used as context, such as files, API responses, or system information.
|
||||
Parameters:
|
||||
- server_name: (required) server name here
|
||||
- uri: (required) resource URI here
|
||||
- server_name: (required) The name of the MCP server providing the resource
|
||||
- uri: (required) The URI identifying the specific resource to access
|
||||
Usage:
|
||||
<access_mcp_resource>
|
||||
<server_name></server_name>
|
||||
<uri></uri>
|
||||
<server_name>server name here</server_name>
|
||||
<uri>resource URI here</uri>
|
||||
</access_mcp_resource>
|
||||
|
||||
## ask_followup_question
|
||||
Description: Ask the user a question to gather additional information needed to complete the task. This tool should be used when you encounter ambiguities, need clarification, or require more details to proceed effectively. It allows for interactive problem-solving by enabling direct communication with the user. Use this tool judiciously to maintain a balance between gathering necessary information and avoiding excessive back-and-forth.
|
||||
Parameters:
|
||||
- question: (required) The question to ask the user. This should be a clear, specific question that addresses the information you need.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer. You may not always need to provide options, but it may be helpful in many cases where it can save the user from having to type out a response manually. IMPORTANT: NEVER include an option to toggle to Act mode, as this would be something you need to direct the user to do manually themselves if needed.
|
||||
Usage:
|
||||
<ask_followup_question>
|
||||
<question>Your question here</question>
|
||||
@@ -193,7 +209,7 @@ Usage:
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
@@ -221,6 +237,10 @@ Usage:
|
||||
|
||||
## load_mcp_documentation
|
||||
Description: Load documentation about creating MCP servers. This tool should be used when the user requests to create or install an MCP server (the user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. You have the ability to create an MCP server and add it to a configuration file that will then expose the tools and resources for you to use with `use_mcp_tool` and `access_mcp_resource`). The documentation provides detailed information about the MCP server creation process, including setup instructions, best practices, and examples.
|
||||
Parameters: None
|
||||
Usage:
|
||||
<load_mcp_documentation>
|
||||
</load_mcp_documentation>
|
||||
|
||||
# Tool Use Examples
|
||||
|
||||
@@ -291,9 +311,7 @@ Description: Load documentation about creating MCP servers. This tool should be
|
||||
<diff>
|
||||
------- SEARCH
|
||||
import React from 'react';
|
||||
|
||||
=======
|
||||
|
||||
import React, { useState } from 'react';
|
||||
+++++++ REPLACE
|
||||
|
||||
@@ -304,15 +322,12 @@ function handleSubmit() {
|
||||
}
|
||||
|
||||
=======
|
||||
|
||||
+++++++ REPLACE
|
||||
|
||||
------- SEARCH
|
||||
return (
|
||||
<div>
|
||||
|
||||
=======
|
||||
|
||||
function handleSubmit() {
|
||||
saveData();
|
||||
setLoading(false);
|
||||
@@ -344,7 +359,7 @@ return (
|
||||
<tool_name>create_issue</tool_name>
|
||||
<arguments>
|
||||
{
|
||||
"owner": "octocat",
|
||||
"owner": "octocat2",
|
||||
"repo": "hello-world",
|
||||
"title": "Found a bug",
|
||||
"body": "I'm having a problem with this.",
|
||||
|
||||
@@ -30,8 +30,8 @@ Always adhere to this format for the tool use to ensure proper parsing and execu
|
||||
## execute_command
|
||||
Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/project
|
||||
Parameters:
|
||||
- command: (required) The CLI command to execute...
|
||||
- requires_approval: (required) A boolean indicating whether...
|
||||
- command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
|
||||
- requires_approval: (required) A boolean indicating whether this command requires explicit user approval before execution in case the user has auto-approve mode enabled. Set to 'true' for potentially impactful operations like installing/uninstalling packages, deleting/overwriting files, system configuration changes, network operations, or any commands that could have unintended side effects. Set to 'false' for safe operations like reading files/directories, running development servers, building projects, and other non-destructive operations.
|
||||
Usage:
|
||||
<execute_command>
|
||||
<command>Your command here</command>
|
||||
@@ -71,7 +71,6 @@ Parameters:
|
||||
------- SEARCH
|
||||
[exact content to find]
|
||||
=======
|
||||
|
||||
[new content to replace with]
|
||||
+++++++ REPLACE
|
||||
```
|
||||
@@ -105,11 +104,13 @@ Parameters:
|
||||
- path: (required) The path of the directory to search in (relative to the current working directory /test/project). This directory will be recursively searched.
|
||||
- regex: (required) The regular expression pattern to search for. Uses Rust regex syntax.
|
||||
- file_pattern: (optional) Glob pattern to filter files (e.g., '*.ts' for TypeScript files). If not provided, it will search all files (*).
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<search_files>
|
||||
<path>Directory path here</path>
|
||||
<regex>Your regex pattern here</regex>
|
||||
<file_pattern>file pattern here (optional)</file_pattern>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</search_files>
|
||||
|
||||
## list_files
|
||||
@@ -117,19 +118,23 @@ Description: Request to list files and directories within the specified director
|
||||
Parameters:
|
||||
- path: (required) The path of the directory to list contents for (relative to the current working directory /test/project)
|
||||
- recursive: (optional) Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<list_files>
|
||||
<path>Directory path here</path>
|
||||
<recursive>true or false (optional)</recursive>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</list_files>
|
||||
|
||||
## list_code_definition_names
|
||||
Description: Request to list definition names (classes, functions, methods, etc.) used in source code files at the top level of the specified directory. This tool provides insights into the codebase structure and important constructs, encapsulating high-level concepts and relationships that are crucial for understanding the overall architecture.
|
||||
Parameters:
|
||||
- path: (required) The path of the directory (relative to the current working directory /test/project) to list top level source code definitions for.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<list_code_definition_names>
|
||||
<path>Directory path here</path>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</list_code_definition_names>
|
||||
|
||||
## browser_action
|
||||
@@ -139,10 +144,25 @@ Description: Request to interact with a Puppeteer-controlled browser. Every acti
|
||||
- The browser window has a resolution of **1280x720** pixels. When performing any click actions, ensure the coordinates are within this resolution range.
|
||||
- Before clicking on any elements such as icons, links, or buttons, you must consult the provided screenshot of the page to determine the coordinates of the element. The click should be targeted at the **center of the element**, not on its edges.
|
||||
Parameters:
|
||||
- action: (required) The action to perform. The available actions are: * launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**. - Use with the `url` parameter to provide the URL. - Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.) * click: Click at a specific x,y coordinate. - Use with the `coordinate` parameter to specify the location. - Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot. * type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text. - Use with the `text` parameter to provide the string to type. * scroll_down: Scroll down the page by one page height. * scroll_up: Scroll up the page by one page height. * close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**. - Example: `<action>close</action>`
|
||||
- url: (optional) Use this for providing the URL for the `launch` action. * Example: <url>https://example.com</url>
|
||||
- coordinate: (optional) The X and Y coordinates for the `click` action. Coordinates should be within the **1280x720** resolution. * Example: <coordinate>450,300</coordinate>
|
||||
- text: (optional) Use this for providing the text for the `type` action. * Example: <text>Hello, world!</text>
|
||||
- action: (required) The action to perform. The available actions are:
|
||||
* launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**.
|
||||
- Use with the `url` parameter to provide the URL.
|
||||
- Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.)
|
||||
* click: Click at a specific x,y coordinate.
|
||||
- Use with the `coordinate` parameter to specify the location.
|
||||
- Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot.
|
||||
* type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text.
|
||||
- Use with the `text` parameter to provide the string to type.
|
||||
* scroll_down: Scroll down the page by one page height.
|
||||
* scroll_up: Scroll up the page by one page height.
|
||||
* close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**.
|
||||
- Example: `<action>close</action>`
|
||||
- url: (optional) Use this for providing the URL for the `launch` action.
|
||||
* Example: <url>https://example.com</url>
|
||||
- coordinate: (optional) The X and Y coordinates for the `click` action. Coordinates should be within the **1280x720** resolution.
|
||||
* Example: <coordinate>450,300</coordinate>
|
||||
- text: (optional) Use this for providing the text for the `type` action.
|
||||
* Example: <text>Hello, world!</text>
|
||||
Usage:
|
||||
<browser_action>
|
||||
<action>Action to perform (e.g., launch, click, type, scroll_down, scroll_up, close)</action>
|
||||
@@ -157,28 +177,30 @@ Parameters:
|
||||
- server_name: (required) The name of the MCP server providing the tool
|
||||
- tool_name: (required) The name of the tool to execute
|
||||
- arguments: (required) A JSON object containing the tool's input parameters, following the tool's input schema
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<use_mcp_tool>
|
||||
<server_name>server name here</server_name>
|
||||
<tool_name>tool name here</tool_name>
|
||||
<arguments>{
|
||||
<arguments>
|
||||
{
|
||||
"param1": "value1",
|
||||
"param2": "value2"
|
||||
}</arguments>
|
||||
}
|
||||
</arguments>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</use_mcp_tool>
|
||||
|
||||
## access_mcp_resource
|
||||
Description: The name of the MCP server providing the resource.
|
||||
Description: Request to access a resource provided by a connected MCP server. Resources represent data sources that can be used as context, such as files, API responses, or system information.
|
||||
Parameters:
|
||||
- server_name: (required) server name here
|
||||
- uri: (required) resource URI here
|
||||
- server_name: (required) The name of the MCP server providing the resource
|
||||
- uri: (required) The URI identifying the specific resource to access
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<access_mcp_resource>
|
||||
<server_name></server_name>
|
||||
<uri></uri>
|
||||
<server_name>server name here</server_name>
|
||||
<uri>resource URI here</uri>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</access_mcp_resource>
|
||||
|
||||
@@ -186,11 +208,13 @@ Usage:
|
||||
Description: Ask the user a question to gather additional information needed to complete the task. This tool should be used when you encounter ambiguities, need clarification, or require more details to proceed effectively. It allows for interactive problem-solving by enabling direct communication with the user. Use this tool judiciously to maintain a balance between gathering necessary information and avoiding excessive back-and-forth.
|
||||
Parameters:
|
||||
- question: (required) The question to ask the user. This should be a clear, specific question that addresses the information you need.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer.
|
||||
- options: (optional) An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer. You may not always need to provide options, but it may be helpful in many cases where it can save the user from having to type out a response manually. IMPORTANT: NEVER include an option to toggle to Act mode, as this would be something you need to direct the user to do manually themselves if needed.
|
||||
- task_progress: (optional) A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)
|
||||
Usage:
|
||||
<ask_followup_question>
|
||||
<question>Your question here</question>
|
||||
<options>Array of options here (optional), e.g. ["Option 1", "Option 2", "Option 3"]</options>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
</ask_followup_question>
|
||||
|
||||
## attempt_completion
|
||||
@@ -209,7 +233,7 @@ Usage:
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
@@ -234,11 +258,15 @@ Usage:
|
||||
<plan_mode_respond>
|
||||
<response>Your response here</response>
|
||||
<needs_more_exploration>true or false (optional, but you MUST set to true if in <response> you need to read files or use other exploration tools)</needs_more_exploration>
|
||||
<task_progress>Checklist here (optional)</task_progress>
|
||||
<task_progress>Checklist here (If you have presented the user with concrete steps or requirements, you can optionally include a todo list outlining these steps.)</task_progress>
|
||||
</plan_mode_respond>
|
||||
|
||||
## load_mcp_documentation
|
||||
Description: Load documentation about creating MCP servers. This tool should be used when the user requests to create or install an MCP server (the user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. You have the ability to create an MCP server and add it to a configuration file that will then expose the tools and resources for you to use with `use_mcp_tool` and `access_mcp_resource`). The documentation provides detailed information about the MCP server creation process, including setup instructions, best practices, and examples.
|
||||
Parameters: None
|
||||
Usage:
|
||||
<load_mcp_documentation>
|
||||
</load_mcp_documentation>
|
||||
|
||||
# Tool Use Examples
|
||||
|
||||
@@ -321,9 +349,7 @@ Description: Load documentation about creating MCP servers. This tool should be
|
||||
<diff>
|
||||
------- SEARCH
|
||||
import React from 'react';
|
||||
|
||||
=======
|
||||
|
||||
import React, { useState } from 'react';
|
||||
+++++++ REPLACE
|
||||
|
||||
@@ -334,15 +360,12 @@ function handleSubmit() {
|
||||
}
|
||||
|
||||
=======
|
||||
|
||||
+++++++ REPLACE
|
||||
|
||||
------- SEARCH
|
||||
return (
|
||||
<div>
|
||||
|
||||
=======
|
||||
|
||||
function handleSubmit() {
|
||||
saveData();
|
||||
setLoading(false);
|
||||
@@ -380,7 +403,7 @@ return (
|
||||
<tool_name>create_issue</tool_name>
|
||||
<arguments>
|
||||
{
|
||||
"owner": "octocat",
|
||||
"owner": "octocat2",
|
||||
"repo": "hello-world",
|
||||
"title": "Found a bug",
|
||||
"body": "I'm having a problem with this.",
|
||||
|
||||
@@ -63,7 +63,9 @@ ${differences}
|
||||
|
||||
// Helper to compare two strings and return differences
|
||||
const compareStrings = (expected: string, actual: string): string | null => {
|
||||
if (expected === actual) return null
|
||||
if (expected === actual) {
|
||||
return null
|
||||
}
|
||||
|
||||
const expectedLines = expected.split("\n")
|
||||
const actualLines = actual.split("\n")
|
||||
|
||||
@@ -143,7 +143,7 @@ return (
|
||||
<tool_name>create_issue</tool_name>
|
||||
<arguments>
|
||||
{
|
||||
"owner": "octocat",
|
||||
"owner": "octocat2",
|
||||
"repo": "hello-world",
|
||||
"title": "Found a bug",
|
||||
"body": "I'm having a problem with this.",
|
||||
|
||||
@@ -94,8 +94,23 @@ export class PromptBuilder {
|
||||
.trim() // Remove leading/trailing whitespace
|
||||
.replace(/====+\s*$/, "") // Remove trailing ==== after trim
|
||||
.replace(/\n====+\s*\n+\s*====+\n/g, "\n====\n") // Remove empty sections between separators
|
||||
.replace(/====\n([^\n])/g, "====\n\n$1") // Ensure proper section separation
|
||||
.replace(/([^\n])\n====/g, "$1\n\n====")
|
||||
.replace(/====+\n(?!\n)([^\n])/g, (match, nextChar, offset, string) => {
|
||||
// Add extra newline after ====+ if not already followed by a newline
|
||||
// Exception: preserve single newlines when ====+ appears to be part of diff-like content
|
||||
// Look for patterns like "SEARCH\n=======\n" or ";\n=======\n" (diff markers)
|
||||
const beforeContext = string.substring(Math.max(0, offset - 50), offset)
|
||||
const afterContext = string.substring(offset, Math.min(string.length, offset + 50))
|
||||
const isDiffLike = /SEARCH|REPLACE|\+\+\+\+\+\+\+|-------/.test(beforeContext + afterContext)
|
||||
return isDiffLike ? match : match.replace(/\n/, "\n\n")
|
||||
})
|
||||
.replace(/([^\n])\n(?!\n)====+/g, (match, prevChar, offset, string) => {
|
||||
// Add extra newline before ====+ if not already preceded by a newline
|
||||
// Exception: preserve single newlines when ====+ appears to be part of diff-like content
|
||||
const beforeContext = string.substring(Math.max(0, offset - 50), offset)
|
||||
const afterContext = string.substring(offset, Math.min(string.length, offset + 50))
|
||||
const isDiffLike = /SEARCH|REPLACE|\+\+\+\+\+\+\+|-------/.test(beforeContext + afterContext)
|
||||
return isDiffLike ? match : prevChar + "\n\n" + match.substring(1).replace(/\n/, "")
|
||||
})
|
||||
}
|
||||
|
||||
getBuildMetadata(): {
|
||||
|
||||
@@ -3,6 +3,8 @@ import { getModelFamily } from ".."
|
||||
import { getSystemPromptComponents } from "../components"
|
||||
import { registerClineToolSets } from "../tools"
|
||||
import type { ComponentFunction, ComponentRegistry, PromptVariant, SystemPromptContext } from "../types"
|
||||
import { loadAllVariantConfigs } from "../variants"
|
||||
import { config as genericConfig } from "../variants/generic/config"
|
||||
import { PromptBuilder } from "./PromptBuilder"
|
||||
|
||||
export class PromptRegistry {
|
||||
@@ -32,9 +34,37 @@ export class PromptRegistry {
|
||||
|
||||
await Promise.all([this.loadVariants(), this.loadComponents()])
|
||||
|
||||
// Perform health check to ensure critical variants are available
|
||||
this.performHealthCheck()
|
||||
|
||||
this.loaded = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform health check to ensure registry is in a valid state
|
||||
*/
|
||||
private performHealthCheck(): void {
|
||||
const criticalVariants = [ModelFamily.GENERIC]
|
||||
const missingVariants = criticalVariants.filter((variant) => !this.variants.has(variant))
|
||||
|
||||
if (missingVariants.length > 0) {
|
||||
console.error(`Registry health check failed: Missing critical variants: ${missingVariants.join(", ")}`)
|
||||
console.error(`Available variants: ${Array.from(this.variants.keys()).join(", ")}`)
|
||||
}
|
||||
|
||||
if (this.variants.size === 0) {
|
||||
console.error("Registry health check failed: No variants loaded at all")
|
||||
}
|
||||
|
||||
if (Object.keys(this.components).length === 0) {
|
||||
console.warn("Registry health check warning: No components loaded")
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Registry health check: ${this.variants.size} variants, ${Object.keys(this.components).length} components loaded`,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prompt by model ID with fallback to generic
|
||||
*/
|
||||
@@ -43,11 +73,31 @@ export class PromptRegistry {
|
||||
|
||||
// Try model family fallback (e.g., "claude-4" -> "claude")
|
||||
const modelFamily = getModelFamily(context.providerInfo)
|
||||
const variant = this.variants.get(modelFamily ?? ModelFamily.GENERIC)
|
||||
let variant = this.variants.get(modelFamily ?? ModelFamily.GENERIC)
|
||||
|
||||
// If no variant found for the detected family, explicitly try generic
|
||||
if (!variant && modelFamily !== ModelFamily.GENERIC) {
|
||||
variant = this.variants.get(ModelFamily.GENERIC)
|
||||
}
|
||||
|
||||
if (!variant) {
|
||||
// Enhanced error with debugging information
|
||||
const availableVariants = Array.from(this.variants.keys())
|
||||
const errorDetails = {
|
||||
requestedModel: context.providerInfo.model.id,
|
||||
detectedFamily: modelFamily,
|
||||
availableVariants,
|
||||
variantsCount: this.variants.size,
|
||||
componentsCount: Object.keys(this.components).length,
|
||||
isLoaded: this.loaded,
|
||||
}
|
||||
|
||||
console.error("Prompt variant lookup failed:", errorDetails)
|
||||
|
||||
throw new Error(
|
||||
`No prompt variant found for model '${context.providerInfo.model.id}' and no generic fallback available`,
|
||||
`No prompt variant found for model '${context.providerInfo.model.id}' (family: ${modelFamily}) and no generic fallback available. ` +
|
||||
`Available variants: [${availableVariants.join(", ")}]. ` +
|
||||
`Registry state: loaded=${this.loaded}, variants=${this.variants.size}, components=${Object.keys(this.components).length}`,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -184,30 +234,44 @@ export class PromptRegistry {
|
||||
/**
|
||||
* Load all variants from the variants directory
|
||||
*/
|
||||
private async loadVariants(): Promise<void> {
|
||||
private loadVariants(): void {
|
||||
try {
|
||||
const { VARIANT_CONFIGS } = await import("../variants")
|
||||
this.variants = new Map<string, PromptVariant>()
|
||||
|
||||
// Load each variant configuration
|
||||
const loadPromises = Object.entries(VARIANT_CONFIGS).map(async ([variantId, configLoader]) => {
|
||||
try {
|
||||
const config = await configLoader()
|
||||
await this.loadVariantFromConfig(variantId, config)
|
||||
} catch (error) {
|
||||
console.warn(`Warning: Could not load variant '${variantId}':`, error)
|
||||
}
|
||||
})
|
||||
for (const [id, config] of Object.entries(loadAllVariantConfigs())) {
|
||||
this.variants.set(id, { ...config, id })
|
||||
}
|
||||
|
||||
await Promise.all(loadPromises)
|
||||
// Ensure generic variant is always available as a safety fallback
|
||||
this.ensureGenericFallback()
|
||||
} catch (error) {
|
||||
console.warn("Warning: Could not load variants:", error)
|
||||
// Even if variant loading fails completely, create a minimal generic fallback
|
||||
this.createMinimalGenericFallback()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure generic variant is available, create minimal one if missing
|
||||
*/
|
||||
private ensureGenericFallback(): void {
|
||||
if (!this.variants.has(ModelFamily.GENERIC)) {
|
||||
console.warn("Generic variant not found, creating minimal fallback")
|
||||
this.createMinimalGenericFallback()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a minimal generic variant as absolute fallback
|
||||
*/
|
||||
private createMinimalGenericFallback(): void {
|
||||
this.loadVariantFromConfig(ModelFamily.GENERIC, genericConfig)
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a single variant from its TypeScript config
|
||||
*/
|
||||
private async loadVariantFromConfig(variantId: string, config: Omit<PromptVariant, "id">): Promise<void> {
|
||||
private loadVariantFromConfig(variantId: string, config: Omit<PromptVariant, "id">): void {
|
||||
try {
|
||||
const variant: PromptVariant = {
|
||||
...config,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ModelFamily } from "@/shared/prompts"
|
||||
import { ClineDefaultTool } from "@/shared/tools"
|
||||
import type { ClineToolSpec } from "../spec"
|
||||
import { TASK_PROGRESS_PARAMETER } from "../types"
|
||||
|
||||
/**
|
||||
* ## access_mcp_resource
|
||||
@@ -23,27 +24,23 @@ const generic: ClineToolSpec = {
|
||||
variant: ModelFamily.GENERIC,
|
||||
id: ClineDefaultTool.MCP_ACCESS,
|
||||
name: "access_mcp_resource",
|
||||
description: "The name of the MCP server providing the resource.",
|
||||
description:
|
||||
"Request to access a resource provided by a connected MCP server. Resources represent data sources that can be used as context, such as files, API responses, or system information.",
|
||||
contextRequirements: (context) => context.mcpHub !== undefined && context.mcpHub !== null,
|
||||
parameters: [
|
||||
{
|
||||
name: "server_name",
|
||||
required: true,
|
||||
instruction: "server name here",
|
||||
instruction: "The name of the MCP server providing the resource",
|
||||
usage: "server name here",
|
||||
},
|
||||
{
|
||||
name: "uri",
|
||||
required: true,
|
||||
instruction: "resource URI here",
|
||||
},
|
||||
{
|
||||
name: "task_progress",
|
||||
required: false,
|
||||
instruction:
|
||||
"A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)",
|
||||
usage: "Checklist here (optional)",
|
||||
dependencies: [ClineDefaultTool.TODO],
|
||||
instruction: "The URI identifying the specific resource to access",
|
||||
usage: "resource URI here",
|
||||
},
|
||||
TASK_PROGRESS_PARAMETER,
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ModelFamily } from "@/shared/prompts"
|
||||
import { ClineDefaultTool } from "@/shared/tools"
|
||||
import type { ClineToolSpec } from "../spec"
|
||||
import { TASK_PROGRESS_PARAMETER } from "../types"
|
||||
|
||||
const generic: ClineToolSpec = {
|
||||
variant: ModelFamily.GENERIC,
|
||||
@@ -20,9 +21,10 @@ const generic: ClineToolSpec = {
|
||||
name: "options",
|
||||
required: false,
|
||||
instruction:
|
||||
"An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer.",
|
||||
"An array of 2-5 options for the user to choose from. Each option should be a string describing a possible answer. You may not always need to provide options, but it may be helpful in many cases where it can save the user from having to type out a response manually. IMPORTANT: NEVER include an option to toggle to Act mode, as this would be something you need to direct the user to do manually themselves if needed.",
|
||||
usage: 'Array of options here (optional), e.g. ["Option 1", "Option 2", "Option 3"]',
|
||||
},
|
||||
TASK_PROGRESS_PARAMETER,
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user th
|
||||
"A CLI command to execute to show a live demo of the result to the user. For example, use \`open index.html\` to display a created html website, or \`open localhost:3000\` to display a locally running development server. But DO NOT use commands like \`echo\` or \`cat\` that merely print text. This command should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions",
|
||||
usage: "Your command here (optional)",
|
||||
},
|
||||
// Different than the vanilla ASK_PROGRESS_PARAMETER
|
||||
{
|
||||
name: "task_progress",
|
||||
required: false,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { z } from "zod"
|
||||
import { ModelFamily } from "@/shared/prompts"
|
||||
import { ClineDefaultTool } from "@/shared/tools"
|
||||
import type { ClineToolSpec } from "../spec"
|
||||
@@ -19,46 +18,43 @@ const generic: ClineToolSpec = {
|
||||
{
|
||||
name: "action",
|
||||
required: true,
|
||||
instruction:
|
||||
"The action to perform. The available actions are: * launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**. - Use with the `url` parameter to provide the URL. - Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.) * click: Click at a specific x,y coordinate. - Use with the `coordinate` parameter to specify the location. - Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot. * type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text. - Use with the `text` parameter to provide the string to type. * scroll_down: Scroll down the page by one page height. * scroll_up: Scroll up the page by one page height. * close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**. - Example: `<action>close</action>`",
|
||||
instruction: `The action to perform. The available actions are:
|
||||
* launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**.
|
||||
- Use with the \`url\` parameter to provide the URL.
|
||||
- Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.)
|
||||
* click: Click at a specific x,y coordinate.
|
||||
- Use with the \`coordinate\` parameter to specify the location.
|
||||
- Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot.
|
||||
* type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text.
|
||||
- Use with the \`text\` parameter to provide the string to type.
|
||||
* scroll_down: Scroll down the page by one page height.
|
||||
* scroll_up: Scroll up the page by one page height.
|
||||
* close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**.
|
||||
- Example: \`<action>close</action>\``,
|
||||
usage: "Action to perform (e.g., launch, click, type, scroll_down, scroll_up, close)",
|
||||
},
|
||||
{
|
||||
name: "url",
|
||||
required: false,
|
||||
instruction: "Use this for providing the URL for the `launch` action. * Example: <url>https://example.com</url>",
|
||||
instruction: `Use this for providing the URL for the \`launch\` action.
|
||||
* Example: <url>https://example.com</url>`,
|
||||
usage: "URL to launch the browser at (optional)",
|
||||
},
|
||||
{
|
||||
name: "coordinate",
|
||||
required: false,
|
||||
instruction: `The X and Y coordinates for the \`click\` action. Coordinates should be within the **{{BROWSER_VIEWPORT_WIDTH}}x{{BROWSER_VIEWPORT_HEIGHT}}** resolution. * Example: <coordinate>450,300</coordinate>`,
|
||||
instruction: `The X and Y coordinates for the \`click\` action. Coordinates should be within the **{{BROWSER_VIEWPORT_WIDTH}}x{{BROWSER_VIEWPORT_HEIGHT}}** resolution.
|
||||
* Example: <coordinate>450,300</coordinate>`,
|
||||
usage: "x,y coordinates (optional)",
|
||||
},
|
||||
{
|
||||
name: "text",
|
||||
required: false,
|
||||
instruction: "Use this for providing the text for the `type` action. * Example: <text>Hello, world!</text>",
|
||||
instruction: `Use this for providing the text for the \`type\` action.
|
||||
* Example: <text>Hello, world!</text>`,
|
||||
usage: "Text to type (optional)",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export const browser_action_zod_schema = z.object({
|
||||
action: z
|
||||
.enum(["launch", "click", "type", "scroll_down", "scroll_up", "close"])
|
||||
.describe(
|
||||
"The action to perform. The available actions are: * launch: Launch a new Puppeteer-controlled browser instance at the specified URL. This **must always be the first action**. - Use with the `url` parameter to provide the URL. - Ensure the URL is valid and includes the appropriate protocol (e.g. http://localhost:3000/page, file:///path/to/file.html, etc.) * click: Click at a specific x,y coordinate. - Use with the `coordinate` parameter to specify the location. - Always click in the center of an element (icon, button, link, etc.) based on coordinates derived from a screenshot. * type: Type a string of text on the keyboard. You might use this after clicking on a text field to input text. - Use with the `text` parameter to provide the string to type. * scroll_down: Scroll down the page by one page height. * scroll_up: Scroll up the page by one page height. * close: Close the Puppeteer-controlled browser instance. This **must always be the final browser action**.",
|
||||
),
|
||||
url: z.string().url().optional().describe("Use this for providing the URL for the `launch` action."),
|
||||
coordinate: z
|
||||
.string()
|
||||
.regex(/^\d+,\d+$/)
|
||||
.optional()
|
||||
.describe(
|
||||
"The X and Y coordinates for the `click` action. Coordinates should be within the **{{BROWSER_VIEWPORT_WIDTH}}x{{BROWSER_VIEWPORT_HEIGHT}}** resolution. * Example: <coordinate>450,300</coordinate>",
|
||||
),
|
||||
text: z.string().max(1000).optional().describe("Use this for providing the text for the `type` action."),
|
||||
})
|
||||
|
||||
export const browser_action_variants = [generic]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ModelFamily } from "@/shared/prompts"
|
||||
import { ClineDefaultTool } from "@/shared/tools"
|
||||
import type { ClineToolSpec } from "../spec"
|
||||
import { TASK_PROGRESS_PARAMETER } from "../types"
|
||||
|
||||
const generic: ClineToolSpec = {
|
||||
variant: ModelFamily.GENERIC,
|
||||
@@ -11,13 +12,14 @@ const generic: ClineToolSpec = {
|
||||
{
|
||||
name: "command",
|
||||
required: true,
|
||||
instruction: "The CLI command to execute...",
|
||||
instruction: `The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.`,
|
||||
usage: "Your command here",
|
||||
},
|
||||
{
|
||||
name: "requires_approval",
|
||||
required: true,
|
||||
instruction: "A boolean indicating whether...",
|
||||
instruction:
|
||||
"A boolean indicating whether this command requires explicit user approval before execution in case the user has auto-approve mode enabled. Set to 'true' for potentially impactful operations like installing/uninstalling packages, deleting/overwriting files, system configuration changes, network operations, or any commands that could have unintended side effects. Set to 'false' for safe operations like reading files/directories, running development servers, building projects, and other non-destructive operations.",
|
||||
usage: "true or false",
|
||||
},
|
||||
],
|
||||
@@ -41,6 +43,7 @@ const gpt = {
|
||||
required: false,
|
||||
instruction: "Whether the command is dangerous. If true, user will be asked to confirm.",
|
||||
},
|
||||
TASK_PROGRESS_PARAMETER,
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ModelFamily } from "@/shared/prompts"
|
||||
import { ClineDefaultTool } from "@/shared/tools"
|
||||
import type { ClineToolSpec } from "../spec"
|
||||
import { TASK_PROGRESS_PARAMETER } from "../types"
|
||||
|
||||
const id = ClineDefaultTool.LIST_CODE_DEF
|
||||
|
||||
@@ -17,6 +18,7 @@ const generic: ClineToolSpec = {
|
||||
instruction: `The path of the directory (relative to the current working directory {{CWD}}) to list top level source code definitions for.`,
|
||||
usage: "Directory path here",
|
||||
},
|
||||
TASK_PROGRESS_PARAMETER,
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ModelFamily } from "@/shared/prompts"
|
||||
import { ClineDefaultTool } from "@/shared/tools"
|
||||
import type { ClineToolSpec } from "../spec"
|
||||
import { TASK_PROGRESS_PARAMETER } from "../types"
|
||||
|
||||
const id = ClineDefaultTool.LIST_FILES
|
||||
|
||||
@@ -23,6 +24,7 @@ const generic: ClineToolSpec = {
|
||||
instruction: "Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.",
|
||||
usage: "true or false (optional)",
|
||||
},
|
||||
TASK_PROGRESS_PARAMETER,
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,11 @@ const generic: ClineToolSpec = {
|
||||
id,
|
||||
variant: ModelFamily.GENERIC,
|
||||
name: "load_mcp_documentation",
|
||||
description: `Load documentation about creating MCP servers. This tool should be used when the user requests to create or install an MCP server (the user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. You have the ability to create an MCP server and add it to a configuration file that will then expose the tools and resources for you to use with \`use_mcp_tool\` and \`access_mcp_resource\`). The documentation provides detailed information about the MCP server creation process, including setup instructions, best practices, and examples.`,
|
||||
description: `Load documentation about creating MCP servers. This tool should be used when the user requests to create or install an MCP server (the user may ask you something along the lines of "add a tool" that does some function, in other words to create an MCP server that provides tools and resources that may connect to external APIs for example. You have the ability to create an MCP server and add it to a configuration file that will then expose the tools and resources for you to use with \`use_mcp_tool\` and \`access_mcp_resource\`). The documentation provides detailed information about the MCP server creation process, including setup instructions, best practices, and examples.
|
||||
Parameters: None
|
||||
Usage:
|
||||
<load_mcp_documentation>
|
||||
</load_mcp_documentation>`,
|
||||
contextRequirements: (context) => context.mcpHub !== undefined && context.mcpHub !== null,
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ const generic: ClineToolSpec = {
|
||||
variant: ModelFamily.GENERIC,
|
||||
id,
|
||||
name: "new_task",
|
||||
description: ` Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
description: `Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.`,
|
||||
parameters: [
|
||||
{
|
||||
|
||||
@@ -42,12 +42,13 @@ However, if while writing your response you realize you actually need to do more
|
||||
"Set to true if while formulating your response that you found you need to do more exploration with tools, for example reading files. (Remember, you can explore the project with tools like read_file in PLAN MODE without the user having to toggle to ACT MODE.) Defaults to false if not specified.",
|
||||
usage: "true or false (optional, but you MUST set to true if in <response> you need to read files or use other exploration tools)",
|
||||
},
|
||||
// Different than the vanilla TASK_PROGRESS_PARAMETER
|
||||
{
|
||||
name: "task_progress",
|
||||
required: false,
|
||||
instruction:
|
||||
" A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)",
|
||||
usage: "Checklist here (optional)",
|
||||
usage: "Checklist here (If you have presented the user with concrete steps or requirements, you can optionally include a todo list outlining these steps.)",
|
||||
dependencies: [ClineDefaultTool.TODO],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ModelFamily } from "@/shared/prompts"
|
||||
import { ClineDefaultTool } from "@/shared/tools"
|
||||
import type { ClineToolSpec } from "../spec"
|
||||
import { TASK_PROGRESS_PARAMETER } from "../types"
|
||||
|
||||
const id = ClineDefaultTool.FILE_READ
|
||||
|
||||
@@ -17,13 +18,7 @@ const generic: ClineToolSpec = {
|
||||
instruction: `The path of the file to read (relative to the current working directory {{CWD}})`,
|
||||
usage: "File path here",
|
||||
},
|
||||
{
|
||||
name: "task_progress",
|
||||
required: false,
|
||||
instruction: `A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)`,
|
||||
usage: "Checklist here (optional)",
|
||||
dependencies: [ClineDefaultTool.TODO],
|
||||
},
|
||||
TASK_PROGRESS_PARAMETER,
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ModelFamily } from "@/shared/prompts"
|
||||
import { ClineDefaultTool } from "@/shared/tools"
|
||||
import type { ClineToolSpec } from "../spec"
|
||||
import { TASK_PROGRESS_PARAMETER } from "../types"
|
||||
|
||||
const id = ClineDefaultTool.FILE_EDIT
|
||||
|
||||
@@ -46,13 +47,7 @@ const generic: ClineToolSpec = {
|
||||
* To delete code: Use empty REPLACE section`,
|
||||
usage: "Search and replace blocks here",
|
||||
},
|
||||
{
|
||||
name: "task_progress",
|
||||
required: false,
|
||||
instruction: `A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)`,
|
||||
usage: "Checklist here (optional)",
|
||||
dependencies: [ClineDefaultTool.TODO],
|
||||
},
|
||||
TASK_PROGRESS_PARAMETER,
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ModelFamily } from "@/shared/prompts"
|
||||
import { ClineDefaultTool } from "@/shared/tools"
|
||||
import type { ClineToolSpec } from "../spec"
|
||||
import { TASK_PROGRESS_PARAMETER } from "../types"
|
||||
|
||||
/**
|
||||
* ## search_files
|
||||
@@ -45,6 +46,7 @@ const generic: ClineToolSpec = {
|
||||
"Glob pattern to filter files (e.g., '*.ts' for TypeScript files). If not provided, it will search all files (*).",
|
||||
usage: "file pattern here (optional)",
|
||||
},
|
||||
TASK_PROGRESS_PARAMETER,
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ModelFamily } from "@/shared/prompts"
|
||||
import { ClineDefaultTool } from "@/shared/tools"
|
||||
import type { ClineToolSpec } from "../spec"
|
||||
import { TASK_PROGRESS_PARAMETER } from "../types"
|
||||
|
||||
/**
|
||||
## use_mcp_tool
|
||||
@@ -54,20 +55,14 @@ const generic: ClineToolSpec = {
|
||||
name: "arguments",
|
||||
required: true,
|
||||
instruction: "A JSON object containing the tool's input parameters, following the tool's input schema",
|
||||
usage: `{
|
||||
usage: `
|
||||
{
|
||||
"param1": "value1",
|
||||
"param2": "value2"
|
||||
}`,
|
||||
dependencies: [ClineDefaultTool.MCP_USE],
|
||||
},
|
||||
{
|
||||
name: "task_progress",
|
||||
required: false,
|
||||
instruction:
|
||||
" A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)",
|
||||
usage: "Checklist here (optional)",
|
||||
dependencies: [ClineDefaultTool.TODO],
|
||||
}
|
||||
`,
|
||||
},
|
||||
TASK_PROGRESS_PARAMETER,
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ModelFamily } from "@/shared/prompts"
|
||||
import { ClineDefaultTool } from "@/shared/tools"
|
||||
import type { ClineToolSpec } from "../spec"
|
||||
import { TASK_PROGRESS_PARAMETER } from "../types"
|
||||
|
||||
const nextGen: ClineToolSpec = {
|
||||
variant: ModelFamily.NEXT_GEN,
|
||||
@@ -21,6 +22,7 @@ const nextGen: ClineToolSpec = {
|
||||
instruction: "The URL to fetch content from",
|
||||
usage: "https://example.com/docs",
|
||||
},
|
||||
TASK_PROGRESS_PARAMETER,
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ModelFamily } from "@/shared/prompts"
|
||||
import { ClineDefaultTool } from "@/shared/tools"
|
||||
import type { ClineToolSpec } from "../spec"
|
||||
import { TASK_PROGRESS_PARAMETER } from "../types"
|
||||
|
||||
/**
|
||||
* ## write_to_file
|
||||
@@ -43,14 +44,7 @@ const generic: ClineToolSpec = {
|
||||
"The content to write to the file. ALWAYS provide the COMPLETE intended content of the file, without any truncation or omissions. You MUST include ALL parts of the file, even if they haven't been modified.",
|
||||
usage: "Your file content here",
|
||||
},
|
||||
{
|
||||
name: "task_progress",
|
||||
required: false,
|
||||
instruction:
|
||||
"A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)",
|
||||
usage: "Checklist here (optional)",
|
||||
dependencies: [ClineDefaultTool.TODO],
|
||||
},
|
||||
TASK_PROGRESS_PARAMETER,
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Enhanced type definitions for better type safety and developer experience
|
||||
*/
|
||||
|
||||
import { ApiHandlerModel, ApiProviderInfo } from "@/core/api"
|
||||
import { ApiProviderInfo } from "@/core/api"
|
||||
import type { McpHub } from "@/services/mcp/McpHub"
|
||||
import type { BrowserSettings } from "@/shared/BrowserSettings"
|
||||
import type { FocusChainSettings } from "@/shared/FocusChainSettings"
|
||||
@@ -239,3 +239,14 @@ export interface VariantSchema {
|
||||
readonly optional: readonly string[]
|
||||
readonly validation: Record<string, (value: unknown) => boolean>
|
||||
}
|
||||
|
||||
/**
|
||||
* Common parameter shared between tools for tracking task progress
|
||||
*/
|
||||
export const TASK_PROGRESS_PARAMETER = {
|
||||
name: "task_progress",
|
||||
required: false,
|
||||
instruction: `A checklist showing task progress after this tool use is completed. (See 'Updating Task Progress' section for more details)`,
|
||||
usage: "Checklist here (optional)",
|
||||
dependencies: [ClineDefaultTool.TODO],
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SystemPromptSection } from "../.."
|
||||
import { SystemPromptSection } from "../../templates/placeholders"
|
||||
|
||||
export const baseTemplate = `{{${SystemPromptSection.AGENT_ROLE}}}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SystemPromptSection } from "../.."
|
||||
import { SystemPromptSection } from "../../templates/placeholders"
|
||||
|
||||
export const baseTemplate = `{{${SystemPromptSection.AGENT_ROLE}}}
|
||||
|
||||
|
||||
@@ -7,34 +7,39 @@
|
||||
*/
|
||||
|
||||
export { config as genericConfig, type GenericVariantConfig } from "./generic/config"
|
||||
export { config as gpt5Config, type GPT5VariantConfig } from "./gpt-5/config"
|
||||
export { config as nextGenConfig, type NextGenVariantConfig } from "./next-gen/config"
|
||||
export { config as xsConfig, type XsVariantConfig } from "./xs/config"
|
||||
|
||||
import { config as genericConfig } from "./generic/config"
|
||||
import { config as gpt5Config } from "./gpt-5/config"
|
||||
import { config as nextGenConfig } from "./next-gen/config"
|
||||
import { config as xsConfig } from "./xs/config"
|
||||
|
||||
/**
|
||||
* Variant Registry for dynamic loading
|
||||
*
|
||||
* This registry allows for lazy loading of variant configurations,
|
||||
* which is useful for reducing initial bundle size and enabling
|
||||
* runtime variant selection.
|
||||
* This registry allows for loading variant configurations.
|
||||
*/
|
||||
export const VARIANT_CONFIGS = {
|
||||
/**
|
||||
* Generic variant - Fallback for all model types
|
||||
* Optimized for broad compatibility and stable performance
|
||||
*/
|
||||
generic: () => import("./generic/config").then((m) => m.config),
|
||||
generic: genericConfig,
|
||||
|
||||
/**
|
||||
* Next-gen variant - Advanced models with enhanced capabilities
|
||||
* Includes additional features like feedback loops and web fetching
|
||||
*/
|
||||
"next-gen": () => import("./next-gen/config").then((m) => m.config),
|
||||
"next-gen": nextGenConfig,
|
||||
gpt5: gpt5Config,
|
||||
|
||||
/**
|
||||
* XS variant - Compact models with limited context windows
|
||||
* Streamlined for efficiency with essential tools only
|
||||
*/
|
||||
xs: () => import("./xs/config").then((m) => m.config),
|
||||
xs: xsConfig,
|
||||
} as const
|
||||
|
||||
/**
|
||||
@@ -60,18 +65,16 @@ export function isValidVariantId(id: string): id is VariantId {
|
||||
/**
|
||||
* Load a variant configuration dynamically
|
||||
* @param variantId - The ID of the variant to load
|
||||
* @returns Promise that resolves to the variant configuration
|
||||
* @returns Variant configuration
|
||||
*/
|
||||
export async function loadVariantConfig(variantId: VariantId) {
|
||||
const loader = VARIANT_CONFIGS[variantId]
|
||||
return await loader()
|
||||
export function loadVariantConfig(variantId: VariantId) {
|
||||
return VARIANT_CONFIGS[variantId]
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all variant configurations
|
||||
* @returns Promise that resolves to a map of all variant configurations
|
||||
* @returns A map of all variant configurations
|
||||
*/
|
||||
export async function loadAllVariantConfigs() {
|
||||
const entries = await Promise.all(Object.entries(VARIANT_CONFIGS).map(async ([id, loader]) => [id, await loader()] as const))
|
||||
return Object.fromEntries(entries) as Record<VariantId, Awaited<ReturnType<(typeof VARIANT_CONFIGS)[VariantId]>>>
|
||||
export function loadAllVariantConfigs() {
|
||||
return VARIANT_CONFIGS
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SystemPromptSection } from "../.."
|
||||
import { SystemPromptSection } from "../../templates/placeholders"
|
||||
|
||||
export const baseTemplate = `{{${SystemPromptSection.AGENT_ROLE}}}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { PromptVariant, SystemPromptSection } from "../.."
|
||||
import { SystemPromptSection } from "../../templates/placeholders"
|
||||
import { PromptVariant } from "../../types"
|
||||
|
||||
const XS_EDITING_FILES = `FILE EDITING RULES
|
||||
- Default: replace_in_file; write_to_file for new files or full rewrites.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { telemetryService } from "@services/posthog/PostHogClientProvider"
|
||||
import { ClineRulesToggles } from "@shared/cline-rules"
|
||||
import fs from "fs/promises"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import {
|
||||
condenseToolResponse,
|
||||
deepPlanningToolResponse,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ApiConfiguration, fireworksDefaultModelId } from "@shared/api"
|
||||
import type { ExtensionContext } from "vscode"
|
||||
import { writeTaskHistoryToState } from "./disk"
|
||||
import { STATE_MANAGER_NOT_INITIALIZED } from "./error-messages"
|
||||
import { GlobalState, GlobalStateKey, LocalState, LocalStateKey, SecretKey, Secrets } from "./state-keys"
|
||||
import { readGlobalStateFromDisk, readSecretsFromDisk, readWorkspaceStateFromDisk } from "./utils/state-helpers"
|
||||
@@ -46,13 +47,13 @@ export class StateManager {
|
||||
const secrets = await readSecretsFromDisk(this.context)
|
||||
const workspaceState = await readWorkspaceStateFromDisk(this.context)
|
||||
|
||||
// Populate the caches with all extension state fields
|
||||
// Populate the cache with all extension state and secrets fields
|
||||
// Use populate method to avoid triggering persistence during initialization
|
||||
this.populateCache(globalState, secrets, workspaceState)
|
||||
|
||||
this.isInitialized = true
|
||||
} catch (error) {
|
||||
console.error("Failed to initialize StateManager:", error)
|
||||
console.error("[StateManager] Failed to initialize:", error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
@@ -550,11 +551,11 @@ export class StateManager {
|
||||
this.pendingWorkspaceState.clear()
|
||||
this.persistenceTimeout = null
|
||||
} catch (error) {
|
||||
console.error("Failed to persist pending changes:", error)
|
||||
console.error("[StateManager] Failed to persist pending changes:", error)
|
||||
this.persistenceTimeout = null
|
||||
|
||||
// Call persistence error callback for error recovery
|
||||
this.onPersistenceError?.({ error: error as Error })
|
||||
this.onPersistenceError?.({ error: error })
|
||||
}
|
||||
}, this.PERSISTENCE_DELAY_MS)
|
||||
}
|
||||
@@ -566,12 +567,15 @@ export class StateManager {
|
||||
try {
|
||||
await Promise.all(
|
||||
Array.from(keys).map((key) => {
|
||||
const value = this.globalStateCache[key]
|
||||
return this.context.globalState.update(key, value)
|
||||
if (key === "taskHistory") {
|
||||
// Route task history persistence to file, not VS Code globalState
|
||||
return writeTaskHistoryToState(this.context, this.globalStateCache[key])
|
||||
}
|
||||
return this.context.globalState.update(key, this.globalStateCache[key])
|
||||
}),
|
||||
)
|
||||
} catch (error) {
|
||||
console.error("Failed to persist global state batch:", error)
|
||||
console.error("[StateManager] Failed to persist global state batch:", error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { TaskMetadata } from "@core/context/context-tracking/ContextTrackerTypes"
|
||||
import { execa } from "@packages/execa"
|
||||
import { ClineMessage } from "@shared/ExtensionMessage"
|
||||
import { HistoryItem } from "@shared/HistoryItem"
|
||||
import { fileExistsAtPath } from "@utils/fs"
|
||||
import fs from "fs/promises"
|
||||
import os from "os"
|
||||
@@ -180,3 +181,42 @@ export async function saveTaskMetadata(context: vscode.ExtensionContext, taskId:
|
||||
console.error("Failed to save task metadata:", error)
|
||||
}
|
||||
}
|
||||
|
||||
export async function ensureStateDirectoryExists(context: vscode.ExtensionContext): Promise<string> {
|
||||
const stateDir = path.join(context.globalStorageUri.fsPath, "state")
|
||||
await fs.mkdir(stateDir, { recursive: true })
|
||||
return stateDir
|
||||
}
|
||||
|
||||
export async function getTaskHistoryStateFilePath(context: vscode.ExtensionContext): Promise<string> {
|
||||
return path.join(await ensureStateDirectoryExists(context), "taskHistory.json")
|
||||
}
|
||||
|
||||
export async function taskHistoryStateFileExists(context: vscode.ExtensionContext): Promise<boolean> {
|
||||
const filePath = await getTaskHistoryStateFilePath(context)
|
||||
return fileExistsAtPath(filePath)
|
||||
}
|
||||
|
||||
export async function readTaskHistoryFromState(context: vscode.ExtensionContext): Promise<HistoryItem[]> {
|
||||
try {
|
||||
const filePath = await getTaskHistoryStateFilePath(context)
|
||||
if (await fileExistsAtPath(filePath)) {
|
||||
return JSON.parse(await fs.readFile(filePath, "utf8"))
|
||||
}
|
||||
return []
|
||||
} catch (error) {
|
||||
console.error("[Disk] Failed to read task history:", error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export async function writeTaskHistoryToState(context: vscode.ExtensionContext, items: HistoryItem[]): Promise<void> {
|
||||
try {
|
||||
const filePath = await getTaskHistoryStateFilePath(context)
|
||||
// Always create the file; if items is empty, write [] to ensure presence on first startup
|
||||
await fs.writeFile(filePath, JSON.stringify(items))
|
||||
} catch (error) {
|
||||
console.error("[Disk] Failed to write task history:", error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
import * as vscode from "vscode"
|
||||
import { ensureRulesDirectoryExists } from "./disk"
|
||||
import { ensureRulesDirectoryExists, readTaskHistoryFromState, writeTaskHistoryToState } from "./disk"
|
||||
import { StateManager } from "./StateManager"
|
||||
|
||||
export async function migrateWorkspaceToGlobalStorage(context: vscode.ExtensionContext) {
|
||||
@@ -66,6 +66,27 @@ export async function migrateWorkspaceToGlobalStorage(context: vscode.ExtensionC
|
||||
}
|
||||
}
|
||||
|
||||
export async function migrateTaskHistoryToFile(context: vscode.ExtensionContext) {
|
||||
try {
|
||||
// If the old taskHistory vs code global state is undefined, do nothing
|
||||
const vscodeGlobalStateTaskHistory = await context.globalState.get("taskHistory")
|
||||
if (vscodeGlobalStateTaskHistory === undefined) {
|
||||
return
|
||||
}
|
||||
// Read legacy from VS Code globalState, default to []
|
||||
console.log("[Storage Migration] taskHistory from vscode global state: ", vscodeGlobalStateTaskHistory)
|
||||
// Always create the file, even when empty
|
||||
await writeTaskHistoryToState(context, Array.isArray(vscodeGlobalStateTaskHistory) ? vscodeGlobalStateTaskHistory : [])
|
||||
// Don't remove the old taskHistory yet, while this version is not in production, for better dev experience.
|
||||
// This is because the old version of the code (still in prod) is still reading taskHistory from the vs code global state, so it will appear as if all the user's tasks have been deleted.
|
||||
// await context.globalState.update("taskHistory", undefined)
|
||||
console.log("[Storage Migration] taskHistory file in new location: ", await readTaskHistoryFromState(context))
|
||||
console.log("[Storage Migration] old vscode global state: ", await context.globalState.get("taskHistory"))
|
||||
} catch (error) {
|
||||
console.error("[Storage Migration] Failed to migrate task history to file:", error)
|
||||
}
|
||||
}
|
||||
|
||||
export async function migrateMcpMarketplaceEnableSetting(mcpMarketplaceEnabledRaw: boolean | undefined): Promise<boolean> {
|
||||
const config = vscode.workspace.getConfiguration("cline")
|
||||
const mcpMarketplaceEnabled = config.get<boolean>("mcpMarketplace.enabled")
|
||||
|
||||
@@ -5,12 +5,11 @@ import { AutoApprovalSettings, DEFAULT_AUTO_APPROVAL_SETTINGS } from "@/shared/A
|
||||
import { BrowserSettings, DEFAULT_BROWSER_SETTINGS } from "@/shared/BrowserSettings"
|
||||
import { ClineRulesToggles } from "@/shared/cline-rules"
|
||||
import { DEFAULT_FOCUS_CHAIN_SETTINGS, FocusChainSettings } from "@/shared/FocusChainSettings"
|
||||
import { HistoryItem } from "@/shared/HistoryItem"
|
||||
import { DEFAULT_MCP_DISPLAY_MODE, McpDisplayMode } from "@/shared/McpDisplayMode"
|
||||
import { McpMarketplaceCatalog } from "@/shared/mcp"
|
||||
import { Mode, OpenaiReasoningEffort } from "@/shared/storage/types"
|
||||
import { TelemetrySetting } from "@/shared/TelemetrySetting"
|
||||
import { UserInfo } from "@/shared/UserInfo"
|
||||
import { readTaskHistoryFromState } from "../disk"
|
||||
import { GlobalState, LocalState, SecretKey, Secrets } from "../state-keys"
|
||||
|
||||
export async function readSecretsFromDisk(context: ExtensionContext): Promise<Secrets> {
|
||||
@@ -142,303 +141,321 @@ export async function readWorkspaceStateFromDisk(context: ExtensionContext): Pro
|
||||
}
|
||||
|
||||
export async function readGlobalStateFromDisk(context: ExtensionContext): Promise<GlobalState> {
|
||||
// Get all global state values
|
||||
const strictPlanModeEnabled = context.globalState.get("strictPlanModeEnabled") as boolean | undefined
|
||||
const useAutoCondense = context.globalState.get("useAutoCondense") as boolean | undefined
|
||||
const isNewUser = context.globalState.get("isNewUser") as boolean | undefined
|
||||
const welcomeViewCompleted = context.globalState.get("welcomeViewCompleted") as boolean | undefined
|
||||
const awsRegion = context.globalState.get("awsRegion") as string | undefined
|
||||
const awsUseCrossRegionInference = context.globalState.get("awsUseCrossRegionInference") as boolean | undefined
|
||||
const awsBedrockUsePromptCache = context.globalState.get("awsBedrockUsePromptCache") as boolean | undefined
|
||||
const awsBedrockEndpoint = context.globalState.get("awsBedrockEndpoint") as string | undefined
|
||||
const awsProfile = context.globalState.get("awsProfile") as string | undefined
|
||||
const awsUseProfile = context.globalState.get("awsUseProfile") as boolean | undefined
|
||||
const awsAuthentication = context.globalState.get("awsAuthentication") as string | undefined
|
||||
const vertexProjectId = context.globalState.get("vertexProjectId") as string | undefined
|
||||
const vertexRegion = context.globalState.get("vertexRegion") as string | undefined
|
||||
const openAiBaseUrl = context.globalState.get("openAiBaseUrl") as string | undefined
|
||||
const requestyBaseUrl = context.globalState.get("requestyBaseUrl") as string | undefined
|
||||
const openAiHeaders = context.globalState.get("openAiHeaders") as Record<string, string> | undefined
|
||||
const ollamaBaseUrl = context.globalState.get("ollamaBaseUrl") as string | undefined
|
||||
const ollamaApiOptionsCtxNum = context.globalState.get("ollamaApiOptionsCtxNum") as string | undefined
|
||||
const lmStudioBaseUrl = context.globalState.get("lmStudioBaseUrl") as string | undefined
|
||||
const lmStudioMaxTokens = context.globalState.get("lmStudioMaxTokens") as string | undefined
|
||||
const anthropicBaseUrl = context.globalState.get("anthropicBaseUrl") as string | undefined
|
||||
const geminiBaseUrl = context.globalState.get("geminiBaseUrl") as string | undefined
|
||||
const azureApiVersion = context.globalState.get("azureApiVersion") as string | undefined
|
||||
const openRouterProviderSorting = context.globalState.get("openRouterProviderSorting") as string | undefined
|
||||
const lastShownAnnouncementId = context.globalState.get("lastShownAnnouncementId") as string | undefined
|
||||
const taskHistory = context.globalState.get("taskHistory") as HistoryItem[] | undefined
|
||||
const autoApprovalSettings = context.globalState.get("autoApprovalSettings") as AutoApprovalSettings | undefined
|
||||
const browserSettings = context.globalState.get("browserSettings") as BrowserSettings | undefined
|
||||
const liteLlmBaseUrl = context.globalState.get("liteLlmBaseUrl") as string | undefined
|
||||
const liteLlmUsePromptCache = context.globalState.get("liteLlmUsePromptCache") as boolean | undefined
|
||||
const fireworksModelMaxCompletionTokens = context.globalState.get("fireworksModelMaxCompletionTokens") as number | undefined
|
||||
const fireworksModelMaxTokens = context.globalState.get("fireworksModelMaxTokens") as number | undefined
|
||||
const userInfo = context.globalState.get("userInfo") as UserInfo | undefined
|
||||
const qwenApiLine = context.globalState.get("qwenApiLine") as string | undefined
|
||||
const moonshotApiLine = context.globalState.get("moonshotApiLine") as string | undefined
|
||||
const zaiApiLine = context.globalState.get("zaiApiLine") as string | undefined
|
||||
const telemetrySetting = context.globalState.get("telemetrySetting") as TelemetrySetting | undefined
|
||||
const asksageApiUrl = context.globalState.get("asksageApiUrl") as string | undefined
|
||||
const planActSeparateModelsSettingRaw = context.globalState.get("planActSeparateModelsSetting") as boolean | undefined
|
||||
const favoritedModelIds = context.globalState.get("favoritedModelIds") as string[] | undefined
|
||||
const globalClineRulesToggles = context.globalState.get("globalClineRulesToggles") as ClineRulesToggles | undefined
|
||||
const requestTimeoutMs = context.globalState.get("requestTimeoutMs") as number | undefined
|
||||
const shellIntegrationTimeout = context.globalState.get("shellIntegrationTimeout") as number | undefined
|
||||
const enableCheckpointsSettingRaw = context.globalState.get("enableCheckpointsSetting") as boolean | undefined
|
||||
const mcpMarketplaceEnabledRaw = context.globalState.get("mcpMarketplaceEnabled") as boolean | undefined
|
||||
const mcpDisplayMode = context.globalState.get("mcpDisplayMode") as McpDisplayMode | undefined
|
||||
const mcpResponsesCollapsedRaw = context.globalState.get("mcpResponsesCollapsed") as boolean | undefined
|
||||
const globalWorkflowToggles = context.globalState.get("globalWorkflowToggles") as ClineRulesToggles | undefined
|
||||
const terminalReuseEnabled = context.globalState.get("terminalReuseEnabled") as boolean | undefined
|
||||
const terminalOutputLineLimit = context.globalState.get("terminalOutputLineLimit") as number | undefined
|
||||
const defaultTerminalProfile = context.globalState.get("defaultTerminalProfile") as string | undefined
|
||||
const sapAiCoreBaseUrl = context.globalState.get("sapAiCoreBaseUrl") as string | undefined
|
||||
const sapAiCoreTokenUrl = context.globalState.get("sapAiCoreTokenUrl") as string | undefined
|
||||
const sapAiResourceGroup = context.globalState.get("sapAiResourceGroup") as string | undefined
|
||||
const claudeCodePath = context.globalState.get("claudeCodePath") as string | undefined
|
||||
const difyBaseUrl = context.globalState.get("difyBaseUrl") as string | undefined
|
||||
const openaiReasoningEffort = context.globalState.get("openaiReasoningEffort") as OpenaiReasoningEffort | undefined
|
||||
const preferredLanguage = context.globalState.get("preferredLanguage") as string | undefined
|
||||
const focusChainSettings = context.globalState.get("focusChainSettings") as FocusChainSettings | undefined
|
||||
const focusChainFeatureFlagEnabled = context.globalState.get("focusChainFeatureFlagEnabled") as boolean | undefined
|
||||
try {
|
||||
// Get all global state values
|
||||
const strictPlanModeEnabled = context.globalState.get("strictPlanModeEnabled") as boolean | undefined
|
||||
const useAutoCondense = context.globalState.get("useAutoCondense") as boolean | undefined
|
||||
const isNewUser = context.globalState.get("isNewUser") as boolean | undefined
|
||||
const welcomeViewCompleted = context.globalState.get("welcomeViewCompleted") as boolean | undefined
|
||||
const awsRegion = context.globalState.get("awsRegion") as string | undefined
|
||||
const awsUseCrossRegionInference = context.globalState.get("awsUseCrossRegionInference") as boolean | undefined
|
||||
const awsBedrockUsePromptCache = context.globalState.get("awsBedrockUsePromptCache") as boolean | undefined
|
||||
const awsBedrockEndpoint = context.globalState.get("awsBedrockEndpoint") as string | undefined
|
||||
const awsProfile = context.globalState.get("awsProfile") as string | undefined
|
||||
const awsUseProfile = context.globalState.get("awsUseProfile") as boolean | undefined
|
||||
const awsAuthentication = context.globalState.get("awsAuthentication") as string | undefined
|
||||
const vertexProjectId = context.globalState.get("vertexProjectId") as string | undefined
|
||||
const vertexRegion = context.globalState.get("vertexRegion") as string | undefined
|
||||
const openAiBaseUrl = context.globalState.get("openAiBaseUrl") as string | undefined
|
||||
const requestyBaseUrl = context.globalState.get("requestyBaseUrl") as string | undefined
|
||||
const openAiHeaders = context.globalState.get("openAiHeaders") as Record<string, string> | undefined
|
||||
const ollamaBaseUrl = context.globalState.get("ollamaBaseUrl") as string | undefined
|
||||
const ollamaApiOptionsCtxNum = context.globalState.get("ollamaApiOptionsCtxNum") as string | undefined
|
||||
const lmStudioBaseUrl = context.globalState.get("lmStudioBaseUrl") as string | undefined
|
||||
const lmStudioMaxTokens = context.globalState.get("lmStudioMaxTokens") as string | undefined
|
||||
const anthropicBaseUrl = context.globalState.get("anthropicBaseUrl") as string | undefined
|
||||
const geminiBaseUrl = context.globalState.get("geminiBaseUrl") as string | undefined
|
||||
const azureApiVersion = context.globalState.get("azureApiVersion") as string | undefined
|
||||
const openRouterProviderSorting = context.globalState.get("openRouterProviderSorting") as string | undefined
|
||||
const lastShownAnnouncementId = context.globalState.get("lastShownAnnouncementId") as string | undefined
|
||||
const autoApprovalSettings = context.globalState.get("autoApprovalSettings") as AutoApprovalSettings | undefined
|
||||
const browserSettings = context.globalState.get("browserSettings") as BrowserSettings | undefined
|
||||
const liteLlmBaseUrl = context.globalState.get("liteLlmBaseUrl") as string | undefined
|
||||
const liteLlmUsePromptCache = context.globalState.get("liteLlmUsePromptCache") as boolean | undefined
|
||||
const fireworksModelMaxCompletionTokens = context.globalState.get("fireworksModelMaxCompletionTokens") as
|
||||
| number
|
||||
| undefined
|
||||
const fireworksModelMaxTokens = context.globalState.get("fireworksModelMaxTokens") as number | undefined
|
||||
const userInfo = context.globalState.get("userInfo") as UserInfo | undefined
|
||||
const qwenApiLine = context.globalState.get("qwenApiLine") as string | undefined
|
||||
const moonshotApiLine = context.globalState.get("moonshotApiLine") as string | undefined
|
||||
const zaiApiLine = context.globalState.get("zaiApiLine") as string | undefined
|
||||
const telemetrySetting = context.globalState.get("telemetrySetting") as TelemetrySetting | undefined
|
||||
const asksageApiUrl = context.globalState.get("asksageApiUrl") as string | undefined
|
||||
const planActSeparateModelsSettingRaw = context.globalState.get("planActSeparateModelsSetting") as boolean | undefined
|
||||
const favoritedModelIds = context.globalState.get("favoritedModelIds") as string[] | undefined
|
||||
const globalClineRulesToggles = context.globalState.get("globalClineRulesToggles") as ClineRulesToggles | undefined
|
||||
const requestTimeoutMs = context.globalState.get("requestTimeoutMs") as number | undefined
|
||||
const shellIntegrationTimeout = context.globalState.get("shellIntegrationTimeout") as number | undefined
|
||||
const enableCheckpointsSettingRaw = context.globalState.get("enableCheckpointsSetting") as boolean | undefined
|
||||
const mcpMarketplaceEnabledRaw = context.globalState.get("mcpMarketplaceEnabled") as boolean | undefined
|
||||
const mcpDisplayMode = context.globalState.get("mcpDisplayMode") as McpDisplayMode | undefined
|
||||
const mcpResponsesCollapsedRaw = context.globalState.get("mcpResponsesCollapsed") as boolean | undefined
|
||||
const globalWorkflowToggles = context.globalState.get("globalWorkflowToggles") as ClineRulesToggles | undefined
|
||||
const terminalReuseEnabled = context.globalState.get("terminalReuseEnabled") as boolean | undefined
|
||||
const terminalOutputLineLimit = context.globalState.get("terminalOutputLineLimit") as number | undefined
|
||||
const defaultTerminalProfile = context.globalState.get("defaultTerminalProfile") as string | undefined
|
||||
const sapAiCoreBaseUrl = context.globalState.get("sapAiCoreBaseUrl") as string | undefined
|
||||
const sapAiCoreTokenUrl = context.globalState.get("sapAiCoreTokenUrl") as string | undefined
|
||||
const sapAiResourceGroup = context.globalState.get("sapAiResourceGroup") as string | undefined
|
||||
const claudeCodePath = context.globalState.get("claudeCodePath") as string | undefined
|
||||
const difyBaseUrl = context.globalState.get("difyBaseUrl") as string | undefined
|
||||
const openaiReasoningEffort = context.globalState.get("openaiReasoningEffort") as OpenaiReasoningEffort | undefined
|
||||
const preferredLanguage = context.globalState.get("preferredLanguage") as string | undefined
|
||||
const focusChainSettings = context.globalState.get("focusChainSettings") as FocusChainSettings | undefined
|
||||
const focusChainFeatureFlagEnabled = context.globalState.get("focusChainFeatureFlagEnabled") as boolean | undefined
|
||||
|
||||
const mcpMarketplaceCatalog = context.globalState.get("mcpMarketplaceCatalog") as GlobalState["mcpMarketplaceCatalog"]
|
||||
const qwenCodeOauthPath = context.globalState.get("qwenCodeOauthPath") as GlobalState["qwenCodeOauthPath"]
|
||||
const customPrompt = context.globalState.get("customPrompt") as GlobalState["customPrompt"]
|
||||
const mcpMarketplaceCatalog = context.globalState.get("mcpMarketplaceCatalog") as GlobalState["mcpMarketplaceCatalog"]
|
||||
const qwenCodeOauthPath = context.globalState.get("qwenCodeOauthPath") as GlobalState["qwenCodeOauthPath"]
|
||||
const customPrompt = context.globalState.get("customPrompt") as GlobalState["customPrompt"]
|
||||
|
||||
// Get mode-related configurations
|
||||
const mode = context.globalState.get("mode") as Mode | undefined
|
||||
// Get mode-related configurations
|
||||
const mode = context.globalState.get("mode") as Mode | undefined
|
||||
|
||||
// Plan mode configurations
|
||||
const planModeApiProvider = context.globalState.get("planModeApiProvider") as ApiProvider | undefined
|
||||
const planModeApiModelId = context.globalState.get("planModeApiModelId") as string | undefined
|
||||
const planModeThinkingBudgetTokens = context.globalState.get("planModeThinkingBudgetTokens") as number | undefined
|
||||
const planModeReasoningEffort = context.globalState.get("planModeReasoningEffort") as string | undefined
|
||||
const planModeVsCodeLmModelSelector = context.globalState.get("planModeVsCodeLmModelSelector") as
|
||||
| LanguageModelChatSelector
|
||||
| undefined
|
||||
const planModeAwsBedrockCustomSelected = context.globalState.get("planModeAwsBedrockCustomSelected") as boolean | undefined
|
||||
const planModeAwsBedrockCustomModelBaseId = context.globalState.get("planModeAwsBedrockCustomModelBaseId") as
|
||||
| BedrockModelId
|
||||
| undefined
|
||||
const planModeOpenRouterModelId = context.globalState.get("planModeOpenRouterModelId") as string | undefined
|
||||
const planModeOpenRouterModelInfo = context.globalState.get("planModeOpenRouterModelInfo") as ModelInfo | undefined
|
||||
const planModeOpenAiModelId = context.globalState.get("planModeOpenAiModelId") as string | undefined
|
||||
const planModeOpenAiModelInfo = context.globalState.get("planModeOpenAiModelInfo") as ModelInfo | undefined
|
||||
const planModeOllamaModelId = context.globalState.get("planModeOllamaModelId") as string | undefined
|
||||
const planModeLmStudioModelId = context.globalState.get("planModeLmStudioModelId") as string | undefined
|
||||
const planModeLiteLlmModelId = context.globalState.get("planModeLiteLlmModelId") as string | undefined
|
||||
const planModeLiteLlmModelInfo = context.globalState.get("planModeLiteLlmModelInfo") as ModelInfo | undefined
|
||||
const planModeRequestyModelId = context.globalState.get("planModeRequestyModelId") as string | undefined
|
||||
const planModeRequestyModelInfo = context.globalState.get("planModeRequestyModelInfo") as ModelInfo | undefined
|
||||
const planModeTogetherModelId = context.globalState.get("planModeTogetherModelId") as string | undefined
|
||||
const planModeFireworksModelId = context.globalState.get("planModeFireworksModelId") as string | undefined
|
||||
const planModeSapAiCoreModelId = context.globalState.get("planModeSapAiCoreModelId") as string | undefined
|
||||
const planModeGroqModelId = context.globalState.get("planModeGroqModelId") as string | undefined
|
||||
const planModeGroqModelInfo = context.globalState.get("planModeGroqModelInfo") as ModelInfo | undefined
|
||||
const planModeHuggingFaceModelId = context.globalState.get("planModeHuggingFaceModelId") as string | undefined
|
||||
const planModeHuggingFaceModelInfo = context.globalState.get("planModeHuggingFaceModelInfo") as ModelInfo | undefined
|
||||
const planModeHuaweiCloudMaasModelId = context.globalState.get("planModeHuaweiCloudMaasModelId") as string | undefined
|
||||
const planModeHuaweiCloudMaasModelInfo = context.globalState.get("planModeHuaweiCloudMaasModelInfo") as ModelInfo | undefined
|
||||
const planModeBasetenModelId = context.globalState.get("planModeBasetenModelId") as string | undefined
|
||||
const planModeBasetenModelInfo = context.globalState.get("planModeBasetenModelInfo") as ModelInfo | undefined
|
||||
const planModeVercelAiGatewayModelId = context.globalState.get("planModeVercelAiGatewayModelId") as string | undefined
|
||||
const planModeVercelAiGatewayModelInfo = context.globalState.get("planModeVercelAiGatewayModelInfo") as ModelInfo | undefined
|
||||
// Act mode configurations
|
||||
const actModeApiProvider = context.globalState.get("actModeApiProvider") as ApiProvider | undefined
|
||||
const actModeApiModelId = context.globalState.get("actModeApiModelId") as string | undefined
|
||||
const actModeThinkingBudgetTokens = context.globalState.get("actModeThinkingBudgetTokens") as number | undefined
|
||||
const actModeReasoningEffort = context.globalState.get("actModeReasoningEffort") as string | undefined
|
||||
const actModeVsCodeLmModelSelector = context.globalState.get("actModeVsCodeLmModelSelector") as
|
||||
| LanguageModelChatSelector
|
||||
| undefined
|
||||
const actModeAwsBedrockCustomSelected = context.globalState.get("actModeAwsBedrockCustomSelected") as boolean | undefined
|
||||
const actModeAwsBedrockCustomModelBaseId = context.globalState.get("actModeAwsBedrockCustomModelBaseId") as
|
||||
| BedrockModelId
|
||||
| undefined
|
||||
const actModeOpenRouterModelId = context.globalState.get("actModeOpenRouterModelId") as string | undefined
|
||||
const actModeOpenRouterModelInfo = context.globalState.get("actModeOpenRouterModelInfo") as ModelInfo | undefined
|
||||
const actModeOpenAiModelId = context.globalState.get("actModeOpenAiModelId") as string | undefined
|
||||
const actModeOpenAiModelInfo = context.globalState.get("actModeOpenAiModelInfo") as ModelInfo | undefined
|
||||
const actModeOllamaModelId = context.globalState.get("actModeOllamaModelId") as string | undefined
|
||||
const actModeLmStudioModelId = context.globalState.get("actModeLmStudioModelId") as string | undefined
|
||||
const actModeLiteLlmModelId = context.globalState.get("actModeLiteLlmModelId") as string | undefined
|
||||
const actModeLiteLlmModelInfo = context.globalState.get("actModeLiteLlmModelInfo") as ModelInfo | undefined
|
||||
const actModeRequestyModelId = context.globalState.get("actModeRequestyModelId") as string | undefined
|
||||
const actModeRequestyModelInfo = context.globalState.get("actModeRequestyModelInfo") as ModelInfo | undefined
|
||||
const actModeTogetherModelId = context.globalState.get("actModeTogetherModelId") as string | undefined
|
||||
const actModeFireworksModelId = context.globalState.get("actModeFireworksModelId") as string | undefined
|
||||
const actModeSapAiCoreModelId = context.globalState.get("actModeSapAiCoreModelId") as string | undefined
|
||||
const actModeGroqModelId = context.globalState.get("actModeGroqModelId") as string | undefined
|
||||
const actModeGroqModelInfo = context.globalState.get("actModeGroqModelInfo") as ModelInfo | undefined
|
||||
const actModeHuggingFaceModelId = context.globalState.get("actModeHuggingFaceModelId") as string | undefined
|
||||
const actModeHuggingFaceModelInfo = context.globalState.get("actModeHuggingFaceModelInfo") as ModelInfo | undefined
|
||||
const actModeHuaweiCloudMaasModelId = context.globalState.get("actModeHuaweiCloudMaasModelId") as string | undefined
|
||||
const actModeHuaweiCloudMaasModelInfo = context.globalState.get("actModeHuaweiCloudMaasModelInfo") as ModelInfo | undefined
|
||||
const actModeBasetenModelId = context.globalState.get("actModeBasetenModelId") as string | undefined
|
||||
const actModeBasetenModelInfo = context.globalState.get("actModeBasetenModelInfo") as ModelInfo | undefined
|
||||
const actModeVercelAiGatewayModelId = context.globalState.get("actModeVercelAiGatewayModelId") as string | undefined
|
||||
const actModeVercelAiGatewayModelInfo = context.globalState.get("actModeVercelAiGatewayModelInfo") as ModelInfo | undefined
|
||||
const sapAiCoreUseOrchestrationMode = context.globalState.get("sapAiCoreUseOrchestrationMode") as boolean | undefined
|
||||
|
||||
let apiProvider: ApiProvider
|
||||
if (planModeApiProvider) {
|
||||
apiProvider = planModeApiProvider
|
||||
} else {
|
||||
// New users should default to openrouter, since they've opted to use an API key instead of signing in
|
||||
apiProvider = "openrouter"
|
||||
}
|
||||
|
||||
const mcpResponsesCollapsed = mcpResponsesCollapsedRaw ?? false
|
||||
|
||||
// Plan/Act separate models setting is a boolean indicating whether the user wants to use different models for plan and act. Existing users expect this to be enabled, while we want new users to opt in to this being disabled by default.
|
||||
// On win11 state sometimes initializes as empty string instead of undefined
|
||||
let planActSeparateModelsSetting: boolean | undefined
|
||||
if (planActSeparateModelsSettingRaw === true || planActSeparateModelsSettingRaw === false) {
|
||||
planActSeparateModelsSetting = planActSeparateModelsSettingRaw
|
||||
} else {
|
||||
// default to true for existing users
|
||||
if (planModeApiProvider) {
|
||||
planActSeparateModelsSetting = true
|
||||
} else {
|
||||
// default to false for new users
|
||||
planActSeparateModelsSetting = false
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
// api configuration fields
|
||||
claudeCodePath,
|
||||
awsRegion,
|
||||
awsUseCrossRegionInference,
|
||||
awsBedrockUsePromptCache,
|
||||
awsBedrockEndpoint,
|
||||
awsProfile,
|
||||
awsUseProfile,
|
||||
awsAuthentication,
|
||||
vertexProjectId,
|
||||
vertexRegion,
|
||||
openAiBaseUrl,
|
||||
requestyBaseUrl,
|
||||
openAiHeaders: openAiHeaders || {},
|
||||
ollamaBaseUrl,
|
||||
ollamaApiOptionsCtxNum,
|
||||
lmStudioBaseUrl,
|
||||
lmStudioMaxTokens,
|
||||
anthropicBaseUrl,
|
||||
geminiBaseUrl,
|
||||
qwenApiLine,
|
||||
moonshotApiLine,
|
||||
zaiApiLine,
|
||||
azureApiVersion,
|
||||
openRouterProviderSorting,
|
||||
liteLlmBaseUrl,
|
||||
liteLlmUsePromptCache,
|
||||
fireworksModelMaxCompletionTokens,
|
||||
fireworksModelMaxTokens,
|
||||
asksageApiUrl,
|
||||
favoritedModelIds,
|
||||
requestTimeoutMs,
|
||||
sapAiCoreBaseUrl,
|
||||
sapAiCoreTokenUrl,
|
||||
sapAiResourceGroup,
|
||||
difyBaseUrl,
|
||||
sapAiCoreUseOrchestrationMode,
|
||||
// Plan mode configurations
|
||||
planModeApiProvider: planModeApiProvider || apiProvider,
|
||||
planModeApiModelId,
|
||||
planModeThinkingBudgetTokens,
|
||||
planModeReasoningEffort,
|
||||
planModeVsCodeLmModelSelector,
|
||||
planModeAwsBedrockCustomSelected,
|
||||
planModeAwsBedrockCustomModelBaseId,
|
||||
planModeOpenRouterModelId,
|
||||
planModeOpenRouterModelInfo,
|
||||
planModeOpenAiModelId,
|
||||
planModeOpenAiModelInfo,
|
||||
planModeOllamaModelId,
|
||||
planModeLmStudioModelId,
|
||||
planModeLiteLlmModelId,
|
||||
planModeLiteLlmModelInfo,
|
||||
planModeRequestyModelId,
|
||||
planModeRequestyModelInfo,
|
||||
planModeTogetherModelId,
|
||||
planModeFireworksModelId,
|
||||
planModeSapAiCoreModelId,
|
||||
planModeGroqModelId,
|
||||
planModeGroqModelInfo,
|
||||
planModeHuggingFaceModelId,
|
||||
planModeHuggingFaceModelInfo,
|
||||
planModeHuaweiCloudMaasModelId,
|
||||
planModeHuaweiCloudMaasModelInfo,
|
||||
planModeBasetenModelId,
|
||||
planModeBasetenModelInfo,
|
||||
planModeVercelAiGatewayModelId,
|
||||
planModeVercelAiGatewayModelInfo,
|
||||
const planModeApiProvider = context.globalState.get("planModeApiProvider") as ApiProvider | undefined
|
||||
const planModeApiModelId = context.globalState.get("planModeApiModelId") as string | undefined
|
||||
const planModeThinkingBudgetTokens = context.globalState.get("planModeThinkingBudgetTokens") as number | undefined
|
||||
const planModeReasoningEffort = context.globalState.get("planModeReasoningEffort") as string | undefined
|
||||
const planModeVsCodeLmModelSelector = context.globalState.get("planModeVsCodeLmModelSelector") as
|
||||
| LanguageModelChatSelector
|
||||
| undefined
|
||||
const planModeAwsBedrockCustomSelected = context.globalState.get("planModeAwsBedrockCustomSelected") as
|
||||
| boolean
|
||||
| undefined
|
||||
const planModeAwsBedrockCustomModelBaseId = context.globalState.get("planModeAwsBedrockCustomModelBaseId") as
|
||||
| BedrockModelId
|
||||
| undefined
|
||||
const planModeOpenRouterModelId = context.globalState.get("planModeOpenRouterModelId") as string | undefined
|
||||
const planModeOpenRouterModelInfo = context.globalState.get("planModeOpenRouterModelInfo") as ModelInfo | undefined
|
||||
const planModeOpenAiModelId = context.globalState.get("planModeOpenAiModelId") as string | undefined
|
||||
const planModeOpenAiModelInfo = context.globalState.get("planModeOpenAiModelInfo") as ModelInfo | undefined
|
||||
const planModeOllamaModelId = context.globalState.get("planModeOllamaModelId") as string | undefined
|
||||
const planModeLmStudioModelId = context.globalState.get("planModeLmStudioModelId") as string | undefined
|
||||
const planModeLiteLlmModelId = context.globalState.get("planModeLiteLlmModelId") as string | undefined
|
||||
const planModeLiteLlmModelInfo = context.globalState.get("planModeLiteLlmModelInfo") as ModelInfo | undefined
|
||||
const planModeRequestyModelId = context.globalState.get("planModeRequestyModelId") as string | undefined
|
||||
const planModeRequestyModelInfo = context.globalState.get("planModeRequestyModelInfo") as ModelInfo | undefined
|
||||
const planModeTogetherModelId = context.globalState.get("planModeTogetherModelId") as string | undefined
|
||||
const planModeFireworksModelId = context.globalState.get("planModeFireworksModelId") as string | undefined
|
||||
const planModeSapAiCoreModelId = context.globalState.get("planModeSapAiCoreModelId") as string | undefined
|
||||
const planModeGroqModelId = context.globalState.get("planModeGroqModelId") as string | undefined
|
||||
const planModeGroqModelInfo = context.globalState.get("planModeGroqModelInfo") as ModelInfo | undefined
|
||||
const planModeHuggingFaceModelId = context.globalState.get("planModeHuggingFaceModelId") as string | undefined
|
||||
const planModeHuggingFaceModelInfo = context.globalState.get("planModeHuggingFaceModelInfo") as ModelInfo | undefined
|
||||
const planModeHuaweiCloudMaasModelId = context.globalState.get("planModeHuaweiCloudMaasModelId") as string | undefined
|
||||
const planModeHuaweiCloudMaasModelInfo = context.globalState.get("planModeHuaweiCloudMaasModelInfo") as
|
||||
| ModelInfo
|
||||
| undefined
|
||||
const planModeBasetenModelId = context.globalState.get("planModeBasetenModelId") as string | undefined
|
||||
const planModeBasetenModelInfo = context.globalState.get("planModeBasetenModelInfo") as ModelInfo | undefined
|
||||
const planModeVercelAiGatewayModelId = context.globalState.get("planModeVercelAiGatewayModelId") as string | undefined
|
||||
const planModeVercelAiGatewayModelInfo = context.globalState.get("planModeVercelAiGatewayModelInfo") as
|
||||
| ModelInfo
|
||||
| undefined
|
||||
// Act mode configurations
|
||||
actModeApiProvider: actModeApiProvider || apiProvider,
|
||||
actModeApiModelId,
|
||||
actModeThinkingBudgetTokens,
|
||||
actModeReasoningEffort,
|
||||
actModeVsCodeLmModelSelector,
|
||||
actModeAwsBedrockCustomSelected,
|
||||
actModeAwsBedrockCustomModelBaseId,
|
||||
actModeOpenRouterModelId,
|
||||
actModeOpenRouterModelInfo,
|
||||
actModeOpenAiModelId,
|
||||
actModeOpenAiModelInfo,
|
||||
actModeOllamaModelId,
|
||||
actModeLmStudioModelId,
|
||||
actModeLiteLlmModelId,
|
||||
actModeLiteLlmModelInfo,
|
||||
actModeRequestyModelId,
|
||||
actModeRequestyModelInfo,
|
||||
actModeTogetherModelId,
|
||||
actModeFireworksModelId,
|
||||
actModeSapAiCoreModelId,
|
||||
actModeGroqModelId,
|
||||
actModeGroqModelInfo,
|
||||
actModeHuggingFaceModelId,
|
||||
actModeHuggingFaceModelInfo,
|
||||
actModeHuaweiCloudMaasModelId,
|
||||
actModeHuaweiCloudMaasModelInfo,
|
||||
actModeBasetenModelId,
|
||||
actModeBasetenModelInfo,
|
||||
actModeVercelAiGatewayModelId,
|
||||
actModeVercelAiGatewayModelInfo,
|
||||
const actModeApiProvider = context.globalState.get("actModeApiProvider") as ApiProvider | undefined
|
||||
const actModeApiModelId = context.globalState.get("actModeApiModelId") as string | undefined
|
||||
const actModeThinkingBudgetTokens = context.globalState.get("actModeThinkingBudgetTokens") as number | undefined
|
||||
const actModeReasoningEffort = context.globalState.get("actModeReasoningEffort") as string | undefined
|
||||
const actModeVsCodeLmModelSelector = context.globalState.get("actModeVsCodeLmModelSelector") as
|
||||
| LanguageModelChatSelector
|
||||
| undefined
|
||||
const actModeAwsBedrockCustomSelected = context.globalState.get("actModeAwsBedrockCustomSelected") as boolean | undefined
|
||||
const actModeAwsBedrockCustomModelBaseId = context.globalState.get("actModeAwsBedrockCustomModelBaseId") as
|
||||
| BedrockModelId
|
||||
| undefined
|
||||
const actModeOpenRouterModelId = context.globalState.get("actModeOpenRouterModelId") as string | undefined
|
||||
const actModeOpenRouterModelInfo = context.globalState.get("actModeOpenRouterModelInfo") as ModelInfo | undefined
|
||||
const actModeOpenAiModelId = context.globalState.get("actModeOpenAiModelId") as string | undefined
|
||||
const actModeOpenAiModelInfo = context.globalState.get("actModeOpenAiModelInfo") as ModelInfo | undefined
|
||||
const actModeOllamaModelId = context.globalState.get("actModeOllamaModelId") as string | undefined
|
||||
const actModeLmStudioModelId = context.globalState.get("actModeLmStudioModelId") as string | undefined
|
||||
const actModeLiteLlmModelId = context.globalState.get("actModeLiteLlmModelId") as string | undefined
|
||||
const actModeLiteLlmModelInfo = context.globalState.get("actModeLiteLlmModelInfo") as ModelInfo | undefined
|
||||
const actModeRequestyModelId = context.globalState.get("actModeRequestyModelId") as string | undefined
|
||||
const actModeRequestyModelInfo = context.globalState.get("actModeRequestyModelInfo") as ModelInfo | undefined
|
||||
const actModeTogetherModelId = context.globalState.get("actModeTogetherModelId") as string | undefined
|
||||
const actModeFireworksModelId = context.globalState.get("actModeFireworksModelId") as string | undefined
|
||||
const actModeSapAiCoreModelId = context.globalState.get("actModeSapAiCoreModelId") as string | undefined
|
||||
const actModeGroqModelId = context.globalState.get("actModeGroqModelId") as string | undefined
|
||||
const actModeGroqModelInfo = context.globalState.get("actModeGroqModelInfo") as ModelInfo | undefined
|
||||
const actModeHuggingFaceModelId = context.globalState.get("actModeHuggingFaceModelId") as string | undefined
|
||||
const actModeHuggingFaceModelInfo = context.globalState.get("actModeHuggingFaceModelInfo") as ModelInfo | undefined
|
||||
const actModeHuaweiCloudMaasModelId = context.globalState.get("actModeHuaweiCloudMaasModelId") as string | undefined
|
||||
const actModeHuaweiCloudMaasModelInfo = context.globalState.get("actModeHuaweiCloudMaasModelInfo") as
|
||||
| ModelInfo
|
||||
| undefined
|
||||
const actModeBasetenModelId = context.globalState.get("actModeBasetenModelId") as string | undefined
|
||||
const actModeBasetenModelInfo = context.globalState.get("actModeBasetenModelInfo") as ModelInfo | undefined
|
||||
const actModeVercelAiGatewayModelId = context.globalState.get("actModeVercelAiGatewayModelId") as string | undefined
|
||||
const actModeVercelAiGatewayModelInfo = context.globalState.get("actModeVercelAiGatewayModelInfo") as
|
||||
| ModelInfo
|
||||
| undefined
|
||||
const sapAiCoreUseOrchestrationMode = context.globalState.get("sapAiCoreUseOrchestrationMode") as boolean | undefined
|
||||
|
||||
// Other global fields
|
||||
focusChainSettings: focusChainSettings || DEFAULT_FOCUS_CHAIN_SETTINGS,
|
||||
focusChainFeatureFlagEnabled: focusChainFeatureFlagEnabled ?? false,
|
||||
strictPlanModeEnabled: strictPlanModeEnabled ?? true,
|
||||
useAutoCondense: useAutoCondense ?? true,
|
||||
isNewUser: isNewUser ?? true,
|
||||
welcomeViewCompleted,
|
||||
lastShownAnnouncementId,
|
||||
taskHistory: taskHistory || [],
|
||||
autoApprovalSettings: autoApprovalSettings || DEFAULT_AUTO_APPROVAL_SETTINGS, // default value can be 0 or empty string
|
||||
globalClineRulesToggles: globalClineRulesToggles || {},
|
||||
browserSettings: { ...DEFAULT_BROWSER_SETTINGS, ...browserSettings }, // this will ensure that older versions of browserSettings (e.g. before remoteBrowserEnabled was added) are merged with the default values (false for remoteBrowserEnabled)
|
||||
preferredLanguage: preferredLanguage || "English",
|
||||
openaiReasoningEffort: (openaiReasoningEffort as OpenaiReasoningEffort) || "medium",
|
||||
mode: mode || "act",
|
||||
userInfo,
|
||||
mcpMarketplaceEnabled: mcpMarketplaceEnabledRaw ?? true,
|
||||
mcpDisplayMode: mcpDisplayMode ?? DEFAULT_MCP_DISPLAY_MODE,
|
||||
mcpResponsesCollapsed: mcpResponsesCollapsed,
|
||||
telemetrySetting: telemetrySetting || "unset",
|
||||
planActSeparateModelsSetting,
|
||||
enableCheckpointsSetting: enableCheckpointsSettingRaw ?? true,
|
||||
shellIntegrationTimeout: shellIntegrationTimeout || 4000,
|
||||
terminalReuseEnabled: terminalReuseEnabled ?? true,
|
||||
terminalOutputLineLimit: terminalOutputLineLimit ?? 500,
|
||||
defaultTerminalProfile: defaultTerminalProfile ?? "default",
|
||||
globalWorkflowToggles: globalWorkflowToggles || {},
|
||||
mcpMarketplaceCatalog,
|
||||
qwenCodeOauthPath,
|
||||
customPrompt,
|
||||
let apiProvider: ApiProvider
|
||||
if (planModeApiProvider) {
|
||||
apiProvider = planModeApiProvider
|
||||
} else {
|
||||
// New users should default to openrouter, since they've opted to use an API key instead of signing in
|
||||
apiProvider = "openrouter"
|
||||
}
|
||||
|
||||
const mcpResponsesCollapsed = mcpResponsesCollapsedRaw ?? false
|
||||
|
||||
// Plan/Act separate models setting is a boolean indicating whether the user wants to use different models for plan and act. Existing users expect this to be enabled, while we want new users to opt in to this being disabled by default.
|
||||
// On win11 state sometimes initializes as empty string instead of undefined
|
||||
let planActSeparateModelsSetting: boolean | undefined
|
||||
if (planActSeparateModelsSettingRaw === true || planActSeparateModelsSettingRaw === false) {
|
||||
planActSeparateModelsSetting = planActSeparateModelsSettingRaw
|
||||
} else {
|
||||
// default to true for existing users
|
||||
if (planModeApiProvider) {
|
||||
planActSeparateModelsSetting = true
|
||||
} else {
|
||||
// default to false for new users
|
||||
planActSeparateModelsSetting = false
|
||||
}
|
||||
}
|
||||
|
||||
const taskHistory = await readTaskHistoryFromState(context)
|
||||
|
||||
return {
|
||||
// api configuration fields
|
||||
claudeCodePath,
|
||||
awsRegion,
|
||||
awsUseCrossRegionInference,
|
||||
awsBedrockUsePromptCache,
|
||||
awsBedrockEndpoint,
|
||||
awsProfile,
|
||||
awsUseProfile,
|
||||
awsAuthentication,
|
||||
vertexProjectId,
|
||||
vertexRegion,
|
||||
openAiBaseUrl,
|
||||
requestyBaseUrl,
|
||||
openAiHeaders: openAiHeaders || {},
|
||||
ollamaBaseUrl,
|
||||
ollamaApiOptionsCtxNum,
|
||||
lmStudioBaseUrl,
|
||||
lmStudioMaxTokens,
|
||||
anthropicBaseUrl,
|
||||
geminiBaseUrl,
|
||||
qwenApiLine,
|
||||
moonshotApiLine,
|
||||
zaiApiLine,
|
||||
azureApiVersion,
|
||||
openRouterProviderSorting,
|
||||
liteLlmBaseUrl,
|
||||
liteLlmUsePromptCache,
|
||||
fireworksModelMaxCompletionTokens,
|
||||
fireworksModelMaxTokens,
|
||||
asksageApiUrl,
|
||||
favoritedModelIds,
|
||||
requestTimeoutMs,
|
||||
sapAiCoreBaseUrl,
|
||||
sapAiCoreTokenUrl,
|
||||
sapAiResourceGroup,
|
||||
difyBaseUrl,
|
||||
sapAiCoreUseOrchestrationMode,
|
||||
// Plan mode configurations
|
||||
planModeApiProvider: planModeApiProvider || apiProvider,
|
||||
planModeApiModelId,
|
||||
planModeThinkingBudgetTokens,
|
||||
planModeReasoningEffort,
|
||||
planModeVsCodeLmModelSelector,
|
||||
planModeAwsBedrockCustomSelected,
|
||||
planModeAwsBedrockCustomModelBaseId,
|
||||
planModeOpenRouterModelId,
|
||||
planModeOpenRouterModelInfo,
|
||||
planModeOpenAiModelId,
|
||||
planModeOpenAiModelInfo,
|
||||
planModeOllamaModelId,
|
||||
planModeLmStudioModelId,
|
||||
planModeLiteLlmModelId,
|
||||
planModeLiteLlmModelInfo,
|
||||
planModeRequestyModelId,
|
||||
planModeRequestyModelInfo,
|
||||
planModeTogetherModelId,
|
||||
planModeFireworksModelId,
|
||||
planModeSapAiCoreModelId,
|
||||
planModeGroqModelId,
|
||||
planModeGroqModelInfo,
|
||||
planModeHuggingFaceModelId,
|
||||
planModeHuggingFaceModelInfo,
|
||||
planModeHuaweiCloudMaasModelId,
|
||||
planModeHuaweiCloudMaasModelInfo,
|
||||
planModeBasetenModelId,
|
||||
planModeBasetenModelInfo,
|
||||
planModeVercelAiGatewayModelId,
|
||||
planModeVercelAiGatewayModelInfo,
|
||||
// Act mode configurations
|
||||
actModeApiProvider: actModeApiProvider || apiProvider,
|
||||
actModeApiModelId,
|
||||
actModeThinkingBudgetTokens,
|
||||
actModeReasoningEffort,
|
||||
actModeVsCodeLmModelSelector,
|
||||
actModeAwsBedrockCustomSelected,
|
||||
actModeAwsBedrockCustomModelBaseId,
|
||||
actModeOpenRouterModelId,
|
||||
actModeOpenRouterModelInfo,
|
||||
actModeOpenAiModelId,
|
||||
actModeOpenAiModelInfo,
|
||||
actModeOllamaModelId,
|
||||
actModeLmStudioModelId,
|
||||
actModeLiteLlmModelId,
|
||||
actModeLiteLlmModelInfo,
|
||||
actModeRequestyModelId,
|
||||
actModeRequestyModelInfo,
|
||||
actModeTogetherModelId,
|
||||
actModeFireworksModelId,
|
||||
actModeSapAiCoreModelId,
|
||||
actModeGroqModelId,
|
||||
actModeGroqModelInfo,
|
||||
actModeHuggingFaceModelId,
|
||||
actModeHuggingFaceModelInfo,
|
||||
actModeHuaweiCloudMaasModelId,
|
||||
actModeHuaweiCloudMaasModelInfo,
|
||||
actModeBasetenModelId,
|
||||
actModeBasetenModelInfo,
|
||||
actModeVercelAiGatewayModelId,
|
||||
actModeVercelAiGatewayModelInfo,
|
||||
|
||||
// Other global fields
|
||||
focusChainSettings: focusChainSettings || DEFAULT_FOCUS_CHAIN_SETTINGS,
|
||||
focusChainFeatureFlagEnabled: focusChainFeatureFlagEnabled ?? false,
|
||||
strictPlanModeEnabled: strictPlanModeEnabled ?? true,
|
||||
useAutoCondense: useAutoCondense ?? false,
|
||||
isNewUser: isNewUser ?? true,
|
||||
welcomeViewCompleted,
|
||||
lastShownAnnouncementId,
|
||||
taskHistory: taskHistory || [],
|
||||
autoApprovalSettings: autoApprovalSettings || DEFAULT_AUTO_APPROVAL_SETTINGS, // default value can be 0 or empty string
|
||||
globalClineRulesToggles: globalClineRulesToggles || {},
|
||||
browserSettings: { ...DEFAULT_BROWSER_SETTINGS, ...browserSettings }, // this will ensure that older versions of browserSettings (e.g. before remoteBrowserEnabled was added) are merged with the default values (false for remoteBrowserEnabled)
|
||||
preferredLanguage: preferredLanguage || "English",
|
||||
openaiReasoningEffort: (openaiReasoningEffort as OpenaiReasoningEffort) || "medium",
|
||||
mode: mode || "act",
|
||||
userInfo,
|
||||
mcpMarketplaceEnabled: mcpMarketplaceEnabledRaw ?? true,
|
||||
mcpDisplayMode: mcpDisplayMode ?? DEFAULT_MCP_DISPLAY_MODE,
|
||||
mcpResponsesCollapsed: mcpResponsesCollapsed,
|
||||
telemetrySetting: telemetrySetting || "unset",
|
||||
planActSeparateModelsSetting,
|
||||
enableCheckpointsSetting: enableCheckpointsSettingRaw ?? true,
|
||||
shellIntegrationTimeout: shellIntegrationTimeout || 4000,
|
||||
terminalReuseEnabled: terminalReuseEnabled ?? true,
|
||||
terminalOutputLineLimit: terminalOutputLineLimit ?? 500,
|
||||
defaultTerminalProfile: defaultTerminalProfile ?? "default",
|
||||
globalWorkflowToggles: globalWorkflowToggles || {},
|
||||
mcpMarketplaceCatalog,
|
||||
qwenCodeOauthPath,
|
||||
customPrompt,
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[StateHelpers] Failed to read global state:", error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { FocusChainSettings } from "@shared/FocusChainSettings"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { ClineAskResponse } from "@shared/WebviewMessage"
|
||||
import * as vscode from "vscode"
|
||||
import { modelDoesntSupportWebp } from "@/utils/model-utils"
|
||||
import { ToolUse, ToolUseName } from "../assistant-message"
|
||||
import { ContextManager } from "../context/context-management/ContextManager"
|
||||
import { formatResponse } from "../prompts/responses"
|
||||
@@ -119,6 +120,7 @@ export class ToolExecutor {
|
||||
}
|
||||
|
||||
// Create a properly typed TaskConfig object for handlers
|
||||
// NOTE: modifying this object in the tool handlers is okay since these are all references to the singular ToolExecutor instance's variables. However, be careful modifying this object assuming it will update the ToolExecutor instance, e.g. config.browserSession = ... will not update the ToolExecutor.browserSession instance variable. Use applyLatestBrowserSettings() instead.
|
||||
private asToolConfig(): TaskConfig {
|
||||
const config: TaskConfig = {
|
||||
taskId: this.taskId,
|
||||
@@ -157,7 +159,9 @@ export class ToolExecutor {
|
||||
updateFCListFromToolResponse: this.updateFCListFromToolResponse,
|
||||
sayAndCreateMissingParamError: this.sayAndCreateMissingParamError,
|
||||
removeLastPartialMessageIfExistsWithType: this.removeLastPartialMessageIfExistsWithType,
|
||||
shouldAutoApproveTool: this.shouldAutoApproveTool.bind(this),
|
||||
shouldAutoApproveToolWithPath: this.shouldAutoApproveToolWithPath.bind(this),
|
||||
applyLatestBrowserSettings: this.applyLatestBrowserSettings.bind(this),
|
||||
},
|
||||
coordinator: this.coordinator,
|
||||
}
|
||||
@@ -222,6 +226,22 @@ export class ToolExecutor {
|
||||
await this.execute(block)
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the browser settings
|
||||
*/
|
||||
public async applyLatestBrowserSettings() {
|
||||
if (this.context) {
|
||||
await this.browserSession.dispose()
|
||||
const apiHandlerModel = this.api.getModel()
|
||||
const useWebp = this.api ? !modelDoesntSupportWebp(apiHandlerModel) : true
|
||||
this.browserSession = new BrowserSession(this.context, this.browserSettings, useWebp)
|
||||
} else {
|
||||
console.warn("no controller context available for browserSession")
|
||||
}
|
||||
|
||||
return this.browserSession
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles errors during tool execution
|
||||
*/
|
||||
@@ -305,6 +325,7 @@ export class ToolExecutor {
|
||||
|
||||
// Handle complete blocks
|
||||
await this.handleCompleteBlock(block, config)
|
||||
await this.saveCheckpoint()
|
||||
return true
|
||||
} catch (error) {
|
||||
await this.handleError(`executing ${block.name}`, error as Error, block)
|
||||
@@ -351,15 +372,13 @@ export class ToolExecutor {
|
||||
* Handle complete block execution
|
||||
*/
|
||||
private async handleCompleteBlock(block: ToolUse, config: any): Promise<void> {
|
||||
// All tools are now fully self-managed and implement IPartialBlockHandler
|
||||
const result = await this.coordinator.execute(config, block)
|
||||
|
||||
this.pushToolResult(result, block)
|
||||
|
||||
// Handle focus chain updates
|
||||
if (!block.partial && this.focusChainSettings.enabled) {
|
||||
await this.updateFCListFromToolResponse(block.params.task_progress)
|
||||
}
|
||||
|
||||
await this.saveCheckpoint()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { featureFlagsService, telemetryService } from "@services/posthog/PostHogClientProvider"
|
||||
import { FocusChainSettings } from "@shared/FocusChainSettings"
|
||||
import * as fs from "fs/promises"
|
||||
import * as vscode from "vscode"
|
||||
import { featureFlagsService } from "@/services/feature-flags"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import { HostProvider } from "../../../hosts/host-provider"
|
||||
import { ClineSay } from "../../../shared/ExtensionMessage"
|
||||
import { FileChangeEvent_ChangeType, SubscribeToFileRequest } from "../../../shared/proto/host/watch"
|
||||
|
||||
@@ -43,7 +43,6 @@ import { UrlContentFetcher } from "@services/browser/UrlContentFetcher"
|
||||
import { listFiles } from "@services/glob/list-files"
|
||||
import { Logger } from "@services/logging/Logger"
|
||||
import { McpHub } from "@services/mcp/McpHub"
|
||||
import { telemetryService } from "@services/posthog/PostHogClientProvider"
|
||||
import { AutoApprovalSettings } from "@shared/AutoApprovalSettings"
|
||||
import { ApiConfiguration } from "@shared/api"
|
||||
import { findLast, findLastIndex } from "@shared/array"
|
||||
@@ -70,7 +69,8 @@ import * as vscode from "vscode"
|
||||
import type { SystemPromptContext } from "@/core/prompts/system-prompt"
|
||||
import { getSystemPrompt } from "@/core/prompts/system-prompt"
|
||||
import { HostProvider } from "@/hosts/host-provider"
|
||||
import { errorService } from "@/services/posthog/PostHogClientProvider"
|
||||
import { errorService } from "@/services/error"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import { ShowMessageType } from "@/shared/proto/index.host"
|
||||
import { isInTestMode } from "../../services/test/TestMode"
|
||||
import { ensureLocalClineDirExists } from "../context/instructions/user-instructions/rule-helpers"
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import type { ToolUse } from "@core/assistant-message"
|
||||
import { formatResponse } from "@core/prompts/responses"
|
||||
import { telemetryService } from "@services/posthog/PostHogClientProvider"
|
||||
import { ClineAsk } from "@shared/ExtensionMessage"
|
||||
import { ClineAsk, ClineAskUseMcpServer } from "@shared/ExtensionMessage"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import type { ToolResponse } from "../../index"
|
||||
import { showNotificationForApprovalIfAutoApprovalEnabled } from "../../utils"
|
||||
import type { IFullyManagedTool } from "../ToolExecutorCoordinator"
|
||||
import type { TaskConfig } from "../types/TaskConfig"
|
||||
import type { StronglyTypedUIHelpers } from "../types/UIHelpers"
|
||||
import { ToolResultUtils } from "../utils/ToolResultUtils"
|
||||
|
||||
export class AccessMcpResourceHandler implements IFullyManagedTool {
|
||||
readonly name = "access_mcp_resource"
|
||||
@@ -21,21 +22,16 @@ export class AccessMcpResourceHandler implements IFullyManagedTool {
|
||||
const server_name = block.params.server_name
|
||||
const uri = block.params.uri
|
||||
|
||||
// Early return if we don't have enough data yet
|
||||
if (!server_name || !uri) {
|
||||
return
|
||||
}
|
||||
|
||||
const partialMessage = JSON.stringify({
|
||||
type: "access_mcp_resource",
|
||||
serverName: uiHelpers.removeClosingTag(block, "server_name", server_name),
|
||||
toolName: undefined,
|
||||
uri: uiHelpers.removeClosingTag(block, "uri", uri),
|
||||
arguments: undefined,
|
||||
})
|
||||
} satisfies ClineAskUseMcpServer)
|
||||
|
||||
// Check if tool should be auto-approved (access_mcp_resource uses general auto-approval)
|
||||
const shouldAutoApprove = uiHelpers.shouldAutoApproveTool("access_mcp_resource")
|
||||
const shouldAutoApprove = uiHelpers.shouldAutoApproveTool(block.name)
|
||||
|
||||
if (shouldAutoApprove) {
|
||||
await uiHelpers.removeLastPartialMessageIfExistsWithType("ask", "use_mcp_server")
|
||||
@@ -47,11 +43,6 @@ export class AccessMcpResourceHandler implements IFullyManagedTool {
|
||||
}
|
||||
|
||||
async execute(config: TaskConfig, block: ToolUse): Promise<ToolResponse> {
|
||||
// For partial blocks, return empty string to let coordinator handle UI
|
||||
if (block.partial) {
|
||||
return ""
|
||||
}
|
||||
|
||||
const server_name: string | undefined = block.params.server_name
|
||||
const uri: string | undefined = block.params.uri
|
||||
|
||||
@@ -75,10 +66,9 @@ export class AccessMcpResourceHandler implements IFullyManagedTool {
|
||||
toolName: undefined,
|
||||
uri: uri,
|
||||
arguments: undefined,
|
||||
})
|
||||
} satisfies ClineAskUseMcpServer)
|
||||
|
||||
// access_mcp_resource uses general auto-approval
|
||||
const shouldAutoApprove = config.autoApprovalSettings.actions.useMcp
|
||||
const shouldAutoApprove = config.callbacks.shouldAutoApproveTool(block.name)
|
||||
|
||||
if (shouldAutoApprove) {
|
||||
// Auto-approval flow
|
||||
@@ -101,45 +91,36 @@ export class AccessMcpResourceHandler implements IFullyManagedTool {
|
||||
|
||||
await config.callbacks.removeLastPartialMessageIfExistsWithType("say", "use_mcp_server")
|
||||
|
||||
// Ask for approval
|
||||
const { response } = await config.callbacks.ask("use_mcp_server", completeMessage, false)
|
||||
|
||||
if (response !== "yesButtonClicked") {
|
||||
// Handle rejection
|
||||
config.taskState.didRejectTool = true
|
||||
const didApprove = await ToolResultUtils.askApprovalAndPushFeedback("use_mcp_server", completeMessage, config)
|
||||
if (!didApprove) {
|
||||
telemetryService.captureToolUsage(config.ulid, block.name, config.api.getModel().id, false, false)
|
||||
return "The user denied this operation."
|
||||
return formatResponse.toolDenied()
|
||||
} else {
|
||||
telemetryService.captureToolUsage(config.ulid, block.name, config.api.getModel().id, false, true)
|
||||
}
|
||||
}
|
||||
|
||||
// Show MCP request started message
|
||||
await config.callbacks.say("mcp_server_request_started")
|
||||
|
||||
try {
|
||||
// Execute the MCP resource access
|
||||
const resourceResult = await config.services.mcpHub.readResource(server_name, uri)
|
||||
// Execute the MCP resource access
|
||||
const resourceResult = await config.services.mcpHub.readResource(server_name, uri)
|
||||
|
||||
// Process the resource result
|
||||
const resourceResultPretty =
|
||||
resourceResult?.contents
|
||||
.map((item: any) => {
|
||||
if (item.text) {
|
||||
return item.text
|
||||
}
|
||||
return ""
|
||||
})
|
||||
.filter(Boolean)
|
||||
.join("\n\n") || "(Empty response)"
|
||||
// Process the resource result
|
||||
const resourceResultPretty =
|
||||
resourceResult?.contents
|
||||
.map((item: any) => {
|
||||
if (item.text) {
|
||||
return item.text
|
||||
}
|
||||
return ""
|
||||
})
|
||||
.filter(Boolean)
|
||||
.join("\n\n") || "(Empty response)"
|
||||
|
||||
// Display result to user
|
||||
await config.callbacks.say("mcp_server_response", resourceResultPretty)
|
||||
// Display result to user
|
||||
await config.callbacks.say("mcp_server_response", resourceResultPretty)
|
||||
|
||||
// Return formatted result
|
||||
return formatResponse.toolResult(resourceResultPretty)
|
||||
} catch (error) {
|
||||
return `Error accessing MCP resource: ${(error as Error)?.message}`
|
||||
}
|
||||
// Return formatted result
|
||||
return formatResponse.toolResult(resourceResultPretty)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { processFilesIntoText } from "@integrations/misc/extract-text"
|
||||
import { showSystemNotification } from "@integrations/notifications"
|
||||
import { telemetryService } from "@services/posthog/PostHogClientProvider"
|
||||
import { findLast, parsePartialArrayString } from "@shared/array"
|
||||
import { ClineAsk, ClineAskQuestion } from "@shared/ExtensionMessage"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import { ToolUse, ToolUseName } from "../../../assistant-message"
|
||||
import { formatResponse } from "../../../prompts/responses"
|
||||
import { ToolResponse } from "../.."
|
||||
@@ -26,79 +26,68 @@ export class AskFollowupQuestionToolHandler implements IToolHandler, IPartialBlo
|
||||
options: parsePartialArrayString(uiHelpers.removeClosingTag(block, "options", optionsRaw)),
|
||||
} satisfies ClineAskQuestion
|
||||
|
||||
// For followup, just stream ask messages
|
||||
await uiHelpers.removeLastPartialMessageIfExistsWithType("say", "followup")
|
||||
await uiHelpers.ask("followup" as ClineAsk, JSON.stringify(sharedMessage), block.partial).catch(() => {})
|
||||
}
|
||||
|
||||
async execute(config: TaskConfig, block: ToolUse): Promise<ToolResponse> {
|
||||
// For partial blocks, don't execute yet
|
||||
if (block.partial) {
|
||||
return ""
|
||||
const question: string | undefined = block.params.question
|
||||
const optionsRaw: string | undefined = block.params.options
|
||||
|
||||
// Validate required parameter
|
||||
if (!question) {
|
||||
config.taskState.consecutiveMistakeCount++
|
||||
return await config.callbacks.sayAndCreateMissingParamError("ask_followup_question", "question")
|
||||
}
|
||||
config.taskState.consecutiveMistakeCount = 0
|
||||
|
||||
// Show notification if auto-approval is enabled
|
||||
if (config.autoApprovalSettings.enabled && config.autoApprovalSettings.enableNotifications) {
|
||||
showSystemNotification({
|
||||
subtitle: "Cline has a question...",
|
||||
message: question.replace(/\n/g, " "),
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
const question: string | undefined = block.params.question
|
||||
const optionsRaw: string | undefined = block.params.options
|
||||
const sharedMessage = {
|
||||
question: question,
|
||||
options: parsePartialArrayString(optionsRaw || "[]"),
|
||||
} satisfies ClineAskQuestion
|
||||
|
||||
// Validate required parameter
|
||||
if (!question) {
|
||||
config.taskState.consecutiveMistakeCount++
|
||||
return await config.callbacks.sayAndCreateMissingParamError("ask_followup_question", "question")
|
||||
const options = parsePartialArrayString(optionsRaw || "[]")
|
||||
|
||||
// Ask the question
|
||||
const {
|
||||
text,
|
||||
images,
|
||||
files: followupFiles,
|
||||
} = await config.callbacks.ask("followup", JSON.stringify(sharedMessage), false)
|
||||
|
||||
// Check if options contains the text response
|
||||
if (optionsRaw && text && options.includes(text)) {
|
||||
telemetryService.captureOptionSelected(config.ulid, options.length, "act")
|
||||
|
||||
// Valid option selected, update last followup message with selected option
|
||||
const clineMessages = config.messageState.getClineMessages()
|
||||
const lastFollowupMessage = findLast(clineMessages, (m: any) => m.ask === "followup")
|
||||
if (lastFollowupMessage) {
|
||||
lastFollowupMessage.text = JSON.stringify({
|
||||
...sharedMessage,
|
||||
selected: text,
|
||||
} satisfies ClineAskQuestion)
|
||||
await config.messageState.saveClineMessagesAndUpdateHistory()
|
||||
}
|
||||
config.taskState.consecutiveMistakeCount = 0
|
||||
|
||||
// Show notification if auto-approval is enabled
|
||||
if (config.autoApprovalSettings.enabled && config.autoApprovalSettings.enableNotifications) {
|
||||
showSystemNotification({
|
||||
subtitle: "Cline has a question...",
|
||||
message: question.replace(/\n/g, " "),
|
||||
})
|
||||
}
|
||||
|
||||
const sharedMessage = {
|
||||
question: question,
|
||||
options: parsePartialArrayString(optionsRaw || "[]"),
|
||||
} satisfies ClineAskQuestion
|
||||
|
||||
const options = parsePartialArrayString(optionsRaw || "[]")
|
||||
|
||||
// Ask the question
|
||||
const {
|
||||
text,
|
||||
images,
|
||||
files: followupFiles,
|
||||
} = await config.callbacks.ask("followup", JSON.stringify(sharedMessage), false)
|
||||
|
||||
// Check if options contains the text response
|
||||
if (optionsRaw && text && options.includes(text)) {
|
||||
telemetryService.captureOptionSelected(config.ulid, options.length, "act")
|
||||
|
||||
// Valid option selected, update last followup message with selected option
|
||||
const clineMessages = config.messageState.getClineMessages()
|
||||
const lastFollowupMessage = findLast(clineMessages, (m: any) => m.ask === "followup")
|
||||
if (lastFollowupMessage) {
|
||||
lastFollowupMessage.text = JSON.stringify({
|
||||
...sharedMessage,
|
||||
selected: text,
|
||||
} satisfies ClineAskQuestion)
|
||||
await config.messageState.saveClineMessagesAndUpdateHistory()
|
||||
}
|
||||
} else {
|
||||
// Option not selected, send user feedback
|
||||
telemetryService.captureOptionsIgnored(config.ulid, options.length, "act")
|
||||
await config.callbacks.say("user_feedback", text ?? "", images, followupFiles)
|
||||
}
|
||||
|
||||
// Process any attached files
|
||||
let fileContentString = ""
|
||||
if (followupFiles && followupFiles.length > 0) {
|
||||
fileContentString = await processFilesIntoText(followupFiles)
|
||||
}
|
||||
|
||||
return formatResponse.toolResult(`<answer>\n${text}\n</answer>`, images, fileContentString)
|
||||
} catch (error) {
|
||||
return `Error asking question: ${(error as Error).message}`
|
||||
} else {
|
||||
// Option not selected, send user feedback
|
||||
telemetryService.captureOptionsIgnored(config.ulid, options.length, "act")
|
||||
await config.callbacks.say("user_feedback", text ?? "", images, followupFiles)
|
||||
}
|
||||
|
||||
// Process any attached files
|
||||
let fileContentString = ""
|
||||
if (followupFiles && followupFiles.length > 0) {
|
||||
fileContentString = await processFilesIntoText(followupFiles)
|
||||
}
|
||||
|
||||
return formatResponse.toolResult(`<answer>\n${text}\n</answer>`, images, fileContentString)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,14 @@ import type { ToolUse } from "@core/assistant-message"
|
||||
import { formatResponse } from "@core/prompts/responses"
|
||||
import { processFilesIntoText } from "@integrations/misc/extract-text"
|
||||
import { showSystemNotification } from "@integrations/notifications"
|
||||
import { telemetryService } from "@services/posthog/PostHogClientProvider"
|
||||
import { findLastIndex } from "@shared/array"
|
||||
import { COMPLETION_RESULT_CHANGES_FLAG } from "@shared/ExtensionMessage"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import type { ToolResponse } from "../../index"
|
||||
import type { IPartialBlockHandler, IToolHandler } from "../ToolExecutorCoordinator"
|
||||
import type { TaskConfig } from "../types/TaskConfig"
|
||||
import type { StronglyTypedUIHelpers } from "../types/UIHelpers"
|
||||
import { ToolResultUtils } from "../utils/ToolResultUtils"
|
||||
|
||||
export class AttemptCompletionHandler implements IToolHandler, IPartialBlockHandler {
|
||||
readonly name = "attempt_completion"
|
||||
@@ -28,37 +29,26 @@ export class AttemptCompletionHandler implements IToolHandler, IPartialBlockHand
|
||||
const result = block.params.result
|
||||
const command = block.params.command
|
||||
|
||||
if (command) {
|
||||
// the attempt_completion text is done, now we're getting command
|
||||
// Original had complex logic here but most was commented out
|
||||
// For now, we'll keep it simple and not stream command (matching original's disabled approach)
|
||||
// But we can still stream result if we have it
|
||||
if (result) {
|
||||
const cleanResult = uiHelpers.removeClosingTag(block, "result", result)
|
||||
await uiHelpers.say("completion_result", cleanResult, undefined, undefined, true)
|
||||
}
|
||||
} else {
|
||||
// no command, still outputting partial result - MATCH ORIGINAL EXACTLY
|
||||
if (result) {
|
||||
const cleanResult = uiHelpers.removeClosingTag(block, "result", result)
|
||||
await uiHelpers.say("completion_result", cleanResult, undefined, undefined, true)
|
||||
}
|
||||
if (!command) {
|
||||
// no command, still outputting partial result
|
||||
await uiHelpers.say(
|
||||
"completion_result",
|
||||
uiHelpers.removeClosingTag(block, "result", result),
|
||||
undefined,
|
||||
undefined,
|
||||
block.partial,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
async execute(config: TaskConfig, block: ToolUse): Promise<ToolResponse> {
|
||||
// For partial blocks, don't execute yet
|
||||
if (block.partial) {
|
||||
return ""
|
||||
}
|
||||
|
||||
const result: string | undefined = block.params.result
|
||||
const command: string | undefined = block.params.command
|
||||
|
||||
// Validate required parameters
|
||||
if (!result) {
|
||||
config.taskState.consecutiveMistakeCount++
|
||||
return "Missing required parameter: result"
|
||||
return await config.callbacks.sayAndCreateMissingParamError("attempt_completion", "result")
|
||||
}
|
||||
|
||||
config.taskState.consecutiveMistakeCount = 0
|
||||
@@ -107,10 +97,9 @@ export class AttemptCompletionHandler implements IToolHandler, IPartialBlockHand
|
||||
}
|
||||
|
||||
// complete command message - need to ask for approval
|
||||
const { response } = await config.callbacks.ask("command", command, false)
|
||||
if (response !== "yesButtonClicked") {
|
||||
// User rejected the command
|
||||
return "The user denied the command execution."
|
||||
const didApprove = await ToolResultUtils.askApprovalAndPushFeedback("command", command, config)
|
||||
if (!didApprove) {
|
||||
return formatResponse.toolDenied()
|
||||
}
|
||||
|
||||
// User approved, execute the command
|
||||
@@ -129,13 +118,16 @@ export class AttemptCompletionHandler implements IToolHandler, IPartialBlockHand
|
||||
}
|
||||
|
||||
// we already sent completion_result says, an empty string asks relinquishes control over button and field
|
||||
// in case last command was interactive and in partial state, the UI is expecting an ask response. This ends the command ask response, freeing up the UI to proceed with the completion ask.
|
||||
if (config.messageState.getClineMessages().at(-1)?.ask === "command_output") {
|
||||
await config.callbacks.say("command_output", "")
|
||||
}
|
||||
const { response, text, images, files: completionFiles } = await config.callbacks.ask("completion_result", "", false)
|
||||
if (response === "yesButtonClicked") {
|
||||
return "" // signals to recursive loop to stop (for now this never happens since yesButtonClicked will trigger a new task)
|
||||
}
|
||||
|
||||
await config.callbacks.say("user_feedback", text ?? "", images, completionFiles)
|
||||
await config.callbacks.saveCheckpoint()
|
||||
|
||||
const toolResults: (Anthropic.TextBlockParam | Anthropic.ImageBlockParam)[] = []
|
||||
if (commandResult) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { BrowserSession } from "@services/browser/BrowserSession"
|
||||
import { BrowserAction, BrowserActionResult, browserActions, ClineSayBrowserAction } from "@shared/ExtensionMessage"
|
||||
import { modelDoesntSupportWebp } from "@utils/model-utils"
|
||||
import { ToolUse } from "../../../assistant-message"
|
||||
import { formatResponse } from "../../../prompts/responses"
|
||||
import { ToolResponse } from "../.."
|
||||
import { showNotificationForApprovalIfAutoApprovalEnabled } from "../../utils"
|
||||
import type { IFullyManagedTool } from "../ToolExecutorCoordinator"
|
||||
import type { TaskConfig } from "../types/TaskConfig"
|
||||
import type { StronglyTypedUIHelpers } from "../types/UIHelpers"
|
||||
import { ToolResultUtils } from "../utils/ToolResultUtils"
|
||||
|
||||
export class BrowserToolHandler implements IFullyManagedTool {
|
||||
readonly name = "browser_action"
|
||||
@@ -59,11 +59,6 @@ export class BrowserToolHandler implements IFullyManagedTool {
|
||||
}
|
||||
|
||||
async execute(config: TaskConfig, block: ToolUse): Promise<ToolResponse> {
|
||||
// For partial blocks, don't execute yet
|
||||
if (block.partial) {
|
||||
return ""
|
||||
}
|
||||
|
||||
const action: BrowserAction | undefined = block.params.action as BrowserAction
|
||||
const url: string | undefined = block.params.url
|
||||
const coordinate: string | undefined = block.params.coordinate
|
||||
@@ -75,7 +70,6 @@ export class BrowserToolHandler implements IFullyManagedTool {
|
||||
config.taskState.consecutiveMistakeCount++
|
||||
const errorResult = await config.callbacks.sayAndCreateMissingParamError("browser_action", "action")
|
||||
await config.services.browserSession.closeBrowser()
|
||||
await config.callbacks.saveCheckpoint()
|
||||
return errorResult
|
||||
}
|
||||
|
||||
@@ -88,7 +82,6 @@ export class BrowserToolHandler implements IFullyManagedTool {
|
||||
config.taskState.consecutiveMistakeCount++
|
||||
const errorResult = await config.callbacks.sayAndCreateMissingParamError("browser_action", "url")
|
||||
await config.services.browserSession.closeBrowser()
|
||||
await config.callbacks.saveCheckpoint()
|
||||
return errorResult
|
||||
}
|
||||
config.taskState.consecutiveMistakeCount = 0
|
||||
@@ -96,21 +89,20 @@ export class BrowserToolHandler implements IFullyManagedTool {
|
||||
// Handle approval flow for launch using callbacks
|
||||
const autoApprover = config.autoApprover || { shouldAutoApproveTool: () => false }
|
||||
if (autoApprover.shouldAutoApproveTool(block.name)) {
|
||||
await config.callbacks.removeLastPartialMessageIfExistsWithType("ask", "browser_action_launch")
|
||||
await config.callbacks.say("browser_action_launch", url, undefined, undefined, false)
|
||||
config.taskState.consecutiveAutoApprovedRequestsCount++
|
||||
} else {
|
||||
// Show notification for approval if auto approval enabled
|
||||
const { showNotificationForApprovalIfAutoApprovalEnabled } = require("../../utils")
|
||||
showNotificationForApprovalIfAutoApprovalEnabled(
|
||||
`Cline wants to use a browser and launch ${url}`,
|
||||
config.autoApprovalSettings.enabled,
|
||||
config.autoApprovalSettings.enableNotifications,
|
||||
)
|
||||
|
||||
const { response } = await config.callbacks.ask("browser_action_launch", url, false)
|
||||
if (response !== "yesButtonClicked") {
|
||||
await config.callbacks.saveCheckpoint()
|
||||
return formatResponse.toolResult("The user rejected this browser action.")
|
||||
await config.callbacks.removeLastPartialMessageIfExistsWithType("say", "browser_action_launch")
|
||||
const didApprove = await ToolResultUtils.askApprovalAndPushFeedback("browser_action_launch", url, config)
|
||||
if (!didApprove) {
|
||||
return formatResponse.toolDenied()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,15 +110,8 @@ export class BrowserToolHandler implements IFullyManagedTool {
|
||||
await config.callbacks.say("browser_action_result", "")
|
||||
|
||||
// Re-make browserSession to make sure latest settings apply
|
||||
const browserSession = config.services.browserSession
|
||||
if (config.context) {
|
||||
await browserSession.dispose()
|
||||
const apiHandlerModel = config.api.getModel()
|
||||
const useWebp = config.api ? !modelDoesntSupportWebp(apiHandlerModel) : true
|
||||
config.services.browserSession = new BrowserSession(config.context, config.browserSettings, useWebp)
|
||||
} else {
|
||||
console.warn("no controller context available for browserSession")
|
||||
}
|
||||
// This updates the ToolExecutor browserSession and returns it, for us to modify the local config object accordingly. (Previously we would set config.services.browserSession = new BrowserSession... but this would not update the ToolExecutor.browserSession which is used in subsequent browser tool calls)
|
||||
config.services.browserSession = await config.callbacks.applyLatestBrowserSettings()
|
||||
await config.services.browserSession.launchBrowser()
|
||||
browserActionResult = await config.services.browserSession.navigateToUrl(url)
|
||||
} else {
|
||||
@@ -136,7 +121,6 @@ export class BrowserToolHandler implements IFullyManagedTool {
|
||||
config.taskState.consecutiveMistakeCount++
|
||||
const errorResult = await config.callbacks.sayAndCreateMissingParamError("browser_action", "coordinate")
|
||||
await config.services.browserSession.closeBrowser()
|
||||
await config.callbacks.saveCheckpoint()
|
||||
return errorResult
|
||||
}
|
||||
}
|
||||
@@ -145,7 +129,6 @@ export class BrowserToolHandler implements IFullyManagedTool {
|
||||
config.taskState.consecutiveMistakeCount++
|
||||
const errorResult = await config.callbacks.sayAndCreateMissingParamError("browser_action", "text")
|
||||
await config.services.browserSession.closeBrowser()
|
||||
await config.callbacks.saveCheckpoint()
|
||||
return errorResult
|
||||
}
|
||||
}
|
||||
@@ -200,22 +183,17 @@ export class BrowserToolHandler implements IFullyManagedTool {
|
||||
browserActionResult.screenshot ? [browserActionResult.screenshot] : [],
|
||||
)
|
||||
|
||||
await config.callbacks.saveCheckpoint()
|
||||
return result
|
||||
|
||||
case "close":
|
||||
const closeResult = formatResponse.toolResult(
|
||||
`The browser has been closed. You may now proceed to using other tools.`,
|
||||
)
|
||||
await config.callbacks.saveCheckpoint()
|
||||
return closeResult
|
||||
}
|
||||
} catch (error) {
|
||||
await config.services.browserSession.closeBrowser() // if any error occurs, the browser session is terminated
|
||||
return `Error executing browser action: ${(error as Error).message}`
|
||||
throw error
|
||||
}
|
||||
|
||||
// This should never be reached, but TypeScript requires a return
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,6 @@ export class CondenseHandler implements IToolHandler, IPartialBlockHandler {
|
||||
}
|
||||
|
||||
async execute(config: TaskConfig, block: ToolUse): Promise<ToolResponse> {
|
||||
// For partial blocks, don't execute yet
|
||||
if (block.partial) {
|
||||
return ""
|
||||
}
|
||||
|
||||
const context: string | undefined = block.params.context
|
||||
|
||||
// Validate required parameters
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import type { ToolUse } from "@core/assistant-message"
|
||||
import { formatResponse } from "@core/prompts/responses"
|
||||
import { showSystemNotification } from "@integrations/notifications"
|
||||
import { telemetryService } from "@services/posthog/PostHogClientProvider"
|
||||
import { COMMAND_REQ_APP_STRING } from "@shared/combineCommandSequences"
|
||||
import { ClineAsk } from "@shared/ExtensionMessage"
|
||||
import { fixModelHtmlEscaping } from "@utils/string"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import type { ToolResponse } from "../../index"
|
||||
import { showNotificationForApprovalIfAutoApprovalEnabled } from "../../utils"
|
||||
import type { IFullyManagedTool } from "../ToolExecutorCoordinator"
|
||||
import type { ToolValidator } from "../ToolValidator"
|
||||
import type { TaskConfig } from "../types/TaskConfig"
|
||||
import type { StronglyTypedUIHelpers } from "../types/UIHelpers"
|
||||
import { ToolResultUtils } from "../utils/ToolResultUtils"
|
||||
|
||||
export class ExecuteCommandToolHandler implements IFullyManagedTool {
|
||||
readonly name = "execute_command"
|
||||
@@ -24,15 +25,6 @@ export class ExecuteCommandToolHandler implements IFullyManagedTool {
|
||||
async handlePartialBlock(block: ToolUse, uiHelpers: StronglyTypedUIHelpers): Promise<void> {
|
||||
const command = block.params.command
|
||||
|
||||
// For commands, we need to wait for the requires_approval parameter before showing UI
|
||||
// This is because the approval flow depends on that parameter
|
||||
if (!block.params.requires_approval) {
|
||||
return // Wait for complete block
|
||||
}
|
||||
|
||||
// Command partial streaming is handled differently - just show the command
|
||||
const partialCommand = uiHelpers.removeClosingTag(block, "command", command)
|
||||
|
||||
// Check if this should be auto-approved to determine UI flow
|
||||
const shouldAutoApprove = uiHelpers.shouldAutoApproveTool("execute_command")
|
||||
|
||||
@@ -42,109 +34,101 @@ export class ExecuteCommandToolHandler implements IFullyManagedTool {
|
||||
// So we wait for the complete block
|
||||
return
|
||||
} else {
|
||||
// For manual approval, stream the ask message
|
||||
await uiHelpers.removeLastPartialMessageIfExistsWithType("say", "command")
|
||||
await uiHelpers.ask("command" as ClineAsk, partialCommand, block.partial).catch(() => {})
|
||||
await uiHelpers
|
||||
.ask("command" as ClineAsk, uiHelpers.removeClosingTag(block, "command", command), block.partial)
|
||||
.catch(() => {})
|
||||
}
|
||||
}
|
||||
|
||||
async execute(config: TaskConfig, block: ToolUse): Promise<ToolResponse> {
|
||||
// For partial blocks, don't execute yet
|
||||
if (block.partial) {
|
||||
return ""
|
||||
let command: string | undefined = block.params.command
|
||||
const requiresApprovalRaw: string | undefined = block.params.requires_approval
|
||||
const requiresApprovalPerLLM = requiresApprovalRaw?.toLowerCase() === "true"
|
||||
|
||||
// Validate required parameters
|
||||
if (!command) {
|
||||
config.taskState.consecutiveMistakeCount++
|
||||
return await config.callbacks.sayAndCreateMissingParamError("execute_command", "command")
|
||||
}
|
||||
|
||||
try {
|
||||
let command: string | undefined = block.params.command
|
||||
const requiresApprovalRaw: string | undefined = block.params.requires_approval
|
||||
const requiresApprovalPerLLM = requiresApprovalRaw?.toLowerCase() === "true"
|
||||
|
||||
// Validate required parameters
|
||||
if (!command) {
|
||||
config.taskState.consecutiveMistakeCount++
|
||||
return await config.callbacks.sayAndCreateMissingParamError("execute_command", "command")
|
||||
}
|
||||
|
||||
if (!requiresApprovalRaw) {
|
||||
config.taskState.consecutiveMistakeCount++
|
||||
return await config.callbacks.sayAndCreateMissingParamError("execute_command", "requires_approval")
|
||||
}
|
||||
|
||||
config.taskState.consecutiveMistakeCount = 0
|
||||
|
||||
// Pre-process command for certain models
|
||||
if (config.api.getModel().id.includes("gemini")) {
|
||||
command = fixModelHtmlEscaping(command)
|
||||
}
|
||||
|
||||
// Check clineignore validation for command
|
||||
const ignoredFileAttemptedToAccess = config.services.clineIgnoreController.validateCommand(command)
|
||||
if (ignoredFileAttemptedToAccess) {
|
||||
await config.callbacks.say("clineignore_error", ignoredFileAttemptedToAccess)
|
||||
return formatResponse.toolError(formatResponse.clineIgnoreError(ignoredFileAttemptedToAccess))
|
||||
}
|
||||
|
||||
let didAutoApprove = false
|
||||
|
||||
// Complex dual approval system for commands
|
||||
const autoApproveResult = config.autoApprover?.shouldAutoApproveTool(block.name)
|
||||
const [autoApproveSafe, autoApproveAll] = Array.isArray(autoApproveResult)
|
||||
? autoApproveResult
|
||||
: [autoApproveResult, false]
|
||||
|
||||
if ((!requiresApprovalPerLLM && autoApproveSafe) || (requiresApprovalPerLLM && autoApproveSafe && autoApproveAll)) {
|
||||
// Auto-approve flow
|
||||
await config.callbacks.removeLastPartialMessageIfExistsWithType("ask", "command")
|
||||
await config.callbacks.say("command", command, undefined, undefined, false)
|
||||
config.taskState.consecutiveAutoApprovedRequestsCount++
|
||||
didAutoApprove = true
|
||||
telemetryService.captureToolUsage(config.ulid, "execute_command", config.api.getModel().id, true, true)
|
||||
} else {
|
||||
// Manual approval flow
|
||||
showNotificationForApprovalIfAutoApprovalEnabled(
|
||||
`Cline wants to execute a command: ${command}`,
|
||||
config.autoApprovalSettings.enabled,
|
||||
config.autoApprovalSettings.enableNotifications,
|
||||
)
|
||||
|
||||
const { response } = await config.callbacks.ask(
|
||||
"command",
|
||||
command + `${autoApproveSafe && requiresApprovalPerLLM ? COMMAND_REQ_APP_STRING : ""}`,
|
||||
false,
|
||||
)
|
||||
|
||||
if (response !== "yesButtonClicked") {
|
||||
telemetryService.captureToolUsage(config.ulid, "execute_command", config.api.getModel().id, false, false)
|
||||
return "The user denied this operation."
|
||||
}
|
||||
telemetryService.captureToolUsage(config.ulid, "execute_command", config.api.getModel().id, false, true)
|
||||
}
|
||||
|
||||
// Setup timeout notification for long-running auto-approved commands
|
||||
let timeoutId: NodeJS.Timeout | undefined
|
||||
if (didAutoApprove && config.autoApprovalSettings.enableNotifications) {
|
||||
timeoutId = setTimeout(() => {
|
||||
showSystemNotification({
|
||||
subtitle: "Command is still running",
|
||||
message: "An auto-approved command has been running for 30s, and may need your attention.",
|
||||
})
|
||||
}, 30_000)
|
||||
}
|
||||
|
||||
// Execute the command
|
||||
const [userRejected, result] = await config.callbacks.executeCommandTool(command)
|
||||
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId)
|
||||
}
|
||||
|
||||
if (userRejected) {
|
||||
config.taskState.didRejectTool = true
|
||||
}
|
||||
|
||||
return result
|
||||
} catch (error) {
|
||||
return `Error executing command: ${(error as Error).message}`
|
||||
if (!requiresApprovalRaw) {
|
||||
config.taskState.consecutiveMistakeCount++
|
||||
return await config.callbacks.sayAndCreateMissingParamError("execute_command", "requires_approval")
|
||||
}
|
||||
|
||||
config.taskState.consecutiveMistakeCount = 0
|
||||
|
||||
// Pre-process command for certain models
|
||||
if (config.api.getModel().id.includes("gemini")) {
|
||||
command = fixModelHtmlEscaping(command)
|
||||
}
|
||||
|
||||
// Check clineignore validation for command
|
||||
const ignoredFileAttemptedToAccess = config.services.clineIgnoreController.validateCommand(command)
|
||||
if (ignoredFileAttemptedToAccess) {
|
||||
await config.callbacks.say("clineignore_error", ignoredFileAttemptedToAccess)
|
||||
return formatResponse.toolError(formatResponse.clineIgnoreError(ignoredFileAttemptedToAccess))
|
||||
}
|
||||
|
||||
let didAutoApprove = false
|
||||
|
||||
// If the model says this command is safe and auto approval for safe commands is true, execute the command
|
||||
// If the model says the command is risky, but *BOTH* auto approve settings are true, execute the command
|
||||
const autoApproveResult = config.autoApprover?.shouldAutoApproveTool(block.name)
|
||||
const [autoApproveSafe, autoApproveAll] = Array.isArray(autoApproveResult)
|
||||
? autoApproveResult
|
||||
: [autoApproveResult, false]
|
||||
|
||||
if ((!requiresApprovalPerLLM && autoApproveSafe) || (requiresApprovalPerLLM && autoApproveSafe && autoApproveAll)) {
|
||||
// Auto-approve flow
|
||||
await config.callbacks.removeLastPartialMessageIfExistsWithType("ask", "command")
|
||||
await config.callbacks.say("command", command, undefined, undefined, false)
|
||||
config.taskState.consecutiveAutoApprovedRequestsCount++
|
||||
didAutoApprove = true
|
||||
telemetryService.captureToolUsage(config.ulid, block.name, config.api.getModel().id, true, true)
|
||||
} else {
|
||||
// Manual approval flow
|
||||
showNotificationForApprovalIfAutoApprovalEnabled(
|
||||
`Cline wants to execute a command: ${command}`,
|
||||
config.autoApprovalSettings.enabled,
|
||||
config.autoApprovalSettings.enableNotifications,
|
||||
)
|
||||
|
||||
const didApprove = await ToolResultUtils.askApprovalAndPushFeedback(
|
||||
"command",
|
||||
command + `${autoApproveSafe && requiresApprovalPerLLM ? COMMAND_REQ_APP_STRING : ""}`,
|
||||
config,
|
||||
)
|
||||
if (!didApprove) {
|
||||
telemetryService.captureToolUsage(config.ulid, block.name, config.api.getModel().id, false, false)
|
||||
return formatResponse.toolDenied()
|
||||
}
|
||||
telemetryService.captureToolUsage(config.ulid, block.name, config.api.getModel().id, false, true)
|
||||
}
|
||||
|
||||
// Setup timeout notification for long-running auto-approved commands
|
||||
let timeoutId: NodeJS.Timeout | undefined
|
||||
if (didAutoApprove && config.autoApprovalSettings.enableNotifications) {
|
||||
// if the command was auto-approved, and it's long running we need to notify the user after some time has passed without proceeding
|
||||
timeoutId = setTimeout(() => {
|
||||
showSystemNotification({
|
||||
subtitle: "Command is still running",
|
||||
message: "An auto-approved command has been running for 30s, and may need your attention.",
|
||||
})
|
||||
}, 30_000)
|
||||
}
|
||||
|
||||
// Execute the command
|
||||
const [userRejected, result] = await config.callbacks.executeCommandTool(command)
|
||||
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId)
|
||||
}
|
||||
|
||||
if (userRejected) {
|
||||
config.taskState.didRejectTool = true
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import type { ToolUse } from "@core/assistant-message"
|
||||
import { telemetryService } from "@services/posthog/PostHogClientProvider"
|
||||
import { parseSourceCodeForDefinitionsTopLevel } from "@services/tree-sitter"
|
||||
import { getReadablePath, isLocatedInWorkspace } from "@utils/path"
|
||||
import * as path from "path"
|
||||
import { formatResponse } from "@/core/prompts/responses"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import type { ToolResponse } from "../../index"
|
||||
import { showNotificationForApprovalIfAutoApprovalEnabled } from "../../utils"
|
||||
import type { IFullyManagedTool } from "../ToolExecutorCoordinator"
|
||||
import type { ToolValidator } from "../ToolValidator"
|
||||
import type { TaskConfig } from "../types/TaskConfig"
|
||||
import type { StronglyTypedUIHelpers } from "../types/UIHelpers"
|
||||
import { ToolResultUtils } from "../utils/ToolResultUtils"
|
||||
|
||||
export class ListCodeDefinitionNamesToolHandler implements IFullyManagedTool {
|
||||
readonly name = "list_code_definition_names"
|
||||
@@ -22,20 +24,13 @@ export class ListCodeDefinitionNamesToolHandler implements IFullyManagedTool {
|
||||
async handlePartialBlock(block: ToolUse, uiHelpers: StronglyTypedUIHelpers): Promise<void> {
|
||||
const relPath = block.params.path
|
||||
|
||||
// Early return if we don't have enough data yet
|
||||
if (!relPath) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get config access for services
|
||||
const config = uiHelpers.getConfig()
|
||||
|
||||
// Create and show partial UI message
|
||||
const absolutePath = path.resolve(config.cwd, relPath)
|
||||
const sharedMessageProps = {
|
||||
tool: "listCodeDefinitionNames",
|
||||
path: getReadablePath(config.cwd, uiHelpers.removeClosingTag(block, "path", relPath)),
|
||||
content: absolutePath,
|
||||
content: "",
|
||||
operationIsLocatedInWorkspace: await isLocatedInWorkspace(relPath),
|
||||
}
|
||||
|
||||
@@ -52,11 +47,6 @@ export class ListCodeDefinitionNamesToolHandler implements IFullyManagedTool {
|
||||
}
|
||||
|
||||
async execute(config: TaskConfig, block: ToolUse): Promise<ToolResponse> {
|
||||
// For partial blocks, return empty string to let coordinator handle UI
|
||||
if (block.partial) {
|
||||
return ""
|
||||
}
|
||||
|
||||
const relDirPath: string | undefined = block.params.path
|
||||
|
||||
// Validate required parameters
|
||||
@@ -68,12 +58,14 @@ export class ListCodeDefinitionNamesToolHandler implements IFullyManagedTool {
|
||||
|
||||
config.taskState.consecutiveMistakeCount = 0
|
||||
const absolutePath = path.resolve(config.cwd, relDirPath!)
|
||||
// Execute the actual parse source code operation
|
||||
const result = await parseSourceCodeForDefinitionsTopLevel(absolutePath, config.services.clineIgnoreController)
|
||||
|
||||
// Handle approval flow
|
||||
const sharedMessageProps = {
|
||||
tool: "listCodeDefinitionNames",
|
||||
path: getReadablePath(config.cwd, relDirPath!),
|
||||
content: absolutePath,
|
||||
content: result,
|
||||
operationIsLocatedInWorkspace: await isLocatedInWorkspace(relDirPath!),
|
||||
}
|
||||
|
||||
@@ -100,22 +92,15 @@ export class ListCodeDefinitionNamesToolHandler implements IFullyManagedTool {
|
||||
|
||||
await config.callbacks.removeLastPartialMessageIfExistsWithType("say", "tool")
|
||||
|
||||
// Ask for approval
|
||||
const { response } = await config.callbacks.ask("tool", completeMessage, false)
|
||||
|
||||
if (response !== "yesButtonClicked") {
|
||||
// Handle rejection
|
||||
config.taskState.didRejectTool = true
|
||||
const didApprove = await ToolResultUtils.askApprovalAndPushFeedback("tool", completeMessage, config)
|
||||
if (!didApprove) {
|
||||
telemetryService.captureToolUsage(config.ulid, block.name, config.api.getModel().id, false, false)
|
||||
return "The user denied this operation."
|
||||
return formatResponse.toolDenied()
|
||||
} else {
|
||||
telemetryService.captureToolUsage(config.ulid, block.name, config.api.getModel().id, false, true)
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the actual parse source code operation
|
||||
const result = await parseSourceCodeForDefinitionsTopLevel(absolutePath, config.services.clineIgnoreController)
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import type { ToolUse } from "@core/assistant-message"
|
||||
import { formatResponse } from "@core/prompts/responses"
|
||||
import { listFiles } from "@services/glob/list-files"
|
||||
import { telemetryService } from "@services/posthog/PostHogClientProvider"
|
||||
import { getReadablePath, isLocatedInWorkspace } from "@utils/path"
|
||||
import * as path from "path"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import type { ToolResponse } from "../../index"
|
||||
import { showNotificationForApprovalIfAutoApprovalEnabled } from "../../utils"
|
||||
import type { IFullyManagedTool } from "../ToolExecutorCoordinator"
|
||||
import type { ToolValidator } from "../ToolValidator"
|
||||
import type { TaskConfig } from "../types/TaskConfig"
|
||||
import type { StronglyTypedUIHelpers } from "../types/UIHelpers"
|
||||
import { ToolResultUtils } from "../utils/ToolResultUtils"
|
||||
|
||||
export class ListFilesToolHandler implements IFullyManagedTool {
|
||||
readonly name = "list_files"
|
||||
@@ -23,22 +24,16 @@ export class ListFilesToolHandler implements IFullyManagedTool {
|
||||
async handlePartialBlock(block: ToolUse, uiHelpers: StronglyTypedUIHelpers): Promise<void> {
|
||||
const relPath = block.params.path
|
||||
|
||||
// Early return if we don't have enough data yet
|
||||
if (!relPath) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get config access for services
|
||||
const config = uiHelpers.getConfig()
|
||||
|
||||
// Create and show partial UI message
|
||||
const absolutePath = path.resolve(config.cwd, relPath)
|
||||
const recursiveRaw = block.params.recursive
|
||||
const recursive = recursiveRaw?.toLowerCase() === "true"
|
||||
const sharedMessageProps = {
|
||||
tool: recursive ? "listFilesRecursive" : "listFilesTopLevel",
|
||||
path: getReadablePath(config.cwd, uiHelpers.removeClosingTag(block, "path", relPath)),
|
||||
content: absolutePath,
|
||||
content: "",
|
||||
operationIsLocatedInWorkspace: await isLocatedInWorkspace(relPath),
|
||||
}
|
||||
|
||||
@@ -55,11 +50,6 @@ export class ListFilesToolHandler implements IFullyManagedTool {
|
||||
}
|
||||
|
||||
async execute(config: TaskConfig, block: ToolUse): Promise<ToolResponse> {
|
||||
// For partial blocks, return empty string to let coordinator handle UI
|
||||
if (block.partial) {
|
||||
return ""
|
||||
}
|
||||
|
||||
const relDirPath: string | undefined = block.params.path
|
||||
const recursiveRaw: string | undefined = block.params.recursive
|
||||
const recursive = recursiveRaw?.toLowerCase() === "true"
|
||||
@@ -74,11 +64,16 @@ export class ListFilesToolHandler implements IFullyManagedTool {
|
||||
config.taskState.consecutiveMistakeCount = 0
|
||||
const absolutePath = path.resolve(config.cwd, relDirPath!)
|
||||
|
||||
// Execute the actual list files operation
|
||||
const [files, didHitLimit] = await listFiles(absolutePath, recursive, 200)
|
||||
|
||||
const result = formatResponse.formatFilesList(absolutePath, files, didHitLimit, config.services.clineIgnoreController)
|
||||
|
||||
// Handle approval flow
|
||||
const sharedMessageProps = {
|
||||
tool: recursive ? "listFilesRecursive" : "listFilesTopLevel",
|
||||
path: getReadablePath(config.cwd, relDirPath!),
|
||||
content: absolutePath,
|
||||
content: result,
|
||||
operationIsLocatedInWorkspace: await isLocatedInWorkspace(relDirPath!),
|
||||
}
|
||||
|
||||
@@ -105,24 +100,15 @@ export class ListFilesToolHandler implements IFullyManagedTool {
|
||||
|
||||
await config.callbacks.removeLastPartialMessageIfExistsWithType("say", "tool")
|
||||
|
||||
// Ask for approval
|
||||
const { response } = await config.callbacks.ask("tool", completeMessage, false)
|
||||
|
||||
if (response !== "yesButtonClicked") {
|
||||
// Handle rejection
|
||||
config.taskState.didRejectTool = true
|
||||
const didApprove = await ToolResultUtils.askApprovalAndPushFeedback("tool", completeMessage, config)
|
||||
if (!didApprove) {
|
||||
telemetryService.captureToolUsage(config.ulid, block.name, config.api.getModel().id, false, false)
|
||||
return "The user denied this operation."
|
||||
return formatResponse.toolDenied()
|
||||
} else {
|
||||
telemetryService.captureToolUsage(config.ulid, block.name, config.api.getModel().id, false, true)
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the actual list files operation
|
||||
const [files, didHitLimit] = await listFiles(absolutePath, recursive, 200)
|
||||
|
||||
const result = formatResponse.formatFilesList(absolutePath, files, didHitLimit, config.services.clineIgnoreController)
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user