Compare commits

...
5 Commits
11 changed files with 142 additions and 32 deletions
-5
View File
@@ -1,5 +0,0 @@
---
"claude-dev": patch
---
Add MCP prompts support - prompts from connected MCP servers now appear in slash command autocomplete as `/mcp:<server>:<prompt>`
+6
View File
@@ -1,5 +1,11 @@
# Changelog # Changelog
## [3.55.0]
- Add new model: Arcee Trinity Large Preview
- Add new model: Moonshot Kimi K2.5
- Add MCP prompts support - prompts from connected MCP servers now appear in slash command autocomplete as `/mcp:<server>:<prompt>`
## [3.54.0] ## [3.54.0]
### Added ### Added
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "claude-dev", "name": "claude-dev",
"version": "3.53.1", "version": "3.55.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "claude-dev", "name": "claude-dev",
"version": "3.53.1", "version": "3.55.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@anthropic-ai/sdk": "^0.37.0", "@anthropic-ai/sdk": "^0.37.0",
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "claude-dev", "name": "claude-dev",
"displayName": "Cline", "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.", "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.54.0", "version": "3.55.0",
"icon": "assets/icons/icon.png", "icon": "assets/icons/icon.png",
"engines": { "engines": {
"vscode": "^1.84.0" "vscode": "^1.84.0"
@@ -16,7 +16,13 @@ interface WhatsNewModalProps {
export const WhatsNewModal: React.FC<WhatsNewModalProps> = ({ open, onClose, version }) => { export const WhatsNewModal: React.FC<WhatsNewModalProps> = ({ open, onClose, version }) => {
const { clineUser } = useClineAuth() const { clineUser } = useClineAuth()
const { openRouterModels, setShowChatModelSelector, refreshOpenRouterModels, navigateToSettings } = useExtensionState() const {
openRouterModels,
setShowChatModelSelector,
refreshOpenRouterModels,
navigateToSettings,
navigateToSettingsModelPicker,
} = useExtensionState()
const { handleFieldsChange } = useApiConfigurationHandlers() const { handleFieldsChange } = useApiConfigurationHandlers()
const clickedModelsRef = useRef<Set<string>>(new Set()) const clickedModelsRef = useRef<Set<string>>(new Set())
@@ -42,6 +48,19 @@ export const WhatsNewModal: React.FC<WhatsNewModalProps> = ({ open, onClose, ver
[handleFieldsChange, openRouterModels, setShowChatModelSelector, onClose], [handleFieldsChange, openRouterModels, setShowChatModelSelector, onClose],
) )
const navigateToModelPicker = useCallback(
(initialModelTab: "recommended" | "free") => {
// Switch to Cline provider first so the model picker tab works
handleFieldsChange({
planModeApiProvider: "cline",
actModeApiProvider: "cline",
})
onClose()
navigateToSettingsModelPicker({ targetSection: "api-config", initialModelTab })
},
[handleFieldsChange, navigateToSettingsModelPicker, onClose],
)
const setOpenAiCodexProvider = useCallback(() => { const setOpenAiCodexProvider = useCallback(() => {
handleFieldsChange({ handleFieldsChange({
planModeApiProvider: "openai-codex", planModeApiProvider: "openai-codex",
@@ -79,6 +98,35 @@ export const WhatsNewModal: React.FC<WhatsNewModalProps> = ({ open, onClose, ver
</Button> </Button>
) )
type InlineModelLinkProps =
| { type: "model"; modelId: string; label: string }
| { type: "picker"; pickerTab: "recommended" | "free"; label: string }
const InlineModelLink: React.FC<InlineModelLinkProps> = (props) => {
if (props.type === "picker") {
return (
<span
onClick={() => navigateToModelPicker(props.pickerTab)}
style={{ color: "var(--vscode-textLink-foreground)", cursor: "pointer" }}>
{props.label}
</span>
)
}
const isClicked = clickedModelsRef.current.has(props.modelId)
if (isClicked) {
return null
}
return (
<span
onClick={() => setModel(props.modelId)}
style={{ color: "var(--vscode-textLink-foreground)", cursor: "pointer" }}>
{props.label}
</span>
)
}
return ( return (
<Dialog onOpenChange={(isOpen) => !isOpen && onClose()} open={open}> <Dialog onOpenChange={(isOpen) => !isOpen && onClose()} open={open}>
<DialogContent <DialogContent
@@ -96,25 +144,28 @@ export const WhatsNewModal: React.FC<WhatsNewModalProps> = ({ open, onClose, ver
{/* Description */} {/* Description */}
<ul className="text-sm pl-3 list-disc" style={{ color: "var(--vscode-descriptionForeground)" }}> <ul className="text-sm pl-3 list-disc" style={{ color: "var(--vscode-descriptionForeground)" }}>
<li className="mb-2"> <li className="mb-2">
<strong>OpenAI ChatGPT Subscription Integration:</strong> Use your ChatGPT subscription directly in <strong>New free model: Arcee Trinity Large:</strong> strong coding performance with an open-weight
Cline with no additional token cost and no api keys to manage.{" "} model.{" "}
<InlineModelLink label="Try free" modelId="cline:arcee-ai/trinity-large-preview:free" type="model" />
</li>
<li className="mb-2">
<strong>Try Kimi K2.5:</strong> Moonshot's latest with advanced reasoning for complex, multi-step
coding tasks. Great for front-end tasks.{" "}
<InlineModelLink label="Try now" modelId="cline:moonshotai/kimi-k2.5" type="model" />
</li>
<li className="mb-2">
<strong>Bring your ChatGPT subscription to Cline!</strong> Use your existing plan directly with no per
token costs or API keys to manage.{" "}
<span <span
onClick={setOpenAiCodexProvider} onClick={setOpenAiCodexProvider}
style={{ color: "var(--vscode-textLink-foreground)", cursor: "pointer" }}> style={{ color: "var(--vscode-textLink-foreground)", cursor: "pointer" }}>
Sign in Connect
</span> </span>
</li> </li>
<li className="mb-2">
<strong>Jupyter Notebooks:</strong> Comprehensive AI-assisted editing of <code>.ipynb</code> files
with full cell-level context awareness.{" "}
<a
href="https://docs.cline.bot/features/jupyter-notebooks"
style={{ color: "var(--vscode-textLink-foreground)" }}>
Learn More
</a>
</li>
<li> <li>
<strong>Grok Code Fast 1</strong> and <strong>Devstral-2512</strong> are no longer free to use. <strong>Grok Code Fast 1 & Devstral are saying goodbye (to free):</strong> free promotion is done but
there are plenty models in our free tier.{" "}
<InlineModelLink label="See alternatives" pickerTab="free" type="picker" />
</li> </li>
</ul> </ul>
</div> </div>
@@ -61,6 +61,7 @@ interface ApiOptionsProps {
modelIdErrorMessage?: string modelIdErrorMessage?: string
isPopup?: boolean isPopup?: boolean
currentMode: Mode currentMode: Mode
initialModelTab?: "recommended" | "free"
} }
// This is necessary to ensure dropdown opens downward, important for when this is used in popup // This is necessary to ensure dropdown opens downward, important for when this is used in popup
@@ -87,7 +88,14 @@ declare module "vscode" {
} }
} }
const ApiOptions = ({ showModelOptions, apiErrorMessage, modelIdErrorMessage, isPopup, currentMode }: ApiOptionsProps) => { const ApiOptions = ({
showModelOptions,
apiErrorMessage,
modelIdErrorMessage,
isPopup,
currentMode,
initialModelTab,
}: ApiOptionsProps) => {
// Use full context state for immediate save payload // Use full context state for immediate save payload
const { apiConfiguration, remoteConfigSettings } = useExtensionState() const { apiConfiguration, remoteConfigSettings } = useExtensionState()
@@ -349,7 +357,12 @@ const ApiOptions = ({ showModelOptions, apiErrorMessage, modelIdErrorMessage, is
)} )}
{apiConfiguration && selectedProvider === "cline" && ( {apiConfiguration && selectedProvider === "cline" && (
<ClineProvider currentMode={currentMode} isPopup={isPopup} showModelOptions={showModelOptions} /> <ClineProvider
currentMode={currentMode}
initialModelTab={initialModelTab}
isPopup={isPopup}
showModelOptions={showModelOptions}
/>
)} )}
{apiConfiguration && selectedProvider === "asksage" && ( {apiConfiguration && selectedProvider === "asksage" && (
@@ -43,6 +43,7 @@ export interface OpenRouterModelPickerProps {
isPopup?: boolean isPopup?: boolean
currentMode: Mode currentMode: Mode
showProviderRouting?: boolean showProviderRouting?: boolean
initialTab?: "recommended" | "free"
} }
// Featured models for Cline provider organized by tabs // Featured models for Cline provider organized by tabs
@@ -89,7 +90,12 @@ export const freeModels = [
const FREE_CLINE_MODELS = freeModels.map((m) => m.id) const FREE_CLINE_MODELS = freeModels.map((m) => m.id)
const OpenRouterModelPicker: React.FC<OpenRouterModelPickerProps> = ({ isPopup, currentMode, showProviderRouting }) => { const OpenRouterModelPicker: React.FC<OpenRouterModelPickerProps> = ({
isPopup,
currentMode,
showProviderRouting,
initialTab,
}) => {
const { handleModeFieldChange, handleModeFieldsChange, handleFieldChange } = useApiConfigurationHandlers() const { handleModeFieldChange, handleModeFieldsChange, handleFieldChange } = useApiConfigurationHandlers()
const { apiConfiguration, favoritedModelIds, openRouterModels, refreshOpenRouterModels } = useExtensionState() const { apiConfiguration, favoritedModelIds, openRouterModels, refreshOpenRouterModels } = useExtensionState()
const modeFields = getModeSpecificFields(apiConfiguration, currentMode) const modeFields = getModeSpecificFields(apiConfiguration, currentMode)
@@ -97,9 +103,19 @@ const OpenRouterModelPicker: React.FC<OpenRouterModelPickerProps> = ({ isPopup,
const [isDropdownVisible, setIsDropdownVisible] = useState(false) const [isDropdownVisible, setIsDropdownVisible] = useState(false)
const [selectedIndex, setSelectedIndex] = useState(-1) const [selectedIndex, setSelectedIndex] = useState(-1)
const [activeTab, setActiveTab] = useState<"recommended" | "free">(() => { const [activeTab, setActiveTab] = useState<"recommended" | "free">(() => {
if (initialTab) {
return initialTab
}
const currentModelId = modeFields.openRouterModelId || openRouterDefaultModelId const currentModelId = modeFields.openRouterModelId || openRouterDefaultModelId
return freeModels.some((m) => m.id === currentModelId) ? "free" : "recommended" return freeModels.some((m) => m.id === currentModelId) ? "free" : "recommended"
}) })
// If a caller wants to deep-link to the Free tab (or Recommended), honor that.
useEffect(() => {
if (initialTab) {
setActiveTab(initialTab)
}
}, [initialTab])
const dropdownRef = useRef<HTMLDivElement>(null) const dropdownRef = useRef<HTMLDivElement>(null)
const itemRefs = useRef<(HTMLDivElement | null)[]>([]) const itemRefs = useRef<(HTMLDivElement | null)[]>([])
const dropdownListRef = useRef<HTMLDivElement>(null) const dropdownListRef = useRef<HTMLDivElement>(null)
@@ -131,7 +131,7 @@ const SettingsView = ({ onDone, targetSection }: SettingsViewProps) => {
[], [],
) // Empty deps - these imports never change ) // Empty deps - these imports never change
const { version, environment } = useExtensionState() const { version, environment, settingsInitialModelTab } = useExtensionState()
const [activeTab, setActiveTab] = useState<string>(targetSection || SETTINGS_TABS[0].id) const [activeTab, setActiveTab] = useState<string>(targetSection || SETTINGS_TABS[0].id)
@@ -233,10 +233,12 @@ const SettingsView = ({ onDone, targetSection }: SettingsViewProps) => {
props.onResetState = handleResetState props.onResetState = handleResetState
} else if (activeTab === "about") { } else if (activeTab === "about") {
props.version = version props.version = version
} else if (activeTab === "api-config") {
props.initialModelTab = settingsInitialModelTab
} }
return <Component {...props} /> return <Component {...props} />
}, [activeTab, handleResetState, version]) }, [activeTab, handleResetState, settingsInitialModelTab, version])
const titleColor = getEnvironmentColor(environment) const titleColor = getEnvironmentColor(environment)
@@ -9,12 +9,13 @@ interface ClineProviderProps {
showModelOptions: boolean showModelOptions: boolean
isPopup?: boolean isPopup?: boolean
currentMode: Mode currentMode: Mode
initialModelTab?: "recommended" | "free"
} }
/** /**
* The Cline provider configuration component * The Cline provider configuration component
*/ */
export const ClineProvider = ({ showModelOptions, isPopup, currentMode }: ClineProviderProps) => { export const ClineProvider = ({ showModelOptions, isPopup, currentMode, initialModelTab }: ClineProviderProps) => {
return ( return (
<div> <div>
{/* Cline Account Info Card */} {/* Cline Account Info Card */}
@@ -25,7 +26,12 @@ export const ClineProvider = ({ showModelOptions, isPopup, currentMode }: ClineP
{showModelOptions && ( {showModelOptions && (
<> <>
{/* OpenRouter Model Picker - includes Provider Routing in Advanced section */} {/* OpenRouter Model Picker - includes Provider Routing in Advanced section */}
<OpenRouterModelPicker currentMode={currentMode} isPopup={isPopup} showProviderRouting={true} /> <OpenRouterModelPicker
currentMode={currentMode}
initialTab={initialModelTab}
isPopup={isPopup}
showProviderRouting={true}
/>
</> </>
)} )}
</div> </div>
@@ -12,9 +12,10 @@ import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandler
interface ApiConfigurationSectionProps { interface ApiConfigurationSectionProps {
renderSectionHeader?: (tabId: string) => JSX.Element | null renderSectionHeader?: (tabId: string) => JSX.Element | null
initialModelTab?: "recommended" | "free"
} }
const ApiConfigurationSection = ({ renderSectionHeader }: ApiConfigurationSectionProps) => { const ApiConfigurationSection = ({ renderSectionHeader, initialModelTab }: ApiConfigurationSectionProps) => {
const { planActSeparateModelsSetting, mode, apiConfiguration } = useExtensionState() const { planActSeparateModelsSetting, mode, apiConfiguration } = useExtensionState()
const [currentTab, setCurrentTab] = useState<Mode>(mode) const [currentTab, setCurrentTab] = useState<Mode>(mode)
const { handleFieldsChange } = useApiConfigurationHandlers() const { handleFieldsChange } = useApiConfigurationHandlers()
@@ -50,11 +51,11 @@ const ApiConfigurationSection = ({ renderSectionHeader }: ApiConfigurationSectio
{/* Content container */} {/* Content container */}
<div className="-mb-3"> <div className="-mb-3">
<ApiOptions currentMode={currentTab} showModelOptions={true} /> <ApiOptions currentMode={currentTab} initialModelTab={initialModelTab} showModelOptions={true} />
</div> </div>
</div> </div>
) : ( ) : (
<ApiOptions currentMode={mode} showModelOptions={true} /> <ApiOptions currentMode={mode} initialModelTab={initialModelTab} showModelOptions={true} />
)} )}
<div className="mb-[5px]"> <div className="mb-[5px]">
@@ -54,6 +54,7 @@ export interface ExtensionStateContextType extends ExtensionState {
mcpTab?: McpViewTab mcpTab?: McpViewTab
showSettings: boolean showSettings: boolean
settingsTargetSection?: string settingsTargetSection?: string
settingsInitialModelTab?: "recommended" | "free"
showHistory: boolean showHistory: boolean
showAccount: boolean showAccount: boolean
showWorktrees: boolean showWorktrees: boolean
@@ -102,6 +103,7 @@ export interface ExtensionStateContextType extends ExtensionState {
// Navigation functions // Navigation functions
navigateToMcp: (tab?: McpViewTab) => void navigateToMcp: (tab?: McpViewTab) => void
navigateToSettings: (targetSection?: string) => void navigateToSettings: (targetSection?: string) => void
navigateToSettingsModelPicker: (opts: { targetSection?: string; initialModelTab?: "recommended" | "free" }) => void
navigateToHistory: () => void navigateToHistory: () => void
navigateToAccount: () => void navigateToAccount: () => void
navigateToWorktrees: () => void navigateToWorktrees: () => void
@@ -130,6 +132,7 @@ export const ExtensionStateContextProvider: React.FC<{
const [mcpTab, setMcpTab] = useState<McpViewTab | undefined>(undefined) const [mcpTab, setMcpTab] = useState<McpViewTab | undefined>(undefined)
const [showSettings, setShowSettings] = useState(false) const [showSettings, setShowSettings] = useState(false)
const [settingsTargetSection, setSettingsTargetSection] = useState<string | undefined>(undefined) const [settingsTargetSection, setSettingsTargetSection] = useState<string | undefined>(undefined)
const [settingsInitialModelTab, setSettingsInitialModelTab] = useState<"recommended" | "free" | undefined>(undefined)
const [showHistory, setShowHistory] = useState(false) const [showHistory, setShowHistory] = useState(false)
const [showAccount, setShowAccount] = useState(false) const [showAccount, setShowAccount] = useState(false)
const [showWorktrees, setShowWorktrees] = useState(false) const [showWorktrees, setShowWorktrees] = useState(false)
@@ -146,6 +149,7 @@ export const ExtensionStateContextProvider: React.FC<{
const hideSettings = useCallback(() => { const hideSettings = useCallback(() => {
setShowSettings(false) setShowSettings(false)
setSettingsTargetSection(undefined) setSettingsTargetSection(undefined)
setSettingsInitialModelTab(undefined)
}, []) }, [])
const hideHistory = useCallback(() => setShowHistory(false), [setShowHistory]) const hideHistory = useCallback(() => setShowHistory(false), [setShowHistory])
const hideAccount = useCallback(() => setShowAccount(false), [setShowAccount]) const hideAccount = useCallback(() => setShowAccount(false), [setShowAccount])
@@ -175,6 +179,20 @@ export const ExtensionStateContextProvider: React.FC<{
setShowAccount(false) setShowAccount(false)
setShowWorktrees(false) setShowWorktrees(false)
setSettingsTargetSection(targetSection) setSettingsTargetSection(targetSection)
setSettingsInitialModelTab(undefined)
setShowSettings(true)
},
[closeMcpView],
)
const navigateToSettingsModelPicker = useCallback(
(opts: { targetSection?: string; initialModelTab?: "recommended" | "free" }) => {
setShowHistory(false)
closeMcpView()
setShowAccount(false)
setShowWorktrees(false)
setSettingsTargetSection(opts.targetSection)
setSettingsInitialModelTab(opts.initialModelTab)
setShowSettings(true) setShowSettings(true)
}, },
[closeMcpView], [closeMcpView],
@@ -773,6 +791,7 @@ export const ExtensionStateContextProvider: React.FC<{
mcpTab, mcpTab,
showSettings, showSettings,
settingsTargetSection, settingsTargetSection,
settingsInitialModelTab,
showHistory, showHistory,
showAccount, showAccount,
showWorktrees, showWorktrees,
@@ -793,6 +812,7 @@ export const ExtensionStateContextProvider: React.FC<{
// Navigation functions // Navigation functions
navigateToMcp, navigateToMcp,
navigateToSettings, navigateToSettings,
navigateToSettingsModelPicker,
navigateToHistory, navigateToHistory,
navigateToAccount, navigateToAccount,
navigateToWorktrees, navigateToWorktrees,