Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(agent): fix the status request with recheck connection option. #3456

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 23 additions & 15 deletions clients/tabby-agent/src/http/tabbyApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
});
Expand All @@ -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}`;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -223,7 +228,10 @@ export class TabbyApiClient extends EventEmitter {
return !!(health && health["chat_model"]);
}

async connect(): Promise<void> {
async connect(options: { reset?: boolean } = {}): Promise<void> {
if (options.reset) {
this.reset();
}
await this.healthCheck();
if (this.status === "ready") {
await this.updateServerProvidedConfig();
Expand All @@ -235,19 +243,16 @@ 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";
const requestDescription = `${method} ${this.endpoint + requestPath}`;
const requestOptions = {
signal: abortSignalFromAnyOf([
signal,
this.healthCheckMutexAbortController?.signal,
this.createTimeOutAbortSignal(),
]),
signal: abortSignalFromAnyOf([signal, abortController.signal, this.createTimeOutAbortSignal()]),
};
this.updateIsConnecting(true);
try {
if (!this.api) {
throw new Error("http client not initialized");
Expand Down Expand Up @@ -288,7 +293,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<void> {
Expand Down
16 changes: 15 additions & 1 deletion clients/tabby-agent/src/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down Expand Up @@ -851,8 +851,22 @@ export type StatusInfo = {
| "fetching"
| "completionResponseSlow";
tooltip?: string;
/**
* The health information of the server if available.
*/
serverHealth?: Record<string, unknown>;
/**
* 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;
};

/**
Expand Down
19 changes: 9 additions & 10 deletions clients/tabby-agent/src/status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ 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();
return this.buildStatusInfo({ includeHelpMessage: true });
});
connection.onRequest(StatusShowHelpMessageRequest.type, async () => {
return this.showStatusHelpMessage();
Expand Down Expand Up @@ -83,20 +83,16 @@ export class StatusProvider extends EventEmitter implements Feature {

async initialized(connection: Connection): Promise<void> {
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<boolean | null> {
let params: ShowMessageRequestParams;
let issue: StatusIssuesName | undefined = undefined;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}

Expand Down
Loading