feat: Add intelligent auto-router and enhanced integrations
- Add intelligent-router.sh hook for automatic agent routing - Add AUTO-TRIGGER-SUMMARY.md documentation - Add FINAL-INTEGRATION-SUMMARY.md documentation - Complete Prometheus integration (6 commands + 4 tools) - Complete Dexto integration (12 commands + 5 tools) - Enhanced Ralph with access to all agents - Fix /clawd command (removed disable-model-invocation) - Update hooks.json to v5 with intelligent routing - 291 total skills now available - All 21 commands with automatic routing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
145
dexto/packages/webui/components/hooks/useQueue.ts
Normal file
145
dexto/packages/webui/components/hooks/useQueue.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { client } from '@/lib/client';
|
||||
import { queryKeys } from '@/lib/queryKeys';
|
||||
|
||||
/**
|
||||
* Hook to fetch queued messages for a session
|
||||
*/
|
||||
export function useQueuedMessages(sessionId: string | null) {
|
||||
return useQuery({
|
||||
queryKey: queryKeys.queue.list(sessionId ?? ''),
|
||||
queryFn: async () => {
|
||||
if (!sessionId) return { messages: [], count: 0 };
|
||||
const response = await client.api.queue[':sessionId'].$get({
|
||||
param: { sessionId },
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch queued messages');
|
||||
}
|
||||
return await response.json();
|
||||
},
|
||||
enabled: !!sessionId,
|
||||
// Refetch frequently while processing to show queue updates
|
||||
refetchInterval: (query) => ((query.state.data?.count ?? 0) > 0 ? 2000 : false),
|
||||
});
|
||||
}
|
||||
|
||||
// Export type for queued message
|
||||
export type QueuedMessage = NonNullable<
|
||||
ReturnType<typeof useQueuedMessages>['data']
|
||||
>['messages'][number];
|
||||
|
||||
/**
|
||||
* Hook to queue a new message
|
||||
*/
|
||||
export function useQueueMessage() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({
|
||||
sessionId,
|
||||
message,
|
||||
imageData,
|
||||
fileData,
|
||||
}: {
|
||||
sessionId: string;
|
||||
message?: string;
|
||||
imageData?: { image: string; mimeType: string };
|
||||
fileData?: { data: string; mimeType: string; filename?: string };
|
||||
}) => {
|
||||
// Build content parts array from text, image, and file data
|
||||
// New API uses unified ContentInput = string | ContentPart[]
|
||||
const contentParts: Array<
|
||||
| { type: 'text'; text: string }
|
||||
| { type: 'image'; image: string; mimeType?: string }
|
||||
| { type: 'file'; data: string; mimeType: string; filename?: string }
|
||||
> = [];
|
||||
|
||||
if (message) {
|
||||
contentParts.push({ type: 'text', text: message });
|
||||
}
|
||||
if (imageData) {
|
||||
contentParts.push({
|
||||
type: 'image',
|
||||
image: imageData.image,
|
||||
mimeType: imageData.mimeType,
|
||||
});
|
||||
}
|
||||
if (fileData) {
|
||||
contentParts.push({
|
||||
type: 'file',
|
||||
data: fileData.data,
|
||||
mimeType: fileData.mimeType,
|
||||
filename: fileData.filename,
|
||||
});
|
||||
}
|
||||
|
||||
const response = await client.api.queue[':sessionId'].$post({
|
||||
param: { sessionId },
|
||||
json: {
|
||||
content:
|
||||
contentParts.length === 1 && contentParts[0]?.type === 'text'
|
||||
? message! // Simple text-only case: send as string
|
||||
: contentParts, // Multimodal: send as array
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to queue message');
|
||||
}
|
||||
return await response.json();
|
||||
},
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: queryKeys.queue.list(variables.sessionId),
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to remove a single queued message
|
||||
*/
|
||||
export function useRemoveQueuedMessage() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({ sessionId, messageId }: { sessionId: string; messageId: string }) => {
|
||||
const response = await client.api.queue[':sessionId'][':messageId'].$delete({
|
||||
param: { sessionId, messageId },
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to remove queued message');
|
||||
}
|
||||
return await response.json();
|
||||
},
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: queryKeys.queue.list(variables.sessionId),
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to clear all queued messages for a session
|
||||
*/
|
||||
export function useClearQueue() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (sessionId: string) => {
|
||||
const response = await client.api.queue[':sessionId'].$delete({
|
||||
param: { sessionId },
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to clear queue');
|
||||
}
|
||||
return await response.json();
|
||||
},
|
||||
onSuccess: (_, sessionId) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: queryKeys.queue.list(sessionId),
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user