Show api_req_started message while verbose details are being built for smoother ux

This commit is contained in:
Saoud Rizwan
2024-08-30 08:35:10 -04:00
parent bf57218ed9
commit dc2f3a5c28
2 changed files with 41 additions and 15 deletions

View File

@@ -260,6 +260,7 @@ export class ClaudeDev {
private askResponseImages?: string[] private askResponseImages?: string[]
private lastMessageTs?: number private lastMessageTs?: number
private executeCommandRunningProcess?: ResultPromise private executeCommandRunningProcess?: ResultPromise
private shouldSkipNextApiReqStartedMessage = false
private providerRef: WeakRef<ClaudeDevProvider> private providerRef: WeakRef<ClaudeDevProvider>
private abort: boolean = false private abort: boolean = false
@@ -475,13 +476,34 @@ export class ClaudeDev {
this.apiConversationHistory = [] this.apiConversationHistory = []
await this.providerRef.deref()?.postStateToWebview() await this.providerRef.deref()?.postStateToWebview()
let textBlock: Anthropic.TextBlockParam = {
type: "text",
text: `<task>\n${task}\n</task>\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.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 = `<task>\n${task}\n</task>`
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<potentially_relevant_details>(see getPotentiallyRelevantDetails in src/ClaudeDev.ts)</potentially_relevant_details>`,
},
...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() { private async resumeTaskFromHistory() {
@@ -1344,13 +1366,17 @@ ${this.customInstructions.trim()}
} }
} }
// what the user sees in the webview if (!this.shouldSkipNextApiReqStartedMessage) {
await this.say( await this.say(
"api_req_started", "api_req_started",
JSON.stringify({ // what the user sees in the webview
request: this.api.createUserReadableRequest(userContent), JSON.stringify({
}) request: this.api.createUserReadableRequest(userContent),
) })
)
} else {
this.shouldSkipNextApiReqStartedMessage = false
}
try { try {
const response = await this.attemptApiRequest() const response = await this.attemptApiRequest()
this.requestCount++ this.requestCount++

View File

@@ -105,10 +105,10 @@ export async function listFiles(dirPath: string, recursive: boolean): Promise<st
// globby doesnt natively support top down level by level globbing, so we implement it ourselves // globby doesnt natively support top down level by level globbing, so we implement it ourselves
async function globbyLevelByLevel(options?: Options) { async function globbyLevelByLevel(options?: Options) {
let results: string[] = [] let results: string[] = []
let currentLevel = 1 let currentLevel = 0
while (results.length < LIST_FILES_LIMIT) { while (results.length < LIST_FILES_LIMIT) {
// Construct the glob pattern for the current level // Construct the glob pattern for the current level
const pattern = `${"*/".repeat(currentLevel)}*` const pattern = currentLevel === 0 ? "*" : `${"*/".repeat(currentLevel)}*`
// Get files and directories at the current level // Get files and directories at the current level
const filesAtLevel = await globby(pattern, options) const filesAtLevel = await globby(pattern, options)