mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 04:11:10 -05:00
Refactor extension state into ExtensionStateContext
This commit is contained in:
@@ -18,29 +18,19 @@ import { ExtensionMessage } from "../../../src/shared/ExtensionMessage"
|
||||
import { getKoduAddCreditsUrl, getKoduHomepageUrl, getKoduSignInUrl } from "../../../src/shared/kodu"
|
||||
import { vscode } from "../utils/vscode"
|
||||
import VSCodeButtonLink from "./VSCodeButtonLink"
|
||||
import { useExtensionState } from "../context/ExtensionStateContext"
|
||||
|
||||
interface ApiOptionsProps {
|
||||
showModelOptions: boolean
|
||||
apiConfiguration?: ApiConfiguration
|
||||
setApiConfiguration: React.Dispatch<React.SetStateAction<ApiConfiguration | undefined>>
|
||||
koduCredits?: number
|
||||
apiErrorMessage?: string
|
||||
vscodeUriScheme?: string
|
||||
setDidAuthKodu?: React.Dispatch<React.SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
const ApiOptions: React.FC<ApiOptionsProps> = ({
|
||||
showModelOptions,
|
||||
apiConfiguration,
|
||||
setApiConfiguration,
|
||||
koduCredits,
|
||||
apiErrorMessage,
|
||||
vscodeUriScheme,
|
||||
setDidAuthKodu,
|
||||
}) => {
|
||||
const ApiOptions: React.FC<ApiOptionsProps> = ({ showModelOptions, apiErrorMessage, setDidAuthKodu }) => {
|
||||
const { apiConfiguration, setApiConfiguration, koduCredits, uriScheme } = useExtensionState()
|
||||
const [, setDidFetchKoduCredits] = useState(false)
|
||||
const handleInputChange = (field: keyof ApiConfiguration) => (event: any) => {
|
||||
setApiConfiguration((prev) => ({ ...prev, [field]: event.target.value }))
|
||||
setApiConfiguration({ ...apiConfiguration, [field]: event.target.value })
|
||||
}
|
||||
|
||||
const { selectedProvider, selectedModelId, selectedModelInfo } = useMemo(() => {
|
||||
@@ -185,7 +175,7 @@ const ApiOptions: React.FC<ApiOptionsProps> = ({
|
||||
</span>
|
||||
</div>
|
||||
<VSCodeButtonLink
|
||||
href={getKoduAddCreditsUrl(vscodeUriScheme)}
|
||||
href={getKoduAddCreditsUrl(uriScheme)}
|
||||
style={{
|
||||
width: "fit-content",
|
||||
}}>
|
||||
@@ -194,9 +184,7 @@ const ApiOptions: React.FC<ApiOptionsProps> = ({
|
||||
</>
|
||||
) : (
|
||||
<div style={{ margin: "4px 0px" }}>
|
||||
<VSCodeButtonLink
|
||||
href={getKoduSignInUrl(vscodeUriScheme)}
|
||||
onClick={() => setDidAuthKodu?.(true)}>
|
||||
<VSCodeButtonLink href={getKoduSignInUrl(uriScheme)} onClick={() => setDidAuthKodu?.(true)}>
|
||||
Sign in to Kodu
|
||||
</VSCodeButtonLink>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
|
||||
import { ClaudeAsk, ClaudeMessage, ClaudeSay, ClaudeSayTool } from "../../../src/shared/ExtensionMessage"
|
||||
import { COMMAND_OUTPUT_STRING } from "../../../src/shared/combineCommandSequences"
|
||||
import { SyntaxHighlighterStyle } from "../utils/getSyntaxHighlighterStyleFromTheme"
|
||||
import CodeBlock from "./CodeBlock/CodeBlock"
|
||||
import CodeBlock from "./CodeBlock"
|
||||
import Thumbnails from "./Thumbnails"
|
||||
import { ApiProvider } from "../../../src/shared/api"
|
||||
|
||||
|
||||
@@ -4,56 +4,50 @@ import vsDarkPlus from "react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-
|
||||
import DynamicTextArea from "react-textarea-autosize"
|
||||
import { useEvent, useMount } from "react-use"
|
||||
import { Virtuoso, type VirtuosoHandle } from "react-virtuoso"
|
||||
import { ClaudeAsk, ClaudeMessage, ExtensionMessage } from "../../../src/shared/ExtensionMessage"
|
||||
import { getApiMetrics } from "../../../src/shared/getApiMetrics"
|
||||
import { ClaudeAsk, ExtensionMessage } from "../../../src/shared/ExtensionMessage"
|
||||
import { combineApiRequests } from "../../../src/shared/combineApiRequests"
|
||||
import { combineCommandSequences } from "../../../src/shared/combineCommandSequences"
|
||||
import { getApiMetrics } from "../../../src/shared/getApiMetrics"
|
||||
import { useExtensionState } from "../context/ExtensionStateContext"
|
||||
import { getSyntaxHighlighterStyleFromTheme } from "../utils/getSyntaxHighlighterStyleFromTheme"
|
||||
import { vscode } from "../utils/vscode"
|
||||
import Announcement from "./Announcement"
|
||||
import ChatRow from "./ChatRow"
|
||||
import HistoryPreview from "./HistoryPreview"
|
||||
import KoduPromo from "./KoduPromo"
|
||||
import TaskHeader from "./TaskHeader"
|
||||
import Thumbnails from "./Thumbnails"
|
||||
import { HistoryItem } from "../../../src/shared/HistoryItem"
|
||||
import { ApiConfiguration } from "../../../src/shared/api"
|
||||
import KoduPromo from "./KoduPromo"
|
||||
|
||||
interface ChatViewProps {
|
||||
version: string
|
||||
messages: ClaudeMessage[]
|
||||
taskHistory: HistoryItem[]
|
||||
isHidden: boolean
|
||||
vscodeThemeName?: string
|
||||
showAnnouncement: boolean
|
||||
selectedModelSupportsImages: boolean
|
||||
selectedModelSupportsPromptCache: boolean
|
||||
hideAnnouncement: () => void
|
||||
showHistoryView: () => void
|
||||
apiConfiguration?: ApiConfiguration
|
||||
vscodeUriScheme?: string
|
||||
shouldShowKoduPromo: boolean
|
||||
koduCredits?: number
|
||||
}
|
||||
|
||||
const MAX_IMAGES_PER_MESSAGE = 20 // Anthropic limits to 20 images
|
||||
|
||||
const ChatView = ({
|
||||
version,
|
||||
messages,
|
||||
taskHistory,
|
||||
isHidden,
|
||||
vscodeThemeName,
|
||||
showAnnouncement,
|
||||
selectedModelSupportsImages,
|
||||
selectedModelSupportsPromptCache,
|
||||
hideAnnouncement,
|
||||
showHistoryView,
|
||||
apiConfiguration,
|
||||
vscodeUriScheme,
|
||||
shouldShowKoduPromo,
|
||||
koduCredits,
|
||||
}: ChatViewProps) => {
|
||||
const {
|
||||
version,
|
||||
claudeMessages: messages,
|
||||
taskHistory,
|
||||
themeName: vscodeThemeName,
|
||||
apiConfiguration,
|
||||
uriScheme,
|
||||
shouldShowKoduPromo,
|
||||
koduCredits,
|
||||
} = useExtensionState()
|
||||
|
||||
//const task = messages.length > 0 ? (messages[0].say === "task" ? messages[0] : undefined) : undefined) : undefined
|
||||
const task = messages.length > 0 ? messages[0] : undefined // leaving this less safe version here since if the first message is not a task, then the extension is in a bad state and needs to be debugged (see ClaudeDev.abort)
|
||||
const modifiedMessages = useMemo(() => combineApiRequests(combineCommandSequences(messages.slice(1))), [messages])
|
||||
@@ -490,7 +484,7 @@ const ChatView = ({
|
||||
onClose={handleTaskCloseButtonClick}
|
||||
isHidden={isHidden}
|
||||
koduCredits={koduCredits}
|
||||
vscodeUriScheme={vscodeUriScheme}
|
||||
vscodeUriScheme={uriScheme}
|
||||
apiProvider={apiConfiguration?.apiProvider}
|
||||
/>
|
||||
) : (
|
||||
@@ -500,11 +494,11 @@ const ChatView = ({
|
||||
version={version}
|
||||
hideAnnouncement={hideAnnouncement}
|
||||
apiConfiguration={apiConfiguration}
|
||||
vscodeUriScheme={vscodeUriScheme}
|
||||
vscodeUriScheme={uriScheme}
|
||||
/>
|
||||
)}
|
||||
{apiConfiguration?.koduApiKey === undefined && !showAnnouncement && shouldShowKoduPromo && (
|
||||
<KoduPromo vscodeUriScheme={vscodeUriScheme} style={{ margin: "10px 15px -10px 15px" }} />
|
||||
<KoduPromo style={{ margin: "10px 15px -10px 15px" }} />
|
||||
)}
|
||||
<div style={{ padding: "0 20px", flexGrow: taskHistory.length > 0 ? undefined : 1 }}>
|
||||
<h2>What can I do for you?</h2>
|
||||
@@ -520,9 +514,7 @@ const ChatView = ({
|
||||
permission), I can assist you in ways that go beyond simple code completion or tech support.
|
||||
</p>
|
||||
</div>
|
||||
{taskHistory.length > 0 && (
|
||||
<HistoryPreview taskHistory={taskHistory} showHistoryView={showHistoryView} />
|
||||
)}
|
||||
{taskHistory.length > 0 && <HistoryPreview showHistoryView={showHistoryView} />}
|
||||
</>
|
||||
)}
|
||||
{task && (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useMemo } from "react"
|
||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
|
||||
import { getLanguageFromPath } from "../../utils/getLanguageFromPath"
|
||||
import { SyntaxHighlighterStyle } from "../../utils/getSyntaxHighlighterStyleFromTheme"
|
||||
import { getLanguageFromPath } from "../utils/getLanguageFromPath"
|
||||
import { SyntaxHighlighterStyle } from "../utils/getSyntaxHighlighterStyleFromTheme"
|
||||
|
||||
/*
|
||||
const vscodeSyntaxStyle: React.CSSProperties = {
|
||||
@@ -1,13 +1,13 @@
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useExtensionState } from "../context/ExtensionStateContext"
|
||||
import { vscode } from "../utils/vscode"
|
||||
import { HistoryItem } from "../../../src/shared/HistoryItem"
|
||||
|
||||
type HistoryPreviewProps = {
|
||||
taskHistory: HistoryItem[]
|
||||
showHistoryView: () => void
|
||||
}
|
||||
|
||||
const HistoryPreview = ({ taskHistory, showHistoryView }: HistoryPreviewProps) => {
|
||||
const HistoryPreview = ({ showHistoryView }: HistoryPreviewProps) => {
|
||||
const { taskHistory } = useExtensionState()
|
||||
const handleHistorySelect = (id: string) => {
|
||||
vscode.postMessage({ type: "showTaskWithId", text: id })
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useExtensionState } from "../context/ExtensionStateContext"
|
||||
import { vscode } from "../utils/vscode"
|
||||
import { HistoryItem } from "../../../src/shared/HistoryItem"
|
||||
|
||||
type HistoryViewProps = {
|
||||
taskHistory: HistoryItem[]
|
||||
onDone: () => void
|
||||
}
|
||||
|
||||
const HistoryView = ({ taskHistory, onDone }: HistoryViewProps) => {
|
||||
const HistoryView = ({ onDone }: HistoryViewProps) => {
|
||||
const { taskHistory } = useExtensionState()
|
||||
const handleHistorySelect = (id: string) => {
|
||||
vscode.postMessage({ type: "showTaskWithId", text: id })
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import React from "react"
|
||||
import { getKoduSignInUrl } from "../../../src/shared/kodu"
|
||||
import { vscode } from "../utils/vscode"
|
||||
import { useExtensionState } from "../context/ExtensionStateContext"
|
||||
|
||||
interface KoduPromoProps {
|
||||
vscodeUriScheme?: string
|
||||
style?: React.CSSProperties
|
||||
}
|
||||
|
||||
const KoduPromo: React.FC<KoduPromoProps> = ({ vscodeUriScheme, style }) => {
|
||||
const KoduPromo: React.FC<KoduPromoProps> = ({ style }) => {
|
||||
const { uriScheme } = useExtensionState()
|
||||
|
||||
function onClose() {
|
||||
vscode.postMessage({ type: "didDismissKoduPromo" })
|
||||
}
|
||||
@@ -28,7 +30,7 @@ const KoduPromo: React.FC<KoduPromoProps> = ({ vscodeUriScheme, style }) => {
|
||||
cursor: "pointer",
|
||||
}}>
|
||||
<a
|
||||
href={getKoduSignInUrl(vscodeUriScheme)}
|
||||
href={getKoduSignInUrl(uriScheme)}
|
||||
style={{
|
||||
textDecoration: "none",
|
||||
color: "inherit",
|
||||
|
||||
@@ -5,8 +5,8 @@ import {
|
||||
VSCodeTextArea,
|
||||
VSCodeTextField,
|
||||
} from "@vscode/webview-ui-toolkit/react"
|
||||
import React, { useEffect, useState } from "react"
|
||||
import { ApiConfiguration } from "../../../src/shared/api"
|
||||
import { useEffect, useState } from "react"
|
||||
import { useExtensionState } from "../context/ExtensionStateContext"
|
||||
import { validateApiConfiguration, validateMaxRequestsPerTask } from "../utils/validate"
|
||||
import { vscode } from "../utils/vscode"
|
||||
import ApiOptions from "./ApiOptions"
|
||||
@@ -14,47 +14,35 @@ import ApiOptions from "./ApiOptions"
|
||||
const IS_DEV = false // FIXME: use flags when packaging
|
||||
|
||||
type SettingsViewProps = {
|
||||
version: string
|
||||
apiConfiguration?: ApiConfiguration
|
||||
setApiConfiguration: React.Dispatch<React.SetStateAction<ApiConfiguration | undefined>>
|
||||
koduCredits?: number
|
||||
maxRequestsPerTask: string
|
||||
setMaxRequestsPerTask: React.Dispatch<React.SetStateAction<string>>
|
||||
customInstructions: string
|
||||
setCustomInstructions: React.Dispatch<React.SetStateAction<string>>
|
||||
onDone: () => void
|
||||
alwaysAllowReadOnly: boolean
|
||||
setAlwaysAllowReadOnly: React.Dispatch<React.SetStateAction<boolean>>
|
||||
vscodeUriScheme?: string
|
||||
}
|
||||
|
||||
const SettingsView = ({
|
||||
version,
|
||||
apiConfiguration,
|
||||
setApiConfiguration,
|
||||
koduCredits,
|
||||
maxRequestsPerTask,
|
||||
setMaxRequestsPerTask,
|
||||
customInstructions,
|
||||
setCustomInstructions,
|
||||
onDone,
|
||||
alwaysAllowReadOnly,
|
||||
setAlwaysAllowReadOnly,
|
||||
vscodeUriScheme,
|
||||
}: SettingsViewProps) => {
|
||||
const SettingsView = ({ onDone }: SettingsViewProps) => {
|
||||
const {
|
||||
apiConfiguration,
|
||||
version,
|
||||
maxRequestsPerTask,
|
||||
customInstructions,
|
||||
setCustomInstructions,
|
||||
alwaysAllowReadOnly,
|
||||
setAlwaysAllowReadOnly,
|
||||
} = useExtensionState()
|
||||
const [apiErrorMessage, setApiErrorMessage] = useState<string | undefined>(undefined)
|
||||
const [maxRequestsErrorMessage, setMaxRequestsErrorMessage] = useState<string | undefined>(undefined)
|
||||
const [maxRequestsPerTaskString, setMaxRequestsPerTaskString] = useState<string>(
|
||||
maxRequestsPerTask?.toString() || ""
|
||||
)
|
||||
|
||||
const handleSubmit = () => {
|
||||
const apiValidationResult = validateApiConfiguration(apiConfiguration)
|
||||
const maxRequestsValidationResult = validateMaxRequestsPerTask(maxRequestsPerTask)
|
||||
const maxRequestsValidationResult = validateMaxRequestsPerTask(maxRequestsPerTaskString)
|
||||
|
||||
setApiErrorMessage(apiValidationResult)
|
||||
setMaxRequestsErrorMessage(maxRequestsValidationResult)
|
||||
|
||||
if (!apiValidationResult && !maxRequestsValidationResult) {
|
||||
vscode.postMessage({ type: "apiConfiguration", apiConfiguration })
|
||||
vscode.postMessage({ type: "maxRequestsPerTask", text: maxRequestsPerTask })
|
||||
vscode.postMessage({ type: "maxRequestsPerTask", text: maxRequestsPerTaskString })
|
||||
vscode.postMessage({ type: "customInstructions", text: customInstructions })
|
||||
vscode.postMessage({ type: "alwaysAllowReadOnly", bool: alwaysAllowReadOnly })
|
||||
onDone()
|
||||
@@ -112,14 +100,7 @@ const SettingsView = ({
|
||||
<div
|
||||
style={{ flexGrow: 1, overflowY: "scroll", paddingRight: 8, display: "flex", flexDirection: "column" }}>
|
||||
<div style={{ marginBottom: 5 }}>
|
||||
<ApiOptions
|
||||
apiConfiguration={apiConfiguration}
|
||||
setApiConfiguration={setApiConfiguration}
|
||||
showModelOptions={true}
|
||||
koduCredits={koduCredits}
|
||||
apiErrorMessage={apiErrorMessage}
|
||||
vscodeUriScheme={vscodeUriScheme}
|
||||
/>
|
||||
<ApiOptions showModelOptions={true} apiErrorMessage={apiErrorMessage} />
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: 5 }}>
|
||||
@@ -141,13 +122,13 @@ const SettingsView = ({
|
||||
|
||||
<div style={{ marginBottom: 5 }}>
|
||||
<VSCodeTextArea
|
||||
value={customInstructions}
|
||||
value={customInstructions ?? ""}
|
||||
style={{ width: "100%" }}
|
||||
rows={4}
|
||||
placeholder={
|
||||
'e.g. "Run unit tests at the end", "Use TypeScript with async/await", "Speak in Spanish"'
|
||||
}
|
||||
onInput={(e: any) => setCustomInstructions(e.target?.value || "")}>
|
||||
onInput={(e: any) => setCustomInstructions(e.target?.value ?? "")}>
|
||||
<span style={{ fontWeight: "500" }}>Custom Instructions</span>
|
||||
</VSCodeTextArea>
|
||||
<p
|
||||
@@ -162,10 +143,10 @@ const SettingsView = ({
|
||||
|
||||
<div>
|
||||
<VSCodeTextField
|
||||
value={maxRequestsPerTask}
|
||||
value={maxRequestsPerTaskString}
|
||||
style={{ width: "100%" }}
|
||||
placeholder="20"
|
||||
onInput={(e: any) => setMaxRequestsPerTask(e.target?.value)}>
|
||||
onInput={(e: any) => setMaxRequestsPerTaskString(e.target?.value ?? "")}>
|
||||
<span style={{ fontWeight: "500" }}>Maximum # Requests Per Task</span>
|
||||
</VSCodeTextField>
|
||||
<p
|
||||
|
||||
@@ -1,24 +1,18 @@
|
||||
import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react"
|
||||
import React, { useEffect, useState } from "react"
|
||||
import { ApiConfiguration } from "../../../src/shared/api"
|
||||
import { getKoduSignInUrl } from "../../../src/shared/kodu"
|
||||
import { useExtensionState } from "../context/ExtensionStateContext"
|
||||
import { validateApiConfiguration } from "../utils/validate"
|
||||
import { vscode } from "../utils/vscode"
|
||||
import ApiOptions from "./ApiOptions"
|
||||
import { getKoduSignInUrl } from "../../../src/shared/kodu"
|
||||
|
||||
interface WelcomeViewProps {
|
||||
apiConfiguration?: ApiConfiguration
|
||||
setApiConfiguration: React.Dispatch<React.SetStateAction<ApiConfiguration | undefined>>
|
||||
vscodeUriScheme?: string
|
||||
setDidAuthKoduFromWelcome: React.Dispatch<React.SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
const WelcomeView: React.FC<WelcomeViewProps> = ({
|
||||
apiConfiguration,
|
||||
setApiConfiguration,
|
||||
vscodeUriScheme,
|
||||
setDidAuthKoduFromWelcome,
|
||||
}) => {
|
||||
const WelcomeView: React.FC<WelcomeViewProps> = ({ setDidAuthKoduFromWelcome }) => {
|
||||
const { apiConfiguration, uriScheme } = useExtensionState()
|
||||
|
||||
const [apiErrorMessage, setApiErrorMessage] = useState<string | undefined>(undefined)
|
||||
|
||||
const disableLetsGoButton = apiErrorMessage != null
|
||||
@@ -67,20 +61,14 @@ const WelcomeView: React.FC<WelcomeViewProps> = ({
|
||||
}}></i>
|
||||
<span>
|
||||
Explore Claude's capabilities with $20 free credits from{" "}
|
||||
<VSCodeLink href={getKoduSignInUrl(vscodeUriScheme)} style={{ display: "inline" }}>
|
||||
<VSCodeLink href={getKoduSignInUrl(uriScheme)} style={{ display: "inline" }}>
|
||||
Kodu
|
||||
</VSCodeLink>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div style={{ marginTop: "10px" }}>
|
||||
<ApiOptions
|
||||
apiConfiguration={apiConfiguration}
|
||||
setApiConfiguration={setApiConfiguration}
|
||||
showModelOptions={false}
|
||||
vscodeUriScheme={vscodeUriScheme}
|
||||
setDidAuthKodu={setDidAuthKoduFromWelcome}
|
||||
/>
|
||||
<ApiOptions showModelOptions={false} setDidAuthKodu={setDidAuthKoduFromWelcome} />
|
||||
{apiConfiguration?.apiProvider !== "kodu" && (
|
||||
<VSCodeButton onClick={handleSubmit} disabled={disableLetsGoButton} style={{ marginTop: "3px" }}>
|
||||
Let's go!
|
||||
|
||||
Reference in New Issue
Block a user