From cd46a17e5f59cf8b490ddfe4a9f38dfe5c36d8e9 Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Thu, 23 Mar 2023 05:31:26 +0400 Subject: [PATCH] Add Khoj Chat Modal, Command in Khoj Obsidian to Chat using API --- src/interface/obsidian/src/chat_modal.ts | 63 ++++++++++++++++++++++++ src/interface/obsidian/src/main.ts | 12 +++++ 2 files changed, 75 insertions(+) create mode 100644 src/interface/obsidian/src/chat_modal.ts diff --git a/src/interface/obsidian/src/chat_modal.ts b/src/interface/obsidian/src/chat_modal.ts new file mode 100644 index 00000000..ca2248a5 --- /dev/null +++ b/src/interface/obsidian/src/chat_modal.ts @@ -0,0 +1,63 @@ +import { App, Modal, request, Setting } from 'obsidian'; +import { KhojSetting } from 'src/settings'; + + +export class KhojChatModal extends Modal { + result: string; + setting: KhojSetting; + + constructor(app: App, setting: KhojSetting) { + super(app); + this.setting = setting; + } + + async onOpen() { + let { contentEl } = this; + + // Add title to the Khoj Chat modal + contentEl.createEl("h1", { text: "Khoj Chat" }); + + // Create area for chat logs + contentEl.createDiv({ attr: { class: "chat-body" } }); + + // Add chat input field + new Setting(contentEl) + .addText((text) => { + text.onChange((value) => { this.result = value }); + text.setPlaceholder("What is the meaning of life?"); + }) + .addButton((btn) => btn + .setButtonText("Send") + .setCta() + .onClick(async () => { await this.getChatResponse(this.result) })); + } + + renderMessage(message: string, sender: string) { + let { contentEl } = this; + + // Append message to conversation history HTML element. + // The chat logs should display above the message input box to follow standard UI semantics + let chat_body_el = contentEl.getElementsByClassName("chat-body").item(0); + if (!!chat_body_el) { + let emojified_sender = sender == "khoj" ? "🦅 Khoj" : "🤔 You"; + chat_body_el.createDiv({ text: `${emojified_sender}: ${message}` }) + } + } + + async getChatResponse(query: string): Promise { + // Exit if query is empty + if (!query || query === "") return; + + // Render user query as chat message + this.renderMessage(query, "you"); + + // Get chat response from Khoj backend + let encodedQuery = encodeURIComponent(query); + let chatUrl = `${this.setting.khojUrl}/api/chat?q=${encodedQuery}`; + let response = await request(chatUrl); + let data = JSON.parse(response); + + // Render Khoj response as chat message + this.renderMessage(data.response, "khoj"); + } +} diff --git a/src/interface/obsidian/src/main.ts b/src/interface/obsidian/src/main.ts index 5feb3364..470e1e89 100644 --- a/src/interface/obsidian/src/main.ts +++ b/src/interface/obsidian/src/main.ts @@ -1,6 +1,7 @@ import { Notice, Plugin } from 'obsidian'; import { KhojSetting, KhojSettingTab, DEFAULT_SETTINGS } from 'src/settings' import { KhojSearchModal } from 'src/search_modal' +import { KhojChatModal } from 'src/chat_modal' import { configureKhojBackend } from './utils'; @@ -32,6 +33,17 @@ export default class Khoj extends Plugin { } }); + // Add chat command. It can be triggered from anywhere + this.addCommand({ + id: 'chat', + name: 'Chat', + checkCallback: (checking) => { + if (!checking && this.settings.connectedToBackend) + new KhojChatModal(this.app, this.settings).open(); + return this.settings.connectedToBackend; + } + }); + // Create an icon in the left ribbon. this.addRibbonIcon('search', 'Khoj', (_: MouseEvent) => { // Called when the user clicks the icon.