Add workspace service to the host bridge. (#4438)

* Add workspace service to the host bridge.

Add a service for workspaces to the host bridge.
The service has one rpc getWorkspacePaths that will replace vscode.workspace.workspaceFolders

* Add the vscode host implementation of getWorkspaceFolders

* Update src/hosts/vscode/workspace/getWorkspacePaths.ts

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
This commit is contained in:
Sarah Fortune
2025-06-25 08:53:56 -10:00
committed by GitHub
co-authored by ellipsis-dev[bot]
parent 14ed98ae87
commit e41e80aaf5
6 changed files with 51 additions and 4 deletions
+1
View File
@@ -58,6 +58,7 @@ const serviceDirs = Object.keys(serviceNameMap).map((serviceKey) => path.join(RO
const hostServiceNameMap = {
uri: "host.UriService",
watch: "host.WatchService",
workspace: "host.WorkspaceService",
// Add new host services here
}
const hostServiceDirs = Object.keys(hostServiceNameMap).map((serviceKey) => path.join(ROOT_DIR, "src/hosts/vscode", serviceKey))
+24
View File
@@ -0,0 +1,24 @@
syntax = "proto3";
package host;
option java_package = "bot.cline.host.proto";
option java_multiple_files = true;
// Provides methods for working with workspaces/projects.
service WorkspaceService {
// Returns a list of the top level directories of the workspace.
rpc getWorkspacePaths(GetWorkspacePathsRequest) returns (GetWorkspacePathsResponse);
}
message GetWorkspacePathsRequest {
// The unique ID for the workspace/project.
// This is currently optional in vscode. It is required in other environments where cline is running at
// the application level, and the user can open multiple projects.
optional string id = 1;
}
message GetWorkspacePathsResponse {
// The unique ID for the workspace/project.
optional string id = 1;
repeated string paths = 2;
}
+6 -1
View File
@@ -1,4 +1,8 @@
import { UriServiceClientInterface, WatchServiceClientInterface } from "@generated/hosts/host-bridge-client-types"
import {
UriServiceClientInterface,
WatchServiceClientInterface,
WorkspaceServiceClientInterface,
} from "@generated/hosts/host-bridge-client-types"
/**
* Interface for host bridge client providers
@@ -6,6 +10,7 @@ import { UriServiceClientInterface, WatchServiceClientInterface } from "@generat
export interface HostBridgeClientProvider {
uriServiceClient: UriServiceClientInterface
watchServiceClient: WatchServiceClientInterface
workspaceClient: WorkspaceServiceClientInterface
}
/**
@@ -5,4 +5,5 @@ import * as host from "@shared/proto/index.host"
export const vscodeHostBridgeClient: HostBridgeClientProvider = {
uriServiceClient: createGrpcClient(host.UriServiceDefinition),
watchServiceClient: createGrpcClient(host.WatchServiceDefinition),
workspaceClient: createGrpcClient(host.WorkspaceServiceDefinition),
}
@@ -0,0 +1,6 @@
import { GetWorkspacePathsRequest, GetWorkspacePathsResponse } from "@/shared/proto/index.host"
import * as vscode from "vscode"
export async function getWorkspacePaths(_: GetWorkspacePathsRequest): Promise<GetWorkspacePathsResponse> {
const paths = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath) ?? []
return GetWorkspacePathsResponse.create({ paths: paths })
}
+13 -3
View File
@@ -1,16 +1,25 @@
import { Channel, createChannel } from "nice-grpc"
import { UriServiceClientImpl, WatchServiceClientImpl } from "@generated/standalone/host-bridge-clients"
import { UriServiceClientInterface, WatchServiceClientInterface } from "@generated/hosts/host-bridge-client-types"
import {
UriServiceClientImpl,
WatchServiceClientImpl,
WorkspaceServiceClientImpl,
} from "@generated/standalone/host-bridge-clients"
import {
UriServiceClientInterface,
WatchServiceClientInterface,
WorkspaceServiceClientInterface,
} from "@generated/hosts/host-bridge-client-types"
import { HostBridgeClientProvider } from "@/hosts/host-provider-types"
/**
* Singleton class to hold the gRPC clients for the host bridge. The clients should be re-used to avoid
* Manager to hold the gRPC clients for the host bridge. The clients should be re-used to avoid
* creating a new TCP connection every time a rpc is made.
*/
export class ExternalHostBridgeClientManager implements HostBridgeClientProvider {
private channel: Channel
uriServiceClient: UriServiceClientInterface
watchServiceClient: WatchServiceClientInterface
workspaceClient: WorkspaceServiceClientInterface
constructor() {
const address = process.env.HOST_BRIDGE_ADDRESS || "localhost:50052"
@@ -18,6 +27,7 @@ export class ExternalHostBridgeClientManager implements HostBridgeClientProvider
this.uriServiceClient = new UriServiceClientImpl(this.channel)
this.watchServiceClient = new WatchServiceClientImpl(this.channel)
this.workspaceClient = new WorkspaceServiceClientImpl(this.channel)
}
public close(): void {