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(vscode): Add dont-show-again for warnings. Add online help links. #821

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
10 changes: 9 additions & 1 deletion clients/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@
{
"command": "tabby.gettingStarted",
"title": "Tabby: Getting Started"
},
{
"command": "tabby.openOnlineHelp",
"title": "Tabby: Online Help"
},
{
"command": "tabby.notifications.resetMuted",
"title": "Tabby: Reset notifications marked as \"Don't Show Again\""
}
],
"menus": {
Expand Down Expand Up @@ -147,7 +155,7 @@
"tabby.usage.anonymousUsageTracking": {
"type": "boolean",
"default": false,
"markdownDescription": "**Disable anonymous usage tracking** \nTabby collects aggregated anonymous usage data and sends it to the Tabby team to help improve our products. \nYour code, generated completions, or any identifying information is never tracked or transmitted. \nFor more details on data collection, please check our [online documentation](https://tabby.tabbyml.com/docs/extensions/configuration#usage-collection)."
"markdownDescription": "**Disable anonymous usage tracking** \nTabby collects aggregated anonymous usage data and sends it to the Tabby team to help improve our products. \nYour code, generated completions, or any identifying information is never tracked or transmitted. \nFor more details on data collection, please check our [online documentation](https://tabby.tabbyml.com/docs/extensions/configurations#usage-collection)."
}
}
},
Expand Down
10 changes: 1 addition & 9 deletions clients/vscode/src/TabbyCompletionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,12 @@ import { CompletionRequest, CompletionResponse, LogEventRequest } from "tabby-ag
import { agent } from "./agent";

export class TabbyCompletionProvider extends EventEmitter implements InlineCompletionItemProvider {
static instance: TabbyCompletionProvider;
static getInstance(): TabbyCompletionProvider {
if (!TabbyCompletionProvider.instance) {
TabbyCompletionProvider.instance = new TabbyCompletionProvider();
}
return TabbyCompletionProvider.instance;
}

private triggerMode: "automatic" | "manual" | "disabled" = "automatic";
private onGoingRequestAbortController: AbortController | null = null;
private loading: boolean = false;
private latestCompletions: CompletionResponse | null = null;

private constructor() {
public constructor() {
super();
this.updateConfiguration();
workspace.onDidChangeConfiguration((event) => {
Expand Down
38 changes: 31 additions & 7 deletions clients/vscode/src/TabbyStatusBarItem.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { StatusBarAlignment, ThemeColor, window } from "vscode";
import { StatusBarAlignment, ThemeColor, ExtensionContext, window } from "vscode";
import { createMachine, interpret } from "@xstate/fsm";
import type { StatusChangedEvent, AuthRequiredEvent, IssuesUpdatedEvent } from "tabby-agent";
import { agent } from "./agent";
Expand All @@ -20,13 +20,26 @@ const backgroundColorWarning = new ThemeColor("statusBarItem.warningBackground")

export class TabbyStatusBarItem {
private item = window.createStatusBarItem(StatusBarAlignment.Right);
private extensionContext: ExtensionContext;
private completionProvider: TabbyCompletionProvider;
private completionResponseWarningShown = false;

private subStatusForReady = [
{
target: "issuesExist",
cond: () => agent().getIssues().length > 0,
cond: () => {
let issues = agent().getIssues();
if (
this.extensionContext.globalState
.get<string[]>("notifications.muted", [])
.includes("completionResponseTimeIssues")
) {
issues = issues.filter(
(issue) => issue !== "highCompletionTimeoutRate" && issue !== "slowCompletionResponseTime",
);
}
return issues.length > 0;
},
},
{
target: "automatic",
Expand Down Expand Up @@ -126,18 +139,20 @@ export class TabbyStatusBarItem {

private fsmService = interpret(this.fsm);

constructor(completionProvider: TabbyCompletionProvider) {
constructor(context: ExtensionContext, completionProvider: TabbyCompletionProvider) {
this.extensionContext = context;
this.completionProvider = completionProvider;
this.fsmService.start();
this.fsmService.send(agent().getStatus());
this.item.show();

this.completionProvider.on("triggerModeUpdated", () => {
this.fsmService.send(agent().getStatus());
this.refresh();
});
this.completionProvider.on("loadingStatusUpdated", () => {
this.fsmService.send(agent().getStatus());
this.refresh();
});

agent().on("statusChanged", (event: StatusChangedEvent) => {
console.debug("Tabby agent statusChanged", { event });
this.fsmService.send(event.status);
Expand All @@ -158,12 +173,17 @@ export class TabbyStatusBarItem {
agent().on("issuesUpdated", (event: IssuesUpdatedEvent) => {
console.debug("Tabby agent issuesUpdated", { event });
this.fsmService.send(agent().getStatus());
const showCompletionResponseWarnings =
!this.completionResponseWarningShown &&
!this.extensionContext.globalState
.get<string[]>("notifications.muted", [])
.includes("completionResponseTimeIssues");
if (event.issues.includes("connectionFailed")) {
notifications.showInformationWhenDisconnected();
} else if (!this.completionResponseWarningShown && event.issues.includes("highCompletionTimeoutRate")) {
} else if (showCompletionResponseWarnings && event.issues.includes("highCompletionTimeoutRate")) {
this.completionResponseWarningShown = true;
notifications.showInformationWhenHighCompletionTimeoutRate();
} else if (!this.completionResponseWarningShown && event.issues.includes("slowCompletionResponseTime")) {
} else if (showCompletionResponseWarnings && event.issues.includes("slowCompletionResponseTime")) {
this.completionResponseWarningShown = true;
notifications.showInformationWhenSlowCompletionResponseTime();
}
Expand All @@ -174,6 +194,10 @@ export class TabbyStatusBarItem {
return this.item;
}

public refresh() {
this.fsmService.send(agent().getStatus());
}

private toInitializing() {
this.item.color = colorNormal;
this.item.backgroundColor = backgroundColorNormal;
Expand Down
124 changes: 110 additions & 14 deletions clients/vscode/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
InputBoxValidationSeverity,
ProgressLocation,
Uri,
ThemeIcon,
ExtensionContext,
workspace,
window,
env,
Expand All @@ -12,6 +14,7 @@ import { strict as assert } from "assert";
import { agent } from "./agent";
import { notifications } from "./notifications";
import { TabbyCompletionProvider } from "./TabbyCompletionProvider";
import { TabbyStatusBarItem } from "./TabbyStatusBarItem";

const configTarget = ConfigurationTarget.Global;

Expand Down Expand Up @@ -175,24 +178,114 @@ const acceptInlineCompletion: Command = {
},
};

const acceptInlineCompletionNextWord: Command = {
command: "tabby.inlineCompletion.acceptNextWord",
callback: () => {
TabbyCompletionProvider.getInstance().postEvent("accept_word");
commands.executeCommand("editor.action.inlineSuggest.acceptNextWord");
},
const acceptInlineCompletionNextWord = (completionProvider: TabbyCompletionProvider): Command => {
return {
command: "tabby.inlineCompletion.acceptNextWord",
callback: () => {
completionProvider.postEvent("accept_word");
commands.executeCommand("editor.action.inlineSuggest.acceptNextWord");
},
};
};

const acceptInlineCompletionNextLine: Command = {
command: "tabby.inlineCompletion.acceptNextLine",
const acceptInlineCompletionNextLine = (completionProvider: TabbyCompletionProvider): Command => {
return {
command: "tabby.inlineCompletion.acceptNextLine",
callback: () => {
completionProvider.postEvent("accept_line");
// FIXME: this command move cursor to next line, but we want to move cursor to the end of current line
commands.executeCommand("editor.action.inlineSuggest.acceptNextLine");
},
};
};

const openOnlineHelp: Command = {
command: "tabby.openOnlineHelp",
callback: () => {
TabbyCompletionProvider.getInstance().postEvent("accept_line");
// FIXME: this command move cursor to next line, but we want to move cursor to the end of current line
commands.executeCommand("editor.action.inlineSuggest.acceptNextLine");
window
.showQuickPick([
{
label: "Online Documentation",
iconPath: new ThemeIcon("book"),
alwaysShow: true,
},
{
label: "Model Registry",
description: "Explore more recommend models from Tabby's model registry",
iconPath: new ThemeIcon("library"),
alwaysShow: true,
},
{
label: "Tabby Slack Community",
description: "Join Tabby's Slack community to get help or feed back",
iconPath: new ThemeIcon("comment-discussion"),
alwaysShow: true,
},
{
label: "Tabby GitHub Repository",
description: "View the source code for Tabby, and open issues",
iconPath: new ThemeIcon("github"),
alwaysShow: true,
},
])
.then((selection) => {
if (selection) {
switch (selection.label) {
case "Online Documentation":
env.openExternal(Uri.parse("https://tabby.tabbyml.com/"));
break;
case "Model Registry":
env.openExternal(Uri.parse("https://tabby.tabbyml.com/docs/models/"));
break;
case "Tabby Slack Community":
env.openExternal(
Uri.parse("https://join.slack.com/t/tabbycommunity/shared_invite/zt-1xeiddizp-bciR2RtFTaJ37RBxr8VxpA"),
);
break;
case "Tabby GitHub Repository":
env.openExternal(Uri.parse("https://github.com/tabbyml/tabby"));
break;
}
}
});
},
};

export const tabbyCommands = () =>
const muteNotifications = (context: ExtensionContext, statusBarItem: TabbyStatusBarItem): Command => {
return {
command: "tabby.notifications.mute",
callback: (type: string) => {
const notifications = context.globalState.get<string[]>("notifications.muted", []);
notifications.push(type);
context.globalState.update("notifications.muted", notifications);
statusBarItem.refresh();
},
};
};

const resetMutedNotifications = (context: ExtensionContext, statusBarItem: TabbyStatusBarItem): Command => {
return {
command: "tabby.notifications.resetMuted",
callback: (type?: string) => {
const notifications = context.globalState.get<string[]>("notifications.muted", []);
if (type) {
context.globalState.update(
"notifications.muted",
notifications.filter((t) => t !== type),
);
} else {
context.globalState.update("notifications.muted", []);
}
statusBarItem.refresh();
},
};
};

export const tabbyCommands = (
context: ExtensionContext,
completionProvider: TabbyCompletionProvider,
statusBarItem: TabbyStatusBarItem,
) =>
[
toggleInlineCompletionTriggerMode,
setApiEndpoint,
Expand All @@ -204,6 +297,9 @@ export const tabbyCommands = () =>
applyCallback,
triggerInlineCompletion,
acceptInlineCompletion,
acceptInlineCompletionNextWord,
acceptInlineCompletionNextLine,
acceptInlineCompletionNextWord(completionProvider),
acceptInlineCompletionNextLine(completionProvider),
openOnlineHelp,
muteNotifications(context, statusBarItem),
resetMutedNotifications(context, statusBarItem),
].map((command) => commands.registerCommand(command.command, command.callback, command.thisArg));
6 changes: 3 additions & 3 deletions clients/vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import { TabbyStatusBarItem } from "./TabbyStatusBarItem";
export async function activate(context: ExtensionContext) {
console.debug("Activating Tabby extension", new Date());
await createAgentInstance(context);
const completionProvider = TabbyCompletionProvider.getInstance();
const statusBarItem = new TabbyStatusBarItem(completionProvider);
const completionProvider = new TabbyCompletionProvider();
const statusBarItem = new TabbyStatusBarItem(context, completionProvider);
context.subscriptions.push(
languages.registerInlineCompletionItemProvider({ pattern: "**" }, completionProvider),
statusBarItem.register(),
...tabbyCommands(),
...tabbyCommands(context, completionProvider, statusBarItem),
);
}

Expand Down
Loading