mirror of
https://github.com/andy-stack/vaultkeeper-ai.git
synced 2026-07-22 06:42:03 +00:00
refactor: enhance file operations to support batch reads and deletion
- Rename ReadVaultFile to ReadVaultFiles with multi-file support - Add DeleteVaultFile function with confirmation parameter - Update function references and error handling - Return detailed error objects from FileSystemService
This commit is contained in:
parent
9ab0897c57
commit
76afac7ffc
8 changed files with 99 additions and 42 deletions
|
|
@ -1,18 +1,20 @@
|
|||
import type { IAIFunctionDefinition } from "./IAIFunctionDefinition";
|
||||
import { SearchVaultFiles } from "./Functions/SearchVaultFiles";
|
||||
import { ReadVaultFile } from "./Functions/ReadVaultFile";
|
||||
import { ReadVaultFiles } from "./Functions/ReadVaultFiles";
|
||||
import { WriteVaultFile } from "./Functions/WriteVaultFile";
|
||||
import { DeleteVaultFile } from "./Functions/DeleteVaultFile";
|
||||
|
||||
export class AIFunctionDefinitions {
|
||||
public getQueryActions(destructive: boolean): IAIFunctionDefinition[] {
|
||||
let actions = [
|
||||
SearchVaultFiles,
|
||||
ReadVaultFile
|
||||
ReadVaultFiles
|
||||
];
|
||||
|
||||
if (destructive) {
|
||||
actions = actions.concat([
|
||||
WriteVaultFile
|
||||
WriteVaultFile,
|
||||
DeleteVaultFile
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
31
AIClasses/FunctionDefinitions/Functions/DeleteVaultFile.ts
Normal file
31
AIClasses/FunctionDefinitions/Functions/DeleteVaultFile.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import { AIFunction } from "Enums/AIFunction";
|
||||
import type { IAIFunctionDefinition } from "../IAIFunctionDefinition";
|
||||
|
||||
export const DeleteVaultFile: IAIFunctionDefinition = {
|
||||
name: AIFunction.DeleteVaultFile,
|
||||
description: `Permanently removes a file from the vault. Use this when the user explicitly
|
||||
requests to delete a file, when a file is no longer needed, or when removing outdated
|
||||
content. IMPORTANT: This action is irreversible - always confirm the exact file path
|
||||
before deletion. Prefer archiving or moving files to a trash folder over permanent
|
||||
deletion when uncertain. Only call this after verifying the file exists and confirming
|
||||
the user's intent to delete.`,
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
file_path: {
|
||||
type: "string",
|
||||
description: "The full path to the file within the vault to be deleted (e.g., 'folder/note.md'). Must be an exact match to an existing file."
|
||||
},
|
||||
user_message: {
|
||||
type: "string",
|
||||
description: "A short message to be displayed to the user explaining why this file is being deleted (e.g., 'Deleting completed task list as requested' or 'Removing duplicate note file')."
|
||||
},
|
||||
confirm_deletion: {
|
||||
type: "boolean",
|
||||
description: "Safety flag that must be explicitly set to true to confirm the deletion is intentional. This prevents accidental deletions.",
|
||||
default: false
|
||||
}
|
||||
},
|
||||
required: ["file_path", "user_message", "confirm_deletion"]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
import { AIFunction } from "Enums/AIFunction";
|
||||
import type { IAIFunctionDefinition } from "../IAIFunctionDefinition";
|
||||
|
||||
export const ReadVaultFile: IAIFunctionDefinition = {
|
||||
name: AIFunction.ReadVaultFile,
|
||||
description: `Reads and returns the complete content of a specific file from the vault.
|
||||
Call this when you need to access existing note content to answer questions,
|
||||
provide summaries, verify information, or gather context before making updates.
|
||||
Use proactively before updating files to understand current content and avoid
|
||||
data loss. Essential for any operation that references or builds upon existing notes.`,
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
file_path: {
|
||||
type: "string",
|
||||
description: "The full path to the file within the vault (e.g., 'folder/note.md')"
|
||||
},
|
||||
user_message: {
|
||||
type: "string",
|
||||
description: "A short message to be displayed to the user explaining why you're reading this file (e.g., 'Reading your daily note to check tasks')"
|
||||
}
|
||||
},
|
||||
required: ["file_path", "user_message"]
|
||||
}
|
||||
}
|
||||
31
AIClasses/FunctionDefinitions/Functions/ReadVaultFiles.ts
Normal file
31
AIClasses/FunctionDefinitions/Functions/ReadVaultFiles.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import { AIFunction } from "Enums/AIFunction";
|
||||
import type { IAIFunctionDefinition } from "../IAIFunctionDefinition";
|
||||
|
||||
export const ReadVaultFiles: IAIFunctionDefinition = {
|
||||
name: AIFunction.ReadVaultFiles,
|
||||
description: `Reads and returns the complete content of one or more files from the vault.
|
||||
Call this when you need to access existing note content to answer questions,
|
||||
provide summaries, verify information, or gather context before making updates.
|
||||
Use proactively before updating files to understand current content and avoid
|
||||
data loss. Essential for any operation that references or builds upon existing notes.
|
||||
|
||||
For multiple files: Use when comparing content, gathering related context, or
|
||||
analyzing information across several documents.`,
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
file_paths: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "string"
|
||||
},
|
||||
description: "Array of full paths to files within the vault. Can contain a single file path ['folder/note.md'] or multiple paths ['folder/note1.md', 'folder/note2.md']. Each path must be exact and point to an existing file.",
|
||||
},
|
||||
user_message: {
|
||||
type: "string",
|
||||
description: "A short message to be displayed to the user explaining why you're reading these file(s). Examples: 'Reading your daily note to check tasks' (single file) or 'Reading your project notes to compile a summary' (multiple files)"
|
||||
}
|
||||
},
|
||||
required: ["file_paths", "user_message"]
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ export const WriteVaultFile: IAIFunctionDefinition = {
|
|||
name: AIFunction.WriteVaultFile,
|
||||
description: `Writes content to a file, creating it if it doesn't exist or replacing its contents if it does.
|
||||
Use this for creating new notes or completely updating existing ones when you have the full content ready.
|
||||
IMPORTANT: This replaces the entire file content - always read the file first with ${AIFunction.ReadVaultFile} if you need to preserve existing content and make partial changes.
|
||||
IMPORTANT: This replaces the entire file content - always read the file first with ${AIFunction.ReadVaultFiles} if you need to preserve existing content and make partial changes.
|
||||
For simple updates or additions, reading first ensures you don't lose data.`,
|
||||
parameters: {
|
||||
type: "object",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
export enum AIFunction {
|
||||
SearchVaultFiles = "search_vault_files",
|
||||
ReadVaultFile = "read_vault_file",
|
||||
ReadVaultFiles = "read_vault_files",
|
||||
WriteVaultFile = "write_vault_file",
|
||||
DeleteVaultFile = "delete_vault_file",
|
||||
|
||||
// used by gemini
|
||||
RequestWebSearch = "request_web_search"
|
||||
|
|
|
|||
|
|
@ -17,12 +17,15 @@ export class AIFunctionService {
|
|||
case AIFunction.SearchVaultFiles:
|
||||
return new AIFunctionResponse(functionCall.name, await this.searchVaultFiles(functionCall.arguments.search_term));
|
||||
|
||||
case AIFunction.ReadVaultFile:
|
||||
return new AIFunctionResponse(functionCall.name, await this.readVaultFile(functionCall.arguments.file_path));
|
||||
case AIFunction.ReadVaultFiles:
|
||||
return new AIFunctionResponse(functionCall.name, await this.readVaultFiles(functionCall.arguments.file_paths));
|
||||
|
||||
case AIFunction.WriteVaultFile:
|
||||
return new AIFunctionResponse(functionCall.name, await this.writeVaultFile(functionCall.arguments.file_path, functionCall.arguments.content));
|
||||
|
||||
case AIFunction.DeleteVaultFile:
|
||||
return new AIFunctionResponse(functionCall.name, await this.deleteVaultFile(functionCall.arguments.file_path, functionCall.arguments.confirm_deletion));
|
||||
|
||||
// this is only used by gemini
|
||||
case AIFunction.RequestWebSearch:
|
||||
return new AIFunctionResponse(functionCall.name, {})
|
||||
|
|
@ -58,16 +61,30 @@ export class AIFunctionService {
|
|||
}));
|
||||
}
|
||||
|
||||
private async readVaultFile(filePath: string): Promise<object> {
|
||||
const content = await this.fileSystemService.readFile(filePath);
|
||||
if (content === null) {
|
||||
return { error: `File not found: ${filePath}` };
|
||||
}
|
||||
return { content };
|
||||
private async readVaultFiles(filePaths: string[]): Promise<object> {
|
||||
const files = await Promise.all(
|
||||
filePaths.map(async (filePath) => {
|
||||
const content = await this.fileSystemService.readFile(filePath);
|
||||
if (content === null) {
|
||||
return { path: filePath, error: `File not found: ${filePath}` };
|
||||
}
|
||||
return { path: filePath, content };
|
||||
})
|
||||
);
|
||||
return { files };
|
||||
}
|
||||
|
||||
private async writeVaultFile(filePath: string, content: string): Promise<object> {
|
||||
const result: boolean = await this.fileSystemService.writeFile(normalizePath(filePath), content);
|
||||
return isBoolean(result) ? { success: result } : { success: false, error: result }
|
||||
const result: any = await this.fileSystemService.writeFile(normalizePath(filePath), content);
|
||||
return isBoolean(result) ? { success: result } : { success: false, error: result };
|
||||
}
|
||||
|
||||
private async deleteVaultFile(filepath: string, confirmation: boolean): Promise<object> {
|
||||
if (!confirmation) {
|
||||
return { error: "Confirmation was false, no action taken" };
|
||||
}
|
||||
|
||||
const result: any = await this.fileSystemService.deleteFile(filepath);
|
||||
return isBoolean(result) ? { success: result } : { success: false, error: result };
|
||||
}
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ export class FileSystemService {
|
|||
}
|
||||
}
|
||||
|
||||
public async deleteFile(filePath: string, allowAccessToPluginRoot: boolean = false): Promise<boolean> {
|
||||
public async deleteFile(filePath: string, allowAccessToPluginRoot: boolean = false): Promise<boolean | any> {
|
||||
try {
|
||||
const file: TAbstractFile | null = this.vaultService.getAbstractFileByPath(filePath, allowAccessToPluginRoot);
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ export class FileSystemService {
|
|||
return false;
|
||||
} catch (error) {
|
||||
console.error("Error deleting file:", error);
|
||||
return false;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue