mirror of
https://github.com/andy-stack/vaultkeeper-ai.git
synced 2026-07-22 06:42:03 +00:00
Rename from AI Agent to Vault AI
This commit is contained in:
parent
61c2e85aa2
commit
ff111c69e6
41 changed files with 261 additions and 261 deletions
|
|
@ -7,7 +7,7 @@ import type { Conversation } from "Conversations/Conversation";
|
|||
import { AIProvider, AIProviderURL } from "Enums/ApiProvider";
|
||||
import { AIFunctionCall } from "AIClasses/AIFunctionCall";
|
||||
import type { IAIFunctionDefinition } from "AIClasses/FunctionDefinitions/IAIFunctionDefinition";
|
||||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import type { AIFunctionDefinitions } from "AIClasses/FunctionDefinitions/AIFunctionDefinitions";
|
||||
import { isValidJson } from "Helpers/Helpers";
|
||||
import type { ConversationContent } from "Conversations/ConversationContent";
|
||||
|
|
@ -20,7 +20,7 @@ export class Claude implements IAIClass {
|
|||
|
||||
private readonly apiKey: string;
|
||||
private readonly aiPrompt: IPrompt = Resolve<IPrompt>(Services.IPrompt);
|
||||
private readonly plugin: AIAgentPlugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
private readonly plugin: VaultAIPlugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
private readonly settingsService: SettingsService = Resolve<SettingsService>(Services.SettingsService);
|
||||
private readonly streamingService: StreamingService = Resolve<StreamingService>(Services.StreamingService);
|
||||
private readonly aiFunctionDefinitions: AIFunctionDefinitions = Resolve<AIFunctionDefinitions>(Services.AIFunctionDefinitions);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { Role } from "Enums/Role";
|
|||
import { AIProvider, AIProviderURL } from "Enums/ApiProvider";
|
||||
import { AIFunctionCall } from "AIClasses/AIFunctionCall";
|
||||
import type { IAIFunctionDefinition } from "AIClasses/FunctionDefinitions/IAIFunctionDefinition";
|
||||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import type { AIFunctionDefinitions } from "AIClasses/FunctionDefinitions/AIFunctionDefinitions";
|
||||
import { isValidJson } from "Helpers/Helpers";
|
||||
import type { ConversationContent } from "Conversations/ConversationContent";
|
||||
|
|
@ -21,7 +21,7 @@ export class Gemini implements IAIClass {
|
|||
|
||||
private readonly apiKey: string;
|
||||
private readonly aiPrompt: IPrompt = Resolve<IPrompt>(Services.IPrompt);
|
||||
private readonly plugin: AIAgentPlugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
private readonly plugin: VaultAIPlugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
private readonly settingsService: SettingsService = Resolve<SettingsService>(Services.SettingsService);
|
||||
private readonly streamingService: StreamingService = Resolve<StreamingService>(Services.StreamingService);
|
||||
private readonly aiFunctionDefinitions: AIFunctionDefinitions = Resolve<AIFunctionDefinitions>(Services.AIFunctionDefinitions);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import { Resolve } from "Services/DependencyService";
|
||||
import { Services } from "Services/Services";
|
||||
import { SystemInstruction } from "./SystemPrompt";
|
||||
|
|
@ -12,12 +12,12 @@ export interface IPrompt {
|
|||
|
||||
export class AIPrompt implements IPrompt {
|
||||
|
||||
private readonly plugin: AIAgentPlugin;
|
||||
private readonly plugin: VaultAIPlugin;
|
||||
private readonly settingsService: SettingsService;
|
||||
private readonly fileSystemService: FileSystemService;
|
||||
|
||||
public constructor() {
|
||||
this.plugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
this.plugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
this.settingsService = Resolve<SettingsService>(Services.SettingsService);
|
||||
this.fileSystemService = Resolve<FileSystemService>(Services.FileSystemService);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import type { Conversation } from "Conversations/Conversation";
|
|||
import { AIProvider, AIProviderURL } from "Enums/ApiProvider";
|
||||
import { AIFunctionCall } from "AIClasses/AIFunctionCall";
|
||||
import type { IAIFunctionDefinition } from "AIClasses/FunctionDefinitions/IAIFunctionDefinition";
|
||||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import type { AIFunctionDefinitions } from "AIClasses/FunctionDefinitions/AIFunctionDefinitions";
|
||||
import { Role } from "Enums/Role";
|
||||
import { isValidJson } from "Helpers/Helpers";
|
||||
|
|
@ -25,7 +25,7 @@ export class OpenAI implements IAIClass {
|
|||
|
||||
private readonly apiKey: string;
|
||||
private readonly aiPrompt: IPrompt = Resolve<IPrompt>(Services.IPrompt);
|
||||
private readonly plugin: AIAgentPlugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
private readonly plugin: VaultAIPlugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
private readonly settingsService: SettingsService = Resolve<SettingsService>(Services.SettingsService);
|
||||
private readonly streamingService: StreamingService = Resolve<StreamingService>(Services.StreamingService);
|
||||
private readonly aiFunctionDefinitions: AIFunctionDefinitions = Resolve<AIFunctionDefinitions>(Services.AIFunctionDefinitions);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
import { tick, onMount } from "svelte";
|
||||
import { conversationStore } from "../Stores/ConversationStore";
|
||||
import { Conversation } from "Conversations/Conversation";
|
||||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import { openPluginSettings } from "Helpers/Helpers";
|
||||
import { Selector } from "Enums/Selector";
|
||||
import type { WorkSpaceService } from "Services/WorkSpaceService";
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
import type { ConversationFileSystemService } from "Services/ConversationFileSystemService";
|
||||
import type { SettingsService } from "Services/SettingsService";
|
||||
|
||||
const plugin: AIAgentPlugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
const plugin: VaultAIPlugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
const settingsService: SettingsService = Resolve<SettingsService>(Services.SettingsService);
|
||||
const chatService: ChatService = Resolve<ChatService>(Services.ChatService);
|
||||
const workSpaceService: WorkSpaceService = Resolve<WorkSpaceService>(Services.WorkSpaceService);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { Resolve } from "../Services/DependencyService";
|
||||
import { Services } from "../Services/Services";
|
||||
import type AIAgentPlugin from "../main";
|
||||
import type VaultAIPlugin from "../main";
|
||||
import { setIcon, type WorkspaceLeaf } from "obsidian";
|
||||
import { ConversationFileSystemService } from "../Services/ConversationFileSystemService";
|
||||
import { conversationStore } from "../Stores/ConversationStore";
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
export let leaf: WorkspaceLeaf;
|
||||
export let onNewConversation: (() => void) | undefined = undefined;
|
||||
|
||||
const plugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
const plugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
const conversationFileSystemService = Resolve<ConversationFileSystemService>(Services.ConversationFileSystemService);
|
||||
const chatService: ChatService = Resolve<ChatService>(Services.ChatService);
|
||||
|
||||
|
|
@ -115,7 +115,7 @@
|
|||
id="settings-button"
|
||||
class="top-bar-button clickable-icon"
|
||||
on:click={openSettings}
|
||||
aria-label="AI Agent Settings"
|
||||
aria-label="Vault AI Settings"
|
||||
></button>
|
||||
<button
|
||||
bind:this={helpMenuButton}
|
||||
|
|
@ -133,7 +133,7 @@
|
|||
id="close-button"
|
||||
class="top-bar-button clickable-icon"
|
||||
on:click={closePlugin}
|
||||
aria-label="Close AI Agent"
|
||||
aria-label="Close Vault AI"
|
||||
></button>
|
||||
</div>
|
||||
</main>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { Copy } from "Enums/Copy";
|
||||
import { Path } from "Enums/Path";
|
||||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import { HelpModal } from "Modals/HelpModal";
|
||||
import { basename } from "path-browserify";
|
||||
import { Resolve } from "Services/DependencyService";
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
export let userInstructionActive: boolean;
|
||||
|
||||
const plugin: AIAgentPlugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
const plugin: VaultAIPlugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
const settingsService: SettingsService = Resolve<SettingsService>(Services.SettingsService);
|
||||
const fileSystemService: FileSystemService = Resolve<FileSystemService>(Services.FileSystemService);
|
||||
|
||||
|
|
|
|||
|
|
@ -58,14 +58,14 @@ export enum Copy {
|
|||
|
||||
// Help Modal Copy
|
||||
HelpModalAboutTitle = "About",
|
||||
HelpModalAboutContent = `#### About AI Agent
|
||||
HelpModalAboutContent = `#### About Vault AI
|
||||
|
||||
This plugin was originally created for a friend who found it useful, so I have decided to release it to the Obsidian community.
|
||||
|
||||
If you find any issues, please feel free to raise them on GitHub:`,
|
||||
|
||||
HelpModalGuideTitle = "Plugin Guide",
|
||||
HelpModalGuideContent = `#### How to Use AI Agent
|
||||
HelpModalGuideContent = `#### How to Use Vault AI
|
||||
|
||||
##### Getting Started
|
||||
1. **Add an API Key**: Go to Settings and add at least one API key (Claude, Gemini, or OpenAI)
|
||||
|
|
@ -100,12 +100,12 @@ The autocomplete dropdown supports keyboard navigation.
|
|||
|
||||
Customize AI behavior for specific workflows:
|
||||
|
||||
1. Create markdown files in **AI Agent/User Instructions/**
|
||||
1. Create markdown files in **Vault AI/User Instructions/**
|
||||
2. Click the "User Instructions" button in chat
|
||||
3. Select your instruction set
|
||||
4. The AI follows these instructions for all interactions
|
||||
|
||||
See [Example Template](#/page/AI%20Agent%2FUser%20Instructions%2FEXAMPLE_INSTRUCTIONS) for help getting started.`,
|
||||
See [Example Template](#/page/Vault%20AI%2FUser%20Instructions%2FEXAMPLE_INSTRUCTIONS) for help getting started.`,
|
||||
|
||||
HelpModalTroubleshootTitle = "Troubleshooting",
|
||||
HelpModalTroubleshootContent = `#### Common Issues & Solutions
|
||||
|
|
@ -153,9 +153,9 @@ This error means you've made too many API requests in a given time period. This
|
|||
|
||||
**What's stored locally**:
|
||||
- API keys (stored in your vault's plugin settings)
|
||||
- Conversation history (stored in \`AI Agent/Conversations/\`)
|
||||
- Custom instructions (stored in \`AI Agent/User Instructions/\`)
|
||||
- Plugin settings (stored in \`.obsidian/plugins/ai-agent-plugin/\`)
|
||||
- Conversation history (stored in \`Vault AI/Conversations/\`)
|
||||
- Custom instructions (stored in \`Vault AI/User Instructions/\`)
|
||||
- Plugin settings (stored in \`.obsidian/plugins/vault-ai/\`)
|
||||
|
||||
##### API Communication
|
||||
|
||||
|
|
@ -213,7 +213,7 @@ Each AI provider has their own data policies:
|
|||
CoffeeLinkText = "Buy me a coffee",
|
||||
|
||||
// Thank You Message
|
||||
ThankYouMessage = "Thanks for using the AI Agent plugin!",
|
||||
ThankYouMessage = "Thanks for using the Vault AI plugin!",
|
||||
|
||||
// SVG Icons
|
||||
GitHubIconPath = "M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
export enum Path {
|
||||
Root = "/",
|
||||
AIAgentDir = "AI Agent",
|
||||
Conversations = `${Path.AIAgentDir}/Conversations`,
|
||||
UserInstructions = `${Path.AIAgentDir}/User Instructions`,
|
||||
VaultAIDir = "Vault AI",
|
||||
Conversations = `${Path.VaultAIDir}/Conversations`,
|
||||
UserInstructions = `${Path.VaultAIDir}/User Instructions`,
|
||||
ExampleUserInstructions = `${Path.UserInstructions}/EXAMPLE_INSTRUCTIONS.md`
|
||||
};
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
export enum Selector {
|
||||
MarkDownLink = "ai-agent-internal-markdown-link",
|
||||
MarkDownLink = "vault-ai-internal-markdown-link",
|
||||
AIExclusionsInput = "ai-exclusions-input",
|
||||
ApiKeySettingOk = "api-key-setting-ok",
|
||||
ApiKeySettingError = "api-key-setting-error",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
|
||||
export function openPluginSettings(plugin: AIAgentPlugin) {
|
||||
export function openPluginSettings(plugin: VaultAIPlugin) {
|
||||
// @ts-ignore - accessing internal API
|
||||
plugin.app.setting.open();
|
||||
// @ts-ignore - accessing internal API
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { dateToString } from 'Helpers/Helpers';
|
|||
import { conversationStore } from 'Stores/ConversationStore';
|
||||
import { Selector } from 'Enums/Selector';
|
||||
import type { ChatService } from 'Services/ChatService';
|
||||
import type AIAgentPlugin from 'main';
|
||||
import type VaultAIPlugin from 'main';
|
||||
|
||||
interface IListItem {
|
||||
id: string;
|
||||
|
|
@ -33,7 +33,7 @@ export class ConversationHistoryModal extends Modal {
|
|||
public onModalClose?: () => void;
|
||||
|
||||
constructor() {
|
||||
const plugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
const plugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
super(plugin.app);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import { Modal } from "obsidian";
|
||||
import { Resolve } from "Services/DependencyService";
|
||||
import { Services } from "Services/Services";
|
||||
|
|
@ -11,7 +11,7 @@ export class HelpModal extends Modal {
|
|||
private component: Record<string, any> | null = null;
|
||||
|
||||
public constructor() {
|
||||
const plugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
const plugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
super(plugin.app);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { Copy } from "Enums/Copy";
|
||||
import { Selector } from "Enums/Selector";
|
||||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import { DropdownComponent, setIcon } from "obsidian";
|
||||
import { Resolve } from "Services/DependencyService";
|
||||
import { Services } from "Services/Services";
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
export let onClose: () => void;
|
||||
export let initialTopic: number = 1;
|
||||
|
||||
const plugin: AIAgentPlugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
const plugin: VaultAIPlugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
const streamingMarkdownService: StreamingMarkdownService = Resolve<StreamingMarkdownService>(Services.StreamingMarkdownService);
|
||||
const workSpaceService: WorkSpaceService = Resolve<WorkSpaceService>(Services.WorkSpaceService);
|
||||
|
||||
|
|
|
|||
24
README.md
24
README.md
|
|
@ -1,4 +1,4 @@
|
|||
# AI Agent for Obsidian
|
||||
# Vault AI for Obsidian
|
||||
|
||||
> A powerful AI assistant plugin that brings Claude, Gemini, and OpenAI directly into your Obsidian vault with intelligent note management capabilities.
|
||||
|
||||
|
|
@ -28,16 +28,16 @@
|
|||
|
||||
### Manual Installation
|
||||
|
||||
1. Download the latest release from the [Releases page](https://github.com/andy-stack/ai-agent-plugin/releases)
|
||||
2. Extract the files into your vault's `.obsidian/plugins/ai-agent-plugin/` directory
|
||||
1. Download the latest release from the [Releases page](https://github.com/andy-stack/vault-ai/releases)
|
||||
2. Extract the files into your vault's `.obsidian/plugins/vault-ai/` directory
|
||||
3. Reload Obsidian
|
||||
4. Enable "AI Agent" in Settings → Community Plugins
|
||||
4. Enable "Vault AI" in Settings → Community Plugins
|
||||
|
||||
### From Community Plugins
|
||||
|
||||
1. Open Obsidian Settings
|
||||
2. Navigate to Community Plugins
|
||||
3. Search for "AI Agent"
|
||||
3. Search for "Vault AI"
|
||||
4. Click Install, then Enable
|
||||
|
||||
## Quick Start
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
2. **Select a Model**: Choose your preferred AI model from the dropdown
|
||||
|
||||
3. **Start Chatting**: Click the AI Agent icon in the left sidebar to open the chat window
|
||||
3. **Start Chatting**: Click the Vault AI icon in the left sidebar to open the chat window
|
||||
|
||||
4. **Try the Reference System**:
|
||||
- Type `@` to reference files
|
||||
|
|
@ -130,7 +130,7 @@ The autocomplete dropdown appears automatically and supports:
|
|||
|
||||
Customize the AI's behavior with system instructions:
|
||||
|
||||
1. Create markdown files in `AI Agent/User Instructions/`
|
||||
1. Create markdown files in `Vault AI/User Instructions/`
|
||||
2. Click the "User Instructions" button in the chat
|
||||
3. Select your custom instruction set
|
||||
4. The AI will follow these instructions for all interactions
|
||||
|
|
@ -149,7 +149,7 @@ See `EXAMPLE_INSTRUCTIONS.md` in your vault for a template.
|
|||
- All conversations are automatically saved
|
||||
- Click the history icon to browse past conversations
|
||||
- Conversations are automatically named by AI based on content
|
||||
- Stored in `AI Agent/Conversations/` as JSON files
|
||||
- Stored in `Vault AI/Conversations/` as JSON files
|
||||
|
||||
## Configuration
|
||||
|
||||
|
|
@ -205,7 +205,7 @@ Protect your privacy by preventing the AI from accessing sensitive files or dire
|
|||
**Custom Instructions Path**
|
||||
|
||||
- Customize where instruction files are stored
|
||||
- Default: `AI Agent/User Instructions/`
|
||||
- Default: `Vault AI/User Instructions/`
|
||||
|
||||
## Development
|
||||
|
||||
|
|
@ -220,8 +220,8 @@ Protect your privacy by preventing the AI from accessing sensitive files or dire
|
|||
```bash
|
||||
# Clone into your vault's plugin directory
|
||||
cd /path/to/vault/.obsidian/plugins/
|
||||
git clone https://github.com/andy-stack/ai-agent-plugin.git
|
||||
cd ai-agent-plugin
|
||||
git clone https://github.com/andy-stack/vault-ai.git
|
||||
cd vault-ai
|
||||
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
|
@ -280,7 +280,7 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
|
|||
|
||||
## Support
|
||||
|
||||
- **Issues**: Report bugs or request features on [GitHub Issues](https://github.com/andy-stack/ai-agent-plugin/issues)
|
||||
- **Issues**: Report bugs or request features on [GitHub Issues](https://github.com/andy-stack/vault-ai/issues)
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import { TAbstractFile, TFile, TFolder, type Vault } from "obsidian";
|
||||
import { Resolve } from "./DependencyService";
|
||||
import { Services } from "./Services";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { AIProvider } from "Enums/ApiProvider";
|
||||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import { RegisterSingleton, RegisterTransient, Resolve } from "./DependencyService";
|
||||
import { Services } from "./Services";
|
||||
import { AIPrompt, type IPrompt } from "AIClasses/IPrompt";
|
||||
|
|
@ -37,13 +37,13 @@ import { HTMLService } from "./HTMLService";
|
|||
import { SettingsService } from "./SettingsService";
|
||||
import { HelpModal } from "Modals/HelpModal";
|
||||
|
||||
export async function RegisterPlugin(plugin: AIAgentPlugin) {
|
||||
RegisterSingleton<AIAgentPlugin>(Services.AIAgentPlugin, plugin);
|
||||
export async function RegisterPlugin(plugin: VaultAIPlugin) {
|
||||
RegisterSingleton<VaultAIPlugin>(Services.VaultAIPlugin, plugin);
|
||||
RegisterSingleton<SettingsService>(Services.SettingsService, new SettingsService(await plugin.loadData()));
|
||||
}
|
||||
|
||||
export function RegisterDependencies() {
|
||||
const plugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
const plugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
|
||||
RegisterSingleton<FileManager>(Services.FileManager, plugin.app.fileManager);
|
||||
RegisterSingleton<StatusBarService>(Services.StatusBarService, new StatusBarService());
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
export class Services {
|
||||
static AIAgentPlugin = Symbol("AIAgentPlugin");
|
||||
static VaultAIPlugin = Symbol("VaultAIPlugin");
|
||||
static SettingsService = Symbol("SettingsService");
|
||||
static StatusBarService = Symbol("StatusBarService");
|
||||
static HTMLService = Symbol("HTMLService");
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import { Resolve } from "./DependencyService";
|
||||
import { Services } from "./Services";
|
||||
import { AIProvider, AIProviderModel } from "Enums/ApiProvider";
|
||||
|
||||
const DEFAULT_SETTINGS: IAIAgentSettings = {
|
||||
const DEFAULT_SETTINGS: IVaultAISettings = {
|
||||
firstTimeStart: true,
|
||||
userInstruction: "",
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ const DEFAULT_SETTINGS: IAIAgentSettings = {
|
|||
snippetSizeLimit: 300
|
||||
}
|
||||
|
||||
export interface IAIAgentSettings {
|
||||
export interface IVaultAISettings {
|
||||
firstTimeStart: boolean;
|
||||
userInstruction: string;
|
||||
|
||||
|
|
@ -37,12 +37,12 @@ export interface IAIAgentSettings {
|
|||
|
||||
export class SettingsService {
|
||||
|
||||
private readonly plugin: AIAgentPlugin;
|
||||
private readonly plugin: VaultAIPlugin;
|
||||
|
||||
public readonly settings: IAIAgentSettings;
|
||||
public readonly settings: IVaultAISettings;
|
||||
|
||||
public constructor(loadedSettings: Partial<IAIAgentSettings>) {
|
||||
this.plugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
public constructor(loadedSettings: Partial<IVaultAISettings>) {
|
||||
this.plugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, loadedSettings);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import { Resolve } from "./DependencyService";
|
||||
import { Services } from "./Services";
|
||||
import { Selector } from "Enums/Selector";
|
||||
|
||||
export class StatusBarService {
|
||||
|
||||
private readonly plugin: AIAgentPlugin;
|
||||
private readonly plugin: VaultAIPlugin;
|
||||
private statusBarItem: HTMLElement | null;
|
||||
private currentInputTokens: number = 0;
|
||||
private currentOutputTokens: number = 0;
|
||||
private animationFrame: number | null = null;
|
||||
|
||||
public constructor() {
|
||||
this.plugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
this.plugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
}
|
||||
|
||||
public setStatusBarMessage(message: string) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import { Resolve } from "./DependencyService";
|
||||
import { Services } from "./Services";
|
||||
import type { VaultService } from "./VaultService";
|
||||
|
|
@ -17,7 +17,7 @@ export class VaultCacheService {
|
|||
key: "prepared"
|
||||
};
|
||||
|
||||
private readonly plugin: AIAgentPlugin;
|
||||
private readonly plugin: VaultAIPlugin;
|
||||
private readonly vaultService: VaultService;
|
||||
private readonly metaDataCache: MetadataCache;
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ export class VaultCacheService {
|
|||
private initialised = false;
|
||||
|
||||
public constructor() {
|
||||
this.plugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
this.plugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
this.vaultService = Resolve<VaultService>(Services.VaultService);
|
||||
this.metaDataCache = this.plugin.app.metadataCache;
|
||||
this.registerFileEvents();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { FileManager, TAbstractFile, TFile, TFolder, type Vault } from "obsidian";
|
||||
import { Resolve } from "./DependencyService";
|
||||
import { Services } from "./Services";
|
||||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import { Path } from "Enums/Path";
|
||||
import { escapeRegex, randomSample } from "Helpers/Helpers";
|
||||
import type { ISearchMatch, ISearchSnippet } from "../Helpers/SearchTypes";
|
||||
|
|
@ -16,17 +16,17 @@ interface IFileEventArgs {
|
|||
/* This service protects the users vault through their exclusions. The plugin root is excluded by default */
|
||||
export class VaultService {
|
||||
|
||||
private readonly AGENT_ROOT_DIR = Path.AIAgentDir;
|
||||
private readonly AGENT_ROOT_CONTENTS = `${Path.AIAgentDir}/**`;
|
||||
private readonly AGENT_ROOT_DIR = Path.VaultAIDir;
|
||||
private readonly AGENT_ROOT_CONTENTS = `${Path.VaultAIDir}/**`;
|
||||
|
||||
private readonly vault: Vault;
|
||||
private readonly plugin: AIAgentPlugin;
|
||||
private readonly plugin: VaultAIPlugin;
|
||||
private readonly settingsService: SettingsService;
|
||||
private readonly fileManager: FileManager;
|
||||
private readonly sanitiserService: SanitiserService;
|
||||
|
||||
public constructor() {
|
||||
this.plugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
this.plugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
this.vault = this.plugin.app.vault;
|
||||
this.settingsService = Resolve<SettingsService>(Services.SettingsService);
|
||||
this.fileManager = Resolve<FileManager>(Services.FileManager);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import { Resolve } from "./DependencyService";
|
||||
import { Services } from "./Services";
|
||||
import type { TFile, WorkspaceLeaf } from "obsidian";
|
||||
|
||||
export class WorkSpaceService {
|
||||
private readonly plugin: AIAgentPlugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
private readonly plugin: VaultAIPlugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
|
||||
public async openNote(noteName: string) {
|
||||
const file: TFile | null = this.plugin.app.metadataCache.getFirstLinkpathDest(noteName, "");
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
import { AIProvider, AIProviderModel } from "Enums/ApiProvider";
|
||||
import { Copy } from "Enums/Copy";
|
||||
import { Selector } from "Enums/Selector";
|
||||
import type AIAgentPlugin from "main";
|
||||
import type VaultAIPlugin from "main";
|
||||
import { PluginSettingTab, Setting, setIcon, setTooltip } from "obsidian";
|
||||
import { Resolve } from "Services/DependencyService";
|
||||
import type { SettingsService } from "Services/SettingsService";
|
||||
import { Services } from "Services/Services";
|
||||
import { RegisterAiProvider } from "Services/ServiceRegistration";
|
||||
|
||||
export class AIAgentSettingTab extends PluginSettingTab {
|
||||
export class VaultAISettingTab extends PluginSettingTab {
|
||||
private readonly settingsService: SettingsService;
|
||||
|
||||
private apiKeySetting: Setting | null = null;
|
||||
private apiKeyInputEl: HTMLInputElement | null = null;
|
||||
|
||||
constructor() {
|
||||
const plugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
const plugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
super(plugin.app, plugin);
|
||||
this.settingsService = Resolve<SettingsService>(Services.SettingsService);
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ import type { StatusBarService } from 'Services/StatusBarService';
|
|||
import { Resolve } from 'Services/DependencyService';
|
||||
import { Services } from 'Services/Services';
|
||||
|
||||
export const VIEW_TYPE_MAIN = 'ai-agent-main-view';
|
||||
export const VIEW_TYPE_MAIN = 'vault-ai-main-view';
|
||||
|
||||
export class MainView extends ItemView {
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ export class MainView extends ItemView {
|
|||
}
|
||||
|
||||
getDisplayText() {
|
||||
return "AI Agent";
|
||||
return "Vault AI";
|
||||
}
|
||||
|
||||
getIcon(): string {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { RegisterSingleton, Resolve, DeregisterAllServices } from '../../Service
|
|||
import { Services } from '../../Services/Services';
|
||||
import { StreamingService } from '../../Services/StreamingService';
|
||||
import type { IPrompt } from '../../AIClasses/IPrompt';
|
||||
import type AIAgentPlugin from '../../main';
|
||||
import type VaultAIPlugin from '../../main';
|
||||
import { AIFunctionDefinitions } from '../../AIClasses/FunctionDefinitions/AIFunctionDefinitions';
|
||||
import { Conversation } from '../../Conversations/Conversation';
|
||||
import { ConversationContent } from '../../Conversations/ConversationContent';
|
||||
|
|
@ -28,9 +28,9 @@ describe('Claude', () => {
|
|||
};
|
||||
RegisterSingleton(Services.IPrompt, mockPrompt);
|
||||
|
||||
// Mock AIAgentPlugin
|
||||
// Mock VaultAIPlugin
|
||||
mockPlugin = {};
|
||||
RegisterSingleton(Services.AIAgentPlugin, mockPlugin);
|
||||
RegisterSingleton(Services.VaultAIPlugin, mockPlugin);
|
||||
|
||||
// Mock SettingsService
|
||||
mockSettingsService = {
|
||||
|
|
@ -95,7 +95,7 @@ describe('Claude', () => {
|
|||
|
||||
it('should resolve all required services', () => {
|
||||
const prompt = Resolve<IPrompt>(Services.IPrompt);
|
||||
const plugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
const plugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
const settingsService = Resolve<SettingsService>(Services.SettingsService);
|
||||
const streaming = Resolve<StreamingService>(Services.StreamingService);
|
||||
const functions = Resolve<AIFunctionDefinitions>(Services.AIFunctionDefinitions);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ describe('ClaudeConversationNamingService', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
mockPlugin = {};
|
||||
RegisterSingleton(Services.AIAgentPlugin, mockPlugin);
|
||||
RegisterSingleton(Services.VaultAIPlugin, mockPlugin);
|
||||
|
||||
// Mock SettingsService
|
||||
mockSettingsService = {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { RegisterSingleton, Resolve, DeregisterAllServices } from '../../Service
|
|||
import { Services } from '../../Services/Services';
|
||||
import { StreamingService } from '../../Services/StreamingService';
|
||||
import type { IPrompt } from '../../AIClasses/IPrompt';
|
||||
import type AIAgentPlugin from '../../main';
|
||||
import type VaultAIPlugin from '../../main';
|
||||
import { AIFunctionDefinitions } from '../../AIClasses/FunctionDefinitions/AIFunctionDefinitions';
|
||||
import { Conversation } from '../../Conversations/Conversation';
|
||||
import { ConversationContent } from '../../Conversations/ConversationContent';
|
||||
|
|
@ -28,9 +28,9 @@ describe('Gemini', () => {
|
|||
};
|
||||
RegisterSingleton(Services.IPrompt, mockPrompt);
|
||||
|
||||
// Mock AIAgentPlugin
|
||||
// Mock VaultAIPlugin
|
||||
mockPlugin = {};
|
||||
RegisterSingleton(Services.AIAgentPlugin, mockPlugin);
|
||||
RegisterSingleton(Services.VaultAIPlugin, mockPlugin);
|
||||
|
||||
// Mock SettingsService
|
||||
mockSettingsService = {
|
||||
|
|
@ -94,7 +94,7 @@ describe('Gemini', () => {
|
|||
|
||||
it('should resolve all required services', () => {
|
||||
const prompt = Resolve<IPrompt>(Services.IPrompt);
|
||||
const plugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
const plugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
const settingsService = Resolve<SettingsService>(Services.SettingsService);
|
||||
const streaming = Resolve<StreamingService>(Services.StreamingService);
|
||||
const functions = Resolve<AIFunctionDefinitions>(Services.AIFunctionDefinitions);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ describe('GeminiConversationNamingService', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
mockPlugin = {};
|
||||
RegisterSingleton(Services.AIAgentPlugin, mockPlugin);
|
||||
RegisterSingleton(Services.VaultAIPlugin, mockPlugin);
|
||||
|
||||
// Mock SettingsService
|
||||
mockSettingsService = {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { RegisterSingleton, Resolve, DeregisterAllServices } from '../../Service
|
|||
import { Services } from '../../Services/Services';
|
||||
import { StreamingService } from '../../Services/StreamingService';
|
||||
import type { IPrompt } from '../../AIClasses/IPrompt';
|
||||
import type AIAgentPlugin from '../../main';
|
||||
import type VaultAIPlugin from '../../main';
|
||||
import { AIFunctionDefinitions } from '../../AIClasses/FunctionDefinitions/AIFunctionDefinitions';
|
||||
import { Conversation } from '../../Conversations/Conversation';
|
||||
import { ConversationContent } from '../../Conversations/ConversationContent';
|
||||
|
|
@ -28,9 +28,9 @@ describe('OpenAI', () => {
|
|||
};
|
||||
RegisterSingleton(Services.IPrompt, mockPrompt);
|
||||
|
||||
// Mock AIAgentPlugin
|
||||
// Mock VaultAIPlugin
|
||||
mockPlugin = {};
|
||||
RegisterSingleton(Services.AIAgentPlugin, mockPlugin);
|
||||
RegisterSingleton(Services.VaultAIPlugin, mockPlugin);
|
||||
|
||||
// Mock SettingsService
|
||||
mockSettingsService = {
|
||||
|
|
@ -94,7 +94,7 @@ describe('OpenAI', () => {
|
|||
|
||||
it('should resolve all required services', () => {
|
||||
const prompt = Resolve<IPrompt>(Services.IPrompt);
|
||||
const plugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
|
||||
const plugin = Resolve<VaultAIPlugin>(Services.VaultAIPlugin);
|
||||
const settingsService = Resolve<SettingsService>(Services.SettingsService);
|
||||
const streaming = Resolve<StreamingService>(Services.StreamingService);
|
||||
const functions = Resolve<AIFunctionDefinitions>(Services.AIFunctionDefinitions);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ describe('OpenAIConversationNamingService', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
mockPlugin = {};
|
||||
RegisterSingleton(Services.AIAgentPlugin, mockPlugin);
|
||||
RegisterSingleton(Services.VaultAIPlugin, mockPlugin);
|
||||
|
||||
// Mock SettingsService
|
||||
mockSettingsService = {
|
||||
|
|
|
|||
|
|
@ -80,21 +80,21 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
const conversation = createTestConversation('My Test Note');
|
||||
const path = service.generateConversationPath(conversation);
|
||||
|
||||
expect(path).toBe('AI Agent/Conversations/My Test Note.json');
|
||||
expect(path).toBe('Vault AI/Conversations/My Test Note.json');
|
||||
});
|
||||
|
||||
it('should handle special characters in title', () => {
|
||||
const conversation = createTestConversation('Test: Special & Characters!');
|
||||
const path = service.generateConversationPath(conversation);
|
||||
|
||||
expect(path).toBe('AI Agent/Conversations/Test: Special & Characters!.json');
|
||||
expect(path).toBe('Vault AI/Conversations/Test: Special & Characters!.json');
|
||||
});
|
||||
|
||||
it('should handle empty title', () => {
|
||||
const conversation = createTestConversation('');
|
||||
const path = service.generateConversationPath(conversation);
|
||||
|
||||
expect(path).toBe('AI Agent/Conversations/.json');
|
||||
expect(path).toBe('Vault AI/Conversations/.json');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -104,9 +104,9 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
|
||||
const path = await service.saveConversation(conversation);
|
||||
|
||||
expect(path).toBe('AI Agent/Conversations/Test Save.json');
|
||||
expect(path).toBe('Vault AI/Conversations/Test Save.json');
|
||||
expect(mockFileSystemService.writeObjectToFile).toHaveBeenCalledWith(
|
||||
'AI Agent/Conversations/Test Save.json',
|
||||
'Vault AI/Conversations/Test Save.json',
|
||||
expect.objectContaining({
|
||||
title: 'Test Save',
|
||||
created: '2024-01-01T10:00:00.000Z',
|
||||
|
|
@ -160,7 +160,7 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
|
||||
await service.saveConversation(conversation);
|
||||
|
||||
expect(service.getCurrentConversationPath()).toBe('AI Agent/Conversations/First Save.json');
|
||||
expect(service.getCurrentConversationPath()).toBe('Vault AI/Conversations/First Save.json');
|
||||
});
|
||||
|
||||
it('should reuse current path on subsequent saves', async () => {
|
||||
|
|
@ -177,7 +177,7 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
|
||||
// Path should remain the same (uses cached path)
|
||||
expect(firstPath).toBe(secondPath);
|
||||
expect(secondPath).toBe('AI Agent/Conversations/Original Title.json');
|
||||
expect(secondPath).toBe('Vault AI/Conversations/Original Title.json');
|
||||
});
|
||||
|
||||
it('should serialize function calls correctly', async () => {
|
||||
|
|
@ -263,26 +263,26 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
const conversation = createTestConversation('Test Path');
|
||||
await service.saveConversation(conversation);
|
||||
|
||||
expect(service.getCurrentConversationPath()).toBe('AI Agent/Conversations/Test Path.json');
|
||||
expect(service.getCurrentConversationPath()).toBe('Vault AI/Conversations/Test Path.json');
|
||||
});
|
||||
|
||||
it('should return path after manual setting', () => {
|
||||
service.setCurrentConversationPath('AI Agent/Conversations/Manual.json');
|
||||
expect(service.getCurrentConversationPath()).toBe('AI Agent/Conversations/Manual.json');
|
||||
service.setCurrentConversationPath('Vault AI/Conversations/Manual.json');
|
||||
expect(service.getCurrentConversationPath()).toBe('Vault AI/Conversations/Manual.json');
|
||||
});
|
||||
});
|
||||
|
||||
describe('setCurrentConversationPath', () => {
|
||||
it('should set the current path', () => {
|
||||
service.setCurrentConversationPath('AI Agent/Conversations/Custom.json');
|
||||
expect(service.getCurrentConversationPath()).toBe('AI Agent/Conversations/Custom.json');
|
||||
service.setCurrentConversationPath('Vault AI/Conversations/Custom.json');
|
||||
expect(service.getCurrentConversationPath()).toBe('Vault AI/Conversations/Custom.json');
|
||||
});
|
||||
|
||||
it('should override previous path', () => {
|
||||
service.setCurrentConversationPath('AI Agent/Conversations/First.json');
|
||||
service.setCurrentConversationPath('AI Agent/Conversations/Second.json');
|
||||
service.setCurrentConversationPath('Vault AI/Conversations/First.json');
|
||||
service.setCurrentConversationPath('Vault AI/Conversations/Second.json');
|
||||
|
||||
expect(service.getCurrentConversationPath()).toBe('AI Agent/Conversations/Second.json');
|
||||
expect(service.getCurrentConversationPath()).toBe('Vault AI/Conversations/Second.json');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -307,7 +307,7 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
const conv2 = createTestConversation('Second');
|
||||
await service.saveConversation(conv2);
|
||||
|
||||
expect(service.getCurrentConversationPath()).toBe('AI Agent/Conversations/Second.json');
|
||||
expect(service.getCurrentConversationPath()).toBe('Vault AI/Conversations/Second.json');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -322,7 +322,7 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
|
||||
expect(result).toBe(true);
|
||||
expect(mockFileSystemService.deleteFile).toHaveBeenCalledWith(
|
||||
'AI Agent/Conversations/To Delete.json',
|
||||
'Vault AI/Conversations/To Delete.json',
|
||||
true
|
||||
);
|
||||
expect(service.getCurrentConversationPath()).toBeNull();
|
||||
|
|
@ -354,8 +354,8 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
describe('getAllConversations', () => {
|
||||
it('should load all conversations from directory', async () => {
|
||||
const mockFiles = [
|
||||
createMockFile('AI Agent/Conversations/conv1.json'),
|
||||
createMockFile('AI Agent/Conversations/conv2.json')
|
||||
createMockFile('Vault AI/Conversations/conv1.json'),
|
||||
createMockFile('Vault AI/Conversations/conv2.json')
|
||||
];
|
||||
|
||||
mockFileSystemService.listFilesInDirectory.mockResolvedValue(mockFiles);
|
||||
|
|
@ -400,14 +400,14 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
expect(conversations[0].title).toBe('Conversation 1');
|
||||
expect(conversations[1].title).toBe('Conversation 2');
|
||||
expect(mockFileSystemService.listFilesInDirectory).toHaveBeenCalledWith(
|
||||
'AI Agent/Conversations',
|
||||
'Vault AI/Conversations',
|
||||
false,
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it('should reconstruct conversation objects correctly', async () => {
|
||||
const mockFiles = [createMockFile('AI Agent/Conversations/test.json')];
|
||||
const mockFiles = [createMockFile('Vault AI/Conversations/test.json')];
|
||||
|
||||
mockFileSystemService.listFilesInDirectory.mockResolvedValue(mockFiles);
|
||||
mockFileSystemService.readObjectFromFile.mockResolvedValue({
|
||||
|
|
@ -449,8 +449,8 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
|
||||
it('should skip invalid conversation files', async () => {
|
||||
const mockFiles = [
|
||||
createMockFile('AI Agent/Conversations/valid.json'),
|
||||
createMockFile('AI Agent/Conversations/invalid.json')
|
||||
createMockFile('Vault AI/Conversations/valid.json'),
|
||||
createMockFile('Vault AI/Conversations/invalid.json')
|
||||
];
|
||||
|
||||
mockFileSystemService.listFilesInDirectory.mockResolvedValue(mockFiles);
|
||||
|
|
@ -482,7 +482,7 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
it('should reconstruct function call metadata', async () => {
|
||||
const mockFiles = [createMockFile('AI Agent/Conversations/with-functions.json')];
|
||||
const mockFiles = [createMockFile('Vault AI/Conversations/with-functions.json')];
|
||||
|
||||
mockFileSystemService.listFilesInDirectory.mockResolvedValue(mockFiles);
|
||||
mockFileSystemService.readObjectFromFile.mockResolvedValue({
|
||||
|
|
@ -529,13 +529,13 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
mockFileSystemService.moveFile.mockResolvedValue({ success: true });
|
||||
|
||||
await service.updateConversationTitle(
|
||||
'AI Agent/Conversations/Old Title.json',
|
||||
'Vault AI/Conversations/Old Title.json',
|
||||
'New Title'
|
||||
);
|
||||
|
||||
expect(mockFileSystemService.moveFile).toHaveBeenCalledWith(
|
||||
'AI Agent/Conversations/Old Title.json',
|
||||
'AI Agent/Conversations/New Title.json',
|
||||
'Vault AI/Conversations/Old Title.json',
|
||||
'Vault AI/Conversations/New Title.json',
|
||||
true
|
||||
);
|
||||
});
|
||||
|
|
@ -543,21 +543,21 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
it('should update current path if it matches old path', async () => {
|
||||
mockFileSystemService.moveFile.mockResolvedValue({ success: true });
|
||||
|
||||
service.setCurrentConversationPath('AI Agent/Conversations/Old.json');
|
||||
service.setCurrentConversationPath('Vault AI/Conversations/Old.json');
|
||||
|
||||
await service.updateConversationTitle('AI Agent/Conversations/Old.json', 'New');
|
||||
await service.updateConversationTitle('Vault AI/Conversations/Old.json', 'New');
|
||||
|
||||
expect(service.getCurrentConversationPath()).toBe('AI Agent/Conversations/New.json');
|
||||
expect(service.getCurrentConversationPath()).toBe('Vault AI/Conversations/New.json');
|
||||
});
|
||||
|
||||
it('should not update current path if it doesnt match', async () => {
|
||||
mockFileSystemService.moveFile.mockResolvedValue({ success: true });
|
||||
|
||||
service.setCurrentConversationPath('AI Agent/Conversations/Other.json');
|
||||
service.setCurrentConversationPath('Vault AI/Conversations/Other.json');
|
||||
|
||||
await service.updateConversationTitle('AI Agent/Conversations/Old.json', 'New');
|
||||
await service.updateConversationTitle('Vault AI/Conversations/Old.json', 'New');
|
||||
|
||||
expect(service.getCurrentConversationPath()).toBe('AI Agent/Conversations/Other.json');
|
||||
expect(service.getCurrentConversationPath()).toBe('Vault AI/Conversations/Other.json');
|
||||
});
|
||||
|
||||
it('should throw error when move fails', async () => {
|
||||
|
|
@ -567,7 +567,7 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
await expect(
|
||||
service.updateConversationTitle('AI Agent/Conversations/Old.json', 'New')
|
||||
service.updateConversationTitle('Vault AI/Conversations/Old.json', 'New')
|
||||
).rejects.toThrow('Failed to update conversation title: Destination already exists');
|
||||
});
|
||||
|
||||
|
|
@ -575,13 +575,13 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
mockFileSystemService.moveFile.mockResolvedValue({ success: true });
|
||||
|
||||
await service.updateConversationTitle(
|
||||
'AI Agent/Conversations/Old.json',
|
||||
'Vault AI/Conversations/Old.json',
|
||||
'New: Title & More!'
|
||||
);
|
||||
|
||||
expect(mockFileSystemService.moveFile).toHaveBeenCalledWith(
|
||||
'AI Agent/Conversations/Old.json',
|
||||
'AI Agent/Conversations/New: Title & More!.json',
|
||||
'Vault AI/Conversations/Old.json',
|
||||
'Vault AI/Conversations/New: Title & More!.json',
|
||||
true
|
||||
);
|
||||
});
|
||||
|
|
@ -594,7 +594,7 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
await service.saveConversation(conversation);
|
||||
|
||||
const savedPath = service.getCurrentConversationPath();
|
||||
expect(savedPath).toBe('AI Agent/Conversations/Original.json');
|
||||
expect(savedPath).toBe('Vault AI/Conversations/Original.json');
|
||||
|
||||
// Simulate loading conversations
|
||||
const mockFiles = [createMockFile(savedPath!)];
|
||||
|
|
@ -610,14 +610,14 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
mockFileSystemService.moveFile.mockResolvedValue({ success: true });
|
||||
await service.updateConversationTitle(savedPath!, 'Updated Title');
|
||||
|
||||
expect(service.getCurrentConversationPath()).toBe('AI Agent/Conversations/Updated Title.json');
|
||||
expect(service.getCurrentConversationPath()).toBe('Vault AI/Conversations/Updated Title.json');
|
||||
});
|
||||
|
||||
it('should handle save -> delete -> new save workflow', async () => {
|
||||
// First conversation
|
||||
const conv1 = createTestConversation('First');
|
||||
await service.saveConversation(conv1);
|
||||
expect(service.getCurrentConversationPath()).toBe('AI Agent/Conversations/First.json');
|
||||
expect(service.getCurrentConversationPath()).toBe('Vault AI/Conversations/First.json');
|
||||
|
||||
// Delete it
|
||||
mockFileSystemService.deleteFile.mockResolvedValue({ success: true });
|
||||
|
|
@ -627,7 +627,7 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
// New conversation
|
||||
const conv2 = createTestConversation('Second');
|
||||
await service.saveConversation(conv2);
|
||||
expect(service.getCurrentConversationPath()).toBe('AI Agent/Conversations/Second.json');
|
||||
expect(service.getCurrentConversationPath()).toBe('Vault AI/Conversations/Second.json');
|
||||
});
|
||||
|
||||
it('should preserve all conversation data through save/load cycle', async () => {
|
||||
|
|
@ -662,7 +662,7 @@ describe('ConversationFileSystemService - Integration Tests', () => {
|
|||
|
||||
// Simulate load
|
||||
mockFileSystemService.listFilesInDirectory.mockResolvedValue([
|
||||
createMockFile('AI Agent/Conversations/Complete Test.json')
|
||||
createMockFile('Vault AI/Conversations/Complete Test.json')
|
||||
]);
|
||||
mockFileSystemService.readObjectFromFile.mockResolvedValue(savedData);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
|
||||
import { SettingsService, IAIAgentSettings } from '../../Services/SettingsService';
|
||||
import { SettingsService, IVaultAISettings } from '../../Services/SettingsService';
|
||||
import { RegisterSingleton, DeregisterAllServices } from '../../Services/DependencyService';
|
||||
import { Services } from '../../Services/Services';
|
||||
import { AIProvider, AIProviderModel } from '../../Enums/ApiProvider';
|
||||
|
|
@ -9,11 +9,11 @@ describe('SettingsService', () => {
|
|||
let mockPlugin: any;
|
||||
|
||||
beforeEach(() => {
|
||||
// Mock AIAgentPlugin
|
||||
// Mock VaultAIPlugin
|
||||
mockPlugin = {
|
||||
saveData: vi.fn().mockResolvedValue(undefined)
|
||||
};
|
||||
RegisterSingleton(Services.AIAgentPlugin, mockPlugin);
|
||||
RegisterSingleton(Services.VaultAIPlugin, mockPlugin);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
|
@ -39,7 +39,7 @@ describe('SettingsService', () => {
|
|||
});
|
||||
|
||||
it('should merge loaded settings with defaults', () => {
|
||||
const loadedSettings: Partial<IAIAgentSettings> = {
|
||||
const loadedSettings: Partial<IVaultAISettings> = {
|
||||
firstTimeStart: false,
|
||||
model: AIProviderModel.GeminiFlash_2_5,
|
||||
apiKeys: {
|
||||
|
|
@ -51,7 +51,7 @@ describe('SettingsService', () => {
|
|||
snippetSizeLimit: 200
|
||||
};
|
||||
|
||||
settingsService = new SettingsService(loadedSettings as IAIAgentSettings);
|
||||
settingsService = new SettingsService(loadedSettings as IVaultAISettings);
|
||||
|
||||
expect(settingsService.settings.firstTimeStart).toBe(false);
|
||||
expect(settingsService.settings.model).toBe(AIProviderModel.GeminiFlash_2_5);
|
||||
|
|
@ -63,7 +63,7 @@ describe('SettingsService', () => {
|
|||
});
|
||||
|
||||
it('should handle partially loaded settings and fill missing properties with defaults', () => {
|
||||
const loadedSettings: Partial<IAIAgentSettings> = {
|
||||
const loadedSettings: Partial<IVaultAISettings> = {
|
||||
model: AIProviderModel.GPT_4o,
|
||||
apiKeys: {
|
||||
claude: '',
|
||||
|
|
@ -72,7 +72,7 @@ describe('SettingsService', () => {
|
|||
}
|
||||
};
|
||||
|
||||
settingsService = new SettingsService(loadedSettings as IAIAgentSettings);
|
||||
settingsService = new SettingsService(loadedSettings as IVaultAISettings);
|
||||
|
||||
expect(settingsService.settings.firstTimeStart).toBe(true); // Default
|
||||
expect(settingsService.settings.model).toBe(AIProviderModel.GPT_4o); // Loaded
|
||||
|
|
@ -86,7 +86,7 @@ describe('SettingsService', () => {
|
|||
|
||||
describe('getApiKeyForProvider', () => {
|
||||
beforeEach(() => {
|
||||
const loadedSettings: IAIAgentSettings = {
|
||||
const loadedSettings: IVaultAISettings = {
|
||||
firstTimeStart: false,
|
||||
model: AIProviderModel.ClaudeSonnet_4_5,
|
||||
apiKeys: {
|
||||
|
|
@ -126,7 +126,7 @@ describe('SettingsService', () => {
|
|||
|
||||
describe('getApiKeyForCurrentModel', () => {
|
||||
it('should return Claude key when current model is Claude', () => {
|
||||
const loadedSettings: IAIAgentSettings = {
|
||||
const loadedSettings: IVaultAISettings = {
|
||||
firstTimeStart: false,
|
||||
model: AIProviderModel.ClaudeSonnet_4_5,
|
||||
apiKeys: {
|
||||
|
|
@ -146,7 +146,7 @@ describe('SettingsService', () => {
|
|||
});
|
||||
|
||||
it('should return OpenAI key when current model is GPT', () => {
|
||||
const loadedSettings: IAIAgentSettings = {
|
||||
const loadedSettings: IVaultAISettings = {
|
||||
firstTimeStart: false,
|
||||
model: AIProviderModel.GPT_4o,
|
||||
apiKeys: {
|
||||
|
|
@ -166,7 +166,7 @@ describe('SettingsService', () => {
|
|||
});
|
||||
|
||||
it('should return Gemini key when current model is Gemini', () => {
|
||||
const loadedSettings: IAIAgentSettings = {
|
||||
const loadedSettings: IVaultAISettings = {
|
||||
firstTimeStart: false,
|
||||
model: AIProviderModel.GeminiFlash_2_5,
|
||||
apiKeys: {
|
||||
|
|
@ -211,7 +211,7 @@ describe('SettingsService', () => {
|
|||
|
||||
describe('setApiKeyForProvider', () => {
|
||||
beforeEach(() => {
|
||||
const loadedSettings: IAIAgentSettings = {
|
||||
const loadedSettings: IVaultAISettings = {
|
||||
firstTimeStart: false,
|
||||
model: AIProviderModel.ClaudeSonnet_4_5,
|
||||
apiKeys: {
|
||||
|
|
@ -265,7 +265,7 @@ describe('SettingsService', () => {
|
|||
|
||||
describe('saveSettings', () => {
|
||||
beforeEach(() => {
|
||||
const loadedSettings: IAIAgentSettings = {
|
||||
const loadedSettings: IVaultAISettings = {
|
||||
firstTimeStart: false,
|
||||
model: AIProviderModel.ClaudeSonnet_4_5,
|
||||
apiKeys: {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ describe('StatusBarService', () => {
|
|||
mockPlugin = {
|
||||
addStatusBarItem: vi.fn().mockReturnValue(mockStatusBarItem)
|
||||
};
|
||||
RegisterSingleton(Services.AIAgentPlugin, mockPlugin);
|
||||
RegisterSingleton(Services.VaultAIPlugin, mockPlugin);
|
||||
|
||||
service = new StatusBarService();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ describe('VaultCacheService - Integration Tests', () => {
|
|||
};
|
||||
|
||||
// Register dependencies
|
||||
RegisterSingleton(Services.AIAgentPlugin, mockPlugin as any);
|
||||
RegisterSingleton(Services.VaultAIPlugin, mockPlugin as any);
|
||||
RegisterSingleton(Services.VaultService, mockVaultService as any);
|
||||
|
||||
// Create fresh instance
|
||||
|
|
@ -191,7 +191,7 @@ describe('VaultCacheService - Integration Tests', () => {
|
|||
listDirectoryContents: mockListVaultContents
|
||||
};
|
||||
|
||||
RegisterSingleton(Services.AIAgentPlugin, mockPluginWithMetadata as any);
|
||||
RegisterSingleton(Services.VaultAIPlugin, mockPluginWithMetadata as any);
|
||||
RegisterSingleton(Services.VaultService, mockVaultServiceWithContent as any);
|
||||
|
||||
// Create new instance to trigger initialization
|
||||
|
|
@ -607,7 +607,7 @@ describe('VaultCacheService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
describe('folder event handling - exclusions', () => {
|
||||
it('should not cache excluded folders on create (AI Agent directory)', () => {
|
||||
it('should not cache excluded folders on create (Vault AI directory)', () => {
|
||||
// Mock VaultService to return null for excluded paths
|
||||
const mockVaultServiceWithExclusions = {
|
||||
registerFileEvents: vi.fn((handler: any) => {
|
||||
|
|
@ -616,22 +616,22 @@ describe('VaultCacheService - Integration Tests', () => {
|
|||
listDirectoryContents: vi.fn(async () => []),
|
||||
getAbstractFileByPath: vi.fn((path: string) => {
|
||||
// Return null for excluded paths (simulating VaultService exclusion logic)
|
||||
if (path.startsWith('AI Agent')) {
|
||||
if (path.startsWith('Vault AI')) {
|
||||
return null;
|
||||
}
|
||||
// Return a folder for allowed paths
|
||||
return createMockFolder(path);
|
||||
}),
|
||||
isExclusion: vi.fn((path: string) => {
|
||||
// Return true for AI Agent directory paths
|
||||
return path.startsWith('AI Agent');
|
||||
// Return true for Vault AI directory paths
|
||||
return path.startsWith('Vault AI');
|
||||
})
|
||||
};
|
||||
|
||||
RegisterSingleton(Services.VaultService, mockVaultServiceWithExclusions as any);
|
||||
vaultCacheService = new VaultCacheService();
|
||||
|
||||
const excludedFolder = createMockFolder('AI Agent/subfolder');
|
||||
const excludedFolder = createMockFolder('Vault AI/subfolder');
|
||||
fileEventHandler(FileEvent.Create, excludedFolder, { oldPath: '' });
|
||||
|
||||
const results = vaultCacheService.matchFolder('subfolder');
|
||||
|
|
@ -670,7 +670,7 @@ describe('VaultCacheService - Integration Tests', () => {
|
|||
})
|
||||
};
|
||||
|
||||
RegisterSingleton(Services.AIAgentPlugin, mockPluginWithExclusions as any);
|
||||
RegisterSingleton(Services.VaultAIPlugin, mockPluginWithExclusions as any);
|
||||
RegisterSingleton(Services.VaultService, mockVaultServiceWithExclusions as any);
|
||||
vaultCacheService = new VaultCacheService();
|
||||
|
||||
|
|
@ -693,15 +693,15 @@ describe('VaultCacheService - Integration Tests', () => {
|
|||
if (path === 'public-folder') {
|
||||
return createMockFolder(path);
|
||||
}
|
||||
// Second call (AI Agent/renamed) should fail
|
||||
if (path.startsWith('AI Agent')) {
|
||||
// Second call (Vault AI/renamed) should fail
|
||||
if (path.startsWith('Vault AI')) {
|
||||
return null;
|
||||
}
|
||||
return createMockFolder(path);
|
||||
}),
|
||||
isExclusion: vi.fn((path: string) => {
|
||||
// Return true for AI Agent paths
|
||||
return path.startsWith('AI Agent');
|
||||
// Return true for Vault AI paths
|
||||
return path.startsWith('Vault AI');
|
||||
})
|
||||
};
|
||||
|
||||
|
|
@ -717,7 +717,7 @@ describe('VaultCacheService - Integration Tests', () => {
|
|||
expect(results.length).toBeGreaterThan(0);
|
||||
|
||||
// Rename to excluded path
|
||||
const renamedFolder = createMockFolder('AI Agent/renamed');
|
||||
const renamedFolder = createMockFolder('Vault AI/renamed');
|
||||
fileEventHandler(FileEvent.Rename, renamedFolder, { oldPath: folder.path });
|
||||
|
||||
// Should not be in cache under new name
|
||||
|
|
@ -737,14 +737,14 @@ describe('VaultCacheService - Integration Tests', () => {
|
|||
}),
|
||||
listDirectoryContents: vi.fn(async () => []),
|
||||
getAbstractFileByPath: vi.fn((path: string) => {
|
||||
if (path.startsWith('AI Agent')) {
|
||||
if (path.startsWith('Vault AI')) {
|
||||
return null;
|
||||
}
|
||||
return createMockFolder(path);
|
||||
}),
|
||||
isExclusion: vi.fn((path: string) => {
|
||||
// Return true for AI Agent paths, false for others
|
||||
return path.startsWith('AI Agent');
|
||||
// Return true for Vault AI paths, false for others
|
||||
return path.startsWith('Vault AI');
|
||||
})
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { Path } from '../../Enums/Path';
|
|||
import { RegisterSingleton, DeregisterAllServices } from '../../Services/DependencyService';
|
||||
import { Services } from '../../Services/Services';
|
||||
import { SanitiserService } from '../../Services/SanitiserService';
|
||||
import { SettingsService, IAIAgentSettings } from '../../Services/SettingsService';
|
||||
import { SettingsService, IVaultAISettings } from '../../Services/SettingsService';
|
||||
import { AIProviderModel } from '../../Enums/ApiProvider';
|
||||
|
||||
/**
|
||||
|
|
@ -43,7 +43,7 @@ const mockFileManager = {
|
|||
};
|
||||
|
||||
// Create a mutable settings object that tests can modify
|
||||
const mockSettings: IAIAgentSettings = {
|
||||
const mockSettings: IVaultAISettings = {
|
||||
firstTimeStart: false,
|
||||
model: AIProviderModel.ClaudeSonnet_4_5,
|
||||
apiKeys: {
|
||||
|
|
@ -114,7 +114,7 @@ describe('VaultService - Integration Tests', () => {
|
|||
consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
// Register real dependencies in DependencyService
|
||||
RegisterSingleton(Services.AIAgentPlugin, mockPlugin as any);
|
||||
RegisterSingleton(Services.VaultAIPlugin, mockPlugin as any);
|
||||
RegisterSingleton(Services.FileManager, mockFileManager);
|
||||
RegisterSingleton(Services.SanitiserService, new SanitiserService());
|
||||
|
||||
|
|
@ -147,11 +147,11 @@ describe('VaultService - Integration Tests', () => {
|
|||
expect(mockVault.getMarkdownFiles).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('should filter out files in the AI Agent root directory by default', () => {
|
||||
it('should filter out files in the Vault AI root directory by default', () => {
|
||||
const files = [
|
||||
createMockFile('note1.md'),
|
||||
createMockFile('AI Agent/conversation.md'),
|
||||
createMockFile('AI Agent/subfolder/data.md')
|
||||
createMockFile('Vault AI/conversation.md'),
|
||||
createMockFile('Vault AI/subfolder/data.md')
|
||||
];
|
||||
mockVault.getMarkdownFiles.mockReturnValue(files);
|
||||
|
||||
|
|
@ -161,10 +161,10 @@ describe('VaultService - Integration Tests', () => {
|
|||
expect(result[0].path).toBe('note1.md');
|
||||
});
|
||||
|
||||
it('should allow access to AI Agent directory when allowAccessToPluginRoot is true', () => {
|
||||
it('should allow access to Vault AI directory when allowAccessToPluginRoot is true', () => {
|
||||
const files = [
|
||||
createMockFile('note1.md'),
|
||||
createMockFile('AI Agent/conversation.md')
|
||||
createMockFile('Vault AI/conversation.md')
|
||||
];
|
||||
mockVault.getMarkdownFiles.mockReturnValue(files);
|
||||
|
||||
|
|
@ -202,9 +202,9 @@ describe('VaultService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
it('should return null and log error when path is excluded', () => {
|
||||
mockVault.getAbstractFileByPath.mockReturnValue(createMockFile('AI Agent/test.md'));
|
||||
mockVault.getAbstractFileByPath.mockReturnValue(createMockFile('Vault AI/test.md'));
|
||||
|
||||
const result = vaultService.getAbstractFileByPath('AI Agent/test.md', false);
|
||||
const result = vaultService.getAbstractFileByPath('Vault AI/test.md', false);
|
||||
|
||||
expect(result).toBeNull();
|
||||
expect(consoleErrorSpy).toHaveBeenCalled();
|
||||
|
|
@ -223,29 +223,29 @@ describe('VaultService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
it('should allow access to excluded paths when allowAccessToPluginRoot is true', () => {
|
||||
const mockFile = createMockFile('AI Agent/conversation.md');
|
||||
const mockFile = createMockFile('Vault AI/conversation.md');
|
||||
mockVault.getAbstractFileByPath.mockReturnValue(mockFile);
|
||||
|
||||
const result = vaultService.getAbstractFileByPath('AI Agent/conversation.md', true);
|
||||
const result = vaultService.getAbstractFileByPath('Vault AI/conversation.md', true);
|
||||
|
||||
expect(result).toBe(mockFile);
|
||||
});
|
||||
|
||||
it('should exclude the AI Agent directory itself', () => {
|
||||
const mockFolder = createMockFolder('AI Agent');
|
||||
it('should exclude the Vault AI directory itself', () => {
|
||||
const mockFolder = createMockFolder('Vault AI');
|
||||
mockVault.getAbstractFileByPath.mockReturnValue(mockFolder);
|
||||
|
||||
const result = vaultService.getAbstractFileByPath('AI Agent', false);
|
||||
const result = vaultService.getAbstractFileByPath('Vault AI', false);
|
||||
|
||||
expect(result).toBeNull();
|
||||
expect(consoleErrorSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should allow access to AI Agent directory when allowAccessToPluginRoot is true', () => {
|
||||
const mockFolder = createMockFolder('AI Agent');
|
||||
it('should allow access to Vault AI directory when allowAccessToPluginRoot is true', () => {
|
||||
const mockFolder = createMockFolder('Vault AI');
|
||||
mockVault.getAbstractFileByPath.mockReturnValue(mockFolder);
|
||||
|
||||
const result = vaultService.getAbstractFileByPath('AI Agent', true);
|
||||
const result = vaultService.getAbstractFileByPath('Vault AI', true);
|
||||
|
||||
expect(result).toBe(mockFolder);
|
||||
});
|
||||
|
|
@ -261,7 +261,7 @@ describe('VaultService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
it('should return false when file is excluded', async () => {
|
||||
const result = await vaultService.exists('AI Agent/test.md', false);
|
||||
const result = await vaultService.exists('Vault AI/test.md', false);
|
||||
|
||||
expect(result).toBe(false);
|
||||
expect(consoleErrorSpy).toHaveBeenCalled();
|
||||
|
|
@ -296,7 +296,7 @@ describe('VaultService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
it('should return empty string and log error when file is excluded', async () => {
|
||||
const mockFile = createMockFile('AI Agent/test.md');
|
||||
const mockFile = createMockFile('Vault AI/test.md');
|
||||
|
||||
const result = await vaultService.read(mockFile, false);
|
||||
|
||||
|
|
@ -306,7 +306,7 @@ describe('VaultService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
it('should allow reading excluded files when allowAccessToPluginRoot is true', async () => {
|
||||
const mockFile = createMockFile('AI Agent/test.md');
|
||||
const mockFile = createMockFile('Vault AI/test.md');
|
||||
mockVault.read.mockResolvedValue('content');
|
||||
|
||||
const result = await vaultService.read(mockFile, true);
|
||||
|
|
@ -331,7 +331,7 @@ describe('VaultService - Integration Tests', () => {
|
|||
|
||||
it('should throw error when trying to create file in excluded path', async () => {
|
||||
await expect(
|
||||
vaultService.create('AI Agent/test.md', 'content', false)
|
||||
vaultService.create('Vault AI/test.md', 'content', false)
|
||||
).rejects.toThrow('Plugin attempted to create a file that is in the exclusion list');
|
||||
});
|
||||
|
||||
|
|
@ -374,7 +374,7 @@ describe('VaultService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
it('should not modify file and log error when file is excluded', async () => {
|
||||
const mockFile = createMockFile('AI Agent/test.md');
|
||||
const mockFile = createMockFile('Vault AI/test.md');
|
||||
|
||||
await vaultService.modify(mockFile, 'new content', false);
|
||||
|
||||
|
|
@ -409,7 +409,7 @@ describe('VaultService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
it('should not delete file and return error when excluded', async () => {
|
||||
const mockFile = createMockFile('AI Agent/test.md');
|
||||
const mockFile = createMockFile('Vault AI/test.md');
|
||||
|
||||
const result = await vaultService.delete(mockFile, false);
|
||||
|
||||
|
|
@ -460,7 +460,7 @@ describe('VaultService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
it('should return error when source file is excluded', async () => {
|
||||
const result = await vaultService.move('AI Agent/test.md', 'dest.md', false);
|
||||
const result = await vaultService.move('Vault AI/test.md', 'dest.md', false);
|
||||
|
||||
expect(result).toEqual({ success: false, error: 'Source file is in exclusion list' });
|
||||
expect(mockFileManager.renameFile).not.toHaveBeenCalled();
|
||||
|
|
@ -515,7 +515,7 @@ describe('VaultService - Integration Tests', () => {
|
|||
|
||||
it('should throw error when trying to create folder in excluded path', async () => {
|
||||
await expect(
|
||||
vaultService.createFolder('AI Agent/subfolder', false)
|
||||
vaultService.createFolder('Vault AI/subfolder', false)
|
||||
).rejects.toThrow('Plugin attempted to create a folder that is in the exclusion list');
|
||||
});
|
||||
});
|
||||
|
|
@ -586,9 +586,9 @@ describe('VaultService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
it('should respect allowAccessToPluginRoot parameter when accessing directory', async () => {
|
||||
const file1 = createMockFile('AI Agent/test.md');
|
||||
const file2 = createMockFile('AI Agent/notes.md');
|
||||
const agentFolder = createMockFolder('AI Agent', [file1, file2]);
|
||||
const file1 = createMockFile('Vault AI/test.md');
|
||||
const file2 = createMockFile('Vault AI/notes.md');
|
||||
const agentFolder = createMockFolder('Vault AI', [file1, file2]);
|
||||
|
||||
mockVault.getAbstractFileByPath.mockReturnValue(agentFolder);
|
||||
|
||||
|
|
@ -596,19 +596,19 @@ describe('VaultService - Integration Tests', () => {
|
|||
const getAbstractFileSpy = vi.spyOn(vaultService, 'getAbstractFileByPath');
|
||||
|
||||
// Call with allowAccessToPluginRoot = false (should block access)
|
||||
await vaultService.listFilesInDirectory('AI Agent', true, false);
|
||||
await vaultService.listFilesInDirectory('Vault AI', true, false);
|
||||
|
||||
// Verify getAbstractFileByPath was called with the correct parameter
|
||||
expect(getAbstractFileSpy).toHaveBeenCalledWith('AI Agent', false);
|
||||
expect(getAbstractFileSpy).toHaveBeenCalledWith('Vault AI', false);
|
||||
|
||||
// Reset
|
||||
getAbstractFileSpy.mockClear();
|
||||
|
||||
// Call with allowAccessToPluginRoot = true (should allow access)
|
||||
await vaultService.listFilesInDirectory('AI Agent', true, true);
|
||||
await vaultService.listFilesInDirectory('Vault AI', true, true);
|
||||
|
||||
// Verify getAbstractFileByPath was called with the correct parameter
|
||||
expect(getAbstractFileSpy).toHaveBeenCalledWith('AI Agent', true);
|
||||
expect(getAbstractFileSpy).toHaveBeenCalledWith('Vault AI', true);
|
||||
});
|
||||
|
||||
it('should not access excluded directory when allowAccessToPluginRoot is false', async () => {
|
||||
|
|
@ -618,11 +618,11 @@ describe('VaultService - Integration Tests', () => {
|
|||
// Create a spy to verify the correct parameter is passed
|
||||
const getAbstractFileSpy = vi.spyOn(vaultService, 'getAbstractFileByPath');
|
||||
|
||||
// Try to list files in AI Agent directory with allowAccessToPluginRoot = false
|
||||
const result = await vaultService.listFilesInDirectory('AI Agent', true, false);
|
||||
// Try to list files in Vault AI directory with allowAccessToPluginRoot = false
|
||||
const result = await vaultService.listFilesInDirectory('Vault AI', true, false);
|
||||
|
||||
// Should call getAbstractFileByPath with false (not hardcoded true)
|
||||
expect(getAbstractFileSpy).toHaveBeenCalledWith('AI Agent', false);
|
||||
expect(getAbstractFileSpy).toHaveBeenCalledWith('Vault AI', false);
|
||||
|
||||
// Should return empty array since directory is excluded
|
||||
expect(result).toEqual([]);
|
||||
|
|
@ -697,33 +697,33 @@ describe('VaultService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
it('should respect allowAccessToPluginRoot parameter', async () => {
|
||||
const agentFolder = createMockFolder('AI Agent', []);
|
||||
const agentFolder = createMockFolder('Vault AI', []);
|
||||
const notesFolder = createMockFolder('notes', []);
|
||||
const rootFolder = createMockFolder('/', [agentFolder, notesFolder]);
|
||||
|
||||
mockVault.getAbstractFileByPath.mockImplementation((path: string) => {
|
||||
if (path === '/' || path === '') return rootFolder;
|
||||
// AI Agent blocked when allowAccessToPluginRoot = false
|
||||
if (path === 'AI Agent') return null;
|
||||
// Vault AI blocked when allowAccessToPluginRoot = false
|
||||
if (path === 'Vault AI') return null;
|
||||
if (path === 'notes') return notesFolder;
|
||||
return null;
|
||||
});
|
||||
|
||||
// With allowAccessToPluginRoot = false (should exclude AI Agent)
|
||||
// With allowAccessToPluginRoot = false (should exclude Vault AI)
|
||||
const result1 = await vaultService.listFoldersInDirectory('/', true, false);
|
||||
expect(result1.some((folder) => folder.path === 'AI Agent')).toBe(false);
|
||||
expect(result1.some((folder) => folder.path === 'Vault AI')).toBe(false);
|
||||
expect(result1.some((folder) => folder.path === 'notes')).toBe(true);
|
||||
|
||||
// With allowAccessToPluginRoot = true (should include AI Agent)
|
||||
// With allowAccessToPluginRoot = true (should include Vault AI)
|
||||
mockVault.getAbstractFileByPath.mockImplementation((path: string) => {
|
||||
if (path === '/' || path === '') return rootFolder;
|
||||
if (path === 'AI Agent') return agentFolder; // Now allowed
|
||||
if (path === 'Vault AI') return agentFolder; // Now allowed
|
||||
if (path === 'notes') return notesFolder;
|
||||
return null;
|
||||
});
|
||||
|
||||
const result2 = await vaultService.listFoldersInDirectory('/', true, true);
|
||||
expect(result2.some((folder) => folder.path === 'AI Agent')).toBe(true);
|
||||
expect(result2.some((folder) => folder.path === 'Vault AI')).toBe(true);
|
||||
expect(result2.some((folder) => folder.path === 'notes')).toBe(true);
|
||||
});
|
||||
|
||||
|
|
@ -905,19 +905,19 @@ describe('VaultService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
it('should not log errors when vault contains excluded directories', async () => {
|
||||
// Setup: Create a vault structure with excluded "AI Agent" directory
|
||||
// Setup: Create a vault structure with excluded "Vault AI" directory
|
||||
const normalFile = createMockFile('notes/document.md');
|
||||
const excludedFile = createMockFile('AI Agent/secret.md');
|
||||
const excludedFile = createMockFile('Vault AI/secret.md');
|
||||
const notesFolder = createMockFolder('notes', [normalFile]);
|
||||
const excludedFolder = createMockFolder('AI Agent', [excludedFile]);
|
||||
const excludedFolder = createMockFolder('Vault AI', [excludedFile]);
|
||||
const rootFolder = createMockFolder('/', [normalFile, notesFolder, excludedFolder]);
|
||||
|
||||
mockVault.getAbstractFileByPath.mockImplementation((path: string) => {
|
||||
if (path === '/' || path === '') return rootFolder;
|
||||
if (path === 'notes') return notesFolder;
|
||||
if (path === 'notes/document.md') return normalFile;
|
||||
// AI Agent directory should be blocked by getAbstractFileByPath
|
||||
if (path === 'AI Agent') return null;
|
||||
// Vault AI directory should be blocked by getAbstractFileByPath
|
||||
if (path === 'Vault AI') return null;
|
||||
return null;
|
||||
});
|
||||
|
||||
|
|
@ -941,16 +941,16 @@ describe('VaultService - Integration Tests', () => {
|
|||
});
|
||||
|
||||
it('should respect allowAccessToPluginRoot parameter when true', async () => {
|
||||
// Setup: Create vault with AI Agent directory
|
||||
const agentFile = createMockFile('AI Agent/notes.md');
|
||||
// Setup: Create vault with Vault AI directory
|
||||
const agentFile = createMockFile('Vault AI/notes.md');
|
||||
const normalFile = createMockFile('normal.md');
|
||||
const agentFolder = createMockFolder('AI Agent', [agentFile]);
|
||||
const agentFolder = createMockFolder('Vault AI', [agentFile]);
|
||||
const rootFolder = createMockFolder('/', [normalFile, agentFolder]);
|
||||
|
||||
mockVault.getAbstractFileByPath.mockImplementation((path: string) => {
|
||||
if (path === '/' || path === '') return rootFolder;
|
||||
if (path === 'AI Agent') return agentFolder;
|
||||
if (path === 'AI Agent/notes.md') return agentFile;
|
||||
if (path === 'Vault AI') return agentFolder;
|
||||
if (path === 'Vault AI/notes.md') return agentFile;
|
||||
if (path === 'normal.md') return normalFile;
|
||||
return null;
|
||||
});
|
||||
|
|
@ -960,23 +960,23 @@ describe('VaultService - Integration Tests', () => {
|
|||
// Search with allowAccessToPluginRoot = true
|
||||
const results = await vaultService.searchVaultFiles('searchable', true);
|
||||
|
||||
// Should include files from AI Agent directory
|
||||
// Should include files from Vault AI directory
|
||||
const paths = results.map(r => r.file.path);
|
||||
expect(paths).toContain('AI Agent/notes.md');
|
||||
expect(paths).toContain('Vault AI/notes.md');
|
||||
expect(paths).toContain('normal.md');
|
||||
});
|
||||
|
||||
it('should exclude AI Agent directory when allowAccessToPluginRoot is false', async () => {
|
||||
// Setup: Create vault with AI Agent directory
|
||||
const agentFile = createMockFile('AI Agent/notes.md');
|
||||
it('should exclude Vault AI directory when allowAccessToPluginRoot is false', async () => {
|
||||
// Setup: Create vault with Vault AI directory
|
||||
const agentFile = createMockFile('Vault AI/notes.md');
|
||||
const normalFile = createMockFile('normal.md');
|
||||
const agentFolder = createMockFolder('AI Agent', [agentFile]);
|
||||
const agentFolder = createMockFolder('Vault AI', [agentFile]);
|
||||
const rootFolder = createMockFolder('/', [normalFile, agentFolder]);
|
||||
|
||||
mockVault.getAbstractFileByPath.mockImplementation((path: string) => {
|
||||
if (path === '/' || path === '') return rootFolder;
|
||||
// When allowAccessToPluginRoot is false, AI Agent should be blocked
|
||||
if (path === 'AI Agent') return null;
|
||||
// When allowAccessToPluginRoot is false, Vault AI should be blocked
|
||||
if (path === 'Vault AI') return null;
|
||||
if (path === 'normal.md') return normalFile;
|
||||
return null;
|
||||
});
|
||||
|
|
@ -986,9 +986,9 @@ describe('VaultService - Integration Tests', () => {
|
|||
// Search with allowAccessToPluginRoot = false (default)
|
||||
const results = await vaultService.searchVaultFiles('searchable', false);
|
||||
|
||||
// Should NOT include files from AI Agent directory
|
||||
// Should NOT include files from Vault AI directory
|
||||
const paths = results.map(r => r.file.path);
|
||||
expect(paths).not.toContain('AI Agent/notes.md');
|
||||
expect(paths).not.toContain('Vault AI/notes.md');
|
||||
expect(paths).toContain('normal.md');
|
||||
});
|
||||
|
||||
|
|
@ -1057,8 +1057,8 @@ describe('VaultService - Integration Tests', () => {
|
|||
expect(await vaultService.exists('temp/sub/file.md')).toBe(false);
|
||||
});
|
||||
|
||||
it('should always exclude AI Agent root by default', async () => {
|
||||
const result = await vaultService.exists('AI Agent/file.md', false);
|
||||
it('should always exclude Vault AI root by default', async () => {
|
||||
const result = await vaultService.exists('Vault AI/file.md', false);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
|
@ -1166,17 +1166,17 @@ describe('VaultService - Integration Tests', () => {
|
|||
|
||||
it('should filter out excluded files and folders', async () => {
|
||||
const publicNote = createMockFile('public/note.md');
|
||||
const agentNote = createMockFile('AI Agent/conversation.md');
|
||||
const agentNote = createMockFile('Vault AI/conversation.md');
|
||||
const privateNote = createMockFile('private/secret.md');
|
||||
const publicFolder = createMockFolder('public', [publicNote]);
|
||||
const agentFolder = createMockFolder('AI Agent', [agentNote]);
|
||||
const agentFolder = createMockFolder('Vault AI', [agentNote]);
|
||||
const privateFolder = createMockFolder('private', [privateNote]);
|
||||
const rootFolder = createMockFolder('/', [publicNote, agentNote, privateNote, publicFolder, agentFolder, privateFolder]);
|
||||
|
||||
mockVault.getAbstractFileByPath.mockImplementation((path: string) => {
|
||||
if (path === '/' || path === '') return rootFolder;
|
||||
if (path === 'public') return publicFolder;
|
||||
if (path === 'AI Agent') return null; // Excluded by default
|
||||
if (path === 'Vault AI') return null; // Excluded by default
|
||||
if (path === 'private') return privateFolder;
|
||||
return null;
|
||||
});
|
||||
|
|
@ -1186,54 +1186,54 @@ describe('VaultService - Integration Tests', () => {
|
|||
const result = await vaultService.listDirectoryContents(Path.Root, true, false);
|
||||
|
||||
// Should include: public/note.md and public folder
|
||||
// Should exclude: AI Agent folder (default exclusion), private/** content
|
||||
// Should exclude: Vault AI folder (default exclusion), private/** content
|
||||
expect(result.some((item: any) => item.path === 'public/note.md')).toBe(true);
|
||||
expect(result.some((item: any) => item.path === 'public')).toBe(true);
|
||||
expect(result.some((item: any) => item.path === 'AI Agent/conversation.md')).toBe(false);
|
||||
expect(result.some((item: any) => item.path === 'Vault AI/conversation.md')).toBe(false);
|
||||
expect(result.some((item: any) => item.path === 'private/secret.md')).toBe(false);
|
||||
expect(result.some((item: any) => item.path === 'private')).toBe(true); // Folder itself not excluded by 'private/**'
|
||||
});
|
||||
|
||||
it('should exclude the AI Agent directory itself from folder listings', async () => {
|
||||
it('should exclude the Vault AI directory itself from folder listings', async () => {
|
||||
const publicNote = createMockFile('public/note.md');
|
||||
const publicFolder = createMockFolder('public', [publicNote]);
|
||||
const agentFolder = createMockFolder('AI Agent', []);
|
||||
const agentFolder = createMockFolder('Vault AI', []);
|
||||
const notesFolder = createMockFolder('notes', []);
|
||||
const rootFolder = createMockFolder('/', [publicNote, publicFolder, agentFolder, notesFolder]);
|
||||
|
||||
mockVault.getAbstractFileByPath.mockImplementation((path: string) => {
|
||||
if (path === '/' || path === '') return rootFolder;
|
||||
if (path === 'public') return publicFolder;
|
||||
if (path === 'AI Agent') return null; // Excluded by default
|
||||
if (path === 'Vault AI') return null; // Excluded by default
|
||||
if (path === 'notes') return notesFolder;
|
||||
return null;
|
||||
});
|
||||
|
||||
const result = await vaultService.listDirectoryContents(Path.Root, true, false);
|
||||
|
||||
// AI Agent directory itself should be excluded
|
||||
expect(result.some((item: any) => item.path === 'AI Agent')).toBe(false);
|
||||
// Vault AI directory itself should be excluded
|
||||
expect(result.some((item: any) => item.path === 'Vault AI')).toBe(false);
|
||||
// Other folders should be included
|
||||
expect(result.some((item: any) => item.path === 'public')).toBe(true);
|
||||
expect(result.some((item: any) => item.path === 'notes')).toBe(true);
|
||||
});
|
||||
|
||||
it('should include AI Agent directory when allowAccessToPluginRoot is true', async () => {
|
||||
it('should include Vault AI directory when allowAccessToPluginRoot is true', async () => {
|
||||
const note = createMockFile('note.md');
|
||||
const agentNote = createMockFile('AI Agent/conversation.md');
|
||||
const agentFolder = createMockFolder('AI Agent', [agentNote]);
|
||||
const agentNote = createMockFile('Vault AI/conversation.md');
|
||||
const agentFolder = createMockFolder('Vault AI', [agentNote]);
|
||||
const rootFolder = createMockFolder('/', [note, agentFolder]);
|
||||
|
||||
mockVault.getAbstractFileByPath.mockImplementation((path: string) => {
|
||||
if (path === '/' || path === '') return rootFolder;
|
||||
if (path === 'AI Agent') return agentFolder; // Allowed with flag
|
||||
if (path === 'Vault AI') return agentFolder; // Allowed with flag
|
||||
return null;
|
||||
});
|
||||
|
||||
const result = await vaultService.listDirectoryContents(Path.Root, true, true);
|
||||
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result.some((item: any) => item.path === 'AI Agent/conversation.md')).toBe(true);
|
||||
expect(result.some((item: any) => item.path === 'Vault AI/conversation.md')).toBe(true);
|
||||
});
|
||||
|
||||
it('should return empty array when vault is empty', async () => {
|
||||
|
|
|
|||
12
main.ts
12
main.ts
|
|
@ -1,7 +1,7 @@
|
|||
import { WorkspaceLeaf, Plugin } from "obsidian";
|
||||
import { MainView, VIEW_TYPE_MAIN } from "Views/MainView";
|
||||
import { RegisterDependencies, RegisterPlugin } from "Services/ServiceRegistration";
|
||||
import { AIAgentSettingTab } from "AIAgentSettingTab";
|
||||
import { VaultAISettingTab } from "VaultAISettingTab";
|
||||
import { Services } from "Services/Services";
|
||||
import type { StatusBarService } from "Services/StatusBarService";
|
||||
import { DeregisterAllServices, Resolve } from "Services/DependencyService";
|
||||
|
|
@ -10,7 +10,7 @@ import { Path } from "Enums/Path";
|
|||
import { Copy } from "Enums/Copy";
|
||||
import type { SettingsService } from "Services/SettingsService";
|
||||
|
||||
export default class AIAgentPlugin extends Plugin {
|
||||
export default class VaultAIPlugin extends Plugin {
|
||||
|
||||
public async onload() {
|
||||
// KaTeX CSS is bundled with the plugin to comply with CSP
|
||||
|
|
@ -27,18 +27,18 @@ export default class AIAgentPlugin extends Plugin {
|
|||
);
|
||||
|
||||
this.addCommand({
|
||||
id: "ai-agent",
|
||||
name: "AI Agent",
|
||||
id: "vault-ai",
|
||||
name: "Vault AI",
|
||||
callback: () => {
|
||||
this.activateView();
|
||||
}
|
||||
});
|
||||
|
||||
this.addRibbonIcon("sparkles", "AI Agent", (_: MouseEvent) => {
|
||||
this.addRibbonIcon("sparkles", "Vault AI", (_: MouseEvent) => {
|
||||
this.activateView();
|
||||
});
|
||||
|
||||
this.addSettingTab(new AIAgentSettingTab());
|
||||
this.addSettingTab(new VaultAISettingTab());
|
||||
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
await this.setup();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"id": "ai_agent",
|
||||
"name": "AI Agent",
|
||||
"id": "vault-ai",
|
||||
"name": "Vault AI",
|
||||
"version": "1.0.0",
|
||||
"minAppVersion": "1.9.14",
|
||||
"description": "AI powered agent assistant.",
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "ai_agent",
|
||||
"name": "vault-ai",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ai_agent",
|
||||
"name": "vault-ai",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "ai_agent",
|
||||
"name": "vault-ai",
|
||||
"version": "1.0.0",
|
||||
"description": "AI powered agent assistant.",
|
||||
"main": "main.js",
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
/* Main View Customization */
|
||||
/* ============================== */
|
||||
|
||||
.workspace-leaf-content[data-type="ai-agent-main-view"] {
|
||||
.workspace-leaf-content[data-type="vault-ai-main-view"] {
|
||||
background-color: var(--background-secondary);
|
||||
}
|
||||
|
||||
.workspace-leaf-content[data-type="ai-agent-main-view"] .view-content {
|
||||
.workspace-leaf-content[data-type="vault-ai-main-view"] .view-content {
|
||||
align-self: center;
|
||||
max-width: 1000px;
|
||||
background-color: var(--background-secondary);
|
||||
|
|
|
|||
Loading…
Reference in a new issue