mirror of
https://github.com/cline/cline.git
synced 2025-06-03 03:59:07 +00:00
[PROTOBUS] Move deleteRuleFile to protobus 🚌💨 (#3124)
* createRuleFile protobus migration * deleteRuleFile protobus * mend * mend * mend * ellipsis changes * Generic response for delete request * refactored deleteRuleFile for consolidation * rename ruleFileResult to ruleFile
This commit is contained in:
parent
f6d50ead3f
commit
4650ffa86b
5
.changeset/tough-kangaroos-beam.md
Normal file
5
.changeset/tough-kangaroos-beam.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
deleteRuleFile protobus migration
|
@ -49,3 +49,9 @@ message BooleanRequest {
|
||||
message Boolean {
|
||||
bool value = 1;
|
||||
}
|
||||
|
||||
// Generic response for operations that return success status and a message
|
||||
message OperationResponse {
|
||||
bool success = 1; // Whether the operation was successful
|
||||
string message = 2; // Success or error message
|
||||
}
|
||||
|
@ -13,4 +13,20 @@ service FileService {
|
||||
|
||||
// Opens an image in the system viewer
|
||||
rpc openImage(StringRequest) returns (Empty);
|
||||
|
||||
// Deletes a rule file from either global or workspace rules directory
|
||||
rpc deleteRuleFile(DeleteRuleFileRequest) returns (RuleFile);
|
||||
}
|
||||
|
||||
// Request for deleteRuleFile
|
||||
message DeleteRuleFileRequest {
|
||||
Metadata metadata = 1;
|
||||
string rule_path = 2;
|
||||
bool is_global = 3;
|
||||
}
|
||||
|
||||
// Result for rule file operations with meaningful data only
|
||||
message RuleFile {
|
||||
string file_path = 1; // Path to the rule file
|
||||
string display_name = 2; // Filename for display purposes
|
||||
}
|
||||
|
47
src/core/controller/file/deleteRuleFile.ts
Normal file
47
src/core/controller/file/deleteRuleFile.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import { Controller } from ".."
|
||||
import { DeleteRuleFileRequest, RuleFile } from "@shared/proto/file"
|
||||
import { FileMethodHandler } from "./index"
|
||||
import {
|
||||
deleteRuleFile as deleteRuleFileImpl,
|
||||
refreshClineRulesToggles,
|
||||
} from "@core/context/instructions/user-instructions/cline-rules"
|
||||
import * as vscode from "vscode"
|
||||
import * as path from "path"
|
||||
import { cwd } from "@core/task"
|
||||
|
||||
/**
|
||||
* Deletes a rule file from either global or workspace rules directory
|
||||
* @param controller The controller instance
|
||||
* @param request The request containing rule path and isGlobal flag
|
||||
* @returns Result with file path and display name
|
||||
* @throws Error if operation fails
|
||||
*/
|
||||
export const deleteRuleFile: FileMethodHandler = async (
|
||||
controller: Controller,
|
||||
request: DeleteRuleFileRequest,
|
||||
): Promise<RuleFile> => {
|
||||
if (typeof request.isGlobal !== "boolean" || typeof request.rulePath !== "string" || !request.rulePath) {
|
||||
console.error("deleteRuleFile: Missing or invalid parameters", {
|
||||
isGlobal: typeof request.isGlobal === "boolean" ? request.isGlobal : `Invalid: ${typeof request.isGlobal}`,
|
||||
rulePath: typeof request.rulePath === "string" ? request.rulePath : `Invalid: ${typeof request.rulePath}`,
|
||||
})
|
||||
throw new Error("Missing or invalid parameters")
|
||||
}
|
||||
|
||||
const result = await deleteRuleFileImpl(controller.context, request.rulePath, request.isGlobal)
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.message || "Failed to delete rule file")
|
||||
}
|
||||
|
||||
await refreshClineRulesToggles(controller.context, cwd)
|
||||
await controller.postStateToWebview()
|
||||
|
||||
const fileName = path.basename(request.rulePath)
|
||||
vscode.window.showInformationMessage(`Rule file "${fileName}" deleted successfully`)
|
||||
|
||||
return RuleFile.create({
|
||||
filePath: request.rulePath,
|
||||
displayName: fileName,
|
||||
})
|
||||
}
|
@ -3,12 +3,14 @@
|
||||
|
||||
// Import all method implementations
|
||||
import { registerMethod } from "./index"
|
||||
import { deleteRuleFile } from "./deleteRuleFile"
|
||||
import { openFile } from "./openFile"
|
||||
import { openImage } from "./openImage"
|
||||
|
||||
// Register all file service methods
|
||||
export function registerAllMethods(): void {
|
||||
// Register each method with the registry
|
||||
registerMethod("deleteRuleFile", deleteRuleFile)
|
||||
registerMethod("openFile", openFile)
|
||||
registerMethod("openImage", openImage)
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ import {
|
||||
} from "../storage/state"
|
||||
import { Task, cwd } from "../task"
|
||||
import { ClineRulesToggles } from "@shared/cline-rules"
|
||||
import { createRuleFile, deleteRuleFile, refreshClineRulesToggles } from "../context/instructions/user-instructions/cline-rules"
|
||||
import { createRuleFile, refreshClineRulesToggles } from "../context/instructions/user-instructions/cline-rules"
|
||||
|
||||
/*
|
||||
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
|
||||
@ -549,24 +549,6 @@ export class Controller {
|
||||
}
|
||||
break
|
||||
}
|
||||
case "deleteClineRule": {
|
||||
const { isGlobal, rulePath } = message
|
||||
if (rulePath && typeof isGlobal === "boolean") {
|
||||
const result = await deleteRuleFile(this.context, rulePath, isGlobal)
|
||||
if (result.success) {
|
||||
await refreshClineRulesToggles(this.context, cwd)
|
||||
await this.postStateToWebview()
|
||||
} else {
|
||||
console.error("Failed to delete rule file:", result.message)
|
||||
}
|
||||
} else {
|
||||
console.error("deleteClineRule: Missing or invalid parameters", {
|
||||
rulePath,
|
||||
isGlobal: typeof isGlobal === "boolean" ? isGlobal : `Invalid: ${typeof isGlobal}`,
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
case "requestTotalTasksSize": {
|
||||
this.refreshTotalTasksSize()
|
||||
break
|
||||
|
@ -53,6 +53,14 @@ export interface Boolean {
|
||||
value: boolean
|
||||
}
|
||||
|
||||
/** Generic response for operations that return success status and a message */
|
||||
export interface OperationResponse {
|
||||
/** Whether the operation was successful */
|
||||
success: boolean
|
||||
/** Success or error message */
|
||||
message: string
|
||||
}
|
||||
|
||||
function createBaseMetadata(): Metadata {
|
||||
return {}
|
||||
}
|
||||
@ -738,6 +746,82 @@ export const Boolean: MessageFns<Boolean> = {
|
||||
},
|
||||
}
|
||||
|
||||
function createBaseOperationResponse(): OperationResponse {
|
||||
return { success: false, message: "" }
|
||||
}
|
||||
|
||||
export const OperationResponse: MessageFns<OperationResponse> = {
|
||||
encode(message: OperationResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
if (message.success !== false) {
|
||||
writer.uint32(8).bool(message.success)
|
||||
}
|
||||
if (message.message !== "") {
|
||||
writer.uint32(18).string(message.message)
|
||||
}
|
||||
return writer
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): OperationResponse {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
|
||||
let end = length === undefined ? reader.len : reader.pos + length
|
||||
const message = createBaseOperationResponse()
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32()
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 8) {
|
||||
break
|
||||
}
|
||||
|
||||
message.success = reader.bool()
|
||||
continue
|
||||
}
|
||||
case 2: {
|
||||
if (tag !== 18) {
|
||||
break
|
||||
}
|
||||
|
||||
message.message = reader.string()
|
||||
continue
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break
|
||||
}
|
||||
reader.skip(tag & 7)
|
||||
}
|
||||
return message
|
||||
},
|
||||
|
||||
fromJSON(object: any): OperationResponse {
|
||||
return {
|
||||
success: isSet(object.success) ? globalThis.Boolean(object.success) : false,
|
||||
message: isSet(object.message) ? globalThis.String(object.message) : "",
|
||||
}
|
||||
},
|
||||
|
||||
toJSON(message: OperationResponse): unknown {
|
||||
const obj: any = {}
|
||||
if (message.success !== false) {
|
||||
obj.success = message.success
|
||||
}
|
||||
if (message.message !== "") {
|
||||
obj.message = message.message
|
||||
}
|
||||
return obj
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<OperationResponse>, I>>(base?: I): OperationResponse {
|
||||
return OperationResponse.fromPartial(base ?? ({} as any))
|
||||
},
|
||||
fromPartial<I extends Exact<DeepPartial<OperationResponse>, I>>(object: I): OperationResponse {
|
||||
const message = createBaseOperationResponse()
|
||||
message.success = object.success ?? false
|
||||
message.message = object.message ?? ""
|
||||
return message
|
||||
},
|
||||
}
|
||||
|
||||
function bytesFromBase64(b64: string): Uint8Array {
|
||||
return Uint8Array.from(globalThis.Buffer.from(b64, "base64"))
|
||||
}
|
||||
|
@ -5,10 +5,195 @@
|
||||
// source: file.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { Empty, StringRequest } from "./common"
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"
|
||||
import { Empty, Metadata, StringRequest } from "./common"
|
||||
|
||||
export const protobufPackage = "cline"
|
||||
|
||||
/** Request for deleteRuleFile */
|
||||
export interface DeleteRuleFileRequest {
|
||||
metadata?: Metadata | undefined
|
||||
rulePath: string
|
||||
isGlobal: boolean
|
||||
}
|
||||
|
||||
/** Result for rule file operations with meaningful data only */
|
||||
export interface RuleFile {
|
||||
/** Path to the rule file */
|
||||
filePath: string
|
||||
/** Filename for display purposes */
|
||||
displayName: string
|
||||
}
|
||||
|
||||
function createBaseDeleteRuleFileRequest(): DeleteRuleFileRequest {
|
||||
return { metadata: undefined, rulePath: "", isGlobal: false }
|
||||
}
|
||||
|
||||
export const DeleteRuleFileRequest: MessageFns<DeleteRuleFileRequest> = {
|
||||
encode(message: DeleteRuleFileRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
if (message.metadata !== undefined) {
|
||||
Metadata.encode(message.metadata, writer.uint32(10).fork()).join()
|
||||
}
|
||||
if (message.rulePath !== "") {
|
||||
writer.uint32(18).string(message.rulePath)
|
||||
}
|
||||
if (message.isGlobal !== false) {
|
||||
writer.uint32(24).bool(message.isGlobal)
|
||||
}
|
||||
return writer
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): DeleteRuleFileRequest {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
|
||||
let end = length === undefined ? reader.len : reader.pos + length
|
||||
const message = createBaseDeleteRuleFileRequest()
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32()
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break
|
||||
}
|
||||
|
||||
message.metadata = Metadata.decode(reader, reader.uint32())
|
||||
continue
|
||||
}
|
||||
case 2: {
|
||||
if (tag !== 18) {
|
||||
break
|
||||
}
|
||||
|
||||
message.rulePath = reader.string()
|
||||
continue
|
||||
}
|
||||
case 3: {
|
||||
if (tag !== 24) {
|
||||
break
|
||||
}
|
||||
|
||||
message.isGlobal = reader.bool()
|
||||
continue
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break
|
||||
}
|
||||
reader.skip(tag & 7)
|
||||
}
|
||||
return message
|
||||
},
|
||||
|
||||
fromJSON(object: any): DeleteRuleFileRequest {
|
||||
return {
|
||||
metadata: isSet(object.metadata) ? Metadata.fromJSON(object.metadata) : undefined,
|
||||
rulePath: isSet(object.rulePath) ? globalThis.String(object.rulePath) : "",
|
||||
isGlobal: isSet(object.isGlobal) ? globalThis.Boolean(object.isGlobal) : false,
|
||||
}
|
||||
},
|
||||
|
||||
toJSON(message: DeleteRuleFileRequest): unknown {
|
||||
const obj: any = {}
|
||||
if (message.metadata !== undefined) {
|
||||
obj.metadata = Metadata.toJSON(message.metadata)
|
||||
}
|
||||
if (message.rulePath !== "") {
|
||||
obj.rulePath = message.rulePath
|
||||
}
|
||||
if (message.isGlobal !== false) {
|
||||
obj.isGlobal = message.isGlobal
|
||||
}
|
||||
return obj
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<DeleteRuleFileRequest>, I>>(base?: I): DeleteRuleFileRequest {
|
||||
return DeleteRuleFileRequest.fromPartial(base ?? ({} as any))
|
||||
},
|
||||
fromPartial<I extends Exact<DeepPartial<DeleteRuleFileRequest>, I>>(object: I): DeleteRuleFileRequest {
|
||||
const message = createBaseDeleteRuleFileRequest()
|
||||
message.metadata =
|
||||
object.metadata !== undefined && object.metadata !== null ? Metadata.fromPartial(object.metadata) : undefined
|
||||
message.rulePath = object.rulePath ?? ""
|
||||
message.isGlobal = object.isGlobal ?? false
|
||||
return message
|
||||
},
|
||||
}
|
||||
|
||||
function createBaseRuleFile(): RuleFile {
|
||||
return { filePath: "", displayName: "" }
|
||||
}
|
||||
|
||||
export const RuleFile: MessageFns<RuleFile> = {
|
||||
encode(message: RuleFile, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
if (message.filePath !== "") {
|
||||
writer.uint32(10).string(message.filePath)
|
||||
}
|
||||
if (message.displayName !== "") {
|
||||
writer.uint32(18).string(message.displayName)
|
||||
}
|
||||
return writer
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): RuleFile {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
|
||||
let end = length === undefined ? reader.len : reader.pos + length
|
||||
const message = createBaseRuleFile()
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32()
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break
|
||||
}
|
||||
|
||||
message.filePath = reader.string()
|
||||
continue
|
||||
}
|
||||
case 2: {
|
||||
if (tag !== 18) {
|
||||
break
|
||||
}
|
||||
|
||||
message.displayName = reader.string()
|
||||
continue
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break
|
||||
}
|
||||
reader.skip(tag & 7)
|
||||
}
|
||||
return message
|
||||
},
|
||||
|
||||
fromJSON(object: any): RuleFile {
|
||||
return {
|
||||
filePath: isSet(object.filePath) ? globalThis.String(object.filePath) : "",
|
||||
displayName: isSet(object.displayName) ? globalThis.String(object.displayName) : "",
|
||||
}
|
||||
},
|
||||
|
||||
toJSON(message: RuleFile): unknown {
|
||||
const obj: any = {}
|
||||
if (message.filePath !== "") {
|
||||
obj.filePath = message.filePath
|
||||
}
|
||||
if (message.displayName !== "") {
|
||||
obj.displayName = message.displayName
|
||||
}
|
||||
return obj
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<RuleFile>, I>>(base?: I): RuleFile {
|
||||
return RuleFile.fromPartial(base ?? ({} as any))
|
||||
},
|
||||
fromPartial<I extends Exact<DeepPartial<RuleFile>, I>>(object: I): RuleFile {
|
||||
const message = createBaseRuleFile()
|
||||
message.filePath = object.filePath ?? ""
|
||||
message.displayName = object.displayName ?? ""
|
||||
return message
|
||||
},
|
||||
}
|
||||
|
||||
/** Service for file-related operations */
|
||||
export type FileServiceDefinition = typeof FileServiceDefinition
|
||||
export const FileServiceDefinition = {
|
||||
@ -33,5 +218,44 @@ export const FileServiceDefinition = {
|
||||
responseStream: false,
|
||||
options: {},
|
||||
},
|
||||
/** Deletes a rule file from either global or workspace rules directory */
|
||||
deleteRuleFile: {
|
||||
name: "deleteRuleFile",
|
||||
requestType: DeleteRuleFileRequest,
|
||||
requestStream: false,
|
||||
responseType: RuleFile,
|
||||
responseStream: false,
|
||||
options: {},
|
||||
},
|
||||
},
|
||||
} as const
|
||||
|
||||
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined
|
||||
|
||||
export type DeepPartial<T> = T extends Builtin
|
||||
? T
|
||||
: T extends globalThis.Array<infer U>
|
||||
? globalThis.Array<DeepPartial<U>>
|
||||
: T extends ReadonlyArray<infer U>
|
||||
? ReadonlyArray<DeepPartial<U>>
|
||||
: T extends {}
|
||||
? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||
: Partial<T>
|
||||
|
||||
type KeysOfUnion<T> = T extends T ? keyof T : never
|
||||
export type Exact<P, I extends P> = P extends Builtin
|
||||
? P
|
||||
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never }
|
||||
|
||||
function isSet(value: any): boolean {
|
||||
return value !== null && value !== undefined
|
||||
}
|
||||
|
||||
export interface MessageFns<T> {
|
||||
encode(message: T, writer?: BinaryWriter): BinaryWriter
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): T
|
||||
fromJSON(object: any): T
|
||||
toJSON(message: T): unknown
|
||||
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T
|
||||
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { vscode } from "@/utils/vscode"
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import { FileServiceClient } from "@/services/grpc-client"
|
||||
import { DeleteRuleFileRequest } from "@shared/proto/file"
|
||||
|
||||
const RuleRow: React.FC<{
|
||||
rulePath: string
|
||||
@ -16,11 +16,12 @@ const RuleRow: React.FC<{
|
||||
}
|
||||
|
||||
const handleDeleteClick = () => {
|
||||
vscode.postMessage({
|
||||
type: "deleteClineRule",
|
||||
rulePath: rulePath,
|
||||
isGlobal: isGlobal,
|
||||
})
|
||||
FileServiceClient.deleteRuleFile(
|
||||
DeleteRuleFileRequest.create({
|
||||
rulePath: rulePath,
|
||||
isGlobal: isGlobal,
|
||||
}),
|
||||
).catch((err) => console.error("Failed to delete rule file:", err))
|
||||
}
|
||||
|
||||
return (
|
||||
|
Loading…
Reference in New Issue
Block a user