Refactor error handling, client, and tests for Ollama integration
This commit is contained in:
Executable
+147
@@ -0,0 +1,147 @@
|
||||
import { Plugin, WorkspaceLeaf, App, Setting, Notice, PluginSettingTab } from 'obsidian';
|
||||
import { ChatView } from './chat-view';
|
||||
import { PluginSettings } from './types';
|
||||
import {
|
||||
isValidHttpUrl,
|
||||
validatePluginSettings,
|
||||
validateOllamaUrl,
|
||||
validateModelName,
|
||||
Logger,
|
||||
} from './utils';
|
||||
import { DEFAULT_SETTINGS } from './constants';
|
||||
|
||||
export default class OllamaPlugin extends Plugin {
|
||||
settings: PluginSettings = DEFAULT_SETTINGS;
|
||||
|
||||
async onload() {
|
||||
// Initialize logging
|
||||
Logger.info('Ollama Plugin loading...', 'plugin');
|
||||
|
||||
await this.loadSettings();
|
||||
Logger.info('Plugin loaded successfully', 'plugin');
|
||||
|
||||
try {
|
||||
this.registerView(
|
||||
'ollama-chat-view',
|
||||
(leaf: WorkspaceLeaf) => new ChatView(leaf, this.settings)
|
||||
);
|
||||
} catch (error) {
|
||||
Logger.error('Failed to register view: ' + (error as Error).message, 'plugin');
|
||||
new Notice('Failed to register Ollama chat view');
|
||||
// Don't throw - let the plugin continue loading other features
|
||||
}
|
||||
|
||||
try {
|
||||
this.addRibbonIcon('message-square', 'Ollama Chat', async () => {
|
||||
const leaf = this.app.workspace.getLeaf();
|
||||
await leaf.setViewState({
|
||||
type: 'ollama-chat-view',
|
||||
active: true,
|
||||
});
|
||||
this.app.workspace.revealLeaf(leaf);
|
||||
});
|
||||
} catch (error) {
|
||||
Logger.error('Failed to add ribbon icon: ' + (error as Error).message, 'plugin');
|
||||
new Notice('Failed to add Ollama ribbon icon');
|
||||
// Don't throw - let the plugin continue loading other features
|
||||
}
|
||||
|
||||
this.addSettingTab(new OllamaSettingTab(this.app, this));
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
try {
|
||||
const data = await this.loadData();
|
||||
if (data) {
|
||||
Logger.debug('Loading saved settings', 'settings');
|
||||
this.settings = Object.assign({}, this.settings, data);
|
||||
}
|
||||
} catch (error) {
|
||||
// Use centralized error handling
|
||||
const { ErrorHandler } = await import('./error-handler');
|
||||
ErrorHandler.handleError(error, 'settings load');
|
||||
}
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
try {
|
||||
// Validate settings before saving
|
||||
const validationErrors = validatePluginSettings(this.settings);
|
||||
if (validationErrors.length > 0) {
|
||||
Logger.error(
|
||||
'Validation errors prevented saving settings: ' + validationErrors.join('; '),
|
||||
'settings'
|
||||
);
|
||||
new Notice(`Cannot save settings: ${validationErrors[0]}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
Logger.debug('Saving settings: ' + JSON.stringify(this.settings), 'settings');
|
||||
await this.saveData(this.settings);
|
||||
Logger.info('Settings saved successfully', 'settings');
|
||||
return true;
|
||||
} catch (error) {
|
||||
// Use centralized error handling
|
||||
const { ErrorHandler } = await import('./error-handler');
|
||||
ErrorHandler.handleError(error, 'settings save');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class OllamaSettingTab extends PluginSettingTab {
|
||||
private plugin: OllamaPlugin;
|
||||
|
||||
constructor(app: App, plugin: OllamaPlugin) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
display(): void {
|
||||
// Clear any existing content first to prevent duplicates
|
||||
this.containerEl.empty();
|
||||
|
||||
// Create container for settings
|
||||
const container = this.containerEl.createDiv() as HTMLElement;
|
||||
container.empty();
|
||||
|
||||
new Setting(container)
|
||||
.setName('Ollama URL')
|
||||
.setDesc('URL of your Ollama instance')
|
||||
.addText((text) =>
|
||||
text.setValue(this.plugin.settings.ollamaUrl).onChange(async (value) => {
|
||||
const urlValidation = validateOllamaUrl(value);
|
||||
if (urlValidation.valid) {
|
||||
Logger.debug('URL changed to: ' + value, 'settings');
|
||||
this.plugin.settings.ollamaUrl = value;
|
||||
await this.plugin.saveSettings();
|
||||
} else {
|
||||
Logger.warn('Invalid URL format: ' + urlValidation.error, 'settings');
|
||||
new Notice(urlValidation.error || 'Invalid Ollama URL format.');
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
new Setting(container)
|
||||
.setName('Model')
|
||||
.setDesc('Model to use for chat')
|
||||
.addText((text) =>
|
||||
text.setValue(this.plugin.settings.model).onChange(async (value) => {
|
||||
const modelValidation = validateModelName(value);
|
||||
if (modelValidation.valid) {
|
||||
Logger.debug('Model changed to: ' + value, 'settings');
|
||||
this.plugin.settings.model = value;
|
||||
await this.plugin.saveSettings();
|
||||
} else {
|
||||
Logger.warn('Invalid model name format: ' + modelValidation.error, 'settings');
|
||||
new Notice(modelValidation.error || 'Invalid model name format.');
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
hide(): void {
|
||||
// Clear the container to prevent duplicate elements
|
||||
this.containerEl.empty();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user