Allow messages with images and no text

This commit is contained in:
Saoud Rizwan
2024-08-10 02:17:43 -04:00
parent 7da81f651d
commit 60ca8baecb
3 changed files with 10 additions and 12 deletions

View File

@@ -247,9 +247,9 @@ export class ClaudeDev {
constructor( constructor(
provider: ClaudeDevProvider, provider: ClaudeDevProvider,
task: string,
apiConfiguration: ApiConfiguration, apiConfiguration: ApiConfiguration,
maxRequestsPerTask?: number, maxRequestsPerTask?: number,
task?: string,
images?: string[] images?: string[]
) { ) {
this.providerRef = new WeakRef(provider) this.providerRef = new WeakRef(provider)
@@ -323,26 +323,24 @@ export class ClaudeDev {
: [] : []
} }
private formatIntoToolResponse(text?: string, images?: string[]): ToolResponse { private formatIntoToolResponse(text: string, images?: string[]): ToolResponse {
if (images && images.length > 0) { if (images && images.length > 0) {
const textBlock: Anthropic.TextBlockParam = { type: "text", text: text ?? "" } const textBlock: Anthropic.TextBlockParam = { type: "text", text }
const imageBlocks: Anthropic.ImageBlockParam[] = this.formatImagesIntoBlocks(images) const imageBlocks: Anthropic.ImageBlockParam[] = this.formatImagesIntoBlocks(images)
// Placing images after text leads to better results // Placing images after text leads to better results
return [textBlock, ...imageBlocks] return [textBlock, ...imageBlocks]
} else { } else {
return text ?? "" return text
} }
} }
private async startTask(task: string, images?: string[]): Promise<void> { private async startTask(task?: string, images?: string[]): Promise<void> {
// conversationHistory (for API) and claudeMessages (for webview) need to be in sync // conversationHistory (for API) and claudeMessages (for webview) need to be in sync
// if the extension process were killed, then on restart the claudeMessages might not be empty, so we need to set it to [] when we create a new ClaudeDev client (otherwise webview would show stale messages from previous session) // if the extension process were killed, then on restart the claudeMessages might not be empty, so we need to set it to [] when we create a new ClaudeDev client (otherwise webview would show stale messages from previous session)
this.claudeMessages = [] this.claudeMessages = []
this.apiConversationHistory = [] this.apiConversationHistory = []
await this.providerRef.deref()?.postStateToWebview() await this.providerRef.deref()?.postStateToWebview()
// This first message kicks off a task, it is not included in every subsequent message.
let textBlock: Anthropic.TextBlockParam = { type: "text", text: `Task: \"${task}\"` } let textBlock: Anthropic.TextBlockParam = { type: "text", text: `Task: \"${task}\"` }
let imageBlocks: Anthropic.ImageBlockParam[] = this.formatImagesIntoBlocks(images) let imageBlocks: Anthropic.ImageBlockParam[] = this.formatImagesIntoBlocks(images)

View File

@@ -133,15 +133,15 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
this.outputChannel.appendLine("Webview view resolved") this.outputChannel.appendLine("Webview view resolved")
} }
async initClaudeDevWithTask(task: string, images?: string[]) { async initClaudeDevWithTask(task?: string, images?: string[]) {
await this.clearTask() // ensures that an exising task doesn't exist before starting a new one, although this shouldn't be possible since user must clear task before starting a new one await this.clearTask() // ensures that an exising task doesn't exist before starting a new one, although this shouldn't be possible since user must clear task before starting a new one
const { apiProvider, apiKey, openRouterApiKey, awsAccessKey, awsSecretKey, awsRegion, maxRequestsPerTask } = const { apiProvider, apiKey, openRouterApiKey, awsAccessKey, awsSecretKey, awsRegion, maxRequestsPerTask } =
await this.getState() await this.getState()
this.claudeDev = new ClaudeDev( this.claudeDev = new ClaudeDev(
this, this,
task,
{ apiProvider, apiKey, openRouterApiKey, awsAccessKey, awsSecretKey, awsRegion }, { apiProvider, apiKey, openRouterApiKey, awsAccessKey, awsSecretKey, awsRegion },
maxRequestsPerTask, maxRequestsPerTask,
task,
images images
) )
} }
@@ -254,7 +254,7 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
// Could also do this in extension .ts // Could also do this in extension .ts
//this.postMessageToWebview({ type: "text", text: `Extension: ${Date.now()}` }) //this.postMessageToWebview({ type: "text", text: `Extension: ${Date.now()}` })
// initializing new instance of ClaudeDev will make sure that any agentically running promises in old instance don't affect our new task. this essentially creates a fresh slate for the new task // initializing new instance of ClaudeDev will make sure that any agentically running promises in old instance don't affect our new task. this essentially creates a fresh slate for the new task
await this.initClaudeDevWithTask(message.text!, message.images) await this.initClaudeDevWithTask(message.text, message.images)
break break
case "apiConfiguration": case "apiConfiguration":
if (message.apiConfiguration) { if (message.apiConfiguration) {

View File

@@ -177,7 +177,7 @@ const ChatView = ({ messages, isHidden, vscodeThemeName, showAnnouncement, hideA
const handleSendMessage = () => { const handleSendMessage = () => {
const text = inputValue.trim() const text = inputValue.trim()
if (text) { if (text || selectedImages.length > 0) {
if (messages.length === 0) { if (messages.length === 0) {
vscode.postMessage({ type: "newTask", text, images: selectedImages }) vscode.postMessage({ type: "newTask", text, images: selectedImages })
} else if (claudeAsk) { } else if (claudeAsk) {
@@ -598,7 +598,7 @@ const ChatView = ({ messages, isHidden, vscodeThemeName, showAnnouncement, hideA
appearance="icon" appearance="icon"
aria-label="Send Message" aria-label="Send Message"
onClick={handleSendMessage}> onClick={handleSendMessage}>
<span className="codicon codicon-send" style={{ marginBottom: -1 }}></span> <span className="codicon codicon-send"></span>
</VSCodeButton> </VSCodeButton>
</div> </div>
</div> </div>