Skip to content

Commit

Permalink
feat(vscode): check server info for chat panel. (#2259)
Browse files Browse the repository at this point in the history
* feat(vscode): check server info for chat panel.

* fix(vscode): add types for semver.

* fix(vscode): add types for deep-equal.

* Apply suggestions from code review

Co-authored-by: Meng Zhang <meng@tabbyml.com>

---------

Co-authored-by: Meng Zhang <meng@tabbyml.com>
  • Loading branch information
icycodes and wsxiaoys authored May 28, 2024
1 parent 2afde5a commit 750d362
Showing 8 changed files with 224 additions and 210 deletions.
120 changes: 67 additions & 53 deletions clients/tabby-agent/src/lsp/Server.ts
Original file line number Diff line number Diff line change
@@ -32,17 +32,14 @@ import {
ServerCapabilities,
DidChangeConfigurationParams,
ClientProvidedConfig,
AgentServerConfigRequest,
AgentServerConfigSync,
DidChangeServerConfigParams,
ServerConfig,
AgentServerInfoRequest,
AgentServerInfoSync,
ServerInfo,
AgentStatusRequest,
AgentStatusSync,
DidChangeStatusParams,
Status,
AgentIssuesRequest,
AgentIssuesSync,
DidUpdateIssueParams,
IssueList,
AgentIssueDetailRequest,
IssueDetailParams,
@@ -112,10 +109,9 @@ export class Server {
private clientInfo?: ClientInfo | undefined | null;
private clientCapabilities?: ClientCapabilities | undefined | null;
private clientProvidedConfig?: ClientProvidedConfig | undefined | null;
private serverConfig: ServerConfig;
private serverInfo?: ServerInfo | undefined | null;

constructor(private readonly agent: Agent) {
this.serverConfig = agent.getConfig().server;
// Lifecycle
this.connection.onInitialize(async (params) => {
return this.initialize(params);
@@ -133,8 +129,8 @@ export class Server {
return this.exit();
});
// Agent
this.connection.onRequest(AgentServerConfigRequest.type, async () => {
return this.getServerConfig();
this.connection.onRequest(AgentServerInfoRequest.type, async () => {
return this.getServerInfo();
});
this.connection.onRequest(AgentStatusRequest.type, async () => {
return this.getStatus();
@@ -247,49 +243,67 @@ export class Server {
});
}

if (this.clientCapabilities?.tabby?.agent) {
this.agent.on("configUpdated", (event: ConfigUpdatedEvent) => {
if (!deepEqual(event.config.server, this.serverConfig)) {
const params: DidChangeServerConfigParams = {
server: event.config.server,
};
this.connection.sendNotification(AgentServerConfigSync.type, params);
this.serverConfig = event.config.server;
this.serverInfo = {
config: agentConfig.server,
health: this.agent.getServerHealthState(),
};
this.agent.on("configUpdated", (event: ConfigUpdatedEvent) => {
const serverInfo = {
config: event.config.server,
health: this.agent.getServerHealthState(),
};
if (!deepEqual(serverInfo, this.serverInfo)) {
if (this.clientCapabilities?.tabby?.agent) {
this.connection.sendNotification(AgentServerInfoSync.type, { serverInfo });
}
});
this.serverInfo = serverInfo;
}
});

this.agent.on("statusChanged", (event: StatusChangedEvent) => {
const params: DidChangeStatusParams = {
this.agent.on("statusChanged", (event: StatusChangedEvent) => {
if (this.clientCapabilities?.tabby?.agent) {
this.connection.sendNotification(AgentStatusSync.type, {
status: event.status,
};
this.connection.sendNotification(AgentStatusSync.type, params);
});
}

if (this.agent.getServerHealthState()?.chat_model) {
this.connection.sendRequest(RegistrationRequest.type, {
registrations: [
{
id: ChatFeatureRegistration.type.method,
method: ChatFeatureRegistration.type.method,
},
],
});
} else {
this.connection.sendRequest(UnregistrationRequest.type, {
unregisterations: [
{
id: ChatFeatureRegistration.type.method,
method: ChatFeatureRegistration.type.method,
},
],
});
const health = this.agent.getServerHealthState();
const serverInfo = {
config: this.agent.getConfig().server,
health,
};
if (!deepEqual(serverInfo, this.serverInfo)) {
if (this.clientCapabilities?.tabby?.agent) {
this.connection.sendNotification(AgentServerInfoSync.type, { serverInfo });
}
});
this.serverInfo = serverInfo;
}
if (health?.chat_model) {
this.connection.sendRequest(RegistrationRequest.type, {
registrations: [
{
id: ChatFeatureRegistration.type.method,
method: ChatFeatureRegistration.type.method,
},
],
});
} else {
this.connection.sendRequest(UnregistrationRequest.type, {
unregisterations: [
{
id: ChatFeatureRegistration.type.method,
method: ChatFeatureRegistration.type.method,
},
],
});
}
});

if (this.clientCapabilities?.tabby?.agent) {
this.agent.on("issuesUpdated", (event: IssuesUpdatedEvent) => {
const params: DidUpdateIssueParams = {
this.connection.sendNotification(AgentIssuesSync.type, {
issues: event.issues,
};
this.connection.sendNotification(AgentIssuesSync.type, params);
});
});
}
}
@@ -354,13 +368,13 @@ export class Server {
return process.exit(0);
}

private async getServerConfig(): Promise<ServerConfig> {
const serverConfig = this.agent.getConfig().server;
return {
endpoint: serverConfig.endpoint,
token: serverConfig.token,
requestHeaders: serverConfig.requestHeaders,
};
private async getServerInfo(): Promise<ServerInfo> {
return (
this.serverInfo ?? {
config: this.agent.getConfig().server,
health: this.agent.getServerHealthState(),
}
);
}

private async getStatus(): Promise<Status> {
@@ -1047,14 +1061,14 @@ export class Server {
"You can find a list of recommend models in the online documentation.\n";
}
let commonHelpMessage = "";
const host = new URL(this.serverConfig.endpoint).host;
if (helpMessageForRunningLargeModelOnCPU.length == 0) {
commonHelpMessage += ` - The running model ${
serverHealthState?.model ?? ""
} may be performing poorly due to its large parameter size. `;
commonHelpMessage +=
"Please consider trying smaller models. You can find a list of recommend models in the online documentation.\n";
}
const host = new URL(this.serverInfo?.config.endpoint ?? "http://localhost:8080").host;
if (!(host.startsWith("localhost") || host.startsWith("127.0.0.1") || host.startsWith("0.0.0.0"))) {
commonHelpMessage += " - A poor network connection. Please check your network and proxy settings.\n";
commonHelpMessage += " - Server overload. Please contact your Tabby server administrator for assistance.\n";
45 changes: 23 additions & 22 deletions clients/tabby-agent/src/lsp/protocol.ts
Original file line number Diff line number Diff line change
@@ -317,43 +317,44 @@ export type EventParams = {
};

/**
* [Tabby] DidChangeServerConfig Notification(⬅️)
* [Tabby] DidUpdateServerInfo Notification(⬅️)
*
* This method is sent from the server to the client to notify the current configuration
* for connecting to the Tabby server has changed.
* - method: `tabby/agent/didChangeServerConfig`
* - params: {@link DidChangeServerConfigParams}
* This method is sent from the server to the client to notify the current Tabby server info has changed.
* - method: `tabby/agent/didChangeServerInfo`
* - params: {@link DidUpdateServerInfoParams}
* - result: void
*/
export namespace AgentServerConfigSync {
export const method = "tabby/agent/didChangeServerConfig";
export namespace AgentServerInfoSync {
export const method = "tabby/agent/didUpdateServerInfo";
export const messageDirection = MessageDirection.serverToClient;
export const type = new ProtocolNotificationType<DidChangeServerConfigParams, void>(method);
export const type = new ProtocolNotificationType<DidUpdateServerInfoParams, void>(method);
}

export type DidChangeServerConfigParams = {
server: ServerConfig;
export type DidUpdateServerInfoParams = {
serverInfo: ServerInfo;
};

export type ServerConfig = {
endpoint: string;
token: string;
requestHeaders: Record<string, string | number | boolean | null | undefined> | null;
export type ServerInfo = {
config: {
endpoint: string;
token: string | null;
requestHeaders: Record<string, string | number | boolean | null | undefined> | null;
};
health: Record<string, unknown> | null;
};

/**
* [Tabby] Server Config Request(↩️)
* [Tabby] Server Info Request(↩️)
*
* This method is sent from the client to the server to check the current configuration
* for connecting to the Tabby server.
* - method: `tabby/agent/server`
* This method is sent from the client to the server to check the current Tabby server info.
* - method: `tabby/agent/serverInfo`
* - params: none
* - result: {@link ServerConfig}
* - result: {@link ServerInfo}
*/
export namespace AgentServerConfigRequest {
export const method = "tabby/agent/server";
export namespace AgentServerInfoRequest {
export const method = "tabby/agent/serverInfo";
export const messageDirection = MessageDirection.clientToServer;
export const type = new ProtocolRequestType0<ServerConfig, never, void, void>(method);
export const type = new ProtocolRequestType0<ServerInfo, never, void, void>(method);
}

/**
4 changes: 4 additions & 0 deletions clients/vscode/package.json
Original file line number Diff line number Diff line change
@@ -276,9 +276,11 @@
"vscode:publish": "vsce publish --no-dependencies"
},
"devDependencies": {
"@types/deep-equal": "^1.0.4",
"@types/mocha": "^10.0.1",
"@types/node": "18.x",
"@types/object-hash": "^3.0.0",
"@types/semver": "^7.5.8",
"@types/vscode": "^1.82.0",
"@typescript-eslint/eslint-plugin": "^6.13.1",
"@typescript-eslint/parser": "^6.13.1",
@@ -299,7 +301,9 @@
},
"dependencies": {
"@quilted/threads": "^2.2.0",
"deep-equal": "^2.2.1",
"object-hash": "^3.0.0",
"semver": "^7.6.0",
"tabby-agent": "workspace:*",
"tabby-chat-panel": "workspace:*",
"vscode-languageclient": "^9.0.1"
31 changes: 2 additions & 29 deletions clients/vscode/src/Config.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
import { EventEmitter } from "events";
import { workspace, ExtensionContext, WorkspaceConfiguration, ConfigurationTarget, Memento } from "vscode";
import { State as LanguageClientState } from "vscode-languageclient";
import { ClientProvidedConfig, ServerConfig } from "tabby-agent";
import { Client } from "./lsp/Client";
import { ClientProvidedConfig } from "tabby-agent";

export class Config extends EventEmitter {
private serverConfig?: ServerConfig;

constructor(
private readonly context: ExtensionContext,
private readonly client: Client,
) {
constructor(private readonly context: ExtensionContext) {
super();
this.client.languageClient.onDidChangeState(async (state) => {
if (state.newState === LanguageClientState.Running) {
this.serverConfig = await this.client.agent.fetchServerConfig();
this.emit("updatedServerConfig");
}
});
this.client.agent.on("didChangeServerConfig", (params: ServerConfig) => {
this.serverConfig = params;
this.emit("updatedServerConfig");
});
context.subscriptions.push(
workspace.onDidChangeConfiguration(async (event) => {
if (event.affectsConfiguration("tabby")) {
@@ -39,16 +22,6 @@ export class Config extends EventEmitter {
return this.context.globalState;
}

get server(): ServerConfig {
return (
this.serverConfig ?? {
endpoint: this.serverEndpoint,
token: this.serverToken,
requestHeaders: null,
}
);
}

get serverEndpoint(): string {
return this.workspace.get("api.endpoint", "");
}
Loading

0 comments on commit 750d362

Please sign in to comment.