diff --git a/src/providers/ClaudeDevProvider.ts b/src/providers/ClaudeDevProvider.ts index 54c7c05..ad4a3da 100644 --- a/src/providers/ClaudeDevProvider.ts +++ b/src/providers/ClaudeDevProvider.ts @@ -378,6 +378,9 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider { await this.updateGlobalState("shouldShowKoduPromo", false) await this.postStateToWebview() break + case "resetState": + await this.resetState() + break // Add more switch case statements here as more webview message commands // are created within the webview context (i.e. inside media/main.js) } @@ -744,4 +747,24 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider { private async getSecret(key: SecretKey) { return await this.context.secrets.get(key) } + + // dev + + async resetState() { + vscode.window.showInformationMessage("Resetting state...") + for (const key of this.context.globalState.keys()) { + await this.context.globalState.update(key, undefined) + } + const secretKeys: SecretKey[] = ["apiKey", "openRouterApiKey", "awsAccessKey", "awsSecretKey", "koduApiKey"] + for (const key of secretKeys) { + await this.storeSecret(key, undefined) + } + if (this.claudeDev) { + this.claudeDev.abortTask() + this.claudeDev = undefined + } + vscode.window.showInformationMessage("State reset") + await this.postStateToWebview() + await this.postMessageToWebview({ type: "action", action: "chatButtonTapped" }) + } } diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index 9f36099..a6b56d4 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -19,6 +19,7 @@ export interface WebviewMessage { | "didClickKoduSignOut" | "fetchKoduCredits" | "didDismissKoduPromo" + | "resetState" text?: string askResponse?: ClaudeAskResponse apiConfiguration?: ApiConfiguration diff --git a/webview-ui/src/App.tsx b/webview-ui/src/App.tsx index 3fa1037..954bc45 100644 --- a/webview-ui/src/App.tsx +++ b/webview-ui/src/App.tsx @@ -33,8 +33,9 @@ const App: React.FC = () => { const [taskHistory, setTaskHistory] = useState([]) const [showAnnouncement, setShowAnnouncement] = useState(false) const [koduCredits, setKoduCredits] = useState(undefined) - const [isNewUser, setIsNewUser] = useState(false) const [shouldShowKoduPromo, setShouldShowKoduPromo] = useState(true) + const [didAuthKoduFromWelcome, setDidAuthKoduFromWelcome] = useState(false) + useEffect(() => { vscode.postMessage({ type: "webviewDidLaunch" }) }, []) @@ -51,8 +52,8 @@ const App: React.FC = () => { message.state!.apiConfiguration?.awsAccessKey !== undefined || message.state!.apiConfiguration?.koduApiKey !== undefined setShowWelcome(!hasKey) - if (!hasKey && !isNewUser) { - setIsNewUser(true) + if (!hasKey) { + setDidAuthKoduFromWelcome(false) } setApiConfiguration(message.state!.apiConfiguration) setMaxRequestsPerTask( @@ -88,31 +89,25 @@ const App: React.FC = () => { setShowSettings(false) setShowHistory(false) break + case "koduCreditsFetched": + setKoduCredits(message.state!.koduCredits) + break case "koduAuthenticated": - if (!isNewUser) { + if (!didAuthKoduFromWelcome) { setShowSettings(true) setShowHistory(false) } break - case "koduCreditsFetched": - setKoduCredits(message.state!.koduCredits) - break } break } // (react-use takes care of not registering the same listener multiple times even if this callback is updated.) }, - [isNewUser] + [didAuthKoduFromWelcome] ) useEvent("message", handleMessage) - useEffect(() => { - if (showWelcome === false) { - setIsNewUser(false) - } - }, [showWelcome]) - const { selectedModelInfo } = useMemo(() => { return normalizeApiConfiguration(apiConfiguration) }, [apiConfiguration]) @@ -128,6 +123,7 @@ const App: React.FC = () => { apiConfiguration={apiConfiguration} setApiConfiguration={setApiConfiguration} vscodeUriScheme={vscodeUriScheme} + setDidAuthKoduFromWelcome={setDidAuthKoduFromWelcome} /> ) : ( <> diff --git a/webview-ui/src/components/Announcement.tsx b/webview-ui/src/components/Announcement.tsx index fcf3e5d..26f1e07 100644 --- a/webview-ui/src/components/Announcement.tsx +++ b/webview-ui/src/components/Announcement.tsx @@ -32,11 +32,11 @@ const Announcement = ({ version, hideAnnouncement, apiConfiguration, vscodeUriSc 🎉{" "}New in v{version} -
    +
    • - Excited to announce that we've partnered with Anthropic and are offering $20 free credits to help - users get the most out of Claude Dev with high rate limits and prompt caching! Stay tuned for some - exciting updates like easier billing, voice mode and one click deployment. + Excited to announce that we've partnered with Anthropic and are offering $20 free credits 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 && ( - Claim $20 Free Credits with Kodu + Claim $20 Credits on Kodu )}
    • Added "Always allow read-only operations" setting to let Claude read files and view directories - without needing to approve (off by default) + without needing to approve (off by default).
    • -
    • Added sliding window context management to keep tasks going past 200k tokens
    • +
    • Added sliding window context management to keep tasks going past 200k tokens.

    Follow me for more updates!{" "} diff --git a/webview-ui/src/components/ApiOptions.tsx b/webview-ui/src/components/ApiOptions.tsx index d577aeb..5bb3063 100644 --- a/webview-ui/src/components/ApiOptions.tsx +++ b/webview-ui/src/components/ApiOptions.tsx @@ -26,6 +26,7 @@ interface ApiOptionsProps { koduCredits?: number apiErrorMessage?: string vscodeUriScheme?: string + setDidAuthKodu?: React.Dispatch> } const ApiOptions: React.FC = ({ @@ -35,6 +36,7 @@ const ApiOptions: React.FC = ({ koduCredits, apiErrorMessage, vscodeUriScheme, + setDidAuthKodu, }) => { const [, setDidFetchKoduCredits] = useState(false) const handleInputChange = (field: keyof ApiConfiguration) => (event: any) => { @@ -192,7 +194,9 @@ const ApiOptions: React.FC = ({ ) : (

    - + setDidAuthKodu?.(true)}> Sign in to Kodu
    diff --git a/webview-ui/src/components/SettingsView.tsx b/webview-ui/src/components/SettingsView.tsx index 3697572..8fc94e2 100644 --- a/webview-ui/src/components/SettingsView.tsx +++ b/webview-ui/src/components/SettingsView.tsx @@ -11,6 +11,8 @@ import { validateApiConfiguration, validateMaxRequestsPerTask } from "../utils/v import { vscode } from "../utils/vscode" import ApiOptions from "./ApiOptions" +const IS_DEV = true + type SettingsViewProps = { version: string apiConfiguration?: ApiConfiguration @@ -79,6 +81,10 @@ const SettingsView = ({ If we only want to run code once on mount we can use react-use's useEffectOnce or useMount */ + const handleResetState = () => { + vscode.postMessage({ type: "resetState" }) + } + return (
    + {IS_DEV && ( + <> +
    Debug
    + + Reset State + +

    + This will reset all global state and secret storage in the extension. +

    + + )} +
    > vscodeUriScheme?: string + setDidAuthKoduFromWelcome: React.Dispatch> } -const WelcomeView: React.FC = ({ apiConfiguration, setApiConfiguration, vscodeUriScheme }) => { +const WelcomeView: React.FC = ({ + apiConfiguration, + setApiConfiguration, + vscodeUriScheme, + setDidAuthKoduFromWelcome, +}) => { const [apiErrorMessage, setApiErrorMessage] = useState(undefined) const disableLetsGoButton = apiErrorMessage != null @@ -73,6 +79,7 @@ const WelcomeView: React.FC = ({ apiConfiguration, setApiConfi setApiConfiguration={setApiConfiguration} showModelOptions={false} vscodeUriScheme={vscodeUriScheme} + setDidAuthKodu={setDidAuthKoduFromWelcome} /> {apiConfiguration?.apiProvider !== "kodu" && (