From 6e299c73f56bbc43c8eb6bb1597a33fcd7dc56f4 Mon Sep 17 00:00:00 2001 From: Smartsheet-JB-Brown Date: Wed, 16 Apr 2025 19:28:39 -0700 Subject: [PATCH] update documentation --- .../implementation/01-architecture.md | 57 +++-- .../implementation/02-core-components.md | 127 ++++++++++-- .../implementation/03-data-structures.md | 97 ++++++++- .../implementation/04-search-and-filter.md | 84 ++++++-- .../implementation/05-ui-components.md | 195 +++++++++++++++++- .../package_manager/implementation/README.md | 35 ++++ 6 files changed, 537 insertions(+), 58 deletions(-) create mode 100644 cline_docs/package_manager/implementation/README.md diff --git a/cline_docs/package-manager/implementation/01-architecture.md b/cline_docs/package-manager/implementation/01-architecture.md index 9e9e283032..ca3cda2108 100644 --- a/cline_docs/package-manager/implementation/01-architecture.md +++ b/cline_docs/package-manager/implementation/01-architecture.md @@ -13,6 +13,7 @@ graph TD User[User] -->|Interacts with| UI[Package Manager UI] UI -->|Sends messages| MH[Message Handler] MH -->|Processes requests| PM[PackageManagerManager] + PM -->|Validates sources| PSV[PackageManagerSourceValidation] PM -->|Fetches repos| GF[GitFetcher] GF -->|Scans metadata| MS[MetadataScanner] MS -->|Reads| FS[File System / Git Repositories] @@ -171,6 +172,16 @@ classDiagram +sortItems(sortBy, order): PackageManagerItem[] +refreshRepository(url): void -queueOperation(operation): void + -validateSources(sources): ValidationError[] + } + + class PackageManagerSourceValidation { + +validateSourceUrl(url): ValidationError[] + +validateSourceName(name): ValidationError[] + +validateSourceDuplicates(sources): ValidationError[] + +validateSource(source): ValidationError[] + +validateSources(sources): ValidationError[] + -isValidGitRepositoryUrl(url): boolean } class GitFetcher { @@ -190,16 +201,25 @@ classDiagram } class PackageManagerViewStateManager { - -items: PackageManagerItem[] - -filters: Filters - -sortBy: string - -sortOrder: string - +setFilters(filters): void - +getFilteredAndSortedItems(): PackageManagerItem[] - -itemMatchesFilters(item): boolean + -state: ViewState + -stateChangeHandlers: Set + -fetchTimeoutId: NodeJS.Timeout + -sourcesModified: boolean + +initialize(): void + +onStateChange(handler): () => void + +cleanup(): void + +getState(): ViewState + +transition(transition): Promise + -notifyStateChange(): void + -clearFetchTimeout(): void + -isFilterActive(): boolean + -filterItems(items): PackageManagerItem[] + -sortItems(items): PackageManagerItem[] + +handleMessage(message): Promise } PackageManagerManager --> GitFetcher: uses + PackageManagerManager --> PackageManagerSourceValidation: uses GitFetcher --> MetadataScanner: uses PackageManagerManager --> PackageManagerViewStateManager: updates ``` @@ -239,26 +259,37 @@ classDiagram 1. **PackageManagerViewStateManager** - - Manages view-level state - - Handles filtering and sorting - - Maintains UI preferences + - Manages frontend state and backend synchronization + - Handles state transitions and message processing + - Manages filtering, sorting, and view preferences - Coordinates with backend state + - Handles timeout protection for operations + - Manages source modification tracking + - Provides state change subscriptions -2. **PackageManagerItemCard** +2. **PackageManagerSourceValidation** + + - Validates Git repository URLs for any domain + - Validates source names and configurations + - Detects duplicate sources (case-insensitive) + - Provides structured validation errors + - Supports multiple Git protocols (HTTPS, SSH, Git) + +3. **PackageManagerItemCard** - Displays package information - Handles tag interactions - Manages expandable sections - Shows match highlights -3. **ExpandableSection** +4. **ExpandableSection** - Provides collapsible sections - Manages expand/collapse state - Handles animations - Shows section metadata -4. **TypeGroup** +5. **TypeGroup** - Groups items by type - Formats item lists - Highlights search matches diff --git a/cline_docs/package-manager/implementation/02-core-components.md b/cline_docs/package-manager/implementation/02-core-components.md index e411bd9607..f274795de8 100644 --- a/cline_docs/package-manager/implementation/02-core-components.md +++ b/cline_docs/package-manager/implementation/02-core-components.md @@ -234,37 +234,129 @@ The filtering system provides rich functionality: - Support highlighting - Maintain match context -## PackageManagerViewStateManager +## PackageManagerSourceValidation -The PackageManagerViewStateManager handles UI state and view-level operations. +The PackageManagerSourceValidation component handles validation of package manager sources and their configurations. ### Responsibilities -- Managing view-level state -- Handling UI filters -- Coordinating sorting -- Managing item visibility +- Validating Git repository URLs for any domain +- Validating source names and configurations +- Detecting duplicate sources +- Providing structured validation errors +- Supporting multiple Git protocols + +### Implementation Details + +```typescript +export class PackageManagerSourceValidation { + /** + * Validates a package manager source URL + */ + public static validateSourceUrl(url: string): ValidationError[] { + // Implementation details + } + + /** + * Validates a package manager source name + */ + public static validateSourceName(name?: string): ValidationError[] { + // Implementation details + } + + /** + * Validates sources for duplicates + */ + public static validateSourceDuplicates( + sources: PackageManagerSource[], + newSource?: PackageManagerSource, + ): ValidationError[] { + // Implementation details + } + + /** + * Checks if a URL is a valid Git repository URL + */ + private static isValidGitRepositoryUrl(url: string): boolean { + // Implementation details + } +} +``` + +### Key Algorithms + +#### URL Validation + +The URL validation system supports: + +1. **Protocol Validation**: + + - HTTPS URLs + - SSH URLs + - Git protocol URLs + - Custom domains and ports + +2. **Domain Validation**: + + - Any valid domain name + - IP addresses + - Localhost for testing + - Internal company domains + +3. **Path Validation**: + - Username/organization + - Repository name + - Optional .git suffix + - Subpath support + +## PackageManagerViewStateManager + +The PackageManagerViewStateManager manages frontend state and synchronization with the backend. + +### Responsibilities + +- Managing frontend state transitions +- Handling message processing +- Managing timeouts and retries +- Coordinating with backend state +- Providing state change subscriptions +- Managing source modification tracking +- Handling filtering and sorting ### Implementation Details ```typescript class PackageManagerViewStateManager { - private items: PackageManagerItem[] = [] - private sortBy: "name" | "lastUpdated" = "name" - private sortOrder: "asc" | "desc" = "asc" - private filters: Filters = { type: "", search: "", tags: [] } + private state: ViewState + private stateChangeHandlers: Set + private fetchTimeoutId?: NodeJS.Timeout + private sourcesModified: boolean /** - * Get filtered and sorted items + * Initialize state manager */ - public getFilteredAndSortedItems(): PackageManagerItem[] { + public initialize(): void { // Implementation details } /** - * Check if item matches current filters + * Subscribe to state changes */ - private itemMatchesFilters(item: PackageManagerItem | Subcomponent): boolean { + public onStateChange(handler: StateChangeHandler): () => void { + // Implementation details + } + + /** + * Process state transitions + */ + public async transition(transition: ViewStateTransition): Promise { + // Implementation details + } + + /** + * Handle incoming messages + */ + public async handleMessage(message: any): Promise { // Implementation details } } @@ -278,6 +370,7 @@ The components work together through well-defined interfaces: 1. **Repository Operations**: + - PackageManagerManager validates sources with PackageManagerSourceValidation - PackageManagerManager coordinates with GitFetcher - GitFetcher manages repository state - MetadataScanner processes repository content @@ -286,9 +379,11 @@ The components work together through well-defined interfaces: 2. **State Management**: - PackageManagerManager maintains backend state - - ViewStateManager handles UI state - - State changes trigger UI updates + - ViewStateManager handles UI state transitions + - ViewStateManager processes messages + - State changes notify subscribers - Components react to state changes + - Timeout protection ensures responsiveness 3. **User Interactions**: - UI events trigger state updates diff --git a/cline_docs/package-manager/implementation/03-data-structures.md b/cline_docs/package-manager/implementation/03-data-structures.md index f6d295274e..b7b2012780 100644 --- a/cline_docs/package-manager/implementation/03-data-structures.md +++ b/cline_docs/package-manager/implementation/03-data-structures.md @@ -109,6 +109,23 @@ Enhanced match tracking: ## State Management Structures +### ValidationError + +```typescript +/** + * Error type for package manager source validation + */ +export interface ValidationError { + field: string + message: string +} +``` + +Used for structured validation errors: + +- **field**: The field that failed validation (e.g., "url", "name") +- **message**: Human-readable error message + ### ViewState ```typescript @@ -116,18 +133,64 @@ Enhanced match tracking: * View-level state management */ interface ViewState { - items: PackageManagerItem[] - sortBy: "name" | "lastUpdated" - sortOrder: "asc" | "desc" + allItems: PackageManagerItem[] + displayItems?: PackageManagerItem[] + isFetching: boolean + activeTab: "browse" | "sources" + refreshingUrls: string[] + sources: PackageManagerSource[] filters: Filters + sortConfig: { + by: "name" | "author" | "lastUpdated" + order: "asc" | "desc" + } } ``` Manages UI state: -- Current items -- Sort configuration -- Filter state +- **allItems**: All available items +- **displayItems**: Currently filtered/displayed items +- **isFetching**: Loading state indicator +- **activeTab**: Current view tab +- **refreshingUrls**: Sources being refreshed +- **sources**: Package manager sources +- **filters**: Active filters +- **sortConfig**: Sort configuration + +### ViewStateTransition + +```typescript +/** + * State transition types and payloads + */ +type ViewStateTransition = { + type: + | "FETCH_ITEMS" + | "FETCH_COMPLETE" + | "FETCH_ERROR" + | "SET_ACTIVE_TAB" + | "UPDATE_FILTERS" + | "UPDATE_SORT" + | "REFRESH_SOURCE" + | "REFRESH_SOURCE_COMPLETE" + | "UPDATE_SOURCES" + payload?: { + items?: PackageManagerItem[] + tab?: "browse" | "sources" + filters?: Partial + sortConfig?: Partial + url?: string + sources?: PackageManagerSource[] + } +} +``` + +Defines state transitions: + +- Operation types +- Optional payloads +- Type-safe transitions ### Filters @@ -364,14 +427,28 @@ function validateMetadata(metadata: unknown): metadata is ComponentMetadata { /** * Validate Git repository URL */ -function isValidGitUrl(url: string): boolean { - if (!url) return false +function isValidGitRepositoryUrl(url: string): boolean { + // HTTPS pattern (any domain) + const httpsPattern = + /^https?:\/\/[a-zA-Z0-9_.-]+(\.[a-zA-Z0-9_.-]+)*\/[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(\/.+)*(\.git)?$/ - // Support common Git URL formats - return /^(https?:\/\/|git@)/.test(url) && /\.git$/.test(url) + // SSH pattern (any domain) + const sshPattern = /^git@[a-zA-Z0-9_.-]+(\.[a-zA-Z0-9_.-]+)*:([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)(\.git)?$/ + + // Git protocol pattern (any domain) + const gitProtocolPattern = /^git:\/\/[a-zA-Z0-9_.-]+(\.[a-zA-Z0-9_.-]+)*\/[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(\.git)?$/ + + return httpsPattern.test(url) || sshPattern.test(url) || gitProtocolPattern.test(url) } ``` +Supports: + +- Any valid domain name +- Multiple Git protocols +- Optional .git suffix +- Subpath components + ## Data Flow The Package Manager transforms data through several stages: diff --git a/cline_docs/package-manager/implementation/04-search-and-filter.md b/cline_docs/package-manager/implementation/04-search-and-filter.md index 30971f8a03..a941a39347 100644 --- a/cline_docs/package-manager/implementation/04-search-and-filter.md +++ b/cline_docs/package-manager/implementation/04-search-and-filter.md @@ -169,32 +169,74 @@ export function sortItems( ## State Management Integration -The filtering system integrates with the state management: +The filtering system integrates with the state management through state transitions: ```typescript export class PackageManagerViewStateManager { - private items: PackageManagerItem[] = [] - private sortBy: "name" | "lastUpdated" = "name" - private sortOrder: "asc" | "desc" = "asc" - private filters: Filters = { type: "", search: "", tags: [] } + private state: ViewState + private stateChangeHandlers: Set /** - * Get filtered and sorted items + * Process state transitions */ - getFilteredAndSortedItems(): PackageManagerItem[] { - const filtered = filterItems(this.items, this.filters) - return sortItems(filtered, this.sortBy, this.sortOrder) + public async transition(transition: ViewStateTransition): Promise { + switch (transition.type) { + case "UPDATE_FILTERS": { + const { filters = {} } = transition.payload || {} + + // Update filters while preserving existing ones + const updatedFilters = { + type: filters.type ?? this.state.filters.type, + search: filters.search ?? this.state.filters.search, + tags: filters.tags ?? this.state.filters.tags, + } + + // Update state + this.state = { + ...this.state, + filters: updatedFilters, + } + + // Notify subscribers + this.notifyStateChange() + + // Request filtered items from backend + vscode.postMessage({ + type: "filterPackageManagerItems", + filters: updatedFilters, + }) + break + } + + case "FETCH_COMPLETE": { + const { items } = transition.payload as { items: PackageManagerItem[] } + + // Update both all items and display items + this.state = { + ...this.state, + allItems: items, + displayItems: items, + isFetching: false, + } + + this.notifyStateChange() + break + } + } } /** - * Update filters with optimistic updates + * Subscribe to state changes */ - setFilters(newFilters: Partial): void { - this.filters = { ...this.filters, ...newFilters } + public onStateChange(handler: StateChangeHandler): () => void { + this.stateChangeHandlers.add(handler) + return () => this.stateChangeHandlers.delete(handler) } } ``` +```` + ## Performance Optimizations ### Concurrent Operation Handling @@ -230,7 +272,7 @@ export class PackageManagerManager { } } } -``` +```` ### Filter Optimizations @@ -247,9 +289,12 @@ export class PackageManagerManager { - Avoids regex for simple matches 3. **State Management**: - - Optimistic updates - - Batched filter changes - - Efficient re-renders + - State transitions for predictable updates + - Subscriber pattern for state changes + - Separation of all items and display items + - Backend-driven filtering + - Optimistic UI updates + - Efficient state synchronization ## Testing Strategy @@ -294,9 +339,12 @@ The system includes robust error handling: - Type mismatches 3. **State Errors**: - - Concurrent updates - Invalid state transitions - - Cache inconsistencies + - Message handling errors + - State synchronization issues + - Timeout handling + - Source modification tracking + - Filter validation errors --- diff --git a/cline_docs/package-manager/implementation/05-ui-components.md b/cline_docs/package-manager/implementation/05-ui-components.md index 24f949cc23..c8343e1ace 100644 --- a/cline_docs/package-manager/implementation/05-ui-components.md +++ b/cline_docs/package-manager/implementation/05-ui-components.md @@ -2,6 +2,105 @@ This document details the design and implementation of the Package Manager's UI components, including their structure, styling, interactions, and accessibility features. +## PackageManagerView + +The PackageManagerView is the main container component that manages the overall package manager interface. + +### Component Structure + +```tsx +const PackageManagerView: React.FC = ({ onDone }) => { + const [state, manager] = useStateManager() + const [tagSearch, setTagSearch] = useState("") + const [isTagInputActive, setIsTagInputActive] = useState(false) + + // Fetch items on mount + useEffect(() => { + manager.transition({ type: "FETCH_ITEMS" }) + }, [manager]) + + return ( + + +
+

Package Manager

+
+ + +
+
+
+ + + {state.activeTab === "browse" ? ( + + manager.transition({ + type: "UPDATE_FILTERS", + payload: { filters }, + }) + } + /> + ) : ( + + manager.transition({ + type: "REFRESH_SOURCE", + payload: { url }, + }) + } + onSourcesChange={(sources) => + manager.transition({ + type: "UPDATE_SOURCES", + payload: { sources }, + }) + } + /> + )} + +
+ ) +} +``` + +### State Management Integration + +The component uses the PackageManagerViewStateManager through the useStateManager hook: + +```tsx +const [state, manager] = useStateManager() +``` + +Key features: + +- Manages tab state (browse/sources) +- Handles source configuration +- Coordinates filtering and sorting +- Manages loading states +- Handles source validation + ## PackageManagerItemCard The PackageManagerItemCard is the primary component for displaying package information in the UI. @@ -397,9 +496,103 @@ export const TypeGroup: React.FC = ({ type, items, className, se - Avoids rendering empty containers - Prevents unnecessary UI elements +## Source Configuration Components + +The Package Manager includes components for managing package sources. + +### SourcesView + +```tsx +const SourcesView: React.FC = ({ sources, refreshingUrls, onRefreshSource, onSourcesChange }) => { + const [newSourceUrl, setNewSourceUrl] = useState("") + const [newSourceName, setNewSourceName] = useState("") + const [error, setError] = useState("") + + const handleAddSource = () => { + // Validate source URL and name + const errors = [ + ...validateSourceUrl(newSourceUrl), + ...validateSourceName(newSourceName), + ...validateSourceDuplicates(sources, { + url: newSourceUrl, + name: newSourceName, + enabled: true, + }), + ] + + if (errors.length > 0) { + setError(errors[0].message) + return + } + + // Add new source + onSourcesChange([ + ...sources, + { + url: newSourceUrl, + name: newSourceName || undefined, + enabled: true, + }, + ]) + + // Clear form + setNewSourceUrl("") + setNewSourceName("") + setError("") + } + + return ( +
+

Configure Package Manager Sources

+

Add Git repositories containing package manager items.

+ + {/* Source form */} +
+ setNewSourceUrl(e.target.value)} + /> + setNewSourceName(e.target.value)} + /> + {error &&

{error}

} + +
+ + {/* Source list */} +
+ {sources.map((source) => ( + onRefreshSource(source.url)} + onToggle={() => { + const updatedSources = sources.map((s) => + s.url === source.url ? { ...s, enabled: !s.enabled } : s, + ) + onSourcesChange(updatedSources) + }} + onRemove={() => { + const updatedSources = sources.filter((s) => s.url !== source.url) + onSourcesChange(updatedSources) + }} + /> + ))} +
+
+ ) +} +``` + ## Filter Components -The Package Manager includes several components for filtering and searching. +The Package Manager includes components for filtering and searching. ### SearchInput diff --git a/cline_docs/package_manager/implementation/README.md b/cline_docs/package_manager/implementation/README.md new file mode 100644 index 0000000000..fa91e20754 --- /dev/null +++ b/cline_docs/package_manager/implementation/README.md @@ -0,0 +1,35 @@ +# Package Manager Implementation + +The package manager feature allows users to discover, browse, and manage Git-based package sources containing reusable components like modes, MCP servers, and prompts. + +## Core Components + +### Backend (VSCode Extension) + +- **PackageManagerManager**: Central service that manages package sources, fetching, and caching +- **GitFetcher**: Handles Git operations for cloning and updating repositories +- **MetadataScanner**: Scans repositories for component metadata +- **PackageManagerSourceValidation**: Validates package manager source URLs and configurations + +### Frontend (Webview UI) + +- **PackageManagerView**: React component for the package manager interface +- **PackageManagerViewStateManager**: Manages frontend state and synchronization with backend +- **useStateManager**: React hook for accessing the state manager + +## Key Features + +- Git repository integration (HTTPS, SSH, Git protocol) +- Component metadata scanning and validation +- Source configuration management +- Caching and concurrent operation handling +- Component filtering and sorting +- Real-time state synchronization between frontend and backend + +## Implementation Details + +See the following documentation for detailed implementation information: + +- [Architecture Overview](./architecture.md) +- [Class Diagram](./class-diagram.md) +- [Sequence Diagrams](./sequence-diagrams.md)