-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Tidy up following ClineProvider refactor #2182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tidy up following ClineProvider refactor #2182
Conversation
Increase type flexibility so we can directly use postMessageToWebview()
expose new public writeDataToCache() method to commonize code. also decided to leave updateApiConfiguration as public, since widely used in diverse ways.
Symmetric naming of functions that complement each other.
Stop using deprecated (private) method. Use contextProxy set/getValue methods instead. Utility functions provided for brevity.
log is already public, outputChannel should be private. But also prefer log internally for the additional value of console logging, plus code brevity.
|
| import { ExtensionMessage } from "../../shared/ExtensionMessage" | ||
| import { Mode, PromptComponent, defaultModeSlug, getModeBySlug, getGroupName } from "../../shared/modes" | ||
| import { EXPERIMENT_IDS, experiments as Experiments, experimentDefault, ExperimentId } from "../../shared/experiments" | ||
| import { experimentDefault } from "../../shared/experiments" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imports ahould have been removed in previous PR, but I overlooked them
| // not private, so it can be accessed from webviewMessageHandler | ||
| // callers could update to get viewLaunched() getter function | ||
| isViewLaunched = false | ||
| private view?: vscode.WebviewView | vscode.WebviewPanel |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed use of this by changing code to use proper public API: postMessageToWebview
| latestAnnouncementId = "mar-30-2025-3-11" // update for v3.11.0 announcement | ||
| // not private, so it can be accessed from webviewMessageHandler | ||
| settingsImportedAt?: number | ||
| private _workspaceTracker?: WorkspaceTracker // workSpaceTracker read-only for access outside this class |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
workspaceTracker needs to be public to allow access to initializeFilePaths() but we can make it readonly externally.
can't apply the TS readonly property because we need to write to this field in our dispose() method, so this is the next best option in terms of limiting public access.
| public get workspaceTracker(): WorkspaceTracker | undefined { | ||
| return this._workspaceTracker | ||
| } | ||
| protected mcpHub?: McpHub // Change from private to protected |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switched back to "protected" as code was before. I don't understand the value of this being "protected" as I don't see any sub-classes of ClineProvider, but pre-existing comment shows this is intentional.
Could consider switching to same model as workspaceTracker with an internal property _mcpHub and a getter so that external components can access provider.mcpHub rather than provider,getMcpHub().
I think that's a nicer API to offer, but it's orthogonal to this refactor, so I've not made that change.
| return this._workspaceTracker | ||
| } | ||
| protected mcpHub?: McpHub // Change from private to protected | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reordered properties so they are grouped by access privileges.
These ones are accessed one-time in webviewMessageHandler. Simplest solution is to make them public (and readonly for the ones that don't need to be writeable)
| readonly context: vscode.ExtensionContext, | ||
| // not private, so it can be accessed from webviewMessageHandler | ||
| readonly outputChannel: vscode.OutputChannel, | ||
| private readonly outputChannel: vscode.OutputChannel, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made this private again.
Prefer provider.log() over provider.outputChannel.appendLine()
| super() | ||
|
|
||
| this.outputChannel.appendLine("ClineProvider instantiated") | ||
| this.log("ClineProvider instantiated") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made this change throughout this module, as well as in webviewMessageHandler - it's more concise and cleaner.
Minor functional change in that we also log to console, but volume will be minimal, and probably useful to log to console as well as to the outputChannel.
| telemetryService.setProvider(this) | ||
|
|
||
| this.workspaceTracker = new WorkspaceTracker(this) | ||
| this._workspaceTracker = new WorkspaceTracker(this) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above - internal field is now _workspaceTracker.
workspaceTracker is public, but read-only via a getter.
| } | ||
|
|
||
| // not private, so it can be accessed from webviewMessageHandler | ||
| async writeModelsToCache<T>(filename: string, data: T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New function, avoids need to make ensureCacheDirectoryExists public, and offers a higher level of abstraction to message handlers.
Symmetry with pre-existing readModelsFromCache function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe in the future we can remove file management from this file.
| // @deprecated - Use `ContextProxy#setValue` instead. | ||
| // not private, so it can be accessed from webviewMessageHandler | ||
| async updateGlobalState<K extends keyof GlobalState>(key: K, value: GlobalState[K]) { | ||
| private async updateGlobalState<K extends keyof GlobalState>(key: K, value: GlobalState[K]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-instate private status here. message handlers use ContextProxy.setValue as per comment.
| // @deprecated - Use `ContextProxy#getValue` instead. | ||
| // not private, so it can be accessed from webviewMessageHandler | ||
| getGlobalState<K extends keyof GlobalState>(key: K) { | ||
| private getGlobalState<K extends keyof GlobalState>(key: K) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-instate private status here. message handlers use ContextProxy.getValue as per comment.
| import { checkoutDiffPayloadSchema, checkoutRestorePayloadSchema, WebviewMessage } from "../../shared/WebviewMessage" | ||
| import { checkExistKey } from "../../shared/checkExistApiConfig" | ||
| import { EXPERIMENT_IDS, experiments as Experiments, experimentDefault, ExperimentId } from "../../shared/experiments" | ||
| import { EXPERIMENT_IDS, experimentDefault, ExperimentId } from "../../shared/experiments" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Superfluous imports - overlooked in previous PR.
| import { TelemetrySetting } from "../../shared/TelemetrySetting" | ||
| import { getWorkspacePath } from "../../utils/path" | ||
| import { Mode, PromptComponent, defaultModeSlug, getModeBySlug, getGroupName } from "../../shared/modes" | ||
| import { Mode, defaultModeSlug, getModeBySlug, getGroupName } from "../../shared/modes" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Superfluous import - overlooked in previous PR
| import { GlobalState } from "../../schemas" | ||
|
|
||
| export const webviewMessageHandler = async (provider: ClineProvider, message: WebviewMessage) => { | ||
| // Utility functions provided for concise get/update of global state via contextProxy API. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
provider.get/updateGlobalState is marked as deprecated in ClineProvider.ts, so don't use it.
getGobalState is more concise than provider.contextProxy.getValue (and used a lot throughout this file, so worthwhile to offer a more concise syntax).
| // Load custom modes first | ||
| const customModes = await provider.customModesManager.getCustomModes() | ||
| await provider.updateGlobalState("customModes", customModes) | ||
| await updateGlobalState("customModes", customModes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uses new local updateGlobalState utility function, over (deprecated, private) provider.updateGlobalState method. You'll see this change many times in this file.
|
|
||
| // If MCP Hub is already initialized, update the webview with current server list | ||
| if (provider.mcpHub) { | ||
| const mcpHub = provider.getMcpHub() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
provider.mcpHub -> protected again. This is the public method to access it.
| }) | ||
| } | ||
|
|
||
| const cacheDir = await provider.ensureCacheDirectoryExists() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is folded into the new higher-level writeModelsToCache() method.
| path.join(cacheDir, GlobalFileNames.openRouterModels), | ||
| JSON.stringify(openRouterModels), | ||
| ) | ||
| await provider.writeModelsToCache(GlobalFileNames.openRouterModels, openRouterModels) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One of several instances where we have moved to the new higher-level writeModelsToCache() method, alowing provider.ensureCacheDirectoryExists() to become private again.
| const currentState = await provider.getState() | ||
| const stateWithPrompts = { ...currentState, customModePrompts: updatedPrompts } | ||
| provider.view?.webview.postMessage({ type: "state", state: stateWithPrompts }) | ||
| provider.postMessageToWebview({ type: "state", state: stateWithPrompts }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use public API, rather than accessing private view property. Had to slightly adjust types on postMessageToWebview to enable this - see later.
That might be why the code had been written this way previously.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change of plan - use provider.getStateToPostToWebview() instead, then no type relaxation needed.
src/shared/ExtensionMessage.ts
Outdated
| | "didBecomeVisible" | ||
| invoke?: "newChat" | "sendMessage" | "primaryButtonClick" | "secondaryButtonClick" | "setChatBoxMessage" | ||
| state?: ExtensionState | ||
| state?: Partial<ExtensionState> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Relaxed type here, so that we could move away from using private view property.
See: https://github.com/RooVetGit/Roo-Code/pull/2182/files#r2022956143
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change of plan - not relaxing type after all.
| x.dispose() | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wondered 🤔 why there were areas with output channels and this.log
We also need to remove the console.log to this.log in the future
| } | ||
|
|
||
| // not private, so it can be accessed from webviewMessageHandler | ||
| async writeModelsToCache<T>(filename: string, data: T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe in the future we can remove file management from this file.
Add Korean language
|
Nice 👍
…On Sat, 5 Apr 2025, 23:00 Matt Rubens, ***@***.***> wrote:
Merged #2182 <#2182> into main.
—
Reply to this email directly, view it on GitHub
<#2182 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACUTT3O37AT575Y6LTFBB6D2YBHAZAVCNFSM6AAAAAB2G7RKY6VHI2DSMVQWIX3LMV45UABCJFZXG5LFIV3GK3TUJZXXI2LGNFRWC5DJN5XDWMJXGE2DCNBUGU3TAMQ>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Context
PR #2149 split ClineProvider into two files.
This required making certain private properties of the ClineProvider class public.
For this PR, I have carefully reviewed all of those, and tidied up everything I can to make the public interface of ClineProvider as clean as possible.
Implementation
Approach:
For specific details, see line-by-line comments in the code review.
Screenshots
N/A
How to Test
As with previous refactoring, given that the TS compiles cleanly, risk seems low.
No obvious targeted testing that would be valuable. The changes are wide-ranging, so a lot of code paths will be altered, but all in pretty minimal ways that should not impact function.
Get in Touch
@diarmidm on Discord, or the Cline.ts modularization Discord channel.
Important
Refactor
ClineProviderto improve encapsulation and state management, adjusting public interfaces and utilizingcontextProxyfor cleaner code.view,workspaceTracker, andmcpHubprivate or read-only inClineProvider.getMcpHub()inClineProviderto accessmcpHub.outputChannel.appendLinewithlog()inClineProviderandwebviewMessageHandler.contextProxyfor state management inwebviewMessageHandler.ExtensionStateinExtensionMessage.tsto usePartial<ExtensionState>.mergeExtensionStateinExtensionStateContext.tsxto handle partial state updates.This description was created by
for 783138c. It will automatically update as commits are pushed.