mirror of
https://github.com/andy-stack/vaultkeeper-ai.git
synced 2026-07-22 06:42:03 +00:00
Introduce a new AbortService to centralize cancellation logic across all async operations, replacing scattered AbortSignal parameters with a unified singleton service. This improves maintainability and provides consistent cancellation behavior throughout the application. Key changes: - Add AbortService for centralized abort signal management with automatic cleanup - Refactor all AI providers (Claude, Gemini, OpenAI) to use AbortService instead of passing AbortSignal parameters - Update streaming operations to use centralized abort handling - Add CancellationIndicator component to show visual feedback during operation cancellation - Rename ChatAreaThought to ThoughtIndicator for better semantic clarity - Add Environment enum for consistent environment detection - Enhance ChatService lifecycle with proper cancellation state management - Remove scattered abort-related UI selectors and error messages in favor of dedicated indicator - Add safeContinue() factory method to ConversationContent for internal continuations - Update all tests to reflect new abort handling architecture This change simplifies the API surface by removing AbortSignal parameters from method signatures while improving the user experience with clearer cancellation feedback.
103 lines
No EOL
6.3 KiB
TypeScript
103 lines
No EOL
6.3 KiB
TypeScript
import { AIProvider, fromModel } from "Enums/ApiProvider";
|
|
import type VaultkeeperAIPlugin from "main";
|
|
import { RegisterSingleton, RegisterTransient, Resolve } from "./DependencyService";
|
|
import { Services } from "./Services";
|
|
import { AIPrompt, type IPrompt } from "AIClasses/IPrompt";
|
|
import type { IAIClass } from "AIClasses/IAIClass";
|
|
import type { IConversationNamingService } from "AIClasses/IConversationNamingService";
|
|
import { Gemini } from "AIClasses/Gemini/Gemini";
|
|
import { GeminiConversationNamingService } from "AIClasses/Gemini/GeminiConversationNamingService";
|
|
import { StreamingMarkdownService } from "./StreamingMarkdownService";
|
|
import { FileSystemService } from "./FileSystemService";
|
|
import { ConversationFileSystemService } from "./ConversationFileSystemService";
|
|
import { ConversationHistoryModal } from "Modals/ConversationHistoryModal";
|
|
import { AIFunctionService } from "./AIFunctionService";
|
|
import { StreamingService } from "./StreamingService";
|
|
import { AIFunctionDefinitions } from "AIClasses/FunctionDefinitions/AIFunctionDefinitions";
|
|
import { WorkSpaceService } from "./WorkSpaceService";
|
|
import { ChatService } from "./ChatService";
|
|
import { ConversationNamingService } from "./ConversationNamingService";
|
|
import { VaultService } from "./VaultService";
|
|
import type { ITokenService } from "AIClasses/ITokenService";
|
|
import { GeminiTokenService } from "AIClasses/Gemini/GeminiTokenService";
|
|
import { StatusBarService } from "./StatusBarService";
|
|
import { ClaudeTokenService } from "AIClasses/Claude/ClaudeTokenService";
|
|
import { OpenAITokenService } from "AIClasses/OpenAI/OpenAITokenService";
|
|
import { ClaudeConversationNamingService } from "AIClasses/Claude/ClaudeConversationNamingService";
|
|
import { Claude } from "AIClasses/Claude/Claude";
|
|
import { OpenAIConversationNamingService } from "AIClasses/OpenAI/OpenAIConversationNamingService";
|
|
import { OpenAI } from "AIClasses/OpenAI/OpenAI";
|
|
import { SanitiserService } from "./SanitiserService";
|
|
import { VaultCacheService } from "./VaultCacheService";
|
|
import { UserInputService } from "./UserInputService";
|
|
import { SearchStateStore } from "Stores/SearchStateStore";
|
|
import { InputService } from "./InputService";
|
|
import { HTMLService } from "./HTMLService";
|
|
import { SettingsService, type IVaultkeeperAISettings } from "./SettingsService";
|
|
import { HelpModal } from "Modals/HelpModal";
|
|
import { EventService } from "./EventService";
|
|
import { DiffService } from "./DiffService";
|
|
import { AbortService } from "./AbortService";
|
|
|
|
export async function RegisterPlugin(plugin: VaultkeeperAIPlugin) {
|
|
RegisterSingleton<VaultkeeperAIPlugin>(Services.VaultkeeperAIPlugin, plugin);
|
|
RegisterSingleton<SettingsService>(Services.SettingsService, new SettingsService(await plugin.loadData() as Partial<IVaultkeeperAISettings>));
|
|
}
|
|
|
|
export function RegisterDependencies() {
|
|
RegisterSingleton<EventService>(Services.EventService, new EventService());
|
|
RegisterSingleton<AbortService>(Services.AbortService, new AbortService());
|
|
RegisterSingleton<StatusBarService>(Services.StatusBarService, new StatusBarService());
|
|
RegisterSingleton<HTMLService>(Services.HTMLService, new HTMLService());
|
|
RegisterSingleton<SanitiserService>(Services.SanitiserService, new SanitiserService());
|
|
RegisterSingleton<DiffService>(Services.DiffService, new DiffService());
|
|
RegisterSingleton<VaultService>(Services.VaultService, new VaultService());
|
|
RegisterSingleton<VaultCacheService>(Services.VaultCacheService, new VaultCacheService());
|
|
RegisterSingleton<SearchStateStore>(Services.SearchStateStore, new SearchStateStore());
|
|
RegisterSingleton<UserInputService>(Services.UserInputService, new UserInputService());
|
|
RegisterSingleton<WorkSpaceService>(Services.WorkSpaceService, new WorkSpaceService());
|
|
RegisterSingleton<FileSystemService>(Services.FileSystemService, new FileSystemService());
|
|
RegisterSingleton<ConversationFileSystemService>(Services.ConversationFileSystemService, new ConversationFileSystemService());
|
|
RegisterSingleton<ConversationNamingService>(Services.ConversationNamingService, new ConversationNamingService());
|
|
|
|
RegisterSingleton<IPrompt>(Services.IPrompt, new AIPrompt());
|
|
RegisterSingleton<AIFunctionDefinitions>(Services.AIFunctionDefinitions, new AIFunctionDefinitions());
|
|
RegisterSingleton<AIFunctionService>(Services.AIFunctionService, new AIFunctionService());
|
|
RegisterSingleton<StreamingService>(Services.StreamingService, new StreamingService());
|
|
RegisterSingleton<ChatService>(Services.ChatService, new ChatService());
|
|
|
|
RegisterTransient<StreamingMarkdownService>(Services.StreamingMarkdownService, () => new StreamingMarkdownService());
|
|
RegisterTransient<InputService>(Services.InputService, () => new InputService());
|
|
|
|
RegisterModals();
|
|
RegisterAiProvider();
|
|
}
|
|
|
|
export function RegisterAiProvider() {
|
|
const settingsService = Resolve<SettingsService>(Services.SettingsService);
|
|
const provider = fromModel(settingsService.settings.model);
|
|
|
|
if (provider == AIProvider.Claude) {
|
|
RegisterSingleton<IAIClass>(Services.IAIClass, new Claude());
|
|
RegisterSingleton<ITokenService>(Services.ITokenService, new ClaudeTokenService());
|
|
RegisterSingleton<IConversationNamingService>(Services.IConversationNamingService, new ClaudeConversationNamingService());
|
|
}
|
|
else if (provider == AIProvider.Gemini) {
|
|
RegisterSingleton<IAIClass>(Services.IAIClass, new Gemini());
|
|
RegisterSingleton<ITokenService>(Services.ITokenService, new GeminiTokenService());
|
|
RegisterSingleton<IConversationNamingService>(Services.IConversationNamingService, new GeminiConversationNamingService());
|
|
}
|
|
else if (provider == AIProvider.OpenAI) {
|
|
RegisterSingleton<IAIClass>(Services.IAIClass, new OpenAI());
|
|
RegisterSingleton<ITokenService>(Services.ITokenService, new OpenAITokenService());
|
|
RegisterSingleton<IConversationNamingService>(Services.IConversationNamingService, new OpenAIConversationNamingService());
|
|
}
|
|
|
|
Resolve<ChatService>(Services.ChatService).resolveAIProvider();
|
|
Resolve<ConversationNamingService>(Services.ConversationNamingService).resolveNamingProvider();
|
|
}
|
|
|
|
function RegisterModals() {
|
|
RegisterTransient<ConversationHistoryModal>(Services.ConversationHistoryModal, () => new ConversationHistoryModal());
|
|
RegisterTransient<HelpModal>(Services.HelpModal, () => new HelpModal())
|
|
} |