Allow sending current conversation state
This commit is contained in:
@@ -120,6 +120,7 @@ class Odidere {
|
|||||||
this.#clearAttachments();
|
this.#clearAttachments();
|
||||||
this.$textInput.value = '';
|
this.$textInput.value = '';
|
||||||
this.$textInput.style.height = 'auto';
|
this.$textInput.style.height = 'auto';
|
||||||
|
this.#updateSendButtonState();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====================
|
// ====================
|
||||||
@@ -258,6 +259,7 @@ class Odidere {
|
|||||||
// Render the active path.
|
// Render the active path.
|
||||||
const activePath = this.getActivePath();
|
const activePath = this.getActivePath();
|
||||||
this.#renderMessages(activePath);
|
this.#renderMessages(activePath);
|
||||||
|
this.#updateSendButtonState();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('failed to load history:', e);
|
console.error('failed to load history:', e);
|
||||||
this.messagesMap.clear();
|
this.messagesMap.clear();
|
||||||
@@ -349,6 +351,7 @@ class Odidere {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.#saveToStorage();
|
this.#saveToStorage();
|
||||||
|
this.#updateSendButtonState();
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,6 +452,7 @@ class Odidere {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.#saveToStorage();
|
this.#saveToStorage();
|
||||||
|
this.#updateSendButtonState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -572,6 +576,7 @@ class Odidere {
|
|||||||
const maxHeight = parseFloat(computed.maxHeight);
|
const maxHeight = parseFloat(computed.maxHeight);
|
||||||
const newHeight = Math.min(textarea.scrollHeight, maxHeight);
|
const newHeight = Math.min(textarea.scrollHeight, maxHeight);
|
||||||
textarea.style.height = `${newHeight}px`;
|
textarea.style.height = `${newHeight}px`;
|
||||||
|
this.#updateSendButtonState();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -592,6 +597,7 @@ class Odidere {
|
|||||||
this.attachments.push(file);
|
this.attachments.push(file);
|
||||||
}
|
}
|
||||||
this.#renderAttachments();
|
this.#renderAttachments();
|
||||||
|
this.#updateSendButtonState();
|
||||||
this.$fileInput.value = '';
|
this.$fileInput.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1025,9 +1031,6 @@ class Odidere {
|
|||||||
*/
|
*/
|
||||||
async #submitText() {
|
async #submitText() {
|
||||||
const text = this.$textInput.value.trim();
|
const text = this.$textInput.value.trim();
|
||||||
const hasContent = text || this.attachments.length > 0;
|
|
||||||
|
|
||||||
if (!hasContent) return;
|
|
||||||
if (this.isProcessing) return;
|
if (this.isProcessing) return;
|
||||||
|
|
||||||
this.#stopCurrentAudio();
|
this.#stopCurrentAudio();
|
||||||
@@ -1060,20 +1063,25 @@ class Odidere {
|
|||||||
this.currentController = new AbortController();
|
this.currentController = new AbortController();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Build the user message with text and attachments.
|
const hasNewInput = text || this.attachments.length > 0 || audio;
|
||||||
const userMessage = await this.#buildUserMessage(text, this.attachments);
|
|
||||||
const hasContent = text || this.attachments.length > 0 || audio;
|
|
||||||
if (!hasContent) {
|
|
||||||
this.#setLoadingState(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build messages array from active path + current user message.
|
// Build messages array from active path + current user message.
|
||||||
const activePath = this.getActivePath();
|
const activePath = this.getActivePath();
|
||||||
const messages = [
|
let messages;
|
||||||
|
let userMessage;
|
||||||
|
|
||||||
|
if (hasNewInput) {
|
||||||
|
userMessage = await this.#buildUserMessage(text, this.attachments);
|
||||||
|
messages = [
|
||||||
...activePath.map(({ parent, children, id, meta, ...msg }) => msg),
|
...activePath.map(({ parent, children, id, meta, ...msg }) => msg),
|
||||||
userMessage,
|
userMessage,
|
||||||
];
|
];
|
||||||
|
} else {
|
||||||
|
// Continue conversation: send existing history without a new user message.
|
||||||
|
messages = activePath.map(
|
||||||
|
({ parent, children, id, meta, ...msg }) => msg,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
messages,
|
messages,
|
||||||
@@ -1091,9 +1099,9 @@ class Odidere {
|
|||||||
// Clear attachments after building payload (before async operations).
|
// Clear attachments after building payload (before async operations).
|
||||||
this.#clearAttachments();
|
this.#clearAttachments();
|
||||||
|
|
||||||
// For text-only requests (no audio), add to history and render
|
// For text-only requests with new input, add to history and render
|
||||||
// immediately. Use the returned messages (with IDs) for rendering.
|
// immediately. Skip when continuing conversation (no new user message).
|
||||||
if (!audio) {
|
if (!audio && hasNewInput) {
|
||||||
const appended = this.#appendHistory([userMessage]);
|
const appended = this.#appendHistory([userMessage]);
|
||||||
this.#renderMessages(appended);
|
this.#renderMessages(appended);
|
||||||
}
|
}
|
||||||
@@ -1310,6 +1318,23 @@ class Odidere {
|
|||||||
// ====================
|
// ====================
|
||||||
// STATE
|
// STATE
|
||||||
// ====================
|
// ====================
|
||||||
|
/**
|
||||||
|
* #updateSendButtonState enables the send button when there is text,
|
||||||
|
* attachments, or at least one message in the conversation history,
|
||||||
|
* and disables it otherwise.
|
||||||
|
*/
|
||||||
|
#updateSendButtonState() {
|
||||||
|
const hasText = this.$textInput.value.trim().length > 0;
|
||||||
|
const hasAttachments = this.attachments.length > 0;
|
||||||
|
const hasHistory = this.messagesMap.size > 0;
|
||||||
|
const enabled = hasText || hasAttachments || hasHistory;
|
||||||
|
this.$send.disabled = !enabled;
|
||||||
|
this.$send.setAttribute(
|
||||||
|
'aria-label',
|
||||||
|
enabled ? 'Send message' : 'Start a conversation to enable send',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* #setLoadingState updates UI to reflect loading state.
|
* #setLoadingState updates UI to reflect loading state.
|
||||||
* @param {boolean} loading
|
* @param {boolean} loading
|
||||||
@@ -1813,6 +1838,7 @@ class Odidere {
|
|||||||
#removeAttachment(index) {
|
#removeAttachment(index) {
|
||||||
this.attachments.splice(index, 1);
|
this.attachments.splice(index, 1);
|
||||||
this.#renderAttachments();
|
this.#renderAttachments();
|
||||||
|
this.#updateSendButtonState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user