Remove Kodu provider

This commit is contained in:
Saoud Rizwan
2024-08-27 21:38:01 -04:00
parent ac6f712b9c
commit 843ef29a07
22 changed files with 95 additions and 689 deletions

View File

@@ -15,54 +15,40 @@ const AppContent = () => {
const [showHistory, setShowHistory] = useState(false)
const [showWelcome, setShowWelcome] = useState<boolean>(false)
const [showAnnouncement, setShowAnnouncement] = useState(false)
const [didAuthKoduFromWelcome, setDidAuthKoduFromWelcome] = useState<boolean>(false)
const handleMessage = useCallback(
(e: MessageEvent) => {
const message: ExtensionMessage = e.data
switch (message.type) {
case "state":
const hasKey =
message.state!.apiConfiguration?.apiKey !== undefined ||
message.state!.apiConfiguration?.openRouterApiKey !== undefined ||
message.state!.apiConfiguration?.awsAccessKey !== undefined ||
message.state!.apiConfiguration?.koduApiKey !== undefined
setShowWelcome(!hasKey)
if (!hasKey) {
setDidAuthKoduFromWelcome(false)
}
// don't update showAnnouncement to false if shouldShowAnnouncement is false
if (message.state!.shouldShowAnnouncement) {
setShowAnnouncement(true)
}
break
case "action":
switch (message.action!) {
case "settingsButtonTapped":
setShowSettings(true)
setShowHistory(false)
break
case "historyButtonTapped":
setShowSettings(false)
setShowHistory(true)
break
case "chatButtonTapped":
setShowSettings(false)
setShowHistory(false)
break
case "koduAuthenticated":
if (!didAuthKoduFromWelcome) {
setShowSettings(true)
setShowHistory(false)
}
break
}
break
}
// (react-use takes care of not registering the same listener multiple times even if this callback is updated.)
},
[didAuthKoduFromWelcome]
)
const handleMessage = useCallback((e: MessageEvent) => {
const message: ExtensionMessage = e.data
switch (message.type) {
case "state":
const hasKey =
message.state!.apiConfiguration?.apiKey !== undefined ||
message.state!.apiConfiguration?.openRouterApiKey !== undefined ||
message.state!.apiConfiguration?.awsAccessKey !== undefined
setShowWelcome(!hasKey)
// don't update showAnnouncement to false if shouldShowAnnouncement is false
if (message.state!.shouldShowAnnouncement) {
setShowAnnouncement(true)
}
break
case "action":
switch (message.action!) {
case "settingsButtonTapped":
setShowSettings(true)
setShowHistory(false)
break
case "historyButtonTapped":
setShowSettings(false)
setShowHistory(true)
break
case "chatButtonTapped":
setShowSettings(false)
setShowHistory(false)
break
}
break
}
// (react-use takes care of not registering the same listener multiple times even if this callback is updated.)
}, [])
useEvent("message", handleMessage)
@@ -73,7 +59,7 @@ const AppContent = () => {
return (
<>
{showWelcome ? (
<WelcomeView setDidAuthKoduFromWelcome={setDidAuthKoduFromWelcome} />
<WelcomeView />
) : (
<>
{showSettings && <SettingsView onDone={() => setShowSettings(false)} />}

View File

@@ -1,7 +1,5 @@
import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react"
import { ApiConfiguration } from "../../../src/shared/api"
import { getKoduSignInUrl } from "../../../src/shared/kodu"
import VSCodeButtonLink from "./VSCodeButtonLink"
interface AnnouncementProps {
version: string
@@ -33,23 +31,6 @@ const Announcement = ({ version, hideAnnouncement, apiConfiguration, vscodeUriSc
</h3>
<ul style={{ margin: "0 0 8px", paddingLeft: "12px" }}>
<li>
Excited to announce that we've partnered with Anthropic and are offering <b>$20 free credits</b> to
help users get the most out of Claude Dev with increased rate limits and prompt caching! Stay tuned
for some exciting updates like easier billing, voice mode and one click deployment!
{apiConfiguration?.koduApiKey === undefined && (
<VSCodeButtonLink
appearance="secondary"
href={getKoduSignInUrl(vscodeUriScheme)}
style={{
transform: "scale(0.85)",
transformOrigin: "left center",
margin: "4px -30px 2px 0",
}}>
Claim $20 Credits on Kodu
</VSCodeButtonLink>
)}
</li>
<li>
Added "Always allow read-only operations" setting to let Claude read files and view directories
without needing to approve (off by default).

View File

@@ -1,6 +1,5 @@
import { VSCodeDropdown, VSCodeLink, VSCodeOption, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
import React, { useCallback, useEffect, useMemo, useState } from "react"
import { useEvent } from "react-use"
import React, { useMemo } from "react"
import {
ApiConfiguration,
ApiModelId,
@@ -9,26 +8,18 @@ import {
anthropicModels,
bedrockDefaultModelId,
bedrockModels,
koduDefaultModelId,
koduModels,
openRouterDefaultModelId,
openRouterModels,
} from "../../../src/shared/api"
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
apiErrorMessage?: string
setDidAuthKodu?: React.Dispatch<React.SetStateAction<boolean>>
}
const ApiOptions: React.FC<ApiOptionsProps> = ({ showModelOptions, apiErrorMessage, setDidAuthKodu }) => {
const { apiConfiguration, setApiConfiguration, koduCredits, uriScheme } = useExtensionState()
const [, setDidFetchKoduCredits] = useState(false)
const ApiOptions: React.FC<ApiOptionsProps> = ({ showModelOptions, apiErrorMessage }) => {
const { apiConfiguration, setApiConfiguration } = useExtensionState()
const handleInputChange = (field: keyof ApiConfiguration) => (event: any) => {
setApiConfiguration({ ...apiConfiguration, [field]: event.target.value })
}
@@ -69,27 +60,6 @@ const ApiOptions: React.FC<ApiOptionsProps> = ({ showModelOptions, apiErrorMessa
)
}
useEffect(() => {
if (selectedProvider === "kodu" && apiConfiguration?.koduApiKey && koduCredits === undefined) {
setDidFetchKoduCredits(false)
vscode.postMessage({ type: "fetchKoduCredits" })
}
}, [selectedProvider, apiConfiguration?.koduApiKey, koduCredits])
const handleMessage = useCallback((e: MessageEvent) => {
const message: ExtensionMessage = e.data
switch (message.type) {
case "action":
switch (message.action) {
case "koduCreditsFetched":
setDidFetchKoduCredits(true)
break
}
break
}
}, [])
useEvent("message", handleMessage)
return (
<div style={{ display: "flex", flexDirection: "column", gap: 5 }}>
<div className="dropdown-container">
@@ -97,7 +67,6 @@ const ApiOptions: React.FC<ApiOptionsProps> = ({ showModelOptions, apiErrorMessa
<span style={{ fontWeight: 500 }}>API Provider</span>
</label>
<VSCodeDropdown id="api-provider" value={selectedProvider} onChange={handleInputChange("apiProvider")}>
<VSCodeOption value="kodu">Kodu</VSCodeOption>
<VSCodeOption value="anthropic">Anthropic</VSCodeOption>
<VSCodeOption value="bedrock">AWS Bedrock</VSCodeOption>
<VSCodeOption value="openrouter">OpenRouter</VSCodeOption>
@@ -154,56 +123,6 @@ const ApiOptions: React.FC<ApiOptionsProps> = ({ showModelOptions, apiErrorMessa
</div>
)}
{selectedProvider === "kodu" && (
<div>
{apiConfiguration?.koduApiKey !== undefined ? (
<>
<div style={{ marginBottom: 5, marginTop: 3 }}>
<span style={{ color: "var(--vscode-descriptionForeground)" }}>
Signed in as {apiConfiguration?.koduEmail || "Unknown"}
</span>{" "}
<VSCodeLink
style={{ display: "inline" }}
onClick={() => vscode.postMessage({ type: "didClickKoduSignOut" })}>
(sign out?)
</VSCodeLink>
</div>
<div style={{ marginBottom: 7 }}>
Credits remaining:{" "}
<span style={{ fontWeight: 500, opacity: koduCredits !== undefined ? 1 : 0.6 }}>
{formatPrice(koduCredits || 0)}
</span>
</div>
<VSCodeButtonLink
href={getKoduAddCreditsUrl(uriScheme)}
style={{
width: "fit-content",
}}>
Add Credits
</VSCodeButtonLink>
</>
) : (
<div style={{ margin: "4px 0px" }}>
<VSCodeButtonLink href={getKoduSignInUrl(uriScheme)} onClick={() => setDidAuthKodu?.(true)}>
Sign in to Kodu
</VSCodeButtonLink>
</div>
)}
<p
style={{
fontSize: 12,
marginTop: 6,
color: "var(--vscode-descriptionForeground)",
}}>
Kodu is recommended for its high rate limits and access to the latest features like prompt
caching.
<VSCodeLink href={getKoduHomepageUrl()} style={{ display: "inline", fontSize: "12px" }}>
Learn more about Kodu here.
</VSCodeLink>
</p>
</div>
)}
{selectedProvider === "bedrock" && (
<div style={{ display: "flex", flexDirection: "column", gap: 5 }}>
<VSCodeTextField
@@ -289,7 +208,6 @@ const ApiOptions: React.FC<ApiOptionsProps> = ({ showModelOptions, apiErrorMessa
{selectedProvider === "anthropic" && createDropdown(anthropicModels)}
{selectedProvider === "openrouter" && createDropdown(openRouterModels)}
{selectedProvider === "bedrock" && createDropdown(bedrockModels)}
{selectedProvider === "kodu" && createDropdown(koduModels)}
</div>
<ModelInfoView modelInfo={selectedModelInfo} />
@@ -393,8 +311,6 @@ export function normalizeApiConfiguration(apiConfiguration?: ApiConfiguration) {
return getProviderData(openRouterModels, openRouterDefaultModelId)
case "bedrock":
return getProviderData(bedrockModels, bedrockDefaultModelId)
case "kodu":
return getProviderData(koduModels, koduDefaultModelId)
default:
return getProviderData(anthropicModels, anthropicDefaultModelId)
}

View File

@@ -281,7 +281,7 @@ const ChatRow: React.FC<ChatRowProps> = ({
<p style={{ ...pStyle, color: "var(--vscode-errorForeground)" }}>
{apiRequestFailedMessage}
</p>
{apiProvider === "kodu" && (
{/* {apiProvider === "kodu" && (
<div
style={{
display: "flex",
@@ -312,7 +312,7 @@ const ChatRow: React.FC<ChatRowProps> = ({
.
</span>
</div>
)}
)} */}
</>
)}
</>

View File

@@ -14,7 +14,6 @@ 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"
@@ -44,8 +43,6 @@ const ChatView = ({
themeName: vscodeThemeName,
apiConfiguration,
uriScheme,
shouldShowKoduPromo,
koduCredits,
} = useExtensionState()
//const task = messages.length > 0 ? (messages[0].say === "task" ? messages[0] : undefined) : undefined) : undefined
@@ -483,7 +480,6 @@ const ChatView = ({
totalCost={apiMetrics.totalCost}
onClose={handleTaskCloseButtonClick}
isHidden={isHidden}
koduCredits={koduCredits}
vscodeUriScheme={uriScheme}
apiProvider={apiConfiguration?.apiProvider}
/>
@@ -497,9 +493,6 @@ const ChatView = ({
vscodeUriScheme={uriScheme}
/>
)}
{apiConfiguration?.koduApiKey === undefined && !showAnnouncement && shouldShowKoduPromo && (
<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>
<p>

View File

@@ -1,71 +0,0 @@
import React from "react"
import { getKoduSignInUrl } from "../../../src/shared/kodu"
import { vscode } from "../utils/vscode"
import { useExtensionState } from "../context/ExtensionStateContext"
interface KoduPromoProps {
style?: React.CSSProperties
}
const KoduPromo: React.FC<KoduPromoProps> = ({ style }) => {
const { uriScheme } = useExtensionState()
function onClose() {
vscode.postMessage({ type: "didDismissKoduPromo" })
}
return (
<div style={{ ...style }}>
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
backgroundColor: "var(--vscode-editor-inactiveSelectionBackground)",
color: "var(--vscode-textLink-foreground)",
padding: "6px 8px",
borderRadius: "3px",
margin: "0 0 8px 0px",
fontSize: "12px",
cursor: "pointer",
}}>
<a
href={getKoduSignInUrl(uriScheme)}
style={{
textDecoration: "none",
color: "inherit",
outline: "none",
display: "flex",
alignItems: "center",
}}>
<i
className="codicon codicon-info"
style={{
marginRight: 6,
fontSize: 16,
}}></i>
<span>Claim $20 free credits from Kodu</span>
</a>
<button
onClick={onClose}
style={{
background: "none",
border: "none",
color: "var(--vscode-textLink-foreground)",
cursor: "pointer",
fontSize: "12px",
opacity: 0.7,
padding: 0,
marginLeft: 4,
marginTop: 2,
}}
onMouseEnter={(e) => (e.currentTarget.style.opacity = "1")}
onMouseLeave={(e) => (e.currentTarget.style.opacity = "0.7")}>
<i className="codicon codicon-close"></i>
</button>
</div>
</div>
)
}
export default KoduPromo

View File

@@ -1,12 +1,10 @@
import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react"
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
import React, { useEffect, useRef, useState } from "react"
import { useWindowSize } from "react-use"
import { ApiProvider } from "../../../src/shared/api"
import { ClaudeMessage } from "../../../src/shared/ExtensionMessage"
import { vscode } from "../utils/vscode"
import Thumbnails from "./Thumbnails"
import { formatPrice } from "./ApiOptions"
import { getKoduAddCreditsUrl } from "../../../src/shared/kodu"
import { ApiProvider } from "../../../src/shared/api"
interface TaskHeaderProps {
task: ClaudeMessage
@@ -18,7 +16,6 @@ interface TaskHeaderProps {
totalCost: number
onClose: () => void
isHidden: boolean
koduCredits?: number
vscodeUriScheme?: string
apiProvider?: ApiProvider
}
@@ -33,7 +30,6 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
totalCost,
onClose,
isHidden,
koduCredits,
vscodeUriScheme,
apiProvider,
}) => {
@@ -258,7 +254,7 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
</div>
</div>
</div>
{apiProvider === "kodu" && (
{/* {apiProvider === "kodu" && (
<div
style={{
backgroundColor: "color-mix(in srgb, var(--vscode-badge-background) 50%, transparent)",
@@ -285,7 +281,7 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
)}
</div>
</div>
)}
)} */}
</div>
)
}

View File

@@ -1,17 +1,14 @@
import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react"
import React, { useEffect, useState } from "react"
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"
interface WelcomeViewProps {
setDidAuthKoduFromWelcome: React.Dispatch<React.SetStateAction<boolean>>
}
interface WelcomeViewProps {}
const WelcomeView: React.FC<WelcomeViewProps> = ({ setDidAuthKoduFromWelcome }) => {
const { apiConfiguration, uriScheme } = useExtensionState()
const WelcomeView: React.FC<WelcomeViewProps> = () => {
const { apiConfiguration } = useExtensionState()
const [apiErrorMessage, setApiErrorMessage] = useState<string | undefined>(undefined)
@@ -41,39 +38,11 @@ const WelcomeView: React.FC<WelcomeViewProps> = ({ setDidAuthKoduFromWelcome })
<b>To get started, this extension needs an API provider for Claude 3.5 Sonnet.</b>
<div
style={{
display: "flex",
alignItems: "center",
backgroundColor: "var(--vscode-editor-inactiveSelectionBackground)",
color: "var(--vscode-editor-foreground)",
padding: "6px 8px",
borderRadius: "3px",
margin: "8px 0px",
fontSize: "12px",
}}>
<i
className="codicon codicon-info"
style={{
marginRight: "6px",
fontSize: "16px",
color: "var(--vscode-infoIcon-foreground)",
}}></i>
<span>
Explore Claude's capabilities with $20 free credits from{" "}
<VSCodeLink href={getKoduSignInUrl(uriScheme)} style={{ display: "inline" }}>
Kodu
</VSCodeLink>
</span>
</div>
<div style={{ marginTop: "10px" }}>
<ApiOptions showModelOptions={false} setDidAuthKodu={setDidAuthKoduFromWelcome} />
{apiConfiguration?.apiProvider !== "kodu" && (
<VSCodeButton onClick={handleSubmit} disabled={disableLetsGoButton} style={{ marginTop: "3px" }}>
Let's go!
</VSCodeButton>
)}
<ApiOptions showModelOptions={false} />
<VSCodeButton onClick={handleSubmit} disabled={disableLetsGoButton} style={{ marginTop: "3px" }}>
Let's go!
</VSCodeButton>
</div>
</div>
)

View File

@@ -20,7 +20,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
claudeMessages: [],
taskHistory: [],
shouldShowAnnouncement: false,
shouldShowKoduPromo: false,
})
const [didHydrateState, setDidHydrateState] = useState(false)
@@ -30,14 +29,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
setState(message.state)
setDidHydrateState(true)
}
if (message.type === "action" && message.action) {
switch (message.action) {
case "koduCreditsFetched":
// special case where we only want to update one part of state in case user is in the middle of modifying settings
setState((prevState) => ({ ...prevState, koduCredits: message.state?.koduCredits }))
break
}
}
}, [])
useEvent("message", handleMessage)

View File

@@ -18,11 +18,6 @@ export function validateApiConfiguration(apiConfiguration?: ApiConfiguration): s
return "You must provide a valid API key or choose a different provider."
}
break
case "kodu":
if (!apiConfiguration.koduApiKey) {
return "You must sign in to Kodu to use it as an API provider."
}
break
}
}
return undefined