mirror of
https://github.com/cline/cline.git
synced 2026-08-31 01:40:46 +08:00
refactor to hostbridge: route @mentions search via WorkspaceService.searchWorkspaceItems (#5655)
This commit is contained in:
@@ -7,7 +7,17 @@
|
||||
"src/generated/hosts/vscode/protobus-services.ts",
|
||||
"src/generated/hosts/vscode/hostbridge-grpc-service-config.ts"
|
||||
],
|
||||
"project": ["src/**/*.ts"],
|
||||
"ignore": ["out/**", "node_modules/**", "*.d.ts", "**/*.test.ts", "**/__tests__", "src/test/**", "src/shared/**"],
|
||||
"project": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"ignore": [
|
||||
"out/**",
|
||||
"node_modules/**",
|
||||
"*.d.ts",
|
||||
"**/*.test.ts",
|
||||
"**/__tests__",
|
||||
"src/test/**",
|
||||
"src/shared/**"
|
||||
],
|
||||
"vite": true
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ service WorkspaceService {
|
||||
|
||||
// Get diagnostics from the workspace.
|
||||
rpc getDiagnostics(GetDiagnosticsRequest) returns (GetDiagnosticsResponse);
|
||||
// Returns workspace items (files/folders) matching a query for mention autocomplete
|
||||
rpc searchWorkspaceItems(SearchWorkspaceItemsRequest) returns (SearchWorkspaceItemsResponse);
|
||||
|
||||
// Makes the problems panel/pane visible in the IDE and focuses it.
|
||||
rpc openProblemsPanel(OpenProblemsPanelRequest) returns (OpenProblemsPanelResponse);
|
||||
@@ -55,6 +57,28 @@ message GetDiagnosticsResponse {
|
||||
repeated cline.FileDiagnostics file_diagnostics = 1;
|
||||
}
|
||||
|
||||
// Request for host-side workspace search (files/folders) used by mentions autocomplete
|
||||
message SearchWorkspaceItemsRequest {
|
||||
string query = 1; // Search query string
|
||||
optional int32 limit = 2; // Optional limit for results (default decided by host)
|
||||
// Optional selected type filter
|
||||
enum SearchItemType {
|
||||
FILE = 0;
|
||||
FOLDER = 1;
|
||||
}
|
||||
optional SearchItemType selected_type = 3;
|
||||
}
|
||||
|
||||
// Response for host-side workspace search
|
||||
message SearchWorkspaceItemsResponse {
|
||||
message SearchItem {
|
||||
string path = 1; // Workspace-relative path using platform separators
|
||||
SearchWorkspaceItemsRequest.SearchItemType type = 2;
|
||||
optional string label = 3; // Optional display label (e.g., basename)
|
||||
}
|
||||
repeated SearchItem items = 1;
|
||||
}
|
||||
|
||||
message OpenProblemsPanelRequest {}
|
||||
message OpenProblemsPanelResponse {}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { searchWorkspaceFiles } from "@services/search/file-search"
|
||||
import { FileSearchRequest, FileSearchResults, FileSearchType } from "@shared/proto/cline/file"
|
||||
import { convertSearchResultsToProtoFileInfos } from "@shared/proto-conversions/file/search-result-conversion"
|
||||
import { getWorkspacePath } from "@utils/path"
|
||||
import { Controller } from ".."
|
||||
import { FileSearchRequest, FileSearchResults, FileSearchType } from "@shared/proto/cline/file"
|
||||
import { getWorkspacePath } from "@utils/path"
|
||||
import { convertSearchResultsToProtoFileInfos } from "@shared/proto-conversions/file/search-result-conversion"
|
||||
import { HostProvider } from "@/hosts/host-provider"
|
||||
import { SearchWorkspaceItemsRequest_SearchItemType } from "@shared/proto/host/workspace"
|
||||
|
||||
/**
|
||||
* Searches for files in the workspace with fuzzy matching
|
||||
@@ -23,35 +24,37 @@ export async function searchFiles(_controller: Controller, request: FileSearchRe
|
||||
}
|
||||
|
||||
try {
|
||||
// Map enum to string for the search service
|
||||
let selectedTypeString: "file" | "folder" | undefined
|
||||
if (request.selectedType === FileSearchType.FILE) {
|
||||
selectedTypeString = "file"
|
||||
} else if (request.selectedType === FileSearchType.FOLDER) {
|
||||
selectedTypeString = "folder"
|
||||
}
|
||||
// Map enum to host SearchItemType (0 = FILE, 1 = FOLDER)
|
||||
const selectedTypeValue: SearchWorkspaceItemsRequest_SearchItemType | undefined =
|
||||
request.selectedType === FileSearchType.FILE
|
||||
? SearchWorkspaceItemsRequest_SearchItemType.FILE
|
||||
: request.selectedType === FileSearchType.FOLDER
|
||||
? SearchWorkspaceItemsRequest_SearchItemType.FOLDER
|
||||
: undefined
|
||||
|
||||
// Call file search service with query from request
|
||||
const searchResults = await searchWorkspaceFiles(
|
||||
request.query || "",
|
||||
workspacePath,
|
||||
request.limit || 20, // Use default limit of 20 if not specified
|
||||
selectedTypeString,
|
||||
// Use host-provided search via hostbridge (no fallback)
|
||||
const hostResponse = await HostProvider.workspace.searchWorkspaceItems({
|
||||
query: request.query || "",
|
||||
limit: request.limit || 20,
|
||||
selectedType: selectedTypeValue,
|
||||
})
|
||||
|
||||
const mapped: { path: string; type: "file" | "folder"; label?: string }[] = (hostResponse.items || []).map(
|
||||
(item: { path?: string; type: SearchWorkspaceItemsRequest_SearchItemType; label?: string }) => ({
|
||||
path: String(item.path || ""),
|
||||
type: item.type === SearchWorkspaceItemsRequest_SearchItemType.FOLDER ? "folder" : "file",
|
||||
label: item.label || undefined,
|
||||
}),
|
||||
)
|
||||
|
||||
// Convert search results to proto FileInfo objects using the conversion function
|
||||
const protoResults = convertSearchResultsToProtoFileInfos(searchResults)
|
||||
const protoResults = convertSearchResultsToProtoFileInfos(mapped)
|
||||
|
||||
// Return successful results
|
||||
return FileSearchResults.create({
|
||||
results: protoResults,
|
||||
mentionsRequestId: request.mentionsRequestId,
|
||||
})
|
||||
} catch (error) {
|
||||
// Log the error but don't include it in the response, following the pattern in searchCommits
|
||||
console.error("Error in searchFiles:", error instanceof Error ? error.message : String(error))
|
||||
|
||||
// Return empty results without error message
|
||||
console.error("Error in host searchWorkspaceItems:", error instanceof Error ? error.message : String(error))
|
||||
return FileSearchResults.create({
|
||||
results: [],
|
||||
mentionsRequestId: request.mentionsRequestId,
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import * as vscode from "vscode"
|
||||
import { basename } from "path"
|
||||
import {
|
||||
SearchWorkspaceItemsRequest,
|
||||
SearchWorkspaceItemsResponse,
|
||||
SearchWorkspaceItemsRequest_SearchItemType,
|
||||
} from "@/shared/proto/index.host"
|
||||
import { searchWorkspaceFiles } from "@/services/search/file-search"
|
||||
|
||||
export async function searchWorkspaceItems(request: SearchWorkspaceItemsRequest): Promise<SearchWorkspaceItemsResponse> {
|
||||
const workspacePath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath
|
||||
if (!workspacePath) {
|
||||
return SearchWorkspaceItemsResponse.create({ items: [] })
|
||||
}
|
||||
|
||||
let selectedTypeString: "file" | "folder" | undefined = undefined
|
||||
if (request.selectedType === SearchWorkspaceItemsRequest_SearchItemType.FILE) {
|
||||
selectedTypeString = "file"
|
||||
} else if (request.selectedType === SearchWorkspaceItemsRequest_SearchItemType.FOLDER) {
|
||||
selectedTypeString = "folder"
|
||||
}
|
||||
|
||||
const results = await searchWorkspaceFiles(request.query || "", workspacePath, request.limit || 20, selectedTypeString)
|
||||
|
||||
return SearchWorkspaceItemsResponse.create({
|
||||
items: results.map((r) => ({
|
||||
path: r.path,
|
||||
type:
|
||||
r.type === "folder"
|
||||
? SearchWorkspaceItemsRequest_SearchItemType.FOLDER
|
||||
: SearchWorkspaceItemsRequest_SearchItemType.FILE,
|
||||
label: r.label ?? basename(r.path),
|
||||
})),
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user