mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 12:21:13 -05:00
Refactor ClaudeDev
This commit is contained in:
@@ -51,7 +51,7 @@ type UserContent = Array<
|
|||||||
Anthropic.TextBlockParam | Anthropic.ImageBlockParam | Anthropic.ToolUseBlockParam | Anthropic.ToolResultBlockParam
|
Anthropic.TextBlockParam | Anthropic.ImageBlockParam | Anthropic.ToolUseBlockParam | Anthropic.ToolResultBlockParam
|
||||||
>
|
>
|
||||||
|
|
||||||
export class ClaudeDev {
|
export class Cline {
|
||||||
readonly taskId: string
|
readonly taskId: string
|
||||||
api: ApiHandler
|
api: ApiHandler
|
||||||
private terminalManager: TerminalManager
|
private terminalManager: TerminalManager
|
||||||
@@ -1731,7 +1731,7 @@ export class ClaudeDev {
|
|||||||
await abortStream("streaming_failed", error.message ?? JSON.stringify(serializeError(error), null, 2))
|
await abortStream("streaming_failed", error.message ?? JSON.stringify(serializeError(error), null, 2))
|
||||||
const history = await this.providerRef.deref()?.getTaskWithId(this.taskId)
|
const history = await this.providerRef.deref()?.getTaskWithId(this.taskId)
|
||||||
if (history) {
|
if (history) {
|
||||||
await this.providerRef.deref()?.initClaudeDevWithHistoryItem(history.historyItem)
|
await this.providerRef.deref()?.initClineWithHistoryItem(history.historyItem)
|
||||||
// await this.providerRef.deref()?.postStateToWebview()
|
// await this.providerRef.deref()?.postStateToWebview()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Anthropic } from "@anthropic-ai/sdk"
|
import { Anthropic } from "@anthropic-ai/sdk"
|
||||||
import * as vscode from "vscode"
|
import * as vscode from "vscode"
|
||||||
import { ClaudeDev } from "../ClaudeDev"
|
import { Cline } from "../ClaudeDev"
|
||||||
import { ApiProvider, ModelInfo } from "../../shared/api"
|
import { ApiProvider, ModelInfo } from "../../shared/api"
|
||||||
import { ExtensionMessage } from "../../shared/ExtensionMessage"
|
import { ExtensionMessage } from "../../shared/ExtensionMessage"
|
||||||
import { WebviewMessage } from "../../shared/WebviewMessage"
|
import { WebviewMessage } from "../../shared/WebviewMessage"
|
||||||
@@ -67,7 +67,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
private static activeInstances: Set<ClineProvider> = new Set()
|
private static activeInstances: Set<ClineProvider> = new Set()
|
||||||
private disposables: vscode.Disposable[] = []
|
private disposables: vscode.Disposable[] = []
|
||||||
private view?: vscode.WebviewView | vscode.WebviewPanel
|
private view?: vscode.WebviewView | vscode.WebviewPanel
|
||||||
private claudeDev?: ClaudeDev
|
private cline?: Cline
|
||||||
private workspaceTracker?: WorkspaceTracker
|
private workspaceTracker?: WorkspaceTracker
|
||||||
private latestAnnouncementId = "sep-21-2024" // update to some unique identifier when we add a new announcement
|
private latestAnnouncementId = "sep-21-2024" // update to some unique identifier when we add a new announcement
|
||||||
|
|
||||||
@@ -208,16 +208,16 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
this.outputChannel.appendLine("Webview view resolved")
|
this.outputChannel.appendLine("Webview view resolved")
|
||||||
}
|
}
|
||||||
|
|
||||||
async initClaudeDevWithTask(task?: string, images?: string[]) {
|
async initClineWithTask(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 { apiConfiguration, customInstructions, alwaysAllowReadOnly } = await this.getState()
|
const { apiConfiguration, customInstructions, alwaysAllowReadOnly } = await this.getState()
|
||||||
this.claudeDev = new ClaudeDev(this, apiConfiguration, customInstructions, alwaysAllowReadOnly, task, images)
|
this.cline = new Cline(this, apiConfiguration, customInstructions, alwaysAllowReadOnly, task, images)
|
||||||
}
|
}
|
||||||
|
|
||||||
async initClaudeDevWithHistoryItem(historyItem: HistoryItem) {
|
async initClineWithHistoryItem(historyItem: HistoryItem) {
|
||||||
await this.clearTask()
|
await this.clearTask()
|
||||||
const { apiConfiguration, customInstructions, alwaysAllowReadOnly } = await this.getState()
|
const { apiConfiguration, customInstructions, alwaysAllowReadOnly } = await this.getState()
|
||||||
this.claudeDev = new ClaudeDev(
|
this.cline = new Cline(
|
||||||
this,
|
this,
|
||||||
apiConfiguration,
|
apiConfiguration,
|
||||||
customInstructions,
|
customInstructions,
|
||||||
@@ -347,8 +347,8 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
// You can send any JSON serializable data.
|
// You can send any JSON serializable data.
|
||||||
// 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 Cline 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.initClineWithTask(message.text, message.images)
|
||||||
break
|
break
|
||||||
case "apiConfiguration":
|
case "apiConfiguration":
|
||||||
if (message.apiConfiguration) {
|
if (message.apiConfiguration) {
|
||||||
@@ -396,8 +396,8 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
await this.updateGlobalState("azureApiVersion", azureApiVersion)
|
await this.updateGlobalState("azureApiVersion", azureApiVersion)
|
||||||
await this.updateGlobalState("openRouterModelId", openRouterModelId)
|
await this.updateGlobalState("openRouterModelId", openRouterModelId)
|
||||||
await this.updateGlobalState("openRouterModelInfo", openRouterModelInfo)
|
await this.updateGlobalState("openRouterModelInfo", openRouterModelInfo)
|
||||||
if (this.claudeDev) {
|
if (this.cline) {
|
||||||
this.claudeDev.api = buildApiHandler(message.apiConfiguration)
|
this.cline.api = buildApiHandler(message.apiConfiguration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await this.postStateToWebview()
|
await this.postStateToWebview()
|
||||||
@@ -407,13 +407,13 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
break
|
break
|
||||||
case "alwaysAllowReadOnly":
|
case "alwaysAllowReadOnly":
|
||||||
await this.updateGlobalState("alwaysAllowReadOnly", message.bool ?? undefined)
|
await this.updateGlobalState("alwaysAllowReadOnly", message.bool ?? undefined)
|
||||||
if (this.claudeDev) {
|
if (this.cline) {
|
||||||
this.claudeDev.alwaysAllowReadOnly = message.bool ?? false
|
this.cline.alwaysAllowReadOnly = message.bool ?? false
|
||||||
}
|
}
|
||||||
await this.postStateToWebview()
|
await this.postStateToWebview()
|
||||||
break
|
break
|
||||||
case "askResponse":
|
case "askResponse":
|
||||||
this.claudeDev?.handleWebviewAskResponse(message.askResponse!, message.text, message.images)
|
this.cline?.handleWebviewAskResponse(message.askResponse!, message.text, message.images)
|
||||||
break
|
break
|
||||||
case "clearTask":
|
case "clearTask":
|
||||||
// newTask will start a new task with a given task text, while clear task resets the current session and allows for a new task to be started
|
// newTask will start a new task with a given task text, while clear task resets the current session and allows for a new task to be started
|
||||||
@@ -429,7 +429,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
await this.postMessageToWebview({ type: "selectedImages", images })
|
await this.postMessageToWebview({ type: "selectedImages", images })
|
||||||
break
|
break
|
||||||
case "exportCurrentTask":
|
case "exportCurrentTask":
|
||||||
const currentTaskId = this.claudeDev?.taskId
|
const currentTaskId = this.cline?.taskId
|
||||||
if (currentTaskId) {
|
if (currentTaskId) {
|
||||||
this.exportTaskWithId(currentTaskId)
|
this.exportTaskWithId(currentTaskId)
|
||||||
}
|
}
|
||||||
@@ -463,13 +463,13 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
openMention(message.text)
|
openMention(message.text)
|
||||||
break
|
break
|
||||||
case "cancelTask":
|
case "cancelTask":
|
||||||
if (this.claudeDev) {
|
if (this.cline) {
|
||||||
const { historyItem } = await this.getTaskWithId(this.claudeDev.taskId)
|
const { historyItem } = await this.getTaskWithId(this.cline.taskId)
|
||||||
this.claudeDev.abortTask()
|
this.cline.abortTask()
|
||||||
await pWaitFor(() => this.claudeDev === undefined || this.claudeDev.didFinishAborting, {
|
await pWaitFor(() => this.cline === undefined || this.cline.didFinishAborting, {
|
||||||
timeout: 3_000,
|
timeout: 3_000,
|
||||||
})
|
})
|
||||||
await this.initClaudeDevWithHistoryItem(historyItem) // clears task again, so we need to abortTask manually above
|
await this.initClineWithHistoryItem(historyItem) // clears task again, so we need to abortTask manually above
|
||||||
// await this.postStateToWebview() // new claude dev instance will post state when it's ready. having this here sent an empty messages array to webview leading to virtuoso having to reload the entire list
|
// await this.postStateToWebview() // new claude dev instance will post state when it's ready. having this here sent an empty messages array to webview leading to virtuoso having to reload the entire list
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,8 +486,8 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
async updateCustomInstructions(instructions?: string) {
|
async updateCustomInstructions(instructions?: string) {
|
||||||
// User may be clearing the field
|
// User may be clearing the field
|
||||||
await this.updateGlobalState("customInstructions", instructions || undefined)
|
await this.updateGlobalState("customInstructions", instructions || undefined)
|
||||||
if (this.claudeDev) {
|
if (this.cline) {
|
||||||
this.claudeDev.customInstructions = instructions || undefined
|
this.cline.customInstructions = instructions || undefined
|
||||||
}
|
}
|
||||||
await this.postStateToWebview()
|
await this.postStateToWebview()
|
||||||
}
|
}
|
||||||
@@ -531,8 +531,8 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
await this.updateGlobalState("apiProvider", openrouter)
|
await this.updateGlobalState("apiProvider", openrouter)
|
||||||
await this.storeSecret("openRouterApiKey", apiKey)
|
await this.storeSecret("openRouterApiKey", apiKey)
|
||||||
await this.postStateToWebview()
|
await this.postStateToWebview()
|
||||||
if (this.claudeDev) {
|
if (this.cline) {
|
||||||
this.claudeDev.api = buildApiHandler({ apiProvider: openrouter, openRouterApiKey: apiKey })
|
this.cline.api = buildApiHandler({ apiProvider: openrouter, openRouterApiKey: apiKey })
|
||||||
}
|
}
|
||||||
// await this.postMessageToWebview({ type: "action", action: "settingsButtonTapped" }) // bad ux if user is on welcome
|
// await this.postMessageToWebview({ type: "action", action: "settingsButtonTapped" }) // bad ux if user is on welcome
|
||||||
}
|
}
|
||||||
@@ -678,10 +678,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async showTaskWithId(id: string) {
|
async showTaskWithId(id: string) {
|
||||||
if (id !== this.claudeDev?.taskId) {
|
if (id !== this.cline?.taskId) {
|
||||||
// non-current task
|
// non-current task
|
||||||
const { historyItem } = await this.getTaskWithId(id)
|
const { historyItem } = await this.getTaskWithId(id)
|
||||||
await this.initClaudeDevWithHistoryItem(historyItem) // clears existing task
|
await this.initClineWithHistoryItem(historyItem) // clears existing task
|
||||||
}
|
}
|
||||||
await this.postMessageToWebview({ type: "action", action: "chatButtonTapped" })
|
await this.postMessageToWebview({ type: "action", action: "chatButtonTapped" })
|
||||||
}
|
}
|
||||||
@@ -692,7 +692,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async deleteTaskWithId(id: string) {
|
async deleteTaskWithId(id: string) {
|
||||||
if (id === this.claudeDev?.taskId) {
|
if (id === this.cline?.taskId) {
|
||||||
await this.clearTask()
|
await this.clearTask()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -736,15 +736,15 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
customInstructions,
|
customInstructions,
|
||||||
alwaysAllowReadOnly,
|
alwaysAllowReadOnly,
|
||||||
uriScheme: vscode.env.uriScheme,
|
uriScheme: vscode.env.uriScheme,
|
||||||
claudeMessages: this.claudeDev?.claudeMessages || [],
|
claudeMessages: this.cline?.claudeMessages || [],
|
||||||
taskHistory: (taskHistory || []).filter((item) => item.ts && item.task).sort((a, b) => b.ts - a.ts),
|
taskHistory: (taskHistory || []).filter((item) => item.ts && item.task).sort((a, b) => b.ts - a.ts),
|
||||||
shouldShowAnnouncement: lastShownAnnouncementId !== this.latestAnnouncementId,
|
shouldShowAnnouncement: lastShownAnnouncementId !== this.latestAnnouncementId,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearTask() {
|
async clearTask() {
|
||||||
this.claudeDev?.abortTask()
|
this.cline?.abortTask()
|
||||||
this.claudeDev = undefined // removes reference to it, so once promises end it will be garbage collected
|
this.cline = undefined // removes reference to it, so once promises end it will be garbage collected
|
||||||
}
|
}
|
||||||
|
|
||||||
// Caching mechanism to keep track of webview messages + API conversation history per provider instance
|
// Caching mechanism to keep track of webview messages + API conversation history per provider instance
|
||||||
@@ -1004,9 +1004,9 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
for (const key of secretKeys) {
|
for (const key of secretKeys) {
|
||||||
await this.storeSecret(key, undefined)
|
await this.storeSecret(key, undefined)
|
||||||
}
|
}
|
||||||
if (this.claudeDev) {
|
if (this.cline) {
|
||||||
this.claudeDev.abortTask()
|
this.cline.abortTask()
|
||||||
this.claudeDev = undefined
|
this.cline = undefined
|
||||||
}
|
}
|
||||||
vscode.window.showInformationMessage("State reset")
|
vscode.window.showInformationMessage("State reset")
|
||||||
await this.postStateToWebview()
|
await this.postStateToWebview()
|
||||||
|
|||||||
Reference in New Issue
Block a user