feat: allow recording audio in workflow builder

This commit is contained in:
Abhishek Kumar 2026-03-25 15:01:39 +05:30
parent ac0731a374
commit 2fa4191d9b
22 changed files with 700 additions and 246 deletions

View file

@ -215,11 +215,7 @@ export default function CustomEdge(props: CustomEdgeProps) {
const handleSaveEdgeData = useCallback(async (updatedData: FlowEdgeData) => {
// Use the workflow store's updateEdge method to properly track history
updateEdge(id, { data: updatedData });
// Save the workflow after updating edge data with a small delay to ensure state is updated
setTimeout(async () => {
await saveWorkflow();
}, 100);
await saveWorkflow();
}, [id, updateEdge, saveWorkflow]);
return (

View file

@ -89,10 +89,7 @@ export const AgentNode = memo(({ data, selected, id }: AgentNodeProps) => {
document_uuids: documentUuids.length > 0 ? documentUuids : undefined,
});
setOpen(false);
// Save the workflow after updating node data with a small delay to ensure state is updated
setTimeout(async () => {
await saveWorkflow();
}, 100);
await saveWorkflow();
};
// Reset form state when dialog opens
@ -127,27 +124,23 @@ export const AgentNode = memo(({ data, selected, id }: AgentNodeProps) => {
}, [data, open]);
// Handle cleanup of stale document UUIDs
const handleStaleDocuments = useCallback((staleUuids: string[]) => {
const handleStaleDocuments = useCallback(async (staleUuids: string[]) => {
const cleanedUuids = (data.document_uuids ?? []).filter(uuid => !staleUuids.includes(uuid));
handleSaveNodeData({
...data,
document_uuids: cleanedUuids.length > 0 ? cleanedUuids : undefined,
});
setTimeout(async () => {
await saveWorkflow();
}, 100);
await saveWorkflow();
}, [data, handleSaveNodeData, saveWorkflow]);
// Handle cleanup of stale tool UUIDs
const handleStaleTools = useCallback((staleUuids: string[]) => {
const handleStaleTools = useCallback(async (staleUuids: string[]) => {
const cleanedUuids = (data.tool_uuids ?? []).filter(uuid => !staleUuids.includes(uuid));
handleSaveNodeData({
...data,
tool_uuids: cleanedUuids.length > 0 ? cleanedUuids : undefined,
});
setTimeout(async () => {
await saveWorkflow();
}, 100);
await saveWorkflow();
}, [data, handleSaveNodeData, saveWorkflow]);
return (

View file

@ -75,10 +75,7 @@ export const EndCall = memo(({ data, selected, id }: EndCallNodeProps) => {
add_global_prompt: addGlobalPrompt,
});
setOpen(false);
// Save the workflow after updating node data with a small delay to ensure state is updated
setTimeout(async () => {
await saveWorkflow();
}, 100);
await saveWorkflow();
};
// Reset form state when dialog opens

View file

@ -52,10 +52,7 @@ export const GlobalNode = memo(({ data, selected, id }: GlobalNodeProps) => {
name
});
setOpen(false);
// Save the workflow after updating node data with a small delay to ensure state is updated
setTimeout(async () => {
await saveWorkflow();
}, 100);
await saveWorkflow();
};
// Reset form state when dialog opens

View file

@ -66,9 +66,7 @@ export const QANode = memo(({ data, selected, id }: QANodeProps) => {
qa_sample_rate: qaSampleRate,
});
setOpen(false);
setTimeout(async () => {
await saveWorkflow();
}, 100);
await saveWorkflow();
};
const resetFormState = () => {

View file

@ -104,10 +104,7 @@ export const StartCall = memo(({ data, selected, id }: StartCallNodeProps) => {
document_uuids: documentUuids.length > 0 ? documentUuids : undefined,
});
setOpen(false);
// Save the workflow after updating node data with a small delay to ensure state is updated
setTimeout(async () => {
await saveWorkflow();
}, 100);
await saveWorkflow();
};
// Reset form state when dialog opens
@ -148,27 +145,23 @@ export const StartCall = memo(({ data, selected, id }: StartCallNodeProps) => {
}, [data, open]);
// Handle cleanup of stale document UUIDs
const handleStaleDocuments = useCallback((staleUuids: string[]) => {
const handleStaleDocuments = useCallback(async (staleUuids: string[]) => {
const cleanedUuids = (data.document_uuids ?? []).filter(uuid => !staleUuids.includes(uuid));
handleSaveNodeData({
...data,
document_uuids: cleanedUuids.length > 0 ? cleanedUuids : undefined,
});
setTimeout(async () => {
await saveWorkflow();
}, 100);
await saveWorkflow();
}, [data, handleSaveNodeData, saveWorkflow]);
// Handle cleanup of stale tool UUIDs
const handleStaleTools = useCallback((staleUuids: string[]) => {
const handleStaleTools = useCallback(async (staleUuids: string[]) => {
const cleanedUuids = (data.tool_uuids ?? []).filter(uuid => !staleUuids.includes(uuid));
handleSaveNodeData({
...data,
tool_uuids: cleanedUuids.length > 0 ? cleanedUuids : undefined,
});
setTimeout(async () => {
await saveWorkflow();
}, 100);
await saveWorkflow();
}, [data, handleSaveNodeData, saveWorkflow]);
return (

View file

@ -61,10 +61,7 @@ export const TriggerNode = memo(({ data, selected, id }: TriggerNodeProps) => {
trigger_path: triggerPath,
});
setOpen(false);
// Save the workflow after updating node data
setTimeout(async () => {
await saveWorkflow();
}, 100);
await saveWorkflow();
};
// Reset form state when dialog opens

View file

@ -86,9 +86,7 @@ export const WebhookNode = memo(({ data, selected, id }: WebhookNodeProps) => {
payload_template: validation.parsed as Record<string, unknown>,
});
setOpen(false);
setTimeout(async () => {
await saveWorkflow();
}, 100);
await saveWorkflow();
};
const handleOpenChange = (newOpen: boolean) => {

View file

@ -71,12 +71,13 @@ export const NodeEditDialog = ({
const handleKeyDown = (e: KeyboardEvent) => {
if ((e.metaKey || e.ctrlKey) && e.key === 's') {
e.preventDefault();
e.stopImmediatePropagation();
handleSave();
}
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
window.addEventListener('keydown', handleKeyDown, true);
return () => window.removeEventListener('keydown', handleKeyDown, true);
}, [open, handleSave]);
return (