mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 12:21:13 -05:00
Merge remote-tracking branch 'origin/main' into aws-profile-support
This commit is contained in:
@@ -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>
|
||||
)
|
||||
|
||||
@@ -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) => (
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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").{" "}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")}>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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")}>
|
||||
|
||||
@@ -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 }}>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user