mirror of
https://github.com/cline/cline.git
synced 2026-09-02 07:42:19 +08:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a0a392d636 | |||
| 5fe80172ed | |||
| 9b0f2b82ef | |||
| c2c23054b9 | |||
| 3baaa5c8b4 | |||
| abafcc7290 | |||
| d82aa0add9 | |||
| abe4721a0b | |||
| 60d55b69a8 | |||
| d18e0271d3 | |||
| af71f9da90 | |||
| 2a1c8826aa | |||
| 9a54f2d246 | |||
| d928d58a40 | |||
| 31859b5fda | |||
| 0d5d89e8c7 | |||
| af34451eec | |||
| 027a4f6386 | |||
| 49642882c5 | |||
| 21ed6bc432 | |||
| da2689f885 | |||
| 5049326f02 | |||
| b02ce46a57 | |||
| de974737c8 | |||
| d072156e9a | |||
| 4939309a09 | |||
| 1a07ca7906 | |||
| c1eefbad3f | |||
| 1bfdce9b84 | |||
| b002cdacdb | |||
| cf4005b25e | |||
| 1494d145d5 | |||
| 1ab4b3cc24 | |||
| 535b653228 | |||
| 1335fa5452 | |||
| b2a4395f71 | |||
| ae34a3a8c5 |
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Fix task timeline display height.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Ensure tool arguments are streamed during file operations when native tool calling is enabled.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Feat: add thought signature support for Gemini SDK
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Skip MCP tool with invalid name (e.g. name too long) when native tool calling is enabled.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Fix Anthropic provider missing signature param when thinking is enabled.
|
||||
+26
-6
@@ -1,14 +1,34 @@
|
||||
# Changelog
|
||||
|
||||
## 3.37.1
|
||||
## [3.38.2]
|
||||
|
||||
- cf8dd1c: Comprehensive changes to better support GPT 5.1 - System prompt, tools, deep-planning, focus chain, etc.
|
||||
- 02abbcf: Add AGENTS.md support
|
||||
- 855db7d: feat(models): Add free minimax/mimax-m2 model to the model picker
|
||||
- Add Claude Opus 4.5
|
||||
|
||||
## [3.38.1]
|
||||
|
||||
### Fixed
|
||||
- Fixed handling of 'signature' field in sanitizeAnthropicContentBlock to properly preserve it when thinking is enabled, as required by Anthropic's API.
|
||||
|
||||
## [3.38.0]
|
||||
|
||||
### Added
|
||||
- Gemini 3 Pro Preview model
|
||||
- AquaVoice Avalon model for voice-to-text dictation
|
||||
|
||||
### Fixed
|
||||
- Automatic context truncation when AWS Bedrock token usage rate limits are exceeded
|
||||
- Removed new_task tool from system prompts, updated slash command prompts, and added helper function for native tool calling validation
|
||||
|
||||
|
||||
## [3.37.1]
|
||||
|
||||
- Comprehensive changes to better support GPT 5.1 - System prompt, tools, deep-planning, focus chain, etc.
|
||||
- Add AGENTS.md support
|
||||
- feat(models): Add free minimax/mimax-m2 model to the model picker
|
||||
|
||||
## [3.37.0]
|
||||
|
||||
## Added
|
||||
### Added
|
||||
|
||||
- GPT-5.1 with model-specific prompting: tailored system prompts, tool usage, focus chain, and deep-planning optimizations
|
||||
- Nous Research provider with Hermes 4 model family and custom system prompts
|
||||
@@ -18,7 +38,7 @@
|
||||
- Expanded HTTP proxy support throughout the codebase
|
||||
- Improved focus chain prompting for frontier models (Anthropic, OpenAI, Gemini, xAI)
|
||||
|
||||
## Fixed
|
||||
### Fixed
|
||||
|
||||
- Duplicate tool results prevention through existence checking
|
||||
- XML entity escaping in model content processor
|
||||
|
||||
@@ -517,7 +517,7 @@ func (pw *ProviderWizard) applyModelChange(provider cline.ApiProvider, modelID s
|
||||
ModelInfo: modelInfo,
|
||||
}
|
||||
|
||||
return UpdateProviderPartial(pw.ctx, pw.manager, provider, updates, false)
|
||||
return UpdateProviderPartial(pw.ctx, pw.manager, provider, updates, true)
|
||||
}
|
||||
|
||||
// SwitchToBYOProvider switches to a BYO provider that's already configured.
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
# Git
|
||||
.git
|
||||
.gitignore
|
||||
.gitattributes
|
||||
|
||||
# Node modules
|
||||
node_modules
|
||||
npm-debug.log
|
||||
|
||||
# Build artifacts
|
||||
dist
|
||||
dist-standalone
|
||||
build
|
||||
*.log
|
||||
|
||||
# Generated code
|
||||
src/generated
|
||||
|
||||
# CLI build artifacts
|
||||
cli/bin
|
||||
cli/dist
|
||||
|
||||
# Webview build artifacts
|
||||
webview-ui/dist
|
||||
webview-ui/build
|
||||
|
||||
# IDE
|
||||
.vscode
|
||||
.idea
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Documentation
|
||||
*.md
|
||||
!README.md
|
||||
|
||||
# Tests
|
||||
tests
|
||||
*.test.js
|
||||
*.spec.js
|
||||
|
||||
# CI/CD
|
||||
.github
|
||||
.gitlab-ci.yml
|
||||
@@ -1,49 +0,0 @@
|
||||
FROM node:22-slim
|
||||
|
||||
# TARGETARCH enables multi-architecture support without emulation warnings:
|
||||
# - Docker automatically sets TARGETARCH to the build platform's architecture
|
||||
# - On arm64 machines (Apple Silicon): TARGETARCH=arm64, uses linux-arm64 binaries
|
||||
# - On amd64 machines (Intel/AMD): TARGETARCH=amd64, uses linux-x64 binaries
|
||||
# The corresponding platform-specific binaries and native modules (better-sqlite3)
|
||||
# are pre-built by scripts/package-standalone.mjs during the build process.
|
||||
ARG TARGETARCH
|
||||
|
||||
# Install only runtime dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
git curl ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /opt/cline
|
||||
|
||||
# Copy the entire pre-built distribution
|
||||
COPY dist-standalone/ ./
|
||||
|
||||
# Create symlink for Linux native modules
|
||||
# Map Docker's TARGETARCH (arm64/amd64) to Node's platform naming (x64 for amd64)
|
||||
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
||||
ln -sf /opt/cline/binaries/linux-x64/node_modules/better-sqlite3 /opt/cline/node_modules/better-sqlite3; \
|
||||
else \
|
||||
ln -sf /opt/cline/binaries/linux-$TARGETARCH/node_modules/better-sqlite3 /opt/cline/node_modules/better-sqlite3; \
|
||||
fi
|
||||
|
||||
# Set up CLI binaries
|
||||
# The Linux binaries are already in /opt/cline/bin/ from dist-standalone
|
||||
# Just need to create symlinks to the platform-specific ones
|
||||
RUN cd /opt/cline/bin && \
|
||||
ln -sf cline-linux-$TARGETARCH cline && \
|
||||
ln -sf cline-host-linux-$TARGETARCH cline-host && \
|
||||
chmod +x cline-linux-$TARGETARCH cline-host-linux-$TARGETARCH cline cline-host
|
||||
|
||||
# Add binaries to PATH
|
||||
ENV PATH="/opt/cline/bin:${PATH}"
|
||||
ENV NODE_ENV=production
|
||||
ENV CLINE_HOME=/root/.cline
|
||||
|
||||
RUN mkdir -p $CLINE_HOME
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
ENTRYPOINT ["/opt/cline/bin/cline"]
|
||||
CMD ["--help"]
|
||||
Generated
+6
-34
@@ -5146,28 +5146,6 @@
|
||||
"node": ">=6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/gray-matter/node_modules/argparse": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/gray-matter/node_modules/js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/has-bigints": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
|
||||
@@ -6490,9 +6468,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
@@ -10235,12 +10213,6 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/stack-utils": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
|
||||
@@ -10609,9 +10581,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tar-fs": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.0.tgz",
|
||||
"integrity": "sha512-5Mty5y/sOF1YWj1J6GiBodjlDc05CUR8PKXrsnFAiSG0xA+GHeWLovaZPYUDXkH/1iKRf2+M5+OrRgzC7O9b7w==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz",
|
||||
"integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"pump": "^3.0.0",
|
||||
|
||||
@@ -14,5 +14,9 @@
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"mintlify": "^4.2.23"
|
||||
},
|
||||
"overrides": {
|
||||
"tar-fs": "^3.1.1",
|
||||
"js-yaml": "^4.1.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ description: "Learn how to configure and use Anthropic Claude models with Cline.
|
||||
Cline supports the following Anthropic Claude models:
|
||||
|
||||
- `claude-haiku-4-5-20251001`
|
||||
- `claude-opus-4-5-20251101`
|
||||
- `claude-opus-4-1-20250805`
|
||||
- `claude-opus-4-20250514`
|
||||
- `anthropic/claude-sonnet-4.5` (Recommended)
|
||||
|
||||
Generated
-1422
File diff suppressed because it is too large
Load Diff
+46
-45
@@ -1,47 +1,48 @@
|
||||
{
|
||||
"name": "cline-evals",
|
||||
"version": "0.1.0",
|
||||
"description": "Evaluation scripts and tools for Cline",
|
||||
"main": "cli/dist/index.js",
|
||||
"scripts": {
|
||||
"build:cli": "cd cli && tsc",
|
||||
"start:cli": "cd cli && node dist/index.js",
|
||||
"dev:cli": "cd cli && ts-node src/index.ts",
|
||||
"diff-eval": "./diff-edits/run_and_open_dashboard.sh",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"cline",
|
||||
"evaluation",
|
||||
"benchmark",
|
||||
"diff-edits"
|
||||
],
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"axios": "^1.12.0",
|
||||
"better-sqlite3": "^12.4.1",
|
||||
"chalk": "5.6.2",
|
||||
"dotenv": "^16.5.0",
|
||||
"commander": "^9.4.1",
|
||||
"execa": "^5.1.1",
|
||||
"node-fetch": "^2.7.0",
|
||||
"ora": "^5.4.1",
|
||||
"sqlite": "^4.1.2",
|
||||
"tiktoken": "^1.0.21",
|
||||
"uuid": "^9.0.0",
|
||||
"yargs": "^17.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/better-sqlite3": "^7.6.3",
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/node-fetch": "^2.6.12",
|
||||
"@types/uuid": "^9.0.0",
|
||||
"@types/yargs": "^17.0.19",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.9.4"
|
||||
},
|
||||
"overrides": {
|
||||
"tar-fs": "^3.1.1"
|
||||
}
|
||||
"name": "cline-evals",
|
||||
"version": "0.1.0",
|
||||
"description": "Evaluation scripts and tools for Cline",
|
||||
"main": "cli/dist/index.js",
|
||||
"scripts": {
|
||||
"build:cli": "cd cli && tsc",
|
||||
"start:cli": "cd cli && node dist/index.js",
|
||||
"dev:cli": "cd cli && ts-node src/index.ts",
|
||||
"diff-eval": "./diff-edits/run_and_open_dashboard.sh",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"cline",
|
||||
"evaluation",
|
||||
"benchmark",
|
||||
"diff-edits"
|
||||
],
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"axios": "^1.12.0",
|
||||
"better-sqlite3": "^12.4.1",
|
||||
"chalk": "5.6.2",
|
||||
"dotenv": "^16.5.0",
|
||||
"commander": "^9.4.1",
|
||||
"execa": "^5.1.1",
|
||||
"node-fetch": "^2.7.0",
|
||||
"ora": "^5.4.1",
|
||||
"sqlite": "^4.1.2",
|
||||
"tiktoken": "^1.0.21",
|
||||
"uuid": "^9.0.0",
|
||||
"yargs": "^17.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/better-sqlite3": "^7.6.3",
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/node-fetch": "^2.6.12",
|
||||
"@types/uuid": "^9.0.0",
|
||||
"@types/yargs": "^17.0.19",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.9.4"
|
||||
},
|
||||
"overrides": {
|
||||
"tar-fs": "^3.1.1",
|
||||
"js-yaml": "^4.1.1"
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+402
-910
File diff suppressed because it is too large
Load Diff
+8
-9
@@ -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.37.1",
|
||||
"version": "3.38.2",
|
||||
"icon": "assets/icons/icon.png",
|
||||
"engines": {
|
||||
"vscode": "^1.84.0"
|
||||
@@ -306,8 +306,6 @@
|
||||
"compile-cli-all-platforms": "scripts/build-cli-all-platforms.sh",
|
||||
"compile-cli-man-page": "pandoc cli/man/cline.1.md -s -t man -o cli/man/cline.1",
|
||||
"build:npm": "scripts/build-npm-package.sh",
|
||||
"build:docker:dev": "node scripts/build-docker-dev.mjs",
|
||||
"docker:shell": "node scripts/docker-shell.mjs",
|
||||
"test:install": "bash scripts/test-install.sh",
|
||||
"dev:cli:watch": "node scripts/dev-cli-watch.mjs",
|
||||
"postcompile-standalone": "node scripts/package-standalone.mjs",
|
||||
@@ -419,7 +417,7 @@
|
||||
"@bufbuild/protobuf": "^2.2.5",
|
||||
"@cerebras/cerebras_cloud_sdk": "^1.35.0",
|
||||
"@google-cloud/vertexai": "^1.9.3",
|
||||
"@google/genai": "^1.11.0",
|
||||
"@google/genai": "^1.30.0",
|
||||
"@grpc/grpc-js": "^1.9.15",
|
||||
"@grpc/reflection": "^1.0.4",
|
||||
"@mistralai/mistralai": "^1.5.0",
|
||||
@@ -444,8 +442,8 @@
|
||||
"@opentelemetry/sdk-trace-node": "^1.30.1",
|
||||
"@opentelemetry/semantic-conventions": "^1.37.0",
|
||||
"@playwright/test": "^1.55.1",
|
||||
"@sap-ai-sdk/ai-api": "^1.17.0",
|
||||
"@sap-ai-sdk/orchestration": "^1.17.0",
|
||||
"@sap-ai-sdk/ai-api": "^2.1.0",
|
||||
"@sap-ai-sdk/orchestration": "^2.1.0",
|
||||
"@sentry/browser": "^9.12.0",
|
||||
"@streamparser/json": "^0.0.22",
|
||||
"@tailwindcss/vite": "^4.1.14",
|
||||
@@ -463,7 +461,6 @@
|
||||
"exceljs": "^4.4.0",
|
||||
"execa": "^9.5.2",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"firebase": "^11.2.0",
|
||||
"fzf": "^0.5.2",
|
||||
"get-folder-size": "^5.0.0",
|
||||
"globby": "^14.0.2",
|
||||
@@ -473,7 +470,6 @@
|
||||
"image-size": "^2.0.2",
|
||||
"isbinaryfile": "^5.0.2",
|
||||
"jschardet": "^3.1.4",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"mammoth": "^1.11.0",
|
||||
"nanoid": "^5.1.6",
|
||||
"nice-grpc": "^2.1.12",
|
||||
@@ -506,7 +502,10 @@
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"overrides": {
|
||||
"tar-fs": ">=3.1.1"
|
||||
"tar-fs": ">=3.1.1",
|
||||
"tar": "^7.5.2",
|
||||
"vite": "^7.1.11",
|
||||
"js-yaml": "^4.1.1"
|
||||
},
|
||||
"c8": {
|
||||
"reporter": [
|
||||
|
||||
@@ -97,6 +97,7 @@ message OpenRouterModelInfo {
|
||||
optional bool supports_global_endpoint = 11;
|
||||
repeated ModelTier tiers = 12;
|
||||
optional string name = 13;
|
||||
optional double temperature = 14;
|
||||
}
|
||||
|
||||
// Shared response message for model information
|
||||
|
||||
+15
-1
@@ -362,7 +362,7 @@ message UpdateSettingsRequest {
|
||||
optional int32 subagent_terminal_output_line_limit = 30;
|
||||
optional string cline_env = 31;
|
||||
optional bool native_tool_call_enabled = 32;
|
||||
optional bool show_onboarding_flow = 33;
|
||||
optional OnboardingModelGroup onboarding_models = 33;
|
||||
}
|
||||
|
||||
message UpdateTerminalConnectionTimeoutRequest {
|
||||
@@ -390,3 +390,17 @@ message OnboardingProgressRequest {
|
||||
optional bool completed = 3;
|
||||
optional string model_selected = 4;
|
||||
}
|
||||
|
||||
message OnboardingModelGroup {
|
||||
repeated OnboardingModel models = 1;
|
||||
}
|
||||
|
||||
message OnboardingModel {
|
||||
string id = 1;
|
||||
string name = 2;
|
||||
int32 score = 3;
|
||||
int32 latency = 4;
|
||||
string badge = 5;
|
||||
string group = 6;
|
||||
OpenRouterModelInfo info = 7;
|
||||
}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { execSync } from "child_process"
|
||||
|
||||
/**
|
||||
* Build Docker image for Cline CLI
|
||||
* This script builds a Docker image using pre-built binaries from dist-standalone/
|
||||
*
|
||||
* Prerequisites:
|
||||
* - Run `npm run compile-standalone` first to build all platform binaries
|
||||
* - Run `npm run compile-cli` first to build CLI binaries
|
||||
*/
|
||||
|
||||
function runCommand(command, description) {
|
||||
console.log(`\n${description}...`)
|
||||
try {
|
||||
execSync(command, { stdio: "inherit" })
|
||||
console.log("✓ Success\n")
|
||||
} catch (error) {
|
||||
console.error(`✗ Failed: ${error.message}`)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
function getCommandOutput(command) {
|
||||
try {
|
||||
return execSync(command, { encoding: "utf-8" }).trim()
|
||||
} catch (error) {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
function buildPrerequisites() {
|
||||
console.log("Building prerequisites...\n")
|
||||
|
||||
// Build standalone (includes cline-core and platform-specific native modules)
|
||||
runCommand("npm run compile-standalone", "Running npm run compile-standalone")
|
||||
|
||||
// Build CLI binaries for all platforms
|
||||
runCommand("npm run compile-cli-all-platforms", "Running npm run compile-cli-all-platforms")
|
||||
|
||||
console.log("✓ All prerequisites built successfully\n")
|
||||
}
|
||||
|
||||
function main() {
|
||||
console.log("🐳 Building Cline CLI Docker Image\n")
|
||||
|
||||
// Remove existing container to ensure clean state after rebuild
|
||||
const containerId = getCommandOutput(`docker ps -aq --filter "name=^cline-cli-dev$"`)
|
||||
if (containerId) {
|
||||
console.log("🗑️ Removing existing container to ensure fresh start...")
|
||||
try {
|
||||
execSync(`docker rm -f cline-cli-dev`, { stdio: "inherit" })
|
||||
console.log("✓ Container removed\n")
|
||||
} catch (error) {
|
||||
console.log("Note: Container cleanup failed, continuing anyway\n")
|
||||
}
|
||||
}
|
||||
|
||||
buildPrerequisites()
|
||||
|
||||
// Build Docker image for native platform
|
||||
// Docker will automatically use the correct architecture (arm64 on Apple Silicon, amd64 on Intel)
|
||||
runCommand("docker build -f docker/Dockerfile -t cline-cli:dev .", "Building Docker image")
|
||||
|
||||
console.log("✅ Docker image built successfully!")
|
||||
console.log("\n📋 Next steps:\n")
|
||||
console.log("Interactive shell:")
|
||||
console.log(" npm run docker:shell\n")
|
||||
console.log("This will:")
|
||||
console.log(" • Reuse existing 'cline-cli-dev' container if running")
|
||||
console.log(" • Start stopped container if it exists")
|
||||
console.log(" • Create new persistent container if none exists")
|
||||
console.log(" • Mount current directory at /workspace")
|
||||
console.log(" • Provide all CLI commands (cline auth, cline task, etc.)")
|
||||
console.log("\nContainer persists between sessions. To remove:")
|
||||
console.log(" docker rm -f cline-cli-dev\n")
|
||||
}
|
||||
|
||||
main()
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { execSync } from "child_process"
|
||||
import { platform } from "os"
|
||||
|
||||
const CONTAINER_NAME = "cline-cli-dev"
|
||||
|
||||
function runCommand(command) {
|
||||
try {
|
||||
return execSync(command, { encoding: "utf-8" }).trim()
|
||||
} catch (error) {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentDirectory() {
|
||||
// Get current working directory in a cross-platform way
|
||||
return process.cwd()
|
||||
}
|
||||
|
||||
function main() {
|
||||
console.log("🐳 Cline CLI Docker Shell\n")
|
||||
|
||||
// Check if container exists (running or stopped)
|
||||
const containerId = runCommand(`docker ps -a --filter "name=^${CONTAINER_NAME}$" --format "{{.ID}}"`)
|
||||
|
||||
if (containerId) {
|
||||
// Check if container is running
|
||||
const isRunning = runCommand(`docker ps --filter "id=${containerId}" --format "{{.ID}}"`)
|
||||
|
||||
if (isRunning) {
|
||||
console.log(`📦 Connecting to running container: ${CONTAINER_NAME}\n`)
|
||||
try {
|
||||
execSync(`docker exec -it ${containerId} /bin/bash`, { stdio: "inherit" })
|
||||
} catch (error) {
|
||||
// User exited shell normally
|
||||
}
|
||||
} else {
|
||||
console.log(`▶️ Starting stopped container: ${CONTAINER_NAME}\n`)
|
||||
try {
|
||||
execSync(`docker start ${containerId}`, { stdio: "inherit" })
|
||||
execSync(`docker exec -it ${containerId} /bin/bash`, { stdio: "inherit" })
|
||||
} catch (error) {
|
||||
// User exited shell normally
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(`🚀 Creating new container: ${CONTAINER_NAME}\n`)
|
||||
const cwd = getCurrentDirectory()
|
||||
|
||||
try {
|
||||
// Use different volume mount syntax for Windows vs Unix
|
||||
const isWindows = platform() === "win32"
|
||||
const volumeMount = isWindows ? `${cwd.replace(/\\/g, "/")}:/workspace` : `${cwd}:/workspace`
|
||||
|
||||
execSync(
|
||||
`docker run -it --name ${CONTAINER_NAME} -v "${volumeMount}" -w /workspace --entrypoint /bin/bash cline-cli:dev`,
|
||||
{ stdio: "inherit" },
|
||||
)
|
||||
} catch (error) {
|
||||
// User exited shell normally
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
@@ -11,7 +11,7 @@ import fs from "fs"
|
||||
import https from "https"
|
||||
import path from "path"
|
||||
import { pipeline } from "stream/promises"
|
||||
import tar from "tar"
|
||||
import * as tar from "tar"
|
||||
import { promisify } from "util"
|
||||
import { createGunzip } from "zlib"
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ const TARGET_PLATFORMS = [
|
||||
{ platform: "darwin", arch: "x64", targetDir: "darwin-x64" },
|
||||
{ platform: "darwin", arch: "arm64", targetDir: "darwin-arm64" },
|
||||
{ platform: "linux", arch: "x64", targetDir: "linux-x64" },
|
||||
{ platform: "linux", arch: "arm64", targetDir: "linux-arm64" },
|
||||
]
|
||||
const SUPPORTED_BINARY_MODULES = ["better-sqlite3"]
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ModelInfo } from "@shared/api"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler } from "../../core/api/index"
|
||||
import { ApiStream } from "../../core/api/transform/stream"
|
||||
@@ -33,7 +33,7 @@ export class DifyHandler implements ApiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
console.log("[DIFY DEBUG] createMessage called with:", {
|
||||
systemPromptLength: systemPrompt?.length || 0,
|
||||
messagesCount: messages?.length || 0,
|
||||
@@ -255,7 +255,7 @@ export class DifyHandler implements ApiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private convertMessagesToQuery(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): string {
|
||||
private convertMessagesToQuery(systemPrompt: string, messages: ClineStorageMessage[]): string {
|
||||
// Dify's context is managed by `conversation_id`. The `query` should be the last user message.
|
||||
// The system prompt is typically configured in the Dify App itself.
|
||||
const lastUserMessage = messages.filter((m) => m.role === "user").pop()
|
||||
|
||||
@@ -9,14 +9,6 @@ export interface EnvironmentConfig {
|
||||
appBaseUrl: string
|
||||
apiBaseUrl: string
|
||||
mcpBaseUrl: string
|
||||
firebase: {
|
||||
apiKey: string
|
||||
authDomain: string
|
||||
projectId: string
|
||||
storageBucket?: string
|
||||
messagingSenderId?: string
|
||||
appId?: string
|
||||
}
|
||||
}
|
||||
|
||||
class ClineEndpoint {
|
||||
@@ -63,14 +55,6 @@ class ClineEndpoint {
|
||||
appBaseUrl: "https://staging-app.cline.bot",
|
||||
apiBaseUrl: "https://core-api.staging.int.cline.bot",
|
||||
mcpBaseUrl: "https://core-api.staging.int.cline.bot/v1/mcp",
|
||||
firebase: {
|
||||
apiKey: "AIzaSyASSwkwX1kSO8vddjZkE5N19QU9cVQ0CIk",
|
||||
authDomain: "cline-staging.firebaseapp.com",
|
||||
projectId: "cline-staging",
|
||||
storageBucket: "cline-staging.firebasestorage.app",
|
||||
messagingSenderId: "853479478430",
|
||||
appId: "1:853479478430:web:2de0dba1c63c3262d4578f",
|
||||
},
|
||||
}
|
||||
case Environment.local:
|
||||
return {
|
||||
@@ -78,11 +62,6 @@ class ClineEndpoint {
|
||||
appBaseUrl: "http://localhost:3000",
|
||||
apiBaseUrl: "http://localhost:7777",
|
||||
mcpBaseUrl: "https://api.cline.bot/v1/mcp",
|
||||
firebase: {
|
||||
apiKey: "AIzaSyD8wtkd1I-EICuAg6xgAQpRdwYTvwxZG2w",
|
||||
authDomain: "cline-preview.firebaseapp.com",
|
||||
projectId: "cline-preview",
|
||||
},
|
||||
}
|
||||
default:
|
||||
return {
|
||||
@@ -90,14 +69,6 @@ class ClineEndpoint {
|
||||
appBaseUrl: "https://app.cline.bot",
|
||||
apiBaseUrl: "https://api.cline.bot",
|
||||
mcpBaseUrl: "https://api.cline.bot/v1/mcp",
|
||||
firebase: {
|
||||
apiKey: "AIzaSyC5rx59Xt8UgwdU3PCfzUF7vCwmp9-K2vk",
|
||||
authDomain: "cline-prod.firebaseapp.com",
|
||||
projectId: "cline-prod",
|
||||
storageBucket: "cline-prod.firebasestorage.app",
|
||||
messagingSenderId: "941048379330",
|
||||
appId: "1:941048379330:web:45058eedeefc5cdfcc485b",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { afterEach, beforeEach, describe, it } from "mocha"
|
||||
import sinon from "sinon"
|
||||
import "should"
|
||||
import { ClaudeCodeHandler } from "@core/api/providers/claude-code"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
|
||||
describe("ClaudeCodeHandler", () => {
|
||||
let handler: ClaudeCodeHandler
|
||||
@@ -71,7 +71,7 @@ describe("ClaudeCodeHandler", () => {
|
||||
runClaudeCodeStub.returns(mockGenerator() as any)
|
||||
|
||||
const systemPrompt = "You are a helpful assistant."
|
||||
const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Hello" }]
|
||||
const messages: ClineStorageMessage[] = [{ role: "user", content: "Hello" }]
|
||||
|
||||
const usageData: any[] = []
|
||||
|
||||
@@ -140,7 +140,7 @@ describe("ClaudeCodeHandler", () => {
|
||||
runClaudeCodeStub.returns(mockGenerator() as any)
|
||||
|
||||
const systemPrompt = "You are a helpful assistant."
|
||||
const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Hello" }]
|
||||
const messages: ClineStorageMessage[] = [{ role: "user", content: "Hello" }]
|
||||
|
||||
const usageData: any[] = []
|
||||
|
||||
@@ -199,7 +199,7 @@ describe("ClaudeCodeHandler", () => {
|
||||
runClaudeCodeStub.returns(mockGenerator() as any)
|
||||
|
||||
const systemPrompt = "You are a helpful assistant."
|
||||
const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Hello" }]
|
||||
const messages: ClineStorageMessage[] = [{ role: "user", content: "Hello" }]
|
||||
|
||||
const usageData: any[] = []
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import Anthropic from "@anthropic-ai/sdk"
|
||||
import { LiteLlmHandler, type LiteLlmModelInfoResponse } from "@core/api/providers/litellm"
|
||||
import { convertToOpenAiMessages } from "@core/api/transform/openai-format"
|
||||
import { expect } from "chai"
|
||||
import sinon from "sinon"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { mockFetchForTesting } from "@/shared/net"
|
||||
|
||||
const fakeClient = {
|
||||
@@ -109,7 +109,7 @@ describe("LiteLlmHandler", () => {
|
||||
|
||||
it("sends the system prompt and messages with the openai format", async () => {
|
||||
const systemPrompt = "Test System Prompt"
|
||||
const messages: Anthropic.Messages.MessageParam[] = [
|
||||
const messages: ClineStorageMessage[] = [
|
||||
{
|
||||
role: "user",
|
||||
content: "first message",
|
||||
@@ -161,7 +161,7 @@ describe("LiteLlmHandler", () => {
|
||||
|
||||
it("inserts the cache control in the system prompt and the last two user messages", async () => {
|
||||
const systemPrompt = "Test System Prompt"
|
||||
const messages: Anthropic.Messages.MessageParam[] = [
|
||||
const messages: ClineStorageMessage[] = [
|
||||
{
|
||||
role: "user",
|
||||
content: "first message",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { afterEach, before, beforeEach, describe, it } from "mocha"
|
||||
import "should"
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ApiHandlerOptions } from "@shared/api"
|
||||
import axios from "axios"
|
||||
import sinon from "sinon"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { OllamaHandler } from "../ollama"
|
||||
|
||||
describe("OllamaHandler", () => {
|
||||
@@ -59,7 +59,7 @@ describe("OllamaHandler", () => {
|
||||
} as any)
|
||||
|
||||
const systemPrompt = "You are a helpful assistant."
|
||||
const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Hello" }]
|
||||
const messages: ClineStorageMessage[] = [{ role: "user", content: "Hello" }]
|
||||
|
||||
const result = []
|
||||
const usageInfo = []
|
||||
@@ -114,7 +114,7 @@ describe("OllamaHandler", () => {
|
||||
}
|
||||
|
||||
const systemPrompt = "You are a helpful assistant."
|
||||
const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Hello" }]
|
||||
const messages: ClineStorageMessage[] = [{ role: "user", content: "Hello" }]
|
||||
|
||||
// Start the request and catch the error
|
||||
let errorMessage = ""
|
||||
@@ -158,7 +158,7 @@ describe("OllamaHandler", () => {
|
||||
} as any)
|
||||
|
||||
const systemPrompt = "You are a helpful assistant."
|
||||
const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Hello" }]
|
||||
const messages: ClineStorageMessage[] = [{ role: "user", content: "Hello" }]
|
||||
|
||||
const result = []
|
||||
|
||||
@@ -204,7 +204,7 @@ describe("OllamaHandler", () => {
|
||||
}
|
||||
|
||||
const systemPrompt = "You are a helpful assistant."
|
||||
const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Hello" }]
|
||||
const messages: ClineStorageMessage[] = [{ role: "user", content: "Hello" }]
|
||||
|
||||
const result = []
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { Tool as AnthropicTool } from "@anthropic-ai/sdk/resources/index"
|
||||
import { Stream as AnthropicStream } from "@anthropic-ai/sdk/streaming"
|
||||
import { AnthropicModelId, anthropicDefaultModelId, anthropicModels, CLAUDE_SONNET_1M_SUFFIX, ModelInfo } from "@shared/api"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ClineTool } from "@/shared/tools"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../index"
|
||||
@@ -43,7 +44,7 @@ export class AnthropicHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: ClineTool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: ClineTool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
|
||||
const model = this.getModel()
|
||||
@@ -70,6 +71,7 @@ export class AnthropicHandler implements ApiHandler {
|
||||
case "claude-3-7-sonnet-20250219":
|
||||
case "claude-3-5-sonnet-20241022":
|
||||
case "claude-3-5-haiku-20241022":
|
||||
case "claude-opus-4-5-20251101":
|
||||
case "claude-opus-4-20250514":
|
||||
case "claude-opus-4-1-20250805":
|
||||
case "claude-3-opus-20240229":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { AskSageModelId, askSageDefaultModelId, askSageDefaultURL, askSageModels, ModelInfo } from "@shared/api"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from ".."
|
||||
import { withRetry } from "../retry"
|
||||
@@ -47,7 +47,7 @@ export class AskSageHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
try {
|
||||
const model = this.getModel()
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { BasetenModelId, basetenDefaultModelId, basetenModels, ModelInfo } from "@shared/api"
|
||||
import { calculateApiCostOpenAI } from "@utils/cost"
|
||||
import OpenAI from "openai"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -98,7 +98,7 @@ export class BasetenHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
const maxTokens = this.getOptimalMaxTokens(model)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
// Import proper AWS SDK types
|
||||
import type { ContentBlock, Message } from "@aws-sdk/client-bedrock-runtime"
|
||||
import {
|
||||
@@ -12,6 +11,7 @@ import { fromNodeProviderChain } from "@aws-sdk/credential-providers"
|
||||
import { BedrockModelId, bedrockDefaultModelId, bedrockModels, CLAUDE_SONNET_1M_SUFFIX, ModelInfo } from "@shared/api"
|
||||
import { calculateApiCostOpenAI, calculateApiCostQwen } from "@utils/cost"
|
||||
import { ExtensionRegistryInfo } from "@/registry"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
import { convertToR1Format } from "../transform/r1-format"
|
||||
@@ -121,7 +121,7 @@ export class AwsBedrockHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry({ maxRetries: 4 })
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
// cross region inference requires prefixing the model id with the region
|
||||
const rawModelId = await this.getModelId()
|
||||
|
||||
@@ -342,7 +342,7 @@ export class AwsBedrockHandler implements ApiHandler {
|
||||
*/
|
||||
private async *createDeepseekMessage(
|
||||
systemPrompt: string,
|
||||
messages: Anthropic.Messages.MessageParam[],
|
||||
messages: ClineStorageMessage[],
|
||||
modelId: string,
|
||||
model: { id: string; info: ModelInfo },
|
||||
): ApiStream {
|
||||
@@ -480,7 +480,7 @@ export class AwsBedrockHandler implements ApiHandler {
|
||||
* First uses convertToR1Format to merge consecutive messages with the same role,
|
||||
* then converts to the string format that DeepSeek R1 expects
|
||||
*/
|
||||
private formatDeepseekR1Prompt(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): string {
|
||||
private formatDeepseekR1Prompt(systemPrompt: string, messages: ClineStorageMessage[]): string {
|
||||
// First use convertToR1Format to merge consecutive messages with the same role
|
||||
const r1Messages = convertToR1Format([{ role: "user", content: systemPrompt }, ...messages])
|
||||
|
||||
@@ -513,7 +513,7 @@ export class AwsBedrockHandler implements ApiHandler {
|
||||
* Estimates token count based on text length (approximate)
|
||||
* Note: This is a rough estimation, as the actual token count depends on the tokenizer
|
||||
*/
|
||||
private estimateInputTokens(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): number {
|
||||
private estimateInputTokens(systemPrompt: string, messages: ClineStorageMessage[]): number {
|
||||
// For Deepseek R1, we estimate the token count of the formatted prompt
|
||||
// The formatted prompt includes special tokens and consistent formatting
|
||||
const formattedPrompt = this.formatDeepseekR1Prompt(systemPrompt, messages)
|
||||
@@ -680,11 +680,7 @@ export class AwsBedrockHandler implements ApiHandler {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error processing Converse API response:", error)
|
||||
yield {
|
||||
type: "text",
|
||||
text: `[ERROR] Failed to process response: ${error instanceof Error ? error.message : String(error)}`,
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,9 +699,20 @@ export class AwsBedrockHandler implements ApiHandler {
|
||||
text: `[ERROR] Model stream error: ${chunk.modelStreamErrorException.message}`,
|
||||
}
|
||||
} else if (chunk.validationException) {
|
||||
// Check if this is a context window error - if so, throw it
|
||||
// so the retry mechanism can handle truncation
|
||||
const message = chunk.validationException.message || ""
|
||||
const isContextError = /input.*too long|context.*exceed|maximum.*token|input length.*max.*tokens/i.test(message)
|
||||
|
||||
if (isContextError) {
|
||||
// Throw as exception so context management can handle it
|
||||
throw chunk.validationException
|
||||
}
|
||||
|
||||
// Otherwise yield as error text
|
||||
yield {
|
||||
type: "text",
|
||||
text: `[ERROR] Validation error: ${chunk.validationException.message}`,
|
||||
text: `[ERROR] Validation error: ${message}`,
|
||||
}
|
||||
} else if (chunk.throttlingException) {
|
||||
yield {
|
||||
@@ -779,7 +786,7 @@ export class AwsBedrockHandler implements ApiHandler {
|
||||
*/
|
||||
private async *createAnthropicMessage(
|
||||
systemPrompt: string,
|
||||
messages: Anthropic.Messages.MessageParam[],
|
||||
messages: ClineStorageMessage[],
|
||||
modelId: string,
|
||||
model: { id: string; info: ModelInfo },
|
||||
enable1mContextWindow: boolean,
|
||||
@@ -835,7 +842,7 @@ export class AwsBedrockHandler implements ApiHandler {
|
||||
* Formats messages for models using the Converse API specification
|
||||
* Used by both Anthropic and Nova models to avoid code duplication
|
||||
*/
|
||||
private formatMessagesForConverseAPI(messages: Anthropic.Messages.MessageParam[]): Message[] {
|
||||
private formatMessagesForConverseAPI(messages: ClineStorageMessage[]): Message[] {
|
||||
return messages.map((message) => {
|
||||
// Determine role (user or assistant)
|
||||
const role = message.role === "user" ? ConversationRole.USER : ConversationRole.ASSISTANT
|
||||
@@ -968,7 +975,7 @@ export class AwsBedrockHandler implements ApiHandler {
|
||||
*/
|
||||
private async *createNovaMessage(
|
||||
systemPrompt: string,
|
||||
messages: Anthropic.Messages.MessageParam[],
|
||||
messages: ClineStorageMessage[],
|
||||
modelId: string,
|
||||
model: { id: string; info: ModelInfo },
|
||||
): ApiStream {
|
||||
@@ -1008,7 +1015,7 @@ export class AwsBedrockHandler implements ApiHandler {
|
||||
*/
|
||||
private async *createOpenAIMessage(
|
||||
systemPrompt: string,
|
||||
messages: Anthropic.Messages.MessageParam[],
|
||||
messages: ClineStorageMessage[],
|
||||
modelId: string,
|
||||
model: { id: string; info: ModelInfo },
|
||||
): ApiStream {
|
||||
@@ -1143,7 +1150,7 @@ export class AwsBedrockHandler implements ApiHandler {
|
||||
*/
|
||||
private async *createQwenMessage(
|
||||
systemPrompt: string,
|
||||
messages: Anthropic.Messages.MessageParam[],
|
||||
messages: ClineStorageMessage[],
|
||||
modelId: string,
|
||||
model: { id: string; info: ModelInfo },
|
||||
): ApiStream {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import Cerebras from "@cerebras/cerebras_cloud_sdk"
|
||||
import { CerebrasModelId, cerebrasDefaultModelId, cerebrasModels, ModelInfo } from "@shared/api"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../index"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -46,7 +46,7 @@ export class CerebrasHandler implements ApiHandler {
|
||||
baseDelay: 5000, // Start with 5 second delay
|
||||
maxDelay: 60000, // Allow up to 60 second delays to respect rate limits
|
||||
})
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
|
||||
// Convert Anthropic messages to Cerebras format
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { filterMessagesForClaudeCode } from "@/integrations/claude-code/message-filter"
|
||||
import { runClaudeCode } from "@/integrations/claude-code/run"
|
||||
import { ClaudeCodeModelId, claudeCodeDefaultModelId, claudeCodeModels } from "@/shared/api"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { type ApiHandler, CommonApiHandlerOptions } from ".."
|
||||
import { withRetry } from "../retry"
|
||||
import { type ApiStream, ApiStreamUsageChunk } from "../transform/stream"
|
||||
@@ -24,7 +24,7 @@ export class ClaudeCodeHandler implements ApiHandler {
|
||||
baseDelay: 2000,
|
||||
maxDelay: 15000,
|
||||
})
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
// Filter out image blocks since Claude Code doesn't support them
|
||||
const filteredMessages = filterMessagesForClaudeCode(messages)
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ModelInfo, openRouterDefaultModelId, openRouterDefaultModelInfo } from "@shared/api"
|
||||
import { shouldSkipReasoningForModel } from "@utils/model-utils"
|
||||
import axios from "axios"
|
||||
@@ -9,6 +8,7 @@ import { ClineAccountService } from "@/services/account/ClineAccountService"
|
||||
import { AuthService } from "@/services/auth/AuthService"
|
||||
import { buildClineExtraHeaders } from "@/services/EnvUtils"
|
||||
import { CLINE_ACCOUNT_AUTH_ERROR_MESSAGE } from "@/shared/ClineAccount"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch, getAxiosSettings } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -96,7 +96,7 @@ export class ClineHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
try {
|
||||
const client = await this.ensureClient()
|
||||
|
||||
@@ -154,10 +154,12 @@ export class ClineHandler implements ApiHandler {
|
||||
type: "text",
|
||||
text: delta.content,
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (delta?.tool_calls) {
|
||||
yield* toolCallProcessor.processToolCallDeltas(delta.tool_calls)
|
||||
continue
|
||||
}
|
||||
|
||||
// Reasoning tokens are returned separately from the content
|
||||
@@ -167,6 +169,7 @@ export class ClineHandler implements ApiHandler {
|
||||
type: "reasoning",
|
||||
reasoning: typeof delta.reasoning === "string" ? delta.reasoning : JSON.stringify(delta.reasoning),
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -188,6 +191,7 @@ export class ClineHandler implements ApiHandler {
|
||||
reasoning: "",
|
||||
details: delta.reasoning_details,
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (!didOutputUsage && chunk.usage) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { DeepSeekModelId, deepSeekDefaultModelId, deepSeekModels, ModelInfo } from "@shared/api"
|
||||
import { calculateApiCostOpenAI } from "@utils/cost"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -75,7 +75,7 @@ export class DeepSeekHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ModelInfo } from "../../../shared/api"
|
||||
import { ApiHandler } from "../index"
|
||||
@@ -97,7 +97,7 @@ export class DifyHandler implements ApiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
console.log("[DIFY DEBUG] createMessage called with:", {
|
||||
systemPromptLength: systemPrompt?.length || 0,
|
||||
messagesCount: messages?.length || 0,
|
||||
@@ -384,7 +384,7 @@ export class DifyHandler implements ApiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private convertMessagesToQuery(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): string {
|
||||
private convertMessagesToQuery(systemPrompt: string, messages: ClineStorageMessage[]): string {
|
||||
// Dify's context is managed by `conversation_id`. The `query` should be the last user message.
|
||||
// The system prompt is typically configured in the Dify App itself.
|
||||
const lastUserMessage = messages.filter((m) => m.role === "user").pop()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { DoubaoModelId, doubaoDefaultModelId, doubaoModels, ModelInfo } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from ".."
|
||||
import { withRetry } from "../retry"
|
||||
@@ -50,7 +50,7 @@ export class DoubaoHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
const openAiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { FireworksModelId, fireworksDefaultModelId, fireworksModels, ModelInfo } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from ".."
|
||||
import { withRetry } from "../retry"
|
||||
@@ -41,7 +41,7 @@ export class FireworksHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const modelId = this.options.fireworksModelId ?? ""
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { Anthropic } from "@anthropic-ai/sdk"
|
||||
// Restore GenerateContentConfig import and add GenerateContentResponseUsageMetadata
|
||||
import {
|
||||
ApiError,
|
||||
@@ -7,10 +6,11 @@ import {
|
||||
type GenerateContentResponseUsageMetadata,
|
||||
GoogleGenAI,
|
||||
FunctionDeclaration as GoogleTool,
|
||||
Part,
|
||||
ThinkingLevel,
|
||||
} from "@google/genai"
|
||||
import { GeminiModelId, geminiDefaultModelId, geminiModels, ModelInfo } from "@shared/api"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { RetriableError, withRetry } from "../retry"
|
||||
import { convertAnthropicMessageToGemini } from "../transform/gemini-format"
|
||||
@@ -110,34 +110,45 @@ export class GeminiHandler implements ApiHandler {
|
||||
baseDelay: 2000,
|
||||
maxDelay: 15000,
|
||||
})
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: GoogleTool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: GoogleTool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const { id: modelId, info } = this.getModel()
|
||||
const contents = messages.map(convertAnthropicMessageToGemini)
|
||||
|
||||
// Configure thinking budget if supported
|
||||
const thinkingBudget = this.options.thinkingBudgetTokens ?? 0
|
||||
const _maxBudget = info.thinkingConfig?.maxBudget ?? 0
|
||||
const _thinkingBudget = this.options.thinkingBudgetTokens ?? 0
|
||||
const maxBudget = info.thinkingConfig?.maxBudget ?? 24576
|
||||
const thinkingBudget = Math.min(_thinkingBudget, maxBudget)
|
||||
const thinkLevel = info.thinkingConfig?.thinkingLevel
|
||||
// When ThinkingLevel is defineded, thinking budget cannot be zero
|
||||
// and only level is used to control thinking behavior.
|
||||
const thinkingLevel = thinkLevel ? (thinkLevel === "low" ? ThinkingLevel.LOW : ThinkingLevel.HIGH) : undefined
|
||||
|
||||
// Set up base generation config
|
||||
const requestConfig: GenerateContentConfig = {
|
||||
// Add base URL if configured
|
||||
httpOptions: this.options.geminiBaseUrl ? { baseUrl: this.options.geminiBaseUrl } : undefined,
|
||||
...{ systemInstruction: systemPrompt },
|
||||
systemInstruction: systemPrompt,
|
||||
// Set temperature (default to 0)
|
||||
temperature: 0,
|
||||
// Gemini 3.0 recommends 1.0
|
||||
temperature: info.temperature ?? 1,
|
||||
}
|
||||
|
||||
// Add thinking config if the model supports it
|
||||
if (thinkingBudget > 0) {
|
||||
requestConfig.thinkingConfig = {
|
||||
thinkingBudget: thinkingBudget,
|
||||
includeThoughts: true,
|
||||
}
|
||||
requestConfig.thinkingConfig = {
|
||||
// Turn off thinking:
|
||||
// thinkingBudget: 0
|
||||
// Turn on dynamic thinking:
|
||||
// thinkingBudget: -1
|
||||
// Turn on fixed thinking budget:
|
||||
thinkingBudget: thinkingLevel ? undefined : thinkingBudget,
|
||||
thinkingLevel,
|
||||
includeThoughts: thinkingBudget > 0,
|
||||
}
|
||||
|
||||
// Generate content using the configured parameters
|
||||
const sdkCallStartTime = Date.now()
|
||||
let responseId: string | undefined
|
||||
let sdkFirstChunkTime: number | undefined
|
||||
let ttftSdkMs: number | undefined
|
||||
let apiSuccess = false
|
||||
@@ -148,7 +159,8 @@ export class GeminiHandler implements ApiHandler {
|
||||
let thoughtsTokenCount = 0 // Initialize thought token counts
|
||||
let lastUsageMetadata: GenerateContentResponseUsageMetadata | undefined
|
||||
|
||||
if (tools?.length) {
|
||||
const isNativeToolCallsEnabled = tools?.length
|
||||
if (isNativeToolCallsEnabled) {
|
||||
requestConfig.tools = [{ functionDeclarations: tools }]
|
||||
requestConfig.toolConfig = {
|
||||
// Force the model to call 'any' function.
|
||||
@@ -176,56 +188,45 @@ export class GeminiHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
// Handle thinking content from Gemini's response
|
||||
const candidateForThoughts = chunk?.candidates?.[0]
|
||||
const partsForThoughts = candidateForThoughts?.content?.parts
|
||||
let thoughts = "" // Initialize as empty string
|
||||
|
||||
if (partsForThoughts) {
|
||||
// This ensures partsForThoughts is a Part[] array
|
||||
for (const part of partsForThoughts) {
|
||||
const { thought, text } = part as Part
|
||||
if (thought && text) {
|
||||
// Ensure part.text exists
|
||||
// Handle the thought part
|
||||
thoughts += text + "\n" // Append thought and a newline
|
||||
const parts = chunk?.candidates?.[0]?.content?.parts || []
|
||||
for (const part of parts) {
|
||||
if (part.thought && part.text) {
|
||||
yield {
|
||||
type: "reasoning",
|
||||
id: chunk.responseId,
|
||||
reasoning: part.text || "",
|
||||
signature: part.thoughtSignature,
|
||||
}
|
||||
} else if (part.text) {
|
||||
yield {
|
||||
type: "text",
|
||||
text: part.text,
|
||||
id: chunk.responseId,
|
||||
signature: part.thoughtSignature,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (thoughts.trim() !== "") {
|
||||
yield {
|
||||
type: "reasoning",
|
||||
reasoning: thoughts.trim(),
|
||||
}
|
||||
thoughts = "" // Reset thoughts after yielding
|
||||
}
|
||||
|
||||
if (chunk.text) {
|
||||
yield {
|
||||
type: "text",
|
||||
text: chunk.text,
|
||||
}
|
||||
}
|
||||
|
||||
if (tools && chunk.functionCalls && chunk.functionCalls?.length > 0) {
|
||||
for (const functionCall of chunk.functionCalls) {
|
||||
if (functionCall.args) {
|
||||
console.log("[GeminiHandler] tool call received:", functionCall)
|
||||
if (part.functionCall) {
|
||||
const functionCall = part.functionCall
|
||||
const args = Object.entries(functionCall.args || {}).filter(([_key, val]) => !!val)
|
||||
if (functionCall.args && args.length > 0) {
|
||||
yield {
|
||||
type: "tool_calls",
|
||||
id: chunk.responseId,
|
||||
tool_call: {
|
||||
function: {
|
||||
id: functionCall.id || functionCall.name,
|
||||
id: chunk.responseId,
|
||||
name: functionCall.name,
|
||||
arguments: JSON.stringify(functionCall.args),
|
||||
},
|
||||
},
|
||||
signature: part.thoughtSignature,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chunk.usageMetadata) {
|
||||
responseId = chunk.responseId
|
||||
lastUsageMetadata = chunk.usageMetadata
|
||||
promptTokens = lastUsageMetadata.promptTokenCount ?? promptTokens
|
||||
outputTokens = lastUsageMetadata.candidatesTokenCount ?? outputTokens
|
||||
@@ -251,6 +252,7 @@ export class GeminiHandler implements ApiHandler {
|
||||
cacheReadTokens,
|
||||
cacheWriteTokens: 0,
|
||||
totalCost,
|
||||
id: responseId,
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { GroqModelId, groqDefaultModelId, groqModels, ModelInfo } from "@shared/api"
|
||||
import { calculateApiCostOpenAI } from "@utils/cost"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -192,7 +192,7 @@ export class GroqHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
const modelFamily = this.detectModelFamily(model.id)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { hicapModelInfoSaneDefaults, ModelInfo } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionReasoningEffort } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../index"
|
||||
import { withRetry } from "../retry"
|
||||
import { convertToOpenAiMessages } from "../transform/openai-format"
|
||||
@@ -44,7 +44,7 @@ export class HicapHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const modelId = this.options.hicapModelId ?? ""
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { HuaweiCloudMaasModelId, huaweiCloudMaasDefaultModelId, huaweiCloudMaasModels, ModelInfo } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from ".."
|
||||
import { withRetry } from "../retry"
|
||||
@@ -62,7 +62,7 @@ export class HuaweiCloudMaaSHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
const openAiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { HuggingFaceModelId, huggingFaceDefaultModelId, huggingFaceModels, ModelInfo } from "@shared/api"
|
||||
import { calculateApiCostOpenAI } from "@utils/cost"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -69,7 +69,7 @@ export class HuggingFaceHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
try {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { LiteLLMModelInfo, liteLlmDefaultModelId, liteLlmModelInfoSaneDefaults } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { isAnthropicModelId } from "@/utils/model-utils"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from ".."
|
||||
@@ -183,7 +184,7 @@ export class LiteLlmHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const formattedMessages = convertToOpenAiMessages(messages)
|
||||
const systemMessage: OpenAI.Chat.ChatCompletionSystemMessageParam | Anthropic.Messages.TextBlockParam = {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { type ModelInfo, openAiModelInfoSaneDefaults } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import type { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -40,7 +40,7 @@ export class LmStudioHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry({ retryAllErrors: true })
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const openAiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [
|
||||
{ role: "system", content: systemPrompt },
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { Tool as AnthropicTool } from "@anthropic-ai/sdk/resources/index"
|
||||
import { Stream as AnthropicStream } from "@anthropic-ai/sdk/streaming"
|
||||
import { MinimaxModelId, ModelInfo, minimaxDefaultModelId, minimaxModels } from "@/shared/api"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ClineTool } from "@/shared/tools"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../index"
|
||||
@@ -45,7 +46,7 @@ export class MinimaxHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: ClineTool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: ClineTool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { Mistral } from "@mistralai/mistralai"
|
||||
import { HTTPClient } from "@mistralai/mistralai/lib/http"
|
||||
import { Tool as MistralTool } from "@mistralai/mistralai/models/components/tool"
|
||||
import { MistralModelId, ModelInfo, mistralDefaultModelId, mistralModels } from "@shared/api"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -48,7 +48,7 @@ export class MistralHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const stream = await client.chat
|
||||
.stream({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ModelInfo, MoonshotModelId, moonshotDefaultModelId, moonshotModels } from "@/shared/api"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../index"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -40,7 +40,7 @@ export class MoonshotHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { type ModelInfo, type NebiusModelId, nebiusDefaultModelId, nebiusModels } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../index"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -39,7 +39,7 @@ export class NebiusHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ModelInfo, NousResearchModelId, nousResearchDefaultModelId, nousResearchModels } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../index"
|
||||
import { withRetry } from "../retry"
|
||||
import { convertToOpenAiMessages } from "../transform/openai-format"
|
||||
@@ -37,7 +37,7 @@ export class NousResearchHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { LiteLLMModelInfo, liteLlmDefaultModelId, liteLlmModelInfoSaneDefaults } from "@shared/api"
|
||||
import OpenAI, { APIError, OpenAIError } from "openai"
|
||||
import type { FinalRequestOptions, Headers as OpenAIHeaders } from "openai/core"
|
||||
@@ -11,6 +10,7 @@ import {
|
||||
} from "@/services/auth/oca/utils/constants"
|
||||
import { createOcaHeaders } from "@/services/auth/oca/utils/utils"
|
||||
import { Logger } from "@/services/logging/Logger"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, type CommonApiHandlerOptions } from ".."
|
||||
import { withRetry } from "../retry"
|
||||
@@ -139,7 +139,7 @@ export class OcaHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const formattedMessages = convertToOpenAiMessages(messages)
|
||||
const systemMessage: OpenAI.Chat.ChatCompletionSystemMessageParam = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { type ModelInfo, openAiModelInfoSaneDefaults } from "@shared/api"
|
||||
import { type Config, type Message, Ollama } from "ollama"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import type { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
import { convertToOllamaMessages } from "../transform/ollama-format"
|
||||
@@ -48,7 +48,7 @@ export class OllamaHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry({ retryAllErrors: true })
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const ollamaMessages: Message[] = [{ role: "system", content: systemPrompt }, ...convertToOllamaMessages(messages)]
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ModelInfo, OpenAiNativeModelId, openAiNativeDefaultModelId, openAiNativeModels } from "@shared/api"
|
||||
import { calculateApiCostOpenAI } from "@utils/cost"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionReasoningEffort, ChatCompletionTool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -59,11 +59,7 @@ export class OpenAiNativeHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(
|
||||
systemPrompt: string,
|
||||
messages: Anthropic.Messages.MessageParam[],
|
||||
tools?: ChatCompletionTool[],
|
||||
): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: ChatCompletionTool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
const toolCallProcessor = new ToolCallProcessor()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { azureOpenAiDefaultApiVersion, ModelInfo, OpenAiCompatibleModelInfo, openAiModelInfoSaneDefaults } from "@shared/api"
|
||||
import OpenAI, { AzureOpenAI } from "openai"
|
||||
import type { ChatCompletionReasoningEffort, ChatCompletionTool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../index"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -65,11 +65,7 @@ export class OpenAiHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(
|
||||
systemPrompt: string,
|
||||
messages: Anthropic.Messages.MessageParam[],
|
||||
tools?: ChatCompletionTool[],
|
||||
): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: ChatCompletionTool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const modelId = this.options.openAiModelId ?? ""
|
||||
const isDeepseekReasoner = modelId.includes("deepseek-reasoner")
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { setTimeout as setTimeoutPromise } from "node:timers/promises"
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ModelInfo, openRouterDefaultModelId, openRouterDefaultModelInfo } from "@shared/api"
|
||||
import { shouldSkipReasoningForModel } from "@utils/model-utils"
|
||||
import axios from "axios"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch, getAxiosSettings } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -54,7 +54,7 @@ export class OpenRouterHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
this.lastGenerationId = undefined
|
||||
|
||||
@@ -214,11 +214,9 @@ export class OpenRouterHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
getModel(): { id: string; info: ModelInfo } {
|
||||
const modelId = this.options.openRouterModelId
|
||||
const modelInfo = this.options.openRouterModelInfo
|
||||
if (modelId && modelInfo) {
|
||||
return { id: modelId, info: modelInfo }
|
||||
return {
|
||||
id: this.options.openRouterModelId || openRouterDefaultModelId,
|
||||
info: this.options.openRouterModelInfo || openRouterDefaultModelInfo,
|
||||
}
|
||||
return { id: openRouterDefaultModelId, info: openRouterDefaultModelInfo }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { promises as fs } from "node:fs"
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ModelInfo, QwenCodeModelId, qwenCodeDefaultModelId, qwenCodeModels } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -177,7 +177,7 @@ export class QwenCodeHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
await this.ensureAuthenticated()
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import {
|
||||
InternationalQwenModelId,
|
||||
internationalQwenDefaultModelId,
|
||||
@@ -11,6 +10,7 @@ import {
|
||||
} from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -81,7 +81,7 @@ export class QwenHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
const isDeepseekReasoner = model.id.includes("deepseek-r1")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ModelInfo, requestyDefaultModelId, requestyDefaultModelInfo } from "@shared/api"
|
||||
import { calculateApiCostOpenAI } from "@utils/cost"
|
||||
import OpenAI from "openai"
|
||||
import { toRequestyServiceStringUrl } from "@/shared/clients/requesty"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../index"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -59,7 +59,7 @@ export class RequestyHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ModelInfo, SambanovaModelId, sambanovaDefaultModelId, sambanovaModels } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../index"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -42,7 +42,7 @@ export class SambanovaHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
|
||||
|
||||
@@ -4,10 +4,11 @@ import {
|
||||
ConversationRole as BedrockConversationRole,
|
||||
type Message as BedrockMessage,
|
||||
} from "@aws-sdk/client-bedrock-runtime"
|
||||
import { ChatMessages, LlmModuleConfig, OrchestrationClient, TemplatingModuleConfig } from "@sap-ai-sdk/orchestration"
|
||||
import { ChatMessage, OrchestrationClient, OrchestrationModuleConfig } from "@sap-ai-sdk/orchestration"
|
||||
import { ModelInfo, SapAiCoreModelId, sapAiCoreDefaultModelId, sapAiCoreModels } from "@shared/api"
|
||||
import axios from "axios"
|
||||
import OpenAI from "openai"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { getAxiosSettings } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -115,7 +116,7 @@ namespace Bedrock {
|
||||
* Formats messages for models using the Converse API specification
|
||||
* Used by both Anthropic and Nova models to avoid code duplication
|
||||
*/
|
||||
export function formatMessagesForConverseAPI(messages: Anthropic.Messages.MessageParam[]): BedrockMessage[] {
|
||||
export function formatMessagesForConverseAPI(messages: ClineStorageMessage[]): BedrockMessage[] {
|
||||
return messages.map((message) => {
|
||||
// Determine role (user or assistant)
|
||||
const role = message.role === "user" ? BedrockConversationRole.USER : BedrockConversationRole.ASSISTANT
|
||||
@@ -315,7 +316,7 @@ namespace Gemini {
|
||||
*/
|
||||
export function prepareRequestPayload(
|
||||
systemPrompt: string,
|
||||
messages: Anthropic.Messages.MessageParam[],
|
||||
messages: ClineStorageMessage[],
|
||||
model: { id: SapAiCoreModelId; info: ModelInfo },
|
||||
thinkingBudgetTokens?: number,
|
||||
): any {
|
||||
@@ -458,7 +459,7 @@ export class SapAiCoreHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
if (this.options.sapAiCoreUseOrchestrationMode) {
|
||||
yield* this.createMessageWithOrchestration(systemPrompt, messages)
|
||||
} else {
|
||||
@@ -490,29 +491,31 @@ export class SapAiCoreHandler implements ApiHandler {
|
||||
this.isAiCoreEnvSetup = true
|
||||
}
|
||||
|
||||
private async *createMessageWithOrchestration(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
private async *createMessageWithOrchestration(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
try {
|
||||
// Ensure AI Core environment variable is set up (only runs once)
|
||||
this.ensureAiCoreEnvSetup()
|
||||
const model = this.getModel()
|
||||
|
||||
// Define the LLM to be used by the Orchestration pipeline
|
||||
const llm: LlmModuleConfig = {
|
||||
model_name: model.id,
|
||||
const orchestrationConfig: OrchestrationModuleConfig = {
|
||||
promptTemplating: {
|
||||
model: {
|
||||
name: model.id,
|
||||
},
|
||||
prompt: {
|
||||
template: [
|
||||
{
|
||||
role: "system",
|
||||
content: systemPrompt,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const templating: TemplatingModuleConfig = {
|
||||
template: [
|
||||
{
|
||||
role: "system",
|
||||
content: systemPrompt,
|
||||
},
|
||||
],
|
||||
}
|
||||
const orchestrationClient = new OrchestrationClient(
|
||||
{ llm, templating },
|
||||
{ resourceGroup: this.options.sapAiResourceGroup || "default" },
|
||||
)
|
||||
const orchestrationClient = new OrchestrationClient(orchestrationConfig, {
|
||||
resourceGroup: this.options.sapAiResourceGroup || "default",
|
||||
})
|
||||
|
||||
const sapMessages = this.convertMessageParamToSAPMessages(messages)
|
||||
|
||||
@@ -538,7 +541,7 @@ export class SapAiCoreHandler implements ApiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private async *createMessageWithDeployments(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
private async *createMessageWithDeployments(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
const token = await this.getToken()
|
||||
const headers = {
|
||||
Authorization: `Bearer ${token}`,
|
||||
@@ -1040,8 +1043,8 @@ export class SapAiCoreHandler implements ApiHandler {
|
||||
}
|
||||
return { id: sapAiCoreDefaultModelId, info: sapAiCoreModels[sapAiCoreDefaultModelId] }
|
||||
}
|
||||
private convertMessageParamToSAPMessages(messages: Anthropic.Messages.MessageParam[]): ChatMessages {
|
||||
private convertMessageParamToSAPMessages(messages: ClineStorageMessage[]): ChatMessage[] {
|
||||
// Use the existing OpenAI converter since the logic is identical
|
||||
return convertToOpenAiMessages(messages) as ChatMessages
|
||||
return convertToOpenAiMessages(messages) as ChatMessage[]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ModelInfo, openAiModelInfoSaneDefaults } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../index"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -42,7 +42,7 @@ export class TogetherHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const modelId = this.options.togetherModelId ?? ""
|
||||
const isDeepseekReasoner = modelId.includes("deepseek-reasoner")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ModelInfo, openRouterDefaultModelId, openRouterDefaultModelInfo } from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../index"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -47,7 +47,7 @@ export class VercelAIGatewayHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const modelId = this.getModel().id
|
||||
const modelInfo = this.getModel().info
|
||||
@@ -102,22 +102,16 @@ export class VercelAIGatewayHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
if (!didOutputUsage && chunk.usage) {
|
||||
const inputTokens = chunk.usage.prompt_tokens || 0
|
||||
const outputTokens =
|
||||
(chunk.usage.completion_tokens || 0) + (chunk.usage.completion_tokens_details?.reasoning_tokens || 0)
|
||||
|
||||
const cacheReadTokens = chunk.usage.prompt_tokens_details?.cached_tokens || 0
|
||||
// @ts-ignore - Vercel AI Gateway extends OpenAI types
|
||||
const cacheWriteTokens = chunk.usage.cache_creation_input_tokens || 0
|
||||
const totalCost = (chunk.usage.cost || 0) + (chunk.usage.cost_details?.upstream_inference_cost || 0)
|
||||
|
||||
yield {
|
||||
type: "usage",
|
||||
inputTokens: inputTokens,
|
||||
outputTokens: outputTokens,
|
||||
cacheWriteTokens: cacheWriteTokens,
|
||||
cacheReadTokens: cacheReadTokens,
|
||||
// @ts-expect-error - Vercel AI Gateway extends OpenAI types
|
||||
totalCost: chunk.usage.cost || 0,
|
||||
cacheWriteTokens: 0,
|
||||
cacheReadTokens: chunk.usage.prompt_tokens_details?.cached_tokens || 0,
|
||||
inputTokens: (chunk.usage.prompt_tokens || 0) - (chunk.usage.prompt_tokens_details?.cached_tokens || 0),
|
||||
outputTokens: chunk.usage.completion_tokens || 0,
|
||||
totalCost,
|
||||
}
|
||||
didOutputUsage = true
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { Tool as AnthropicTool } from "@anthropic-ai/sdk/resources/index"
|
||||
import { AnthropicVertex } from "@anthropic-ai/vertex-sdk"
|
||||
import { FunctionDeclaration as GoogleTool } from "@google/genai"
|
||||
import { ModelInfo, VertexModelId, vertexDefaultModelId, vertexModels } from "@shared/api"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { ClineTool } from "@/shared/tools"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -67,7 +67,7 @@ export class VertexHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: ClineTool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: ClineTool[]): ApiStream {
|
||||
const model = this.getModel()
|
||||
const modelId = model.id
|
||||
|
||||
@@ -95,6 +95,7 @@ export class VertexHandler implements ApiHandler {
|
||||
case "claude-haiku-4-5@20251001":
|
||||
case "claude-sonnet-4-5@20250929":
|
||||
case "claude-sonnet-4@20250514":
|
||||
case "claude-opus-4-5@20251101":
|
||||
case "claude-opus-4-1@20250805":
|
||||
case "claude-opus-4@20250514":
|
||||
case "claude-3-7-sonnet@20250219":
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ModelInfo, openAiModelInfoSaneDefaults } from "@shared/api"
|
||||
import { SELECTOR_SEPARATOR, stringifyVsCodeLmModelSelector } from "@shared/vsCodeSelectorUtils"
|
||||
import { calculateApiCostAnthropic } from "@utils/cost"
|
||||
import * as vscode from "vscode"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { ApiHandler, CommonApiHandlerOptions, SingleCompletionHandler } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
import { ApiStream } from "../transform/stream"
|
||||
@@ -366,7 +366,7 @@ export class VsCodeLmHandler implements ApiHandler, SingleCompletionHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[]): ApiStream {
|
||||
// Ensure clean state before starting a new request
|
||||
this.ensureCleanState()
|
||||
const client: vscode.LanguageModelChat = await this.getClient()
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { ModelInfo, XAIModelId, xaiDefaultModelId, xaiModels } from "@shared/api"
|
||||
import { shouldSkipReasoningForModel } from "@utils/model-utils"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ChatCompletionReasoningEffort } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from "../"
|
||||
import { withRetry } from "../retry"
|
||||
@@ -44,7 +44,7 @@ export class XAIHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const modelId = this.getModel().id
|
||||
// ensure reasoning effort is either "low" or "high" for grok-3-mini
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import {
|
||||
internationalZAiDefaultModelId,
|
||||
internationalZAiModelId,
|
||||
@@ -10,6 +9,7 @@ import {
|
||||
} from "@shared/api"
|
||||
import OpenAI from "openai"
|
||||
import type { ChatCompletionTool as OpenAITool } from "openai/resources/chat/completions"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { fetch } from "@/shared/net"
|
||||
import { version as extensionVersion } from "../../../../package.json"
|
||||
import { ApiHandler, CommonApiHandlerOptions } from ".."
|
||||
@@ -76,7 +76,7 @@ export class ZAiHandler implements ApiHandler {
|
||||
}
|
||||
|
||||
@withRetry()
|
||||
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[], tools?: OpenAITool[]): ApiStream {
|
||||
async *createMessage(systemPrompt: string, messages: ClineStorageMessage[], tools?: OpenAITool[]): ApiStream {
|
||||
const client = this.ensureClient()
|
||||
const model = this.getModel()
|
||||
const openAiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Anthropic from "@anthropic-ai/sdk"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
import { ClineContent, ClineStorageMessage } from "@/shared/messages/content"
|
||||
|
||||
/**
|
||||
* Sanitize Anthropic messages by removing reasoning details and adding ephemeral cache control
|
||||
@@ -63,14 +63,21 @@ function removeUnknownParams(param: ClineStorageMessage): Anthropic.Messages.Mes
|
||||
// Construct new content array with known Anthropic content blocks only.
|
||||
return {
|
||||
role: param.role === "user" ? "user" : "assistant",
|
||||
content: Array.isArray(param.content)
|
||||
? param.content.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
// Ensure reasoning_details is removed
|
||||
reasoning_details: undefined,
|
||||
}
|
||||
})
|
||||
: param.content, // String content remains unchanged
|
||||
content: Array.isArray(param.content) ? param.content.map(sanitizeAnthropicContentBlock) : param.content, // String content remains unchanged
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean a content block by removing Cline-specific fields and returning only provider-compatible fields
|
||||
*/
|
||||
function sanitizeAnthropicContentBlock(block: ClineContent): Anthropic.ContentBlock {
|
||||
// Fast path: if no reasoning_details property exists, return as-is
|
||||
// Including reasoning_details in non-openrouter/cline providers may cause API errors
|
||||
if ("reasoning_details" in block || "call_id" in block || "summary" in block) {
|
||||
// biome-ignore lint/correctness/noUnusedVariables: intentional destructuring to remove properties
|
||||
const { reasoning_details, call_id, summary, ...cleanBlock } = block as any
|
||||
return cleanBlock as Anthropic.ContentBlock
|
||||
}
|
||||
|
||||
return block as Anthropic.ContentBlock
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { Content, GenerateContentResponse, Part } from "@google/genai"
|
||||
import { ClineStorageMessage } from "@/shared/messages/content"
|
||||
|
||||
export function convertAnthropicContentToGemini(content: string | Anthropic.ContentBlockParam[]): Part[] {
|
||||
export function convertAnthropicContentToGemini(content: string | ClineStorageMessage["content"]): Part[] {
|
||||
if (typeof content === "string") {
|
||||
return [{ text: content }]
|
||||
}
|
||||
@@ -9,7 +10,7 @@ export function convertAnthropicContentToGemini(content: string | Anthropic.Cont
|
||||
.flatMap((block): Part | undefined => {
|
||||
switch (block.type) {
|
||||
case "text":
|
||||
return { text: block.text }
|
||||
return { text: block.text, thoughtSignature: block.signature }
|
||||
case "image":
|
||||
if (block.source.type !== "base64") {
|
||||
throw new Error("Unsupported image source type")
|
||||
@@ -26,6 +27,7 @@ export function convertAnthropicContentToGemini(content: string | Anthropic.Cont
|
||||
name: block.name,
|
||||
args: block.input as Record<string, unknown>,
|
||||
},
|
||||
thoughtSignature: block.signature,
|
||||
}
|
||||
case "tool_result":
|
||||
return {
|
||||
|
||||
@@ -43,6 +43,7 @@ export async function createOpenRouterStream(
|
||||
case "anthropic/claude-sonnet-4.5":
|
||||
case "anthropic/claude-4.5-sonnet": // OpenRouter accidentally included this in model list for a brief moment, and users may be using this model id. And to support prompt caching, we need to add it here.
|
||||
case "anthropic/claude-sonnet-4":
|
||||
case "anthropic/claude-opus-4.5":
|
||||
case "anthropic/claude-opus-4.1":
|
||||
case "anthropic/claude-opus-4":
|
||||
case "anthropic/claude-3.7-sonnet":
|
||||
@@ -106,6 +107,7 @@ export async function createOpenRouterStream(
|
||||
case "anthropic/claude-sonnet-4.5":
|
||||
case "anthropic/claude-4.5-sonnet":
|
||||
case "anthropic/claude-sonnet-4":
|
||||
case "anthropic/claude-opus-4.5":
|
||||
case "anthropic/claude-opus-4.1":
|
||||
case "anthropic/claude-opus-4":
|
||||
case "anthropic/claude-3.7-sonnet":
|
||||
@@ -138,6 +140,10 @@ export async function createOpenRouterStream(
|
||||
topP = 0.95
|
||||
openAiMessages = convertToR1Format([{ role: "user", content: systemPrompt }, ...messages])
|
||||
}
|
||||
if (model.id.startsWith("google/gemini-3.0") || model.id === "google/gemini-3.0") {
|
||||
// Recommended value from google
|
||||
temperature = 1.0
|
||||
}
|
||||
|
||||
let reasoning: { max_tokens: number } | undefined
|
||||
switch (model.id) {
|
||||
@@ -146,6 +152,7 @@ export async function createOpenRouterStream(
|
||||
case "anthropic/claude-sonnet-4.5":
|
||||
case "anthropic/claude-4.5-sonnet":
|
||||
case "anthropic/claude-sonnet-4":
|
||||
case "anthropic/claude-opus-4.5":
|
||||
case "anthropic/claude-opus-4.1":
|
||||
case "anthropic/claude-opus-4":
|
||||
case "anthropic/claude-3.7-sonnet":
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
export type ApiStream = AsyncGenerator<ApiStreamChunk>
|
||||
export type ApiStream = AsyncGenerator<ApiStreamChunk> & { id?: string }
|
||||
export type ApiStreamChunk = ApiStreamTextChunk | ApiStreamThinkingChunk | ApiStreamUsageChunk | ApiStreamToolCallsChunk
|
||||
|
||||
export interface ApiStreamTextChunk {
|
||||
type: "text"
|
||||
/**
|
||||
* Text content generated by the model
|
||||
*/
|
||||
text: string
|
||||
/**
|
||||
* The response ID associated with this chunk
|
||||
*/
|
||||
id?: string
|
||||
/**
|
||||
* The thought signature associated with this chunk used by Gemini
|
||||
*/
|
||||
signature?: string
|
||||
}
|
||||
|
||||
export interface ApiStreamUsageChunk {
|
||||
@@ -14,27 +25,74 @@ export interface ApiStreamUsageChunk {
|
||||
cacheReadTokens?: number
|
||||
thoughtsTokenCount?: number // openrouter
|
||||
totalCost?: number // openrouter
|
||||
/**
|
||||
* The response ID associated with this response
|
||||
*/
|
||||
id?: string
|
||||
}
|
||||
|
||||
export interface ApiStreamToolCallsChunk {
|
||||
type: "tool_calls"
|
||||
/**
|
||||
* The tool call information
|
||||
*/
|
||||
tool_call: ApiStreamToolCall
|
||||
/**
|
||||
* The response ID associated with this chunk
|
||||
*/
|
||||
id?: string
|
||||
/**
|
||||
* The thought signature associated with this chunk used by Gemini
|
||||
*/
|
||||
signature?: string
|
||||
}
|
||||
|
||||
export interface ApiStreamToolCall {
|
||||
call_id?: string // The call / request ID associated with this tool call
|
||||
/**
|
||||
* The call ID associated with this tool call
|
||||
*/
|
||||
call_id?: string
|
||||
// Information about the tool being called
|
||||
function: {
|
||||
id?: string // The tool call ID
|
||||
/**
|
||||
* The tool call ID
|
||||
*/
|
||||
id?: string
|
||||
/**
|
||||
* Name of the tool
|
||||
*/
|
||||
name?: string
|
||||
/**
|
||||
* The arguments passed to the tool execution
|
||||
*/
|
||||
arguments?: any
|
||||
}
|
||||
}
|
||||
|
||||
export interface ApiStreamThinkingChunk {
|
||||
type: "reasoning"
|
||||
/**
|
||||
* The reasoning text generated by the model.
|
||||
* Redacted reasoning block will have this field set to "[REDACTED]" or an empty string.
|
||||
*/
|
||||
reasoning: string
|
||||
details?: unknown // openrouter has various properties that we can pass back unmodified in api requests to preserve reasoning traces
|
||||
/**
|
||||
* openrouter has various properties that we can pass back unmodified in api requests to preserve reasoning traces
|
||||
* This is also where we store the summary details for OpenAI.
|
||||
*/
|
||||
details?: unknown
|
||||
/**
|
||||
* It's used when sending the thinking block back to the API.
|
||||
* API expects this in completed form, not as array of deltas.
|
||||
* Also used by Gemini for thought signature associated with this chunk
|
||||
*/
|
||||
signature?: string
|
||||
/**
|
||||
* redacted data
|
||||
*/
|
||||
redacted_data?: string
|
||||
/**
|
||||
* The response ID associated with this chunk
|
||||
*/
|
||||
id?: string
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ export interface PendingToolUse {
|
||||
name: string
|
||||
input: string
|
||||
parsedInput?: unknown
|
||||
signature?: string
|
||||
jsonParser?: JSONParser
|
||||
call_id?: string
|
||||
}
|
||||
@@ -19,6 +20,7 @@ interface ToolUseDeltaBlock {
|
||||
type?: string
|
||||
name?: string
|
||||
input?: string
|
||||
signature?: string
|
||||
}
|
||||
|
||||
const ESCAPE_MAP: Record<string, string> = {
|
||||
@@ -50,12 +52,17 @@ export class ToolUseHandler {
|
||||
if (delta.name) {
|
||||
pending.name = delta.name
|
||||
}
|
||||
|
||||
if (delta.signature) {
|
||||
pending.signature = delta.signature
|
||||
}
|
||||
|
||||
if (delta.input) {
|
||||
pending.input += delta.input
|
||||
try {
|
||||
pending.jsonParser?.write(delta.input)
|
||||
} catch {
|
||||
// Expected during streaming
|
||||
// Expected during streaming - JSONParser may not have complete JSON yet
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,6 +89,7 @@ export class ToolUseHandler {
|
||||
id: pending.id,
|
||||
name: pending.name,
|
||||
input,
|
||||
signature: pending.signature,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,19 +110,24 @@ export class ToolUseHandler {
|
||||
|
||||
getPartialToolUsesAsContent(): ToolUse[] {
|
||||
const results: ToolUse[] = []
|
||||
const pendingToolUses = this.pendingToolUses.values()
|
||||
|
||||
for (const pending of this.pendingToolUses.values()) {
|
||||
for (const pending of pendingToolUses) {
|
||||
if (!pending.name) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Try to get the most up-to-date parsed input
|
||||
// Priority: parsedInput (from JSONParser) > fallback to manual parsing
|
||||
let input: any = {}
|
||||
if (pending.parsedInput != null) {
|
||||
input = pending.parsedInput
|
||||
} else if (pending.input) {
|
||||
// Try full JSON parse first
|
||||
try {
|
||||
input = JSON.parse(pending.input)
|
||||
} catch {
|
||||
// Fall back to extracting partial fields from incomplete JSON
|
||||
input = this.extractPartialJsonFields(pending.input)
|
||||
}
|
||||
}
|
||||
@@ -131,10 +144,11 @@ export class ToolUseHandler {
|
||||
},
|
||||
partial: true,
|
||||
isNativeToolCall: true,
|
||||
signature: pending.signature,
|
||||
})
|
||||
} else {
|
||||
const params: Record<string, string> = {}
|
||||
if (typeof input === "object") {
|
||||
if (typeof input === "object" && input !== null) {
|
||||
for (const [key, value] of Object.entries(input)) {
|
||||
params[key] = typeof value === "string" ? value : JSON.stringify(value)
|
||||
}
|
||||
@@ -144,12 +158,13 @@ export class ToolUseHandler {
|
||||
name: pending.name as ClineDefaultTool,
|
||||
params: params as any,
|
||||
partial: true,
|
||||
signature: pending.signature,
|
||||
isNativeToolCall: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
// Ensure all returned tool uses are marked as partial
|
||||
return results.map((t) => ({ ...t, partial: true }))
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
@@ -165,6 +180,7 @@ export class ToolUseHandler {
|
||||
parsedInput: undefined,
|
||||
jsonParser,
|
||||
call_id,
|
||||
signature: undefined,
|
||||
}
|
||||
|
||||
jsonParser.onValue = (info: any) => {
|
||||
|
||||
@@ -54,6 +54,7 @@ export interface ToolUse {
|
||||
partial: boolean
|
||||
// Whether this tool use was initiated by a native tool call
|
||||
isNativeToolCall?: boolean
|
||||
signature?: string
|
||||
}
|
||||
|
||||
export interface ReasoningStreamContent {
|
||||
|
||||
@@ -5,7 +5,8 @@ export function checkContextWindowExceededError(error: unknown): boolean {
|
||||
checkIsOpenAIContextWindowError(error) ||
|
||||
checkIsOpenRouterContextWindowError(error) ||
|
||||
checkIsAnthropicContextWindowError(error) ||
|
||||
checkIsCerebrasContextWindowError(error)
|
||||
checkIsCerebrasContextWindowError(error) ||
|
||||
checkIsBedrockContextWindowError(error)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -70,3 +71,45 @@ function checkIsCerebrasContextWindowError(response: any): boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function checkIsBedrockContextWindowError(error: any): boolean {
|
||||
try {
|
||||
// Bedrock returns ValidationException for context window errors
|
||||
const errorType = error?.name ?? error?.error?.type ?? error?.__type
|
||||
const errorCode = error?.code ?? error?.error?.code ?? error?.$metadata?.httpStatusCode
|
||||
|
||||
// Handle nested error structures (e.g., through Vercel AI SDK)
|
||||
const nestedError = error?.error?.param
|
||||
const nestedErrorCode = nestedError?.statusCode ?? error?.details?.code
|
||||
const nestedMessage = nestedError?.message ?? nestedError?.error
|
||||
|
||||
const message: string = String(error?.message || error?.error?.message || nestedMessage || "")
|
||||
|
||||
// Check for ValidationException with HTTP 400
|
||||
const isValidationException =
|
||||
errorType === "ValidationException" ||
|
||||
errorType === "AI_APICallError" ||
|
||||
String(errorCode) === "400" ||
|
||||
String(nestedErrorCode) === "400" ||
|
||||
error?.code === "stream_initialization_failed"
|
||||
|
||||
if (!isValidationException) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Known Bedrock context window error patterns
|
||||
const BEDROCK_CONTEXT_PATTERNS = [
|
||||
/maximum tokens.*exceeds.*model limit/i,
|
||||
/input length and max_tokens exceed context limit/i,
|
||||
/context length.*exceeds/i,
|
||||
/total number of tokens.*exceeds.*limit/i,
|
||||
/requested.*tokens.*exceeds.*limit/i,
|
||||
/reduce.*length.*messages.*completion/i,
|
||||
/input is too long/i,
|
||||
] as const
|
||||
|
||||
return BEDROCK_CONTEXT_PATTERNS.some((pattern) => pattern.test(message))
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import type { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { buildApiHandler } from "@core/api"
|
||||
import { tryAcquireTaskLockWithRetry } from "@core/task/TaskLockUtils"
|
||||
import { detectWorkspaceRoots } from "@core/workspace/detection"
|
||||
import { setupWorkspaceManager } from "@core/workspace/setup"
|
||||
import { WorkspaceRootManager } from "@core/workspace/WorkspaceRootManager"
|
||||
import type { WorkspaceRootManager } from "@core/workspace/WorkspaceRootManager"
|
||||
import { cleanupLegacyCheckpoints } from "@integrations/checkpoints/CheckpointMigration"
|
||||
import { downloadTask } from "@integrations/misc/export-markdown"
|
||||
import { ClineAccountService } from "@services/account/ClineAccountService"
|
||||
import { McpHub } from "@services/mcp/McpHub"
|
||||
import { ApiProvider, ModelInfo } from "@shared/api"
|
||||
import { ChatContent } from "@shared/ChatContent"
|
||||
import { ExtensionState, Platform } from "@shared/ExtensionMessage"
|
||||
import { HistoryItem } from "@shared/HistoryItem"
|
||||
import { McpMarketplaceCatalog, McpMarketplaceItem } from "@shared/mcp"
|
||||
import { Settings } from "@shared/storage/state-keys"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { TelemetrySetting } from "@shared/TelemetrySetting"
|
||||
import { UserInfo } from "@shared/UserInfo"
|
||||
import type { ApiProvider, ModelInfo } from "@shared/api"
|
||||
import type { ChatContent } from "@shared/ChatContent"
|
||||
import type { ExtensionState, Platform } from "@shared/ExtensionMessage"
|
||||
import type { HistoryItem } from "@shared/HistoryItem"
|
||||
import type { McpMarketplaceCatalog, McpMarketplaceItem } from "@shared/mcp"
|
||||
import type { Settings } from "@shared/storage/state-keys"
|
||||
import type { Mode } from "@shared/storage/types"
|
||||
import type { TelemetrySetting } from "@shared/TelemetrySetting"
|
||||
import type { UserInfo } from "@shared/UserInfo"
|
||||
import { fileExistsAtPath } from "@utils/fs"
|
||||
import axios from "axios"
|
||||
import fs from "fs/promises"
|
||||
import pWaitFor from "p-wait-for"
|
||||
import * as path from "path"
|
||||
import type { FolderLockWithRetryResult } from "src/core/locks/types"
|
||||
import * as vscode from "vscode"
|
||||
import type * as vscode from "vscode"
|
||||
import { ClineEnv } from "@/config"
|
||||
import { HostProvider } from "@/hosts/host-provider"
|
||||
import { ExtensionRegistryInfo } from "@/registry"
|
||||
@@ -35,7 +35,7 @@ import { getDistinctId } from "@/services/logging/distinctId"
|
||||
import { telemetryService } from "@/services/telemetry"
|
||||
import { getAxiosSettings } from "@/shared/net"
|
||||
import { ShowMessageType } from "@/shared/proto/host/window"
|
||||
import { AuthState } from "@/shared/proto/index.cline"
|
||||
import type { AuthState } from "@/shared/proto/index.cline"
|
||||
import { getLatestAnnouncementId } from "@/utils/announcements"
|
||||
import { getCwd, getDesktopDir } from "@/utils/path"
|
||||
import { PromptRegistry } from "../prompts/system-prompt"
|
||||
@@ -47,10 +47,11 @@ import {
|
||||
writeMcpMarketplaceCatalogToCache,
|
||||
} from "../storage/disk"
|
||||
import { fetchRemoteConfig } from "../storage/remote-config/fetch"
|
||||
import { PersistenceErrorEvent, StateManager } from "../storage/StateManager"
|
||||
import { type PersistenceErrorEvent, StateManager } from "../storage/StateManager"
|
||||
import { Task } from "../task"
|
||||
import { StreamingResponseHandler } from "./grpc-handler"
|
||||
import type { StreamingResponseHandler } from "./grpc-handler"
|
||||
import { sendMcpMarketplaceCatalogEvent } from "./mcp/subscribeToMcpMarketplaceCatalog"
|
||||
import { getClineOnboardingModels } from "./models/getClineOnboardingModels"
|
||||
import { appendClineStealthModels } from "./models/refreshOpenRouterModels"
|
||||
import { checkCliInstallation } from "./state/checkCliInstallation"
|
||||
import { sendStateUpdate } from "./state/subscribeToState"
|
||||
@@ -846,6 +847,7 @@ export class Controller {
|
||||
|
||||
async getStateToPostToWebview(): Promise<ExtensionState> {
|
||||
// Get API configuration from cache for immediate access
|
||||
const onboardingModels = getClineOnboardingModels()
|
||||
const apiConfiguration = this.stateManager.getApiConfiguration()
|
||||
const lastShownAnnouncementId = this.stateManager.getGlobalStateKey("lastShownAnnouncementId")
|
||||
const taskHistory = this.stateManager.getGlobalStateKey("taskHistory")
|
||||
@@ -958,7 +960,7 @@ export class Controller {
|
||||
defaultTerminalProfile,
|
||||
isNewUser,
|
||||
welcomeViewCompleted,
|
||||
showOnboardingFlow: featureFlagsService.getOnboardingEnabled(),
|
||||
onboardingModels,
|
||||
mcpResponsesCollapsed,
|
||||
terminalOutputLineLimit,
|
||||
maxConsecutiveMistakes,
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import { featureFlagsService } from "@/services/feature-flags"
|
||||
import { CLINE_ONBOARDING_MODELS } from "@/shared/cline/onboarding"
|
||||
import { OnboardingModel, OnboardingModelGroup } from "@/shared/proto/cline/state"
|
||||
|
||||
type OnboardingModelOverride = OnboardingModel & { hidden?: boolean }
|
||||
|
||||
let cached: OnboardingModelGroup | null = null
|
||||
|
||||
export function getClineOnboardingModels(): OnboardingModelGroup {
|
||||
if (cached) {
|
||||
return cached
|
||||
}
|
||||
|
||||
const remoteOverrides = featureFlagsService.getOnboardingOverrides()
|
||||
const models = new Map<string, OnboardingModel>(CLINE_ONBOARDING_MODELS.map((model) => [model.id, model]))
|
||||
|
||||
// Apply remote overrides if available
|
||||
if (remoteOverrides) {
|
||||
for (const [id, override] of Object.entries(remoteOverrides) as [string, OnboardingModelOverride][]) {
|
||||
if (override.hidden) {
|
||||
models.delete(id)
|
||||
} else {
|
||||
const baseModel = models.get(id)
|
||||
models.set(id, mergeModelWithOverride(baseModel, override))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cached = { models: Array.from(models.values()) }
|
||||
return cached
|
||||
}
|
||||
|
||||
function mergeModelWithOverride(baseModel: OnboardingModel | undefined, override: OnboardingModelOverride): OnboardingModel {
|
||||
const baseInfo = baseModel?.info
|
||||
const overrideInfo = override.info
|
||||
|
||||
// Merge info with proper defaults
|
||||
const mergedInfo = {
|
||||
...baseInfo,
|
||||
...overrideInfo,
|
||||
supportsPromptCache: overrideInfo?.supportsPromptCache ?? baseInfo?.supportsPromptCache ?? false,
|
||||
tiers: overrideInfo?.tiers ?? baseInfo?.tiers ?? [],
|
||||
}
|
||||
|
||||
// Return merged model, using base as foundation if available
|
||||
return baseModel ? { ...baseModel, ...override, info: mergedInfo } : { ...override, info: mergedInfo }
|
||||
}
|
||||
|
||||
export function clearOnboardingModelsCache(): void {
|
||||
cached = null
|
||||
}
|
||||
@@ -133,6 +133,11 @@ export async function refreshOpenRouterModels(controller: Controller): Promise<R
|
||||
modelInfo.cacheWritesPrice = 3.75
|
||||
modelInfo.cacheReadsPrice = 0.3
|
||||
break
|
||||
case "anthropic/claude-opus-4.5":
|
||||
modelInfo.supportsPromptCache = true
|
||||
modelInfo.cacheWritesPrice = 6.25
|
||||
modelInfo.cacheReadsPrice = 0.5
|
||||
break
|
||||
case "anthropic/claude-opus-4.1":
|
||||
case "anthropic/claude-opus-4":
|
||||
modelInfo.supportsPromptCache = true
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { EmptyRequest } from "@shared/proto/cline/common"
|
||||
import { OpenRouterCompatibleModelInfo, OpenRouterModelInfo } from "@shared/proto/cline/models"
|
||||
import axios from "axios"
|
||||
import { getAxiosSettings } from "@/shared/net"
|
||||
import { toRequestyServiceUrl } from "@/shared/clients/requesty"
|
||||
import { getAxiosSettings } from "@/shared/net"
|
||||
import { Controller } from ".."
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { BooleanRequest } from "@shared/proto/cline/common"
|
||||
import { Empty } from "@shared/proto/cline/common"
|
||||
import type { Controller } from "../index"
|
||||
import { clearOnboardingModelsCache } from "../models/getClineOnboardingModels"
|
||||
|
||||
/**
|
||||
* Sets the welcomeViewCompleted flag to the specified boolean value
|
||||
@@ -20,5 +21,7 @@ export async function setWelcomeViewCompleted(controller: Controller, request: B
|
||||
} catch (error) {
|
||||
console.error("Failed to set welcome view completed:", error)
|
||||
throw error
|
||||
} finally {
|
||||
clearOnboardingModelsCache()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,12 @@ export async function executeHook<Name extends keyof Hooks>(options: HookExecuti
|
||||
}
|
||||
hookMessageTs = await say("hook", JSON.stringify(hookMetadata))
|
||||
|
||||
// Reorder messages immediately so hook UI appears above tool UI
|
||||
// This must happen right after creating the hook message, before the hook runs
|
||||
if (hookName === "PreToolUse") {
|
||||
await reorderHookAndToolMessages(messageStateHandler)
|
||||
}
|
||||
|
||||
// Track active hook execution for cancellation (only if cancellable and message was created)
|
||||
if (isCancellable && hookMessageTs !== undefined && setActiveHookExecution) {
|
||||
await setActiveHookExecution({
|
||||
@@ -224,3 +230,56 @@ async function updateHookMessage(
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorders hook and tool messages so hook UI appears before tool UI.
|
||||
* This is called immediately after a hook message is created.
|
||||
*
|
||||
* The algorithm:
|
||||
* 1. Find the most recent tool message (ask or say with type "tool", "command", "use_mcp_server", or "browser_action_launch")
|
||||
* 2. Find any hook messages that came after it
|
||||
* 3. Delete the tool message
|
||||
* 4. Re-add the tool message at the end (after hook messages)
|
||||
*/
|
||||
async function reorderHookAndToolMessages(messageStateHandler: MessageStateHandler): Promise<void> {
|
||||
const clineMessages = messageStateHandler.getClineMessages()
|
||||
|
||||
// Define all message types that represent tool executions with PreToolUse hooks
|
||||
const toolMessageTypes = ["tool", "command", "use_mcp_server", "browser_action_launch"]
|
||||
|
||||
// Find the most recent tool message
|
||||
let lastToolMessageIndex = -1
|
||||
for (let i = clineMessages.length - 1; i >= 0; i--) {
|
||||
const msgType = clineMessages[i].ask || clineMessages[i].say
|
||||
if (msgType && toolMessageTypes.includes(msgType)) {
|
||||
lastToolMessageIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (lastToolMessageIndex === -1) {
|
||||
return // No tool message found, nothing to reorder
|
||||
}
|
||||
|
||||
// Check if there are any hook messages after the tool message
|
||||
let hasHookMessagesAfterTool = false
|
||||
for (let i = lastToolMessageIndex + 1; i < clineMessages.length; i++) {
|
||||
if (clineMessages[i].say === "hook" || clineMessages[i].say === "hook_output") {
|
||||
hasHookMessagesAfterTool = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasHookMessagesAfterTool) {
|
||||
return // No reordering needed
|
||||
}
|
||||
|
||||
// Store the tool message (deep copy to preserve all properties)
|
||||
const toolMessage = { ...clineMessages[lastToolMessageIndex] }
|
||||
|
||||
// Delete the tool message at its current position
|
||||
await messageStateHandler.deleteClineMessage(lastToolMessageIndex)
|
||||
|
||||
// Re-add the tool message at the end (after hook messages)
|
||||
await messageStateHandler.addToClineMessages(toolMessage)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,40 @@
|
||||
import type { ApiProviderInfo } from "@/core/api"
|
||||
import { getDeepPlanningPrompt } from "./commands/deep-planning"
|
||||
|
||||
export const newTaskToolResponse = () =>
|
||||
`<explicit_instructions type="new_task">
|
||||
export const newTaskToolResponse = (enableNativeToolCalls?: boolean) => {
|
||||
const xmlExample = enableNativeToolCalls
|
||||
? ""
|
||||
: `
|
||||
Example:
|
||||
<new_task>
|
||||
<context>1. Current Work:
|
||||
[Detailed description]
|
||||
|
||||
2. Key Technical Concepts:
|
||||
- [Concept 1]
|
||||
- [Concept 2]
|
||||
- [...]
|
||||
|
||||
3. Relevant Files and Code:
|
||||
- [File Name 1]
|
||||
- [Summary of why this file is important]
|
||||
- [Summary of the changes made to this file, if any]
|
||||
- [Important Code Snippet]
|
||||
- [File Name 2]
|
||||
- [Important Code Snippet]
|
||||
- [...]
|
||||
|
||||
4. Problem Solving:
|
||||
[Detailed description]
|
||||
|
||||
5. Pending Tasks and Next Steps:
|
||||
- [Task 1 details & next steps]
|
||||
- [Task 2 details & next steps]
|
||||
- [...]</context>
|
||||
</new_task>
|
||||
`
|
||||
|
||||
return `<explicit_instructions type="new_task">
|
||||
The user has explicitly asked you to help them create a new task with preloaded context, which you will generate. The user may have provided instructions or additional information for you to consider when summarizing existing work and creating the context for the new task.
|
||||
Irrespective of whether additional information or instructions are given, you are ONLY allowed to respond to this message by calling the new_task tool.
|
||||
|
||||
@@ -19,15 +51,11 @@ Parameters:
|
||||
3. Relevant Files and Code: If applicable, enumerate specific files and code sections examined, modified, or created for the task continuation. Pay special attention to the most recent messages and changes.
|
||||
4. Problem Solving: Document problems solved thus far and any ongoing troubleshooting efforts.
|
||||
5. Pending Tasks and Next Steps: Outline all pending tasks that you have explicitly been asked to work on, as well as list the next steps you will take for all outstanding work, if applicable. Include code snippets where they add clarity. For any next steps, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no information loss in context between tasks.
|
||||
|
||||
Usage:
|
||||
<new_task>
|
||||
<context>context to preload new task with</context>
|
||||
</new_task>
|
||||
|
||||
${xmlExample}
|
||||
Below is the the user's input when they indicated that they wanted to create a new task.
|
||||
</explicit_instructions>\n
|
||||
`
|
||||
}
|
||||
|
||||
export const condenseToolResponse = (focusChainSettings?: { enabled: boolean }) =>
|
||||
`<explicit_instructions type="condense">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { ApiProviderInfo } from "@/core/api"
|
||||
import type { SystemPromptContext } from "@/core/prompts/system-prompt/types"
|
||||
import { getDeepPlanningRegistry } from "./registry"
|
||||
import { generateGemini3Template } from "./variants/gemini3"
|
||||
import { generateGPT51Template } from "./variants/gpt5"
|
||||
|
||||
/**
|
||||
@@ -24,6 +25,8 @@ export function getDeepPlanningPrompt(focusChainSettings?: { enabled: boolean },
|
||||
let template: string
|
||||
if (variant.id === "gpt-5") {
|
||||
template = generateGPT51Template(focusChainSettings?.enabled ?? false)
|
||||
} else if (variant.id === "gemini-3") {
|
||||
template = generateGemini3Template(focusChainSettings?.enabled ?? false)
|
||||
} else {
|
||||
template = variant.template
|
||||
}
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import type { SystemPromptContext } from "@/core/prompts/system-prompt/types"
|
||||
import type { DeepPlanningVariant, DeepPlanningRegistry as IDeepPlanningRegistry } from "./types"
|
||||
import { createAnthropicVariant, createGeminiVariant, createGenericVariant, createGPT51Variant } from "./variants"
|
||||
import {
|
||||
createAnthropicVariant,
|
||||
createGemini3Variant,
|
||||
createGeminiVariant,
|
||||
createGenericVariant,
|
||||
createGPT51Variant,
|
||||
} from "./variants"
|
||||
|
||||
/**
|
||||
* Singleton registry for managing deep-planning prompt variants
|
||||
@@ -15,6 +21,7 @@ class DeepPlanningRegistry implements IDeepPlanningRegistry {
|
||||
// Initialize all variants
|
||||
this.registerVariant(createAnthropicVariant())
|
||||
this.registerVariant(createGeminiVariant())
|
||||
this.registerVariant(createGemini3Variant())
|
||||
this.registerVariant(createGPT51Variant())
|
||||
|
||||
// Generic variant must be registered last as fallback
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
import { isGemini3ModelFamily } from "@utils/model-utils"
|
||||
import { getShell } from "@utils/shell"
|
||||
import type { SystemPromptContext } from "@/core/prompts/system-prompt/types"
|
||||
import type { DeepPlanningVariant } from "../types"
|
||||
|
||||
/**
|
||||
* Creates the Gemini 3 variant for deep-planning prompt
|
||||
*/
|
||||
export function createGemini3Variant(): DeepPlanningVariant {
|
||||
return {
|
||||
id: "gemini-3",
|
||||
description: "Deep-planning variant optimized for Gemini 3 models",
|
||||
family: "gemini-3",
|
||||
version: 1,
|
||||
matcher: (context: SystemPromptContext) => {
|
||||
const modelId = context.providerInfo?.model?.id
|
||||
if (!modelId) {
|
||||
return false
|
||||
}
|
||||
return isGemini3ModelFamily(modelId)
|
||||
},
|
||||
template: "", // Template is dynamically generated in getDeepPlanningPrompt() based on focus chain settings
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the deep-planning template with shell-specific commands
|
||||
* @param focusChainEnabled Whether focus chain (task_progress) is enabled for this task
|
||||
*/
|
||||
export function generateGemini3Template(focusChainEnabled: boolean): string {
|
||||
const detectedShell = getShell()
|
||||
|
||||
let isPowerShell = false
|
||||
try {
|
||||
isPowerShell =
|
||||
detectedShell != null &&
|
||||
typeof detectedShell === "string" &&
|
||||
(detectedShell.toLowerCase().includes("powershell") || detectedShell.toLowerCase().includes("pwsh"))
|
||||
} catch {}
|
||||
|
||||
return `<explicit_instructions type="deep-planning">
|
||||
Your task is to create a comprehensive implementation plan before writing any code. This process has five distinct steps that must be completed in order:
|
||||
1. Silent Read Investigation
|
||||
2. Silent Terminal Investigation
|
||||
3. Discussion and Questions
|
||||
4. Create Implementation Plan Document
|
||||
5. Create new_task for Implementation Phase
|
||||
|
||||
${focusChainEnabled ? `You should track these five steps in your task_progress parameter, and update it only when steps are completed.` : ""}
|
||||
Your behavior should be methodical and thorough - take time to understand the codebase completely before making any recommendations. The quality of your investigation and use of targeted reads/searches directly impacts the success of the implementation.
|
||||
|
||||
<IMPORTANT>
|
||||
Execute only exploration and plan generation steps until explicitly instructed by the user to proceed with coding.
|
||||
You must thoroughly understand the existing codebase before proposing any changes.
|
||||
Perform your research without commentary or narration. Execute commands and read files without explaining what you're about to do. Only speak up if you have specific questions for the user.
|
||||
</IMPORTANT>
|
||||
|
||||
## STEP 1: Silent Read Investigation
|
||||
|
||||
### Required Research Activities
|
||||
You MUST first use the read_file tool to examine several source files, configuration files, and documentation to better inform subsequent research steps. You should only use read_file to prepare for more granular searching. Use this step to get the big picture, then you will use the next step for granular details by searching using terminal commands. Use this tool to determine the language(s) used in the codebase, and to identify the domain(s) relevant to the user's request.
|
||||
|
||||
|
||||
## STEP 2: Silent Terminal Investigation
|
||||
|
||||
### Required Research Activities
|
||||
You MUST use terminal commands to gather information about the codebase structure and patterns relevant to the user's request.
|
||||
You will tailor these commands to explore and identify key functions, classes, methods, types, and variables that are directly, or indirectly related to the task.
|
||||
These commands must be crafted to not produce exceptionally long or verbose search results. For example, you should exclude dependency folders such as node_modules, venv or php vendor, etc. Carefully consider the scope of search patterns. Use the results of your read_file tool calls to tailor the commands for balanced search result lengths. If a command returns no results, you may loosen the search patterns or scope slightly. If a command returns hundreds or thousands of results, you should adjust subsequent commands to be more targeted.
|
||||
Execute these commands to build your understanding. Adjust subsequent commands based on the output you have received from each previous command, informing the scope and direction of your search.
|
||||
You should only execute one command at a time for the first 1-3 commands. Do not chain search commands until you have executed and interpreted the results of several search commands, then use the context you have gathered to inform more complex chained commands.
|
||||
|
||||
Here are some example commands, remember to adjust them as instructed previously:
|
||||
${
|
||||
isPowerShell
|
||||
? // PowerShell-specific commands
|
||||
`
|
||||
# Discover project structure and file types
|
||||
Get-ChildItem -Recurse -Include "*.py","*.js","*.ts","*.java","*.cpp","*.go" | Select-Object -First 30 | Select-Object FullName
|
||||
|
||||
# Find all class and function definitions
|
||||
Get-ChildItem -Recurse -Include "*.py","*.js","*.ts","*.java","*.cpp","*.go" | Select-String -Pattern "class|function|def|interface|struct"
|
||||
|
||||
# Analyze import patterns and dependencies
|
||||
Get-ChildItem -Recurse -Include "*.py","*.js","*.ts","*.java","*.cpp" | Select-String -Pattern "import|from|require|#include" | Sort-Object | Get-Unique
|
||||
|
||||
# Find dependency manifests
|
||||
Get-ChildItem -Recurse -Include "requirements*.txt","package.json","Cargo.toml","pom.xml","Gemfile","go.mod" | Get-Content
|
||||
|
||||
# Identify technical debt and TODOs
|
||||
Get-ChildItem -Recurse -Include "*.py","*.js","*.ts","*.java","*.cpp","*.go" | Select-String -Pattern "TODO|FIXME|XXX|HACK|NOTE"
|
||||
`
|
||||
: // bash/zsh-specific commands
|
||||
`
|
||||
# Discover project structure and file types
|
||||
find . -type f -name "*.py" -o -name "*.js" -o -name "*.ts" -o -name "*.java" -o -name "*.cpp" -o -name "*.go" | head -30 | cat
|
||||
|
||||
# Find all class and function definitions
|
||||
grep -r "class\\|function\\|def\\|interface\\|struct\\|func\\|type.*struct\\|type.*interface" --include="*.py" --include="*.js" --include="*.ts" --include="*.java" --include="*.cpp" --include="*.go" . | cat
|
||||
|
||||
# Analyze import patterns and dependencies
|
||||
grep -r "import\\|from\\|require\\|#include" --include="*.py" --include="*.js" --include="*.ts" --include="*.java" --include="*.cpp" . | sort | uniq | cat
|
||||
|
||||
# Find dependency manifests
|
||||
find . -name "requirements*.txt" -o -name "package.json" -o -name "Cargo.toml" -o -name "pom.xml" -o -name "Gemfile" -o -name "go.mod" | xargs cat
|
||||
|
||||
# Identify technical debt and TODOs
|
||||
grep -r "TODO\\|FIXME\\|XXX\\|HACK\\|NOTE" --include="*.py" --include="*.js" --include="*.ts" --include="*.java" --include="*.cpp" --include="*.go" . | cat
|
||||
`
|
||||
}
|
||||
|
||||
|
||||
## STEP 3: Discussion and Questions
|
||||
|
||||
Ask the user brief, targeted questions that will influence your implementation plan. Keep your questions concise and conversational. Ask only essential questions needed to create an accurate plan.
|
||||
|
||||
**Ask questions only when necessary for:**
|
||||
- Clarifying ambiguous requirements or unclear specifications
|
||||
- Choosing between multiple equally valid implementation approaches that have significant trade-offs
|
||||
- Confirming non-trivial assumptions about existing system behavior or constraints
|
||||
- Understanding preferences for specific technical decisions that will affect the final implementation's behavior or code maintainability
|
||||
|
||||
Your questions should be direct and specific. Avoid long explanations or multiple questions in one response. Only ask one question at a time. You may ask several questions if required and within scope of the task.
|
||||
|
||||
## STEP 4: Create Implementation Plan Document
|
||||
|
||||
Once you have obtained sufficient context to understand all code modifications that will be required, create a structured markdown document containing your complete implementation plan. The document must follow this exact format with clearly marked sections:
|
||||
|
||||
### Document Structure Requirements
|
||||
|
||||
Your implementation plan must be saved as implementation_plan.md, and *must* be structured as follows:
|
||||
|
||||
<example_implementation_plan>
|
||||
# Implementation Plan
|
||||
|
||||
[Overview]
|
||||
Single sentence describing the overall goal.
|
||||
|
||||
Multiple paragraphs outlining the scope, context, and high-level approach. Explain why this implementation is needed and how it fits into the existing system.
|
||||
|
||||
[Types]
|
||||
Single sentence describing the type system changes.
|
||||
|
||||
Detailed type definitions, interfaces, enums, or data structures with complete specifications. Include field names, types, validation rules, and relationships.
|
||||
|
||||
[Files]
|
||||
Single sentence describing file modifications.
|
||||
|
||||
Detailed breakdown:
|
||||
- New files to be created (with full paths and purpose)
|
||||
- Existing files to be modified (with specific changes)
|
||||
- Files to be deleted or moved
|
||||
- Configuration file updates
|
||||
|
||||
[Functions]
|
||||
Single sentence describing function modifications.
|
||||
|
||||
Detailed breakdown:
|
||||
- New functions (name, signature, file path, purpose)
|
||||
- Modified functions (exact name, current file path, required changes)
|
||||
- Removed functions (name, file path, reason, migration strategy)
|
||||
|
||||
[Classes]
|
||||
Single sentence describing class modifications.
|
||||
|
||||
Detailed breakdown:
|
||||
- New classes (name, file path, key methods, inheritance)
|
||||
- Modified classes (exact name, file path, specific modifications)
|
||||
- Removed classes (name, file path, replacement strategy)
|
||||
|
||||
[Dependencies]
|
||||
Single sentence describing dependency modifications.
|
||||
|
||||
Details of new packages, version changes, and integration requirements.
|
||||
|
||||
[Implementation Order]
|
||||
Single sentence describing the implementation sequence.
|
||||
|
||||
Numbered steps showing the logical order of changes to minimize conflicts and ensure successful integration.
|
||||
${focusChainEnabled ? "A task_progress list of steps that will need to be completed during the implementation" : ""}
|
||||
|
||||
</example_implementation_plan>
|
||||
|
||||
## STEP 5: Create Implementation new_task
|
||||
|
||||
Use the new_task command to create a task for implementing the plan. ${focusChainEnabled ? "The task must include a <task_progress> list that breaks down the implementation into trackable steps." : ""}
|
||||
|
||||
### Task Creation Requirements
|
||||
|
||||
<IMPORTANT>
|
||||
**Standalone Product:**
|
||||
Your new task should be self-contained and reference the plan document rather than requiring additional codebase investigation. Include these specific instructions in the task description:
|
||||
|
||||
${
|
||||
focusChainEnabled
|
||||
? `**Task Progress Format:**
|
||||
You absolutely MUST include the task_progress contents in context when creating the new task. When providing it, do not wrap it in XML tags- instead provide it like this:
|
||||
|
||||
task_progress Items:
|
||||
- [ ] Step 1: Brief description of first implementation step
|
||||
- [ ] Step 2: Brief description of second implementation step
|
||||
- [ ] Step 3: Brief description of third implementation step
|
||||
- [ ] Step N: Brief description of subsequent/final implementation step(s)
|
||||
|
||||
**Markdown Implementation Plan Path:**
|
||||
You also MUST include the path to the markdown file you have created in your new task prompt. You should do this as follows:
|
||||
Refer to @path/to/file/markdown.md for a complete breakdown of the task requirements and steps. You should periodically read this file again.`
|
||||
: ""
|
||||
}
|
||||
</IMPORTANT>
|
||||
|
||||
|
||||
### Mode Switching
|
||||
|
||||
<IMPORTANT>
|
||||
When creating the new task, request a switch to "act mode" if you are currently in "plan mode". This ensures the implementation agent operates in execution mode rather than planning mode.
|
||||
</IMPORTANT>
|
||||
|
||||
## Quality Standards
|
||||
|
||||
You must be specific with exact file paths, function names, and class names. You must be comprehensive and avoid assuming implicit understanding. You must be practical and consider real-world constraints and edge cases. You must use precise technical language and avoid ambiguity.
|
||||
|
||||
Your implementation plan should be detailed enough that another developer could execute it without additional investigation.
|
||||
|
||||
---
|
||||
|
||||
**Execute all five steps in sequence. Your role is to plan thoroughly, not to implement. Code creation begins only after the new task is created and you receive explicit instruction to proceed.**
|
||||
|
||||
Below is the user's input from when they indicated that they wanted to create this comprehensive implementation plan.
|
||||
</explicit_instructions>
|
||||
`
|
||||
}
|
||||
@@ -4,5 +4,6 @@
|
||||
|
||||
export { createAnthropicVariant } from "./anthropic"
|
||||
export { createGeminiVariant } from "./gemini"
|
||||
export { createGemini3Variant } from "./gemini3"
|
||||
export { createGenericVariant } from "./generic"
|
||||
export { createGPT51Variant } from "./gpt5"
|
||||
|
||||
@@ -65,6 +65,7 @@ describe("PromptRegistry", () => {
|
||||
{ id: "gpt-5", provider: "cline", expected: ModelFamily.GPT_5, useNativeTools: false },
|
||||
{ id: "gpt-5-1", provider: "openai-native", expected: ModelFamily.NATIVE_GPT_5_1, useNativeTools: true },
|
||||
{ id: "openai/gpt-5", expected: ModelFamily.NEXT_GEN },
|
||||
{ id: "gemini3", provider: "vertex", expected: ModelFamily.GEMINI_3, useNativeTools: true },
|
||||
{ id: "unknown-model", expected: ModelFamily.GENERIC },
|
||||
]
|
||||
|
||||
|
||||
-15
@@ -250,21 +250,6 @@ Usage:
|
||||
<task_progress>Checklist here (required if you used task_progress in previous tool uses)</task_progress>
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
1. Current Work: Describe in detail what was being worked on prior to this request to create a new task. Pay special attention to the more recent messages / conversation.
|
||||
2. Key Technical Concepts: List all important technical concepts, technologies, coding conventions, and frameworks discussed, which might be relevant for the new task.
|
||||
3. Relevant Files and Code: If applicable, enumerate specific files and code sections examined, modified, or created for the task continuation. Pay special attention to the most recent messages and changes.
|
||||
4. Problem Solving: Document problems solved thus far and any ongoing troubleshooting efforts.
|
||||
5. Pending Tasks and Next Steps: Outline all pending tasks that you have explicitly been asked to work on, as well as list the next steps you will take for all outstanding work, if applicable. Include code snippets where they add clarity. For any next steps, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no information loss in context between tasks. It's important to be detailed here.
|
||||
Usage:
|
||||
<new_task>
|
||||
<context>context to preload new task with</context>
|
||||
</new_task>
|
||||
|
||||
## plan_mode_respond
|
||||
Description: Respond to the user's inquiry in an effort to plan a solution to the user's task. This tool should ONLY be used when you have already explored the relevant files and are ready to present a concrete plan. DO NOT use this tool to announce what files you're going to read - just read them first. This tool is only available in PLAN MODE. The environment_details will specify the current mode; if it is not PLAN_MODE then you should not use this tool.
|
||||
However, if while writing your response you realize you actually need to do more exploration before providing a complete plan, you can add the optional needs_more_exploration parameter to indicate this. This allows you to acknowledge that you should have done more exploration first, and signals that your next message will use exploration tools instead.
|
||||
|
||||
-15
@@ -216,21 +216,6 @@ Usage:
|
||||
<task_progress>Checklist here (required if you used task_progress in previous tool uses)</task_progress>
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
1. Current Work: Describe in detail what was being worked on prior to this request to create a new task. Pay special attention to the more recent messages / conversation.
|
||||
2. Key Technical Concepts: List all important technical concepts, technologies, coding conventions, and frameworks discussed, which might be relevant for the new task.
|
||||
3. Relevant Files and Code: If applicable, enumerate specific files and code sections examined, modified, or created for the task continuation. Pay special attention to the most recent messages and changes.
|
||||
4. Problem Solving: Document problems solved thus far and any ongoing troubleshooting efforts.
|
||||
5. Pending Tasks and Next Steps: Outline all pending tasks that you have explicitly been asked to work on, as well as list the next steps you will take for all outstanding work, if applicable. Include code snippets where they add clarity. For any next steps, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no information loss in context between tasks. It's important to be detailed here.
|
||||
Usage:
|
||||
<new_task>
|
||||
<context>context to preload new task with</context>
|
||||
</new_task>
|
||||
|
||||
## plan_mode_respond
|
||||
Description: Respond to the user's inquiry in an effort to plan a solution to the user's task. This tool should ONLY be used when you have already explored the relevant files and are ready to present a concrete plan. DO NOT use this tool to announce what files you're going to read - just read them first. This tool is only available in PLAN MODE. The environment_details will specify the current mode; if it is not PLAN_MODE then you should not use this tool.
|
||||
However, if while writing your response you realize you actually need to do more exploration before providing a complete plan, you can add the optional needs_more_exploration parameter to indicate this. This allows you to acknowledge that you should have done more exploration first, and signals that your next message will use exploration tools instead.
|
||||
|
||||
-15
@@ -224,21 +224,6 @@ Usage:
|
||||
<command>Your command here (optional)</command>
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
1. Current Work: Describe in detail what was being worked on prior to this request to create a new task. Pay special attention to the more recent messages / conversation.
|
||||
2. Key Technical Concepts: List all important technical concepts, technologies, coding conventions, and frameworks discussed, which might be relevant for the new task.
|
||||
3. Relevant Files and Code: If applicable, enumerate specific files and code sections examined, modified, or created for the task continuation. Pay special attention to the most recent messages and changes.
|
||||
4. Problem Solving: Document problems solved thus far and any ongoing troubleshooting efforts.
|
||||
5. Pending Tasks and Next Steps: Outline all pending tasks that you have explicitly been asked to work on, as well as list the next steps you will take for all outstanding work, if applicable. Include code snippets where they add clarity. For any next steps, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no information loss in context between tasks. It's important to be detailed here.
|
||||
Usage:
|
||||
<new_task>
|
||||
<context>context to preload new task with</context>
|
||||
</new_task>
|
||||
|
||||
## plan_mode_respond
|
||||
Description: Respond to the user's inquiry in an effort to plan a solution to the user's task. This tool should ONLY be used when you have already explored the relevant files and are ready to present a concrete plan. DO NOT use this tool to announce what files you're going to read - just read them first. This tool is only available in PLAN MODE. The environment_details will specify the current mode; if it is not PLAN_MODE then you should not use this tool.
|
||||
However, if while writing your response you realize you actually need to do more exploration before providing a complete plan, you can add the optional needs_more_exploration parameter to indicate this. This allows you to acknowledge that you should have done more exploration first, and signals that your next message will use exploration tools instead.
|
||||
|
||||
-15
@@ -250,21 +250,6 @@ Usage:
|
||||
<task_progress>Checklist here (required if you used task_progress in previous tool uses)</task_progress>
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
1. Current Work: Describe in detail what was being worked on prior to this request to create a new task. Pay special attention to the more recent messages / conversation.
|
||||
2. Key Technical Concepts: List all important technical concepts, technologies, coding conventions, and frameworks discussed, which might be relevant for the new task.
|
||||
3. Relevant Files and Code: If applicable, enumerate specific files and code sections examined, modified, or created for the task continuation. Pay special attention to the most recent messages and changes.
|
||||
4. Problem Solving: Document problems solved thus far and any ongoing troubleshooting efforts.
|
||||
5. Pending Tasks and Next Steps: Outline all pending tasks that you have explicitly been asked to work on, as well as list the next steps you will take for all outstanding work, if applicable. Include code snippets where they add clarity. For any next steps, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no information loss in context between tasks. It's important to be detailed here.
|
||||
Usage:
|
||||
<new_task>
|
||||
<context>context to preload new task with</context>
|
||||
</new_task>
|
||||
|
||||
## plan_mode_respond
|
||||
Description: Respond to the user's inquiry in an effort to plan a solution to the user's task. This tool should ONLY be used when you have already explored the relevant files and are ready to present a concrete plan. DO NOT use this tool to announce what files you're going to read - just read them first. This tool is only available in PLAN MODE. The environment_details will specify the current mode; if it is not PLAN_MODE then you should not use this tool.
|
||||
However, if while writing your response you realize you actually need to do more exploration before providing a complete plan, you can add the optional needs_more_exploration parameter to indicate this. This allows you to acknowledge that you should have done more exploration first, and signals that your next message will use exploration tools instead.
|
||||
|
||||
@@ -232,21 +232,6 @@ Usage:
|
||||
<task_progress>Checklist here (required if you used task_progress in previous tool uses)</task_progress>
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
1. Current Work: Describe in detail what was being worked on prior to this request to create a new task. Pay special attention to the more recent messages / conversation.
|
||||
2. Key Technical Concepts: List all important technical concepts, technologies, coding conventions, and frameworks discussed, which might be relevant for the new task.
|
||||
3. Relevant Files and Code: If applicable, enumerate specific files and code sections examined, modified, or created for the task continuation. Pay special attention to the most recent messages and changes.
|
||||
4. Problem Solving: Document problems solved thus far and any ongoing troubleshooting efforts.
|
||||
5. Pending Tasks and Next Steps: Outline all pending tasks that you have explicitly been asked to work on, as well as list the next steps you will take for all outstanding work, if applicable. Include code snippets where they add clarity. For any next steps, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no information loss in context between tasks. It's important to be detailed here.
|
||||
Usage:
|
||||
<new_task>
|
||||
<context>context to preload new task with</context>
|
||||
</new_task>
|
||||
|
||||
## plan_mode_respond
|
||||
Description: Respond to the user's inquiry in an effort to plan a solution to the user's task. This tool should ONLY be used when you have already explored the relevant files and are ready to present a concrete plan. DO NOT use this tool to announce what files you're going to read - just read them first. This tool is only available in PLAN MODE. The environment_details will specify the current mode; if it is not PLAN_MODE then you should not use this tool.
|
||||
However, if while writing your response you realize you actually need to do more exploration before providing a complete plan, you can add the optional needs_more_exploration parameter to indicate this. This allows you to acknowledge that you should have done more exploration first, and signals that your next message will use exploration tools instead.
|
||||
|
||||
@@ -198,21 +198,6 @@ Usage:
|
||||
<task_progress>Checklist here (required if you used task_progress in previous tool uses)</task_progress>
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
1. Current Work: Describe in detail what was being worked on prior to this request to create a new task. Pay special attention to the more recent messages / conversation.
|
||||
2. Key Technical Concepts: List all important technical concepts, technologies, coding conventions, and frameworks discussed, which might be relevant for the new task.
|
||||
3. Relevant Files and Code: If applicable, enumerate specific files and code sections examined, modified, or created for the task continuation. Pay special attention to the most recent messages and changes.
|
||||
4. Problem Solving: Document problems solved thus far and any ongoing troubleshooting efforts.
|
||||
5. Pending Tasks and Next Steps: Outline all pending tasks that you have explicitly been asked to work on, as well as list the next steps you will take for all outstanding work, if applicable. Include code snippets where they add clarity. For any next steps, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no information loss in context between tasks. It's important to be detailed here.
|
||||
Usage:
|
||||
<new_task>
|
||||
<context>context to preload new task with</context>
|
||||
</new_task>
|
||||
|
||||
## plan_mode_respond
|
||||
Description: Respond to the user's inquiry in an effort to plan a solution to the user's task. This tool should ONLY be used when you have already explored the relevant files and are ready to present a concrete plan. DO NOT use this tool to announce what files you're going to read - just read them first. This tool is only available in PLAN MODE. The environment_details will specify the current mode; if it is not PLAN_MODE then you should not use this tool.
|
||||
However, if while writing your response you realize you actually need to do more exploration before providing a complete plan, you can add the optional needs_more_exploration parameter to indicate this. This allows you to acknowledge that you should have done more exploration first, and signals that your next message will use exploration tools instead.
|
||||
|
||||
-15
@@ -208,21 +208,6 @@ Usage:
|
||||
<command>Your command here (optional)</command>
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
1. Current Work: Describe in detail what was being worked on prior to this request to create a new task. Pay special attention to the more recent messages / conversation.
|
||||
2. Key Technical Concepts: List all important technical concepts, technologies, coding conventions, and frameworks discussed, which might be relevant for the new task.
|
||||
3. Relevant Files and Code: If applicable, enumerate specific files and code sections examined, modified, or created for the task continuation. Pay special attention to the most recent messages and changes.
|
||||
4. Problem Solving: Document problems solved thus far and any ongoing troubleshooting efforts.
|
||||
5. Pending Tasks and Next Steps: Outline all pending tasks that you have explicitly been asked to work on, as well as list the next steps you will take for all outstanding work, if applicable. Include code snippets where they add clarity. For any next steps, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no information loss in context between tasks. It's important to be detailed here.
|
||||
Usage:
|
||||
<new_task>
|
||||
<context>context to preload new task with</context>
|
||||
</new_task>
|
||||
|
||||
## plan_mode_respond
|
||||
Description: Respond to the user's inquiry in an effort to plan a solution to the user's task. This tool should ONLY be used when you have already explored the relevant files and are ready to present a concrete plan. DO NOT use this tool to announce what files you're going to read - just read them first. This tool is only available in PLAN MODE. The environment_details will specify the current mode; if it is not PLAN_MODE then you should not use this tool.
|
||||
However, if while writing your response you realize you actually need to do more exploration before providing a complete plan, you can add the optional needs_more_exploration parameter to indicate this. This allows you to acknowledge that you should have done more exploration first, and signals that your next message will use exploration tools instead.
|
||||
|
||||
@@ -232,21 +232,6 @@ Usage:
|
||||
<task_progress>Checklist here (required if you used task_progress in previous tool uses)</task_progress>
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
1. Current Work: Describe in detail what was being worked on prior to this request to create a new task. Pay special attention to the more recent messages / conversation.
|
||||
2. Key Technical Concepts: List all important technical concepts, technologies, coding conventions, and frameworks discussed, which might be relevant for the new task.
|
||||
3. Relevant Files and Code: If applicable, enumerate specific files and code sections examined, modified, or created for the task continuation. Pay special attention to the most recent messages and changes.
|
||||
4. Problem Solving: Document problems solved thus far and any ongoing troubleshooting efforts.
|
||||
5. Pending Tasks and Next Steps: Outline all pending tasks that you have explicitly been asked to work on, as well as list the next steps you will take for all outstanding work, if applicable. Include code snippets where they add clarity. For any next steps, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no information loss in context between tasks. It's important to be detailed here.
|
||||
Usage:
|
||||
<new_task>
|
||||
<context>context to preload new task with</context>
|
||||
</new_task>
|
||||
|
||||
## plan_mode_respond
|
||||
Description: Respond to the user's inquiry in an effort to plan a solution to the user's task. This tool should ONLY be used when you have already explored the relevant files and are ready to present a concrete plan. DO NOT use this tool to announce what files you're going to read - just read them first. This tool is only available in PLAN MODE. The environment_details will specify the current mode; if it is not PLAN_MODE then you should not use this tool.
|
||||
However, if while writing your response you realize you actually need to do more exploration before providing a complete plan, you can add the optional needs_more_exploration parameter to indicate this. This allows you to acknowledge that you should have done more exploration first, and signals that your next message will use exploration tools instead.
|
||||
|
||||
@@ -250,21 +250,6 @@ Usage:
|
||||
<task_progress>Checklist here (required if you used task_progress in previous tool uses)</task_progress>
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
1. Current Work: Describe in detail what was being worked on prior to this request to create a new task. Pay special attention to the more recent messages / conversation.
|
||||
2. Key Technical Concepts: List all important technical concepts, technologies, coding conventions, and frameworks discussed, which might be relevant for the new task.
|
||||
3. Relevant Files and Code: If applicable, enumerate specific files and code sections examined, modified, or created for the task continuation. Pay special attention to the most recent messages and changes.
|
||||
4. Problem Solving: Document problems solved thus far and any ongoing troubleshooting efforts.
|
||||
5. Pending Tasks and Next Steps: Outline all pending tasks that you have explicitly been asked to work on, as well as list the next steps you will take for all outstanding work, if applicable. Include code snippets where they add clarity. For any next steps, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no information loss in context between tasks. It's important to be detailed here.
|
||||
Usage:
|
||||
<new_task>
|
||||
<context>context to preload new task with</context>
|
||||
</new_task>
|
||||
|
||||
## plan_mode_respond
|
||||
Description: Respond to the user's inquiry in an effort to plan a solution to the user's task. This tool should ONLY be used when you have already explored the relevant files and are ready to present a concrete plan. DO NOT use this tool to announce what files you're going to read - just read them first. This tool is only available in PLAN MODE. The environment_details will specify the current mode; if it is not PLAN_MODE then you should not use this tool.
|
||||
However, if while writing your response you realize you actually need to do more exploration before providing a complete plan, you can add the optional needs_more_exploration parameter to indicate this. This allows you to acknowledge that you should have done more exploration first, and signals that your next message will use exploration tools instead.
|
||||
|
||||
@@ -216,21 +216,6 @@ Usage:
|
||||
<task_progress>Checklist here (required if you used task_progress in previous tool uses)</task_progress>
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
1. Current Work: Describe in detail what was being worked on prior to this request to create a new task. Pay special attention to the more recent messages / conversation.
|
||||
2. Key Technical Concepts: List all important technical concepts, technologies, coding conventions, and frameworks discussed, which might be relevant for the new task.
|
||||
3. Relevant Files and Code: If applicable, enumerate specific files and code sections examined, modified, or created for the task continuation. Pay special attention to the most recent messages and changes.
|
||||
4. Problem Solving: Document problems solved thus far and any ongoing troubleshooting efforts.
|
||||
5. Pending Tasks and Next Steps: Outline all pending tasks that you have explicitly been asked to work on, as well as list the next steps you will take for all outstanding work, if applicable. Include code snippets where they add clarity. For any next steps, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no information loss in context between tasks. It's important to be detailed here.
|
||||
Usage:
|
||||
<new_task>
|
||||
<context>context to preload new task with</context>
|
||||
</new_task>
|
||||
|
||||
## plan_mode_respond
|
||||
Description: Respond to the user's inquiry in an effort to plan a solution to the user's task. This tool should ONLY be used when you have already explored the relevant files and are ready to present a concrete plan. DO NOT use this tool to announce what files you're going to read - just read them first. This tool is only available in PLAN MODE. The environment_details will specify the current mode; if it is not PLAN_MODE then you should not use this tool.
|
||||
However, if while writing your response you realize you actually need to do more exploration before providing a complete plan, you can add the optional needs_more_exploration parameter to indicate this. This allows you to acknowledge that you should have done more exploration first, and signals that your next message will use exploration tools instead.
|
||||
|
||||
-15
@@ -224,21 +224,6 @@ Usage:
|
||||
<command>Your command here (optional)</command>
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
1. Current Work: Describe in detail what was being worked on prior to this request to create a new task. Pay special attention to the more recent messages / conversation.
|
||||
2. Key Technical Concepts: List all important technical concepts, technologies, coding conventions, and frameworks discussed, which might be relevant for the new task.
|
||||
3. Relevant Files and Code: If applicable, enumerate specific files and code sections examined, modified, or created for the task continuation. Pay special attention to the most recent messages and changes.
|
||||
4. Problem Solving: Document problems solved thus far and any ongoing troubleshooting efforts.
|
||||
5. Pending Tasks and Next Steps: Outline all pending tasks that you have explicitly been asked to work on, as well as list the next steps you will take for all outstanding work, if applicable. Include code snippets where they add clarity. For any next steps, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no information loss in context between tasks. It's important to be detailed here.
|
||||
Usage:
|
||||
<new_task>
|
||||
<context>context to preload new task with</context>
|
||||
</new_task>
|
||||
|
||||
## plan_mode_respond
|
||||
Description: Respond to the user's inquiry in an effort to plan a solution to the user's task. This tool should ONLY be used when you have already explored the relevant files and are ready to present a concrete plan. DO NOT use this tool to announce what files you're going to read - just read them first. This tool is only available in PLAN MODE. The environment_details will specify the current mode; if it is not PLAN_MODE then you should not use this tool.
|
||||
However, if while writing your response you realize you actually need to do more exploration before providing a complete plan, you can add the optional needs_more_exploration parameter to indicate this. This allows you to acknowledge that you should have done more exploration first, and signals that your next message will use exploration tools instead.
|
||||
|
||||
@@ -250,21 +250,6 @@ Usage:
|
||||
<task_progress>Checklist here (required if you used task_progress in previous tool uses)</task_progress>
|
||||
</attempt_completion>
|
||||
|
||||
## new_task
|
||||
Description: Request to create a new task with preloaded context covering the conversation with the user up to this point and key information for continuing with the new task. With this tool, you will create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions, with a focus on the most relevant information required for the new task.
|
||||
Among other important areas of focus, this summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing with the new task. The user will be presented with a preview of your generated context and can choose to create a new task or keep chatting in the current conversation. The user may choose to start a new task at any point.
|
||||
Parameters:
|
||||
- context: (required) The context to preload the new task with. If applicable based on the current task, this should include:
|
||||
1. Current Work: Describe in detail what was being worked on prior to this request to create a new task. Pay special attention to the more recent messages / conversation.
|
||||
2. Key Technical Concepts: List all important technical concepts, technologies, coding conventions, and frameworks discussed, which might be relevant for the new task.
|
||||
3. Relevant Files and Code: If applicable, enumerate specific files and code sections examined, modified, or created for the task continuation. Pay special attention to the most recent messages and changes.
|
||||
4. Problem Solving: Document problems solved thus far and any ongoing troubleshooting efforts.
|
||||
5. Pending Tasks and Next Steps: Outline all pending tasks that you have explicitly been asked to work on, as well as list the next steps you will take for all outstanding work, if applicable. Include code snippets where they add clarity. For any next steps, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no information loss in context between tasks. It's important to be detailed here.
|
||||
Usage:
|
||||
<new_task>
|
||||
<context>context to preload new task with</context>
|
||||
</new_task>
|
||||
|
||||
## plan_mode_respond
|
||||
Description: Respond to the user's inquiry in an effort to plan a solution to the user's task. This tool should ONLY be used when you have already explored the relevant files and are ready to present a concrete plan. DO NOT use this tool to announce what files you're going to read - just read them first. This tool is only available in PLAN MODE. The environment_details will specify the current mode; if it is not PLAN_MODE then you should not use this tool.
|
||||
However, if while writing your response you realize you actually need to do more exploration before providing a complete plan, you can add the optional needs_more_exploration parameter to indicate this. This allows you to acknowledge that you should have done more exploration first, and signals that your next message will use exploration tools instead.
|
||||
|
||||
@@ -144,6 +144,8 @@ This ensures your work aligns with the existing codebase structure and avoids un
|
||||
|
||||
This tool is non-blocking, so using it frequently improves user experience and ensures long tasks are completed successfully.
|
||||
|
||||
Additionally, you MUST NOT call act_mode_respond more than once in a row. After using act_mode_respond, your next assistant message MUST either call a different tool or perform additional work without using act_mode_respond again. If you attempt to call act_mode_respond consecutively, the tool call will fail with an explicit error and you must choose a different action instead.
|
||||
|
||||
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) 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. **Code Generation Self-Review Loop**: After generating code, evaluate against an internal quality rubric using your reasoning:
|
||||
|
||||
@@ -142,6 +142,8 @@ This ensures your work aligns with the existing codebase structure and avoids un
|
||||
|
||||
This tool is non-blocking, so using it frequently improves user experience and ensures long tasks are completed successfully.
|
||||
|
||||
Additionally, you MUST NOT call act_mode_respond more than once in a row. After using act_mode_respond, your next assistant message MUST either call a different tool or perform additional work without using act_mode_respond again. If you attempt to call act_mode_respond consecutively, the tool call will fail with an explicit error and you must choose a different action instead.
|
||||
|
||||
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) 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. **Code Generation Self-Review Loop**: After generating code, evaluate against an internal quality rubric using your reasoning:
|
||||
|
||||
+2
@@ -110,6 +110,8 @@ This ensures your work aligns with the existing codebase structure and avoids un
|
||||
|
||||
This tool is non-blocking, so using it frequently improves user experience and ensures long tasks are completed successfully.
|
||||
|
||||
Additionally, you MUST NOT call act_mode_respond more than once in a row. After using act_mode_respond, your next assistant message MUST either call a different tool or perform additional work without using act_mode_respond again. If you attempt to call act_mode_respond consecutively, the tool call will fail with an explicit error and you must choose a different action instead.
|
||||
|
||||
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) 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. **Code Generation Self-Review Loop**: After generating code, evaluate against an internal quality rubric using your reasoning:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user