From 05bbf7437730fa578ca45363e6bea8ca0cfc3876 Mon Sep 17 00:00:00 2001 From: Zhiming Ma Date: Fri, 22 Nov 2024 22:38:52 +0800 Subject: [PATCH 1/2] fix(agent): fix the status request with recheck connection option. --- .../tabby-agent/src/http/tabbyApiClient.ts | 34 +++++++++++++------ clients/tabby-agent/src/status.ts | 2 +- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/clients/tabby-agent/src/http/tabbyApiClient.ts b/clients/tabby-agent/src/http/tabbyApiClient.ts index 4c658d8ec90e..a0e13d8c674f 100644 --- a/clients/tabby-agent/src/http/tabbyApiClient.ts +++ b/clients/tabby-agent/src/http/tabbyApiClient.ts @@ -74,12 +74,7 @@ export class TabbyApiClient extends EventEmitter { ); if (isServerConnectionChanged) { this.logger.debug("Server configurations updated, reconnecting..."); - this.updateStatus("noConnection"); - this.updateCompletionResponseIssue(undefined); - this.connectionErrorMessage = undefined; - this.serverHealth = undefined; - this.completionRequestStats.reset(); - this.api = this.createApiClient(); + this.reset(); this.connect(); // no await } }); @@ -99,6 +94,15 @@ export class TabbyApiClient extends EventEmitter { } } + private reset() { + this.updateStatus("noConnection"); + this.updateCompletionResponseIssue(undefined); + this.connectionErrorMessage = undefined; + this.serverHealth = undefined; + this.completionRequestStats.reset(); + this.api = this.createApiClient(); + } + private buildUserAgentString(clientInfo: ClientInfo | undefined): string { const envInfo = isBrowser ? navigator?.userAgent : `Node.js/${process.version}`; const tabbyAgentInfo = `${agentName}/${agentVersion}`; @@ -154,6 +158,7 @@ export class TabbyApiClient extends EventEmitter { } } + // FIXME(icycodes): move fetchingCompletion status to completion provider private updateIsFetchingCompletion(isFetchingCompletion: boolean) { if (this.fetchingCompletion != isFetchingCompletion) { this.fetchingCompletion = isFetchingCompletion; @@ -223,7 +228,10 @@ export class TabbyApiClient extends EventEmitter { return !!(health && health["chat_model"]); } - async connect(): Promise { + async connect(options: { reset?: boolean } = {}): Promise { + if (options.reset) { + this.reset(); + } await this.healthCheck(); if (this.status === "ready") { await this.updateServerProvidedConfig(); @@ -235,7 +243,9 @@ export class TabbyApiClient extends EventEmitter { if (this.healthCheckMutexAbortController && !this.healthCheckMutexAbortController.signal.aborted) { this.healthCheckMutexAbortController.abort(new MutexAbortError()); } - this.healthCheckMutexAbortController = new AbortController(); + const abortController = new AbortController(); + this.healthCheckMutexAbortController = abortController; + this.updateIsConnecting(true); const requestId = uuid(); const requestPath = "/v1/health"; @@ -243,11 +253,10 @@ export class TabbyApiClient extends EventEmitter { const requestOptions = { signal: abortSignalFromAnyOf([ signal, - this.healthCheckMutexAbortController?.signal, + abortController.signal, this.createTimeOutAbortSignal(), ]), }; - this.updateIsConnecting(true); try { if (!this.api) { throw new Error("http client not initialized"); @@ -288,7 +297,10 @@ export class TabbyApiClient extends EventEmitter { this.updateStatus("noConnection"); } } - this.updateIsConnecting(false); + if (this.healthCheckMutexAbortController === abortController) { + this.healthCheckMutexAbortController = undefined; + this.updateIsConnecting(false); + } } private async updateServerProvidedConfig(): Promise { diff --git a/clients/tabby-agent/src/status.ts b/clients/tabby-agent/src/status.ts index 96712ca02bdb..135adf8cc4ec 100644 --- a/clients/tabby-agent/src/status.ts +++ b/clients/tabby-agent/src/status.ts @@ -40,7 +40,7 @@ export class StatusProvider extends EventEmitter implements Feature { connection.onRequest(StatusRequest.type, async (params) => { if (params?.recheckConnection) { - await this.tabbyApiClient.connect(); + await this.tabbyApiClient.connect({ reset: true }); } return this.getStatusInfo(); }); From 53ecfed48ccf4ac2dfca9af10e553d65873dba43 Mon Sep 17 00:00:00 2001 From: Zhiming Ma Date: Fri, 22 Nov 2024 22:49:08 +0800 Subject: [PATCH 2/2] fix(agent): return help message for status request. --- clients/tabby-agent/src/http/tabbyApiClient.ts | 6 +----- clients/tabby-agent/src/protocol.ts | 16 +++++++++++++++- clients/tabby-agent/src/status.ts | 17 ++++++++--------- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/clients/tabby-agent/src/http/tabbyApiClient.ts b/clients/tabby-agent/src/http/tabbyApiClient.ts index a0e13d8c674f..9ca8f044d4a4 100644 --- a/clients/tabby-agent/src/http/tabbyApiClient.ts +++ b/clients/tabby-agent/src/http/tabbyApiClient.ts @@ -251,11 +251,7 @@ export class TabbyApiClient extends EventEmitter { const requestPath = "/v1/health"; const requestDescription = `${method} ${this.endpoint + requestPath}`; const requestOptions = { - signal: abortSignalFromAnyOf([ - signal, - abortController.signal, - this.createTimeOutAbortSignal(), - ]), + signal: abortSignalFromAnyOf([signal, abortController.signal, this.createTimeOutAbortSignal()]), }; try { if (!this.api) { diff --git a/clients/tabby-agent/src/protocol.ts b/clients/tabby-agent/src/protocol.ts index 73dd9f044130..5c96c6b64eb2 100644 --- a/clients/tabby-agent/src/protocol.ts +++ b/clients/tabby-agent/src/protocol.ts @@ -482,7 +482,7 @@ export type ChatEditResolveParams = { }; /** - * [Tabby] Apply workspace edit request(↩️) + * [Tabby] Apply workspace edit request(↪️) * * This method is sent from the server to client to apply edit in workspace with options. * - method: `tabby/workspace/applyEdit` @@ -851,8 +851,22 @@ export type StatusInfo = { | "fetching" | "completionResponseSlow"; tooltip?: string; + /** + * The health information of the server if available. + */ serverHealth?: Record; + /** + * The action to take for this status. + * - `disconnected` or `completionResponseSlow` -> StatusShowHelpMessageCommand + * - others -> undefined + */ command?: StatusShowHelpMessageCommand | LspCommand; + /** + * The help message if available. + * Only available when this status info is returned from {@link StatusRequest}, not provided in {@link StatusDidChangeNotification}. + * Only available when the status is `disconnected` or `completionResponseSlow`. + */ + helpMessage?: string; }; /** diff --git a/clients/tabby-agent/src/status.ts b/clients/tabby-agent/src/status.ts index 135adf8cc4ec..2c41dc485a38 100644 --- a/clients/tabby-agent/src/status.ts +++ b/clients/tabby-agent/src/status.ts @@ -42,7 +42,7 @@ export class StatusProvider extends EventEmitter implements Feature { if (params?.recheckConnection) { await this.tabbyApiClient.connect({ reset: true }); } - return this.getStatusInfo(); + return this.buildStatusInfo({ includeHelpMessage: true }); }); connection.onRequest(StatusShowHelpMessageRequest.type, async () => { return this.showStatusHelpMessage(); @@ -83,20 +83,16 @@ export class StatusProvider extends EventEmitter implements Feature { async initialized(connection: Connection): Promise { if (this.clientCapabilities?.tabby?.statusDidChangeListener) { - const statusInfo = await this.getStatusInfo(); + const statusInfo = await this.buildStatusInfo(); connection.sendNotification(StatusDidChangeNotification.type, statusInfo); } } private async notify() { - const statusInfo = await this.getStatusInfo(); + const statusInfo = await this.buildStatusInfo(); this.emit("updated", statusInfo); } - getStatusInfo(): StatusInfo { - return this.buildStatusInfo(); - } - async showStatusHelpMessage(): Promise { let params: ShowMessageRequestParams; let issue: StatusIssuesName | undefined = undefined; @@ -186,7 +182,7 @@ export class StatusProvider extends EventEmitter implements Feature { return false; } - private buildStatusInfo(): StatusInfo { + private buildStatusInfo(options: { includeHelpMessage?: boolean } = {}): StatusInfo { let statusInfo: StatusInfo; const apiClientStatus = this.tabbyApiClient.getStatus(); switch (apiClientStatus) { @@ -221,13 +217,16 @@ export class StatusProvider extends EventEmitter implements Feature { } this.fillToolTip(statusInfo); statusInfo.serverHealth = this.tabbyApiClient.getServerHealth(); - statusInfo.command = this.tabbyApiClient.hasHelpMessage() + const hasHelpMessage = this.tabbyApiClient.hasHelpMessage(); + statusInfo.command = hasHelpMessage ? { title: "Detail", command: "tabby/status/showHelpMessage", arguments: [{}], } : undefined; + statusInfo.helpMessage = + hasHelpMessage && options.includeHelpMessage ? this.tabbyApiClient.getHelpMessage() : undefined; return statusInfo; }