Merge remote-tracking branch 'origin/main' into aws-profile-support

This commit is contained in:
Matt Rubens
2025-01-24 09:10:11 -05:00
80 changed files with 6247 additions and 1775 deletions

View File

@@ -30,41 +30,37 @@ const Announcement = ({ version, hideAnnouncement }: AnnouncementProps) => {
<span className="codicon codicon-close"></span>
</VSCodeButton>
<h2 style={{ margin: "0 0 8px" }}>
🎉{" "}Introducing Roo Cline v{minorVersion}
🎉{" "}Introducing Roo Code {minorVersion}
</h2>
<h3 style={{ margin: "0 0 8px" }}>Agent Modes Customization</h3>
<p style={{ margin: "5px 0px" }}>
Click the new <span className="codicon codicon-notebook" style={{ fontSize: "10px" }}></span> icon in
the menu bar to open the Prompts Settings and customize Agent Modes for new levels of productivity.
<ul style={{ margin: "4px 0 6px 20px", padding: 0 }}>
<li>Tailor how Roo Cline behaves in different modes: Code, Architect, and Ask.</li>
<li>Preview and verify your changes using the Preview System Prompt button.</li>
</ul>
Our biggest update yet is here - we're officially changing our name from Roo Cline to Roo Code! After
growing beyond 50,000 installations, we're ready to chart our own course. Our heartfelt thanks to
everyone in the Cline community who helped us reach this milestone.
</p>
<h3 style={{ margin: "0 0 8px" }}>Prompt Enhancement Configuration</h3>
<h3 style={{ margin: "12px 0 8px" }}>Custom Modes: Celebrating Our New Identity</h3>
<p style={{ margin: "5px 0px" }}>
Now available for all providers! Access it directly in the chat box by clicking the{" "}
<span className="codicon codicon-sparkle" style={{ fontSize: "10px" }}></span> sparkle icon next to the
input field. From there, you can customize the enhancement logic and provider to best suit your
workflow.
To mark this new chapter, we're introducing the power to shape Roo Code into any role you need! Create
specialized personas and create an entire team of agents with deeply customized prompts:
<ul style={{ margin: "4px 0 6px 20px", padding: 0 }}>
<li>Customize how prompts are enhanced for better results in your workflow.</li>
<li>
Use the sparkle icon in the chat box to select a API configuration and provider (e.g., GPT-4)
and configure your own enhancement logic.
</li>
<li>Test your changes instantly with the Preview Prompt Enhancement tool.</li>
<li>QA Engineers who write thorough test cases and catch edge cases</li>
<li>Product Managers who excel at user stories and feature prioritization</li>
<li>UI/UX Designers who craft beautiful, accessible interfaces</li>
<li>Code Reviewers who ensure quality and maintainability</li>
</ul>
Just click the <span className="codicon codicon-notebook" style={{ fontSize: "10px" }}></span> icon to
get started with Custom Modes!
</p>
<h3 style={{ margin: "12px 0 8px" }}>Join Us for the Next Chapter</h3>
<p style={{ margin: "5px 0px" }}>
We're very excited to see what you build with this new feature! Join us at
<VSCodeLink href="https://www.reddit.com/r/roocline" style={{ display: "inline" }}>
reddit.com/r/roocline
We can't wait to see how you'll push Roo Code's potential even further! Share your custom modes and join
the discussion at{" "}
<VSCodeLink href="https://www.reddit.com/r/RooCode" style={{ display: "inline" }}>
reddit.com/r/RooCode
</VSCodeLink>
to discuss and share feedback.
.
</p>
</div>
)

View File

@@ -209,7 +209,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
color: "var(--vscode-descriptionForeground)",
fontSize: "12px",
}}>
Auto-approve allows Cline to perform actions without asking for permission. Only enable for
Auto-approve allows Roo Code to perform actions without asking for permission. Only enable for
actions you fully trust.
</div>
{actions.map((action) => (

View File

@@ -242,7 +242,7 @@ const BrowserSessionRow = memo((props: BrowserSessionRowProps) => {
style={{ color: "var(--vscode-foreground)", marginBottom: "-1.5px" }}></span>
)}
<span style={{ fontWeight: "bold" }}>
<>Cline wants to use the browser:</>
<>Roo wants to use the browser:</>
</span>
</div>
<div

View File

@@ -117,7 +117,7 @@ export const ChatRowContent = ({
<span
className="codicon codicon-error"
style={{ color: errorColor, marginBottom: "-1.5px" }}></span>,
<span style={{ color: errorColor, fontWeight: "bold" }}>Cline is having trouble...</span>,
<span style={{ color: errorColor, fontWeight: "bold" }}>Roo is having trouble...</span>,
]
case "command":
return [
@@ -128,9 +128,7 @@ export const ChatRowContent = ({
className="codicon codicon-terminal"
style={{ color: normalColor, marginBottom: "-1.5px" }}></span>
),
<span style={{ color: normalColor, fontWeight: "bold" }}>
Cline wants to execute this command:
</span>,
<span style={{ color: normalColor, fontWeight: "bold" }}>Roo wants to execute this command:</span>,
]
case "use_mcp_server":
const mcpServerUse = JSON.parse(message.text || "{}") as ClineAskUseMcpServer
@@ -143,8 +141,8 @@ export const ChatRowContent = ({
style={{ color: normalColor, marginBottom: "-1.5px" }}></span>
),
<span style={{ color: normalColor, fontWeight: "bold" }}>
Cline wants to {mcpServerUse.type === "use_mcp_tool" ? "use a tool" : "access a resource"} on
the <code>{mcpServerUse.serverName}</code> MCP server:
Roo wants to {mcpServerUse.type === "use_mcp_tool" ? "use a tool" : "access a resource"} on the{" "}
<code>{mcpServerUse.serverName}</code> MCP server:
</span>,
]
case "completion_result":
@@ -208,7 +206,7 @@ export const ChatRowContent = ({
<span
className="codicon codicon-question"
style={{ color: normalColor, marginBottom: "-1.5px" }}></span>,
<span style={{ color: normalColor, fontWeight: "bold" }}>Cline has a question:</span>,
<span style={{ color: normalColor, fontWeight: "bold" }}>Roo has a question:</span>,
]
default:
return [null, null]
@@ -250,7 +248,7 @@ export const ChatRowContent = ({
<>
<div style={headerStyle}>
{toolIcon(tool.tool === "appliedDiff" ? "diff" : "edit")}
<span style={{ fontWeight: "bold" }}>Cline wants to edit this file:</span>
<span style={{ fontWeight: "bold" }}>Roo wants to edit this file:</span>
</div>
<CodeAccordian
isLoading={message.partial}
@@ -266,7 +264,7 @@ export const ChatRowContent = ({
<>
<div style={headerStyle}>
{toolIcon("new-file")}
<span style={{ fontWeight: "bold" }}>Cline wants to create a new file:</span>
<span style={{ fontWeight: "bold" }}>Roo wants to create a new file:</span>
</div>
<CodeAccordian
isLoading={message.partial}
@@ -283,7 +281,7 @@ export const ChatRowContent = ({
<div style={headerStyle}>
{toolIcon("file-code")}
<span style={{ fontWeight: "bold" }}>
{message.type === "ask" ? "Cline wants to read this file:" : "Cline read this file:"}
{message.type === "ask" ? "Roo wants to read this file:" : "Roo read this file:"}
</span>
</div>
{/* <CodeAccordian
@@ -341,8 +339,8 @@ export const ChatRowContent = ({
{toolIcon("folder-opened")}
<span style={{ fontWeight: "bold" }}>
{message.type === "ask"
? "Cline wants to view the top level files in this directory:"
: "Cline viewed the top level files in this directory:"}
? "Roo wants to view the top level files in this directory:"
: "Roo viewed the top level files in this directory:"}
</span>
</div>
<CodeAccordian
@@ -361,8 +359,8 @@ export const ChatRowContent = ({
{toolIcon("folder-opened")}
<span style={{ fontWeight: "bold" }}>
{message.type === "ask"
? "Cline wants to recursively view all files in this directory:"
: "Cline recursively viewed all files in this directory:"}
? "Roo wants to recursively view all files in this directory:"
: "Roo recursively viewed all files in this directory:"}
</span>
</div>
<CodeAccordian
@@ -381,8 +379,8 @@ export const ChatRowContent = ({
{toolIcon("file-code")}
<span style={{ fontWeight: "bold" }}>
{message.type === "ask"
? "Cline wants to view source code definition names used in this directory:"
: "Cline viewed source code definition names used in this directory:"}
? "Roo wants to view source code definition names used in this directory:"
: "Roo viewed source code definition names used in this directory:"}
</span>
</div>
<CodeAccordian
@@ -401,11 +399,11 @@ export const ChatRowContent = ({
<span style={{ fontWeight: "bold" }}>
{message.type === "ask" ? (
<>
Cline wants to search this directory for <code>{tool.regex}</code>:
Roo wants to search this directory for <code>{tool.regex}</code>:
</>
) : (
<>
Cline searched this directory for <code>{tool.regex}</code>:
Roo searched this directory for <code>{tool.regex}</code>:
</>
)}
</span>
@@ -428,9 +426,9 @@ export const ChatRowContent = ({
// {isInspecting ? <ProgressIndicator /> : toolIcon("inspect")}
// <span style={{ fontWeight: "bold" }}>
// {message.type === "ask" ? (
// <>Cline wants to inspect this website:</>
// <>Roo wants to inspect this website:</>
// ) : (
// <>Cline is inspecting this website:</>
// <>Roo is inspecting this website:</>
// )}
// </span>
// </div>
@@ -572,14 +570,17 @@ export const ChatRowContent = ({
alignItems: "flex-start",
gap: "10px",
}}>
<span style={{ display: "block", flexGrow: 1 }}>{highlightMentions(message.text)}</span>
<span style={{ display: "block", flexGrow: 1, padding: "4px" }}>
{highlightMentions(message.text)}
</span>
<VSCodeButton
appearance="icon"
style={{
padding: "3px",
flexShrink: 0,
height: "24px",
marginTop: "-6px",
marginTop: "-3px",
marginBottom: "-3px",
marginRight: "-6px",
}}
disabled={isStreaming}
@@ -663,7 +664,7 @@ export const ChatRowContent = ({
</span>
</div>
<div>
Cline won't be able to view the command's output. Please update VSCode (
Roo won't be able to view the command's output. Please update VSCode (
<code>CMD/CTRL + Shift + P</code> "Update") and make sure you're using a supported
shell: zsh, bash, fish, or PowerShell (<code>CMD/CTRL + Shift + P</code> →
"Terminal: Select Default Profile").{" "}

View File

@@ -14,7 +14,7 @@ import ContextMenu from "./ContextMenu"
import Thumbnails from "../common/Thumbnails"
import { vscode } from "../../utils/vscode"
import { WebviewMessage } from "../../../../src/shared/WebviewMessage"
import { Mode, modes } from "../../../../src/shared/modes"
import { Mode, getAllModes } from "../../../../src/shared/modes"
import { CaretIcon } from "../common/CaretIcon"
interface ChatTextAreaProps {
@@ -50,7 +50,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
},
ref,
) => {
const { filePaths, currentApiConfigName, listApiConfigMeta } = useExtensionState()
const { filePaths, currentApiConfigName, listApiConfigMeta, customModes } = useExtensionState()
const [gitCommits, setGitCommits] = useState<any[]>([])
const [showDropdown, setShowDropdown] = useState(false)
@@ -730,7 +730,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
minWidth: "70px",
flex: "0 0 auto",
}}>
{modes.map((mode) => (
{getAllModes(customModes).map((mode) => (
<option
key={mode.slug}
value={mode.slug}

View File

@@ -1,7 +1,7 @@
import { render, fireEvent, screen } from "@testing-library/react"
import { useExtensionState } from "../../../context/ExtensionStateContext"
import AutoApproveMenu from "../AutoApproveMenu"
import { codeMode, defaultPrompts } from "../../../../../src/shared/modes"
import { defaultModeSlug, defaultPrompts } from "../../../../../src/shared/modes"
// Mock the ExtensionStateContext hook
jest.mock("../../../context/ExtensionStateContext")
@@ -29,8 +29,9 @@ describe("AutoApproveMenu", () => {
requestDelaySeconds: 5,
currentApiConfigName: "default",
listApiConfigMeta: [],
mode: codeMode,
customPrompts: defaultPrompts,
mode: defaultModeSlug,
customModePrompts: defaultPrompts,
customSupportPrompts: {},
enhancementApiConfigId: "",
didHydrateState: true,
showWelcome: false,

View File

@@ -24,8 +24,8 @@ const McpEnabledToggle = () => {
marginTop: "5px",
color: "var(--vscode-descriptionForeground)",
}}>
When enabled, Cline will be able to interact with MCP servers for advanced functionality. If you're not
using MCP, you can disable this to reduce Cline's token usage.
When enabled, Roo will be able to interact with MCP servers for advanced functionality. If you're not
using MCP, you can disable this to reduce Roo's token usage.
</p>
</div>
)

View File

@@ -115,12 +115,12 @@ const McpView = ({ onDone }: McpViewProps) => {
Model Context Protocol
</VSCodeLink>{" "}
enables communication with locally running MCP servers that provide additional tools and resources
to extend Cline's capabilities. You can use{" "}
to extend Roo's capabilities. You can use{" "}
<VSCodeLink href="https://github.com/modelcontextprotocol/servers" style={{ display: "inline" }}>
community-made servers
</VSCodeLink>{" "}
or ask Cline to create new tools specific to your workflow (e.g., "add a tool that gets the latest
npm docs").
or ask Roo to create new tools specific to your workflow (e.g., "add a tool that gets the latest npm
docs").
</div>
<McpEnabledToggle />

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@ jest.mock("../../../utils/vscode", () => ({
}))
const mockExtensionState = {
customPrompts: {},
customModePrompts: {},
listApiConfigMeta: [
{ id: "config1", name: "Config 1" },
{ id: "config2", name: "Config 2" },
@@ -57,8 +57,12 @@ describe("PromptsView", () => {
expect(architectTab).toHaveAttribute("data-active", "false")
})
it("switches between tabs correctly", () => {
renderPromptsView({ mode: "code" })
it("switches between tabs correctly", async () => {
const { rerender } = render(
<ExtensionStateContext.Provider value={{ ...mockExtensionState, mode: "code" } as any}>
<PromptsView onDone={jest.fn()} />
</ExtensionStateContext.Provider>,
)
const codeTab = screen.getByTestId("code-tab")
const askTab = screen.getByTestId("ask-tab")
@@ -68,16 +72,27 @@ describe("PromptsView", () => {
expect(codeTab).toHaveAttribute("data-active", "true")
expect(askTab).toHaveAttribute("data-active", "false")
expect(architectTab).toHaveAttribute("data-active", "false")
expect(architectTab).toHaveAttribute("data-active", "false")
// Click Ask tab
// Click Ask tab and update context
fireEvent.click(askTab)
rerender(
<ExtensionStateContext.Provider value={{ ...mockExtensionState, mode: "ask" } as any}>
<PromptsView onDone={jest.fn()} />
</ExtensionStateContext.Provider>,
)
expect(askTab).toHaveAttribute("data-active", "true")
expect(codeTab).toHaveAttribute("data-active", "false")
expect(architectTab).toHaveAttribute("data-active", "false")
// Click Architect tab
// Click Architect tab and update context
fireEvent.click(architectTab)
rerender(
<ExtensionStateContext.Provider value={{ ...mockExtensionState, mode: "architect" } as any}>
<PromptsView onDone={jest.fn()} />
</ExtensionStateContext.Provider>,
)
expect(architectTab).toHaveAttribute("data-active", "true")
expect(askTab).toHaveAttribute("data-active", "false")
expect(codeTab).toHaveAttribute("data-active", "false")
@@ -105,22 +120,56 @@ describe("PromptsView", () => {
})
})
it("resets prompt to default value", () => {
renderPromptsView()
it("resets role definition only for built-in modes", async () => {
const customMode = {
slug: "custom-mode",
name: "Custom Mode",
roleDefinition: "Custom role",
groups: [],
}
const resetButton = screen.getByTestId("reset-prompt-button")
fireEvent.click(resetButton)
// Test with built-in mode (code)
const { unmount } = render(
<ExtensionStateContext.Provider
value={{ ...mockExtensionState, mode: "code", customModes: [customMode] } as any}>
<PromptsView onDone={jest.fn()} />
</ExtensionStateContext.Provider>,
)
// Find and click the role definition reset button
const resetButton = screen.getByTestId("role-definition-reset")
expect(resetButton).toBeInTheDocument()
await fireEvent.click(resetButton)
// Verify it only resets role definition
expect(vscode.postMessage).toHaveBeenCalledWith({
type: "updatePrompt",
promptMode: "code",
customPrompt: { roleDefinition: undefined },
})
// Cleanup before testing custom mode
unmount()
// Test with custom mode
render(
<ExtensionStateContext.Provider
value={{ ...mockExtensionState, mode: "custom-mode", customModes: [customMode] } as any}>
<PromptsView onDone={jest.fn()} />
</ExtensionStateContext.Provider>,
)
// Verify reset button is not present for custom mode
expect(screen.queryByTestId("role-definition-reset")).not.toBeInTheDocument()
})
it("handles API configuration selection", () => {
renderPromptsView()
// Click the ENHANCE tab first to show the API config dropdown
const enhanceTab = screen.getByTestId("ENHANCE-tab")
fireEvent.click(enhanceTab)
const dropdown = screen.getByTestId("api-config-dropdown")
fireEvent(
dropdown,

View File

@@ -1,4 +1,4 @@
import { Checkbox, Dropdown } from "vscrui"
import { Checkbox, Dropdown, Pane } from "vscrui"
import type { DropdownOption } from "vscrui"
import { VSCodeLink, VSCodeRadio, VSCodeRadioGroup, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
import { Fragment, memo, useCallback, useEffect, useMemo, useState } from "react"
@@ -45,7 +45,7 @@ interface ApiOptionsProps {
}
const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) => {
const { apiConfiguration, setApiConfiguration, uriScheme, handleInputChange } = useExtensionState()
const { apiConfiguration, uriScheme, handleInputChange } = useExtensionState()
const [ollamaModels, setOllamaModels] = useState<string[]>([])
const [lmStudioModels, setLmStudioModels] = useState<string[]>([])
const [vsCodeLmModels, setVsCodeLmModels] = useState<vscodemodels.LanguageModelChatSelector[]>([])
@@ -156,7 +156,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
value={apiConfiguration?.apiKey || ""}
style={{ width: "100%" }}
type="password"
onChange={handleInputChange("apiKey")}
onInput={handleInputChange("apiKey")}
placeholder="Enter API Key...">
<span style={{ fontWeight: 500 }}>Anthropic API Key</span>
</VSCodeTextField>
@@ -166,7 +166,11 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
onChange={(checked: boolean) => {
setAnthropicBaseUrlSelected(checked)
if (!checked) {
setApiConfiguration({ ...apiConfiguration, anthropicBaseUrl: "" })
handleInputChange("anthropicBaseUrl")({
target: {
value: "",
},
})
}
}}>
Use custom base URL
@@ -177,7 +181,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
value={apiConfiguration?.anthropicBaseUrl || ""}
style={{ width: "100%", marginTop: 3 }}
type="url"
onChange={handleInputChange("anthropicBaseUrl")}
onInput={handleInputChange("anthropicBaseUrl")}
placeholder="Default: https://api.anthropic.com"
/>
)}
@@ -206,7 +210,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
value={apiConfiguration?.glamaApiKey || ""}
style={{ width: "100%" }}
type="password"
onChange={handleInputChange("glamaApiKey")}
onInput={handleInputChange("glamaApiKey")}
placeholder="Enter API Key...">
<span style={{ fontWeight: 500 }}>Glama API Key</span>
</VSCodeTextField>
@@ -235,7 +239,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
value={apiConfiguration?.openAiNativeApiKey || ""}
style={{ width: "100%" }}
type="password"
onChange={handleInputChange("openAiNativeApiKey")}
onInput={handleInputChange("openAiNativeApiKey")}
placeholder="Enter API Key...">
<span style={{ fontWeight: 500 }}>OpenAI API Key</span>
</VSCodeTextField>
@@ -263,7 +267,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
value={apiConfiguration?.mistralApiKey || ""}
style={{ width: "100%" }}
type="password"
onChange={handleInputChange("mistralApiKey")}
onInput={handleInputChange("mistralApiKey")}
placeholder="Enter API Key...">
<span style={{ fontWeight: 500 }}>Mistral API Key</span>
</VSCodeTextField>
@@ -294,7 +298,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
value={apiConfiguration?.openRouterApiKey || ""}
style={{ width: "100%" }}
type="password"
onChange={handleInputChange("openRouterApiKey")}
onInput={handleInputChange("openRouterApiKey")}
placeholder="Enter API Key...">
<span style={{ fontWeight: 500 }}>OpenRouter API Key</span>
</VSCodeTextField>
@@ -448,7 +452,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
<VSCodeTextField
value={apiConfiguration?.vertexProjectId || ""}
style={{ width: "100%" }}
onChange={handleInputChange("vertexProjectId")}
onInput={handleInputChange("vertexProjectId")}
placeholder="Enter Project ID...">
<span style={{ fontWeight: 500 }}>Google Cloud Project ID</span>
</VSCodeTextField>
@@ -506,7 +510,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
value={apiConfiguration?.geminiApiKey || ""}
style={{ width: "100%" }}
type="password"
onChange={handleInputChange("geminiApiKey")}
onInput={handleInputChange("geminiApiKey")}
placeholder="Enter API Key...">
<span style={{ fontWeight: 500 }}>Gemini API Key</span>
</VSCodeTextField>
@@ -534,7 +538,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
value={apiConfiguration?.openAiBaseUrl || ""}
style={{ width: "100%" }}
type="url"
onChange={handleInputChange("openAiBaseUrl")}
onInput={handleInputChange("openAiBaseUrl")}
placeholder={"Enter base URL..."}>
<span style={{ fontWeight: 500 }}>Base URL</span>
</VSCodeTextField>
@@ -542,7 +546,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
value={apiConfiguration?.openAiApiKey || ""}
style={{ width: "100%" }}
type="password"
onChange={handleInputChange("openAiApiKey")}
onInput={handleInputChange("openAiApiKey")}
placeholder="Enter API Key...">
<span style={{ fontWeight: 500 }}>API Key</span>
</VSCodeTextField>
@@ -558,12 +562,25 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
Enable streaming
</Checkbox>
</div>
<Checkbox
checked={apiConfiguration?.openAiUseAzure ?? false}
onChange={(checked: boolean) => {
handleInputChange("openAiUseAzure")({
target: { value: checked },
})
}}>
Use Azure
</Checkbox>
<Checkbox
checked={azureApiVersionSelected}
onChange={(checked: boolean) => {
setAzureApiVersionSelected(checked)
if (!checked) {
setApiConfiguration({ ...apiConfiguration, azureApiVersion: "" })
handleInputChange("azureApiVersion")({
target: {
value: "",
},
})
}
}}>
Set Azure API version
@@ -572,10 +589,436 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
<VSCodeTextField
value={apiConfiguration?.azureApiVersion || ""}
style={{ width: "100%", marginTop: 3 }}
onChange={handleInputChange("azureApiVersion")}
onInput={handleInputChange("azureApiVersion")}
placeholder={`Default: ${azureOpenAiDefaultApiVersion}`}
/>
)}
<div
style={{
marginTop: 15,
}}
/>
<Pane
title="Model Configuration"
open={false}
actions={[
{
iconName: "refresh",
onClick: () =>
handleInputChange("openAiCustomModelInfo")({
target: { value: openAiModelInfoSaneDefaults },
}),
},
]}>
<div
style={{
padding: 15,
backgroundColor: "var(--vscode-editor-background)",
}}>
<p
style={{
fontSize: "12px",
color: "var(--vscode-descriptionForeground)",
margin: "0 0 15px 0",
lineHeight: "1.4",
}}>
Configure the capabilities and pricing for your custom OpenAI-compatible model. <br />
Be careful for the model capabilities, as they can affect how Roo Code can work.
</p>
{/* Capabilities Section */}
<div
style={{
marginBottom: 20,
padding: 12,
backgroundColor: "var(--vscode-editor-inactiveSelectionBackground)",
borderRadius: 4,
}}>
<span
style={{
fontWeight: 500,
fontSize: "12px",
display: "block",
marginBottom: 12,
color: "var(--vscode-editor-foreground)",
}}>
Model Capabilities
</span>
<div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
<div className="token-config-field">
<VSCodeTextField
value={
apiConfiguration?.openAiCustomModelInfo?.maxTokens?.toString() ||
openAiModelInfoSaneDefaults.maxTokens?.toString() ||
""
}
type="text"
style={{
width: "100%",
borderColor: (() => {
const value = apiConfiguration?.openAiCustomModelInfo?.maxTokens
if (!value) return "var(--vscode-input-border)"
return value > 0
? "var(--vscode-charts-green)"
: "var(--vscode-errorForeground)"
})(),
}}
title="Maximum number of tokens the model can generate in a single response"
onChange={(e: any) => {
const value = parseInt(e.target.value)
handleInputChange("openAiCustomModelInfo")({
target: {
value: {
...(apiConfiguration?.openAiCustomModelInfo ||
openAiModelInfoSaneDefaults),
maxTokens: isNaN(value) ? undefined : value,
},
},
})
}}
placeholder="e.g. 4096">
<span style={{ fontWeight: 500 }}>Max Output Tokens</span>
</VSCodeTextField>
<div
style={{
fontSize: "11px",
color: "var(--vscode-descriptionForeground)",
marginTop: 4,
display: "flex",
alignItems: "center",
gap: 4,
}}>
<i className="codicon codicon-info" style={{ fontSize: "12px" }}></i>
<span>
Maximum number of tokens the model can generate in a response. <br />
(-1 is depend on server)
</span>
</div>
</div>
<div className="token-config-field">
<VSCodeTextField
value={
apiConfiguration?.openAiCustomModelInfo?.contextWindow?.toString() ||
openAiModelInfoSaneDefaults.contextWindow?.toString() ||
""
}
type="text"
style={{
width: "100%",
borderColor: (() => {
const value = apiConfiguration?.openAiCustomModelInfo?.contextWindow
if (!value) return "var(--vscode-input-border)"
return value > 0
? "var(--vscode-charts-green)"
: "var(--vscode-errorForeground)"
})(),
}}
title="Total number of tokens (input + output) the model can process in a single request"
onChange={(e: any) => {
const parsed = parseInt(e.target.value)
handleInputChange("openAiCustomModelInfo")({
target: {
value: {
...(apiConfiguration?.openAiCustomModelInfo ||
openAiModelInfoSaneDefaults),
contextWindow:
e.target.value === ""
? undefined
: isNaN(parsed)
? openAiModelInfoSaneDefaults.contextWindow
: parsed,
},
},
})
}}
placeholder="e.g. 128000">
<span style={{ fontWeight: 500 }}>Context Window Size</span>
</VSCodeTextField>
<div
style={{
fontSize: "11px",
color: "var(--vscode-descriptionForeground)",
marginTop: 4,
display: "flex",
alignItems: "center",
gap: 4,
}}>
<i className="codicon codicon-info" style={{ fontSize: "12px" }}></i>
<span>
Total tokens (input + output) the model can process. This will help Roo
Code run correctly.
</span>
</div>
</div>
<div
style={{
backgroundColor: "var(--vscode-editor-background)",
padding: "12px",
borderRadius: "4px",
marginTop: "8px",
border: "1px solid var(--vscode-input-border)",
transition: "background-color 0.2s ease",
}}>
<span
style={{
fontSize: "11px",
fontWeight: 500,
color: "var(--vscode-editor-foreground)",
display: "block",
marginBottom: "10px",
}}>
Model Features
</span>
<div style={{ display: "flex", flexDirection: "column", gap: "12px" }}>
<div className="feature-toggle">
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
<Checkbox
checked={
apiConfiguration?.openAiCustomModelInfo?.supportsImages ??
openAiModelInfoSaneDefaults.supportsImages
}
onChange={(checked: boolean) => {
handleInputChange("openAiCustomModelInfo")({
target: {
value: {
...(apiConfiguration?.openAiCustomModelInfo ||
openAiModelInfoSaneDefaults),
supportsImages: checked,
},
},
})
}}>
<span style={{ fontWeight: 500 }}>Image Support</span>
</Checkbox>
<i
className="codicon codicon-info"
title="Enable if the model can process and understand images in the input. Required for image-based assistance and visual code understanding."
style={{
fontSize: "12px",
color: "var(--vscode-descriptionForeground)",
cursor: "help",
}}
/>
</div>
<p
style={{
fontSize: "11px",
color: "var(--vscode-descriptionForeground)",
marginLeft: "24px",
marginTop: "4px",
lineHeight: "1.4",
}}>
Allows the model to analyze and understand images, essential for
visual code assistance
</p>
</div>
<div
className="feature-toggle"
style={{
borderTop: "1px solid var(--vscode-input-border)",
paddingTop: "12px",
}}>
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
<Checkbox
checked={
apiConfiguration?.openAiCustomModelInfo
?.supportsComputerUse ?? false
}
onChange={(checked: boolean) => {
handleInputChange("openAiCustomModelInfo")({
target: {
value: {
...(apiConfiguration?.openAiCustomModelInfo ||
openAiModelInfoSaneDefaults),
supportsComputerUse: checked,
},
},
})
}}>
<span style={{ fontWeight: 500 }}>Computer Use</span>
</Checkbox>
<i
className="codicon codicon-info"
title="Enable if the model can interact with your computer through commands and file operations. Required for automated tasks and file modifications."
style={{
fontSize: "12px",
color: "var(--vscode-descriptionForeground)",
cursor: "help",
}}
/>
</div>
<p
style={{
fontSize: "11px",
color: "var(--vscode-descriptionForeground)",
marginLeft: "24px",
marginTop: "4px",
lineHeight: "1.4",
}}>
This model feature is for computer use like sonnet 3.5 support
</p>
</div>
</div>
</div>
</div>
</div>
{/* Pricing Section */}
<div
style={{
backgroundColor: "var(--vscode-editor-inactiveSelectionBackground)",
padding: "12px",
borderRadius: "4px",
marginTop: "15px",
}}>
<div style={{ marginBottom: "12px" }}>
<span
style={{
fontWeight: 500,
fontSize: "12px",
color: "var(--vscode-editor-foreground)",
display: "block",
marginBottom: "4px",
}}>
Model Pricing
</span>
<span
style={{
fontSize: "11px",
color: "var(--vscode-descriptionForeground)",
display: "block",
}}>
Configure token-based pricing in USD per million tokens
</span>
</div>
<div
style={{
display: "grid",
gridTemplateColumns: "1fr 1fr",
gap: "12px",
backgroundColor: "var(--vscode-editor-background)",
padding: "12px",
borderRadius: "4px",
}}>
<div className="price-input">
<VSCodeTextField
value={
apiConfiguration?.openAiCustomModelInfo?.inputPrice?.toString() ??
openAiModelInfoSaneDefaults.inputPrice?.toString() ??
""
}
type="text"
style={{
width: "100%",
borderColor: (() => {
const value = apiConfiguration?.openAiCustomModelInfo?.inputPrice
if (!value && value !== 0) return "var(--vscode-input-border)"
return value >= 0
? "var(--vscode-charts-green)"
: "var(--vscode-errorForeground)"
})(),
}}
onChange={(e: any) => {
const parsed = parseFloat(e.target.value)
handleInputChange("openAiCustomModelInfo")({
target: {
value: {
...(apiConfiguration?.openAiCustomModelInfo ??
openAiModelInfoSaneDefaults),
inputPrice:
e.target.value === ""
? undefined
: isNaN(parsed)
? openAiModelInfoSaneDefaults.inputPrice
: parsed,
},
},
})
}}
placeholder="e.g. 0.0001">
<div style={{ display: "flex", alignItems: "center", gap: "4px" }}>
<span style={{ fontWeight: 500 }}>Input Price</span>
<i
className="codicon codicon-info"
title="Cost per million tokens in the input/prompt. This affects the cost of sending context and instructions to the model."
style={{
fontSize: "12px",
color: "var(--vscode-descriptionForeground)",
cursor: "help",
}}
/>
</div>
</VSCodeTextField>
</div>
<div className="price-input">
<VSCodeTextField
value={
apiConfiguration?.openAiCustomModelInfo?.outputPrice?.toString() ||
openAiModelInfoSaneDefaults.outputPrice?.toString() ||
""
}
type="text"
style={{
width: "100%",
borderColor: (() => {
const value = apiConfiguration?.openAiCustomModelInfo?.outputPrice
if (!value && value !== 0) return "var(--vscode-input-border)"
return value >= 0
? "var(--vscode-charts-green)"
: "var(--vscode-errorForeground)"
})(),
}}
onChange={(e: any) => {
const parsed = parseFloat(e.target.value)
handleInputChange("openAiCustomModelInfo")({
target: {
value: {
...(apiConfiguration?.openAiCustomModelInfo ||
openAiModelInfoSaneDefaults),
outputPrice:
e.target.value === ""
? undefined
: isNaN(parsed)
? openAiModelInfoSaneDefaults.outputPrice
: parsed,
},
},
})
}}
placeholder="e.g. 0.0002">
<div style={{ display: "flex", alignItems: "center", gap: "4px" }}>
<span style={{ fontWeight: 500 }}>Output Price</span>
<i
className="codicon codicon-info"
title="Cost per million tokens in the model's response. This affects the cost of generated content and completions."
style={{
fontSize: "12px",
color: "var(--vscode-descriptionForeground)",
cursor: "help",
}}
/>
</div>
</VSCodeTextField>
</div>
</div>
</div>
</div>
</Pane>
<div
style={{
marginTop: 15,
}}
/>
{/* end Model Info Configuration */}
<p
style={{
fontSize: "12px",
@@ -583,7 +1026,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
color: "var(--vscode-descriptionForeground)",
}}>
<span style={{ color: "var(--vscode-errorForeground)" }}>
(<span style={{ fontWeight: 500 }}>Note:</span> Cline uses complex prompts and works best
(<span style={{ fontWeight: 500 }}>Note:</span> Roo Code uses complex prompts and works best
with Claude models. Less capable models may not work as expected.)
</span>
</p>
@@ -596,14 +1039,14 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
value={apiConfiguration?.lmStudioBaseUrl || ""}
style={{ width: "100%" }}
type="url"
onChange={handleInputChange("lmStudioBaseUrl")}
onInput={handleInputChange("lmStudioBaseUrl")}
placeholder={"Default: http://localhost:1234"}>
<span style={{ fontWeight: 500 }}>Base URL (optional)</span>
</VSCodeTextField>
<VSCodeTextField
value={apiConfiguration?.lmStudioModelId || ""}
style={{ width: "100%" }}
onChange={handleInputChange("lmStudioModelId")}
onInput={handleInputChange("lmStudioModelId")}
placeholder={"e.g. meta-llama-3.1-8b-instruct"}>
<span style={{ fontWeight: 500 }}>Model ID</span>
</VSCodeTextField>
@@ -652,7 +1095,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
</VSCodeLink>{" "}
feature to use it with this extension.{" "}
<span style={{ color: "var(--vscode-errorForeground)" }}>
(<span style={{ fontWeight: 500 }}>Note:</span> Cline uses complex prompts and works best
(<span style={{ fontWeight: 500 }}>Note:</span> Roo Code uses complex prompts and works best
with Claude models. Less capable models may not work as expected.)
</span>
</p>
@@ -665,7 +1108,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
value={apiConfiguration?.deepSeekApiKey || ""}
style={{ width: "100%" }}
type="password"
onChange={handleInputChange("deepSeekApiKey")}
onInput={handleInputChange("deepSeekApiKey")}
placeholder="Enter API Key...">
<span style={{ fontWeight: 500 }}>DeepSeek API Key</span>
</VSCodeTextField>
@@ -743,7 +1186,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
fontWeight: 500,
}}>
Note: This is a very experimental integration and may not work as expected. Please report
any issues to the Roo-Cline GitHub repository.
any issues to the Roo-Code GitHub repository.
</p>
</div>
</div>
@@ -755,14 +1198,14 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
value={apiConfiguration?.ollamaBaseUrl || ""}
style={{ width: "100%" }}
type="url"
onChange={handleInputChange("ollamaBaseUrl")}
onInput={handleInputChange("ollamaBaseUrl")}
placeholder={"Default: http://localhost:11434"}>
<span style={{ fontWeight: 500 }}>Base URL (optional)</span>
</VSCodeTextField>
<VSCodeTextField
value={apiConfiguration?.ollamaModelId || ""}
style={{ width: "100%" }}
onChange={handleInputChange("ollamaModelId")}
onInput={handleInputChange("ollamaModelId")}
placeholder={"e.g. llama3.1"}>
<span style={{ fontWeight: 500 }}>Model ID</span>
</VSCodeTextField>
@@ -806,7 +1249,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
quickstart guide.
</VSCodeLink>
<span style={{ color: "var(--vscode-errorForeground)" }}>
(<span style={{ fontWeight: 500 }}>Note:</span> Cline uses complex prompts and works best
(<span style={{ fontWeight: 500 }}>Note:</span> Roo Code uses complex prompts and works best
with Claude models. Less capable models may not work as expected.)
</span>
</p>
@@ -1057,7 +1500,7 @@ export function normalizeApiConfiguration(apiConfiguration?: ApiConfiguration) {
return {
selectedProvider: provider,
selectedModelId: apiConfiguration?.openAiModelId || "",
selectedModelInfo: openAiModelInfoSaneDefaults,
selectedModelInfo: apiConfiguration?.openAiCustomModelInfo || openAiModelInfoSaneDefaults,
}
case "ollama":
return {

View File

@@ -167,17 +167,8 @@ const GlamaModelPicker: React.FC = () => {
placeholder="Search and select a model..."
value={searchTerm}
onInput={(e) => {
const newModelId = (e.target as HTMLInputElement)?.value?.toLowerCase()
const apiConfig = {
...apiConfiguration,
openAiModelId: newModelId,
}
setApiConfiguration(apiConfig)
setSearchTerm(newModelId)
setIsDropdownVisible(true)
}}
onChange={(e) => {
handleModelChange((e.target as HTMLInputElement)?.value?.toLowerCase())
setIsDropdownVisible(true)
}}
onFocus={() => setIsDropdownVisible(true)}
onKeyDown={handleKeyDown}
@@ -240,7 +231,7 @@ const GlamaModelPicker: React.FC = () => {
<VSCodeLink style={{ display: "inline", fontSize: "inherit" }} href="https://glama.ai/models">
Glama.
</VSCodeLink>
If you're unsure which model to choose, Cline works best with{" "}
If you're unsure which model to choose, Roo Code works best with{" "}
<VSCodeLink
style={{ display: "inline", fontSize: "inherit" }}
onClick={() => handleModelChange("anthropic/claude-3.5-sonnet")}>

View File

@@ -159,17 +159,8 @@ const OpenAiModelPicker: React.FC = () => {
placeholder="Search and select a model..."
value={searchTerm}
onInput={(e) => {
const newModelId = (e.target as HTMLInputElement)?.value?.toLowerCase()
const apiConfig = {
...apiConfiguration,
openAiModelId: newModelId,
}
setApiConfiguration(apiConfig)
setSearchTerm(newModelId)
setIsDropdownVisible(true)
}}
onChange={(e) => {
handleModelChange((e.target as HTMLInputElement)?.value?.toLowerCase())
setIsDropdownVisible(true)
}}
onFocus={() => setIsDropdownVisible(true)}
onKeyDown={handleKeyDown}

View File

@@ -167,17 +167,8 @@ const OpenRouterModelPicker: React.FC = () => {
placeholder="Search and select a model..."
value={searchTerm}
onInput={(e) => {
const newModelId = (e.target as HTMLInputElement)?.value?.toLowerCase()
const apiConfig = {
...apiConfiguration,
openAiModelId: newModelId,
}
setApiConfiguration(apiConfig)
setSearchTerm(newModelId)
setIsDropdownVisible(true)
}}
onChange={(e) => {
handleModelChange((e.target as HTMLInputElement)?.value?.toLowerCase())
setIsDropdownVisible(true)
}}
onFocus={() => setIsDropdownVisible(true)}
onKeyDown={handleKeyDown}
@@ -240,7 +231,7 @@ const OpenRouterModelPicker: React.FC = () => {
<VSCodeLink style={{ display: "inline", fontSize: "inherit" }} href="https://openrouter.ai/models">
OpenRouter.
</VSCodeLink>
If you're unsure which model to choose, Cline works best with{" "}
If you're unsure which model to choose, Roo Code works best with{" "}
<VSCodeLink
style={{ display: "inline", fontSize: "inherit" }}
onClick={() => handleModelChange("anthropic/claude-3.5-sonnet:beta")}>

View File

@@ -193,9 +193,9 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
<div style={{ marginBottom: 40 }}>
<h3 style={{ color: "var(--vscode-foreground)", margin: "0 0 15px 0" }}>Auto-Approve Settings</h3>
<p style={{ fontSize: "12px", marginBottom: 15, color: "var(--vscode-descriptionForeground)" }}>
The following settings allow Cline to automatically perform operations without requiring
approval. Enable these settings only if you fully trust the AI and understand the associated
security risks.
The following settings allow Roo to automatically perform operations without requiring approval.
Enable these settings only if you fully trust the AI and understand the associated security
risks.
</p>
<div style={{ marginBottom: 15 }}>
@@ -210,7 +210,7 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
marginTop: "5px",
color: "var(--vscode-descriptionForeground)",
}}>
When enabled, Cline will automatically view directory contents and read files without
When enabled, Roo will automatically view directory contents and read files without
requiring you to click the Approve button.
</p>
</div>
@@ -485,7 +485,7 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
marginTop: "5px",
color: "var(--vscode-descriptionForeground)",
}}>
When enabled, Cline will play sound effects for notifications and events.
When enabled, Roo will play sound effects for notifications and events.
</p>
</div>
{soundEnabled && (
@@ -560,7 +560,7 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
marginTop: "5px",
color: "var(--vscode-descriptionForeground)",
}}>
When enabled, Cline will be able to edit files more quickly and will automatically reject
When enabled, Roo will be able to edit files more quickly and will automatically reject
truncated full-file writes. Works best with the latest Claude 3.5 Sonnet model.
</p>
@@ -635,12 +635,12 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
}}>
<p style={{ wordWrap: "break-word", margin: 0, padding: 0 }}>
If you have any questions or feedback, feel free to open an issue at{" "}
<VSCodeLink href="https://github.com/RooVetGit/Roo-Cline" style={{ display: "inline" }}>
github.com/RooVetGit/Roo-Cline
<VSCodeLink href="https://github.com/RooVetGit/Roo-Code" style={{ display: "inline" }}>
github.com/RooVetGit/Roo-Code
</VSCodeLink>{" "}
or join{" "}
<VSCodeLink href="https://www.reddit.com/r/roocline/" style={{ display: "inline" }}>
reddit.com/r/roocline
<VSCodeLink href="https://www.reddit.com/r/RooCode/" style={{ display: "inline" }}>
reddit.com/r/RooCode
</VSCodeLink>
</p>
<p style={{ fontStyle: "italic", margin: "10px 0 0 0", padding: 0, marginBottom: 100 }}>

View File

@@ -22,7 +22,7 @@ const WelcomeView = () => {
return (
<div style={{ position: "fixed", top: 0, left: 0, right: 0, bottom: 0, padding: "0 20px" }}>
<h2>Hi, I'm Cline</h2>
<h2>Hi, I'm Roo!</h2>
<p>
I can do all kinds of tasks thanks to the latest breakthroughs in agentic coding capabilities and access
to tools that let me create & edit files, explore complex projects, use the browser, and execute

View File

@@ -14,8 +14,8 @@ import { convertTextMateToHljs } from "../utils/textMateToHljs"
import { findLastIndex } from "../../../src/shared/array"
import { McpServer } from "../../../src/shared/mcp"
import { checkExistKey } from "../../../src/shared/checkExistApiConfig"
import { Mode } from "../../../src/core/prompts/types"
import { CustomPrompts, defaultModeSlug, defaultPrompts } from "../../../src/shared/modes"
import { Mode, CustomModePrompts, defaultModeSlug, defaultPrompts, ModeConfig } from "../../../src/shared/modes"
import { CustomSupportPrompts } from "../../../src/shared/support-prompt"
export interface ExtensionStateContextType extends ExtensionState {
didHydrateState: boolean
@@ -58,7 +58,8 @@ export interface ExtensionStateContextType extends ExtensionState {
onUpdateApiConfig: (apiConfig: ApiConfiguration) => void
mode: Mode
setMode: (value: Mode) => void
setCustomPrompts: (value: CustomPrompts) => void
setCustomModePrompts: (value: CustomModePrompts) => void
setCustomSupportPrompts: (value: CustomSupportPrompts) => void
enhancementApiConfigId?: string
setEnhancementApiConfigId: (value: string) => void
experimentalDiffStrategy: boolean
@@ -66,6 +67,8 @@ export interface ExtensionStateContextType extends ExtensionState {
autoApprovalEnabled?: boolean
setAutoApprovalEnabled: (value: boolean) => void
handleInputChange: (field: keyof ApiConfiguration) => (event: any) => void
customModes: ModeConfig[]
setCustomModes: (value: ModeConfig[]) => void
}
export const ExtensionStateContext = createContext<ExtensionStateContextType | undefined>(undefined)
@@ -92,11 +95,14 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
currentApiConfigName: "default",
listApiConfigMeta: [],
mode: defaultModeSlug,
customPrompts: defaultPrompts,
customModePrompts: defaultPrompts,
customSupportPrompts: {},
enhancementApiConfigId: "",
experimentalDiffStrategy: false,
autoApprovalEnabled: false,
customModes: [],
})
const [didHydrateState, setDidHydrateState] = useState(false)
const [showWelcome, setShowWelcome] = useState(false)
const [theme, setTheme] = useState<any>(undefined)
@@ -267,13 +273,15 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
setListApiConfigMeta,
onUpdateApiConfig,
setMode: (value: Mode) => setState((prevState) => ({ ...prevState, mode: value })),
setCustomPrompts: (value) => setState((prevState) => ({ ...prevState, customPrompts: value })),
setCustomModePrompts: (value) => setState((prevState) => ({ ...prevState, customModePrompts: value })),
setCustomSupportPrompts: (value) => setState((prevState) => ({ ...prevState, customSupportPrompts: value })),
setEnhancementApiConfigId: (value) =>
setState((prevState) => ({ ...prevState, enhancementApiConfigId: value })),
setExperimentalDiffStrategy: (value) =>
setState((prevState) => ({ ...prevState, experimentalDiffStrategy: value })),
setAutoApprovalEnabled: (value) => setState((prevState) => ({ ...prevState, autoApprovalEnabled: value })),
handleInputChange,
setCustomModes: (value) => setState((prevState) => ({ ...prevState, customModes: value })),
}
return <ExtensionStateContext.Provider value={contextValue}>{children}</ExtensionStateContext.Provider>

View File

@@ -119,6 +119,11 @@ https://github.com/microsoft/vscode-webview-ui-toolkit/tree/main/src/dropdown#wi
margin-bottom: 2px;
}
/* Fix dropdown double scrollbar overflow */
#api-provider > div > ul {
overflow: unset;
}
/* Fix scrollbar in dropdown */
vscode-dropdown::part(listbox) {