mirror of
https://github.com/khoj-ai/khoj.git
synced 2024-11-23 15:38:55 +01:00
Cycle through chat history in chat input on Obsidian (#861)
* Add ability to cycle through the chat history in the chat input on Obsidian (similar to terminal history navigation) * Add mod key shortcut to cycle through chat history in chat input * Add shortcut help text in chat input placeholder --------- Co-authored-by: Debanjum Singh Solanky <debanjum@gmail.com>
This commit is contained in:
parent
05c0aa3882
commit
b5bcce7f85
2 changed files with 72 additions and 5 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -37,6 +37,8 @@ src/interface/obsidian/main.js
|
||||||
|
|
||||||
# Exclude sourcemaps
|
# Exclude sourcemaps
|
||||||
*.map
|
*.map
|
||||||
|
# IntelliJ
|
||||||
|
.idea
|
||||||
|
|
||||||
# obsidian
|
# obsidian
|
||||||
data.json
|
data.json
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ItemView, MarkdownRenderer, Scope, WorkspaceLeaf, request, requestUrl, setIcon } from 'obsidian';
|
import {ItemView, MarkdownRenderer, Scope, WorkspaceLeaf, request, requestUrl, setIcon, Platform} from 'obsidian';
|
||||||
import * as DOMPurify from 'dompurify';
|
import * as DOMPurify from 'dompurify';
|
||||||
import { KhojSetting } from 'src/settings';
|
import { KhojSetting } from 'src/settings';
|
||||||
import { KhojPaneView } from 'src/pane_view';
|
import { KhojPaneView } from 'src/pane_view';
|
||||||
|
@ -45,6 +45,10 @@ export class KhojChatView extends KhojPaneView {
|
||||||
waitingForLocation: boolean;
|
waitingForLocation: boolean;
|
||||||
location: Location;
|
location: Location;
|
||||||
keyPressTimeout: NodeJS.Timeout | null = null;
|
keyPressTimeout: NodeJS.Timeout | null = null;
|
||||||
|
userMessages: string[] = []; // Store user sent messages for input history cycling
|
||||||
|
currentMessageIndex: number = -1; // Track current message index in userMessages array
|
||||||
|
private currentUserInput: string = ""; // Stores the current user input that is being typed in chat
|
||||||
|
private startingMessage: string = "Message";
|
||||||
chatMessageState: ChatMessageState;
|
chatMessageState: ChatMessageState;
|
||||||
|
|
||||||
constructor(leaf: WorkspaceLeaf, setting: KhojSetting) {
|
constructor(leaf: WorkspaceLeaf, setting: KhojSetting) {
|
||||||
|
@ -96,6 +100,14 @@ export class KhojChatView extends KhojPaneView {
|
||||||
|
|
||||||
// Clear text after extracting message to send
|
// Clear text after extracting message to send
|
||||||
let user_message = input_el.value.trim();
|
let user_message = input_el.value.trim();
|
||||||
|
// Store the message in the array if it's not empty
|
||||||
|
if (user_message) {
|
||||||
|
this.userMessages.push(user_message);
|
||||||
|
// Update starting message after sending a new message
|
||||||
|
const modifierKey = Platform.isMacOS ? '⌘' : '^';
|
||||||
|
this.startingMessage = `(${modifierKey}+↑/↓) for prev messages`;
|
||||||
|
input_el.placeholder = this.startingMessage;
|
||||||
|
}
|
||||||
input_el.value = "";
|
input_el.value = "";
|
||||||
this.autoResize();
|
this.autoResize();
|
||||||
|
|
||||||
|
@ -147,7 +159,10 @@ export class KhojChatView extends KhojPaneView {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
chatInput.addEventListener('input', (_) => { this.onChatInput() });
|
chatInput.addEventListener('input', (_) => { this.onChatInput() });
|
||||||
chatInput.addEventListener('keydown', (event) => { this.incrementalChat(event) });
|
chatInput.addEventListener('keydown', (event) => {
|
||||||
|
this.incrementalChat(event);
|
||||||
|
this.handleArrowKeys(event);
|
||||||
|
});
|
||||||
|
|
||||||
// Add event listeners for long press keybinding
|
// Add event listeners for long press keybinding
|
||||||
this.contentEl.addEventListener('keydown', this.handleKeyDown.bind(this));
|
this.contentEl.addEventListener('keydown', this.handleKeyDown.bind(this));
|
||||||
|
@ -181,7 +196,8 @@ export class KhojChatView extends KhojPaneView {
|
||||||
|
|
||||||
// Get chat history from Khoj backend and set chat input state
|
// Get chat history from Khoj backend and set chat input state
|
||||||
let getChatHistorySucessfully = await this.getChatHistory(chatBodyEl);
|
let getChatHistorySucessfully = await this.getChatHistory(chatBodyEl);
|
||||||
let placeholderText = getChatHistorySucessfully ? "Message" : "Configure Khoj to enable chat";
|
|
||||||
|
let placeholderText : string = getChatHistorySucessfully ? this.startingMessage : "Configure Khoj to enable chat";
|
||||||
chatInput.placeholder = placeholderText;
|
chatInput.placeholder = placeholderText;
|
||||||
chatInput.disabled = !getChatHistorySucessfully;
|
chatInput.disabled = !getChatHistorySucessfully;
|
||||||
|
|
||||||
|
@ -627,10 +643,19 @@ export class KhojChatView extends KhojPaneView {
|
||||||
chatBodyEl.innerHTML = "";
|
chatBodyEl.innerHTML = "";
|
||||||
chatBodyEl.dataset.conversationId = "";
|
chatBodyEl.dataset.conversationId = "";
|
||||||
chatBodyEl.dataset.conversationTitle = "";
|
chatBodyEl.dataset.conversationTitle = "";
|
||||||
|
this.userMessages = [];
|
||||||
|
this.startingMessage = "Message";
|
||||||
|
|
||||||
|
// Update the placeholder of the chat input
|
||||||
|
const chatInput = this.contentEl.querySelector('.khoj-chat-input') as HTMLTextAreaElement;
|
||||||
|
if (chatInput) {
|
||||||
|
chatInput.placeholder = this.startingMessage;
|
||||||
|
}
|
||||||
this.renderMessage(chatBodyEl, "Hey 👋🏾, what's up?", "khoj");
|
this.renderMessage(chatBodyEl, "Hey 👋🏾, what's up?", "khoj");
|
||||||
}
|
}
|
||||||
|
|
||||||
async toggleChatSessions(forceShow: boolean = false): Promise<boolean> {
|
async toggleChatSessions(forceShow: boolean = false): Promise<boolean> {
|
||||||
|
this.userMessages = []; // clear user previous message history
|
||||||
let chatBodyEl = this.contentEl.getElementsByClassName("khoj-chat-body")[0] as HTMLElement;
|
let chatBodyEl = this.contentEl.getElementsByClassName("khoj-chat-body")[0] as HTMLElement;
|
||||||
if (!forceShow && this.contentEl.getElementsByClassName("side-panel")?.length > 0) {
|
if (!forceShow && this.contentEl.getElementsByClassName("side-panel")?.length > 0) {
|
||||||
chatBodyEl.innerHTML = "";
|
chatBodyEl.innerHTML = "";
|
||||||
|
@ -846,7 +871,6 @@ export class KhojChatView extends KhojPaneView {
|
||||||
chatBodyEl.dataset.conversationId = responseJson.response.conversation_id;
|
chatBodyEl.dataset.conversationId = responseJson.response.conversation_id;
|
||||||
chatBodyEl.dataset.conversationTitle = responseJson.response.slug || `New conversation 🌱`;
|
chatBodyEl.dataset.conversationTitle = responseJson.response.slug || `New conversation 🌱`;
|
||||||
|
|
||||||
|
|
||||||
let chatLogs = responseJson.response?.conversation_id ? responseJson.response.chat ?? [] : responseJson.response;
|
let chatLogs = responseJson.response?.conversation_id ? responseJson.response.chat ?? [] : responseJson.response;
|
||||||
chatLogs.forEach((chatLog: any) => {
|
chatLogs.forEach((chatLog: any) => {
|
||||||
this.renderMessageWithReferences(
|
this.renderMessageWithReferences(
|
||||||
|
@ -859,7 +883,23 @@ export class KhojChatView extends KhojPaneView {
|
||||||
chatLog.intent?.type,
|
chatLog.intent?.type,
|
||||||
chatLog.intent?.["inferred-queries"],
|
chatLog.intent?.["inferred-queries"],
|
||||||
);
|
);
|
||||||
|
// push the user messages to the chat history
|
||||||
|
if(chatLog.by === "you"){
|
||||||
|
this.userMessages.push(chatLog.message);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update starting message after loading history
|
||||||
|
const modifierKey: string = Platform.isMacOS ? '⌘' : '^';
|
||||||
|
this.startingMessage = this.userMessages.length > 0
|
||||||
|
? `(${modifierKey}+↑/↓) for prev messages`
|
||||||
|
: "Message";
|
||||||
|
|
||||||
|
// Update the placeholder of the chat input
|
||||||
|
const chatInput = this.contentEl.querySelector('.khoj-chat-input') as HTMLTextAreaElement;
|
||||||
|
if (chatInput) {
|
||||||
|
chatInput.placeholder = this.startingMessage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
let errorMsg = "Unable to get response from Khoj server ❤️🩹. Ensure server is running or contact developers for help at [team@khoj.dev](mailto:team@khoj.dev) or in [Discord](https://discord.gg/BDgyabRM6e)";
|
let errorMsg = "Unable to get response from Khoj server ❤️🩹. Ensure server is running or contact developers for help at [team@khoj.dev](mailto:team@khoj.dev) or in [Discord](https://discord.gg/BDgyabRM6e)";
|
||||||
|
@ -1228,7 +1268,9 @@ export class KhojChatView extends KhojPaneView {
|
||||||
onChatInput() {
|
onChatInput() {
|
||||||
const chatInput = <HTMLTextAreaElement>this.contentEl.getElementsByClassName("khoj-chat-input")[0];
|
const chatInput = <HTMLTextAreaElement>this.contentEl.getElementsByClassName("khoj-chat-input")[0];
|
||||||
chatInput.value = chatInput.value.trimStart();
|
chatInput.value = chatInput.value.trimStart();
|
||||||
|
this.currentMessageIndex = -1;
|
||||||
|
// store the current input
|
||||||
|
this.currentUserInput = chatInput.value;
|
||||||
this.autoResize();
|
this.autoResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1360,4 +1402,27 @@ export class KhojChatView extends KhojPaneView {
|
||||||
|
|
||||||
return referencesDiv;
|
return referencesDiv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// function to loop through the user's past messages
|
||||||
|
handleArrowKeys(event: KeyboardEvent) {
|
||||||
|
const chatInput = event.target as HTMLTextAreaElement;
|
||||||
|
const isModKey = Platform.isMacOS ? event.metaKey : event.ctrlKey;
|
||||||
|
|
||||||
|
if (isModKey && event.key === 'ArrowUp') {
|
||||||
|
event.preventDefault();
|
||||||
|
if (this.currentMessageIndex < this.userMessages.length - 1) {
|
||||||
|
this.currentMessageIndex++;
|
||||||
|
chatInput.value = this.userMessages[this.userMessages.length - 1 - this.currentMessageIndex];
|
||||||
|
}
|
||||||
|
} else if (isModKey && event.key === 'ArrowDown') {
|
||||||
|
event.preventDefault();
|
||||||
|
if (this.currentMessageIndex > 0) {
|
||||||
|
this.currentMessageIndex--;
|
||||||
|
chatInput.value = this.userMessages[this.userMessages.length - 1 - this.currentMessageIndex];
|
||||||
|
} else if (this.currentMessageIndex === 0) {
|
||||||
|
this.currentMessageIndex = -1;
|
||||||
|
chatInput.value = this.currentUserInput;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue