Add secret and global state management + messaging between web and extension; persist API key and max num requests; add Welcome screen

This commit is contained in:
Saoud Rizwan
2024-07-07 11:22:16 -04:00
parent 991ea6bd4e
commit 8ba1be1167
10 changed files with 329 additions and 36 deletions

View File

@@ -1,12 +1,69 @@
import React from "react"
import React, { useEffect, useState } from "react"
import { VSCodeTextField, VSCodeDivider, VSCodeLink, VSCodeButton } from "@vscode/webview-ui-toolkit/react"
import { vscode } from "../utilities/vscode"
const SettingsView = () => {
const handleDoneClick = () => {
// Add your logic here for what should happen when the Done button is clicked
console.log("Done button clicked")
type SettingsViewProps = {
apiKey: string
setApiKey: React.Dispatch<React.SetStateAction<string>>
maxRequestsPerTask: string
setMaxRequestsPerTask: React.Dispatch<React.SetStateAction<string>>
onDone: () => void // Define the type of the onDone prop
}
const SettingsView = ({ apiKey, setApiKey, maxRequestsPerTask, setMaxRequestsPerTask, onDone }: SettingsViewProps) => {
const [apiKeyErrorMessage, setApiKeyErrorMessage] = useState<string | undefined>(undefined)
const [maxRequestsErrorMessage, setMaxRequestsErrorMessage] = useState<string | undefined>(undefined)
const disableDoneButton = apiKeyErrorMessage != null || maxRequestsErrorMessage != null
const handleApiKeyChange = (event: any) => {
const input = event.target.value
setApiKey(input)
validateApiKey(input)
}
const validateApiKey = (value: string) => {
if (value.trim() === "") {
setApiKeyErrorMessage("API Key cannot be empty")
} else {
setApiKeyErrorMessage(undefined)
}
}
const handleMaxRequestsChange = (event: any) => {
const input = event.target.value
setMaxRequestsPerTask(input)
validateMaxRequests(input)
}
const validateMaxRequests = (value: string | undefined) => {
if (value?.trim()) {
const num = Number(value)
if (isNaN(num)) {
setMaxRequestsErrorMessage("Maximum requests must be a number")
} else if (num < 3 || num > 100) {
setMaxRequestsErrorMessage("Maximum requests must be between 3 and 100")
} else {
setMaxRequestsErrorMessage(undefined)
}
} else {
setMaxRequestsErrorMessage(undefined)
}
}
const handleSubmit = () => {
vscode.postMessage({ type: "apiKey", text: apiKey })
vscode.postMessage({ type: "maxRequestsPerTask", text: maxRequestsPerTask })
onDone()
}
// validate as soon as the component is mounted
useEffect(() => {
validateApiKey(apiKey)
validateMaxRequests(maxRequestsPerTask)
}, [])
return (
<div style={{ margin: "0 auto", paddingTop: "10px" }}>
<div
@@ -14,16 +71,32 @@ const SettingsView = () => {
display: "flex",
justifyContent: "space-between",
alignItems: "center",
marginBottom: "20px",
marginBottom: "17px",
}}>
<h2 style={{ color: "var(--vscode-foreground)", margin: 0 }}>Settings</h2>
<VSCodeButton onClick={handleDoneClick}>Done</VSCodeButton>
<h3 style={{ color: "var(--vscode-foreground)", margin: 0 }}>Settings</h3>
<VSCodeButton onClick={handleSubmit} disabled={disableDoneButton}>
Done
</VSCodeButton>
</div>
<div style={{ marginBottom: "20px" }}>
<VSCodeTextField style={{ width: "100%" }} placeholder="Enter your Anthropic API Key">
<VSCodeTextField
value={apiKey}
style={{ width: "100%" }}
placeholder="Enter your Anthropic API Key"
onInput={handleApiKeyChange}>
Anthropic API Key
</VSCodeTextField>
{apiKeyErrorMessage && (
<p
style={{
fontSize: "12px",
marginTop: "5px",
color: "var(--vscode-errorForeground)",
}}>
{apiKeyErrorMessage}
</p>
)}
<p
style={{
fontSize: "12px",
@@ -38,9 +111,23 @@ const SettingsView = () => {
</div>
<div style={{ marginBottom: "20px" }}>
<VSCodeTextField style={{ width: "100%" }} placeholder="Enter maximum number of requests">
<VSCodeTextField
value={maxRequestsPerTask}
style={{ width: "100%" }}
placeholder="20"
onInput={handleMaxRequestsChange}>
Maximum # Requests Per Task
</VSCodeTextField>
{maxRequestsErrorMessage && (
<p
style={{
fontSize: "12px",
marginTop: "5px",
color: "var(--vscode-errorForeground)",
}}>
{maxRequestsErrorMessage}
</p>
)}
<p
style={{
fontSize: "12px",
@@ -65,7 +152,7 @@ const SettingsView = () => {
}}>
<p>Made possible by the latest breakthroughs in Claude 3.5 Sonnet's agentic coding capabilities.</p>
<p>
This project was submitted to Anthropic's<br/>"Build with Claude June 2024 contest"
This project was made for Anthropic's "Build with Claude June 2024 contest"
<VSCodeLink href="https://github.com/saoudrizwan/claude-dev">
https://github.com/saoudrizwan/claude-dev
</VSCodeLink>

View File

@@ -0,0 +1,91 @@
import React, { useState, useEffect } from "react"
import { VSCodeButton, VSCodeTextField, VSCodeLink, VSCodeDivider } from "@vscode/webview-ui-toolkit/react"
import { vscode } from "../utilities/vscode"
interface WelcomeViewProps {
apiKey: string
setApiKey: React.Dispatch<React.SetStateAction<string>>
}
const WelcomeView: React.FC<WelcomeViewProps> = ({ apiKey, setApiKey }) => {
const [apiKeyErrorMessage, setApiKeyErrorMessage] = useState<string | undefined>(undefined)
const disableLetsGoButton = apiKeyErrorMessage != null
const handleApiKeyChange = (event: any) => {
const input = event.target.value
setApiKey(input)
validateApiKey(input)
}
const validateApiKey = (value: string) => {
if (value.trim() === "") {
setApiKeyErrorMessage("API Key cannot be empty")
} else {
setApiKeyErrorMessage(undefined)
}
}
const handleSubmit = () => {
vscode.postMessage({ type: "apiKey", text: apiKey })
}
useEffect(() => {
validateApiKey(apiKey)
}, [])
return (
<div style={{ maxWidth: "600px", margin: "0 auto", padding: "20px" }}>
<h1 style={{ color: "var(--vscode-foreground)" }}>Hi, I'm Claude Dev</h1>
<p>
I can do all kinds of tasks thanks to the latest breakthroughs in Claude Sonnet 3.5's agentic coding
capabilities. I am prompted to think through tasks step-by-step and have access to tools that let me get
information about your project, read & write code, and execute terminal commands (with your permission,
of course).
</p>
<h3>Here are some cool things I can do:</h3>
<ul>
<li>Create new projects from scratch based on your requirements</li>
<li>Debug and fix code issues in your existing projects</li>
<li>Refactor and optimize your codebase</li>
<li>Analyze your system's performance and suggest improvements</li>
<li>Generate documentation for your code</li>
<li>Set up and configure development environments</li>
<li>Perform code reviews and suggest best practices</li>
</ul>
<h3>To get started, this extension needs an Anthropic API key:</h3>
<ol>
<li>
Go to{" "}
<VSCodeLink href="https://console.anthropic.com/" style={{ display: "inline" }}>
https://console.anthropic.com/
</VSCodeLink>
</li>
<li>You may need to buy some credits (although Anthropic is offering $5 free credit for new users)</li>
<li>Click 'Get API Keys' and create a new key for me (you can delete it any time)</li>
</ol>
<VSCodeDivider />
<div style={{ marginTop: "20px", display: "flex", alignItems: "center" }}>
<VSCodeTextField
style={{ flexGrow: 1, marginRight: "10px" }}
placeholder="Enter your Anthropic API Key"
value={apiKey}
onInput={handleApiKeyChange}
/>
<VSCodeButton onClick={handleSubmit} disabled={disableLetsGoButton}>
Let's go!
</VSCodeButton>
</div>
<p style={{ fontSize: "12px", marginTop: "10px", color: "var(--vscode-descriptionForeground)" }}>
Your API key is stored securely on your computer and used only for interacting with the Anthropic API.
</p>
</div>
)
}
export default WelcomeView