From dc2f3a5c284eedeaf3cb3a20fc1d972ac37c5c97 Mon Sep 17 00:00:00 2001 From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com> Date: Fri, 30 Aug 2024 08:35:10 -0400 Subject: [PATCH] Show api_req_started message while verbose details are being built for smoother ux --- src/ClaudeDev.ts | 52 +++++++++++++++++++++++++--------- src/parse-source-code/index.ts | 4 +-- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/ClaudeDev.ts b/src/ClaudeDev.ts index ab0c5b1..3ffb1d9 100644 --- a/src/ClaudeDev.ts +++ b/src/ClaudeDev.ts @@ -260,6 +260,7 @@ export class ClaudeDev { private askResponseImages?: string[] private lastMessageTs?: number private executeCommandRunningProcess?: ResultPromise + private shouldSkipNextApiReqStartedMessage = false private providerRef: WeakRef private abort: boolean = false @@ -475,13 +476,34 @@ export class ClaudeDev { this.apiConversationHistory = [] await this.providerRef.deref()?.postStateToWebview() - let textBlock: Anthropic.TextBlockParam = { - type: "text", - text: `\n${task}\n\n\n${await this.getPotentiallyRelevantDetails(true)}`, // cannot be sent with system prompt since it's cached and these details can change - } - let imageBlocks: Anthropic.ImageBlockParam[] = this.formatImagesIntoBlocks(images) await this.say("text", task, images) - await this.initiateTaskLoop([textBlock, ...imageBlocks]) + + // getting verbose details is an expensive operation, it uses globby to top-down build file structure of project which for large projects can take a few seconds + // for the best UX we show a loading spinner as this happens + const taskText = `\n${task}\n` + let imageBlocks: Anthropic.ImageBlockParam[] = this.formatImagesIntoBlocks(images) + await this.say( + "api_req_started", + JSON.stringify({ + request: this.api.createUserReadableRequest([ + { + type: "text", + text: `${taskText}\n\n(see getPotentiallyRelevantDetails in src/ClaudeDev.ts)`, + }, + ...imageBlocks, + ]), + }) + ) + this.shouldSkipNextApiReqStartedMessage = true + this.getPotentiallyRelevantDetails(true).then(async (verboseDetails) => { + await this.initiateTaskLoop([ + { + type: "text", + text: `${taskText}\n\n${verboseDetails}`, // cannot be sent with system prompt since it's cached and these details can change + }, + ...imageBlocks, + ]) + }) } private async resumeTaskFromHistory() { @@ -1344,13 +1366,17 @@ ${this.customInstructions.trim()} } } - // what the user sees in the webview - await this.say( - "api_req_started", - JSON.stringify({ - request: this.api.createUserReadableRequest(userContent), - }) - ) + if (!this.shouldSkipNextApiReqStartedMessage) { + await this.say( + "api_req_started", + // what the user sees in the webview + JSON.stringify({ + request: this.api.createUserReadableRequest(userContent), + }) + ) + } else { + this.shouldSkipNextApiReqStartedMessage = false + } try { const response = await this.attemptApiRequest() this.requestCount++ diff --git a/src/parse-source-code/index.ts b/src/parse-source-code/index.ts index 5a9d6f3..08c3e73 100644 --- a/src/parse-source-code/index.ts +++ b/src/parse-source-code/index.ts @@ -105,10 +105,10 @@ export async function listFiles(dirPath: string, recursive: boolean): Promise