adding a queue system to the agent runner

This commit is contained in:
Test User
2025-12-26 10:59:13 -05:00
parent f95282069d
commit 17c1c733b7
24 changed files with 1753 additions and 65 deletions

View File

@@ -12,6 +12,15 @@ interface UseElectronAgentOptions {
onToolUse?: (toolName: string, toolInput: unknown) => void;
}
// Server-side queued prompt type
interface QueuedPrompt {
id: string;
message: string;
imagePaths?: string[];
model?: string;
addedAt: string;
}
interface UseElectronAgentResult {
messages: Message[];
isProcessing: boolean;
@@ -24,7 +33,7 @@ interface UseElectronAgentResult {
stopExecution: () => Promise<void>;
clearHistory: () => Promise<void>;
error: string | null;
// Queue-related state
// Client-side queue (local)
queuedMessages: {
id: string;
content: string;
@@ -34,6 +43,15 @@ interface UseElectronAgentResult {
}[];
isQueueProcessing: boolean;
clearMessageQueue: () => void;
// Server-side queue (persistent, auto-runs)
serverQueue: QueuedPrompt[];
addToServerQueue: (
message: string,
images?: ImageAttachment[],
textFiles?: TextFileAttachment[]
) => Promise<void>;
removeFromServerQueue: (promptId: string) => Promise<void>;
clearServerQueue: () => Promise<void>;
}
/**
@@ -52,6 +70,7 @@ export function useElectronAgent({
const [isProcessing, setIsProcessing] = useState(false);
const [isConnected, setIsConnected] = useState(false);
const [error, setError] = useState<string | null>(null);
const [serverQueue, setServerQueue] = useState<QueuedPrompt[]>([]);
const unsubscribeRef = useRef<(() => void) | null>(null);
const currentMessageRef = useRef<Message | null>(null);
@@ -231,6 +250,12 @@ export function useElectronAgent({
console.log('[useElectronAgent] Stream event for', sessionId, ':', event.type);
switch (event.type) {
case 'started':
// Agent started processing (including from queue)
console.log('[useElectronAgent] Agent started processing for session:', sessionId);
setIsProcessing(true);
break;
case 'message':
// User message added
setMessages((prev) => [...prev, event.message]);
@@ -299,6 +324,18 @@ export function useElectronAgent({
setMessages((prev) => [...prev, errorMessage]);
}
break;
case 'queue_updated':
// Server queue was updated
console.log('[useElectronAgent] Queue updated:', event.queue);
setServerQueue(event.queue || []);
break;
case 'queue_error':
// Error processing a queued prompt
console.error('[useElectronAgent] Queue error:', event.error);
setError(event.error);
break;
}
};
@@ -438,6 +475,102 @@ export function useElectronAgent({
}
}, [sessionId]);
// Add a prompt to the server queue (will auto-run when current task finishes)
const addToServerQueue = useCallback(
async (message: string, images?: ImageAttachment[], textFiles?: TextFileAttachment[]) => {
const api = getElectronAPI();
if (!api?.agent?.queueAdd) {
setError('Queue API not available');
return;
}
try {
// Build message content with text file context
let messageContent = message;
if (textFiles && textFiles.length > 0) {
const contextParts = textFiles.map((file) => {
return `<file name="${file.filename}">\n${file.content}\n</file>`;
});
const contextBlock = `Here are some files for context:\n\n${contextParts.join('\n\n')}\n\n`;
messageContent = contextBlock + message;
}
// Save images and get paths
let imagePaths: string[] | undefined;
if (images && images.length > 0 && api.saveImageToTemp) {
imagePaths = [];
for (const image of images) {
const result = await api.saveImageToTemp(
image.data,
sanitizeFilename(image.filename),
image.mimeType,
workingDirectory
);
if (result.success && result.path) {
imagePaths.push(result.path);
}
}
}
console.log('[useElectronAgent] Adding to server queue');
const result = await api.agent.queueAdd(sessionId, messageContent, imagePaths, model);
if (!result.success) {
setError(result.error || 'Failed to add to queue');
}
} catch (err) {
console.error('[useElectronAgent] Failed to add to queue:', err);
setError(err instanceof Error ? err.message : 'Failed to add to queue');
}
},
[sessionId, workingDirectory, model]
);
// Remove a prompt from the server queue
const removeFromServerQueue = useCallback(
async (promptId: string) => {
const api = getElectronAPI();
if (!api?.agent?.queueRemove) {
setError('Queue API not available');
return;
}
try {
console.log('[useElectronAgent] Removing from server queue:', promptId);
const result = await api.agent.queueRemove(sessionId, promptId);
if (!result.success) {
setError(result.error || 'Failed to remove from queue');
}
} catch (err) {
console.error('[useElectronAgent] Failed to remove from queue:', err);
setError(err instanceof Error ? err.message : 'Failed to remove from queue');
}
},
[sessionId]
);
// Clear the entire server queue
const clearServerQueue = useCallback(async () => {
const api = getElectronAPI();
if (!api?.agent?.queueClear) {
setError('Queue API not available');
return;
}
try {
console.log('[useElectronAgent] Clearing server queue');
const result = await api.agent.queueClear(sessionId);
if (!result.success) {
setError(result.error || 'Failed to clear queue');
}
} catch (err) {
console.error('[useElectronAgent] Failed to clear queue:', err);
setError(err instanceof Error ? err.message : 'Failed to clear queue');
}
}, [sessionId]);
return {
messages,
isProcessing,
@@ -449,5 +582,10 @@ export function useElectronAgent({
queuedMessages,
isQueueProcessing: isProcessingQueue,
clearMessageQueue: clearQueue,
// Server-side queue
serverQueue,
addToServerQueue,
removeFromServerQueue,
clearServerQueue,
};
}