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

feat(status): add model status in statusbar tooltips and commandPalette, also adding heartbeat #3894

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
30 changes: 27 additions & 3 deletions clients/tabby-agent/src/http/tabbyApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ export class TabbyApiClient extends EventEmitter {

private reconnectTimer: ReturnType<typeof setInterval> | undefined = undefined;

private heartbeatTimer: ReturnType<typeof setInterval> | undefined = undefined;

constructor(
private readonly configurations: Configurations,
private readonly anonymousUsageLogger: AnonymousUsageLogger,
Expand Down Expand Up @@ -88,12 +90,24 @@ export class TabbyApiClient extends EventEmitter {
await this.connect();
}
}, reconnectInterval);
setTimeout(() => {
const heartBeatInterval = 1000 * 60; // 1m
this.heartbeatTimer = setInterval(async () => {
if (this.status !== "noConnection" && this.status !== "unauthorized") {
this.logger.debug("Heartbeat...");
await this.healthCheck({ background: true });
}
}, heartBeatInterval);
}, 10000);
}

async shutdown() {
if (this.reconnectTimer) {
clearInterval(this.reconnectTimer);
}
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer);
}
}

private reset() {
Expand Down Expand Up @@ -253,8 +267,18 @@ export class TabbyApiClient extends EventEmitter {
}
}

private async healthCheck(signal?: AbortSignal, method: "GET" | "POST" = "GET"): Promise<void> {
if (this.healthCheckMutexAbortController && !this.healthCheckMutexAbortController.signal.aborted) {
private async healthCheck(
options: { signal?: AbortSignal; method?: "GET" | "POST"; background?: boolean } = {
method: "GET",
background: false,
},
): Promise<void> {
const { signal, method, background } = options;
if (this.healthCheckMutexAbortController && !this.healthCheckMutexAbortController.signal.aborted && background) {
// if background check true, and there is a running check, ignore background check
if (background) {
return;
}
this.healthCheckMutexAbortController.abort(new MutexAbortError());
}
const abortController = new AbortController();
Expand Down Expand Up @@ -290,7 +314,7 @@ export class TabbyApiClient extends EventEmitter {
if (isCanceledError(error)) {
this.logger.debug(`Health check request canceled. [${requestId}]`);
} else if (error instanceof HttpError && error.status == 405 && method !== "POST") {
return await this.healthCheck(signal, "POST");
return await this.healthCheck({ signal, method: "POST" });
} else if (isUnauthorizedError(error)) {
this.serverHealth = undefined;
this.updateStatus("unauthorized");
Expand Down
20 changes: 14 additions & 6 deletions clients/vscode/src/StatusBarItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const iconLoading = "$(loading~spin)";
const iconDisconnected = "$(debug-disconnect)";
const iconUnauthorized = "$(key)";
const iconWarning = "$(warning)";
const iconCodeModelNotFound = "$(close)";
const colorNormal = new ThemeColor("statusBar.foreground");
const colorWarning = new ThemeColor("statusBarItem.warningForeground");
const backgroundColorNormal = new ThemeColor("statusBar.background");
Expand Down Expand Up @@ -51,6 +52,8 @@ export class StatusBarItem {
}
case LanguageClientState.Running: {
const statusInfo = this.client.status.current;
const codeModel = statusInfo?.serverHealth?.["model"];

switch (statusInfo?.status) {
case "connecting": {
this.setColorNormal();
Expand All @@ -71,16 +74,21 @@ export class StatusBarItem {
break;
}
case "ready":
case "readyForAutoTrigger": {
if (this.checkIfVSCodeInlineCompletionEnabled()) {
case "readyForAutoTrigger":
case "readyForManualTrigger": {
// TODO(Sma1lboy): implement this status in tabby-agent in the future when need to generalize to other IDEs
if (!codeModel) {
this.setColorNormal();
this.setIcon(iconCodeModelNotFound);
this.setTooltip(statusInfo?.tooltip);
break;
}
if (statusInfo.status == "readyForAutoTrigger" && this.checkIfVSCodeInlineCompletionEnabled()) {
this.setColorNormal();
this.setIcon(iconAutomatic);
this.setTooltip(statusInfo.tooltip);
}
break;
}
case "readyForManualTrigger": {
if (this.checkIfVSCodeInlineCompletionEnabled()) {
if (statusInfo.status == "readyForManualTrigger" && this.checkIfVSCodeInlineCompletionEnabled()) {
this.setColorNormal();
this.setIcon(iconManual);
this.setTooltip(statusInfo.tooltip);
Expand Down