mirror of
https://github.com/cline/cline.git
synced 2026-09-09 15:02:23 +08:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc98799948 | ||
|
|
3fab973195 | ||
|
|
25616d344d | ||
|
|
231eefee00 |
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Refactor Anthropic handler to use metadata for reasoning support
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
docs: add workflow guide for adding settings to Cline
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Exclude files without extensions (and dotfiles) from getDiffSet results if they are binary
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Fix Cerebras rate limiting by using conservative max_tokens (16K) instead of model maximum.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Fixed Auto Compact not triggering when using Claude Code provider. Short model aliases like "sonnet" and "opus" are now correctly recognized as Claude 4+ models.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Fix Workspace and Favorites history filters to work independently instead of being mutually exclusive
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Fixed connection failures with remote MCP servers that return 404 instead of 405 for SSE stream checks. This was causing "Failed to open SSE stream: Not Found" errors after the v3.46.0 SDK upgrade.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
fix: correct typos in gemini system prompt overrides
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
feat(prompts): modify prompts for parallel tool usage in claude and gemini 3 models
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Stop automatically opening Cline sidebar on extension update - only show a notification
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
add supportsReasoning property to Baseten models
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Bug fix for the isMacOSOrLinux() function in the webview-ui/ code for the extension.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": minor
|
||||
---
|
||||
|
||||
show slash command autocompletion in the cli
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
fix regression that broke JSON parsing for SAP AI Core provider in native API mode for claude models
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
fix: Fetch remote config values from the cache
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Fix Baseten model selector issue in model picker modal mode
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Replace current diff edit tools with Apply Patch tool for GPT-5+ models
|
||||
@@ -1,51 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Only run in Claude Code remote environments
|
||||
if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cd "$CLAUDE_PROJECT_DIR"
|
||||
|
||||
echo "=== Claude Code for Web Setup ==="
|
||||
echo ""
|
||||
|
||||
# Install latest gh CLI tool
|
||||
echo "Installing GitHub CLI..."
|
||||
GH_VERSION=$(curl -s https://api.github.com/repos/cli/cli/releases/latest | grep '"tag_name"' | cut -d'"' -f4 | sed 's/^v//')
|
||||
curl -sL "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_amd64.tar.gz" -o /tmp/gh.tar.gz
|
||||
tar -xzf /tmp/gh.tar.gz -C /tmp
|
||||
sudo mv "/tmp/gh_${GH_VERSION}_linux_amd64/bin/gh" /usr/local/bin/gh
|
||||
rm -rf /tmp/gh.tar.gz /tmp/gh_${GH_VERSION}_linux_amd64
|
||||
echo "Installed gh version: $(gh --version | head -1)"
|
||||
echo ""
|
||||
|
||||
# Check if GITHUB_TOKEN is set and configure gh
|
||||
if [ -n "${GITHUB_TOKEN:-}" ]; then
|
||||
echo "GITHUB_TOKEN is configured - gh CLI is ready to use"
|
||||
echo ""
|
||||
echo "You can use gh commands directly, for example:"
|
||||
echo " gh issue list --repo cline/cline --limit 5"
|
||||
echo " gh pr list --repo cline/cline --state open"
|
||||
echo " gh issue view 123 --repo cline/cline"
|
||||
echo ""
|
||||
else
|
||||
echo "GITHUB_TOKEN is not set - gh CLI will have limited functionality"
|
||||
echo ""
|
||||
echo "To enable full GitHub API access:"
|
||||
echo "1. Create a Fine-grained Personal Access Token at https://github.com/settings/tokens?type=beta"
|
||||
echo "2. Add it as GITHUB_TOKEN in your Claude Code environment settings"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Install project dependencies
|
||||
echo "Installing dependencies..."
|
||||
npm run install:all
|
||||
|
||||
# Generate gRPC/protobuf types (required for TypeScript)
|
||||
echo "Generating proto types..."
|
||||
npm run protos
|
||||
|
||||
echo ""
|
||||
echo "Session setup complete!"
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/claude-code-for-web-setup.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
# Adding a Setting to Cline
|
||||
|
||||
Add a new user-facing setting (boolean toggle, dropdown, etc.) to Cline.
|
||||
|
||||
## Overview
|
||||
|
||||
Settings in Cline flow through multiple layers:
|
||||
1. **Proto definition** → TypeScript generation
|
||||
2. **Backend state management** → reading, writing, persistence
|
||||
3. **State broadcasting** → sending to webview
|
||||
4. **Frontend** → displaying and updating
|
||||
|
||||
**Common gotcha**: Forgetting to include the setting in `getStateToPostToWebview()` causes the setting to reset when navigating away from settings or toggling other settings.
|
||||
|
||||
## Step 1: Proto Definition
|
||||
|
||||
Add the field to both messages in `proto/cline/state.proto`:
|
||||
|
||||
1. **GlobalState** (for persistence):
|
||||
```protobuf
|
||||
message GlobalState {
|
||||
// ... existing fields
|
||||
optional bool your_setting = NEXT_NUMBER;
|
||||
}
|
||||
```
|
||||
|
||||
2. **UpdateSettingsRequest** (for updates from UI):
|
||||
```protobuf
|
||||
message UpdateSettingsRequest {
|
||||
// ... existing fields
|
||||
optional bool your_setting = NEXT_NUMBER;
|
||||
}
|
||||
```
|
||||
|
||||
Generate TypeScript:
|
||||
```bash
|
||||
npm run proto:generate
|
||||
```
|
||||
|
||||
## Step 2: TypeScript Type Definitions
|
||||
|
||||
### `src/shared/storage/state-keys.ts`
|
||||
|
||||
Add to the `Settings` interface:
|
||||
```typescript
|
||||
export interface Settings {
|
||||
// ... existing
|
||||
yourSetting: boolean
|
||||
}
|
||||
```
|
||||
|
||||
### `src/shared/ExtensionMessage.ts`
|
||||
|
||||
Add to the `ExtensionState` interface:
|
||||
```typescript
|
||||
export interface ExtensionState {
|
||||
// ... existing
|
||||
yourSetting?: boolean
|
||||
}
|
||||
```
|
||||
|
||||
## Step 3: Backend State Management
|
||||
|
||||
### `src/core/storage/utils/state-helpers.ts`
|
||||
|
||||
Add reading from storage (with default value):
|
||||
```typescript
|
||||
// Near other similar reads (~line 320)
|
||||
const yourSetting = context.globalState.get<GlobalStateAndSettings["yourSetting"]>("yourSetting")
|
||||
|
||||
// In the return object (~line 690)
|
||||
return {
|
||||
// ... existing
|
||||
yourSetting: yourSetting ?? false, // default value
|
||||
}
|
||||
```
|
||||
|
||||
### `src/core/controller/state/updateSettings.ts`
|
||||
|
||||
Add handling for the setting update:
|
||||
```typescript
|
||||
if (request.yourSetting !== undefined) {
|
||||
controller.stateManager.setGlobalState("yourSetting", !!request.yourSetting)
|
||||
}
|
||||
```
|
||||
|
||||
## Step 4: State Broadcasting (CRITICAL)
|
||||
|
||||
### `src/core/controller/index.ts`
|
||||
|
||||
**This is the most commonly missed step!**
|
||||
|
||||
In `getStateToPostToWebview()`:
|
||||
|
||||
1. **Read the setting** (near other similar reads ~line 867):
|
||||
```typescript
|
||||
const yourSetting = this.stateManager.getGlobalSettingsKey("yourSetting")
|
||||
```
|
||||
|
||||
2. **Include in return object** (~line 968):
|
||||
```typescript
|
||||
return {
|
||||
// ... existing
|
||||
yourSetting,
|
||||
}
|
||||
```
|
||||
|
||||
Without this, the setting will appear to save but will reset when the UI refreshes.
|
||||
|
||||
## Step 5: Frontend
|
||||
|
||||
### `webview-ui/src/context/ExtensionStateContext.tsx`
|
||||
|
||||
Add default value in `defaultState`:
|
||||
```typescript
|
||||
const defaultState: ExtensionState = {
|
||||
// ... existing
|
||||
yourSetting: false,
|
||||
}
|
||||
```
|
||||
|
||||
### UI Component (e.g., `FeatureSettingsSection.tsx`)
|
||||
|
||||
1. **Extract from context**:
|
||||
```typescript
|
||||
const { yourSetting } = useExtensionState()
|
||||
```
|
||||
|
||||
2. **Render the control**:
|
||||
```tsx
|
||||
<VSCodeCheckbox
|
||||
checked={yourSetting}
|
||||
onChange={(e: any) => {
|
||||
const checked = e.target.checked === true
|
||||
updateSetting("yourSetting", checked)
|
||||
}}>
|
||||
Your Setting Label
|
||||
</VSCodeCheckbox>
|
||||
```
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] `proto/cline/state.proto` - GlobalState field
|
||||
- [ ] `proto/cline/state.proto` - UpdateSettingsRequest field
|
||||
- [ ] `npm run proto:generate`
|
||||
- [ ] `src/shared/storage/state-keys.ts` - Settings interface
|
||||
- [ ] `src/shared/ExtensionMessage.ts` - ExtensionState interface
|
||||
- [ ] `src/core/storage/utils/state-helpers.ts` - read with default
|
||||
- [ ] `src/core/controller/state/updateSettings.ts` - handle update
|
||||
- [ ] `src/core/controller/index.ts` - **getStateToPostToWebview()** (read + return)
|
||||
- [ ] `webview-ui/src/context/ExtensionStateContext.tsx` - default state
|
||||
- [ ] UI component - display and onChange handler
|
||||
|
||||
## Testing
|
||||
|
||||
1. Toggle the setting ON
|
||||
2. Navigate away from settings (e.g., to chat)
|
||||
3. Return to settings - verify setting is still ON
|
||||
4. Toggle a DIFFERENT setting
|
||||
5. Verify your setting didn't reset
|
||||
6. Reload the window - verify persistence
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/docs/
|
||||
/.github/ @saoudrizwan @garoth @sjf
|
||||
/README.md @saoudrizwan @nickbaumann98
|
||||
/src/core/storage/ @celestial-vault @abeatrix
|
||||
/src/core/storage/ @celestial-vault
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
name: Claude Issue Triage
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
# Manual trigger for backfilling existing issues. Run from terminal:
|
||||
# gh workflow run claude-issue-triage.yml -f issue_number=1234
|
||||
# Or batch process:
|
||||
# gh issue list --state open --limit 10 --json number --jq '.[].number' | while read num; do
|
||||
# gh workflow run claude-issue-triage.yml -f issue_number=$num
|
||||
# sleep 60
|
||||
# done
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
issue_number:
|
||||
description: 'Issue number to triage'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
claude-issue-triage:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
# SECURITY: These permissions are intentionally restrictive.
|
||||
# - contents: read -> Claude can read the codebase but CANNOT write/push any code
|
||||
# - issues: write -> Claude can comment and add labels (the only write access needed)
|
||||
# - pull-requests: read -> Claude can view PR context but CANNOT create PRs
|
||||
# This ensures that even if a malicious user attempts prompt injection via issue content,
|
||||
# Claude cannot modify repository code, create branches, or open PRs.
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: read
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run Issue Response & Triage
|
||||
id: triage
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
allowed_non_write_users: "*"
|
||||
# Allow all tools - security is enforced by GitHub permissions above (contents: read, issues: write)
|
||||
claude_args: --model claude-opus-4-5-20251101 --allowedTools "Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch"
|
||||
prompt: |
|
||||
You're a GitHub issue first responder for the open source Cline repository.
|
||||
|
||||
**Issue:** #${{ github.event.issue.number || inputs.issue_number }}
|
||||
**Title:** ${{ github.event.issue.title || 'See issue details below' }}
|
||||
**Author:** @${{ github.event.issue.user.login || 'See issue details below' }}
|
||||
|
||||
## Your job
|
||||
|
||||
Investigate this issue thoroughly, then post a single helpful comment that helps the user and gives maintainers the context they need.
|
||||
|
||||
## Investigation
|
||||
|
||||
Start by reading the full issue:
|
||||
gh issue view ${{ github.event.issue.number || inputs.issue_number }}
|
||||
|
||||
### Search for duplicates and related issues
|
||||
|
||||
Search thoroughly for existing issues that match this one:
|
||||
gh issue list --search "<keywords from the issue>" --state all --limit 30
|
||||
gh issue list --search "<error messages>" --state all --limit 20
|
||||
gh issue list --search "<affected feature/component>" --state all --limit 20
|
||||
|
||||
For each relevant issue you find, read it including its comments:
|
||||
gh issue view <number> --comments
|
||||
|
||||
You're looking for:
|
||||
- **Duplicates**: Issues describing the same problem. Link to them and explain why you think they're duplicates. If closed, check how they were resolved - the solution might apply here.
|
||||
- **Related issues**: Similar problems or context that could help. Pull useful information from their comments (workarounds others found, debugging steps that helped, maintainer explanations). Link to them and explain the connection.
|
||||
|
||||
If there are closed issues with solutions, surface those solutions prominently - this might immediately solve the user's problem.
|
||||
|
||||
### Analyze recent changes (ALWAYS DO THIS)
|
||||
|
||||
Many issues are regressions from recent releases. **Always** check what changed recently:
|
||||
gh release list --limit 10
|
||||
gh pr list --state merged --limit 50 --json number,title,mergedAt,author,body
|
||||
|
||||
Look for PRs merged in the last few weeks that might correlate with the issue. If you find a likely connection:
|
||||
gh pr view <number>
|
||||
gh pr diff <number>
|
||||
git log --since="1 month ago" --oneline -- <relevant paths>
|
||||
git show <commit>
|
||||
|
||||
**Always include your findings in your comment:**
|
||||
- If you find a regression, call it out explicitly: which PR/commit likely caused it, who authored it, what changed, and suggest a fix direction if you can see one.
|
||||
- If you don't find anything related, still mention it: "I analyzed recent PRs and releases but didn't find any changes that seem related to this issue."
|
||||
|
||||
### Search the codebase
|
||||
|
||||
Find the relevant code:
|
||||
- Use grep/find to locate code related to the issue
|
||||
- Key areas: `src/api/` (providers/models), `src/core/prompts/` (tools/prompts), platform-specific code for VS Code vs JetBrains
|
||||
|
||||
### Find documentation
|
||||
|
||||
Cline docs are at **https://docs.cline.bot/** and built with Mintlify from the `docs/` directory.
|
||||
|
||||
The URL structure maps directly to the file structure:
|
||||
- `docs/getting-started/selecting-your-model.mdx` → https://docs.cline.bot/getting-started/selecting-your-model
|
||||
- `docs/troubleshooting.mdx` → https://docs.cline.bot/troubleshooting
|
||||
- Headings become anchors: `## Which Model` → `#which-model`
|
||||
|
||||
Search the `docs/` directory to find relevant documentation, then construct URLs to link users to:
|
||||
```bash
|
||||
ls docs/
|
||||
grep -r "keyword" docs/ --include="*.mdx" -l
|
||||
```
|
||||
|
||||
### Identify subject matter experts
|
||||
|
||||
For issues that clearly need engineering attention:
|
||||
git log --since="6 months ago" --format="%an" -- <relevant paths> | sort | uniq -c | sort -rn | head -5
|
||||
|
||||
Cross-reference with GitHub usernames. Include in your response (@mention, do NOT assign):
|
||||
|
||||
| SME | Reason |
|
||||
|-----|--------|
|
||||
| @username1 | Authored PR #X which modified this area |
|
||||
| @username2 | Primary contributor to affected file |
|
||||
|
||||
## Weak model detection
|
||||
|
||||
Many issues are caused by users running small or non-frontier models that don't tool-call reliably. Signs include:
|
||||
- Model failing to use tools correctly
|
||||
- Nonsensical or malformed responses
|
||||
- User is running a small/local model or older model version
|
||||
|
||||
If this looks like a weak model issue, kindly suggest they try reproducing with Claude Sonnet and report back if it persists. Link to https://docs.cline.bot/getting-started/selecting-your-model if helpful. Still label and triage normally.
|
||||
|
||||
## Your comment
|
||||
|
||||
Write a single comment as a helpful community member. Be conversational, not robotic. Include what's relevant:
|
||||
|
||||
- **Helpful response** - Answer their question, suggest a fix, provide a workaround. If you found solutions in related closed issues, surface those prominently.
|
||||
- **Duplicates and related issues** - Link to any you found and explain why they're duplicates/related. Summarize useful context from their comments.
|
||||
- **Regression analysis** - If this looks like a regression, explain what change likely caused it, link to the PR/commit, and tag the author.
|
||||
- **Clarifying questions** - If you need more info, ask specific questions. Don't ask for things already provided.
|
||||
- **SME table** - Include the table above if this needs engineering attention. Don't tag people for questions with obvious answers or weak-model issues.
|
||||
- **Context for maintainers** - Relevant code paths, what you found. Keep it concise.
|
||||
- **Docs links** - If there's relevant documentation, link to it naturally in your response as a recommendation (e.g., "For more details, check out [the Ollama setup guide](url)"). Do NOT add a "Sources" section at the end - integrate doc links into your response where they're helpful.
|
||||
- **Possible Duplicates section** - ALWAYS include a "Possible Duplicates" section at the end of your comment listing issues that might be duplicates so maintainers can quickly close if appropriate. If none found, say "No obvious duplicates found."
|
||||
|
||||
## Labels
|
||||
First, retrieve all available labels and read their descriptions to understand what each is for:
|
||||
gh label list --json name,description --limit 100
|
||||
|
||||
Then apply the appropriate labels based on your analysis. Only use labels from the list above—do not create new labels.
|
||||
gh issue edit ${{ github.event.issue.number || inputs.issue_number }} --add-label "label1,label2"
|
||||
|
||||
If your regression analysis found a likely culprit (a recent PR/commit that probably caused this issue), add the "Regression" label:
|
||||
gh issue edit ${{ github.event.issue.number || inputs.issue_number }} --add-label "Regression"
|
||||
|
||||
IMPORTANT: After posting your comment, add the "Bot Responded" label to indicate this issue has received an automated response:
|
||||
gh issue edit ${{ github.event.issue.number || inputs.issue_number }} --add-label "Bot Responded"
|
||||
|
||||
## Remember
|
||||
|
||||
- **This is a one-time automated response** - you will NOT see their reply or respond again. Never say things like "I can help you", "let me know", "once I have that info", or "I can give you more targeted help" - you won't be there to follow up. If you ask clarifying questions, frame them for the maintainers who will follow up, e.g., "If you can share X, that would help the maintainers diagnose this."
|
||||
- Don't be formulaic. Respond to what the issue actually needs.
|
||||
- Surface solutions from past issues - often the fastest path to helping.
|
||||
- Connecting regressions to specific changes is extremely valuable.
|
||||
- Link issues with #number so they're clickable.
|
||||
@@ -1,272 +0,0 @@
|
||||
name: Claude PR Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, ready_for_review]
|
||||
# Manual trigger for backfilling existing PRs. Run from terminal:
|
||||
# gh workflow run claude-pr-review.yml -f pr_number=1234
|
||||
# Or batch process open PRs:
|
||||
# gh pr list --state open --limit 10 --json number --jq '.[].number' | while read num; do
|
||||
# gh workflow run claude-pr-review.yml -f pr_number=$num
|
||||
# sleep 60
|
||||
# done
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: 'PR number to review'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
claude-pr-review:
|
||||
# Runs on PR opened/ready_for_review (skips drafts) or manual trigger for backfilling
|
||||
if: |
|
||||
(github.event_name == 'pull_request' && github.event.pull_request.draft == false) ||
|
||||
github.event_name == 'workflow_dispatch'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
|
||||
# SECURITY: These permissions are intentionally restrictive.
|
||||
# - contents: read -> Claude can read the codebase but CANNOT write/push any code
|
||||
# - pull-requests: write -> Claude can post reviews and inline suggestions
|
||||
# - issues: read -> Claude can search for related issues
|
||||
# NOTE: Even with pull-requests: write, Claude CANNOT merge PRs because branch protection
|
||||
# requires 1 approval from a Code Owner. The GITHUB_TOKEN cannot bypass this.
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: read
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get PR number
|
||||
id: pr
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
||||
echo "number=${{ inputs.pr_number }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Run PR Review
|
||||
id: review
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
allowed_non_write_users: "*"
|
||||
claude_args: --model claude-opus-4-5-20251101 --allowedTools "Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch"
|
||||
prompt: |
|
||||
You're a GitHub PR reviewer for the open source Cline repository. Your goal is to give the PR author helpful feedback and give maintainers the context they need to review efficiently.
|
||||
|
||||
PR: #${{ steps.pr.outputs.number }}
|
||||
|
||||
## Gather context
|
||||
|
||||
```bash
|
||||
# Get full PR details
|
||||
gh pr view ${{ steps.pr.outputs.number }} --json number,title,body,author,createdAt,updatedAt,isDraft,labels,commits,files,additions,deletions,changedFiles,baseRefName,headRefName,mergeable,reviewDecision
|
||||
|
||||
# Get the diff
|
||||
gh pr diff ${{ steps.pr.outputs.number }}
|
||||
|
||||
# Check CI status
|
||||
gh pr checks ${{ steps.pr.outputs.number }}
|
||||
|
||||
# Get existing review comments (to understand context and your previous feedback)
|
||||
gh api repos/${{ github.repository }}/pulls/${{ steps.pr.outputs.number }}/comments --jq '.[] | {user: .user.login, body: .body, path: .path, created_at: .created_at}'
|
||||
|
||||
# Get conversation comments
|
||||
gh pr view ${{ steps.pr.outputs.number }} --comments
|
||||
```
|
||||
|
||||
If this is a re-review (workflow_dispatch event):
|
||||
Read your previous comments carefully. Understand what you asked for before.
|
||||
Check if new commits or comments address your previous feedback.
|
||||
|
||||
## Check contributing guidelines
|
||||
|
||||
Flag (but don't block) if:
|
||||
- Missing changeset - For user-facing changes, check if there's a `.changeset/` file:
|
||||
```bash
|
||||
gh pr diff ${{ steps.pr.outputs.number }} --name-only | grep '.changeset/' || echo "No changeset found"
|
||||
```
|
||||
If missing, ask them to run `npm run changeset`
|
||||
- Missing tests - New features should have tests
|
||||
|
||||
## Find related issues and PRs
|
||||
|
||||
Search thoroughly for context that might help with the review:
|
||||
|
||||
```bash
|
||||
# Find related issues for context
|
||||
gh issue list --search "<keywords from the PR>" --state all --limit 30
|
||||
gh issue list --search "<error messages or feature names>" --state all --limit 20
|
||||
|
||||
# Find similar PRs for reference
|
||||
gh pr list --search "<keywords>" --state all --limit 30
|
||||
```
|
||||
|
||||
For each relevant issue or PR you find, read it including comments:
|
||||
```bash
|
||||
gh issue view <number> --comments
|
||||
gh pr view <number> --comments
|
||||
```
|
||||
|
||||
Look for:
|
||||
- Open issues this PR might fix that weren't linked in the description
|
||||
- Similar PRs that went through review - what feedback did they get? What patterns did they follow?
|
||||
- Context from maintainer discussions that could inform your review
|
||||
|
||||
## Find subject matter experts
|
||||
|
||||
For files changed in this PR, find who knows the code best:
|
||||
```bash
|
||||
# Get files changed
|
||||
gh pr diff ${{ steps.pr.outputs.number }} --name-only
|
||||
|
||||
# For each relevant path, find contributors
|
||||
git log --since="6 months ago" --format="%an" -- <path> | sort | uniq -c | sort -rn | head -5
|
||||
```
|
||||
|
||||
Cross-reference git authors with GitHub usernames. Include an SME table in your response:
|
||||
|
||||
| SME | Reason |
|
||||
|-----|--------|
|
||||
| @username1 | Authored PR #X which modified this area |
|
||||
| @username2 | Primary contributor to affected file (15 commits in 6 months) |
|
||||
| @username3 | Reviewed similar PR #Y with extensive feedback |
|
||||
|
||||
## Deep code review
|
||||
|
||||
This is the most important part. Don't just look for syntax issues - understand what the PR is trying to achieve and whether the implementation is the right approach.
|
||||
|
||||
Step 1: Understand the intent
|
||||
Read the PR description and understand what the author is trying to accomplish. What problem are they solving? What feature are they adding?
|
||||
|
||||
Step 2: Form your own opinion first
|
||||
Before analyzing their code, think about how YOU would implement this feature or fix. What files would you touch? What patterns would you follow? What edge cases would you handle?
|
||||
|
||||
Step 3: Compare approaches
|
||||
Now look at their implementation. How does it compare to what you would have done?
|
||||
- Is their approach better in some ways? Note what they did well.
|
||||
- Is their approach missing something? Be specific about what and why.
|
||||
- Are there edge cases they haven't considered?
|
||||
- Does it follow the patterns established in similar parts of the codebase?
|
||||
|
||||
Step 4: Look at the bigger picture
|
||||
- What other files or systems does this change interact with?
|
||||
- Could this break anything else?
|
||||
- Is there additional work needed beyond this PR to complete the feature?
|
||||
- Does this fit well with the overall architecture?
|
||||
|
||||
Step 5: Find reference implementations
|
||||
Look for similar changes in the codebase:
|
||||
```bash
|
||||
git log --oneline --all --grep="<relevant keywords>" | head -20
|
||||
git log --oneline -- <similar files> | head -20
|
||||
```
|
||||
|
||||
If this is adding a new API provider, look at how other providers are implemented.
|
||||
If this is adding a new feature, look at how similar features were added.
|
||||
Note where their implementation aligns with or diverges from established patterns.
|
||||
|
||||
Step 6: Standard code review checks
|
||||
- DRY: Is there duplicated code that could be extracted?
|
||||
- Error handling: Are errors handled appropriately?
|
||||
- Security: Any injection risks, credential exposure, unsafe dependencies?
|
||||
- Performance: Any obvious inefficiencies, memory leaks, N+1 patterns?
|
||||
- Types: Is TypeScript used correctly? Any unsafe type assertions?
|
||||
- Naming: Are variables and functions named clearly?
|
||||
- Comments: Is complex logic explained? Are there outdated comments?
|
||||
|
||||
## Inline code suggestions
|
||||
|
||||
For specific code improvements, use GitHub's suggestion syntax via `gh api`.
|
||||
This creates suggestions the author can commit with one click.
|
||||
|
||||
Single-line suggestion:
|
||||
```bash
|
||||
gh api repos/${{ github.repository }}/pulls/${{ steps.pr.outputs.number }}/reviews \
|
||||
-X POST \
|
||||
-f commit_id="$(gh pr view ${{ steps.pr.outputs.number }} --json headRefOid -q .headRefOid)" \
|
||||
-f event="COMMENT" \
|
||||
-f body="" \
|
||||
-F comments='[
|
||||
{
|
||||
"path": "src/example.ts",
|
||||
"line": 42,
|
||||
"body": "Consider simplifying:\n\n```suggestion\nconst result = items.filter(Boolean);\n```"
|
||||
}
|
||||
]'
|
||||
```
|
||||
|
||||
Multi-line suggestion (replacing lines 40-45):
|
||||
```bash
|
||||
gh api repos/${{ github.repository }}/pulls/${{ steps.pr.outputs.number }}/reviews \
|
||||
-X POST \
|
||||
-f commit_id="$(gh pr view ${{ steps.pr.outputs.number }} --json headRefOid -q .headRefOid)" \
|
||||
-f event="COMMENT" \
|
||||
-f body="" \
|
||||
-F comments='[
|
||||
{
|
||||
"path": "src/example.ts",
|
||||
"start_line": 40,
|
||||
"line": 45,
|
||||
"body": "This can be simplified:\n\n```suggestion\nconst simplified = doThing();\n```"
|
||||
}
|
||||
]'
|
||||
```
|
||||
|
||||
Use inline suggestions for concrete improvements. Use regular comments for questions or broader feedback.
|
||||
|
||||
## Post your review
|
||||
|
||||
After your investigation, post a single helpful comment that helps the author and gives maintainers context.
|
||||
|
||||
Start with a warm thank you for their contribution. Be conversational, not robotic.
|
||||
|
||||
Include what's relevant:
|
||||
- In-depth explanation of what the PR does - Be comprehensive. A maintainer should be able to read this section and fully understand the author's intent, why they made the changes, how they implemented it, and what files/systems are affected. Don't just summarize - explain.
|
||||
- Related issues/PRs you found that provide useful context (link to them)
|
||||
- Your review findings (issues to address, suggestions, etc.)
|
||||
- Clear next steps for the author
|
||||
|
||||
Include a "For Maintainers" section with:
|
||||
- Anything else useful to help the maintainer resolve this PR
|
||||
- Related issues/PRs with context on why they're relevant
|
||||
- Open issues this PR might fix that weren't linked in the description
|
||||
- Your recommendation: merge as-is, needs changes, needs discussion, close, etc.
|
||||
- SME table - who should review this and why
|
||||
|
||||
For the SME table:
|
||||
| SME | Reason |
|
||||
|-----|--------|
|
||||
| @username | Primary contributor to affected files |
|
||||
|
||||
## Update labels
|
||||
|
||||
Add appropriate labels based on your analysis:
|
||||
```bash
|
||||
gh label list --json name,description --limit 100
|
||||
gh pr edit ${{ steps.pr.outputs.number }} --add-label "label1,label2"
|
||||
```
|
||||
|
||||
When done, add the reviewed label:
|
||||
```bash
|
||||
gh pr edit ${{ steps.pr.outputs.number }} --add-label "Bot Reviewed"
|
||||
```
|
||||
|
||||
## Remember
|
||||
|
||||
- This is a one-time automated response - you will NOT see their reply or respond again. Never say things like "let me know if you have questions", "I can help you with", or "feel free to ask" - you won't be there to follow up. Frame any questions for the maintainers who will follow up.
|
||||
- Be helpful and welcoming - Many contributors are new to the project
|
||||
- Be specific - Point to exact lines and suggest fixes, don't give vague feedback
|
||||
- Think deeply - Don't just surface-level review, understand the intent and evaluate the approach
|
||||
- Use inline suggestions - Make it easy for authors to accept changes
|
||||
- You're a first-pass reviewer - A human maintainer will do final approval
|
||||
@@ -36,8 +36,6 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.inputs.tag }}
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
@@ -118,31 +116,22 @@ jobs:
|
||||
echo "Successfully published release version ${{ steps.get_version.outputs.version }} to VS Code Marketplace and Open VSX Registry"
|
||||
fi
|
||||
|
||||
- name: Get Previous Tag
|
||||
id: prev_tag
|
||||
run: |
|
||||
CURRENT_TAG="${{ steps.validate_tag.outputs.tag }}"
|
||||
PREV_TAG=$(git describe --tags --abbrev=0 "$CURRENT_TAG^" 2>/dev/null || echo "")
|
||||
echo "prev_tag=$PREV_TAG" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get Changelog Entry
|
||||
id: changelog
|
||||
run: |
|
||||
# Get content between first ## [ and second ## [
|
||||
CONTENT=$(awk '/^## \[/{if(found) exit; found=1; next} found{print}' CHANGELOG.md)
|
||||
echo "content<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$CONTENT" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
# - name: Get Changelog Entry
|
||||
# id: changelog
|
||||
# uses: mindsers/changelog-reader-action@v2
|
||||
# with:
|
||||
# # This expects a standard Keep a Changelog format
|
||||
# # "latest" means it will read whichever is the most recent version
|
||||
# # set in "## [1.2.3] - 2025-01-28" style
|
||||
# version: latest
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: ${{ steps.validate_tag.outputs.tag }}
|
||||
files: "*.vsix"
|
||||
body: |
|
||||
${{ steps.changelog.outputs.content }}
|
||||
|
||||
**Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ steps.prev_tag.outputs.prev_tag }}...${{ steps.validate_tag.outputs.tag }}
|
||||
# body: ${{ steps.changelog.outputs.content }}
|
||||
generate_release_notes: true
|
||||
prerelease: ${{ github.event.inputs.release-type == 'pre-release' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -8,14 +8,12 @@ tmp
|
||||
|
||||
.DS_Store
|
||||
.idea
|
||||
.husky/_/
|
||||
|
||||
pnpm-lock.yaml
|
||||
|
||||
.clineignore
|
||||
.venv
|
||||
.actrc
|
||||
CLAUDE.local.md
|
||||
|
||||
webview-ui/src/**/*.js
|
||||
webview-ui/src/**/*.js.map
|
||||
@@ -30,8 +28,6 @@ coverage-unit
|
||||
*evals.env
|
||||
.env
|
||||
|
||||
.worktrees
|
||||
|
||||
## Generated files ##
|
||||
src/generated/
|
||||
src/shared/proto/
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
.gitignore
|
||||
@@ -1,37 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## [3.46.1]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Remove GLM 4.6 from free models
|
||||
|
||||
|
||||
## [3.46.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Added GLM 4.7 model
|
||||
- Enhanced background terminal execution with command tracking, log file output, zombie process prevention (10-minute timeout), and clickable log paths in UI
|
||||
- Apply Patch tool for GPT-5+ models (replacing current diff edit tools)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Duplicate error messages during streaming for Diff Edit tool when Parallel Tool Calling is not enabled
|
||||
- Banner carousel styling and dismiss functionality
|
||||
- Typos in Gemini system prompt overrides
|
||||
- Model picker favorites ordering, star toggle, and keyboard navigation for OpenRouter and Vercel AI Gateway providers
|
||||
- Fetch remote config values from the cache
|
||||
|
||||
### Refactored
|
||||
|
||||
- Anthropic handler to use metadata for reasoning support
|
||||
- Bedrock provider to use metadata for reasoning support
|
||||
|
||||
## [3.45.1]
|
||||
|
||||
- Fixed MCP settings race condition where toggling auto-approve or changing timeout settings would cause the UI to flash and revert
|
||||
|
||||
## [3.45.0]
|
||||
|
||||
- Added Gemini 3 Flash Preview model
|
||||
|
||||
@@ -14,10 +14,6 @@ This file is the secret sauce for working effectively in this codebase. It captu
|
||||
|
||||
**What NOT to add:** Stuff you can figure out from reading a few files, obvious patterns, or standard practices. This file should be high-signal, not comprehensive.
|
||||
|
||||
## Miscellaneous
|
||||
- This is a VS Code extension—check `package.json` for available scripts before trying to verify builds (e.g., `npm run compile`, not `npm run build`).
|
||||
- When creating PRs, if the change is user-facing and significant enough to warrant a changelog entry, run `npm run changeset` and create a patch changeset. Never create minor or major version bumps. Skip changesets for trivial fixes, internal refactors, or minor UI tweaks that users wouldn't notice.
|
||||
|
||||
## gRPC/Protobuf Communication
|
||||
The extension and webview communicate via gRPC-like protocol over VS Code message passing.
|
||||
|
||||
|
||||
@@ -14,9 +14,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
port int
|
||||
verbose bool
|
||||
workspaces []string
|
||||
port int
|
||||
verbose bool
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -29,7 +28,6 @@ func main() {
|
||||
|
||||
rootCmd.Flags().IntVarP(&port, "port", "p", 51052, "port to listen on")
|
||||
rootCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "verbose logging")
|
||||
rootCmd.Flags().StringSliceVar(&workspaces, "workspace", nil, "workspace paths")
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
@@ -41,7 +39,7 @@ func runServer(cmd *cobra.Command, args []string) error {
|
||||
ctx := cmd.Context()
|
||||
|
||||
// Create gRPC hostbridge service
|
||||
service := hostbridge.NewGrpcServer(port, verbose, workspaces)
|
||||
service := hostbridge.NewGrpcServer(port, verbose)
|
||||
|
||||
// Handle graceful shutdown
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
||||
+24
-69
@@ -6,7 +6,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/huh"
|
||||
@@ -26,13 +25,12 @@ var (
|
||||
outputFormat string
|
||||
|
||||
// Task creation flags (for root command)
|
||||
images []string
|
||||
files []string
|
||||
mode string
|
||||
settings []string
|
||||
yolo bool
|
||||
oneshot bool
|
||||
workspaces []string
|
||||
images []string
|
||||
files []string
|
||||
mode string
|
||||
settings []string
|
||||
yolo bool
|
||||
oneshot bool
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -72,23 +70,12 @@ see the manual page: man cline`,
|
||||
|
||||
var instanceAddress string
|
||||
|
||||
// Validate workspace paths exist
|
||||
if err := common.ValidateDirsExist(workspaces); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Build the full workspace list: cwd first, then additional workspaces
|
||||
allWorkspaces, err := buildWorkspaceList(workspaces)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to build workspace list: %w", err)
|
||||
}
|
||||
|
||||
// If --address flag not provided, start instance BEFORE getting prompt
|
||||
if !cmd.Flags().Changed("address") {
|
||||
if global.Config.Verbose {
|
||||
fmt.Println("Starting new Cline instance...")
|
||||
}
|
||||
instance, err := global.Clients.StartNewInstance(ctx, allWorkspaces...)
|
||||
instance, err := global.Clients.StartNewInstance(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to start new instance: %w", err)
|
||||
}
|
||||
@@ -144,8 +131,8 @@ see the manual page: man cline`,
|
||||
|
||||
// If no prompt from args or stdin, show interactive input
|
||||
if prompt == "" {
|
||||
// Pass the mode flag and workspaces to banner so it shows correct info
|
||||
prompt, err = promptForInitialTask(ctx, instanceAddress, mode, allWorkspaces)
|
||||
// Pass the mode flag to banner so it shows correct mode
|
||||
prompt, err = promptForInitialTask(ctx, instanceAddress, mode)
|
||||
if err != nil {
|
||||
// Check if user cancelled - exit cleanly without error
|
||||
if err == huh.ErrUserAborted {
|
||||
@@ -165,14 +152,13 @@ see the manual page: man cline`,
|
||||
}
|
||||
|
||||
return cli.CreateAndFollowTask(ctx, prompt, cli.TaskOptions{
|
||||
Images: images,
|
||||
Files: files,
|
||||
Mode: mode,
|
||||
Settings: settings,
|
||||
Yolo: yolo,
|
||||
Address: instanceAddress,
|
||||
Verbose: verbose,
|
||||
Workspaces: allWorkspaces,
|
||||
Images: images,
|
||||
Files: files,
|
||||
Mode: mode,
|
||||
Settings: settings,
|
||||
Yolo: yolo,
|
||||
Address: instanceAddress,
|
||||
Verbose: verbose,
|
||||
})
|
||||
},
|
||||
}
|
||||
@@ -189,7 +175,6 @@ see the manual page: man cline`,
|
||||
rootCmd.Flags().BoolVarP(&yolo, "yolo", "y", false, "enable yolo mode (non-interactive)")
|
||||
rootCmd.Flags().BoolVar(&yolo, "no-interactive", false, "enable yolo mode (non-interactive)")
|
||||
rootCmd.Flags().BoolVarP(&oneshot, "oneshot", "o", false, "full autonomous mode")
|
||||
rootCmd.Flags().StringSliceVarP(&workspaces, "workspace", "w", nil, "additional workspace paths (can be specified multiple times)")
|
||||
|
||||
rootCmd.AddCommand(cli.NewTaskCommand())
|
||||
rootCmd.AddCommand(cli.NewInstanceCommand())
|
||||
@@ -204,9 +189,9 @@ see the manual page: man cline`,
|
||||
}
|
||||
}
|
||||
|
||||
func promptForInitialTask(ctx context.Context, instanceAddress, modeFlag string, workspaces []string) (string, error) {
|
||||
func promptForInitialTask(ctx context.Context, instanceAddress, modeFlag string) (string, error) {
|
||||
// Show session banner before the initial input
|
||||
showSessionBanner(ctx, instanceAddress, modeFlag, workspaces)
|
||||
showSessionBanner(ctx, instanceAddress, modeFlag)
|
||||
|
||||
var prompt string
|
||||
|
||||
@@ -248,7 +233,7 @@ func promptForInitialTask(ctx context.Context, instanceAddress, modeFlag string,
|
||||
}
|
||||
|
||||
// showSessionBanner displays session info before initial prompt
|
||||
func showSessionBanner(ctx context.Context, instanceAddress, modeFlag string, workspaces []string) {
|
||||
func showSessionBanner(ctx context.Context, instanceAddress, modeFlag string) {
|
||||
bannerInfo := display.BannerInfo{
|
||||
Version: global.CliVersion,
|
||||
Mode: modeFlag, // Use the mode from command flag, not state
|
||||
@@ -259,7 +244,10 @@ func showSessionBanner(ctx context.Context, instanceAddress, modeFlag string, wo
|
||||
bannerInfo.Mode = "plan"
|
||||
}
|
||||
|
||||
bannerInfo.Workdirs = workspaces
|
||||
// Get current working directory (this is what Cline will use)
|
||||
if cwd, err := os.Getwd(); err == nil {
|
||||
bannerInfo.Workdir = cwd
|
||||
}
|
||||
|
||||
// Get provider/model using auth functions (same logic as auth menu)
|
||||
manager, err := cli.NewTaskManagerForAddress(ctx, instanceAddress)
|
||||
@@ -357,37 +345,4 @@ func getContentFromStdinAndArgs(args []string) (string, error) {
|
||||
}
|
||||
|
||||
return content.String(), nil
|
||||
}
|
||||
|
||||
// buildWorkspaceList builds the full workspace list with cwd as the first entry
|
||||
func buildWorkspaceList(additionalWorkspaces []string) ([]string, error) {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get current working directory: %w", err)
|
||||
}
|
||||
|
||||
// Start with cwd
|
||||
workspaces := []string{cwd}
|
||||
|
||||
// Add additional workspaces, avoiding duplicates
|
||||
for _, ws := range additionalWorkspaces {
|
||||
// Normalize the path
|
||||
absPath, err := common.AbsPath(ws)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to resolve workspace path %s: %w", ws, err)
|
||||
}
|
||||
|
||||
// Skip if it's the same as cwd
|
||||
if absPath == cwd {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check for duplicates
|
||||
isDuplicate := slices.Contains(workspaces, absPath)
|
||||
if !isDuplicate {
|
||||
workspaces = append(workspaces, absPath)
|
||||
}
|
||||
}
|
||||
|
||||
return workspaces, nil
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
module github.com/cline/cli
|
||||
|
||||
go 1.24.0
|
||||
go 1.23.0
|
||||
|
||||
require (
|
||||
github.com/atotto/clipboard v0.1.4
|
||||
|
||||
@@ -70,10 +70,6 @@ When using the instant task syntax **cline "prompt"** the following options are
|
||||
|
||||
: Starting mode. Options: **act** (default), **plan**
|
||||
|
||||
**-w**, **\--workspace** *path*
|
||||
|
||||
: Additional workspace paths. Can be specified multiple times to include multiple directories. The current working directory is always included as the first workspace. Example: cline -w /path/to/other/project "refactor shared code"
|
||||
|
||||
# GLOBAL OPTIONS
|
||||
|
||||
These options apply to all subcommands:
|
||||
|
||||
@@ -47,7 +47,7 @@ func GetProviderConfigurations(ctx context.Context, manager *task.Manager) (*Pro
|
||||
}
|
||||
|
||||
// Parse state_json as map[string]interface{}
|
||||
var stateData map[string]any
|
||||
var stateData map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(stateJSON), &stateData); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse state JSON: %w", err)
|
||||
}
|
||||
@@ -57,7 +57,7 @@ func GetProviderConfigurations(ctx context.Context, manager *task.Manager) (*Pro
|
||||
}
|
||||
|
||||
// Extract apiConfiguration object from state
|
||||
apiConfig, ok := stateData["apiConfiguration"].(map[string]any)
|
||||
apiConfig, ok := stateData["apiConfiguration"].(map[string]interface{})
|
||||
if !ok {
|
||||
if global.Config.Verbose {
|
||||
fmt.Println("[DEBUG] No apiConfiguration found in state")
|
||||
@@ -128,11 +128,11 @@ func (r *ProviderListResult) GetAllReadyProviders() []*ProviderDisplay {
|
||||
modelID := getProviderSpecificModelID(r.apiConfig, "plan", provider)
|
||||
|
||||
// Determine if credentials exist
|
||||
hasCreds := checkCredentialsExists(r.apiConfig, provider)
|
||||
hasCreds := checkAPIKeyExists(r.apiConfig, provider)
|
||||
|
||||
// Determine readiness: OCA uses auth state presence; others need creds and model
|
||||
if provider == cline.ApiProvider_OCA {
|
||||
state, _ := GetLatestOCAState(context.Background(), 2*time.Second)
|
||||
state, _ := GetLatestOCAState(context.Background(), 2 *time.Second)
|
||||
if state == nil || state.User == nil {
|
||||
continue
|
||||
}
|
||||
@@ -156,7 +156,7 @@ func (r *ProviderListResult) GetAllReadyProviders() []*ProviderDisplay {
|
||||
Mode: "Ready",
|
||||
Provider: provider,
|
||||
ModelID: modelID,
|
||||
HasAPIKey: checkCredentialsExists(r.apiConfig, provider),
|
||||
HasAPIKey: checkAPIKeyExists(r.apiConfig, provider),
|
||||
BaseURL: baseURL,
|
||||
})
|
||||
seenProviders[provider] = true
|
||||
@@ -192,7 +192,7 @@ func extractProviderFromState(stateData map[string]interface{}, mode string) *Pr
|
||||
modelID := getProviderSpecificModelID(stateData, mode, provider)
|
||||
|
||||
// Check if API key exists
|
||||
hasCredentials := checkCredentialsExists(stateData, provider)
|
||||
hasAPIKey := checkAPIKeyExists(stateData, provider)
|
||||
|
||||
// Get base URL for Ollama (can be shown publicly)
|
||||
baseURL := ""
|
||||
@@ -206,7 +206,7 @@ func extractProviderFromState(stateData map[string]interface{}, mode string) *Pr
|
||||
Mode: capitalizeMode(mode),
|
||||
Provider: provider,
|
||||
ModelID: modelID,
|
||||
HasAPIKey: hasCredentials,
|
||||
HasAPIKey: hasAPIKey,
|
||||
BaseURL: baseURL,
|
||||
}
|
||||
}
|
||||
@@ -215,7 +215,7 @@ func extractProviderFromState(stateData map[string]interface{}, mode string) *Pr
|
||||
// Returns (provider, ok) where ok is false if the provider is unknown
|
||||
func mapProviderStringToEnum(providerStr string) (cline.ApiProvider, bool) {
|
||||
normalizedStr := strings.ToLower(providerStr)
|
||||
|
||||
|
||||
// Map string values to enum values
|
||||
switch normalizedStr {
|
||||
case "anthropic":
|
||||
@@ -303,23 +303,19 @@ func getProviderSpecificModelID(stateData map[string]interface{}, mode string, p
|
||||
return modelID
|
||||
}
|
||||
|
||||
// checkCredentialsExists checks if API key field exists in state (never retrieve actual key)
|
||||
func checkCredentialsExists(stateData map[string]interface{}, provider cline.ApiProvider) bool {
|
||||
// checkAPIKeyExists checks if API key field exists in state (never retrieve actual key)
|
||||
func checkAPIKeyExists(stateData map[string]interface{}, provider cline.ApiProvider) bool {
|
||||
// Get field mapping from centralized function
|
||||
fields, err := GetProviderFields(provider)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if the key exists and is not empty
|
||||
if value, ok := stateData[fields.APIKeyField]; ok {
|
||||
if str, ok := value.(string); ok && str != "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
keyField := fields.APIKeyField
|
||||
|
||||
if value, ok := stateData[fields.UseProfileField]; ok {
|
||||
if hasProfileField, ok := value.(bool); ok && hasProfileField {
|
||||
// Check if the key exists and is not empty
|
||||
if value, ok := stateData[keyField]; ok {
|
||||
if str, ok := value.(string); ok && str != "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -442,13 +438,13 @@ func DetectAllConfiguredProviders(ctx context.Context, manager *task.Manager) ([
|
||||
stateJSON := state.StateJson
|
||||
|
||||
// Parse state_json as map[string]interface{}
|
||||
var stateData map[string]any
|
||||
var stateData map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(stateJSON), &stateData); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse state JSON: %w", err)
|
||||
}
|
||||
|
||||
// Extract apiConfiguration object from state
|
||||
apiConfig, ok := stateData["apiConfiguration"].(map[string]any)
|
||||
apiConfig, ok := stateData["apiConfiguration"].(map[string]interface{})
|
||||
if !ok {
|
||||
verboseLog("[DEBUG] No apiConfiguration found in state")
|
||||
verboseLog("[DEBUG] Available keys in stateData: %v", getMapKeys(stateData))
|
||||
@@ -473,38 +469,36 @@ func DetectAllConfiguredProviders(ctx context.Context, manager *task.Manager) ([
|
||||
|
||||
// Check each BYO provider for API key presence
|
||||
providersToCheck := []struct {
|
||||
provider cline.ApiProvider
|
||||
keyFields []string
|
||||
provider cline.ApiProvider
|
||||
keyField string
|
||||
}{
|
||||
{cline.ApiProvider_ANTHROPIC, []string{"apiKey"}},
|
||||
{cline.ApiProvider_OPENAI, []string{"openAiApiKey"}},
|
||||
{cline.ApiProvider_OPENAI_NATIVE, []string{"openAiNativeApiKey"}},
|
||||
{cline.ApiProvider_OPENROUTER, []string{"openRouterApiKey"}},
|
||||
{cline.ApiProvider_XAI, []string{"xaiApiKey"}},
|
||||
{cline.ApiProvider_BEDROCK, []string{"awsAccessKey", "awsUseProfile"}},
|
||||
{cline.ApiProvider_GEMINI, []string{"geminiApiKey"}},
|
||||
{cline.ApiProvider_OLLAMA, []string{"ollamaBaseUrl"}}, // Ollama uses baseUrl instead of API key
|
||||
{cline.ApiProvider_CEREBRAS, []string{"cerebrasApiKey"}},
|
||||
{cline.ApiProvider_HICAP, []string{"hicapApiKey"}},
|
||||
{cline.ApiProvider_NOUSRESEARCH, []string{"nousResearchApiKey"}},
|
||||
{cline.ApiProvider_ANTHROPIC, "apiKey"},
|
||||
{cline.ApiProvider_OPENAI, "openAiApiKey"},
|
||||
{cline.ApiProvider_OPENAI_NATIVE, "openAiNativeApiKey"},
|
||||
{cline.ApiProvider_OPENROUTER, "openRouterApiKey"},
|
||||
{cline.ApiProvider_XAI, "xaiApiKey"},
|
||||
{cline.ApiProvider_BEDROCK, "awsAccessKey"},
|
||||
{cline.ApiProvider_GEMINI, "geminiApiKey"},
|
||||
{cline.ApiProvider_OLLAMA, "ollamaBaseUrl"}, // Ollama uses baseUrl instead of API key
|
||||
{cline.ApiProvider_CEREBRAS, "cerebrasApiKey"},
|
||||
{cline.ApiProvider_HICAP, "hicapApiKey"},
|
||||
{cline.ApiProvider_NOUSRESEARCH, "nousResearchApiKey"},
|
||||
}
|
||||
|
||||
for _, providerCheck := range providersToCheck {
|
||||
verboseLog("[DEBUG] Checking for %s key: %s", GetProviderDisplayName(providerCheck.provider), providerCheck.keyFields)
|
||||
for _, keyField := range providerCheck.keyFields {
|
||||
if value, ok := apiConfig[keyField]; ok {
|
||||
verboseLog("[DEBUG] Found key, value type: %T, is empty: %v", value, value == "")
|
||||
if str, ok := value.(string); ok && str != "" {
|
||||
configuredProviders = append(configuredProviders, providerCheck.provider)
|
||||
verboseLog("[DEBUG] ✓ Provider %s is configured", GetProviderDisplayName(providerCheck.provider))
|
||||
break
|
||||
}
|
||||
} else {
|
||||
verboseLog("[DEBUG] Key %s not found", keyField)
|
||||
verboseLog("[DEBUG] Checking for %s key: %s", GetProviderDisplayName(providerCheck.provider), providerCheck.keyField)
|
||||
if value, ok := apiConfig[providerCheck.keyField]; ok {
|
||||
verboseLog("[DEBUG] Found key, value type: %T, is empty: %v", value, value == "")
|
||||
if str, ok := value.(string); ok && str != "" {
|
||||
configuredProviders = append(configuredProviders, providerCheck.provider)
|
||||
verboseLog("[DEBUG] ✓ Provider %s is configured", GetProviderDisplayName(providerCheck.provider))
|
||||
}
|
||||
} else {
|
||||
verboseLog("[DEBUG] Key %s not found", providerCheck.keyField)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
verboseLog("[DEBUG] Total configured providers: %d", len(configuredProviders))
|
||||
for _, p := range configuredProviders {
|
||||
verboseLog("[DEBUG] - %s", GetProviderDisplayName(p))
|
||||
|
||||
@@ -54,7 +54,6 @@ type ProviderFields struct {
|
||||
// Provider-specific additional model ID fields
|
||||
PlanModeProviderSpecificModelIDField string // e.g., "planModeOpenRouterModelId"
|
||||
ActModeProviderSpecificModelIDField string // e.g., "actModeOpenRouterModelId"
|
||||
UseProfileField string // e.g., "awsUseProfile" (for bedrock) (optional, empty if not applicable)
|
||||
}
|
||||
|
||||
// GetProviderFields returns the field mapping for a given provider
|
||||
@@ -97,7 +96,6 @@ func GetProviderFields(provider cline.ApiProvider) (ProviderFields, error) {
|
||||
|
||||
case cline.ApiProvider_BEDROCK:
|
||||
return ProviderFields{
|
||||
UseProfileField: "awsUseProfile",
|
||||
APIKeyField: "awsAccessKey",
|
||||
PlanModeModelIDField: "planModeApiModelId",
|
||||
ActModeModelIDField: "actModeApiModelId",
|
||||
|
||||
@@ -15,23 +15,23 @@ import (
|
||||
// BedrockConfig holds all AWS Bedrock-specific configuration fields
|
||||
type BedrockConfig struct {
|
||||
// Profile authentication fields
|
||||
UseProfile bool // Always true for successful config
|
||||
Profile string // Optional: AWS profile name (empty = default)
|
||||
Region string // Required: AWS region
|
||||
Endpoint string // Optional: Custom VPC endpoint URL
|
||||
|
||||
UseProfile bool // Always true for successful config
|
||||
Profile string // Optional: AWS profile name (empty = default)
|
||||
Region string // Required: AWS region
|
||||
Endpoint string // Optional: Custom VPC endpoint URL
|
||||
|
||||
// Optional features
|
||||
UseCrossRegionInference bool // Optional: Enable cross-region inference
|
||||
UseGlobalInference bool // Optional: Use global inference endpoint
|
||||
UsePromptCache bool // Optional: Enable prompt caching
|
||||
|
||||
UseCrossRegionInference bool // Optional: Enable cross-region inference
|
||||
UseGlobalInference bool // Optional: Use global inference endpoint
|
||||
UsePromptCache bool // Optional: Enable prompt caching
|
||||
|
||||
// Authentication method (always "profile")
|
||||
Authentication string // Always set to "profile"
|
||||
|
||||
Authentication string // Always set to "profile"
|
||||
|
||||
// Legacy fields (no longer used in profile-only flow)
|
||||
AccessKey string // No longer used
|
||||
SecretKey string // No longer used
|
||||
SessionToken string // No longer used
|
||||
AccessKey string // No longer used
|
||||
SecretKey string // No longer used
|
||||
SessionToken string // No longer used
|
||||
}
|
||||
|
||||
// PromptForBedrockConfig displays a profile-first authentication form for Bedrock configuration
|
||||
@@ -130,12 +130,7 @@ func ApplyBedrockConfig(ctx context.Context, manager *task.Manager, config *Bedr
|
||||
// Build the API configuration with all Bedrock fields
|
||||
apiConfig := &cline.ModelsApiConfiguration{}
|
||||
|
||||
// Set provider for both Plan and Act modes
|
||||
bedrockProvider := cline.ApiProvider_BEDROCK
|
||||
apiConfig.PlanModeApiProvider = &bedrockProvider
|
||||
apiConfig.ActModeApiProvider = &bedrockProvider
|
||||
|
||||
// Set model ID field - this is the primary model ID used by Cline Core
|
||||
// Set model ID fields
|
||||
apiConfig.PlanModeApiModelId = proto.String(modelID)
|
||||
apiConfig.ActModeApiModelId = proto.String(modelID)
|
||||
apiConfig.PlanModeAwsBedrockCustomModelBaseId = proto.String(modelID)
|
||||
@@ -171,8 +166,6 @@ func ApplyBedrockConfig(ctx context.Context, manager *task.Manager, config *Bedr
|
||||
|
||||
// Build field mask including all fields we're setting (excluding access keys)
|
||||
fieldPaths := []string{
|
||||
"planModeApiProvider",
|
||||
"actModeApiProvider",
|
||||
"planModeApiModelId",
|
||||
"actModeApiModelId",
|
||||
"planModeAwsBedrockCustomModelBaseId",
|
||||
|
||||
+130
-18
@@ -1,19 +1,22 @@
|
||||
package display
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/cline/cli/pkg/common"
|
||||
)
|
||||
|
||||
// BannerInfo contains information to display in the session banner
|
||||
type BannerInfo struct {
|
||||
Version string
|
||||
Provider string
|
||||
ModelID string
|
||||
Workdirs []string // workspace directories
|
||||
Mode string
|
||||
Version string
|
||||
Provider string
|
||||
ModelID string
|
||||
Workdir string
|
||||
Mode string
|
||||
}
|
||||
|
||||
// RenderSessionBanner renders a nice banner showing version, model, and workspace info
|
||||
@@ -78,22 +81,131 @@ func RenderSessionBanner(info BannerInfo) string {
|
||||
|
||||
// Model line - dim gray
|
||||
if info.Provider != "" && info.ModelID != "" {
|
||||
lines = append(lines, dimStyle.Render(info.Provider+"/"+common.ShortenPath(info.ModelID, 30)))
|
||||
lines = append(lines, dimStyle.Render(info.Provider+"/"+shortenPath(info.ModelID, 30)))
|
||||
}
|
||||
|
||||
for _, wd := range info.Workdirs {
|
||||
lines = append(lines, dimStyle.Render(common.ShortenPath(wd, 45)))
|
||||
}
|
||||
|
||||
// Checkpoint warning for multi-root workspaces
|
||||
if len(info.Workdirs) > 1 {
|
||||
warningStyle := lipgloss.NewStyle().
|
||||
Foreground(lipgloss.Color("3")). // Yellow warning color
|
||||
Italic(true)
|
||||
lines = append(lines, "")
|
||||
lines = append(lines, warningStyle.Render("⚠ Checkpoints disabled for multi-root workspaces"))
|
||||
// Workspace line - dim gray
|
||||
if info.Workdir != "" {
|
||||
lines = append(lines, dimStyle.Render(shortenPath(info.Workdir, 45)))
|
||||
}
|
||||
|
||||
content := lipgloss.JoinVertical(lipgloss.Left, lines...)
|
||||
return boxStyle.Render(content)
|
||||
}
|
||||
|
||||
// shortenPath shortens a filesystem path to fit within maxLen
|
||||
func shortenPath(path string, maxLen int) string {
|
||||
// Try to replace home directory with ~ (cross-platform)
|
||||
if homeDir, err := os.UserHomeDir(); err == nil {
|
||||
if strings.HasPrefix(path, homeDir) {
|
||||
shortened := "~" + path[len(homeDir):]
|
||||
// Always use ~ version if we can
|
||||
path = shortened
|
||||
}
|
||||
}
|
||||
|
||||
if len(path) <= maxLen {
|
||||
return path
|
||||
}
|
||||
|
||||
// If still too long, show last few path components
|
||||
if len(path) > maxLen {
|
||||
parts := strings.Split(path, string(filepath.Separator))
|
||||
if len(parts) > 2 {
|
||||
// Show last 2-3 components
|
||||
lastParts := parts[len(parts)-2:]
|
||||
shortened := "..." + string(filepath.Separator) + strings.Join(lastParts, string(filepath.Separator))
|
||||
if len(shortened) <= maxLen {
|
||||
return shortened
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Last resort: truncate with ellipsis
|
||||
if len(path) > maxLen {
|
||||
return "..." + path[len(path)-maxLen+3:]
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
// ExtractBannerInfoFromState extracts banner info from state JSON
|
||||
func ExtractBannerInfoFromState(stateJSON, version string) (BannerInfo, error) {
|
||||
var state map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(stateJSON), &state); err != nil {
|
||||
return BannerInfo{}, fmt.Errorf("failed to parse state JSON: %w", err)
|
||||
}
|
||||
|
||||
info := BannerInfo{
|
||||
Version: version,
|
||||
}
|
||||
|
||||
// Extract mode
|
||||
if mode, ok := state["mode"].(string); ok {
|
||||
info.Mode = mode
|
||||
}
|
||||
|
||||
// Extract workspace roots
|
||||
if workspaceRoots, ok := state["workspaceRoots"].([]interface{}); ok && len(workspaceRoots) > 0 {
|
||||
if root, ok := workspaceRoots[0].(map[string]interface{}); ok {
|
||||
if path, ok := root["path"].(string); ok {
|
||||
info.Workdir = path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract API configuration to get provider/model
|
||||
if apiConfig, ok := state["apiConfiguration"].(map[string]interface{}); ok {
|
||||
// Try common keys for provider and model (both camelCase and lowercase variants)
|
||||
providerKeys := []string{"apiProvider", "api_provider"}
|
||||
modelKeys := []string{"apiModelId", "api_model_id"}
|
||||
|
||||
// Try to extract provider
|
||||
for _, key := range providerKeys {
|
||||
if provider, ok := apiConfig[key].(string); ok && provider != "" {
|
||||
info.Provider = provider
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Try to extract model ID
|
||||
for _, key := range modelKeys {
|
||||
if modelID, ok := apiConfig[key].(string); ok && modelID != "" {
|
||||
info.ModelID = shortenModelID(modelID)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// shortenModelID shortens long model IDs for display
|
||||
func shortenModelID(modelID string) string {
|
||||
// Remove date suffixes only if they're at the end (e.g., -20241022)
|
||||
// Check if the model ID ends with -YYYYMMDD pattern
|
||||
if len(modelID) > 9 {
|
||||
suffix := modelID[len(modelID)-9:] // Last 9 chars: -20241022
|
||||
if suffix[0] == '-' &&
|
||||
(strings.HasPrefix(suffix[1:], "202") || strings.HasPrefix(suffix[1:], "201")) {
|
||||
// Verify all remaining chars are digits
|
||||
allDigits := true
|
||||
for _, c := range suffix[1:] {
|
||||
if c < '0' || c > '9' {
|
||||
allDigits = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if allDigits {
|
||||
return modelID[:len(modelID)-9]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If still too long, show first 40 chars
|
||||
if len(modelID) > 40 {
|
||||
return modelID[:37] + "..."
|
||||
}
|
||||
|
||||
return modelID
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func (c *ClineClients) Initialize(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// StartNewInstance starts a new Cline instance and waits for cline-core to self-register
|
||||
func (c *ClineClients) StartNewInstance(ctx context.Context, workspaces ...string) (*common.CoreInstanceInfo, error) {
|
||||
func (c *ClineClients) StartNewInstance(ctx context.Context) (*common.CoreInstanceInfo, error) {
|
||||
// Find available ports
|
||||
corePort, hostPort, err := common.FindAvailablePortPair()
|
||||
if err != nil {
|
||||
@@ -48,7 +48,7 @@ func (c *ClineClients) StartNewInstance(ctx context.Context, workspaces ...strin
|
||||
}
|
||||
|
||||
// Start cline-host first
|
||||
hostCmd, err := startClineHost(hostPort, workspaces)
|
||||
hostCmd, err := startClineHost(hostPort, corePort)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to start cline-host: %w", err)
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func (c *ClineClients) StartNewInstance(ctx context.Context, workspaces ...strin
|
||||
}
|
||||
|
||||
// StartNewInstanceAtPort starts a new Cline instance at the specified port and waits for self-registration
|
||||
func (c *ClineClients) StartNewInstanceAtPort(ctx context.Context, corePort int, workspaces ...string) (*common.CoreInstanceInfo, error) {
|
||||
func (c *ClineClients) StartNewInstanceAtPort(ctx context.Context, corePort int) (*common.CoreInstanceInfo, error) {
|
||||
// Find available host port (core port + 1000)
|
||||
hostPort := corePort + 1000
|
||||
coreAddress := fmt.Sprintf("localhost:%d", corePort)
|
||||
@@ -135,7 +135,7 @@ func (c *ClineClients) StartNewInstanceAtPort(ctx context.Context, corePort int,
|
||||
}
|
||||
|
||||
// Start cline-host first
|
||||
hostCmd, err := startClineHost(hostPort, workspaces)
|
||||
hostCmd, err := startClineHost(hostPort, corePort)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to start cline-host: %w", err)
|
||||
}
|
||||
@@ -242,7 +242,7 @@ func (c *ClineClients) EnsureInstanceAtAddress(ctx context.Context, address stri
|
||||
return fmt.Errorf("cannot start remote instance at %s", normalized)
|
||||
}
|
||||
|
||||
func startClineHost(hostPort int, workspaces []string) (*exec.Cmd, error) {
|
||||
func startClineHost(hostPort, corePort int) (*exec.Cmd, error) {
|
||||
if Config.Verbose {
|
||||
fmt.Printf("Starting cline-host on port %d\n", hostPort)
|
||||
}
|
||||
@@ -255,18 +255,10 @@ func startClineHost(hostPort int, workspaces []string) (*exec.Cmd, error) {
|
||||
binDir := path.Dir(execPath)
|
||||
clineHostPath := path.Join(binDir, "cline-host")
|
||||
|
||||
// Build command arguments
|
||||
args := []string{
|
||||
"--verbose",
|
||||
"--port", fmt.Sprintf("%d", hostPort),
|
||||
}
|
||||
|
||||
for _, ws := range workspaces {
|
||||
args = append(args, "--workspace", ws)
|
||||
}
|
||||
|
||||
// Start the cline-host process
|
||||
cmd := exec.Command(clineHostPath, args...)
|
||||
cmd := exec.Command(clineHostPath,
|
||||
"--verbose",
|
||||
"--port", fmt.Sprintf("%d", hostPort))
|
||||
|
||||
// Create logs directory in ~/.cline/logs
|
||||
logsDir := path.Join(Config.ConfigPath, "logs")
|
||||
@@ -341,7 +333,7 @@ func KillInstanceByAddress(ctx context.Context, registry *ClientRegistry, addres
|
||||
if Config.Verbose {
|
||||
fmt.Printf("Waiting for instance to clean up registry entry...\n")
|
||||
}
|
||||
for range 5 {
|
||||
for i := 0; i < 5; i++ {
|
||||
time.Sleep(1 * time.Second)
|
||||
if !registry.HasInstanceAtAddress(address) {
|
||||
if Config.Verbose {
|
||||
@@ -416,15 +408,15 @@ func startClineCore(corePort, hostPort int) (*exec.Cmd, error) {
|
||||
// This handles the case where we're running from cli/bin/cline
|
||||
devClineCorePath := path.Join(binDir, "..", "..", "dist-standalone", "cline-core.js")
|
||||
devInstallDir := path.Join(binDir, "..", "..", "dist-standalone")
|
||||
|
||||
|
||||
if Config.Verbose {
|
||||
fmt.Printf("Primary location not found, trying development path: %s\n", devClineCorePath)
|
||||
}
|
||||
|
||||
|
||||
if _, err := os.Stat(devClineCorePath); os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("cline-core.js not found at '%s' or '%s'. Please ensure you're running from the correct location or reinstall with 'npm install -g cline'", clineCorePath, devClineCorePath)
|
||||
}
|
||||
|
||||
|
||||
finalClineCorePath = devClineCorePath
|
||||
finalInstallDir = devInstallDir
|
||||
if Config.Verbose {
|
||||
@@ -483,7 +475,7 @@ func startClineCore(corePort, hostPort int) (*exec.Cmd, error) {
|
||||
realNodeModules := path.Join(finalInstallDir, "node_modules")
|
||||
fakeNodeModules := path.Join(finalInstallDir, "fake_node_modules")
|
||||
nodePath := fmt.Sprintf("%s%c%s", realNodeModules, os.PathListSeparator, fakeNodeModules)
|
||||
|
||||
|
||||
env = append(env,
|
||||
fmt.Sprintf("NODE_PATH=%s", nodePath),
|
||||
// These control gRPC debug logging
|
||||
@@ -492,7 +484,7 @@ func startClineCore(corePort, hostPort int) (*exec.Cmd, error) {
|
||||
"NODE_ENV=development",
|
||||
)
|
||||
cmd.Env = env
|
||||
|
||||
|
||||
if Config.Verbose {
|
||||
fmt.Printf("NODE_PATH set to: %s\n", nodePath)
|
||||
}
|
||||
|
||||
+7
-8
@@ -20,14 +20,13 @@ import (
|
||||
|
||||
// TaskOptions contains options for creating a task
|
||||
type TaskOptions struct {
|
||||
Images []string
|
||||
Files []string
|
||||
Mode string
|
||||
Settings []string
|
||||
Yolo bool
|
||||
Address string
|
||||
Verbose bool
|
||||
Workspaces []string
|
||||
Images []string
|
||||
Files []string
|
||||
Mode string
|
||||
Settings []string
|
||||
Yolo bool
|
||||
Address string
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
func NewTaskCommand() *cobra.Command {
|
||||
|
||||
@@ -3,16 +3,15 @@ package types
|
||||
// HistoryItem represents a task history item from taskHistory.json
|
||||
// This struct matches the JSON format stored on disk
|
||||
type HistoryItem struct {
|
||||
Id string `json:"id"`
|
||||
Ulid string `json:"ulid,omitempty"`
|
||||
Ts int64 `json:"ts"`
|
||||
Task string `json:"task"`
|
||||
TokensIn int32 `json:"tokensIn"`
|
||||
TokensOut int32 `json:"tokensOut"`
|
||||
CacheWrites int32 `json:"cacheWrites,omitempty"`
|
||||
CacheReads int32 `json:"cacheReads,omitempty"`
|
||||
TotalCost float64 `json:"totalCost"`
|
||||
Size int64 `json:"size,omitempty"`
|
||||
IsFavorited bool `json:"isFavorited,omitempty"`
|
||||
WorkspacePaths []string `json:"workspacePaths,omitempty"`
|
||||
Id string `json:"id"`
|
||||
Ulid string `json:"ulid,omitempty"`
|
||||
Ts int64 `json:"ts"`
|
||||
Task string `json:"task"`
|
||||
TokensIn int32 `json:"tokensIn"`
|
||||
TokensOut int32 `json:"tokensOut"`
|
||||
CacheWrites int32 `json:"cacheWrites,omitempty"`
|
||||
CacheReads int32 `json:"cacheReads,omitempty"`
|
||||
TotalCost float64 `json:"totalCost"`
|
||||
Size int64 `json:"size,omitempty"`
|
||||
IsFavorited bool `json:"isFavorited,omitempty"`
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -185,72 +183,3 @@ DEBUGGING STEPS:
|
||||
For additional help, visit: https://github.com/cline/cline/issues
|
||||
`, maxRetries, lastErr, GetNodeVersion())
|
||||
}
|
||||
|
||||
// validateDirsExist validates that all workspace paths exist on the filesystem
|
||||
func ValidateDirsExist(paths []string) error {
|
||||
for _, p := range paths {
|
||||
info, err := os.Stat(p)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("path does not exist: %s", p)
|
||||
}
|
||||
return fmt.Errorf("failed to access path %s: %w", p, err)
|
||||
}
|
||||
if !info.IsDir() {
|
||||
return fmt.Errorf("path is not a directory: %s", p)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// absPath returns the absolute path, resolving symlinks
|
||||
func AbsPath(path string) (string, error) {
|
||||
// First get absolute path
|
||||
abs, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// Then resolve any symlinks
|
||||
resolved, err := filepath.EvalSymlinks(abs)
|
||||
if err != nil {
|
||||
// If symlink resolution fails, return the absolute path
|
||||
return abs, nil
|
||||
}
|
||||
return resolved, nil
|
||||
}
|
||||
|
||||
// shortenPath shortens a filesystem path to fit within maxLen
|
||||
func ShortenPath(path string, maxLen int) string {
|
||||
// Try to replace home directory with ~ (cross-platform)
|
||||
if homeDir, err := os.UserHomeDir(); err == nil {
|
||||
if strings.HasPrefix(path, homeDir) {
|
||||
shortened := "~" + path[len(homeDir):]
|
||||
// Always use ~ version if we can
|
||||
path = shortened
|
||||
}
|
||||
}
|
||||
|
||||
if len(path) <= maxLen {
|
||||
return path
|
||||
}
|
||||
|
||||
// If still too long, show last few path components
|
||||
if len(path) > maxLen {
|
||||
parts := strings.Split(path, string(filepath.Separator))
|
||||
if len(parts) > 2 {
|
||||
// Show last 2-3 components
|
||||
lastParts := parts[len(parts)-2:]
|
||||
shortened := "..." + string(filepath.Separator) + strings.Join(lastParts, string(filepath.Separator))
|
||||
if len(shortened) <= maxLen {
|
||||
return shortened
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Last resort: truncate with ellipsis
|
||||
if len(path) > maxLen {
|
||||
return "..." + path[len(path)-maxLen+3:]
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
@@ -16,17 +16,15 @@ import (
|
||||
type GrpcServer struct {
|
||||
port int
|
||||
verbose bool
|
||||
workspaces []string
|
||||
server *grpc.Server
|
||||
shutdownCh chan struct{}
|
||||
}
|
||||
|
||||
// NewGrpcServer creates a new GrpcServer
|
||||
func NewGrpcServer(port int, verbose bool, workspaces []string) *GrpcServer {
|
||||
func NewGrpcServer(port int, verbose bool) *GrpcServer {
|
||||
return &GrpcServer{
|
||||
port: port,
|
||||
verbose: verbose,
|
||||
workspaces: workspaces,
|
||||
shutdownCh: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
@@ -52,7 +50,7 @@ func (s *GrpcServer) Start(ctx context.Context) error {
|
||||
grpc_health_v1.RegisterHealthServer(s.server, healthServer)
|
||||
|
||||
// Register services
|
||||
workspaceService := NewSimpleWorkspaceService(s.verbose, s.workspaces)
|
||||
workspaceService := NewSimpleWorkspaceService(s.verbose)
|
||||
host.RegisterWorkspaceServiceServer(s.server, workspaceService)
|
||||
|
||||
windowService := NewWindowService(s.verbose)
|
||||
|
||||
@@ -12,15 +12,13 @@ import (
|
||||
// SimpleWorkspaceService implements a basic workspace service without complex dependencies
|
||||
type SimpleWorkspaceService struct {
|
||||
host.UnimplementedWorkspaceServiceServer
|
||||
verbose bool
|
||||
workspaces []string
|
||||
verbose bool
|
||||
}
|
||||
|
||||
// NewSimpleWorkspaceService creates a new SimpleWorkspaceService
|
||||
func NewSimpleWorkspaceService(verbose bool, workspaces []string) *SimpleWorkspaceService {
|
||||
func NewSimpleWorkspaceService(verbose bool) *SimpleWorkspaceService {
|
||||
return &SimpleWorkspaceService{
|
||||
verbose: verbose,
|
||||
workspaces: workspaces,
|
||||
verbose: verbose,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,24 +28,14 @@ func (s *SimpleWorkspaceService) GetWorkspacePaths(ctx context.Context, req *hos
|
||||
log.Printf("GetWorkspacePaths called")
|
||||
}
|
||||
|
||||
paths := []string{}
|
||||
|
||||
if len(s.workspaces) == 0 {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
paths = append(paths, cwd)
|
||||
} else {
|
||||
paths = s.workspaces
|
||||
}
|
||||
|
||||
if s.verbose {
|
||||
log.Printf("Returning configured workspaces: %v", paths)
|
||||
// Get current working directory as the workspace
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &host.GetWorkspacePathsResponse{
|
||||
Paths: paths,
|
||||
Paths: []string{cwd},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 96 KiB |
@@ -95,12 +95,6 @@ INSTANT TASK OPTIONS
|
||||
-m, --mode mode
|
||||
Starting mode. Options: act (default), plan
|
||||
|
||||
-w, --workspace path
|
||||
Additional workspace paths. Can be specified multiple times to
|
||||
include multiple directories. The current working directory is
|
||||
always included as the first workspace. Example: cline -w
|
||||
/path/to/other/project "refactor shared code"
|
||||
|
||||
GLOBAL OPTIONS
|
||||
These options apply to all subcommands:
|
||||
|
||||
|
||||
+1
-3
@@ -278,7 +278,6 @@
|
||||
"pages": [
|
||||
"enterprise-solutions/overview",
|
||||
"enterprise-solutions/onboarding",
|
||||
"enterprise-solutions/sso-setup",
|
||||
"enterprise-solutions/team-management/managing-members",
|
||||
{
|
||||
"group": "SaaS Provider Configuration",
|
||||
@@ -318,8 +317,7 @@
|
||||
"pages": [
|
||||
"enterprise-solutions/monitoring/overview",
|
||||
"enterprise-solutions/monitoring/telemetry",
|
||||
"enterprise-solutions/monitoring/opentelemetry",
|
||||
"enterprise-solutions/monitoring/opentelemetry_override"
|
||||
"enterprise-solutions/monitoring/opentelemetry"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ Check which models are available in your region first. Some newer models might n
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://assets.int.cline.bot/assets/AWS%20Remote%20Config.gif"
|
||||
src="https://storage.googleapis.com/cline-static-assets-prod/assets/AWS%20Remote%20Config.gif"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ If you don't have AWS credentials yet, reach out to your IT or cloud team to get
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://assets.int.cline.bot/assets/VS%20Code%20Bedrock%20API%20Key.gif"
|
||||
src="https://storage.googleapis.com/cline-static-assets-prod/assets/VS%20Code%20Bedrock%20API%20Key.gif"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
|
||||
@@ -42,45 +42,76 @@ Cline supports three OTLP export protocols:
|
||||
- **HTTP/protobuf**
|
||||
- **HTTP/JSON**
|
||||
|
||||
### Export Destinations
|
||||
|
||||
You can export to:
|
||||
- **Console** (for testing)
|
||||
- **OTLP endpoint** (your own collector or observability platform)
|
||||
|
||||
## Configuration
|
||||
|
||||
OpenTelemetry is configured using [Remote Configuration](/enterprise-solutions/configuration/remote-configuration/overview#how-remote-configuration-works) from the [dashboard](https://app.cline.bot/dashboard/organization?tab=settings).
|
||||
OpenTelemetry is configured using environment variables before launching Cline.
|
||||
|
||||
### Basic Setup
|
||||
|
||||
Enable OpenTelemetry, configure an OTLP endpoint and select a protocol:
|
||||
Enable OpenTelemetry and configure an OTLP endpoint:
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://assets.int.cline.bot/assets/open_telemetry_main_options.png"
|
||||
/>
|
||||
</Frame>
|
||||
```bash
|
||||
# Enable OpenTelemetry
|
||||
export OTEL_TELEMETRY_ENABLED=1
|
||||
|
||||
If you're using gRPC, you can opt out of TLS.
|
||||
# Configure metrics and logs export
|
||||
export OTEL_METRICS_EXPORTER=otlp
|
||||
export OTEL_LOGS_EXPORTER=otlp
|
||||
|
||||
Once the collector has been configured, you can enable logs and/or metrics collection. At least one of them needs to be enabled.
|
||||
# Set your OTLP endpoint
|
||||
export OTEL_EXPORTER_OTLP_ENDPOINT=https://your-collector:4317
|
||||
|
||||
You only need to configure it further if you need an advanced configuration.
|
||||
# Optional: Set protocol (default is grpc)
|
||||
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `OTEL_TELEMETRY_ENABLED` | Enable OpenTelemetry (`1` or `true`) | Disabled |
|
||||
| `OTEL_METRICS_EXPORTER` | Metrics exporter type (`console`, `otlp`, or both) | None |
|
||||
| `OTEL_LOGS_EXPORTER` | Logs exporter type (`console`, `otlp`, or both) | None |
|
||||
| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP endpoint URL | None |
|
||||
| `OTEL_EXPORTER_OTLP_PROTOCOL` | Protocol (`grpc`, `http/protobuf`, `http/json`) | `grpc` |
|
||||
| `OTEL_EXPORTER_OTLP_INSECURE` | Allow insecure connections | `false` |
|
||||
| `OTEL_EXPORTER_OTLP_HEADERS` | Custom headers (comma-separated `key=value` pairs) | None |
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
You can add custom protocols and endpoints for both, logs and metrics. You can also configure the metrics export interval, and the logs batch size, batch timeout and max queue size.
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://assets.int.cline.bot/assets/open_telemetry_metrics_and_logs.png"
|
||||
/>
|
||||
</Frame>
|
||||
**Separate endpoints for metrics and logs:**
|
||||
```bash
|
||||
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://metrics-collector:4317
|
||||
export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://logs-collector:4317
|
||||
```
|
||||
|
||||
**Custom headers for authentication:**
|
||||
```bash
|
||||
export OTEL_EXPORTER_OTLP_HEADERS="api-key=your-key,x-custom-header=value"
|
||||
```
|
||||
|
||||
Finally, if your collector needs authentication headers, you can add key value pairs in the headers section.
|
||||
**Multiple exporters (console + OTLP):**
|
||||
```bash
|
||||
export OTEL_METRICS_EXPORTER=console,otlp
|
||||
export OTEL_LOGS_EXPORTER=console,otlp
|
||||
```
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://assets.int.cline.bot/assets/open_telemetry_headers.png"
|
||||
/>
|
||||
</Frame>
|
||||
**Export intervals:**
|
||||
```bash
|
||||
# Metrics export interval in milliseconds (default: 60000)
|
||||
export OTEL_METRIC_EXPORT_INTERVAL=30000
|
||||
|
||||
# Logs batch size and timeout
|
||||
export OTEL_LOG_BATCH_SIZE=512
|
||||
export OTEL_LOG_BATCH_TIMEOUT=5000
|
||||
export OTEL_LOG_MAX_QUEUE_SIZE=2048
|
||||
```
|
||||
|
||||
## Integration Examples
|
||||
|
||||
@@ -88,46 +119,73 @@ Finally, if your collector needs authentication headers, you can add key value p
|
||||
|
||||
Export to Datadog using their OTLP endpoint:
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://assets.int.cline.bot/assets/open_telemetry_datadog_example.png"
|
||||
/>
|
||||
</Frame>
|
||||
```bash
|
||||
export OTEL_TELEMETRY_ENABLED=1
|
||||
export OTEL_METRICS_EXPORTER=otlp
|
||||
export OTEL_LOGS_EXPORTER=otlp
|
||||
export OTEL_EXPORTER_OTLP_ENDPOINT=https://api.datadoghq.com
|
||||
export OTEL_EXPORTER_OTLP_HEADERS="dd-api-key=YOUR_DD_API_KEY"
|
||||
```
|
||||
|
||||
### New Relic
|
||||
|
||||
Export to New Relic:
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://assets.int.cline.bot/assets/open_telemetry_relic_example.png"
|
||||
/>
|
||||
</Frame>
|
||||
```bash
|
||||
export OTEL_TELEMETRY_ENABLED=1
|
||||
export OTEL_METRICS_EXPORTER=otlp
|
||||
export OTEL_LOGS_EXPORTER=otlp
|
||||
export OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.nr-data.net:4317
|
||||
export OTEL_EXPORTER_OTLP_HEADERS="api-key=YOUR_NEW_RELIC_LICENSE_KEY"
|
||||
```
|
||||
|
||||
### Grafana Cloud
|
||||
|
||||
Export to Grafana Cloud:
|
||||
|
||||
<Frame>
|
||||
<img
|
||||
src="https://assets.int.cline.bot/assets/open_telemetry_grafana_example.png"
|
||||
/>
|
||||
</Frame>
|
||||
```bash
|
||||
export OTEL_TELEMETRY_ENABLED=1
|
||||
export OTEL_METRICS_EXPORTER=otlp
|
||||
export OTEL_LOGS_EXPORTER=otlp
|
||||
export OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp-gateway-prod-us-central-0.grafana.net/otlp
|
||||
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic YOUR_BASE64_CREDENTIALS"
|
||||
```
|
||||
|
||||
|
||||
## Testing Configuration
|
||||
|
||||
To test your configuration, log in to your account, perform some actions in a task, wait for the export interval, and verify that the data has arrived at your collector.
|
||||
Test your configuration with console output before sending to a real endpoint:
|
||||
|
||||
```bash
|
||||
# Enable console output to see what data would be exported
|
||||
export OTEL_TELEMETRY_ENABLED=1
|
||||
export OTEL_METRICS_EXPORTER=console
|
||||
export OTEL_LOGS_EXPORTER=console
|
||||
```
|
||||
|
||||
Then launch Cline and check the console output for metrics and logs.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you aren’t getting any data in your collector, the easiest way to verify your integration is to enable the developer tools in your editor.
|
||||
### No Data Being Exported
|
||||
|
||||
To do this, open the [webview developer tools](https://code.visualstudio.com/api/extension-guides/webview#inspecting-and-debugging-webviews).
|
||||
1. **Verify OpenTelemetry is enabled:**
|
||||
```bash
|
||||
echo $OTEL_TELEMETRY_ENABLED
|
||||
```
|
||||
Should output `1` or `true`
|
||||
|
||||
Once you’ve done so, if you perform some actions that trigger metrics and/or logs (such as doing a task with Cline),
|
||||
you will see error logs if any error occurs when sending the data to your collector.
|
||||
2. **Check exporters are configured:**
|
||||
```bash
|
||||
echo $OTEL_METRICS_EXPORTER
|
||||
echo $OTEL_LOGS_EXPORTER
|
||||
```
|
||||
|
||||
If you don't see any logs, enable [debug mode](#debug-mode).
|
||||
3. **Test with console exporter first:**
|
||||
```bash
|
||||
export OTEL_METRICS_EXPORTER=console
|
||||
export OTEL_LOGS_EXPORTER=console
|
||||
```
|
||||
|
||||
### Connection Errors
|
||||
|
||||
@@ -136,7 +194,10 @@ If you don't see any logs, enable [debug mode](#debug-mode).
|
||||
curl -v https://your-otlp-endpoint:4317
|
||||
```
|
||||
|
||||
2. **Check if insecure mode is needed** by opting out of TLS
|
||||
2. **Check if insecure mode is needed:**
|
||||
```bash
|
||||
export OTEL_EXPORTER_OTLP_INSECURE=true
|
||||
```
|
||||
|
||||
3. **Verify authentication headers:**
|
||||
Double-check your API keys and authentication headers are correct
|
||||
@@ -146,7 +207,7 @@ If you don't see any logs, enable [debug mode](#debug-mode).
|
||||
Enable debug logging to see detailed OpenTelemetry information:
|
||||
|
||||
```bash
|
||||
TEL_DEBUG_DIAGNOSTICS=true code .
|
||||
export TEL_DEBUG_DIAGNOSTICS=true
|
||||
```
|
||||
|
||||
This will output detailed information about:
|
||||
@@ -157,7 +218,7 @@ This will output detailed information about:
|
||||
|
||||
## What Gets Exported
|
||||
|
||||
When OpenTelemetry is enabled, Cline exports:
|
||||
When Opentelemetry is enabled, Cline exports:
|
||||
|
||||
### Metrics
|
||||
- Feature usage counts
|
||||
@@ -177,9 +238,9 @@ Exported data is already anonymous and doesn't include code content, file paths,
|
||||
## Limitations
|
||||
|
||||
Current OpenTelemetry support in Cline:
|
||||
- ✅ OTLP metrics export (gRPC, HTTP)
|
||||
- ✅ OTLP logs export (gRPC, HTTP)
|
||||
- ✅ Basic configuration via [Remote Configuration](/enterprise-solutions/configuration/remote-configuration/overview#how-remote-configuration-works)
|
||||
- ✅ OTLP metrics export (console, gRPC, HTTP)
|
||||
- ✅ OTLP logs export (console, gRPC, HTTP)
|
||||
- ✅ Basic configuration via environment variables
|
||||
- ❌ Distributed tracing (not yet implemented)
|
||||
- ❌ Custom instrumentation API (not yet exposed)
|
||||
- ❌ Sampling configuration (uses defaults)
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
---
|
||||
title: "OpenTelemetry Integration Override"
|
||||
sidebarTitle: "OpenTelemetry Override"
|
||||
description: "Export Cline telemetry to your observability platform using OpenTelemetry Protocol (OTLP)"
|
||||
---
|
||||
|
||||
Cline includes opt-in OpenTelemetry support for exporting metrics and logs to your own observability infrastructure using the OpenTelemetry Protocol (OTLP).
|
||||
|
||||
<Note>
|
||||
OpenTelemetry integration is **optional** and intended for advanced users with existing observability infrastructure. Most users won't need this feature.
|
||||
</Note>
|
||||
|
||||
## What is OpenTelemetry?
|
||||
|
||||
[OpenTelemetry](https://opentelemetry.io/) is an industry-standard observability framework that provides a unified way to collect and export telemetry data (metrics, logs, and traces).
|
||||
|
||||
Cline's OpenTelemetry support allows you to:
|
||||
- Export telemetry to your own systems
|
||||
- Integrate with observability platforms like Datadog, New Relic, Grafana Cloud, etc.
|
||||
- Maintain full control over your monitoring data
|
||||
- Use your organization's existing monitoring infrastructure
|
||||
|
||||
## Supported Features
|
||||
|
||||
Cline supports OpenTelemetry's **OTLP (OpenTelemetry Protocol)** export with:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Metrics Export" icon="chart-bar">
|
||||
Export metrics about Cline usage, performance, and errors
|
||||
</Card>
|
||||
|
||||
<Card title="Logs Export" icon="file-lines">
|
||||
Export structured logs for debugging and analysis
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
### Export Formats
|
||||
|
||||
Cline supports three OTLP export protocols:
|
||||
|
||||
- **gRPC** (default, recommended)
|
||||
- **HTTP/protobuf**
|
||||
- **HTTP/JSON**
|
||||
|
||||
### Export Destinations
|
||||
|
||||
You can export to:
|
||||
- **Console** (for testing)
|
||||
- **OTLP endpoint** (your own collector or observability platform)
|
||||
|
||||
## Configuration
|
||||
|
||||
OpenTelemetry is configured using environment variables before launching Cline.
|
||||
|
||||
### Basic Setup
|
||||
|
||||
Enable OpenTelemetry and configure an OTLP endpoint:
|
||||
|
||||
```bash
|
||||
# Enable OpenTelemetry
|
||||
export OTEL_TELEMETRY_ENABLED=1
|
||||
|
||||
# Configure metrics and logs export
|
||||
export OTEL_METRICS_EXPORTER=otlp
|
||||
export OTEL_LOGS_EXPORTER=otlp
|
||||
|
||||
# Set your OTLP endpoint
|
||||
export OTEL_EXPORTER_OTLP_ENDPOINT=https://your-collector:4317
|
||||
|
||||
# Optional: Set protocol (default is grpc)
|
||||
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `OTEL_TELEMETRY_ENABLED` | Enable OpenTelemetry (`1` or `true`) | Disabled |
|
||||
| `OTEL_METRICS_EXPORTER` | Metrics exporter type (`console`, `otlp`, or both) | None |
|
||||
| `OTEL_LOGS_EXPORTER` | Logs exporter type (`console`, `otlp`, or both) | None |
|
||||
| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP endpoint URL | None |
|
||||
| `OTEL_EXPORTER_OTLP_PROTOCOL` | Protocol (`grpc`, `http/protobuf`, `http/json`) | `grpc` |
|
||||
| `OTEL_EXPORTER_OTLP_INSECURE` | Allow insecure connections | `false` |
|
||||
| `OTEL_EXPORTER_OTLP_HEADERS` | Custom headers (comma-separated `key=value` pairs) | None |
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
**Separate endpoints for metrics and logs:**
|
||||
```bash
|
||||
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://metrics-collector:4317
|
||||
export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://logs-collector:4317
|
||||
```
|
||||
|
||||
**Custom headers for authentication:**
|
||||
```bash
|
||||
export OTEL_EXPORTER_OTLP_HEADERS="api-key=your-key,x-custom-header=value"
|
||||
```
|
||||
|
||||
**Multiple exporters (console + OTLP):**
|
||||
```bash
|
||||
export OTEL_METRICS_EXPORTER=console,otlp
|
||||
export OTEL_LOGS_EXPORTER=console,otlp
|
||||
```
|
||||
|
||||
**Export intervals:**
|
||||
```bash
|
||||
# Metrics export interval in milliseconds (default: 60000)
|
||||
export OTEL_METRIC_EXPORT_INTERVAL=30000
|
||||
|
||||
# Logs batch size and timeout
|
||||
export OTEL_LOG_BATCH_SIZE=512
|
||||
export OTEL_LOG_BATCH_TIMEOUT=5000
|
||||
export OTEL_LOG_MAX_QUEUE_SIZE=2048
|
||||
```
|
||||
|
||||
## Integration Examples
|
||||
|
||||
### Datadog
|
||||
|
||||
Export to Datadog using their OTLP endpoint:
|
||||
|
||||
```bash
|
||||
export OTEL_TELEMETRY_ENABLED=1
|
||||
export OTEL_METRICS_EXPORTER=otlp
|
||||
export OTEL_LOGS_EXPORTER=otlp
|
||||
export OTEL_EXPORTER_OTLP_ENDPOINT=https://api.datadoghq.com
|
||||
export OTEL_EXPORTER_OTLP_HEADERS="dd-api-key=YOUR_DD_API_KEY"
|
||||
```
|
||||
|
||||
### New Relic
|
||||
|
||||
Export to New Relic:
|
||||
|
||||
```bash
|
||||
export OTEL_TELEMETRY_ENABLED=1
|
||||
export OTEL_METRICS_EXPORTER=otlp
|
||||
export OTEL_LOGS_EXPORTER=otlp
|
||||
export OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.nr-data.net:4317
|
||||
export OTEL_EXPORTER_OTLP_HEADERS="api-key=YOUR_NEW_RELIC_LICENSE_KEY"
|
||||
```
|
||||
|
||||
### Grafana Cloud
|
||||
|
||||
Export to Grafana Cloud:
|
||||
|
||||
```bash
|
||||
export OTEL_TELEMETRY_ENABLED=1
|
||||
export OTEL_METRICS_EXPORTER=otlp
|
||||
export OTEL_LOGS_EXPORTER=otlp
|
||||
export OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp-gateway-prod-us-central-0.grafana.net/otlp
|
||||
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic YOUR_BASE64_CREDENTIALS"
|
||||
```
|
||||
|
||||
|
||||
## Testing Configuration
|
||||
|
||||
Test your configuration with console output before sending to a real endpoint:
|
||||
|
||||
```bash
|
||||
# Enable console output to see what data would be exported
|
||||
export OTEL_TELEMETRY_ENABLED=1
|
||||
export OTEL_METRICS_EXPORTER=console
|
||||
export OTEL_LOGS_EXPORTER=console
|
||||
```
|
||||
|
||||
Then launch Cline and check the console output for metrics and logs.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### No Data Being Exported
|
||||
|
||||
1. **Verify OpenTelemetry is enabled:**
|
||||
```bash
|
||||
echo $OTEL_TELEMETRY_ENABLED
|
||||
```
|
||||
Should output `1` or `true`
|
||||
|
||||
2. **Check exporters are configured:**
|
||||
```bash
|
||||
echo $OTEL_METRICS_EXPORTER
|
||||
echo $OTEL_LOGS_EXPORTER
|
||||
```
|
||||
|
||||
3. **Test with console exporter first:**
|
||||
```bash
|
||||
export OTEL_METRICS_EXPORTER=console
|
||||
export OTEL_LOGS_EXPORTER=console
|
||||
```
|
||||
|
||||
### Connection Errors
|
||||
|
||||
1. **Verify endpoint is accessible:**
|
||||
```bash
|
||||
curl -v https://your-otlp-endpoint:4317
|
||||
```
|
||||
|
||||
2. **Check if insecure mode is needed:**
|
||||
```bash
|
||||
export OTEL_EXPORTER_OTLP_INSECURE=true
|
||||
```
|
||||
|
||||
3. **Verify authentication headers:**
|
||||
Double-check your API keys and authentication headers are correct
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable debug logging to see detailed OpenTelemetry information:
|
||||
|
||||
```bash
|
||||
export TEL_DEBUG_DIAGNOSTICS=true
|
||||
```
|
||||
|
||||
This will output detailed information about:
|
||||
- Configuration being used
|
||||
- Exporters being created
|
||||
- Connection attempts
|
||||
- Export successes/failures
|
||||
|
||||
## What Gets Exported
|
||||
|
||||
When OpenTelemetry is enabled, Cline exports:
|
||||
|
||||
### Metrics
|
||||
- Feature usage counts
|
||||
- Task execution metrics
|
||||
- Error rates and types
|
||||
- Performance measurements
|
||||
|
||||
### Logs
|
||||
- System events
|
||||
- Error logs with context
|
||||
- Operational information
|
||||
|
||||
<Warning>
|
||||
Exported data is already anonymous and doesn't include code content, file paths, or sensitive information. However, you're responsible for securing the data once exported to your systems.
|
||||
</Warning>
|
||||
|
||||
## Limitations
|
||||
|
||||
Current OpenTelemetry support in Cline:
|
||||
- ✅ OTLP metrics export (console, gRPC, HTTP)
|
||||
- ✅ OTLP logs export (console, gRPC, HTTP)
|
||||
- ✅ Basic configuration via environment variables
|
||||
- ❌ Distributed tracing (not yet implemented)
|
||||
- ❌ Custom instrumentation API (not yet exposed)
|
||||
- ❌ Sampling configuration (uses defaults)
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Test First**: Always test with console exporter before sending to production
|
||||
2. **Secure Credentials**: Never hardcode API keys; use secure environment variable management
|
||||
3. **Monitor Costs**: Be aware of data ingestion costs with your observability platform
|
||||
4. **Start Simple**: Begin with metrics only, add logs if needed
|
||||
5. **Use Compression**: OTLP supports compression; check if your endpoint requires it
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Cline Telemetry" icon="chart-simple" href="/enterprise-solutions/monitoring/telemetry">
|
||||
Configure simple built-in telemetry
|
||||
</Card>
|
||||
|
||||
<Card title="OpenTelemetry Docs" icon="book" href="https://opentelemetry.io/docs/">
|
||||
Learn more about OpenTelemetry
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -8,20 +8,14 @@ Cline includes optional monitoring capabilities for organizations that want to t
|
||||
|
||||
## Monitoring Options
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="OpenTelemetry" icon="chart-line" href="/enterprise-solutions/monitoring/opentelemetry">
|
||||
Export metrics and logs to your own observability backends
|
||||
</Card>
|
||||
|
||||
<Card title="OpenTelemetry Override" icon="chart-line" href="/enterprise-solutions/monitoring/opentelemetry_override">
|
||||
Export to your own observability backends through environment variables (advanced)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<CardGroup cols={1}>
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Cline Telemetry" icon="chart-simple" href="/enterprise-solutions/monitoring/telemetry">
|
||||
Built-in anonymous usage tracking that helps improve Cline (opt-in)
|
||||
</Card>
|
||||
</Card>
|
||||
|
||||
<Card title="OpenTelemetry" icon="chart-line" href="/enterprise-solutions/monitoring/opentelemetry">
|
||||
Export metrics and logs to your own observability backends (advanced)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Cline Telemetry
|
||||
|
||||
@@ -22,10 +22,6 @@ Your IdP administrator will receive an email with a link to register their organ
|
||||
|
||||
### Step 2: Configure Your Identity Provider
|
||||
|
||||
<Info>
|
||||
For a short overview of where SSO configuration lives (Cline dashboard vs WorkOS vs your IdP), see [SSO Setup](/enterprise-solutions/sso-setup).
|
||||
</Info>
|
||||
|
||||
Connect your identity provider (IdP) to WorkOS:
|
||||
|
||||
1. In the WorkOS dashboard, go to **AuthKit → Connections**
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
title: "SSO Setup"
|
||||
sidebarTitle: "SSO Setup"
|
||||
description: "Configure Single Sign-On (SSO) for Cline Enterprise via WorkOS AuthKit."
|
||||
---
|
||||
|
||||
## Overview
|
||||
Cline Enterprise integrates with your identity provider (IdP) via **WorkOS AuthKit** for SSO.
|
||||
|
||||
This page describes, at a high level, how SSO is set up for Cline Enterprise using WorkOS AuthKit.
|
||||
|
||||
If you haven’t completed initial onboarding, start with [Onboarding](/enterprise-solutions/onboarding).
|
||||
|
||||
## Where setup happens
|
||||
SSO setup spans two places:
|
||||
|
||||
1) **Cline Dashboard (app.cline.bot)**
|
||||
- Where you sign in and verify SSO works for your organization.
|
||||
|
||||
2) **WorkOS dashboard**
|
||||
- Where your IdP connection is configured (AuthKit → Connections). Your designated admin receives access to this during enterprise onboarding.
|
||||
|
||||
## Using the Cline Dashboard
|
||||
Use the Cline Dashboard at https://app.cline.bot to:
|
||||
- complete sign-in and onboarding flows
|
||||
- verify users can authenticate via SSO
|
||||
|
||||
## Configure your IdP connection in WorkOS
|
||||
|
||||
During enterprise onboarding, your designated admin will receive an invitation email from WorkOS with a link to access your organization's WorkOS dashboard.
|
||||
|
||||
<Frame>
|
||||
<img src="/assets/workos-invite-email.png" alt="WorkOS invitation email example" />
|
||||
</Frame>
|
||||
|
||||
To connect your IdP to Cline Enterprise, configure your identity provider in **WorkOS AuthKit**:
|
||||
|
||||
1. In the WorkOS dashboard, go to **AuthKit → Connections**
|
||||
2. Click **Add Connection**
|
||||
3. Select your identity provider (e.g., Okta, Microsoft Entra ID/Azure AD, Google Workspace, Generic SAML/OIDC)
|
||||
4. Follow the provider-specific instructions in WorkOS
|
||||
|
||||
WorkOS’s UI and required fields vary by provider. For details, follow WorkOS documentation:
|
||||
- https://workos.com/docs/authkit/sso
|
||||
|
||||
## Keycloak note (IdP compatibility)
|
||||
Cline Enterprise’s default SSO integration is **via WorkOS**.
|
||||
|
||||
If you use **Keycloak** as your IdP, the supported path is to configure Keycloak in WorkOS as a **Generic SAML** or **Generic OIDC** provider (using the settings WorkOS requests for those provider types).
|
||||
|
||||
## Verification
|
||||
After configuring WorkOS:
|
||||
|
||||
1) Attempt an SSO sign-in from https://app.cline.bot.
|
||||
2) Confirm the sign-in completes (you are redirected back successfully).
|
||||
|
||||
## Troubleshooting
|
||||
- **Redirect URI mismatch**: confirm the redirect/callback URL configured in WorkOS matches what was provided during your Cline Enterprise onboarding.
|
||||
|
||||
For additional troubleshooting guidance, refer to WorkOS documentation:
|
||||
- https://workos.com/docs/authkit/sso
|
||||
@@ -13,6 +13,46 @@ Cline is your AI assistant that can:
|
||||
- Automate repetitive tasks
|
||||
- Integrate with external tools
|
||||
|
||||
## First Steps
|
||||
|
||||
1. **Start a Task**
|
||||
|
||||
- Type your request in the chat
|
||||
- Example: "Create a new React component called Header"
|
||||
|
||||
2. **Provide Context**
|
||||
|
||||
- Use @ mentions to add files, folders, or URLs
|
||||
- Example: "@file:src/components/App.tsx"
|
||||
|
||||
3. **Review Changes**
|
||||
- Cline will show diffs before making changes
|
||||
- You can edit or reject changes
|
||||
|
||||
## Key Features
|
||||
|
||||
1. **File Editing**
|
||||
|
||||
- Create new files
|
||||
- Modify existing code
|
||||
- Search and replace across files
|
||||
|
||||
2. **Terminal Commands**
|
||||
|
||||
- Run npm commands
|
||||
- Start development servers
|
||||
- Install dependencies
|
||||
|
||||
3. **Code Analysis**
|
||||
|
||||
- Find and fix errors
|
||||
- Refactor code
|
||||
- Add documentation
|
||||
|
||||
4. **Browser Integration**
|
||||
- Test web pages
|
||||
- Capture screenshots
|
||||
- Inspect console logs
|
||||
|
||||
## Available Tools
|
||||
|
||||
@@ -44,7 +84,6 @@ Cline has access to the following tools for various tasks:
|
||||
- `ask_followup_question`: Ask user for clarification
|
||||
- `attempt_completion`: Present final results
|
||||
|
||||
|
||||
Each tool has specific parameters and usage patterns. Here are some examples:
|
||||
|
||||
- Create a new file (write_to_file):
|
||||
|
||||
@@ -12,19 +12,6 @@ sidebarTitle: "/deep-planning"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
## Demo Video
|
||||
|
||||
Watch Deep Planning in action as Cline investigates a codebase, asks clarifying questions, and generates a comprehensive implementation plan:
|
||||
|
||||
<Frame>
|
||||
<video
|
||||
muted
|
||||
controls
|
||||
playsInline
|
||||
src="https://storage.googleapis.com/cline_public_images/docs/assets/Cline-Deep-Planning-Demo.mp4"
|
||||
/>
|
||||
</Frame>
|
||||
|
||||
When you use `/deep-planning`, Cline follows a four-step process that mirrors how senior developers approach complex features: thorough investigation, discussion & clarification of requirements, detailed planning, and structured task creation with progress tracking.
|
||||
|
||||
## The Four-Step Process
|
||||
|
||||
Generated
+1423
-2311
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -13,7 +13,7 @@
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"mintlify": "^4.2.249"
|
||||
"mintlify": "^4.2.23"
|
||||
},
|
||||
"overrides": {
|
||||
"tar-fs": "^3.1.1",
|
||||
|
||||
@@ -6,17 +6,12 @@ description: "Complete guide to resolving terminal integration issues in Cline"
|
||||
|
||||
This guide helps you resolve terminal integration issues in Cline. Terminal integration is crucial for Cline to execute commands and read their output, enabling it to understand errors, test results, and command responses.
|
||||
|
||||
## Try This First: Background Execution Mode
|
||||
<Tip>
|
||||
If you're experiencing terminal issues, try switching to a simpler shell like `bash` in the Cline settings, under "Terminal Settings"
|
||||
|
||||
The simplest fix for most terminal issues is switching to **Background Execution Mode**:
|
||||
This resolves most terminal integration problems.
|
||||
|
||||
1. Click **Settings** (top right of Cline chat)
|
||||
2. Go to **Terminal Settings**
|
||||
3. Set **Terminal Execution Mode** → **Background Exec**
|
||||
|
||||
This runs commands in a background process instead of VSCode's terminal, bypassing most integration issues. The guide below is for users who specifically need VSCode's integrated terminal.
|
||||
|
||||
---
|
||||
</Tip>
|
||||
|
||||
## Quick Diagnosis Flowchart
|
||||
|
||||
|
||||
@@ -4,21 +4,7 @@ sidebarTitle: "Terminal Quick Fixes"
|
||||
description: "Quick solutions for common terminal issues"
|
||||
---
|
||||
|
||||
## Try This First: Background Execution Mode
|
||||
|
||||
The simplest fix for most terminal issues is switching to **Background Execution Mode**:
|
||||
|
||||
1. Click **Settings** (top right of Cline chat)
|
||||
2. Go to **Terminal Settings**
|
||||
3. Set **Terminal Execution Mode** → **Background Exec**
|
||||
|
||||
This runs commands in a background process instead of VSCode's terminal, bypassing most integration issues.
|
||||
|
||||
---
|
||||
|
||||
## Other Fixes
|
||||
|
||||
If you need VSCode's integrated terminal, try these:
|
||||
**Here is a list of common fixes, starting with the most applicable:**
|
||||
|
||||
- **Switch to bash** (solves most instances)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
streamlit==1.43.2
|
||||
streamlit>=1.28.0
|
||||
plotly>=5.17.0
|
||||
pandas>=2.0.0
|
||||
numpy>=1.24.0
|
||||
|
||||
Generated
+69
-176
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "claude-dev",
|
||||
"version": "3.46.1",
|
||||
"version": "3.45.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "claude-dev",
|
||||
"version": "3.46.1",
|
||||
"version": "3.45.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.37.0",
|
||||
@@ -20,7 +20,7 @@
|
||||
"@grpc/grpc-js": "^1.9.15",
|
||||
"@grpc/reflection": "^1.0.4",
|
||||
"@mistralai/mistralai": "^1.5.0",
|
||||
"@modelcontextprotocol/sdk": "^1.25.1",
|
||||
"@modelcontextprotocol/sdk": "^1.11.1",
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
"@opentelemetry/core": "^2.1.0",
|
||||
"@opentelemetry/exporter-logs-otlp-grpc": "^0.56.0",
|
||||
@@ -68,7 +68,6 @@
|
||||
"image-size": "^2.0.2",
|
||||
"isbinaryfile": "^5.0.2",
|
||||
"jschardet": "^3.1.4",
|
||||
"json5": "^2.2.3",
|
||||
"mammoth": "^1.11.0",
|
||||
"nanoid": "^5.1.6",
|
||||
"nice-grpc": "^2.1.12",
|
||||
@@ -1187,6 +1186,7 @@
|
||||
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/generator": "^7.28.3",
|
||||
@@ -2649,6 +2649,7 @@
|
||||
"node_modules/@grpc/grpc-js": {
|
||||
"version": "1.9.15",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@grpc/proto-loader": "^0.7.8",
|
||||
"@types/node": ">=12.12.47"
|
||||
@@ -2684,18 +2685,6 @@
|
||||
"@grpc/grpc-js": "^1.8.21"
|
||||
}
|
||||
},
|
||||
"node_modules/@hono/node-server": {
|
||||
"version": "1.19.7",
|
||||
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.7.tgz",
|
||||
"integrity": "sha512-vUcD0uauS7EU2caukW8z5lJKtoGMokxNbJtBiwHgpqxEXokaHCBkQUmCHhjFB1VUTWdqj25QoMkMKzgjq+uhrw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.14.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"hono": "^4"
|
||||
}
|
||||
},
|
||||
"node_modules/@inquirer/external-editor": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz",
|
||||
@@ -3228,12 +3217,12 @@
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/@modelcontextprotocol/sdk": {
|
||||
"version": "1.25.1",
|
||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.1.tgz",
|
||||
"integrity": "sha512-yO28oVFFC7EBoiKdAn+VqRm+plcfv4v0xp6osG/VsCB0NlPZWi87ajbCZZ8f/RvOFLEu7//rSRmuZZ7lMoe3gQ==",
|
||||
"version": "1.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.22.0.tgz",
|
||||
"integrity": "sha512-VUpl106XVTCpDmTBil2ehgJZjhyLY2QZikzF8NvTXtLRF1CvO5iEE2UNZdVIUer35vFOwMKYeUGbjJtvPWan3g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@hono/node-server": "^1.19.7",
|
||||
"ajv": "^8.17.1",
|
||||
"ajv-formats": "^3.0.1",
|
||||
"content-type": "^1.0.5",
|
||||
@@ -3243,26 +3232,20 @@
|
||||
"eventsource-parser": "^3.0.0",
|
||||
"express": "^5.0.1",
|
||||
"express-rate-limit": "^7.5.0",
|
||||
"jose": "^6.1.1",
|
||||
"json-schema-typed": "^8.0.2",
|
||||
"pkce-challenge": "^5.0.0",
|
||||
"raw-body": "^3.0.0",
|
||||
"zod": "^3.25 || ^4.0",
|
||||
"zod-to-json-schema": "^3.25.0"
|
||||
"zod": "^3.23.8",
|
||||
"zod-to-json-schema": "^3.24.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@cfworker/json-schema": "^4.1.1",
|
||||
"zod": "^3.25 || ^4.0"
|
||||
"@cfworker/json-schema": "^4.1.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@cfworker/json-schema": {
|
||||
"optional": true
|
||||
},
|
||||
"zod": {
|
||||
"optional": false
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3300,6 +3283,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
|
||||
"integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
@@ -4915,8 +4899,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.52.4",
|
||||
@@ -4929,8 +4912,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.52.4",
|
||||
@@ -4943,8 +4925,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.52.4",
|
||||
@@ -4957,8 +4938,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.52.4",
|
||||
@@ -4971,8 +4951,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.52.4",
|
||||
@@ -4985,8 +4964,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.52.4",
|
||||
@@ -4999,8 +4977,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.52.4",
|
||||
@@ -5013,8 +4990,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.52.4",
|
||||
@@ -5027,8 +5003,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.52.4",
|
||||
@@ -5041,8 +5016,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loong64-gnu": {
|
||||
"version": "4.52.4",
|
||||
@@ -5055,8 +5029,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
||||
"version": "4.52.4",
|
||||
@@ -5069,8 +5042,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.52.4",
|
||||
@@ -5083,8 +5055,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||
"version": "4.52.4",
|
||||
@@ -5097,8 +5068,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.52.4",
|
||||
@@ -5111,8 +5081,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.52.4",
|
||||
@@ -5125,8 +5094,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.52.4",
|
||||
@@ -5139,8 +5107,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-openharmony-arm64": {
|
||||
"version": "4.52.4",
|
||||
@@ -5153,8 +5120,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.52.4",
|
||||
@@ -5167,8 +5133,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.52.4",
|
||||
@@ -5181,8 +5146,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-gnu": {
|
||||
"version": "4.52.4",
|
||||
@@ -5195,8 +5159,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.52.4",
|
||||
@@ -5209,8 +5172,7 @@
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/@sap-ai-sdk/ai-api": {
|
||||
"version": "2.1.0",
|
||||
@@ -6467,60 +6429,6 @@
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
|
||||
"version": "1.5.0",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/wasi-threads": "1.1.0",
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||
"version": "1.5.0",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||
"version": "1.1.0",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
|
||||
"version": "1.0.5",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/core": "^1.5.0",
|
||||
"@emnapi/runtime": "^1.5.0",
|
||||
"@tybys/wasm-util": "^0.10.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
|
||||
"version": "0.10.1",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"inBundle": true,
|
||||
"license": "0BSD",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||
"version": "4.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.14.tgz",
|
||||
@@ -6763,8 +6671,7 @@
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/get-folder-size": {
|
||||
"version": "3.0.4",
|
||||
@@ -6789,6 +6696,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.21.tgz",
|
||||
"integrity": "sha512-CsGG2P3I5y48RPMfprQGfy4JPRZ6csfC3ltBZSRItG3ngggmNY/qs2uZKp4p9VbrpqNNSMzUZNFZKzgOGnd/VA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
@@ -7486,6 +7394,7 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -8252,6 +8161,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.8.3",
|
||||
"caniuse-lite": "^1.0.30001741",
|
||||
@@ -9455,7 +9365,8 @@
|
||||
},
|
||||
"node_modules/devtools-protocol": {
|
||||
"version": "0.0.1342118",
|
||||
"license": "BSD-3-Clause"
|
||||
"license": "BSD-3-Clause",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "5.2.0",
|
||||
@@ -11440,16 +11351,6 @@
|
||||
"he": "bin/he"
|
||||
}
|
||||
},
|
||||
"node_modules/hono": {
|
||||
"version": "4.11.1",
|
||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.11.1.tgz",
|
||||
"integrity": "sha512-KsFcH0xxHes0J4zaQgWbYwmz3UPOOskdqZmItstUG93+Wk1ePBLkLGwbP9zlmh1BFUiL8Qp+Xfu9P7feJWpGNg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/hosted-git-info": {
|
||||
"version": "2.8.9",
|
||||
"dev": true,
|
||||
@@ -12431,19 +12332,11 @@
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
|
||||
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"jiti": "lib/jiti-cli.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/jose": {
|
||||
"version": "6.1.3",
|
||||
"resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz",
|
||||
"integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/panva"
|
||||
}
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"dev": true,
|
||||
@@ -12504,16 +12397,9 @@
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-schema-typed": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz",
|
||||
"integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==",
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/json5": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
|
||||
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"json5": "lib/cli.js"
|
||||
@@ -12533,12 +12419,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jsonwebtoken": {
|
||||
"version": "9.0.3",
|
||||
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz",
|
||||
"integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==",
|
||||
"version": "9.0.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"jws": "^4.0.1",
|
||||
"jws": "^3.2.2",
|
||||
"lodash.includes": "^4.3.0",
|
||||
"lodash.isboolean": "^3.0.3",
|
||||
"lodash.isinteger": "^4.0.4",
|
||||
@@ -12554,6 +12438,23 @@
|
||||
"npm": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonwebtoken/node_modules/jwa": {
|
||||
"version": "1.4.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-equal-constant-time": "^1.0.1",
|
||||
"ecdsa-sig-formatter": "1.0.11",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonwebtoken/node_modules/jws": {
|
||||
"version": "3.2.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"jwa": "^1.4.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/jszip": {
|
||||
"version": "3.10.1",
|
||||
"license": "(MIT OR GPL-3.0-or-later)",
|
||||
@@ -12581,12 +12482,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jws": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
|
||||
"integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
|
||||
"version": "4.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"jwa": "^2.0.1",
|
||||
"jwa": "^2.0.0",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
@@ -12662,6 +12561,7 @@
|
||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
|
||||
"integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
|
||||
"license": "MPL-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.3"
|
||||
},
|
||||
@@ -15542,7 +15442,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
@@ -15563,7 +15462,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
@@ -16231,7 +16129,6 @@
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.4.tgz",
|
||||
"integrity": "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.8"
|
||||
},
|
||||
@@ -17668,7 +17565,6 @@
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fdir": "^6.5.0",
|
||||
"picomatch": "^4.0.3"
|
||||
@@ -17685,7 +17581,6 @@
|
||||
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
|
||||
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
@@ -18049,6 +17944,7 @@
|
||||
"version": "5.5.3",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -18308,7 +18204,6 @@
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.2.2.tgz",
|
||||
"integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.5.0",
|
||||
@@ -18383,7 +18278,6 @@
|
||||
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
|
||||
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
@@ -19079,17 +18973,16 @@
|
||||
"node_modules/zod": {
|
||||
"version": "3.25.76",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
},
|
||||
"node_modules/zod-to-json-schema": {
|
||||
"version": "3.25.0",
|
||||
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz",
|
||||
"integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==",
|
||||
"version": "3.24.4",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25 || ^4"
|
||||
"zod": "^3.24.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -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.46.1",
|
||||
"version": "3.45.0",
|
||||
"icon": "assets/icons/icon.png",
|
||||
"engines": {
|
||||
"vscode": "^1.84.0"
|
||||
@@ -463,7 +463,7 @@
|
||||
"@grpc/grpc-js": "^1.9.15",
|
||||
"@grpc/reflection": "^1.0.4",
|
||||
"@mistralai/mistralai": "^1.5.0",
|
||||
"@modelcontextprotocol/sdk": "^1.25.1",
|
||||
"@modelcontextprotocol/sdk": "^1.11.1",
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
"@opentelemetry/core": "^2.1.0",
|
||||
"@opentelemetry/exporter-logs-otlp-grpc": "^0.56.0",
|
||||
@@ -511,7 +511,6 @@
|
||||
"image-size": "^2.0.2",
|
||||
"isbinaryfile": "^5.0.2",
|
||||
"jschardet": "^3.1.4",
|
||||
"json5": "^2.2.3",
|
||||
"mammoth": "^1.11.0",
|
||||
"nanoid": "^5.1.6",
|
||||
"nice-grpc": "^2.1.12",
|
||||
|
||||
@@ -369,7 +369,6 @@ message UpdateSettingsRequest {
|
||||
optional OnboardingModelGroup onboarding_models = 33;
|
||||
optional bool cline_web_tools_enabled = 34;
|
||||
optional bool enable_parallel_tool_calling = 35;
|
||||
optional bool background_edit_enabled = 36;
|
||||
}
|
||||
|
||||
message UpdateTerminalConnectionTimeoutRequest {
|
||||
|
||||
@@ -55,10 +55,8 @@ enum Setting {
|
||||
}
|
||||
message GetTelemetrySettingsResponse {
|
||||
Setting is_enabled = 1;
|
||||
optional string error_level = 2;
|
||||
}
|
||||
|
||||
message TelemetrySettingsEvent {
|
||||
Setting is_enabled = 1;
|
||||
optional string error_level = 2;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,6 @@ function createMockService<T extends grpc.UntypedServiceImplementation>(serviceN
|
||||
case "getTelemetrySettings":
|
||||
callback(null, {
|
||||
isEnabled: 2, // Setting.DISABLED
|
||||
errorLevel: "all",
|
||||
})
|
||||
return
|
||||
|
||||
|
||||
+4
-2
@@ -104,15 +104,17 @@ async function showVersionUpdateAnnouncement(context: vscode.ExtensionContext) {
|
||||
if (!previousVersion || currentVersion !== previousVersion) {
|
||||
Logger.log(`Cline version changed: ${previousVersion} -> ${currentVersion}. First run or update detected.`)
|
||||
|
||||
// Check if there's a new announcement to show
|
||||
// Use the same condition as announcements: focus when there's a new announcement to show
|
||||
const lastShownAnnouncementId = context.globalState.get<string>("lastShownAnnouncementId")
|
||||
const latestAnnouncementId = getLatestAnnouncementId()
|
||||
|
||||
if (lastShownAnnouncementId !== latestAnnouncementId) {
|
||||
// Show notification when there's a new announcement (major/minor updates or fresh installs)
|
||||
// Focus Cline when there's a new announcement to show (major/minor updates or fresh installs)
|
||||
const message = previousVersion
|
||||
? `Cline has been updated to v${currentVersion}`
|
||||
: `Welcome to Cline v${currentVersion}`
|
||||
await HostProvider.workspace.openClineSidebarPanel({})
|
||||
await new Promise((resolve) => setTimeout(resolve, 200))
|
||||
HostProvider.window.showMessage({
|
||||
type: ShowMessageType.INFORMATION,
|
||||
message,
|
||||
|
||||
@@ -4,7 +4,6 @@ import { ModelInfo } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../index"
|
||||
import { withRetry } from "../retry"
|
||||
import { sanitizeAnthropicMessages } from "../transform/anthropic-format"
|
||||
import { convertAnthropicMessageToGemini } from "../transform/gemini-format"
|
||||
import { convertToOpenAiMessages } from "../transform/openai-format"
|
||||
import { ApiStream } from "../transform/stream"
|
||||
@@ -145,15 +144,12 @@ export class AIhubmixHandler implements ApiHandler {
|
||||
const client = this.ensureAnthropicClient()
|
||||
const modelId = this.options.modelId || "claude-3-5-sonnet-20241022"
|
||||
|
||||
// Sanitize messages to remove Cline-specific fields like call_id that are not allowed by Anthropic API
|
||||
const sanitizedMessages = sanitizeAnthropicMessages(messages, false)
|
||||
|
||||
const stream = await client.messages.create({
|
||||
model: modelId,
|
||||
temperature: 0,
|
||||
max_tokens: this.options.modelInfo?.maxTokens || 8192,
|
||||
system: [{ text: systemPrompt, type: "text" }],
|
||||
messages: sanitizedMessages,
|
||||
messages,
|
||||
stream: true,
|
||||
})
|
||||
|
||||
|
||||
@@ -755,7 +755,10 @@ export class AwsBedrockHandler implements ApiHandler {
|
||||
// For Anthropic models with thinking enabled, temperature must be 1
|
||||
if (modelType === "anthropic") {
|
||||
const budget_tokens = this.options.thinkingBudgetTokens || 0
|
||||
const reasoningOn = modelInfo.supportsReasoning && budget_tokens > 0
|
||||
const baseModelId =
|
||||
(this.options.awsBedrockCustomSelected ? this.options.awsBedrockCustomModelBaseId : this.getModel().id) ||
|
||||
this.getModel().id
|
||||
const reasoningOn = this.shouldEnableReasoning(baseModelId, budget_tokens)
|
||||
|
||||
return {
|
||||
maxTokens: modelInfo.maxTokens || 8192,
|
||||
@@ -769,6 +772,20 @@ export class AwsBedrockHandler implements ApiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if reasoning should be enabled for Claude models
|
||||
*/
|
||||
private shouldEnableReasoning(baseModelId: string, budgetTokens: number): boolean {
|
||||
return (
|
||||
(baseModelId.includes("3-7") ||
|
||||
baseModelId.includes("sonnet-4") ||
|
||||
baseModelId.includes("opus-4") ||
|
||||
baseModelId.includes("haiku-4-5") ||
|
||||
baseModelId.includes("sonnet-4-5")) &&
|
||||
budgetTokens !== 0
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a message using Anthropic Claude models through AWS Bedrock Converse API
|
||||
* Implements support for Anthropic Claude models using the unified Converse API
|
||||
@@ -798,7 +815,10 @@ export class AwsBedrockHandler implements ApiHandler {
|
||||
|
||||
// Get thinking configuration
|
||||
const budget_tokens = this.options.thinkingBudgetTokens || 0
|
||||
const reasoningOn = model.info.supportsReasoning && budget_tokens > 0
|
||||
const baseModelId =
|
||||
(this.options.awsBedrockCustomSelected ? this.options.awsBedrockCustomModelBaseId : this.getModel().id) ||
|
||||
this.getModel().id
|
||||
const reasoningOn = this.shouldEnableReasoning(baseModelId, budget_tokens)
|
||||
|
||||
// Prepare request for Anthropic model using Converse API
|
||||
const command = new ConverseStreamCommand({
|
||||
|
||||
@@ -11,12 +11,6 @@ interface CerebrasHandlerOptions extends CommonApiHandlerOptions {
|
||||
apiModelId?: string
|
||||
}
|
||||
|
||||
// Conservative max_tokens for Cerebras to avoid premature rate limiting.
|
||||
// Cerebras rate limiter estimates token consumption using max_completion_tokens upfront,
|
||||
// so requesting the model maximum (e.g., 64K) reserves that quota even if actual usage is low.
|
||||
// 16K is sufficient for most agentic tool use while preserving rate limit headroom.
|
||||
const CEREBRAS_DEFAULT_MAX_TOKENS = 16_384
|
||||
|
||||
export class CerebrasHandler implements ApiHandler {
|
||||
private options: CerebrasHandlerOptions
|
||||
private client: Cerebras | undefined
|
||||
@@ -117,7 +111,7 @@ export class CerebrasHandler implements ApiHandler {
|
||||
messages: cerebrasMessages,
|
||||
temperature: 0,
|
||||
stream: true,
|
||||
max_tokens: CEREBRAS_DEFAULT_MAX_TOKENS,
|
||||
max_tokens: this.getModel().info.maxTokens,
|
||||
})
|
||||
|
||||
// Handle streaming response
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
import { ChatMessage, OrchestrationClient, OrchestrationModuleConfig } from "@sap-ai-sdk/orchestration"
|
||||
import { ModelInfo, SapAiCoreModelId, sapAiCoreDefaultModelId, sapAiCoreModels } from "@shared/api"
|
||||
import axios from "axios"
|
||||
import JSON5 from "json5"
|
||||
import OpenAI from "openai"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { getAxiosSettings } from "@/shared/net"
|
||||
@@ -879,6 +878,12 @@ export class SapAiCoreHandler implements ApiHandler {
|
||||
stream: any,
|
||||
_model: { id: SapAiCoreModelId; info: ModelInfo },
|
||||
): AsyncGenerator<any, void, unknown> {
|
||||
function toStrictJson(str: string): string {
|
||||
// Wrap it in parentheses so JS will treat it as an expression
|
||||
const obj = new Function("return " + str)()
|
||||
return JSON.stringify(obj)
|
||||
}
|
||||
|
||||
const _usage = { input_tokens: 0, output_tokens: 0 }
|
||||
|
||||
try {
|
||||
@@ -893,8 +898,7 @@ export class SapAiCoreHandler implements ApiHandler {
|
||||
|
||||
try {
|
||||
// Parse the incoming JSON data from the stream
|
||||
// Using JSON5 to handle relaxed JSON syntax (e.g., single quotes)
|
||||
const data = JSON5.parse(jsonData)
|
||||
const data = JSON.parse(toStrictJson(jsonData))
|
||||
|
||||
// Handle metadata (token usage)
|
||||
if (data.metadata?.usage) {
|
||||
|
||||
@@ -48,11 +48,7 @@ export function convertAnthropicContentToGemini(content: string | ClineStorageMe
|
||||
},
|
||||
}
|
||||
case "thinking":
|
||||
return {
|
||||
text: block.thinking,
|
||||
thought: true,
|
||||
thoughtSignature: block.signature || GEMINI_DUMMY_THOUGHT_SIGNATURE,
|
||||
}
|
||||
return { text: block.thinking, thought: true, thoughtSignature: block.signature }
|
||||
default:
|
||||
return undefined
|
||||
}
|
||||
|
||||
@@ -176,18 +176,11 @@ export function convertToOpenAiMessages(
|
||||
// Process tool use messages
|
||||
const tool_calls: OpenAI.Chat.ChatCompletionMessageToolCall[] = toolMessages.map((toolMessage) => {
|
||||
const toolDetails = toolMessage.reasoning_details
|
||||
if (toolDetails) {
|
||||
if (toolDetails?.length) {
|
||||
if (Array.isArray(toolDetails)) {
|
||||
// For Gemini: reasoning details must be linkable back to the tool call.
|
||||
// Sometimes OpenRouter/Gemini returns entries without `id`; those poison the next request.
|
||||
// Keep only entries with an id matching the tool call id.
|
||||
// See: https://github.com/cline/cline/issues/8214
|
||||
const validDetails = toolDetails.filter((detail: any) => detail?.id === toolMessage.id)
|
||||
if (validDetails.length > 0) reasoningDetails.push(...validDetails)
|
||||
reasoningDetails.push(...toolDetails)
|
||||
} else {
|
||||
// Single reasoning detail - only include if it has matching id
|
||||
const detail = toolDetails as any
|
||||
if (detail?.id === toolMessage.id) reasoningDetails.push(toolDetails)
|
||||
reasoningDetails.push(toolDetails)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,17 +200,13 @@ export function convertToOpenAiMessages(
|
||||
const hasMeaningfulContent = content !== undefined && content.trim() !== ""
|
||||
const finalContent = hasMeaningfulContent ? content : hasToolCalls ? null : undefined
|
||||
|
||||
const consolidatedReasoningDetails =
|
||||
reasoningDetails.length > 0 ? consolidateReasoningDetails(reasoningDetails as any) : []
|
||||
|
||||
openAiMessages.push({
|
||||
role: "assistant",
|
||||
content: finalContent,
|
||||
// Cannot be an empty array. API expects an array with minimum length 1, and will respond with an error if it's empty
|
||||
tool_calls: tool_calls?.length > 0 ? tool_calls : undefined,
|
||||
// Only include reasoning_details when non-empty; sending [] can trigger provider validation issues.
|
||||
// @ts-ignore-next-line
|
||||
reasoning_details: consolidatedReasoningDetails.length > 0 ? consolidatedReasoningDetails : undefined,
|
||||
reasoning_details: reasoningDetails.length > 0 ? consolidateReasoningDetails(reasoningDetails) : undefined,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -256,11 +245,6 @@ function consolidateReasoningDetails(reasoningDetails: ReasoningDetail[]): Reaso
|
||||
const groupedByIndex = new Map<number, ReasoningDetail[]>()
|
||||
|
||||
for (const detail of reasoningDetails) {
|
||||
// Drop corrupted encrypted reasoning blocks that would otherwise trigger:
|
||||
// "Invalid input: expected string, received undefined" for reasoning_details.*.data
|
||||
// See: https://github.com/cline/cline/issues/8214
|
||||
if (detail.type === "reasoning.encrypted" && !detail.data) continue
|
||||
|
||||
const index = detail.index ?? 0
|
||||
if (!groupedByIndex.has(index)) {
|
||||
groupedByIndex.set(index, [])
|
||||
|
||||
@@ -36,46 +36,6 @@ export async function createOpenRouterStream(
|
||||
model.id = model.id.slice(0, -CLAUDE_SONNET_1M_SUFFIX.length)
|
||||
}
|
||||
|
||||
// Gemini models require thought signatures for tool calls. When switching providers mid-conversation,
|
||||
// historical tool calls may not include Gemini/OpenRouter reasoning details, which can poison the next request.
|
||||
// Bandaid: for Gemini only, drop tool_calls that lack reasoning_details and their paired tool messages.
|
||||
if (model.id.includes("gemini")) {
|
||||
const droppedToolCallIds = new Set<string>()
|
||||
const sanitized: OpenAI.Chat.ChatCompletionMessageParam[] = []
|
||||
|
||||
for (const msg of openAiMessages) {
|
||||
if (msg.role === "assistant") {
|
||||
const anyMsg = msg as any
|
||||
const toolCalls = anyMsg.tool_calls
|
||||
if (Array.isArray(toolCalls) && toolCalls.length > 0) {
|
||||
const reasoningDetails = anyMsg.reasoning_details
|
||||
const hasReasoningDetails = Array.isArray(reasoningDetails) && reasoningDetails.length > 0
|
||||
if (!hasReasoningDetails) {
|
||||
for (const tc of toolCalls) {
|
||||
if (tc?.id) droppedToolCallIds.add(tc.id)
|
||||
}
|
||||
// Keep any textual content, but drop the tool_calls themselves.
|
||||
if (anyMsg.content) {
|
||||
sanitized.push({ role: "assistant", content: anyMsg.content } as any)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.role === "tool") {
|
||||
const anyMsg = msg as any
|
||||
if (anyMsg.tool_call_id && droppedToolCallIds.has(anyMsg.tool_call_id)) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
sanitized.push(msg)
|
||||
}
|
||||
|
||||
openAiMessages = sanitized
|
||||
}
|
||||
|
||||
// prompt caching: https://openrouter.ai/docs/prompt-caching
|
||||
// this was initially specifically for claude models (some models may 'support prompt caching' automatically without this)
|
||||
// handles direct model.id match logic
|
||||
|
||||
@@ -954,7 +954,6 @@ export class Controller {
|
||||
subagentsEnabled,
|
||||
nativeToolCallSetting: this.stateManager.getGlobalStateKey("nativeToolCallEnabled"),
|
||||
enableParallelToolCalling: this.stateManager.getGlobalSettingsKey("enableParallelToolCalling"),
|
||||
backgroundEditEnabled: this.stateManager.getGlobalSettingsKey("backgroundEditEnabled"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import fs from "node:fs/promises"
|
||||
import path from "node:path"
|
||||
import { ensureCacheDirectoryExists, GlobalFileNames } from "@core/storage/disk"
|
||||
import { ANTHROPIC_MAX_THINKING_BUDGET, ModelInfo } from "@shared/api"
|
||||
import { ModelInfo } from "@shared/api"
|
||||
import { fileExistsAtPath } from "@utils/fs"
|
||||
import { parsePrice } from "@utils/model-utils"
|
||||
import axios from "axios"
|
||||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
import { getAxiosSettings } from "@/shared/net"
|
||||
import { basetenModels } from "../../../shared/api"
|
||||
import { Controller } from ".."
|
||||
@@ -22,7 +22,22 @@ export async function refreshBasetenModels(controller: Controller): Promise<Reco
|
||||
|
||||
const models: Record<string, Partial<ModelInfo> & { supportedFeatures?: string[] }> = {}
|
||||
try {
|
||||
if (basetenApiKey) {
|
||||
if (!basetenApiKey) {
|
||||
// Don't throw an error, just use static models, althought this might be slightly out of date
|
||||
for (const [modelId, modelInfo] of Object.entries(basetenModels)) {
|
||||
models[modelId] = {
|
||||
maxTokens: modelInfo.maxTokens,
|
||||
contextWindow: modelInfo.contextWindow,
|
||||
supportsImages: modelInfo.supportsImages,
|
||||
supportsPromptCache: modelInfo.supportsPromptCache,
|
||||
inputPrice: modelInfo.inputPrice,
|
||||
outputPrice: modelInfo.outputPrice,
|
||||
cacheWritesPrice: (modelInfo as any).cacheWritesPrice || 0,
|
||||
cacheReadsPrice: (modelInfo as any).cacheReadsPrice || 0,
|
||||
description: (modelInfo as any).description || `${modelId} model`,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Ensure the API key is properly formatted
|
||||
const cleanApiKey = basetenApiKey.trim()
|
||||
if (!cleanApiKey) {
|
||||
@@ -39,9 +54,9 @@ export async function refreshBasetenModels(controller: Controller): Promise<Reco
|
||||
...getAxiosSettings(),
|
||||
})
|
||||
|
||||
const rawModels = response?.data?.data
|
||||
if (response.data?.data) {
|
||||
const rawModels = response.data.data
|
||||
|
||||
if (rawModels && Array.isArray(rawModels)) {
|
||||
for (const rawModel of rawModels) {
|
||||
// Filter out non-chat models and validate model capabilities
|
||||
if (!isValidChatModel(rawModel)) {
|
||||
@@ -50,9 +65,6 @@ export async function refreshBasetenModels(controller: Controller): Promise<Reco
|
||||
|
||||
// Check if we have static pricing information for this model
|
||||
const staticModelInfo = basetenModels[rawModel.id as keyof typeof basetenModels]
|
||||
const supportThinking = rawModel?.supported_features?.some(
|
||||
(p: string) => p === "reasoning_effort" || p === "reasoning",
|
||||
)
|
||||
|
||||
const modelInfo: Partial<ModelInfo> & { supportedFeatures?: string[] } = {
|
||||
maxTokens: rawModel.max_completion_tokens || staticModelInfo?.maxTokens,
|
||||
@@ -65,23 +77,15 @@ export async function refreshBasetenModels(controller: Controller): Promise<Reco
|
||||
cacheReadsPrice: staticModelInfo?.cacheReadsPrice || 0,
|
||||
description: generateModelDescription(rawModel, staticModelInfo),
|
||||
supportedFeatures: rawModel.supported_features || [],
|
||||
supportsReasoning: supportThinking || false,
|
||||
// If thinking is supported, set maxBudget with a default value as a placeholder
|
||||
// to ensure it has a valid thinkingConfig that lets the application know thinking is supported.
|
||||
thinkingConfig: supportThinking ? { maxBudget: ANTHROPIC_MAX_THINKING_BUDGET } : undefined,
|
||||
}
|
||||
|
||||
models[rawModel.id] = modelInfo
|
||||
}
|
||||
} else {
|
||||
console.error("Invalid response from Baseten API")
|
||||
}
|
||||
// Cache the fetched models to disk
|
||||
await fs.writeFile(basetenModelsFilePath, JSON.stringify(models))
|
||||
}
|
||||
|
||||
// If no API key is set or models is empty, throw an error to trigger fallback
|
||||
if (Object.keys(models).length === 0) {
|
||||
throw new Error("No Baseten API key set or no models fetched")
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching Baseten models:", error)
|
||||
|
||||
@@ -125,8 +129,6 @@ export async function refreshBasetenModels(controller: Controller): Promise<Reco
|
||||
cacheWritesPrice: (modelInfo as any).cacheWritesPrice || 0,
|
||||
cacheReadsPrice: (modelInfo as any).cacheReadsPrice || 0,
|
||||
description: (modelInfo as any).description || `${modelId} model`,
|
||||
supportsReasoning: modelInfo.supportsReasoning || false,
|
||||
thinkingConfig: modelInfo.supportsReasoning ? { maxBudget: ANTHROPIC_MAX_THINKING_BUDGET } : undefined,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,8 +149,6 @@ export async function refreshBasetenModels(controller: Controller): Promise<Reco
|
||||
cacheReadsPrice: model.cacheReadsPrice ?? 0,
|
||||
description: model.description ?? "",
|
||||
tiers: model.tiers,
|
||||
supportsReasoning: model.supportsReasoning || false,
|
||||
thinkingConfig: model.supportsReasoning ? { maxBudget: ANTHROPIC_MAX_THINKING_BUDGET } : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -320,10 +320,6 @@ export async function updateSettings(controller: Controller, request: UpdateSett
|
||||
}
|
||||
}
|
||||
|
||||
if (request.backgroundEditEnabled !== undefined) {
|
||||
controller.stateManager.setGlobalState("backgroundEditEnabled", !!request.backgroundEditEnabled)
|
||||
}
|
||||
|
||||
if (request.autoCondenseThreshold !== undefined) {
|
||||
const threshold = Math.min(1, Math.max(0, request.autoCondenseThreshold)) // Clamp to 0-1 range
|
||||
controller.stateManager.setGlobalState("autoCondenseThreshold", threshold)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { buildApiHandler } from "@core/api"
|
||||
import { isBinaryFile } from "isbinaryfile"
|
||||
import { HostProvider } from "@/hosts/host-provider"
|
||||
import { formatContentBlockToMarkdown } from "@/integrations/misc/export-markdown"
|
||||
import { ApiConfiguration } from "@/shared/api"
|
||||
@@ -444,29 +443,9 @@ const BINARY_EXTENSIONS = new Set([
|
||||
])
|
||||
|
||||
/**
|
||||
* Check if a file is binary based on its extension or content.
|
||||
* @param filePath - Absolute path to the file to check
|
||||
* @returns Promise<boolean> - true if the file is binary, false if text or if detection fails
|
||||
* Check if a file is binary based on its extension
|
||||
*/
|
||||
export async function detectBinaryFile(filePath: string): Promise<boolean> {
|
||||
const lastDotIndex = filePath.lastIndexOf(".")
|
||||
const lastSlashIndex = Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\"))
|
||||
const ext = lastDotIndex > lastSlashIndex ? filePath.substring(lastDotIndex).toLowerCase() : ""
|
||||
const isDotfile = lastDotIndex !== -1 && lastDotIndex === lastSlashIndex + 1
|
||||
|
||||
// Legacy/fast method: Check known binary extensions
|
||||
if (ext && BINARY_EXTENSIONS.has(ext)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Use actual binary check for dotfiles or files without extensions. Returns true if file is binary.
|
||||
if (!ext || isDotfile) {
|
||||
try {
|
||||
const result = await isBinaryFile(filePath)
|
||||
return result
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
export function isBinaryFile(filePath: string): boolean {
|
||||
const ext = filePath.substring(filePath.lastIndexOf(".")).toLowerCase()
|
||||
return BINARY_EXTENSIONS.has(ext)
|
||||
}
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
* @returns true if hooks are enabled and supported on this platform, false otherwise
|
||||
*/
|
||||
export function getHooksEnabledSafe(userSetting: boolean | undefined): boolean {
|
||||
// Handle legacy object format: {user: boolean, featureFlag: boolean}, which
|
||||
// can occur if the migration hasn't run yet or if reading from an old state.
|
||||
const booleanValue = Boolean((userSetting as any)?.user ?? userSetting)
|
||||
|
||||
// Force hooks to false on Windows (not yet supported)
|
||||
return process.platform === "win32" ? false : booleanValue
|
||||
return process.platform === "win32" ? false : (userSetting ?? false)
|
||||
}
|
||||
|
||||
+2
-3
@@ -2,7 +2,7 @@ You are Cline, a highly skilled software engineer with extensive knowledge in ma
|
||||
|
||||
TOOL USE
|
||||
|
||||
You have access to a set of tools that are executed upon the user's approval. You will receive the results of all tool uses in the user's response.
|
||||
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
|
||||
|
||||
====
|
||||
|
||||
@@ -68,8 +68,7 @@ When user is providing you with feedback on how you could improve, you can let t
|
||||
|
||||
RULES
|
||||
|
||||
- The current working directory is `/test/project` - this is the directory where all the tools will be executed from. Then if you want to test your work, you might use browser_action to launch the site, wait for the user's response confirming the site was launched along with a screenshot, then perhaps e.g., click a button to test functionality if needed, wait for the user's response confirming the button was clicked along with a screenshot of the new state, before finally closing the browser.
|
||||
- MCP operations should be used one at a time, similar to other tool usage. Wait for confirmation of success before proceeding with additional operations.
|
||||
- The current working directory is `/test/project` - this is the directory where all the tools will be executed from.
|
||||
|
||||
====
|
||||
|
||||
|
||||
+1
-2
@@ -2,7 +2,7 @@ You are Cline, a highly skilled software engineer with extensive knowledge in ma
|
||||
|
||||
TOOL USE
|
||||
|
||||
You have access to a set of tools that are executed upon the user's approval. You will receive the results of all tool uses in the user's response.
|
||||
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
|
||||
|
||||
====
|
||||
|
||||
@@ -67,7 +67,6 @@ When user is providing you with feedback on how you could improve, you can let t
|
||||
RULES
|
||||
|
||||
- The current working directory is `/test/project` - this is the directory where all the tools will be executed from.
|
||||
- MCP operations should be used one at a time, similar to other tool usage. Wait for confirmation of success before proceeding with additional operations.
|
||||
|
||||
====
|
||||
|
||||
|
||||
+2
-3
@@ -2,7 +2,7 @@ You are Cline, a highly skilled software engineer with extensive knowledge in ma
|
||||
|
||||
TOOL USE
|
||||
|
||||
You have access to a set of tools that are executed upon the user's approval. You will receive the results of all tool uses in the user's response.
|
||||
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
|
||||
|
||||
====
|
||||
|
||||
@@ -42,8 +42,7 @@ CAPABILITIES
|
||||
|
||||
RULES
|
||||
|
||||
- The current working directory is `/test/project` - this is the directory where all the tools will be executed from. Then if you want to test your work, you might use browser_action to launch the site, wait for the user's response confirming the site was launched along with a screenshot, then perhaps e.g., click a button to test functionality if needed, wait for the user's response confirming the button was clicked along with a screenshot of the new state, before finally closing the browser.
|
||||
- MCP operations should be used one at a time, similar to other tool usage. Wait for confirmation of success before proceeding with additional operations.
|
||||
- The current working directory is `/test/project` - this is the directory where all the tools will be executed from.
|
||||
|
||||
====
|
||||
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ You are Cline, a highly skilled software engineer with extensive knowledge in ma
|
||||
|
||||
TOOL USE
|
||||
|
||||
You have access to a set of tools that are executed upon the user's approval. You will receive the results of all tool uses in the user's response.
|
||||
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
|
||||
|
||||
====
|
||||
|
||||
@@ -68,7 +68,7 @@ When user is providing you with feedback on how you could improve, you can let t
|
||||
|
||||
RULES
|
||||
|
||||
- The current working directory is `/test/project` - this is the directory where all the tools will be executed from. Then if you want to test your work, you might use browser_action to launch the site, wait for the user's response confirming the site was launched along with a screenshot, then perhaps e.g., click a button to test functionality if needed, wait for the user's response confirming the button was clicked along with a screenshot of the new state, before finally closing the browser.
|
||||
- The current working directory is `/test/project` - this is the directory where all the tools will be executed from.
|
||||
|
||||
====
|
||||
|
||||
|
||||
@@ -608,6 +608,7 @@ RULES
|
||||
- When using the replace_in_file tool, if you use multiple SEARCH/REPLACE blocks, list them in the order they appear in the file. For example if you need to make changes to both line 10 and line 50, first include the SEARCH/REPLACE block for line 10, followed by the SEARCH/REPLACE block for line 50.
|
||||
- When using the replace_in_file tool, Do NOT add extra characters to the markers (e.g., ------- SEARCH> is INVALID). Do NOT forget to use the closing +++++++ REPLACE marker. Do NOT modify the marker format in any way. Malformed XML will cause complete tool failure and break the entire editing process.
|
||||
- You may use multiple tools in a single response when the operations are independent (e.g., reading several files, creating independent files). For dependent operations where one result informs the next, use tools sequentially and wait for the user's response. Then if you want to test your work, you might use browser_action to launch the site, wait for the user's response confirming the site was launched along with a screenshot, then perhaps e.g., click a button to test functionality if needed, wait for the user's response confirming the button was clicked along with a screenshot of the new state, before finally closing the browser.
|
||||
- MCP operations should be used one at a time, similar to other tool usage. Wait for confirmation of success before proceeding with additional operations.
|
||||
|
||||
====
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ You are Cline, a software engineering AI. Your mission is to execute precisely w
|
||||
|
||||
TOOL USE
|
||||
|
||||
You have access to a set of tools that are executed upon the user's approval. You should use a single tool at a time and wait for the result before proceeding. You will receive the results of all tool uses in the user's response.
|
||||
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
|
||||
|
||||
When using tools, proceed directly with tool calls. Save explanations for the attempt_completion summary. Both attempt_completion and plan_mode_respond display to the user as assistant messages, so include your message content within the tool call itself rather than duplicating it outside.
|
||||
|
||||
@@ -240,7 +240,7 @@ OBJECTIVE
|
||||
You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.
|
||||
|
||||
1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order.
|
||||
2. Work through these goals sequentially, utilizing available tools as necessary. Use a single tool at a time and wait for the result before proceeding. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go.
|
||||
2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go.
|
||||
3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Then, think about which of the provided tools is the most relevant tool to accomplish the user's task. Next, go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. If one of the values for a required parameter is missing, ask the user to provide the missing parameters using the ask_followup_question tool (use your tools to gather information when possible to avoid unnecessary questions). Focus on required parameters only - proceed with defaults for optional parameters.
|
||||
4. Once you've completed the user's task, use the attempt_completion tool to present the result. Provide a CLI command to showcase your work when applicable (e.g., `open index.html` for web development). Before calling attempt_completion, verify with the user that the feature works as expected.
|
||||
5. For non-actionable tasks, use attempt_completion to provide a clear explanation or direct answer.
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ You are Cline, a software engineering AI. Your mission is to execute precisely w
|
||||
|
||||
TOOL USE
|
||||
|
||||
You have access to a set of tools that are executed upon the user's approval. You should use a single tool at a time and wait for the result before proceeding. You will receive the results of all tool uses in the user's response.
|
||||
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
|
||||
|
||||
When using tools, proceed directly with tool calls. Save explanations for the attempt_completion summary. Both attempt_completion and plan_mode_respond display to the user as assistant messages, so include your message content within the tool call itself rather than duplicating it outside.
|
||||
|
||||
@@ -238,7 +238,7 @@ OBJECTIVE
|
||||
You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.
|
||||
|
||||
1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order.
|
||||
2. Work through these goals sequentially, utilizing available tools as necessary. Use a single tool at a time and wait for the result before proceeding. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go.
|
||||
2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go.
|
||||
3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Then, think about which of the provided tools is the most relevant tool to accomplish the user's task. Next, go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. If one of the values for a required parameter is missing, ask the user to provide the missing parameters using the ask_followup_question tool (use your tools to gather information when possible to avoid unnecessary questions). Focus on required parameters only - proceed with defaults for optional parameters.
|
||||
4. Once you've completed the user's task, use the attempt_completion tool to present the result. Provide a CLI command to showcase your work when applicable (e.g., `open index.html` for web development). Before calling attempt_completion, verify with the user that the feature works as expected.
|
||||
5. For non-actionable tasks, use attempt_completion to provide a clear explanation or direct answer.
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ You are Cline, a software engineering AI. Your mission is to execute precisely w
|
||||
|
||||
TOOL USE
|
||||
|
||||
You have access to a set of tools that are executed upon the user's approval. You should use a single tool at a time and wait for the result before proceeding. You will receive the results of all tool uses in the user's response.
|
||||
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
|
||||
|
||||
When using tools, proceed directly with tool calls. Save explanations for the attempt_completion summary. Both attempt_completion and plan_mode_respond display to the user as assistant messages, so include your message content within the tool call itself rather than duplicating it outside.
|
||||
|
||||
@@ -218,7 +218,7 @@ OBJECTIVE
|
||||
You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.
|
||||
|
||||
1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order.
|
||||
2. Work through these goals sequentially, utilizing available tools as necessary. Use a single tool at a time and wait for the result before proceeding. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go.
|
||||
2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go.
|
||||
3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Then, think about which of the provided tools is the most relevant tool to accomplish the user's task. Next, go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. If one of the values for a required parameter is missing, ask the user to provide the missing parameters using the ask_followup_question tool (use your tools to gather information when possible to avoid unnecessary questions). Focus on required parameters only - proceed with defaults for optional parameters.
|
||||
4. Once you've completed the user's task, use the attempt_completion tool to present the result. Provide a CLI command to showcase your work when applicable (e.g., `open index.html` for web development). Before calling attempt_completion, verify with the user that the feature works as expected.
|
||||
5. For non-actionable tasks, use attempt_completion to provide a clear explanation or direct answer.
|
||||
|
||||
@@ -2,7 +2,7 @@ You are Cline, a software engineering AI. Your mission is to execute precisely w
|
||||
|
||||
TOOL USE
|
||||
|
||||
You have access to a set of tools that are executed upon the user's approval. You should use a single tool at a time and wait for the result before proceeding. You will receive the results of all tool uses in the user's response.
|
||||
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
|
||||
|
||||
When using tools, proceed directly with tool calls. Save explanations for the attempt_completion summary. Both attempt_completion and plan_mode_respond display to the user as assistant messages, so include your message content within the tool call itself rather than duplicating it outside.
|
||||
|
||||
@@ -240,7 +240,7 @@ OBJECTIVE
|
||||
You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.
|
||||
|
||||
1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order.
|
||||
2. Work through these goals sequentially, utilizing available tools as necessary. Use a single tool at a time and wait for the result before proceeding. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go.
|
||||
2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go.
|
||||
3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Then, think about which of the provided tools is the most relevant tool to accomplish the user's task. Next, go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. If one of the values for a required parameter is missing, ask the user to provide the missing parameters using the ask_followup_question tool (use your tools to gather information when possible to avoid unnecessary questions). Focus on required parameters only - proceed with defaults for optional parameters.
|
||||
4. Once you've completed the user's task, use the attempt_completion tool to present the result. Provide a CLI command to showcase your work when applicable (e.g., `open index.html` for web development). Before calling attempt_completion, verify with the user that the feature works as expected.
|
||||
5. For non-actionable tasks, use attempt_completion to provide a clear explanation or direct answer.
|
||||
|
||||
@@ -3,23 +3,6 @@ import { SystemPromptSection } from "../templates/placeholders"
|
||||
import { TemplateEngine } from "../templates/TemplateEngine"
|
||||
import type { PromptVariant, SystemPromptContext } from "../types"
|
||||
|
||||
/**
|
||||
* Checks if there are any enabled MCP servers in the context.
|
||||
* This is a utility function to standardize MCP server detection across all prompt variants.
|
||||
*
|
||||
* @param context - The system prompt context
|
||||
* @returns true if there are enabled MCP servers, false otherwise
|
||||
*
|
||||
* @example
|
||||
* const hasMcp = hasEnabledMcpServers(context)
|
||||
* if (hasMcp) {
|
||||
* // Include MCP-specific instructions
|
||||
* }
|
||||
*/
|
||||
export function hasEnabledMcpServers(context: SystemPromptContext): boolean {
|
||||
return (context.mcpHub?.getServers() || []).length > 0
|
||||
}
|
||||
|
||||
const MCP_TEMPLATE_TEXT = `MCP SERVERS
|
||||
|
||||
The Model Context Protocol (MCP) enables communication between the system and locally running MCP servers that provide additional tools and resources to extend your capabilities.
|
||||
|
||||
@@ -14,24 +14,6 @@ Default Shell: {{shell}}
|
||||
Home Directory: {{homeDir}}
|
||||
{{WORKSPACE_TITLE}}: {{workingDir}}`
|
||||
|
||||
/**
|
||||
* Get the shell that will actually be used for command execution.
|
||||
* When using background exec mode, commands run in the system default shell
|
||||
* (cmd.exe on Windows, /bin/bash on Unix), not the VS Code configured shell.
|
||||
*/
|
||||
function getEffectiveShell(context: SystemPromptContext): string {
|
||||
if (context.terminalExecutionMode === "backgroundExec") {
|
||||
// Background exec uses the system default shell, not VS Code config
|
||||
if (process.platform === "win32") {
|
||||
return process.env.COMSPEC || "cmd.exe"
|
||||
} else {
|
||||
return process.env.SHELL || "/bin/bash"
|
||||
}
|
||||
}
|
||||
// VS Code terminal mode (or undefined) uses the VS Code configured shell
|
||||
return getShell()
|
||||
}
|
||||
|
||||
export async function getSystemEnv(context: SystemPromptContext, isTesting = false) {
|
||||
const currentWorkDir = context.cwd || process.cwd()
|
||||
const workspaces = (await getWorkspacePaths({}))?.paths || [currentWorkDir]
|
||||
@@ -48,7 +30,7 @@ export async function getSystemEnv(context: SystemPromptContext, isTesting = fal
|
||||
: {
|
||||
os: osName(),
|
||||
ide: context.ide,
|
||||
shell: getEffectiveShell(context),
|
||||
shell: getShell(),
|
||||
homeDir: osModule.homedir(),
|
||||
workingDir: currentWorkDir,
|
||||
workspaces: workspaces,
|
||||
|
||||
@@ -115,8 +115,6 @@ export interface SystemPromptContext {
|
||||
readonly isSubagentsEnabledAndCliInstalled?: boolean
|
||||
readonly isCliSubagent?: boolean
|
||||
readonly enableNativeToolCalls?: boolean
|
||||
readonly enableParallelToolCalling?: boolean
|
||||
readonly terminalExecutionMode?: "vscodeTerminal" | "backgroundExec"
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,9 +4,9 @@ import type { PromptVariant, SystemPromptContext } from "../../types"
|
||||
const GEMINI_3_AGENT_ROLE_TEMPLATE = (_context: SystemPromptContext) =>
|
||||
`You are Cline, a software engineering AI. Your mission is to execute precisely what is requested - implement exactly what was asked for, with the simplest solution that fulfills all requirements. Ask clarifying questions to ensure you understand the user's requirements and that they understand your approach before proceeding.`
|
||||
|
||||
const GEMINI_3_TOOL_USE_TEMPLATE = (context: SystemPromptContext) => `TOOL USE
|
||||
const GEMINI_3_TOOL_USE_TEMPLATE = (_context: SystemPromptContext) => `TOOL USE
|
||||
|
||||
You have access to a set of tools that are executed upon the user's approval.${context.enableParallelToolCalling ? " You may use multiple tools in a single response when the operations are independent (e.g., reading several files, searching in parallel). For dependent operations where one result informs the next, use tools sequentially." : " You should use a single tool at a time and wait for the result before proceeding."} You will receive the results of all tool uses in the user's response.
|
||||
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
|
||||
|
||||
When using tools, proceed directly with tool calls. Save explanations for the attempt_completion summary. Both attempt_completion and plan_mode_respond display to the user as assistant messages, so include your message content within the tool call itself rather than duplicating it outside.`
|
||||
|
||||
@@ -15,7 +15,7 @@ const GEMINI_3_OBJECTIVE_TEMPLATE = (context: SystemPromptContext) => `OBJECTIVE
|
||||
You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.
|
||||
|
||||
1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order.
|
||||
2. Work through these goals sequentially, utilizing available tools as necessary. ${context.enableParallelToolCalling ? "You may call multiple independent tools in a single response to work efficiently." : "Use a single tool at a time and wait for the result before proceeding."} Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go.
|
||||
2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go.
|
||||
3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Then, think about which of the provided tools is the most relevant tool to accomplish the user's task. Next, go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use.${context.yoloModeToggled !== true ? " If one of the values for a required parameter is missing, ask the user to provide the missing parameters using the ask_followup_question tool (use your tools to gather information when possible to avoid unnecessary questions)." : ""} Focus on required parameters only - proceed with defaults for optional parameters.
|
||||
4. Once you've completed the user's task, use the attempt_completion tool to present the result. Provide a CLI command to showcase your work when applicable (e.g., \`open index.html\` for web development).${context.yoloModeToggled !== true ? " Before calling attempt_completion, verify with the user that the feature works as expected." : ""}
|
||||
5. For non-actionable tasks, use attempt_completion to provide a clear explanation or direct answer.
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { hasEnabledMcpServers } from "../../components/mcp"
|
||||
import { SystemPromptSection } from "../../templates/placeholders"
|
||||
import type { SystemPromptContext } from "../../types"
|
||||
|
||||
const GLM_TOOL_USE_TEMPLATE = (context: SystemPromptContext) => {
|
||||
const hasMcpServers = hasEnabledMcpServers(context)
|
||||
const hasMcpServers = (context.mcpHub?.getServers() || []).length > 0
|
||||
|
||||
return `Begin every task by exploring the codebase (e.g., list_files, search_files, read_file) and outlining the required changes. Do not implement until exploration yields enough context to state objectives, approach, affected files, and risks. Briefly summarize the plan, then proceed with implementation.
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { hasEnabledMcpServers } from "../../components/mcp"
|
||||
import { SystemPromptSection } from "../../templates/placeholders"
|
||||
import type { SystemPromptContext } from "../../types"
|
||||
|
||||
@@ -78,7 +77,8 @@ const RULES = (context: SystemPromptContext) => `RULES
|
||||
- When using the replace_in_file tool, you must include complete lines in your SEARCH blocks, not partial lines. The system requires exact line matches and cannot match partial lines. For example, if you want to match a line containing "const x = 5;", your SEARCH block must include the entire line, not just "x = 5" or other fragments.
|
||||
- When using the replace_in_file tool, if you use multiple SEARCH/REPLACE blocks, list them in the order they appear in the file. For example if you need to make changes to both line 10 and line 50, first include the SEARCH/REPLACE block for line 10, followed by the SEARCH/REPLACE block for line 50.
|
||||
- When using the replace_in_file tool, Do NOT add extra characters to the markers (e.g., ------- SEARCH> is INVALID). Do NOT forget to use the closing +++++++ REPLACE marker. Do NOT modify the marker format in any way. Malformed XML will cause complete tool failure and break the entire editing process.
|
||||
- You may use multiple tools in a single response when the operations are independent (e.g., reading several files, creating independent files). For dependent operations where one result informs the next, use tools sequentially and wait for the user's response.{{BROWSER_WAIT_RULES}}${hasEnabledMcpServers(context) ? "\n- MCP operations should be used one at a time, similar to other tool usage. Wait for confirmation of success before proceeding with additional operations." : ""}`
|
||||
- You may use multiple tools in a single response when the operations are independent (e.g., reading several files, creating independent files). For dependent operations where one result informs the next, use tools sequentially and wait for the user's response.{{BROWSER_WAIT_RULES}}
|
||||
- MCP operations should be used one at a time, similar to other tool usage. Wait for confirmation of success before proceeding with additional operations.`
|
||||
|
||||
export const GPT_5_TEMPLATE_OVERRIDES = {
|
||||
BASE,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { hasEnabledMcpServers } from "../../components/mcp"
|
||||
import { SystemPromptSection } from "../../templates/placeholders"
|
||||
import type { SystemPromptContext } from "../../types"
|
||||
|
||||
@@ -49,22 +48,13 @@ export const BASE = `{{${SystemPromptSection.AGENT_ROLE}}}
|
||||
|
||||
{{${SystemPromptSection.USER_INSTRUCTIONS}}}`
|
||||
|
||||
const RULES = (context: SystemPromptContext) => {
|
||||
const hasMcpServers = hasEnabledMcpServers(context)
|
||||
const RULES = (_context: SystemPromptContext) => `RULES
|
||||
|
||||
return `RULES
|
||||
- The current working directory is \`{{CWD}}\` - this is the directory where all the tools will be executed from.`
|
||||
|
||||
- The current working directory is \`{{CWD}}\` - this is the directory where all the tools will be executed from.${
|
||||
context.enableParallelToolCalling
|
||||
? `
|
||||
- You may use multiple tools in a single response when the operations are independent (e.g., reading several files, creating independent files). For dependent operations where one result informs the next, use tools sequentially and wait for the user's response.`
|
||||
: ""
|
||||
}{{BROWSER_WAIT_RULES}}${hasMcpServers ? "\n- MCP operations should be used one at a time, similar to other tool usage. Wait for confirmation of success before proceeding with additional operations." : ""}`
|
||||
}
|
||||
const TOOL_USE = (_context: SystemPromptContext) => `TOOL USE
|
||||
|
||||
const TOOL_USE = (context: SystemPromptContext) => `TOOL USE
|
||||
|
||||
You have access to a set of tools that are executed upon the user's approval.${context.enableParallelToolCalling ? " You may use multiple tools in a single response when the operations are independent (e.g., reading several files, searching in parallel). For dependent operations where one result informs the next, use tools sequentially." : ""} You will receive the results of all tool uses in the user's response.`
|
||||
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.`
|
||||
|
||||
const ACT_VS_PLAN = (context: SystemPromptContext) => `ACT MODE V.S. PLAN MODE
|
||||
|
||||
@@ -89,7 +79,7 @@ const OBJECTIVE = (context: SystemPromptContext) => `OBJECTIVE
|
||||
You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.
|
||||
|
||||
1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order.
|
||||
2. Work through these goals sequentially, utilizing available tools ${context.enableParallelToolCalling ? "as necessary. You may call multiple independent tools in a single response to work efficiently." : "one at a time as necessary."} Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go.
|
||||
2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go.
|
||||
3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Then, think about which of the provided tools is the most relevant tool to accomplish the user's task. Next, go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params)${context.yoloModeToggled !== true ? " and instead, ask the user to provide the missing parameters using the ask_followup_question tool" : ""}. DO NOT ask for more information on optional parameters if it is not provided.
|
||||
4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. \`open index.html\` to show the website you've built.
|
||||
5. If the task is not actionable, you may use the attempt_completion tool to explain to the user why the task cannot be completed, or provide a simple answer if that is what the user is looking for.`
|
||||
|
||||
@@ -322,8 +322,6 @@ export async function readGlobalStateFromDisk(context: ExtensionContext): Promis
|
||||
const openTelemetryLogMaxQueueSize =
|
||||
context.globalState.get<GlobalStateAndSettings["openTelemetryLogMaxQueueSize"]>("openTelemetryLogMaxQueueSize")
|
||||
const subagentsEnabled = context.globalState.get<GlobalStateAndSettings["subagentsEnabled"]>("subagentsEnabled")
|
||||
const backgroundEditEnabled =
|
||||
context.globalState.get<GlobalStateAndSettings["backgroundEditEnabled"]>("backgroundEditEnabled")
|
||||
|
||||
// Get mode-related configurations
|
||||
const mode = context.globalState.get<GlobalStateAndSettings["mode"]>("mode")
|
||||
@@ -684,7 +682,6 @@ export async function readGlobalStateFromDisk(context: ExtensionContext): Promis
|
||||
qwenCodeOauthPath,
|
||||
customPrompt,
|
||||
autoCondenseThreshold: autoCondenseThreshold || 0.75, // default to 0.75 if not set
|
||||
backgroundEditEnabled: backgroundEditEnabled ?? false,
|
||||
// Hooks require explicit user opt-in and are only supported on macOS/Linux
|
||||
hooksEnabled: getHooksEnabledSafe(hooksEnabled),
|
||||
subagentsEnabled: subagentsEnabled ?? false,
|
||||
|
||||
+23
-21
@@ -69,16 +69,12 @@ import Mutex from "p-mutex"
|
||||
import pWaitFor from "p-wait-for"
|
||||
import * as path from "path"
|
||||
import { ulid } from "ulid"
|
||||
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 { FileEditProvider } from "@/integrations/editor/FileEditProvider"
|
||||
import {
|
||||
CommandExecutor,
|
||||
CommandExecutorCallbacks,
|
||||
FullCommandExecutorConfig,
|
||||
StandaloneTerminalManager,
|
||||
} from "@/integrations/terminal"
|
||||
import { CommandExecutorCallbacks, StandaloneTerminalManager } from "@/integrations/terminal"
|
||||
import { CommandExecutor, FullCommandExecutorConfig } from "@/integrations/terminal/CommandExecutor"
|
||||
import { ClineError, ClineErrorType, ErrorService } from "@/services/error"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import {
|
||||
@@ -276,6 +272,7 @@ export class Task {
|
||||
this.cancelTask = cancelTask
|
||||
this.clineIgnoreController = new ClineIgnoreController(cwd)
|
||||
this.taskLockAcquired = taskLockAcquired
|
||||
|
||||
// Determine terminal execution mode and create appropriate terminal manager
|
||||
this.terminalExecutionMode = vscodeTerminalExecutionMode || "vscodeTerminal"
|
||||
|
||||
@@ -299,16 +296,12 @@ export class Task {
|
||||
this.urlContentFetcher = new UrlContentFetcher(controller.context)
|
||||
this.browserSession = new BrowserSession(stateManager)
|
||||
this.contextManager = new ContextManager()
|
||||
this.diffViewProvider = HostProvider.get().createDiffViewProvider()
|
||||
this.streamHandler = new StreamResponseHandler()
|
||||
this.cwd = cwd
|
||||
this.stateManager = stateManager
|
||||
this.workspaceManager = workspaceManager
|
||||
|
||||
// DiffViewProvider opens Diff Editor during edits while FileEditProvider performs
|
||||
// edits in the background without stealing user's editor's focus.
|
||||
const backgroundEditEnabled = this.stateManager.getGlobalSettingsKey("backgroundEditEnabled")
|
||||
this.diffViewProvider = backgroundEditEnabled ? new FileEditProvider() : HostProvider.get().createDiffViewProvider()
|
||||
|
||||
// Set up MCP notification callback for real-time notifications
|
||||
this.mcpHub.setNotificationCallback(async (serverName: string, _level: string, message: string) => {
|
||||
// Display notification in chat immediately
|
||||
@@ -513,7 +506,7 @@ export class Task {
|
||||
},
|
||||
updateBackgroundCommandState: (isRunning: boolean) =>
|
||||
this.controller.updateBackgroundCommandState(isRunning, this.taskId),
|
||||
updateClineMessage: async (index: number, updates: { commandCompleted?: boolean; text?: string }) => {
|
||||
updateClineMessage: async (index: number, updates: { commandCompleted?: boolean }) => {
|
||||
await this.messageStateHandler.updateClineMessage(index, updates)
|
||||
},
|
||||
getClineMessages: () => this.messageStateHandler.getClineMessages() as Array<{ ask?: string; say?: string }>,
|
||||
@@ -1607,6 +1600,21 @@ export class Task {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrates the disableBrowserTool setting from VSCode configuration to browserSettings
|
||||
*/
|
||||
private async migrateDisableBrowserToolSetting(): Promise<void> {
|
||||
const config = vscode.workspace.getConfiguration("cline")
|
||||
const disableBrowserTool = config.get<boolean>("disableBrowserTool")
|
||||
|
||||
if (disableBrowserTool !== undefined) {
|
||||
const browserSettings = this.stateManager.getGlobalSettingsKey("browserSettings")
|
||||
browserSettings.disableToolUse = disableBrowserTool
|
||||
// Remove from VSCode configuration
|
||||
await config.update("disableBrowserTool", undefined, true)
|
||||
}
|
||||
}
|
||||
|
||||
private getCurrentProviderInfo(): ApiProviderInfo {
|
||||
const model = this.api.getModel()
|
||||
const apiConfig = this.stateManager.getApiConfiguration()
|
||||
@@ -1697,6 +1705,7 @@ export class Task {
|
||||
|
||||
const providerInfo = this.getCurrentProviderInfo()
|
||||
const ide = (await HostProvider.env.getHostVersion({})).platform || "Unknown"
|
||||
await this.migrateDisableBrowserToolSetting()
|
||||
const browserSettings = this.stateManager.getGlobalSettingsKey("browserSettings")
|
||||
const disableBrowserTool = browserSettings.disableToolUse ?? false
|
||||
// cline browser tool uses image recognition for navigation (requires model image support).
|
||||
@@ -1783,8 +1792,6 @@ export class Task {
|
||||
isSubagentsEnabledAndCliInstalled,
|
||||
isCliSubagent,
|
||||
enableNativeToolCalls: this.stateManager.getGlobalStateKey("nativeToolCallEnabled"),
|
||||
enableParallelToolCalling: this.stateManager.getGlobalSettingsKey("enableParallelToolCalling"),
|
||||
terminalExecutionMode: this.terminalExecutionMode,
|
||||
}
|
||||
|
||||
const { systemPrompt, tools } = await getSystemPrompt(promptContext)
|
||||
@@ -2218,12 +2225,7 @@ export class Task {
|
||||
|
||||
// Now, if it's the first request AND checkpoints are enabled AND tracker was successfully initialized,
|
||||
// then say "checkpoint_created" and perform the commit.
|
||||
if (
|
||||
isFirstRequest &&
|
||||
this.stateManager.getGlobalSettingsKey("enableCheckpointsSetting") &&
|
||||
this.checkpointManager &&
|
||||
!this.taskState.checkpointManagerErrorMessage
|
||||
) {
|
||||
if (isFirstRequest && this.stateManager.getGlobalSettingsKey("enableCheckpointsSetting") && this.checkpointManager) {
|
||||
await this.say("checkpoint_created") // Now this is conditional
|
||||
const lastCheckpointMessageIndex = findLastIndex(
|
||||
this.messageStateHandler.getClineMessages(),
|
||||
|
||||
@@ -43,6 +43,10 @@ export class ApplyPatchHandler implements IFullyManagedTool {
|
||||
private config?: TaskConfig
|
||||
private pathResolver?: PathResolver
|
||||
private providerOps?: FileProviderOperations
|
||||
private partialPreviewState?: {
|
||||
originalFiles: Record<string, string>
|
||||
currentPreviewPath?: string
|
||||
}
|
||||
|
||||
constructor(private validator: ToolValidator) {}
|
||||
|
||||
@@ -81,11 +85,19 @@ export class ApplyPatchHandler implements IFullyManagedTool {
|
||||
}
|
||||
}
|
||||
|
||||
private ensurePartialPreviewState(): { originalFiles: Record<string, string>; currentPreviewPath?: string } {
|
||||
if (!this.partialPreviewState) {
|
||||
this.partialPreviewState = { originalFiles: {} }
|
||||
}
|
||||
return this.partialPreviewState
|
||||
}
|
||||
|
||||
private async previewPatchStream(rawInput: string, uiHelpers: StronglyTypedUIHelpers): Promise<void> {
|
||||
const config = uiHelpers.getConfig()
|
||||
const provider = config.services.diffViewProvider
|
||||
this.initializeHelpers(config)
|
||||
|
||||
const state = this.ensurePartialPreviewState()
|
||||
const lines = this.stripBashWrapper(rawInput.split("\n"))
|
||||
|
||||
// Extract the first operation path and type
|
||||
@@ -199,6 +211,12 @@ export class ApplyPatchHandler implements IFullyManagedTool {
|
||||
if (stream.content === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await provider.update(stream.content, false)
|
||||
} catch {
|
||||
// Ignore streaming errors
|
||||
}
|
||||
}
|
||||
|
||||
async execute(config: TaskConfig, block: ToolUse): Promise<ToolResponse> {
|
||||
@@ -220,6 +238,7 @@ export class ApplyPatchHandler implements IFullyManagedTool {
|
||||
// Ignore reset errors
|
||||
}
|
||||
}
|
||||
this.partialPreviewState = undefined
|
||||
|
||||
try {
|
||||
const lines = this.preprocessLines(rawInput)
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { ToolUse } from "@core/assistant-message"
|
||||
import {
|
||||
buildDiffContent,
|
||||
type ChangedFile,
|
||||
detectBinaryFile,
|
||||
isBinaryFile,
|
||||
openDiffView,
|
||||
setupCommentController,
|
||||
streamAIExplanationComments,
|
||||
@@ -160,7 +160,7 @@ export class GenerateExplanationToolHandler implements IToolHandler, IPartialBlo
|
||||
const absolutePath = path.join(cwd, filePath)
|
||||
|
||||
// Skip binary files - they can't be displayed properly in diff view
|
||||
if (await detectBinaryFile(absolutePath)) {
|
||||
if (isBinaryFile(filePath)) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -415,11 +415,6 @@ export class WriteToFileToolHandler implements IFullyManagedTool {
|
||||
!block.partial, // Pass the partial flag correctly
|
||||
)
|
||||
} catch (error) {
|
||||
// As we set the didAlreadyUseTool flag when the tool has failed once, we don't want to add the error message to the
|
||||
// userMessages array again on each new streaming chunk received.
|
||||
if (!config.enableParallelToolCalling && config.taskState.didAlreadyUseTool) {
|
||||
return
|
||||
}
|
||||
// Full original behavior - comprehensive error handling even for partial blocks
|
||||
await config.callbacks.say("diff_error", relPath)
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -228,7 +228,7 @@ function createAuthSucceededHtml(redirectUri?: string): string {
|
||||
<title>Cline - Authentication Success</title>
|
||||
${redirect}
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Azeret:wght@300;400;700&display=swap');
|
||||
@import url('https://fonts.googleapis.com/css2?family=Azeret+Mono:wght@300;400;700&display=swap');
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
@@ -237,7 +237,7 @@ function createAuthSucceededHtml(redirectUri?: string): string {
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Azeret', sans-serif;
|
||||
font-family: 'Azeret Mono', monospace;
|
||||
background-color: #ffffff;
|
||||
color: #333333;
|
||||
height: 100vh;
|
||||
|
||||
+2
-6
@@ -1,15 +1,11 @@
|
||||
import * as vscode from "vscode"
|
||||
import { ErrorSettings } from "@/services/error"
|
||||
import { EmptyRequest } from "@/shared/proto/index.cline"
|
||||
import { GetTelemetrySettingsResponse, Setting } from "@/shared/proto/index.host"
|
||||
|
||||
export async function getTelemetrySettings(_: EmptyRequest): Promise<GetTelemetrySettingsResponse> {
|
||||
const config = vscode.workspace.getConfiguration("telemetry")
|
||||
const errorLevel = config?.get<ErrorSettings["level"]>("telemetryLevel") || "all"
|
||||
|
||||
if (vscode.env.isTelemetryEnabled) {
|
||||
return { isEnabled: Setting.ENABLED, errorLevel }
|
||||
return { isEnabled: Setting.ENABLED }
|
||||
} else {
|
||||
return { isEnabled: Setting.DISABLED, errorLevel }
|
||||
return { isEnabled: Setting.DISABLED }
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user