This commit is contained in:
Saoud Rizwan
2024-09-19 16:49:31 -04:00
parent cfc2ee830e
commit 5fbb335bb6
5 changed files with 14 additions and 17 deletions

View File

@@ -27,7 +27,7 @@ import { truncateHalfConversation } from "./utils/context-management"
import { extractTextFromFile } from "./utils/extract-text" import { extractTextFromFile } from "./utils/extract-text"
import { regexSearchFiles } from "./utils/ripgrep" import { regexSearchFiles } from "./utils/ripgrep"
import { parseMentions } from "./utils/context-mentions" import { parseMentions } from "./utils/context-mentions"
import { UrlScraper } from "./utils/UrlScraper" import { UrlContentFetcher } from "./utils/UrlContentFetcher"
const SYSTEM_PROMPT = const SYSTEM_PROMPT =
async () => `You are Claude Dev, a highly skilled software developer with extensive knowledge in many programming languages, frameworks, design patterns, and best practices. async () => `You are Claude Dev, a highly skilled software developer with extensive knowledge in many programming languages, frameworks, design patterns, and best practices.
@@ -251,7 +251,7 @@ export class ClaudeDev {
readonly taskId: string readonly taskId: string
private api: ApiHandler private api: ApiHandler
private terminalManager: TerminalManager private terminalManager: TerminalManager
private urlScraper: UrlScraper private urlContentFetcher: UrlContentFetcher
private didEditFile: boolean = false private didEditFile: boolean = false
private customInstructions?: string private customInstructions?: string
private alwaysAllowReadOnly: boolean private alwaysAllowReadOnly: boolean
@@ -277,7 +277,7 @@ export class ClaudeDev {
this.providerRef = new WeakRef(provider) this.providerRef = new WeakRef(provider)
this.api = buildApiHandler(apiConfiguration) this.api = buildApiHandler(apiConfiguration)
this.terminalManager = new TerminalManager() this.terminalManager = new TerminalManager()
this.urlScraper = new UrlScraper(provider.context) this.urlContentFetcher = new UrlContentFetcher(provider.context)
this.customInstructions = customInstructions this.customInstructions = customInstructions
this.alwaysAllowReadOnly = alwaysAllowReadOnly ?? false this.alwaysAllowReadOnly = alwaysAllowReadOnly ?? false
@@ -678,7 +678,7 @@ export class ClaudeDev {
abortTask() { abortTask() {
this.abort = true // will stop any autonomously running promises this.abort = true // will stop any autonomously running promises
this.terminalManager.disposeAll() this.terminalManager.disposeAll()
this.urlScraper.closeBrowser() this.urlContentFetcher.closeBrowser()
} }
async executeTool(toolName: ToolName, toolInput: any): Promise<[boolean, ToolResponse]> { async executeTool(toolName: ToolName, toolInput: any): Promise<[boolean, ToolResponse]> {
@@ -1647,14 +1647,14 @@ ${this.customInstructions.trim()}
if (block.type === "text") { if (block.type === "text") {
return { return {
...block, ...block,
text: await parseMentions(block.text, cwd, this.urlScraper), text: await parseMentions(block.text, cwd, this.urlContentFetcher),
} }
} else if (block.type === "tool_result") { } else if (block.type === "tool_result") {
const isUserMessage = (text: string) => text.includes("<feedback>") || text.includes("<answer>") const isUserMessage = (text: string) => text.includes("<feedback>") || text.includes("<answer>")
if (typeof block.content === "string" && isUserMessage(block.content)) { if (typeof block.content === "string" && isUserMessage(block.content)) {
return { return {
...block, ...block,
content: await parseMentions(block.content, cwd, this.urlScraper), content: await parseMentions(block.content, cwd, this.urlContentFetcher),
} }
} else if (Array.isArray(block.content)) { } else if (Array.isArray(block.content)) {
const parsedContent = await Promise.all( const parsedContent = await Promise.all(
@@ -1662,7 +1662,7 @@ ${this.customInstructions.trim()}
if (contentBlock.type === "text" && isUserMessage(contentBlock.text)) { if (contentBlock.type === "text" && isUserMessage(contentBlock.text)) {
return { return {
...contentBlock, ...contentBlock,
text: await parseMentions(contentBlock.text, cwd, this.urlScraper), text: await parseMentions(contentBlock.text, cwd, this.urlContentFetcher),
} }
} }
return contentBlock return contentBlock

View File

@@ -3,7 +3,6 @@
import * as vscode from "vscode" import * as vscode from "vscode"
import { ClaudeDevProvider } from "./providers/ClaudeDevProvider" import { ClaudeDevProvider } from "./providers/ClaudeDevProvider"
import delay from "delay" import delay from "delay"
import { UrlScraper } from "./utils/UrlScraper"
/* /*
Built using https://github.com/microsoft/vscode-webview-ui-toolkit Built using https://github.com/microsoft/vscode-webview-ui-toolkit

View File

@@ -13,7 +13,6 @@ import { getTheme } from "../utils/getTheme"
import { openFile, openImage } from "../utils/open-file" import { openFile, openImage } from "../utils/open-file"
import WorkspaceTracker from "../integrations/WorkspaceTracker" import WorkspaceTracker from "../integrations/WorkspaceTracker"
import { openMention } from "../utils/context-mentions" import { openMention } from "../utils/context-mentions"
import { UrlScraper } from "../utils/UrlScraper"
/* /*
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts

View File

@@ -12,7 +12,7 @@ interface PCRStats {
executablePath: string executablePath: string
} }
export class UrlScraper { export class UrlContentFetcher {
private context: vscode.ExtensionContext private context: vscode.ExtensionContext
private browser?: Browser private browser?: Browser
private page?: Page private page?: Page
@@ -74,8 +74,7 @@ export class UrlScraper {
/* /*
- networkidle2 is equivalent to playwright's networkidle where it waits until there are no more than 2 network connections for at least 500 ms. - networkidle2 is equivalent to playwright's networkidle where it waits until there are no more than 2 network connections for at least 500 ms.
- domcontentloaded is when the basic DOM is loaded - domcontentloaded is when the basic DOM is loaded
this should be sufficient for most doc sites, but we can use the more elaborate waitTillHTMLRendered if we find users are scraping more dynamic complex sites this should be sufficient for most doc sites
https://stackoverflow.com/questions/52497252/puppeteer-wait-until-page-is-completely-loaded/61304202#61304202
*/ */
await this.page.goto(url, { timeout: 10_000, waitUntil: ["domcontentloaded", "networkidle2"] }) await this.page.goto(url, { timeout: 10_000, waitUntil: ["domcontentloaded", "networkidle2"] })
const content = await this.page.content() const content = await this.page.content()

View File

@@ -1,7 +1,7 @@
import * as vscode from "vscode" import * as vscode from "vscode"
import * as path from "path" import * as path from "path"
import { openFile } from "./open-file" import { openFile } from "./open-file"
import { UrlScraper } from "./UrlScraper" import { UrlContentFetcher } from "./UrlContentFetcher"
import { mentionRegexGlobal } from "../shared/context-mentions" import { mentionRegexGlobal } from "../shared/context-mentions"
import fs from "fs/promises" import fs from "fs/promises"
import { extractTextFromFile } from "./extract-text" import { extractTextFromFile } from "./extract-text"
@@ -32,7 +32,7 @@ export function openMention(mention?: string): void {
} }
} }
export async function parseMentions(text: string, cwd: string, urlScraper: UrlScraper): Promise<string> { export async function parseMentions(text: string, cwd: string, urlContentFetcher: UrlContentFetcher): Promise<string> {
const mentions: Set<string> = new Set() const mentions: Set<string> = new Set()
let parsedText = text.replace(mentionRegexGlobal, (match, mention) => { let parsedText = text.replace(mentionRegexGlobal, (match, mention) => {
mentions.add(mention) mentions.add(mention)
@@ -53,7 +53,7 @@ export async function parseMentions(text: string, cwd: string, urlScraper: UrlSc
let launchBrowserError: Error | undefined let launchBrowserError: Error | undefined
if (urlMention) { if (urlMention) {
try { try {
await urlScraper.launchBrowser() await urlContentFetcher.launchBrowser()
} catch (error) { } catch (error) {
launchBrowserError = error launchBrowserError = error
vscode.window.showErrorMessage(`Error fetching content for ${urlMention}: ${error.message}`) vscode.window.showErrorMessage(`Error fetching content for ${urlMention}: ${error.message}`)
@@ -67,7 +67,7 @@ export async function parseMentions(text: string, cwd: string, urlScraper: UrlSc
result = `Error fetching content: ${launchBrowserError.message}` result = `Error fetching content: ${launchBrowserError.message}`
} else { } else {
try { try {
const markdown = await urlScraper.urlToMarkdown(mention) const markdown = await urlContentFetcher.urlToMarkdown(mention)
result = markdown result = markdown
} catch (error) { } catch (error) {
vscode.window.showErrorMessage(`Error fetching content for ${mention}: ${error.message}`) vscode.window.showErrorMessage(`Error fetching content for ${mention}: ${error.message}`)
@@ -103,7 +103,7 @@ export async function parseMentions(text: string, cwd: string, urlScraper: UrlSc
if (urlMention) { if (urlMention) {
try { try {
await urlScraper.closeBrowser() await urlContentFetcher.closeBrowser()
} catch (error) { } catch (error) {
console.error(`Error closing browser: ${error.message}`) console.error(`Error closing browser: ${error.message}`)
} }