feat: add message queue functionality with auto-send and queue mode toggle

- Improved development server hot module replacement (HMR) by reusing OpenCode processes.
- Introduced queued message mode with batching and idle auto-send, including support for attachments.
- Added a toggle for queue mode in OpenChamber settings with persistence across sessions.
- Updated various components to handle queued messages, including ChatInput and QueuedMessageChips.
- Modified settings payload and desktop settings to include queue mode configuration.
- Enhanced message sending logic to support additional parts for queued messages.
This commit is contained in:
Bohdan Triapitsyn
2025-12-29 02:16:42 +02:00
parent aefbb1eac2
commit 66428cbded
15 changed files with 668 additions and 59 deletions
+14 -2
View File
@@ -351,7 +351,7 @@ interface MessageState {
interface MessageActions {
loadMessages: (sessionId: string) => Promise<void>;
sendMessage: (content: string, providerID: string, modelID: string, agent?: string, currentSessionId?: string, attachments?: AttachedFile[], agentMentionName?: string | null) => Promise<void>;
sendMessage: (content: string, providerID: string, modelID: string, agent?: string, currentSessionId?: string, attachments?: AttachedFile[], agentMentionName?: string | null, additionalParts?: Array<{ text: string; attachments?: AttachedFile[] }>) => Promise<void>;
abortCurrentOperation: (currentSessionId?: string) => Promise<void>;
_addStreamingPartImmediate: (sessionId: string, messageId: string, part: Part, role?: string, currentSessionId?: string) => void;
addStreamingPart: (sessionId: string, messageId: string, part: Part, role?: string, currentSessionId?: string) => void;
@@ -551,7 +551,7 @@ export const useMessageStore = create<MessageStore>()(
});
},
sendMessage: async (content: string, providerID: string, modelID: string, agent?: string, currentSessionId?: string, attachments?: AttachedFile[], agentMentionName?: string | null) => {
sendMessage: async (content: string, providerID: string, modelID: string, agent?: string, currentSessionId?: string, attachments?: AttachedFile[], agentMentionName?: string | null, additionalParts?: Array<{ text: string; attachments?: AttachedFile[] }>) => {
if (!currentSessionId) {
throw new Error("No session selected");
}
@@ -676,6 +676,17 @@ export const useMessageStore = create<MessageStore>()(
return { pendingAssistantHeaderSessions: next, pendingUserMessageMetaBySession: nextUserMeta };
});
// Convert additional parts to SDK format
const additionalPartsPayload = additionalParts?.map((part) => ({
text: part.text,
files: part.attachments?.map((file) => ({
type: "file" as const,
mime: file.mimeType,
filename: file.filename,
url: file.dataUrl,
})),
}));
await opencodeClient.sendMessage({
id: sessionId,
providerID,
@@ -683,6 +694,7 @@ export const useMessageStore = create<MessageStore>()(
text: effectiveContent,
agent,
files: filePayloads.length > 0 ? filePayloads : undefined,
additionalParts: additionalPartsPayload,
agentMentions: agentMentionName ? [{ name: agentMentionName }] : undefined,
});