mirror of
https://github.com/ahmetildirim/obsidian-inscribe.git
synced 2026-07-22 05:44:10 +00:00
feat: add Grok provider integration and update settings
This commit is contained in:
parent
b26e61432d
commit
5a1b01b9eb
11 changed files with 155 additions and 8 deletions
|
|
@ -10,6 +10,7 @@ Inscribe is an AI-powered inline autocompletion plugin for Obsidian. It will gen
|
|||
Inscribe supports following providers:
|
||||
- Ollama (local)
|
||||
- Gemini
|
||||
- Grok
|
||||
- OpenAI
|
||||
- OpenAI compatible
|
||||
|
||||
|
|
@ -48,4 +49,3 @@ Using per-path profile config, you can enable completions only for specific path
|
|||
If you find this plugin useful:
|
||||
|
||||
[](https://buymeacoffee.com/ahmetildirim)
|
||||
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "obsidian-inscribe",
|
||||
"version": "1.1.3",
|
||||
"version": "1.1.5",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "obsidian-inscribe",
|
||||
"version": "1.1.3",
|
||||
"version": "1.1.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@google/genai": "^1.41.0",
|
||||
|
|
|
|||
|
|
@ -5,12 +5,14 @@ import { OllamaProvider } from "./ollama";
|
|||
import { OpenAIProvider } from "./openai";
|
||||
import { OpenAICompatibleProvider } from "./openai-compat";
|
||||
import { GeminiProvider } from "./gemini";
|
||||
import { GrokProvider } from "./grok";
|
||||
|
||||
interface Providers {
|
||||
[ProviderType.OLLAMA]: OllamaProvider,
|
||||
[ProviderType.OPENAI]: OpenAIProvider,
|
||||
[ProviderType.OPENAI_COMPATIBLE]: OpenAICompatibleProvider,
|
||||
[ProviderType.GEMINI]: GeminiProvider,
|
||||
[ProviderType.GROK]: GrokProvider,
|
||||
}
|
||||
|
||||
export class ProviderFactory {
|
||||
|
|
@ -44,6 +46,7 @@ export class ProviderFactory {
|
|||
[ProviderType.OPENAI]: new OpenAIProvider(settings.providers.openai),
|
||||
[ProviderType.OPENAI_COMPATIBLE]: new OpenAICompatibleProvider(settings.providers.openai_compatible),
|
||||
[ProviderType.GEMINI]: new GeminiProvider(settings.providers.gemini),
|
||||
[ProviderType.GROK]: new GrokProvider(settings.providers.grok),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
src/providers/grok/index.ts
Normal file
2
src/providers/grok/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export * from "./provider";
|
||||
export * from "./settings";
|
||||
83
src/providers/grok/provider.ts
Normal file
83
src/providers/grok/provider.ts
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import { Provider } from "..";
|
||||
import { Editor } from "obsidian";
|
||||
import OpenAI from "openai";
|
||||
import { ProfileOptions } from "src/settings/settings";
|
||||
import { GrokSettings } from ".";
|
||||
|
||||
export class GrokProvider implements Provider {
|
||||
private static readonly BASE_URL = "https://api.x.ai/v1";
|
||||
client: OpenAI;
|
||||
settings: GrokSettings;
|
||||
aborted: boolean = false;
|
||||
abortcontroller?: AbortController;
|
||||
|
||||
constructor(settings: GrokSettings) {
|
||||
this.settings = settings;
|
||||
this.client = new OpenAI({
|
||||
baseURL: GrokProvider.BASE_URL,
|
||||
apiKey: this.settings.apiKey,
|
||||
dangerouslyAllowBrowser: true,
|
||||
});
|
||||
}
|
||||
|
||||
async *generate(editor: Editor, prompt: string, options: ProfileOptions): AsyncGenerator<string> {
|
||||
this.aborted = false;
|
||||
this.abortcontroller = new AbortController();
|
||||
|
||||
const initialPosition = editor.getCursor();
|
||||
const stream = await this.client.chat.completions.create({
|
||||
model: options.model,
|
||||
messages: [
|
||||
{ role: "system", content: options.systemPrompt },
|
||||
{ role: "user", content: prompt }
|
||||
],
|
||||
temperature: options.temperature,
|
||||
stream: true,
|
||||
}, { signal: this.abortcontroller.signal });
|
||||
|
||||
let completion = "";
|
||||
for await (const chunk of stream) {
|
||||
if (this.aborted) {
|
||||
return;
|
||||
}
|
||||
if (this.cursorMoved(editor, initialPosition)) {
|
||||
this.abort();
|
||||
return;
|
||||
}
|
||||
|
||||
const content = chunk.choices[0]?.delta?.content || "";
|
||||
completion += content;
|
||||
yield completion;
|
||||
}
|
||||
}
|
||||
|
||||
async abort() {
|
||||
if (this.aborted) return;
|
||||
this.aborted = true;
|
||||
this.abortcontroller?.abort();
|
||||
}
|
||||
|
||||
async fetchModels(): Promise<string[]> {
|
||||
if (!this.client) {
|
||||
return this.settings.models;
|
||||
}
|
||||
|
||||
const models = await this.client.models.list();
|
||||
return models.data.map(model => model.id);
|
||||
}
|
||||
|
||||
async connectionTest(): Promise<boolean> {
|
||||
try {
|
||||
await this.client.models.list();
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Error testing connection:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private cursorMoved(editor: Editor, initialPosition: { line: number, ch: number }): boolean {
|
||||
const currentPosition = editor.getCursor();
|
||||
return currentPosition.line !== initialPosition.line || currentPosition.ch !== initialPosition.ch;
|
||||
}
|
||||
}
|
||||
11
src/providers/grok/settings.ts
Normal file
11
src/providers/grok/settings.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { ProviderType } from "..";
|
||||
|
||||
export interface GrokSettings {
|
||||
integration: ProviderType;
|
||||
name: string;
|
||||
description: string;
|
||||
apiKey: string;
|
||||
models: string[];
|
||||
configured: boolean;
|
||||
temperature_range: { min: number; max: number };
|
||||
}
|
||||
|
|
@ -2,5 +2,7 @@ export * from "./provider";
|
|||
export * from "./factory";
|
||||
export * from "./ollama";
|
||||
export * from "./openai";
|
||||
|
||||
export * from "./openai-compat";
|
||||
export * from "./gemini";
|
||||
export * from "./grok";
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ export enum ProviderType {
|
|||
OPENAI = "openai",
|
||||
OPENAI_COMPATIBLE = "openai_compatible",
|
||||
GEMINI = "gemini",
|
||||
GROK = "grok",
|
||||
}
|
||||
|
||||
// Completer interface for ai integrations
|
||||
|
|
@ -15,4 +16,4 @@ export interface Provider {
|
|||
abort: () => Promise<void>;
|
||||
fetchModels(): Promise<string[]> | string[];
|
||||
connectionTest(): Promise<boolean>;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ export class ProviderSettingsModal extends Modal {
|
|||
case ProviderType.GEMINI:
|
||||
this.renderGeminiSettings();
|
||||
break;
|
||||
case ProviderType.GROK:
|
||||
this.renderGrokSettings();
|
||||
break;
|
||||
default:
|
||||
contentEl.createEl('h2', { text: 'Unknown provider type' });
|
||||
break;
|
||||
|
|
@ -137,6 +140,27 @@ export class ProviderSettingsModal extends Modal {
|
|||
this.renderConnectionStatus(this.plugin.settings.providers.gemini);
|
||||
}
|
||||
|
||||
async renderGrokSettings() {
|
||||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
this.setTitle('Grok');
|
||||
|
||||
new Setting(contentEl)
|
||||
.setName("Grok API key")
|
||||
.setDesc("The API key for xAI Grok")
|
||||
.addText((text) => {
|
||||
text
|
||||
.setValue(this.plugin.settings.providers.grok.apiKey)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.providers.grok.apiKey = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
this.renderModelSettings(this.plugin.settings.providers.grok);
|
||||
this.renderConnectionStatus(this.plugin.settings.providers.grok);
|
||||
}
|
||||
|
||||
private renderModelSettings(provider: { models: string[] }) {
|
||||
new Setting(this.contentEl)
|
||||
.setName("Available models")
|
||||
|
|
@ -192,4 +216,4 @@ export class ProviderSettingsModal extends Modal {
|
|||
contentEl.empty();
|
||||
this.onCloseCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { OllamaSettings } from "src/providers/ollama";
|
|||
import { OpenAISettings } from "src/providers/openai";
|
||||
import { OpenAICompatibleSettings } from "src/providers/openai-compat";
|
||||
import { GeminiSettings } from "src/providers/gemini";
|
||||
import { GrokSettings } from "src/providers/grok";
|
||||
|
||||
// Completion options for a profile
|
||||
export interface ProfileOptions {
|
||||
|
|
@ -54,6 +55,7 @@ export interface Settings {
|
|||
openai: OpenAISettings,
|
||||
openai_compatible: OpenAICompatibleSettings,
|
||||
gemini: GeminiSettings,
|
||||
grok: GrokSettings,
|
||||
},
|
||||
// profiles
|
||||
profiles: Profiles,
|
||||
|
|
@ -121,6 +123,15 @@ export const DEFAULT_SETTINGS: Settings = {
|
|||
configured: false,
|
||||
temperature_range: { min: 0, max: 2 },
|
||||
},
|
||||
grok: {
|
||||
integration: ProviderType.GROK,
|
||||
name: "Grok",
|
||||
description: "Use xAI Grok models to generate text.",
|
||||
apiKey: "api-key",
|
||||
models: ["grok-3-mini", "grok-3"],
|
||||
configured: false,
|
||||
temperature_range: { min: 0, max: 1 },
|
||||
},
|
||||
},
|
||||
profiles: {
|
||||
default: {
|
||||
|
|
@ -186,4 +197,4 @@ export function resetSettings(settings: Settings): void {
|
|||
|
||||
export const isDefaultProfile = (profile: ProfileId): boolean => {
|
||||
return profile === DEFAULT_PROFILE;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -369,6 +369,15 @@ class ProvidersSection {
|
|||
ProviderType.GEMINI,
|
||||
this.plugin.settings.providers.gemini.configured));
|
||||
|
||||
// Grok Provider
|
||||
new Setting(this.container)
|
||||
.setName("Grok")
|
||||
.setDesc("xAI Grok API")
|
||||
.addButton((button: ButtonComponent) => this.createConfigureButton(
|
||||
button,
|
||||
ProviderType.GROK,
|
||||
this.plugin.settings.providers.grok.configured));
|
||||
|
||||
// OpenAI Compatible Provider
|
||||
new Setting(this.container)
|
||||
.setName("OpenAI compatible API")
|
||||
|
|
@ -444,6 +453,7 @@ class ProfilesSection {
|
|||
.addOption(ProviderType.OLLAMA, "Ollama")
|
||||
.addOption(ProviderType.OPENAI, "OpenAI")
|
||||
.addOption(ProviderType.GEMINI, "Gemini")
|
||||
.addOption(ProviderType.GROK, "Grok")
|
||||
.addOption(ProviderType.OPENAI_COMPATIBLE, "OpenAI Compatible")
|
||||
.setValue(profile.provider)
|
||||
.onChange(async (value: ProviderType) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue