diff options
Diffstat (limited to 'extension')
| -rw-r--r-- | extension/package-lock.json | 4 | ||||
| -rw-r--r-- | extension/package.json | 2 | ||||
| -rw-r--r-- | extension/react-app/src/components/ComboBox.tsx | 1 | ||||
| -rw-r--r-- | extension/react-app/src/hooks/messenger.ts | 10 | ||||
| -rw-r--r-- | extension/react-app/src/pages/gui.tsx | 1 | ||||
| -rw-r--r-- | extension/src/activation/activate.ts | 2 | ||||
| -rw-r--r-- | extension/src/continueIdeClient.ts | 62 | ||||
| -rw-r--r-- | extension/src/debugPanel.ts | 113 | ||||
| -rw-r--r-- | extension/src/util/messenger.ts | 10 | 
9 files changed, 79 insertions, 126 deletions
| diff --git a/extension/package-lock.json b/extension/package-lock.json index 01e5bc1a..ea853fae 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -1,12 +1,12 @@  {    "name": "continue", -  "version": "0.0.156", +  "version": "0.0.157",    "lockfileVersion": 2,    "requires": true,    "packages": {      "": {        "name": "continue", -      "version": "0.0.156", +      "version": "0.0.157",        "license": "Apache-2.0",        "dependencies": {          "@electron/rebuild": "^3.2.10", diff --git a/extension/package.json b/extension/package.json index f3402abf..b3ff0b52 100644 --- a/extension/package.json +++ b/extension/package.json @@ -14,7 +14,7 @@    "displayName": "Continue",    "pricing": "Free",    "description": "The open-source coding autopilot", -  "version": "0.0.156", +  "version": "0.0.157",    "publisher": "Continue",    "engines": {      "vscode": "^1.67.0" diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx index ac994b0a..7d6541c7 100644 --- a/extension/react-app/src/components/ComboBox.tsx +++ b/extension/react-app/src/components/ComboBox.tsx @@ -331,7 +331,6 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {                ) {                  (event.nativeEvent as any).preventDownshiftDefault = true;                } else if (event.key === "ArrowUp") { -                console.log("OWJFOIJO");                  if (positionInHistory == 0) return;                  else if (                    positionInHistory == history.length && diff --git a/extension/react-app/src/hooks/messenger.ts b/extension/react-app/src/hooks/messenger.ts index e2a0bab8..00ce1fbb 100644 --- a/extension/react-app/src/hooks/messenger.ts +++ b/extension/react-app/src/hooks/messenger.ts @@ -1,6 +1,3 @@ -// console.log("Websocket import"); -// const WebSocket = require("ws"); -  export abstract class Messenger {    abstract send(messageType: string, data: object): void; @@ -28,13 +25,6 @@ export class WebsocketMessenger extends Messenger {    private serverUrl: string;    _newWebsocket(): WebSocket { -    // // Dynamic import, because WebSocket is builtin with browser, but not with node. And can't use require in browser. -    // if (typeof process === "object") { -    //   console.log("Using node"); -    //   // process is only available in Node -    //   var WebSocket = require("ws"); -    // } -      const newWebsocket = new WebSocket(this.serverUrl);      for (const listener of this.onOpenListeners) {        this.onOpen(listener); diff --git a/extension/react-app/src/pages/gui.tsx b/extension/react-app/src/pages/gui.tsx index b9382bd1..4ff260fa 100644 --- a/extension/react-app/src/pages/gui.tsx +++ b/extension/react-app/src/pages/gui.tsx @@ -262,7 +262,6 @@ function GUI(props: GUIProps) {    const onStepUserInput = (input: string, index: number) => {      if (!client) return; -    console.log("Sending step user input", input, index);      client.sendStepUserInput(input, index);    }; diff --git a/extension/src/activation/activate.ts b/extension/src/activation/activate.ts index 559caf44..cd885b12 100644 --- a/extension/src/activation/activate.ts +++ b/extension/src/activation/activate.ts @@ -56,7 +56,7 @@ export async function activateExtension(context: vscode.ExtensionContext) {    registerAllCodeLensProviders(context);    registerAllCommands(context); -  // Initialize IDE Protocol Client, then call "openGUI" +  // Initialize IDE Protocol Client    const serverUrl = getContinueServerUrl();    ideProtocolClient = new IdeProtocolClient(      `${serverUrl.replace("http", "ws")}/ide/ws`, diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts index b728833f..4c1fdf1e 100644 --- a/extension/src/continueIdeClient.ts +++ b/extension/src/continueIdeClient.ts @@ -1,10 +1,9 @@ -// import { ShowSuggestionRequest } from "../schema/ShowSuggestionRequest";  import {    editorSuggestionsLocked,    showSuggestion as showSuggestionInEditor,    SuggestionRanges,  } from "./suggestions"; -import { openEditorAndRevealRange, getRightViewColumn } from "./util/vscode"; +import { openEditorAndRevealRange } from "./util/vscode";  import { FileEdit } from "../schema/FileEdit";  import { RangeInFile } from "../schema/RangeInFile";  import * as vscode from "vscode"; @@ -15,8 +14,6 @@ import {  import { FileEditWithFullContents } from "../schema/FileEditWithFullContents";  import fs = require("fs");  import { WebsocketMessenger } from "./util/messenger"; -import * as path from "path"; -import * as os from "os";  import { diffManager } from "./diffs";  class IdeProtocolClient { @@ -27,17 +24,54 @@ class IdeProtocolClient {    private _highlightDebounce: NodeJS.Timeout | null = null; -  constructor(serverUrl: string, context: vscode.ExtensionContext) { -    this.context = context; +  private _lastReloadTime: number = 16; +  private _reconnectionTimeouts: NodeJS.Timeout[] = []; + +  private _sessionId: string | null = null; +  private _serverUrl: string; -    let messenger = new WebsocketMessenger(serverUrl); +  private _newWebsocketMessenger() { +    const requestUrl = +      this._serverUrl + +      (this._sessionId ? `?session_id=${this._sessionId}` : ""); +    const messenger = new WebsocketMessenger(requestUrl);      this.messenger = messenger; -    messenger.onClose(() => { + +    const reconnect = () => { +      console.log("Trying to reconnect IDE protocol websocket...");        this.messenger = null; + +      // Exponential backoff to reconnect +      this._reconnectionTimeouts.forEach((to) => clearTimeout(to)); + +      const timeout = setTimeout(() => { +        if (this.messenger?.websocket?.readyState === 1) { +          return; +        } +        this._newWebsocketMessenger(); +      }, this._lastReloadTime); + +      this._reconnectionTimeouts.push(timeout); +      this._lastReloadTime = Math.min(2 * this._lastReloadTime, 5000); +    }; +    messenger.onOpen(() => { +      this._reconnectionTimeouts.forEach((to) => clearTimeout(to)); +    }); +    messenger.onClose(() => { +      reconnect(); +    }); +    messenger.onError(() => { +      reconnect();      });      messenger.onMessage((messageType, data, messenger) => {        this.handleMessage(messageType, data, messenger);      }); +  } + +  constructor(serverUrl: string, context: vscode.ExtensionContext) { +    this.context = context; +    this._serverUrl = serverUrl; +    this._newWebsocketMessenger();      // Setup listeners for any file changes in open editors      // vscode.workspace.onDidChangeTextDocument((event) => { @@ -171,7 +205,7 @@ class IdeProtocolClient {        case "showDiff":          this.showDiff(data.filepath, data.replacement, data.step_index);          break; -      case "openGUI": +      case "getSessionId":        case "connected":          break;        default: @@ -284,10 +318,6 @@ class IdeProtocolClient {    // ------------------------------------ //    // Initiate Request -  async openGUI(asRightWebviewPanel: boolean = false) { -    // Open the webview panel -  } -    async getSessionId(): Promise<string> {      await new Promise((resolve, reject) => {        // Repeatedly try to connect to the server @@ -303,10 +333,10 @@ class IdeProtocolClient {          }        }, 1000);      }); -    const resp = await this.messenger?.sendAndReceive("openGUI", {}); -    const sessionId = resp.sessionId; +    const resp = await this.messenger?.sendAndReceive("getSessionId", {});      // console.log("New Continue session with ID: ", sessionId); -    return sessionId; +    this._sessionId = resp.sessionId; +    return resp.sessionId;    }    acceptRejectSuggestion(accept: boolean, key: SuggestionRanges) { diff --git a/extension/src/debugPanel.ts b/extension/src/debugPanel.ts index 487bbedf..5e1689d1 100644 --- a/extension/src/debugPanel.ts +++ b/extension/src/debugPanel.ts @@ -8,76 +8,6 @@ import {  import { RangeInFile } from "./client";  const WebSocket = require("ws"); -class StreamManager { -  private _fullText: string = ""; -  private _insertionPoint: vscode.Position | undefined; - -  private _addToEditor(update: string) { -    let editor = -      vscode.window.activeTextEditor || vscode.window.visibleTextEditors[0]; - -    if (typeof this._insertionPoint === "undefined") { -      if (editor?.selection.isEmpty) { -        this._insertionPoint = editor?.selection.active; -      } else { -        this._insertionPoint = editor?.selection.end; -      } -    } -    editor?.edit((editBuilder) => { -      if (this._insertionPoint) { -        editBuilder.insert(this._insertionPoint, update); -        this._insertionPoint = this._insertionPoint.translate( -          Array.from(update.matchAll(/\n/g)).length, -          update.length -        ); -      } -    }); -  } - -  public closeStream() { -    this._fullText = ""; -    this._insertionPoint = undefined; -    this._codeBlockStatus = "closed"; -    this._pendingBackticks = 0; -  } - -  private _codeBlockStatus: "open" | "closed" | "language-descriptor" = -    "closed"; -  private _pendingBackticks: number = 0; -  public onStreamUpdate(update: string) { -    let textToInsert = ""; -    for (let i = 0; i < update.length; i++) { -      switch (this._codeBlockStatus) { -        case "closed": -          if (update[i] === "`" && this._fullText.endsWith("``")) { -            this._codeBlockStatus = "language-descriptor"; -          } -          break; -        case "language-descriptor": -          if (update[i] === " " || update[i] === "\n") { -            this._codeBlockStatus = "open"; -          } -          break; -        case "open": -          if (update[i] === "`") { -            if (this._fullText.endsWith("``")) { -              this._codeBlockStatus = "closed"; -              this._pendingBackticks = 0; -            } else { -              this._pendingBackticks += 1; -            } -          } else { -            textToInsert += "`".repeat(this._pendingBackticks) + update[i]; -            this._pendingBackticks = 0; -          } -          break; -      } -      this._fullText += update[i]; -    } -    this._addToEditor(textToInsert); -  } -} -  let websocketConnections: { [url: string]: WebsocketConnection | undefined } =    {}; @@ -127,8 +57,6 @@ class WebsocketConnection {    }  } -let streamManager = new StreamManager(); -  export let debugPanelWebview: vscode.Webview | undefined;  export function setupDebugPanel(    panel: vscode.WebviewPanel | vscode.WebviewView, @@ -147,10 +75,7 @@ export function setupDebugPanel(      .toString();    const isProduction = true; // context?.extensionMode === vscode.ExtensionMode.Development; -  if (!isProduction) { -    scriptUri = "http://localhost:5173/src/main.tsx"; -    styleMainUri = "http://localhost:5173/src/main.css"; -  } else { +  if (isProduction) {      scriptUri = debugPanelWebview        .asWebviewUri(          vscode.Uri.joinPath(extensionUri, "react-app/dist/assets/index.js") @@ -161,6 +86,9 @@ export function setupDebugPanel(          vscode.Uri.joinPath(extensionUri, "react-app/dist/assets/index.css")        )        .toString(); +  } else { +    scriptUri = "http://localhost:5173/src/main.tsx"; +    styleMainUri = "http://localhost:5173/src/main.css";    }    panel.webview.options = { @@ -175,11 +103,11 @@ export function setupDebugPanel(        return;      } -    let rangeInFile: RangeInFile = { +    const rangeInFile: RangeInFile = {        range: e.selections[0],        filepath: e.textEditor.document.fileName,      }; -    let filesystem = { +    const filesystem = {        [rangeInFile.filepath]: e.textEditor.document.getText(),      };      panel.webview.postMessage({ @@ -217,13 +145,19 @@ export function setupDebugPanel(            url,          });        }; -      const connection = new WebsocketConnection( -        url, -        onMessage, -        onOpen, -        onClose -      ); -      websocketConnections[url] = connection; +      try { +        const connection = new WebsocketConnection( +          url, +          onMessage, +          onOpen, +          onClose +        ); +        websocketConnections[url] = connection; +        resolve(null); +      } catch (e) { +        console.log("Caught it!: ", e); +        reject(e); +      }      });    } @@ -292,15 +226,6 @@ export function setupDebugPanel(          openEditorAndRevealRange(data.path, undefined, vscode.ViewColumn.One);          break;        } -      case "streamUpdate": { -        // Write code at the position of the cursor -        streamManager.onStreamUpdate(data.update); -        break; -      } -      case "closeStream": { -        streamManager.closeStream(); -        break; -      }        case "withProgress": {          // This message allows withProgress to be used in the webview          if (data.done) { diff --git a/extension/src/util/messenger.ts b/extension/src/util/messenger.ts index b1df161b..7fd71ddd 100644 --- a/extension/src/util/messenger.ts +++ b/extension/src/util/messenger.ts @@ -15,6 +15,8 @@ export abstract class Messenger {    abstract onOpen(callback: () => void): void;    abstract onClose(callback: () => void): void; +   +  abstract onError(callback: () => void): void;    abstract sendAndReceive(messageType: string, data: any): Promise<any>;  } @@ -26,6 +28,7 @@ export class WebsocketMessenger extends Messenger {    } = {};    private onOpenListeners: (() => void)[] = [];    private onCloseListeners: (() => void)[] = []; +  private onErrorListeners: (() => void)[] = [];    private serverUrl: string;    _newWebsocket(): WebSocket { @@ -43,6 +46,9 @@ export class WebsocketMessenger extends Messenger {      for (const listener of this.onCloseListeners) {        this.onClose(listener);      } +    for (const listener of this.onErrorListeners) { +      this.onError(listener); +    }      for (const messageType in this.onMessageListeners) {        for (const listener of this.onMessageListeners[messageType]) {          this.onMessageType(messageType, listener); @@ -151,4 +157,8 @@ export class WebsocketMessenger extends Messenger {    onClose(callback: () => void): void {      this.websocket.addEventListener("close", callback);    } + +  onError(callback: () => void): void { +    this.websocket.addEventListener("error", callback); +  }  } | 
