Repository: aditya-8-88/Project-IDE
Pull request #78: #77 Connect VS Code Extension to WebSocket Server
Author: login: aditya-8-88
Created: 2025-03-31T05:43:45Z | Merged: 2025-03-31T05:44:32Z

## Summary by Sourcery

Implement WebSocket-based collaboration connection for the VS Code extension, adding connection and disconnection functionality with a user-friendly webview interface

New Features:
- Add WebSocket-based collaboration client to connect to a collaboration server
- Create a webview with connect and disconnect buttons for managing collaboration sessions
- Implement automatic reconnection mechanism for WebSocket connections

Enhancements:
- Improve extension activation with more robust error handling
- Add status bar item for easy access to collaboration features
- Create a dynamic webview that updates its status based on connection state

Chores:
- Update package dependencies to include WebSocket library
- Refactor extension activation and deactivation logic


Diff:
diff --git a/Frontend/extension/package-lock.json b/Frontend/extension/package-lock.json
index ed372f1..ab5ef20 100644
--- a/Frontend/extension/package-lock.json
+++ b/Frontend/extension/package-lock.json
@@ -7,10 +7,14 @@
     "": {
       "name": "extension",
       "version": "0.0.1",
+      "dependencies": {
+        "ws": "^8.18.1"
+      },
       "devDependencies": {
         "@types/mocha": "^10.0.10",
         "@types/node": "20.x",
         "@types/vscode": "^1.98.0",
+        "@types/ws": "^8.18.0",
         "@typescript-eslint/eslint-plugin": "^8.25.0",
         "@typescript-eslint/parser": "^8.25.0",
         "@vscode/test-cli": "^0.0.10",
@@ -384,6 +388,15 @@
       "integrity": "sha512-+KuiWhpbKBaG2egF+51KjbGWatTH5BbmWQjSLMDCssb4xF8FJnW4nGH4nuAdOOfMbpD0QlHtI+C3tPq+DoKElg==",
       "dev": true
     },
+    "node_modules/@types/ws": {
+      "version": "8.18.0",
+      "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.0.tgz",
+      "integrity": "sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw==",
+      "dev": true,
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
     "node_modules/@typescript-eslint/eslint-plugin": {
       "version": "8.28.0",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.28.0.tgz",
@@ -3120,6 +3133,26 @@
       "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
       "dev": true
     },
+    "node_modules/ws": {
+      "version": "8.18.1",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
+      "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==",
+      "engines": {
+        "node": ">=10.0.0"
+      },
+      "peerDependencies": {
+        "bufferutil": "^4.0.1",
+        "utf-8-validate": ">=5.0.2"
+      },
+      "peerDependenciesMeta": {
+        "bufferutil": {
+          "optional": true
+        },
+        "utf-8-validate": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/y18n": {
       "version": "5.0.8",
       "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
diff --git a/Frontend/extension/package.json b/Frontend/extension/package.json
index 0184fd8..d9e8704 100644
--- a/Frontend/extension/package.json
+++ b/Frontend/extension/package.json
@@ -11,7 +11,6 @@
   ],
   "activationEvents": [],
   "main": "./out/extension.js",
-  
   "contributes": {
     "viewsContainers": {
       "activitybar": [
@@ -38,10 +37,14 @@
         "command": "project-ide.startSession",
         "title": "Start Collaboration Session",
         "category": "Project IDE"
+      },
+      {
+        "command": "project-ide.connect",
+        "title": "Connect to Collaboration Server",
+        "category": "Project IDE"
       }
     ]
   },
-
   "scripts": {
     "vscode:prepublish": "npm run compile",
     "compile": "tsc -p ./",
@@ -51,14 +54,18 @@
     "test": "vscode-test"
   },
   "devDependencies": {
-    "@types/vscode": "^1.98.0",
     "@types/mocha": "^10.0.10",
     "@types/node": "20.x",
+    "@types/vscode": "^1.98.0",
+    "@types/ws": "^8.18.0",
     "@typescript-eslint/eslint-plugin": "^8.25.0",
     "@typescript-eslint/parser": "^8.25.0",
-    "eslint": "^9.21.0",
-    "typescript": "^5.7.3",
     "@vscode/test-cli": "^0.0.10",
-    "@vscode/test-electron": "^2.4.1"
+    "@vscode/test-electron": "^2.4.1",
+    "eslint": "^9.21.0",
+    "typescript": "^5.7.3"
+  },
+  "dependencies": {
+    "ws": "^8.18.1"
   }
-}
\ No newline at end of file
+}
diff --git a/Frontend/extension/src/extension.ts b/Frontend/extension/src/extension.ts
index ab46712..5e434ca 100644
--- a/Frontend/extension/src/extension.ts
+++ b/Frontend/extension/src/extension.ts
@@ -1,15 +1,18 @@
 import * as vscode from 'vscode';
+import { CollaborationClient } from './websocket';
 
+// This class provides the webview view for collaboration
 class CollaborationViewProvider implements vscode.WebviewViewProvider {
     public static readonly viewType = 'project-ide.collaborationView';
     private _view?: vscode.WebviewView;
 
-    constructor(private readonly _extensionUri: vscode.Uri) {}
+    constructor(private readonly _extensionUri: vscode.Uri) { }
 
+    // Called when the view is created
     public resolveWebviewView(
         webviewView: vscode.WebviewView,
         context: vscode.WebviewViewResolveContext,
-        _token: vscode.CancellationToken,
+        _token: vscode.CancellationToken
     ) {
         this._view = webviewView;
         webviewView.webview.options = {
@@ -17,75 +20,117 @@ class CollaborationViewProvider implements vscode.WebviewViewProvider {
             localResourceRoots: [this._extensionUri]
         };
 
+        // Set the HTML content for the webview
         webviewView.webview.html = this._getHtmlContent();
 
         // Handle messages from the webview
-        const messageListener = webviewView.webview.onDidReceiveMessage(
-            message => {
-                console.log('Received message:', message);
+        const messageListener = webviewView.webview.onDidReceiveMessage((message) => {
+            switch (message.type) {
+                case 'CONNECT':
+                    vscode.commands.executeCommand('project-ide.connect');
+                    break;
+                case 'DISCONNECT':
+                    if (collaborationClient) {
+                        collaborationClient.disconnect();
+                        vscode.commands.executeCommand('project-ide.disconnect');
+                    }
+                    break;
+                default:
+                    console.log('Received unknown message:', message);
             }
-        );
+        });
 
-        // Ensure the listener is disposed when the webview is destroyed
+        // Dispose of the listener when the webview is disposed
         webviewView.onDidDispose(() => messageListener.dispose());
     }
 
-    private _getHtmlContent() {
+    // Called to update the webview status
+    public updateStatus(status: string, isError: boolean = false) {
+        if (this._view) {
+            this._view.webview.html = this._getHtmlContent(status, isError);
+        }
+    }
+
+    // Generates the HTML content for the webview
+    private _getHtmlContent(status: string = 'Ready to collaborate ✨', isError: boolean = false): string {
         return `
-            <!DOCTYPE html>
-            <html>
-                <head>
-                    <meta charset="UTF-8">
-                    <style>
-                        body {
-                            padding: 10px;
-                            color: var(--vscode-foreground);
-                            font-family: var(--vscode-font-family);
-                        }
-                        .status {
-                            font-size: 1.2em;
-                            margin-bottom: 20px;
-                        }
-                        .error {
-                            color: var(--vscode-errorForeground);
-                        }
-                    </style>
-                </head>
-                <body>
-                    <div class="status">Collaboration Started ✨</div>
-                </body>
-            </html>
+        <!DOCTYPE html>
+        <html>
+        <head>
+            <meta charset="UTF-8">
+            <style>
+                body {
+                    padding: 10px;
+                    color: var(--vscode-foreground);
+                    font-family: var(--vscode-font-family);
+                }
+                .status {
+                    font-size: 1.2em;
+                    margin-bottom: 20px;
+                }
+                .error {
+                    color: var(--vscode-errorForeground);
+                }
+                .button {
+                    background: var(--vscode-button-background);
+                    color: var(--vscode-button-foreground);
+                    border: none;
+                    padding: 8px 12px;
+                    cursor: pointer;
+                    margin: 5px;
+                }
+                .button:hover {
+                    background: var(--vscode-button-hoverBackground);
+                }
+            </style>
+        </head>
+        <body>
+            <div class="status ${isError ? 'error' : ''}">${status}</div>
+            <button class="button" onclick="connect()">Connect</button>
+            <button class="button" onclick="disconnect()">Disconnect</button>
+            <script>
+                const vscode = acquireVsCodeApi();
+                
+                function connect() {
+                    vscode.postMessage({ type: 'CONNECT' });
+                }
+                
+                function disconnect() {
+                    vscode.postMessage({ type: 'DISCONNECT' });
+                }
+            </script>
+        </body>
+        </html>
         `;
     }
 
+    // Called when the view is disposed
     public dispose() {
-		this._view = undefined;
+        this._view = undefined;
     }
 }
 
-// Track active sessions and resources
+// Global variables to track active sessions and resources
 let activeProvider: CollaborationViewProvider | undefined;
 let activeDisposables: vscode.Disposable[] = [];
+let collaborationClient: CollaborationClient | undefined;
 
 export async function activate(context: vscode.ExtensionContext) {
-    console.log('Project IDE extension is now active');
-
     try {
         // Create and register the webview provider
         activeProvider = new CollaborationViewProvider(context.extensionUri);
-        
-        // Register core functionality
-        activeDisposables.push(
-            vscode.window.registerWebviewViewProvider(
-                CollaborationViewProvider.viewType,
-                activeProvider
-            ),
 
-            // Register the start session command
+        activeDisposables.push(
+            // Register the webview view provider
+            vscode.window.registerWebviewViewProvider(CollaborationViewProvider.viewType, activeProvider),
+            // Register the command to start a collaboration session
             vscode.commands.registerCommand('project-ide.startSession', async () => {
                 try {
                     await vscode.commands.executeCommand('project-ide.collaborationView.focus');
-                    vscode.window.showInformationMessage('Collaboration session started!');
+                    if (activeProvider) {
+                        activeProvider.updateStatus('Click on Connect to start collaboration');
+                        vscode.window.showInformationMessage('Extension Activated');
+                    }
                 } catch (error) {
                     console.error('Failed to start collaboration session:', error);
                     vscode.window.showErrorMessage('Failed to start collaboration session');
@@ -93,37 +138,93 @@ export async function activate(context: vscode.ExtensionContext) {
             })
         );
 
-        // Register status bar item
-        const statusBarItem = vscode.window.createStatusBarItem(
-            vscode.StatusBarAlignment.Right,
-            100
-        );
+        // Register status bar item for easy access
+        const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 0);
         statusBarItem.text = "$(person-add) Collaborate";
         statusBarItem.command = 'project-ide.startSession';
         statusBarItem.show();
         activeDisposables.push(statusBarItem);
 
-        // Add all disposables to extension context
+        // Add all disposables to the extension context
         context.subscriptions.push(...activeDisposables);
 
+        // Register the connect command
+        context.subscriptions.push(
+            vscode.commands.registerCommand('project-ide.connect', async () => {
+                const { workspaceFolders } = vscode.workspace;
+                if (!workspaceFolders) {
+                    vscode.window.showErrorMessage('Please open a workspace first');
+                    return;
+                }
+
+                const serverUrl = await vscode.window.showInputBox({
+                    prompt: 'Enter collaboration server URL',
+                    placeHolder: 'ws://localhost:3000'
+                });
+
+                if (!serverUrl) {
+                    return;
+                }
+
+                try {
+                    if (activeProvider) {
+                        activeProvider.updateStatus('Connecting to server...');
+                    }
+
+                    // Initialize the collaboration client with the workspace folder
+                    collaborationClient = new CollaborationClient();
+                    await collaborationClient.connect(serverUrl);
+
+                    if (activeProvider) {
+                        activeProvider.updateStatus('Connected and ready to collaborate ✨');
+                    }
+                } catch (error) {
+                    const errorMessage = error instanceof Error ? error.message : 'Unknown error';
+                    if (activeProvider) {
+                        activeProvider.updateStatus(`Connection failed: ${errorMessage}`, true);
+                    }
+                    vscode.window.showErrorMessage('Failed to connect: ' + errorMessage);
+                }
+            })
+        );
+
+        // Register the disconnect command (optional if using webview button only)
+        context.subscriptions.push(
+            vscode.commands.registerCommand('project-ide.disconnect', () => {
+                if (collaborationClient) {
+                    collaborationClient.disconnect();
+                    if (activeProvider) {
+                        activeProvider.updateStatus('Disconnected from server');
+                    }
+                    vscode.window.showInformationMessage('Disconnected from collaboration server');
+                }
+                else{
+                    vscode.window.showWarningMessage('No active connection to disconnect');
+                }
+            })
+        );
+
     } catch (error) {
         console.error('Error during activation:', error);
-        throw error; // Re-throw to show activation failure in VS Code
+        throw error;
     }
 }
 
 export function deactivate() {
     console.log('Project IDE extension is being deactivated');
+
+    if (collaborationClient) {
+        collaborationClient.disconnect();
+        vscode.window.showInformationMessage('Extension Deactivated');
+    }
     
     try {
-        // Clean up provider
         if (activeProvider) {
             activeProvider.dispose();
             activeProvider = undefined;
         }
 
-        // Dispose all registered commands and views
-        activeDisposables.forEach(disposable => {
+        activeDisposables.forEach((disposable) => {
             try {
                 disposable.dispose();
             } catch (error) {
@@ -131,9 +232,8 @@ export function deactivate() {
             }
         });
         activeDisposables = [];
-
     } catch (error) {
         console.error('Error during deactivation:', error);
-        throw error; // Re-throw to show deactivation failure in VS Code
+        throw error;
     }
-}
\ No newline at end of file
+}
diff --git a/Frontend/extension/src/websocket.ts b/Frontend/extension/src/websocket.ts
new file mode 100644
index 0000000..ccafa0a
--- /dev/null
+++ b/Frontend/extension/src/websocket.ts
@@ -0,0 +1,68 @@
+import * as vscode from 'vscode';
+import WebSocket from 'ws';
+
+export class CollaborationClient {
+    private ws: WebSocket | undefined;
+    private reconnectAttempts = 0;
+    private readonly MAX_RECONNECT_ATTEMPTS = 3;
+    private shouldReconnect: boolean = true;
+
+    async connect(serverUrl: string): Promise<void> {
+        this.shouldReconnect = true; // Enable auto-reconnect when connecting
+        return new Promise((resolve, reject) => {
+            try {
+                this.ws = new WebSocket(serverUrl);
+
+                this.ws.addEventListener('open', () => {
+                    this.reconnectAttempts = 0;
+                    vscode.window.showInformationMessage('Connected to collaboration server');
+                    resolve();
+                });
+
+                this.ws.addEventListener('error', (event) => {
+                    const error = new Error('WebSocket error occurred');
+                    vscode.window.showErrorMessage('WebSocket error: ' + error.message);
+                    reject(error);
+                });
+
+                this.ws.addEventListener('close', async () => {
+                    vscode.window.showWarningMessage('Disconnected from collaboration server');
+                    
+                    // Reconnect if the disconnect was not user-initiated
+                    if (this.shouldReconnect && this.reconnectAttempts < this.MAX_RECONNECT_ATTEMPTS) {
+                        this.reconnectAttempts++;
+                        vscode.window.showInformationMessage(`Attempting to reconnect (${this.reconnectAttempts}/${this.MAX_RECONNECT_ATTEMPTS})...`);
+                        try {
+                            await this.connect(serverUrl);
+                        } catch (error) {
+                            console.error('Reconnection failed:', error);
+                        }
+                    }
+                });
+            } catch (error) {
+                console.error('Connection error:', error);
+                reject(error);
+            }
+        });
+    }
+
+    disconnect(): void {
+        // Set flag to prevent auto-reconnect on explicit disconnect
+        this.shouldReconnect = false;
+        if (this.ws) {
+            try {
+                this.ws.close();
+            } catch (error) {
+                console.error('Error closing WebSocket:', error);
+            } finally {
+                this.ws = undefined;
+                this.reconnectAttempts = 0;
+            }
+        }
+        vscode.window.showInformationMessage('Disconnected from collaboration server');
+    }
+
+    isConnected(): boolean {
+        return this.ws?.readyState === WebSocket.OPEN;
+    }
+}


Reviews:
user: login: sourcery-ai[bot]
body: Hey @aditya-8-88 - I've reviewed your changes - here's some feedback:

**Overall Comments**:
- Consider extracting the HTML content generation into a separate file for better organization.
- The `CollaborationClient` class could benefit from more robust error handling and logging.

<details>
<summary>Here's what I looked at during the review</summary>

- 🟡 **General issues**: 1 issue found
- 🟢 **Security**: all looks good
- 🟢 **Testing**: all looks good
- 🟡 **Complexity**: 1 issue found
- 🟢 **Documentation**: all looks good
</details>

***

<details>
<summary>Sourcery is free for open source - if you like our reviews please consider sharing them ✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
</sub>
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T05:44:35Z
user: login: aditya-8-88
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-31T05:59:57Z

Review comments:
diff_hunk: @@ -0,0 +1,68 @@
+import * as vscode from 'vscode';
+import WebSocket from 'ws';
+
+export class CollaborationClient {
+    private ws: WebSocket | undefined;
+    private reconnectAttempts = 0;
+    private readonly MAX_RECONNECT_ATTEMPTS = 3;
+    private shouldReconnect: boolean = true;
+
+    async connect(serverUrl: string): Promise<void> {
+        this.shouldReconnect = true; // Enable auto-reconnect when connecting
+        return new Promise((resolve, reject) => {
+            try {
+                this.ws = new WebSocket(serverUrl);
+
+                this.ws.addEventListener('open', () => {
+                    this.reconnectAttempts = 0;
+                    vscode.window.showInformationMessage('Connected to collaboration server');
+                    resolve();
+                });
+
+                this.ws.addEventListener('error', (event) => {
+                    const error = new Error('WebSocket error occurred');
+                    vscode.window.showErrorMessage('WebSocket error: ' + error.message);
+                    reject(error);
+                });
+
+                this.ws.addEventListener('close', async () => {
+                    vscode.window.showWarningMessage('Disconnected from collaboration server');
path: Frontend/extension/src/websocket.ts
user: login: sourcery-ai[bot]
body: **suggestion (performance):** Consider adding a delay before reconnecting in the close event handler.

Introducing a short delay or an exponential backoff before reattempting connection could help prevent rapid, consecutive retries when the server is unstable.

```suggestion
                this.ws.addEventListener('close', async () => {
                    vscode.window.showWarningMessage('Disconnected from collaboration server');
                    // Adding a delay of 2 seconds before attempting to reconnect
                    await new Promise(resolve => setTimeout(resolve, 2000));
```
created_at: 2025-03-31T05:44:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,68 @@
+import * as vscode from 'vscode';
+import WebSocket from 'ws';
+
+export class CollaborationClient {
+    private ws: WebSocket | undefined;
+    private reconnectAttempts = 0;
+    private readonly MAX_RECONNECT_ATTEMPTS = 3;
+    private shouldReconnect: boolean = true;
+
+    async connect(serverUrl: string): Promise<void> {
+        this.shouldReconnect = true; // Enable auto-reconnect when connecting
+        return new Promise((resolve, reject) => {
+            try {
+                this.ws = new WebSocket(serverUrl);
+
+                this.ws.addEventListener('open', () => {
path: Frontend/extension/src/websocket.ts
user: login: sourcery-ai[bot]
body: **issue (complexity):** Consider extracting WebSocket event handlers into dedicated methods to improve readability and reduce nesting complexity within the connect method, which will clarify responsibilities for WebSocket lifecycle, reconnection logic, and UI notifications while preserving functionality .

**Actionable Comment:**

Consider separating the reconnection logic and UI notifications from the low-level WebSocket event handling to reduce the nesting and improve readability. For example, extract event handlers into dedicated methods and consolidate reconnection attempts in one place:

```ts
private setupWebSocket(serverUrl: string): void {
    this.ws = new WebSocket(serverUrl);
    this.ws.addEventListener('open', this.handleOpen.bind(this));
    this.ws.addEventListener('error', this.handleError.bind(this));
    this.ws.addEventListener('close', () => this.handleClose(serverUrl));
}

private handleOpen(): void {
    this.reconnectAttempts = 0;
    vscode.window.showInformationMessage('Connected to collaboration server');
    // Resolve promise or notify connection success here
}

private handleError(): void {
    const error = new Error('WebSocket error occurred');
    vscode.window.showErrorMessage('WebSocket error: ' + error.message);
    // Reject promise or notify connection error here
}

private async handleClose(serverUrl: string): Promise<void> {
    vscode.window.showWarningMessage('Disconnected from collaboration server');
    if (this.shouldReconnect && this.reconnectAttempts < this.MAX_RECONNECT_ATTEMPTS) {
        this.reconnectAttempts++;
        vscode.window.showInformationMessage(`Attempting to reconnect (${this.reconnectAttempts}/${this.MAX_RECONNECT_ATTEMPTS})...`);
        try {
            // Attempt reconnection using the same setup method
            this.setupWebSocket(serverUrl);
        } catch (error) {
            console.error('Reconnection failed:', error);
        }
    }
}

// Updated connect method delegating setup:
async connect(serverUrl: string): Promise<void> {
    this.shouldReconnect = true;
    return new Promise((resolve, reject) => {
        try {
            this.setupWebSocket(serverUrl);
            // Implement logic to resolve/reject promise after handling open/error events
        } catch (error) {
            console.error('Connection error:', error);
            reject(error);
        }
    });
}
```

This refactoring clarifies each responsibility (WebSocket lifecycle, reconnection logic, and UI notifications) while preserving functionality.
created_at: 2025-03-31T05:44:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,68 @@
+import * as vscode from 'vscode';
+import WebSocket from 'ws';
+
+export class CollaborationClient {
+    private ws: WebSocket | undefined;
+    private reconnectAttempts = 0;
+    private readonly MAX_RECONNECT_ATTEMPTS = 3;
+    private shouldReconnect: boolean = true;
+
+    async connect(serverUrl: string): Promise<void> {
+        this.shouldReconnect = true; // Enable auto-reconnect when connecting
+        return new Promise((resolve, reject) => {
+            try {
+                this.ws = new WebSocket(serverUrl);
+
+                this.ws.addEventListener('open', () => {
+                    this.reconnectAttempts = 0;
+                    vscode.window.showInformationMessage('Connected to collaboration server');
+                    resolve();
+                });
+
+                this.ws.addEventListener('error', (event) => {
+                    const error = new Error('WebSocket error occurred');
+                    vscode.window.showErrorMessage('WebSocket error: ' + error.message);
+                    reject(error);
+                });
+
+                this.ws.addEventListener('close', async () => {
+                    vscode.window.showWarningMessage('Disconnected from collaboration server');
path: Frontend/extension/src/websocket.ts
user: login: aditya-8-88
body: Ya good one
created_at: 2025-03-31T05:59:57Z
author_association: OWNER

PR comments:
user: login: sourcery-ai[bot]
created_at: 2025-03-31T05:43:49Z
body: <!-- Generated by sourcery-ai[bot]: start review_guide -->

## Reviewer's Guide by Sourcery

This pull request introduces WebSocket functionality to the VS Code extension, enabling real-time collaboration features. It includes a `CollaborationClient` class for managing the WebSocket connection, along with corresponding UI elements and commands for connecting and disconnecting from a collaboration server. The extension now prompts the user for a server URL and provides status updates in the collaboration view.

#### Sequence diagram for connecting to the collaboration server

```mermaid
sequenceDiagram
  participant User
  participant VSCodeExtension as Extension
  participant CollaborationClient as Client
  participant WebSocketServer as Server

  User->>Extension: Execute 'Connect' command
  Extension->>User: Show input box for server URL
  User->>Extension: Enter server URL
  Extension->>Client: new CollaborationClient()
  Extension->>Client: connect(serverUrl)
  Client->>Server: new WebSocket(serverUrl)
  Server-->>Client: WebSocket connection established
  Client-->>Extension: Connection successful
  Extension->>User: Show information message 'Connected to collaboration server'
```

#### Sequence diagram for disconnecting from the collaboration server

```mermaid
sequenceDiagram
  participant User
  participant VSCodeExtension as Extension
  participant CollaborationClient as Client
  participant WebSocketServer as Server

  User->>Extension: Execute 'Disconnect' command
  Extension->>Client: disconnect()
  Client->>Server: ws.close()
  Server-->>Client: WebSocket connection closed
  Client-->>Extension: Disconnection successful
  Extension->>User: Show information message 'Disconnected from collaboration server'
```

#### Updated class diagram for CollaborationClient

```mermaid
classDiagram
  class CollaborationClient {
    -ws: WebSocket | undefined
    -reconnectAttempts: number
    -MAX_RECONNECT_ATTEMPTS: number
    -shouldReconnect: boolean
    +connect(serverUrl: string): Promise<void>
    +disconnect(): void
    +isConnected(): boolean
  }
```

### File-Level Changes

| Change | Details | Files |
| ------ | ------- | ----- |
| Introduces a WebSocket client for real-time collaboration, including connection, disconnection, and reconnection logic. | <ul><li>Added `ws` as a project dependency.</li><li>Created `CollaborationClient` class with `connect`, `disconnect`, and `isConnected` methods.</li><li>Implemented auto-reconnect logic with a limited number of attempts.</li><li>Added status messages to inform the user about the connection status.</li><li>Handled WebSocket errors and connection closing events.</li><li>Prevented auto-reconnect on explicit disconnect.</li></ul> | `Frontend/extension/package.json`<br/>`Frontend/extension/src/websocket.ts` |
| Updates the extension to integrate with the WebSocket client, providing connect and disconnect commands, and updating the collaboration view. | <ul><li>Added CONNECT and DISCONNECT message types to the webview.</li><li>Registered 'project-ide.connect' command to initiate WebSocket connection.</li><li>Registered 'project-ide.disconnect' command to terminate WebSocket connection.</li><li>Modified the collaboration view to include connect and disconnect buttons.</li><li>Updated the collaboration view to display connection status and error messages.</li><li>Added logic to update the webview status based on the WebSocket connection state.</li><li>Added a check for workspace folders before attempting to connect.</li><li>Added a prompt for the collaboration server URL.</li><li>Added logic to dispose of the WebSocket client on deactivation.</li></ul> | `Frontend/extension/src/extension.ts` |
| Updates the package.json file to include a new command for connecting to the collaboration server. | <ul><li>Added a new command 'project-ide.connect' to the contributes.commands section.</li><li>Added a title and category for the new command.</li></ul> | `Frontend/extension/package.json` |

---

<details>
<summary>Tips and commands</summary>

#### Interacting with Sourcery

- **Trigger a new review:** Comment `@sourcery-ai review` on the pull request.
- **Continue discussions:** Reply directly to Sourcery's review comments.
- **Generate a GitHub issue from a review comment:** Ask Sourcery to create an
  issue from a review comment by replying to it. You can also reply to a
  review comment with `@sourcery-ai issue` to create an issue from it.
- **Generate a pull request title:** Write `@sourcery-ai` anywhere in the pull
  request title to generate a title at any time. You can also comment
  `@sourcery-ai title` on the pull request to (re-)generate the title at any time.
- **Generate a pull request summary:** Write `@sourcery-ai summary` anywhere in
  the pull request body to generate a PR summary at any time exactly where you
  want it. You can also comment `@sourcery-ai summary` on the pull request to
  (re-)generate the summary at any time.
- **Generate reviewer's guide:** Comment `@sourcery-ai guide` on the pull
  request to (re-)generate the reviewer's guide at any time.
- **Resolve all Sourcery comments:** Comment `@sourcery-ai resolve` on the
  pull request to resolve all Sourcery comments. Useful if you've already
  addressed all the comments and don't want to see them anymore.
- **Dismiss all Sourcery reviews:** Comment `@sourcery-ai dismiss` on the pull
  request to dismiss all existing Sourcery reviews. Especially useful if you
  want to start fresh with a new review - don't forget to comment
  `@sourcery-ai review` to trigger a new review!
- **Generate a plan of action for an issue:** Comment `@sourcery-ai plan` on
  an issue to generate a plan of action for it.

#### Customizing Your Experience

Access your [dashboard](https://app.sourcery.ai) to:
- Enable or disable review features such as the Sourcery-generated pull request
  summary, the reviewer's guide, and others.
- Change the review language.
- Add, remove or edit custom review instructions.
- Adjust other review settings.

#### Getting Help

- [Contact our support team](mailto:support@sourcery.ai) for questions or feedback.
- Visit our [documentation](https://docs.sourcery.ai) for detailed guides and information.
- Keep in touch with the Sourcery team by following us on [X/Twitter](https://x.com/SourceryAI), [LinkedIn](https://www.linkedin.com/company/sourcery-ai/) or [GitHub](https://github.com/sourcery-ai).

</details>

<!-- Generated by sourcery-ai[bot]: end review_guide -->
author_association: CONTRIBUTOR
user: login: aditya-8-88
created_at: 2025-03-31T05:44:17Z
body: #77 completed
author_association: OWNER