diff --git a/src/core/Cline.ts b/src/core/Cline.ts index b1ec758..1098f22 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -59,7 +59,7 @@ export class Cline { customInstructions?: string alwaysAllowReadOnly: boolean apiConversationHistory: Anthropic.MessageParam[] = [] - claudeMessages: ClineMessage[] = [] + clineMessages: ClineMessage[] = [] private askResponse?: ClineAskResponse private askResponseText?: string private askResponseImages?: string[] @@ -149,7 +149,7 @@ export class Cline { } } - private async getSavedClaudeMessages(): Promise { + private async getSavedClineMessages(): Promise { const filePath = path.join(await this.ensureTaskDirectoryExists(), GlobalFileNames.uiMessages) if (await fileExistsAtPath(filePath)) { return JSON.parse(await fs.readFile(filePath, "utf8")) @@ -165,27 +165,27 @@ export class Cline { return [] } - private async addToClaudeMessages(message: ClineMessage) { - this.claudeMessages.push(message) - await this.saveClaudeMessages() + private async addToClineMessages(message: ClineMessage) { + this.clineMessages.push(message) + await this.saveClineMessages() } - private async overwriteClaudeMessages(newMessages: ClineMessage[]) { - this.claudeMessages = newMessages - await this.saveClaudeMessages() + private async overwriteClineMessages(newMessages: ClineMessage[]) { + this.clineMessages = newMessages + await this.saveClineMessages() } - private async saveClaudeMessages() { + private async saveClineMessages() { try { const filePath = path.join(await this.ensureTaskDirectoryExists(), GlobalFileNames.uiMessages) - await fs.writeFile(filePath, JSON.stringify(this.claudeMessages)) + await fs.writeFile(filePath, JSON.stringify(this.clineMessages)) // combined as they are in ChatView - const apiMetrics = getApiMetrics(combineApiRequests(combineCommandSequences(this.claudeMessages.slice(1)))) - const taskMessage = this.claudeMessages[0] // first message is always the task say + const apiMetrics = getApiMetrics(combineApiRequests(combineCommandSequences(this.clineMessages.slice(1)))) + const taskMessage = this.clineMessages[0] // first message is always the task say const lastRelevantMessage = - this.claudeMessages[ + this.clineMessages[ findLastIndex( - this.claudeMessages, + this.clineMessages, (m) => !(m.ask === "resume_task" || m.ask === "resume_completed_task") ) ] @@ -200,7 +200,7 @@ export class Cline { totalCost: apiMetrics.totalCost, }) } catch (error) { - console.error("Failed to save claude messages:", error) + console.error("Failed to save cline messages:", error) } } @@ -218,7 +218,7 @@ export class Cline { } let askTs: number if (partial !== undefined) { - const lastMessage = this.claudeMessages.at(-1) + const lastMessage = this.clineMessages.at(-1) const isUpdatingPreviousPartial = lastMessage && lastMessage.partial && lastMessage.type === "ask" && lastMessage.ask === type if (partial) { @@ -227,7 +227,7 @@ export class Cline { lastMessage.text = text lastMessage.partial = partial // todo be more efficient about saving and posting only new data or one whole message at a time so ignore partial for saves, and only post parts of partial message instead of whole array in new listener - // await this.saveClaudeMessages() + // await this.saveClineMessages() // await this.providerRef.deref()?.postStateToWebview() await this.providerRef .deref() @@ -240,7 +240,7 @@ export class Cline { // this.askResponseImages = undefined askTs = Date.now() this.lastMessageTs = askTs - await this.addToClaudeMessages({ ts: askTs, type: "ask", ask: type, text, partial }) + await this.addToClineMessages({ ts: askTs, type: "ask", ask: type, text, partial }) await this.providerRef.deref()?.postStateToWebview() throw new Error("Current ask promise was ignored 2") } @@ -263,7 +263,7 @@ export class Cline { // lastMessage.ts = askTs lastMessage.text = text lastMessage.partial = false - await this.saveClaudeMessages() + await this.saveClineMessages() // await this.providerRef.deref()?.postStateToWebview() await this.providerRef .deref() @@ -275,19 +275,19 @@ export class Cline { this.askResponseImages = undefined askTs = Date.now() this.lastMessageTs = askTs - await this.addToClaudeMessages({ ts: askTs, type: "ask", ask: type, text }) + await this.addToClineMessages({ ts: askTs, type: "ask", ask: type, text }) await this.providerRef.deref()?.postStateToWebview() } } } else { // this is a new non-partial message, so add it like normal - // const lastMessage = this.claudeMessages.at(-1) + // const lastMessage = this.clineMessages.at(-1) this.askResponse = undefined this.askResponseText = undefined this.askResponseImages = undefined askTs = Date.now() this.lastMessageTs = askTs - await this.addToClaudeMessages({ ts: askTs, type: "ask", ask: type, text }) + await this.addToClineMessages({ ts: askTs, type: "ask", ask: type, text }) await this.providerRef.deref()?.postStateToWebview() } @@ -314,7 +314,7 @@ export class Cline { } if (partial !== undefined) { - const lastMessage = this.claudeMessages.at(-1) + const lastMessage = this.clineMessages.at(-1) const isUpdatingPreviousPartial = lastMessage && lastMessage.partial && lastMessage.type === "say" && lastMessage.say === type if (partial) { @@ -330,7 +330,7 @@ export class Cline { // this is a new partial message, so add it with partial state const sayTs = Date.now() this.lastMessageTs = sayTs - await this.addToClaudeMessages({ ts: sayTs, type: "say", say: type, text, images, partial }) + await this.addToClineMessages({ ts: sayTs, type: "say", say: type, text, images, partial }) await this.providerRef.deref()?.postStateToWebview() } } else { @@ -344,7 +344,7 @@ export class Cline { lastMessage.partial = false // instead of streaming partialMessage events, we do a save and post like normal to persist to disk - await this.saveClaudeMessages() + await this.saveClineMessages() // await this.providerRef.deref()?.postStateToWebview() await this.providerRef .deref() @@ -353,7 +353,7 @@ export class Cline { // this is a new partial=false message, so add it like normal const sayTs = Date.now() this.lastMessageTs = sayTs - await this.addToClaudeMessages({ ts: sayTs, type: "say", say: type, text, images }) + await this.addToClineMessages({ ts: sayTs, type: "say", say: type, text, images }) await this.providerRef.deref()?.postStateToWebview() } } @@ -361,7 +361,7 @@ export class Cline { // this is a new non-partial message, so add it like normal const sayTs = Date.now() this.lastMessageTs = sayTs - await this.addToClaudeMessages({ ts: sayTs, type: "say", say: type, text, images }) + await this.addToClineMessages({ ts: sayTs, type: "say", say: type, text, images }) await this.providerRef.deref()?.postStateToWebview() } } @@ -369,7 +369,7 @@ export class Cline { async sayAndCreateMissingParamError(toolName: ToolUseName, paramName: string, relPath?: string) { await this.say( "error", - `Claude tried to use ${toolName}${ + `Cline tried to use ${toolName}${ relPath ? ` for '${relPath.toPosix()}'` : "" } without value for required parameter '${paramName}'. Retrying...` ) @@ -379,9 +379,9 @@ export class Cline { // Task lifecycle private async startTask(task?: string, images?: string[]): Promise { - // 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 Cline client (otherwise webview would show stale messages from previous session) - this.claudeMessages = [] + // conversationHistory (for API) and clineMessages (for webview) need to be in sync + // if the extension process were killed, then on restart the clineMessages might not be empty, so we need to set it to [] when we create a new Cline client (otherwise webview would show stale messages from previous session) + this.clineMessages = [] this.apiConversationHistory = [] await this.providerRef.deref()?.postStateToWebview() @@ -398,52 +398,52 @@ export class Cline { } private async resumeTaskFromHistory() { - const modifiedClaudeMessages = await this.getSavedClaudeMessages() + const modifiedClineMessages = await this.getSavedClineMessages() // Remove any resume messages that may have been added before const lastRelevantMessageIndex = findLastIndex( - modifiedClaudeMessages, + modifiedClineMessages, (m) => !(m.ask === "resume_task" || m.ask === "resume_completed_task") ) if (lastRelevantMessageIndex !== -1) { - modifiedClaudeMessages.splice(lastRelevantMessageIndex + 1) + modifiedClineMessages.splice(lastRelevantMessageIndex + 1) } // since we don't use api_req_finished anymore, we need to check if the last api_req_started has a cost value, if it doesn't and no cancellation reason to present, then we remove it since it indicates an api request without any partial content streamed const lastApiReqStartedIndex = findLastIndex( - modifiedClaudeMessages, + modifiedClineMessages, (m) => m.type === "say" && m.say === "api_req_started" ) if (lastApiReqStartedIndex !== -1) { - const lastApiReqStarted = modifiedClaudeMessages[lastApiReqStartedIndex] + const lastApiReqStarted = modifiedClineMessages[lastApiReqStartedIndex] const { cost, cancelReason }: ClineApiReqInfo = JSON.parse(lastApiReqStarted.text || "{}") if (cost === undefined && cancelReason === undefined) { - modifiedClaudeMessages.splice(lastApiReqStartedIndex, 1) + modifiedClineMessages.splice(lastApiReqStartedIndex, 1) } } - await this.overwriteClaudeMessages(modifiedClaudeMessages) - this.claudeMessages = await this.getSavedClaudeMessages() + await this.overwriteClineMessages(modifiedClineMessages) + this.clineMessages = await this.getSavedClineMessages() - // Now present the claude messages to the user and ask if they want to resume + // Now present the cline messages to the user and ask if they want to resume - const lastClaudeMessage = this.claudeMessages + const lastClineMessage = this.clineMessages .slice() .reverse() .find((m) => !(m.ask === "resume_task" || m.ask === "resume_completed_task")) // could be multiple resume tasks - // const lastClaudeMessage = this.claudeMessages[lastClaudeMessageIndex] + // const lastClineMessage = this.clineMessages[lastClineMessageIndex] // could be a completion result with a command - // const secondLastClaudeMessage = this.claudeMessages + // const secondLastClineMessage = this.clineMessages // .slice() // .reverse() // .find( // (m, index) => - // index !== lastClaudeMessageIndex && !(m.ask === "resume_task" || m.ask === "resume_completed_task") + // index !== lastClineMessageIndex && !(m.ask === "resume_task" || m.ask === "resume_completed_task") // ) - // (lastClaudeMessage?.ask === "command" && secondLastClaudeMessage?.ask === "completion_result") + // (lastClineMessage?.ask === "command" && secondLastClineMessage?.ask === "completion_result") let askType: ClineAsk - if (lastClaudeMessage?.ask === "completion_result") { + if (lastClineMessage?.ask === "completion_result") { askType = "resume_completed_task" } else { askType = "resume_task" @@ -458,7 +458,7 @@ export class Cline { responseImages = images } - // need to make sure that the api conversation history can be resumed by the api, even if it goes out of sync with claude messages + // need to make sure that the api conversation history can be resumed by the api, even if it goes out of sync with cline messages // if the last message is an assistant message, we need to check if there's tool use since every tool use has to have a tool response // if there's no tool use and only a text block, then we can just add a user message @@ -546,7 +546,7 @@ export class Cline { let newUserContent: UserContent = [...modifiedOldUserContent] const agoText = (() => { - const timestamp = lastClaudeMessage?.ts ?? Date.now() + const timestamp = lastClineMessage?.ts ?? Date.now() const now = Date.now() const diff = now - timestamp const minutes = Math.floor(diff / 60000) @@ -586,11 +586,11 @@ export class Cline { let nextUserContent = userContent let includeFileDetails = true while (!this.abort) { - const didEndLoop = await this.recursivelyMakeClaudeRequests(nextUserContent, includeFileDetails) + const didEndLoop = await this.recursivelyMakeClineRequests(nextUserContent, includeFileDetails) includeFileDetails = false // we only need file details the first time - // The way this agentic loop works is that claude will be given a task that he then calls tools to complete. unless there's an attempt_completion call, we keep responding back to him with his tool's responses until he either attempt_completion or does not use anymore tools. If he does not use anymore tools, we ask him to consider if he's completed the task and then call attempt_completion, otherwise proceed with completing the task. - // There is a MAX_REQUESTS_PER_TASK limit to prevent infinite requests, but Claude is prompted to finish the task as efficiently as he can. + // The way this agentic loop works is that cline will be given a task that he then calls tools to complete. unless there's an attempt_completion call, we keep responding back to him with his tool's responses until he either attempt_completion or does not use anymore tools. If he does not use anymore tools, we ask him to consider if he's completed the task and then call attempt_completion, otherwise proceed with completing the task. + // There is a MAX_REQUESTS_PER_TASK limit to prevent infinite requests, but Cline is prompted to finish the task as efficiently as he can. //const totalCost = this.calculateApiCost(totalInputTokens, totalOutputTokens) if (didEndLoop) { @@ -600,7 +600,7 @@ export class Cline { } else { // this.say( // "tool", - // "Claude responded with only text blocks but has not called attempt_completion yet. Forcing him to continue with task..." + // "Cline responded with only text blocks but has not called attempt_completion yet. Forcing him to continue with task..." // ) nextUserContent = [ { @@ -708,7 +708,7 @@ export class Cline { // If the previous API request's total token usage is close to the context window, truncate the conversation history to free up space for the new request if (previousApiReqIndex >= 0) { - const previousRequest = this.claudeMessages[previousApiReqIndex] + const previousRequest = this.clineMessages[previousApiReqIndex] if (previousRequest && previousRequest.text) { const { tokensIn, tokensOut, cacheWrites, cacheReads }: ClineApiReqInfo = JSON.parse( previousRequest.text @@ -1395,7 +1395,7 @@ export class Cline { let resultToSend = result if (command) { await this.say("completion_result", resultToSend) - // TODO: currently we don't handle if this command fails, it could be useful to let claude know and retry + // TODO: currently we don't handle if this command fails, it could be useful to let cline know and retry const [didUserReject, commandResult] = await this.executeCommand(command, true) // if we received non-empty string, the command was rejected or failed if (commandResult) { @@ -1413,13 +1413,13 @@ export class Cline { const result: string | undefined = block.params.result const command: string | undefined = block.params.command try { - const lastMessage = this.claudeMessages.at(-1) + const lastMessage = this.clineMessages.at(-1) if (block.partial) { if (command) { // the attempt_completion text is done, now we're getting command // remove the previous partial attempt_completion ask, replace with say, post state to webview, then stream command - // const secondLastMessage = this.claudeMessages.at(-2) + // const secondLastMessage = this.clineMessages.at(-2) if (lastMessage && lastMessage.ask === "command") { // update command await this.ask( @@ -1555,7 +1555,7 @@ export class Cline { } } - async recursivelyMakeClaudeRequests( + async recursivelyMakeClineRequests( userContent: UserContent, includeFileDetails: boolean = false ): Promise { @@ -1585,7 +1585,7 @@ export class Cline { } // get previous api req's index to check token usage and determine if we need to truncate conversation history - const previousApiReqIndex = findLastIndex(this.claudeMessages, (m) => m.say === "api_req_started") + const previousApiReqIndex = findLastIndex(this.clineMessages, (m) => m.say === "api_req_started") // 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 placeholder api_req_started message with a loading spinner as this happens @@ -1605,11 +1605,11 @@ export class Cline { await this.addToApiConversationHistory({ role: "user", content: userContent }) // since we sent off a placeholder api_req_started message to update the webview while waiting to actually start the API request (to load potential details for example), we need to update the text of that message - const lastApiReqIndex = findLastIndex(this.claudeMessages, (m) => m.say === "api_req_started") - this.claudeMessages[lastApiReqIndex].text = JSON.stringify({ + const lastApiReqIndex = findLastIndex(this.clineMessages, (m) => m.say === "api_req_started") + this.clineMessages[lastApiReqIndex].text = JSON.stringify({ request: userContent.map((block) => formatContentBlockToMarkdown(block)).join("\n\n"), } satisfies ClineApiReqInfo) - await this.saveClaudeMessages() + await this.saveClineMessages() await this.providerRef.deref()?.postStateToWebview() try { @@ -1623,8 +1623,8 @@ export class Cline { // fortunately api_req_finished was always parsed out for the gui anyways, so it remains solely for legacy purposes to keep track of prices in tasks from history // (it's worth removing a few months from now) const updateApiReqMsg = (cancelReason?: ClineApiReqCancelReason, streamingFailedMessage?: string) => { - this.claudeMessages[lastApiReqIndex].text = JSON.stringify({ - ...JSON.parse(this.claudeMessages[lastApiReqIndex].text || "{}"), + this.clineMessages[lastApiReqIndex].text = JSON.stringify({ + ...JSON.parse(this.clineMessages[lastApiReqIndex].text || "{}"), tokensIn: inputTokens, tokensOut: outputTokens, cacheWrites: cacheWriteTokens, @@ -1649,13 +1649,13 @@ export class Cline { } // if last message is a partial we need to update and save it - const lastMessage = this.claudeMessages.at(-1) + const lastMessage = this.clineMessages.at(-1) if (lastMessage && lastMessage.partial) { // lastMessage.ts = Date.now() DO NOT update ts since it is used as a key for virtuoso list lastMessage.partial = false // instead of streaming partialMessage events, we do a save and post like normal to persist to disk console.log("updating partial message", lastMessage) - // await this.saveClaudeMessages() + // await this.saveClineMessages() } // Let assistant know their response was interrupted for when task is resumed @@ -1677,7 +1677,7 @@ export class Cline { // update api_req_started to have cancelled and cost, so that we can display the cost of the partial stream updateApiReqMsg(cancelReason, streamingFailedMessage) - await this.saveClaudeMessages() + await this.saveClineMessages() // signals to provider that it can retrieve the saved messages from disk, as abortTask can not be awaited on in nature this.didFinishAborting = true @@ -1761,7 +1761,7 @@ export class Cline { } updateApiReqMsg() - await this.saveClaudeMessages() + await this.saveClineMessages() await this.providerRef.deref()?.postStateToWebview() // now add to apiconversationhistory @@ -1793,7 +1793,7 @@ export class Cline { this.consecutiveMistakeCount++ } - const recDidEndLoop = await this.recursivelyMakeClaudeRequests(this.userMessageContent) + const recDidEndLoop = await this.recursivelyMakeClineRequests(this.userMessageContent) didEndLoop = recDidEndLoop } else { // if there's no assistant_responses, that means we got no text or tool_use content blocks from API which we should assume is an error @@ -1863,7 +1863,7 @@ export class Cline { async getEnvironmentDetails(includeFileDetails: boolean = false) { let details = "" - // It could be useful for claude to know if the user went from one or no file to another between messages, so we always include this context + // It could be useful for cline to know if the user went from one or no file to another between messages, so we always include this context details += "\n\n# VSCode Visible Files" const visibleFiles = vscode.window.visibleTextEditors ?.map((editor) => editor.document?.uri?.fsPath) @@ -1911,7 +1911,7 @@ export class Cline { // we want to get diagnostics AFTER terminal cools down for a few reasons: terminal could be scaffolding a project, dev servers (compilers like webpack) will first re-compile and then send diagnostics, etc /* let diagnosticsDetails = "" - const diagnostics = await this.diagnosticsMonitor.getCurrentDiagnostics(this.didEditFile || terminalWasBusy) // if claude ran a command (ie npm install) or edited the workspace then wait a bit for updated diagnostics + const diagnostics = await this.diagnosticsMonitor.getCurrentDiagnostics(this.didEditFile || terminalWasBusy) // if cline ran a command (ie npm install) or edited the workspace then wait a bit for updated diagnostics for (const [uri, fileDiagnostics] of diagnostics) { const problems = fileDiagnostics.filter((d) => d.severity === vscode.DiagnosticSeverity.Error) if (problems.length > 0) { diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index a313722..3ee65c2 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -180,9 +180,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { // if the extension is starting a new session, clear previous task state this.clearTask() - // Clear previous version's (0.0.6) claudeMessage cache from workspace state. We now store in global state with a unique identifier for each provider instance. We need to store globally rather than per workspace to eventually implement task history - this.updateWorkspaceState("claudeMessages", undefined) - this.outputChannel.appendLine("Webview view resolved") } @@ -719,7 +716,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { customInstructions, alwaysAllowReadOnly, uriScheme: vscode.env.uriScheme, - claudeMessages: this.cline?.claudeMessages || [], + clineMessages: this.cline?.clineMessages || [], taskHistory: (taskHistory || []).filter((item) => item.ts && item.task).sort((a, b) => b.ts - a.ts), shouldShowAnnouncement: lastShownAnnouncementId !== this.latestAnnouncementId, } @@ -740,41 +737,6 @@ export class ClineProvider implements vscode.WebviewViewProvider { We need to use a unique identifier for each ClineProvider instance's message cache since we could be running several instances of the extension outside of just the sidebar i.e. in editor panels. - For now since we don't need to store task history, we'll just use an identifier unique to this provider instance (since there can be several provider instances open at once). - However in the future when we implement task history, we'll need to use a unique identifier for each task. As well as manage a data structure that keeps track of task history with their associated identifiers and the task message itself, to present in a 'Task History' view. - Task history is a significant undertaking as it would require refactoring how we wait for ask responses--it would need to be a hidden claudeMessage, so that user's can resume tasks that ended with an ask. - */ - // private providerInstanceIdentifier = Date.now() - // getClaudeMessagesStateKey() { - // return `claudeMessages-${this.providerInstanceIdentifier}` - // } - - // getApiConversationHistoryStateKey() { - // return `apiConversationHistory-${this.providerInstanceIdentifier}` - // } - - // claude messages to present in the webview - - // getClaudeMessages(): ClaudeMessage[] { - // // const messages = (await this.getGlobalState(this.getClaudeMessagesStateKey())) as ClaudeMessage[] - // // return messages || [] - // return this.claudeMessages - // } - - // setClaudeMessages(messages: ClaudeMessage[] | undefined) { - // // await this.updateGlobalState(this.getClaudeMessagesStateKey(), messages) - // this.claudeMessages = messages || [] - // } - - // addClaudeMessage(message: ClaudeMessage): ClaudeMessage[] { - // // const messages = await this.getClaudeMessages() - // // messages.push(message) - // // await this.setClaudeMessages(messages) - // // return messages - // this.claudeMessages.push(message) - // return this.claudeMessages - // } - // conversation history to send in API requests /* diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index 355f2c8..349475c 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -32,7 +32,7 @@ export interface ExtensionState { customInstructions?: string alwaysAllowReadOnly?: boolean uriScheme?: string - claudeMessages: ClineMessage[] + clineMessages: ClineMessage[] taskHistory: HistoryItem[] shouldShowAnnouncement: boolean } diff --git a/src/shared/combineApiRequests.ts b/src/shared/combineApiRequests.ts index 6dcdb0e..be8721b 100644 --- a/src/shared/combineApiRequests.ts +++ b/src/shared/combineApiRequests.ts @@ -1,14 +1,14 @@ import { ClineMessage } from "./ExtensionMessage" /** - * Combines API request start and finish messages in an array of ClaudeMessages. + * Combines API request start and finish messages in an array of ClineMessages. * * This function looks for pairs of 'api_req_started' and 'api_req_finished' messages. * When it finds a pair, it combines them into a single 'api_req_combined' message. * The JSON data in the text fields of both messages are merged. * - * @param messages - An array of ClaudeMessage objects to process. - * @returns A new array of ClaudeMessage objects with API requests combined. + * @param messages - An array of ClineMessage objects to process. + * @returns A new array of ClineMessage objects with API requests combined. * * @example * const messages = [ diff --git a/src/shared/combineCommandSequences.ts b/src/shared/combineCommandSequences.ts index ad2623b..31fe219 100644 --- a/src/shared/combineCommandSequences.ts +++ b/src/shared/combineCommandSequences.ts @@ -1,18 +1,18 @@ import { ClineMessage } from "./ExtensionMessage" /** - * Combines sequences of command and command_output messages in an array of ClaudeMessages. + * Combines sequences of command and command_output messages in an array of ClineMessages. * - * This function processes an array of ClaudeMessage objects, looking for sequences + * This function processes an array of ClineMessages objects, looking for sequences * where a 'command' message is followed by one or more 'command_output' messages. * When such a sequence is found, it combines them into a single message, merging * their text contents. * - * @param messages - An array of ClaudeMessage objects to process. - * @returns A new array of ClaudeMessage objects with command sequences combined. + * @param messages - An array of ClineMessage objects to process. + * @returns A new array of ClineMessage objects with command sequences combined. * * @example - * const messages: ClaudeMessage[] = [ + * const messages: ClineMessage[] = [ * { type: 'ask', ask: 'command', text: 'ls', ts: 1625097600000 }, * { type: 'ask', ask: 'command_output', text: 'file1.txt', ts: 1625097601000 }, * { type: 'ask', ask: 'command_output', text: 'file2.txt', ts: 1625097602000 } diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 62dc42d..517d7d8 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -28,7 +28,7 @@ interface ChatViewProps { export const MAX_IMAGES_PER_MESSAGE = 20 // Anthropic limits to 20 images const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryView }: ChatViewProps) => { - const { version, claudeMessages: messages, taskHistory, apiConfiguration } = useExtensionState() + const { version, clineMessages: messages, taskHistory, apiConfiguration } = useExtensionState() //const task = messages.length > 0 ? (messages[0].say === "task" ? messages[0] : undefined) : undefined) : undefined const task = useMemo(() => messages.at(0), [messages]) // leaving this less safe version here since if the first message is not a task, then the extension is in a bad state and needs to be debugged (see Cline.abort) diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index d9c673f..8381ee8 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -23,7 +23,7 @@ const ExtensionStateContext = createContext = ({ children }) => { const [state, setState] = useState({ version: "", - claudeMessages: [], + clineMessages: [], taskHistory: [], shouldShowAnnouncement: false, }) @@ -69,11 +69,11 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode const partialMessage = message.partialMessage! setState((prevState) => { // worth noting it will never be possible for a more up-to-date message to be sent here or in normal messages post since the presentAssistantContent function uses lock - const lastIndex = findLastIndex(prevState.claudeMessages, (msg) => msg.ts === partialMessage.ts) + const lastIndex = findLastIndex(prevState.clineMessages, (msg) => msg.ts === partialMessage.ts) if (lastIndex !== -1) { - const newClaudeMessages = [...prevState.claudeMessages] - newClaudeMessages[lastIndex] = partialMessage - return { ...prevState, claudeMessages: newClaudeMessages } + const newClineMessages = [...prevState.clineMessages] + newClineMessages[lastIndex] = partialMessage + return { ...prevState, clineMessages: newClineMessages } } return prevState })