diff --git a/proto/build-proto.js b/proto/build-proto.js index d0d779086d..04a42928b9 100755 --- a/proto/build-proto.js +++ b/proto/build-proto.js @@ -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)) diff --git a/proto/host/workspace.proto b/proto/host/workspace.proto new file mode 100644 index 0000000000..a694238395 --- /dev/null +++ b/proto/host/workspace.proto @@ -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; +} diff --git a/src/hosts/host-provider-types.ts b/src/hosts/host-provider-types.ts index 8f54fe8cd9..280709b43e 100644 --- a/src/hosts/host-provider-types.ts +++ b/src/hosts/host-provider-types.ts @@ -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 } /** diff --git a/src/hosts/vscode/client/host-grpc-client.ts b/src/hosts/vscode/client/host-grpc-client.ts index 62e2312d1e..230483d369 100644 --- a/src/hosts/vscode/client/host-grpc-client.ts +++ b/src/hosts/vscode/client/host-grpc-client.ts @@ -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), } diff --git a/src/hosts/vscode/workspace/getWorkspacePaths.ts b/src/hosts/vscode/workspace/getWorkspacePaths.ts new file mode 100644 index 0000000000..1fece8e1d4 --- /dev/null +++ b/src/hosts/vscode/workspace/getWorkspacePaths.ts @@ -0,0 +1,6 @@ +import { GetWorkspacePathsRequest, GetWorkspacePathsResponse } from "@/shared/proto/index.host" +import * as vscode from "vscode" +export async function getWorkspacePaths(_: GetWorkspacePathsRequest): Promise { + const paths = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath) ?? [] + return GetWorkspacePathsResponse.create({ paths: paths }) +} diff --git a/src/standalone/host-bridge-client-manager.ts b/src/standalone/host-bridge-client-manager.ts index 769f31d8c9..4d02107a56 100644 --- a/src/standalone/host-bridge-client-manager.ts +++ b/src/standalone/host-bridge-client-manager.ts @@ -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 {