-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.ts
159 lines (130 loc) · 4.65 KB
/
main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import {
Editor,
MarkdownView,
Notice,
Plugin,
} from 'obsidian';
import {OllamaService} from "./src/services/OllamaService";
import {DEFAULT_SETTINGS, OllamaPluginSettings} from "./src/models/OllamaPluginSettings";
import {OllamaSuggestor} from "./src/OllamaSuggestor";
import {OllamaPromptModal} from "./src/OllamaPromptModal";
import {OllamaSettingTab} from "./src/OllamaSettingTab";
export default class OllamaPlugin extends Plugin {
settings: OllamaPluginSettings;
suggestor: OllamaSuggestor;
ollamaService: OllamaService;
private isProcessingCommand = false;
async onload() {
await this.loadSettings();
this.ollamaService = new OllamaService(this.settings);
// This creates an icon in the left ribbon.
const ribbonIconEl = this.addRibbonIcon('star', 'Ollama AI Integration', (evt: MouseEvent) => {
new OllamaPromptModal(this.app, this).open();
});
ribbonIconEl.addClass('ollama-plugin-ribbon-class');
// This adds a simple command that can be triggered anywhere
this.addCommand({
id: 'open-ollama-prompt-modal',
name: 'Open Ollama prompt modal',
callback: () => {
new OllamaPromptModal(this.app, this).open();
}
});
// Add the new command for /ollama syntax
this.addCommand({
id: 'process-ollama-inline',
name: 'Process /ollama command',
editorCallback: (editor: Editor, view: MarkdownView) => {
console.log('[ollama command]')
const cursor = editor.getCursor();
let initialLine = editor.getLine(cursor.line - 1);
const match = initialLine.match(/^ollama\s+(.+)$/);
if (match && !this.isProcessingCommand) {
initialLine = initialLine.replace(/^ollama\s+/, '');
this.isProcessingCommand = true;
this.processOllamaCommand(editor, initialLine).finally(() => {
this.isProcessingCommand = false;
});
}
}
});
// Initialize the suggestor
this.suggestor = new OllamaSuggestor(this.app, this);
this.registerEditorSuggest(this.suggestor);
// This adds an editor command that can perform some operation on the current editor instance
this.addCommand({
id: 'generate-ollama-response',
name: 'Generate Ollama response',
editorCallback: (editor: Editor, view: MarkdownView) => {
const selection = editor.getSelection();
if (selection) {
this.generateOllamaResponse(selection, (response) => {
editor.replaceSelection(response);
});
}
}
});
// This adds a settings tab so the user can configure various aspects of the plugin
this.addSettingTab(new OllamaSettingTab(this.app, this));
//Add event listener for keypress events
this.registerDomEvent(document, 'keydown', (evt: KeyboardEvent) => {
this.handleKeyPress(evt);
});
}
onunload() {}
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings() {
await this.saveData(this.settings);
}
handleKeyPress(evt: KeyboardEvent) {
if (evt.key === 'Enter' && !this.isProcessingCommand) {
const activeLeaf = this.app.workspace.activeLeaf;
if (activeLeaf?.view instanceof MarkdownView) {
const editor = activeLeaf.view.editor;
const cursor = editor.getCursor();
const lastLine = editor.getLine(cursor.line - 1);
const initialLine = lastLine.replace(/^ollama\s+/, '');
console.log('isProcessingCommand:', lastLine, this.isProcessingCommand);
if (lastLine.trim().startsWith('ollama ')) {
evt.preventDefault();
this.isProcessingCommand = true;
this.processOllamaCommand(editor, initialLine).finally(() => {
this.isProcessingCommand = false;
});
}
}
}
}
async generateOllamaResponse(prompt: string, onChunk: (chunk: string) => void): Promise<void> {
await this.ollamaService.generateResponse(prompt, onChunk);
}
async processOllamaCommand(editor: Editor, raw_prompt: string) {
const cursor = editor.getCursor();
const prompt = raw_prompt;
// Clear the current line
editor.setLine(cursor.line, '');
// Move cursor to the end of the current line
editor.setCursor(cursor.line, 0);
// Insert a new line for the response
editor.replaceRange('\n', cursor);
let response = '';
const updateEditor = () => {
// editor.setLine(cursor.line + 1, response);
editor.setValue(response);
editor.scrollIntoView({from: cursor, to: cursor}, true);
};
await this.ollamaService.generateResponse(prompt, (chunk) => {
response += chunk;
updateEditor();
});
updateEditor();
// Move the cursor to the end of the response
editor.setCursor(cursor.line + 1 + response.split('\n').length - 1, 0);
new Notice('Ollama response generated');
}
async fetchOllamaModels(): Promise<string[]> {
return this.ollamaService.fetchModels();
}
}