diff options
| author | Jacob MacDonald <[email protected]> | 2025-08-18 14:09:02 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-08-18 21:09:02 +0000 |
| commit | 3960ccf78197c140ee483fccd654680894cdea47 (patch) | |
| tree | c6533f9afb4384ed8d7c0411adcaa1c98d3d4b20 /packages/core/src/utils/workspaceContext.ts | |
| parent | 465ac9f547d0d684439886d1466c1a1133da611d (diff) | |
Add MCP Root change notifications (#6502)
Diffstat (limited to 'packages/core/src/utils/workspaceContext.ts')
| -rw-r--r-- | packages/core/src/utils/workspaceContext.ts | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/packages/core/src/utils/workspaceContext.ts b/packages/core/src/utils/workspaceContext.ts index be99a83c..924cd601 100644 --- a/packages/core/src/utils/workspaceContext.ts +++ b/packages/core/src/utils/workspaceContext.ts @@ -8,6 +8,8 @@ import { isNodeError } from '../utils/errors.js'; import * as fs from 'fs'; import * as path from 'path'; +export type Unsubscribe = () => void; + /** * WorkspaceContext manages multiple workspace directories and validates paths * against them. This allows the CLI to operate on files from multiple directories @@ -16,6 +18,7 @@ import * as path from 'path'; export class WorkspaceContext { private directories = new Set<string>(); private initialDirectories: Set<string>; + private onDirectoriesChangedListeners = new Set<() => void>(); /** * Creates a new WorkspaceContext with the given initial directory and optional additional directories. @@ -32,12 +35,41 @@ export class WorkspaceContext { } /** + * Registers a listener that is called when the workspace directories change. + * @param listener The listener to call. + * @returns A function to unsubscribe the listener. + */ + onDirectoriesChanged(listener: () => void): Unsubscribe { + this.onDirectoriesChangedListeners.add(listener); + return () => { + this.onDirectoriesChangedListeners.delete(listener); + }; + } + + private notifyDirectoriesChanged() { + // Iterate over a copy of the set in case a listener unsubscribes itself or others. + for (const listener of [...this.onDirectoriesChangedListeners]) { + try { + listener(); + } catch (e) { + // Don't let one listener break others. + console.error('Error in WorkspaceContext listener:', e); + } + } + } + + /** * Adds a directory to the workspace. * @param directory The directory path to add (can be relative or absolute) * @param basePath Optional base path for resolving relative paths (defaults to cwd) */ addDirectory(directory: string, basePath: string = process.cwd()): void { - this.directories.add(this.resolveAndValidateDir(directory, basePath)); + const resolved = this.resolveAndValidateDir(directory, basePath); + if (this.directories.has(resolved)) { + return; + } + this.directories.add(resolved); + this.notifyDirectoriesChanged(); } private resolveAndValidateDir( @@ -72,9 +104,17 @@ export class WorkspaceContext { } setDirectories(directories: readonly string[]): void { - this.directories.clear(); + const newDirectories = new Set<string>(); for (const dir of directories) { - this.addDirectory(dir); + newDirectories.add(this.resolveAndValidateDir(dir)); + } + + if ( + newDirectories.size !== this.directories.size || + ![...newDirectories].every((d) => this.directories.has(d)) + ) { + this.directories = newDirectories; + this.notifyDirectoriesChanged(); } } |
