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:
116
dexto/packages/webui/components/ToolConfirmationHandler.tsx
Normal file
116
dexto/packages/webui/components/ToolConfirmationHandler.tsx
Normal file
@@ -0,0 +1,116 @@
|
||||
import { useEffect, useCallback } from 'react';
|
||||
import { useSubmitApproval } from './hooks/useApprovals';
|
||||
import type { ApprovalRequest } from '@dexto/core';
|
||||
import { ApprovalStatus } from '@dexto/core';
|
||||
import { useSessionStore } from '@/lib/stores/sessionStore';
|
||||
import { useApprovalStore } from '@/lib/stores/approvalStore';
|
||||
|
||||
// Re-export ApprovalRequest as ApprovalEvent for consumers (e.g., InlineApprovalCard, MessageList)
|
||||
export type ApprovalEvent = ApprovalRequest;
|
||||
|
||||
interface ToolConfirmationHandlerProps {
|
||||
onApprovalRequest?: (approval: ApprovalEvent | null) => void;
|
||||
onApprove?: (formData?: Record<string, unknown>, rememberChoice?: boolean) => void;
|
||||
onDeny?: () => void;
|
||||
onHandlersReady?: (handlers: ApprovalHandlers) => void;
|
||||
}
|
||||
|
||||
export interface ApprovalHandlers {
|
||||
onApprove: (formData?: Record<string, unknown>, rememberChoice?: boolean) => void;
|
||||
onDeny: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebUI component for handling approval requests
|
||||
* Uses approvalStore for state management (no DOM events)
|
||||
* Sends responses back through API via useSubmitApproval
|
||||
*/
|
||||
export function ToolConfirmationHandler({
|
||||
onApprovalRequest,
|
||||
onApprove: externalOnApprove,
|
||||
onDeny: externalOnDeny,
|
||||
onHandlersReady,
|
||||
}: ToolConfirmationHandlerProps) {
|
||||
const currentSessionId = useSessionStore((s) => s.currentSessionId);
|
||||
const pendingApproval = useApprovalStore((s) => s.pendingApproval);
|
||||
const clearApproval = useApprovalStore((s) => s.clearApproval);
|
||||
const { mutateAsync: submitApproval } = useSubmitApproval();
|
||||
|
||||
// Filter approvals by current session
|
||||
const currentApproval =
|
||||
pendingApproval &&
|
||||
(!pendingApproval.sessionId ||
|
||||
!currentSessionId ||
|
||||
pendingApproval.sessionId === currentSessionId)
|
||||
? pendingApproval
|
||||
: null;
|
||||
|
||||
// Notify parent component when approval state changes
|
||||
useEffect(() => {
|
||||
onApprovalRequest?.(currentApproval);
|
||||
}, [currentApproval, onApprovalRequest]);
|
||||
|
||||
// Send confirmation response via API
|
||||
const sendResponse = useCallback(
|
||||
async (approved: boolean, formData?: Record<string, unknown>, rememberChoice?: boolean) => {
|
||||
if (!currentApproval) return;
|
||||
|
||||
const { approvalId } = currentApproval;
|
||||
|
||||
console.debug(
|
||||
`[WebUI] Sending approval response for ${approvalId}: ${approved ? 'approved' : 'denied'}`
|
||||
);
|
||||
|
||||
// Use approval's sessionId as authoritative source for cache invalidation
|
||||
const sessionId = currentApproval.sessionId || currentSessionId;
|
||||
if (!sessionId) {
|
||||
console.error('[WebUI] Cannot submit approval without sessionId');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await submitApproval({
|
||||
approvalId,
|
||||
sessionId,
|
||||
status: approved ? ApprovalStatus.APPROVED : ApprovalStatus.DENIED,
|
||||
...(approved && formData ? { formData } : {}),
|
||||
...(approved && rememberChoice !== undefined ? { rememberChoice } : {}),
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
console.error(`[WebUI] Failed to send approval response: ${message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear current approval (processes queue automatically)
|
||||
clearApproval();
|
||||
},
|
||||
[currentApproval, currentSessionId, submitApproval, clearApproval]
|
||||
);
|
||||
|
||||
const handleApprove = useCallback(
|
||||
(formData?: Record<string, unknown>, rememberChoice?: boolean) => {
|
||||
sendResponse(true, formData, rememberChoice);
|
||||
externalOnApprove?.(formData, rememberChoice);
|
||||
},
|
||||
[sendResponse, externalOnApprove]
|
||||
);
|
||||
|
||||
const handleDeny = useCallback(() => {
|
||||
sendResponse(false);
|
||||
externalOnDeny?.();
|
||||
}, [sendResponse, externalOnDeny]);
|
||||
|
||||
// Expose handlers to parent via callback
|
||||
useEffect(() => {
|
||||
if (onHandlersReady) {
|
||||
onHandlersReady({
|
||||
onApprove: handleApprove,
|
||||
onDeny: handleDeny,
|
||||
});
|
||||
}
|
||||
}, [handleApprove, handleDeny, onHandlersReady]);
|
||||
|
||||
// Don't render anything - the approval will be rendered in MessageList
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user