From 5da020416351007094c482b0115e6e18401461d2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 27 Mar 2026 11:35:18 +0100 Subject: [PATCH] feat: enhance canvas and node components with error handling and retry logic - Integrated retry logic for AI image generation to handle transient errors and improve user experience. - Updated error categorization to provide more informative feedback based on different failure scenarios. - Enhanced node components to display retry attempts and error messages, improving visibility during image generation failures. - Refactored canvas and node components to include retry count in status updates, ensuring accurate tracking of generation attempts. --- .cursor/debug-594b9f.log | 154 +++++++++ app/(app)/canvas/[canvasId]/error.tsx | 37 +++ app/(app)/canvas/[canvasId]/page.tsx | 4 +- app/error.tsx | 43 +++ app/global-error.tsx | 40 +++ app/layout.tsx | 2 - components/canvas/canvas.tsx | 61 ++++ components/canvas/connection-banner.tsx | 112 +++++++ components/canvas/credit-display.tsx | 2 +- components/canvas/nodes/ai-image-node.tsx | 85 ++++- components/canvas/nodes/base-node-wrapper.tsx | 5 +- components/canvas/nodes/compare-node.tsx | 2 +- components/canvas/nodes/frame-node.tsx | 1 + components/canvas/nodes/group-node.tsx | 1 + components/canvas/nodes/image-node.tsx | 2 +- .../canvas/nodes/node-error-boundary.tsx | 66 ++++ components/canvas/nodes/note-node.tsx | 2 +- components/canvas/nodes/prompt-node.tsx | 1 + components/canvas/nodes/text-node.tsx | 7 +- components/dashboard/canvas-card.tsx | 2 +- components/providers.tsx | 2 + components/ui/sonner.tsx | 6 +- convex/ai.ts | 185 ++++++++++- convex/nodes.ts | 13 +- convex/schema.ts | 1 + lib/ai-errors.ts | 296 ++++++++++++++++++ lib/canvas-utils.ts | 1 + lib/toast.ts | 82 +++++ 28 files changed, 1180 insertions(+), 35 deletions(-) create mode 100644 .cursor/debug-594b9f.log create mode 100644 app/(app)/canvas/[canvasId]/error.tsx create mode 100644 app/error.tsx create mode 100644 app/global-error.tsx create mode 100644 components/canvas/connection-banner.tsx create mode 100644 components/canvas/nodes/node-error-boundary.tsx create mode 100644 lib/ai-errors.ts create mode 100644 lib/toast.ts diff --git a/.cursor/debug-594b9f.log b/.cursor/debug-594b9f.log new file mode 100644 index 0000000..bb0b30b --- /dev/null +++ b/.cursor/debug-594b9f.log @@ -0,0 +1,154 @@ +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606648051} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":6,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","source":"js79syh9wc7n20m6fg9r1191q183msb2","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false}]},"timestamp":1774606648051} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606648051} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606648052} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606648051} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606648052} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606648052} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606648052} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606648051} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":6,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","source":"js79syh9wc7n20m6fg9r1191q183msb2","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false}]},"timestamp":1774606648052} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","sourceNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606648052} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606648052} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606648051} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","sourceNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606648051} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606657711} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606657711} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606657711} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606657711} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":7,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","source":"js79syh9wc7n20m6fg9r1191q183msb2","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false}]},"timestamp":1774606657711} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606657711} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606657712} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606657712} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606657712} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606657712} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606657712} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606657711} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","sourceNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606657712} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606657712} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","sourceNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606657711} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":7,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","source":"js79syh9wc7n20m6fg9r1191q183msb2","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false}]},"timestamp":1774606657712} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","sourceNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn76zkdqqkxnpkghrwaevm3j3x83qyyx","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js7380wns03f3m9zr10qfev0wn83q0nv","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":8,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","source":"js79syh9wc7n20m6fg9r1191q183msb2","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn76zkdqqkxnpkghrwaevm3j3x83qyyx","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js7380wns03f3m9zr10qfev0wn83q0nv","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false}]},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn76zkdqqkxnpkghrwaevm3j3x83qyyx","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js7380wns03f3m9zr10qfev0wn83q0nv","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606661453} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","sourceNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606661452} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":8,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","source":"js79syh9wc7n20m6fg9r1191q183msb2","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn76zkdqqkxnpkghrwaevm3j3x83qyyx","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js7380wns03f3m9zr10qfev0wn83q0nv","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false}]},"timestamp":1774606661453} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606680465} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":7,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","source":"js79syh9wc7n20m6fg9r1191q183msb2","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false}]},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","sourceNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","sourceNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":7,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","source":"js79syh9wc7n20m6fg9r1191q183msb2","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false}]},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606680466} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606684760} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606684760} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606684760} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606684760} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606684760} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","sourceNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606684760} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606684760} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn741xv0z6ttznkfncsaansnz983qbse","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79vt1be2c1zab58j94ydfzp183pqdg","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606684760} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":8,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","source":"js79syh9wc7n20m6fg9r1191q183msb2","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn741xv0z6ttznkfncsaansnz983qbse","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79vt1be2c1zab58j94ydfzp183pqdg","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false}]},"timestamp":1774606684760} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606684760} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606684760} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606684760} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606684761} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","sourceNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606684761} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn741xv0z6ttznkfncsaansnz983qbse","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79vt1be2c1zab58j94ydfzp183pqdg","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606684761} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606684761} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606684761} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":8,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","source":"js79syh9wc7n20m6fg9r1191q183msb2","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn741xv0z6ttznkfncsaansnz983qbse","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79vt1be2c1zab58j94ydfzp183pqdg","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false}]},"timestamp":1774606684761} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7a560btkzv97yv0qvk8ep1yd83qmn2","sourceNodeId":"js79vt1be2c1zab58j94ydfzp183pqdg","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606811015} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7a560btkzv97yv0qvk8ep1yd83qmn2","sourceNodeId":"js79vt1be2c1zab58j94ydfzp183pqdg","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","sourceNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn741xv0z6ttznkfncsaansnz983qbse","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79vt1be2c1zab58j94ydfzp183pqdg","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","sourceNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn741xv0z6ttznkfncsaansnz983qbse","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79vt1be2c1zab58j94ydfzp183pqdg","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":9,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","source":"js79syh9wc7n20m6fg9r1191q183msb2","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn741xv0z6ttznkfncsaansnz983qbse","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79vt1be2c1zab58j94ydfzp183pqdg","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7a560btkzv97yv0qvk8ep1yd83qmn2","source":"js79vt1be2c1zab58j94ydfzp183pqdg","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false}]},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":9,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn72b68knm8y5tvjj6a6fj6h8n83n9a7","source":"js79syh9wc7n20m6fg9r1191q183msb2","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn741xv0z6ttznkfncsaansnz983qbse","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79vt1be2c1zab58j94ydfzp183pqdg","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7a560btkzv97yv0qvk8ep1yd83qmn2","source":"js79vt1be2c1zab58j94ydfzp183pqdg","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false}]},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606811016} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":8,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn741xv0z6ttznkfncsaansnz983qbse","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79vt1be2c1zab58j94ydfzp183pqdg","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7a560btkzv97yv0qvk8ep1yd83qmn2","source":"js79vt1be2c1zab58j94ydfzp183pqdg","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false}]},"timestamp":1774606822672} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606822672} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606822671} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":8,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn741xv0z6ttznkfncsaansnz983qbse","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79vt1be2c1zab58j94ydfzp183pqdg","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7a560btkzv97yv0qvk8ep1yd83qmn2","source":"js79vt1be2c1zab58j94ydfzp183pqdg","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false}]},"timestamp":1774606822672} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7a560btkzv97yv0qvk8ep1yd83qmn2","sourceNodeId":"js79vt1be2c1zab58j94ydfzp183pqdg","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606822672} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606822672} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606822671} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606822671} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606822671} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn741xv0z6ttznkfncsaansnz983qbse","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79vt1be2c1zab58j94ydfzp183pqdg","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606822672} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606822672} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606822672} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606822672} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606822672} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606822672} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606822672} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7a560btkzv97yv0qvk8ep1yd83qmn2","sourceNodeId":"js79vt1be2c1zab58j94ydfzp183pqdg","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606822672} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn741xv0z6ttznkfncsaansnz983qbse","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79vt1be2c1zab58j94ydfzp183pqdg","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606822672} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606827178} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606827179} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606827179} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606827179} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606827179} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606827179} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn741xv0z6ttznkfncsaansnz983qbse","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79vt1be2c1zab58j94ydfzp183pqdg","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606827179} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":7,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn741xv0z6ttznkfncsaansnz983qbse","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79vt1be2c1zab58j94ydfzp183pqdg","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false}]},"timestamp":1774606827179} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606827179} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606827179} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606827179} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606827179} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":7,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn741xv0z6ttznkfncsaansnz983qbse","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79vt1be2c1zab58j94ydfzp183pqdg","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false}]},"timestamp":1774606827180} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606827179} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn741xv0z6ttznkfncsaansnz983qbse","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79vt1be2c1zab58j94ydfzp183pqdg","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606827180} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606827179} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606828375} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606828374} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn741xv0z6ttznkfncsaansnz983qbse","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79vt1be2c1zab58j94ydfzp183pqdg","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606828375} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":8,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn741xv0z6ttznkfncsaansnz983qbse","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79vt1be2c1zab58j94ydfzp183pqdg","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7cx57f8hss73bxy5qxbc4v7183qjt4","source":"js79syh9wc7n20m6fg9r1191q183msb2","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false}]},"timestamp":1774606828375} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606828375} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606828376} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606828375} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7axgmhqz0gkt6sndpq6ersch83nysx","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606828375} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn78rknrhj507t3e123ba7ebqn83pnx4","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606828376} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606828375} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","sourceNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"left","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"left"},"timestamp":1774606828376} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H2","location":"canvas.tsx:edgeSyncEffect","message":"edges passed to ReactFlow","data":{"edgeCount":8,"edges":[{"id":"jn7axgmhqz0gkt6sndpq6ersch83nysx","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7242a6vnazmg729y2nwfb4vx83nqgf","source":"js7bbr471t9fqerb27eh3p0ksd83n82c","target":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetHandle":"image-in","typeofTH":"string","isNullTH":false},{"id":"jn7b8ee3z6p073bdecght4ba5d83m5mv","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7fr15mb7ds98dvw9w2wjj89983naj6","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79syh9wc7n20m6fg9r1191q183msb2","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn79n3spvbdrqfgf9wd7h1rvgx83nrtv","source":"js7fr15mb7ds98dvw9w2wjj89983naj6","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"left","typeofTH":"string","isNullTH":false},{"id":"jn78rknrhj507t3e123ba7ebqn83pnx4","source":"js7ak7hkab3rpnxqc6xdzjphx583m665","target":"js7df78fpx4gpt1n50fj6hwyjs83pzxf","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn741xv0z6ttznkfncsaansnz983qbse","source":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","target":"js79vt1be2c1zab58j94ydfzp183pqdg","sourceHandle":"prompt-out","targetHandle":"prompt-in","typeofTH":"string","isNullTH":false},{"id":"jn7cx57f8hss73bxy5qxbc4v7183qjt4","source":"js79syh9wc7n20m6fg9r1191q183msb2","target":"js7cpdwr5v40hw20w55f2cet5583n1g7","sourceHandle":"image-out","targetHandle":"right","typeofTH":"string","isNullTH":false}]},"timestamp":1774606828376} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7cx57f8hss73bxy5qxbc4v7183qjt4","sourceNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606828376} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7b8ee3z6p073bdecght4ba5d83m5mv","sourceNodeId":"js7ak7hkab3rpnxqc6xdzjphx583m665","targetNodeId":"js7fr15mb7ds98dvw9w2wjj89983naj6","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606828375} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7242a6vnazmg729y2nwfb4vx83nqgf","sourceNodeId":"js7bbr471t9fqerb27eh3p0ksd83n82c","targetNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","rawTargetHandle":"image-in","typeofSourceHandle":"undefined","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":true,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedTH":"image-in"},"timestamp":1774606828375} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn741xv0z6ttznkfncsaansnz983qbse","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79vt1be2c1zab58j94ydfzp183pqdg","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606828376} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7cx57f8hss73bxy5qxbc4v7183qjt4","sourceNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","targetNodeId":"js7cpdwr5v40hw20w55f2cet5583n1g7","rawSourceHandle":"image-out","rawTargetHandle":"right","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"image-out","sanitizedTH":"right"},"timestamp":1774606828375} +{"sessionId":"594b9f","runId":"run1","hypothesisId":"H1-H3-H4","location":"canvas-utils.ts:convexEdgeToRF","message":"raw edge from convex","data":{"edgeId":"jn7frrkcn95k984f9w1b7vcv4x83mgpb","sourceNodeId":"js7dt20y2wyrt6mk1e1aee2pgd83mh4e","targetNodeId":"js79syh9wc7n20m6fg9r1191q183msb2","rawSourceHandle":"prompt-out","rawTargetHandle":"prompt-in","typeofSourceHandle":"string","typeofTargetHandle":"string","isNullSH":false,"isNullTH":false,"isUndefinedSH":false,"isUndefinedTH":false,"isStringNullSH":false,"isStringNullTH":false,"sanitizedSH":"prompt-out","sanitizedTH":"prompt-in"},"timestamp":1774606828376} diff --git a/app/(app)/canvas/[canvasId]/error.tsx b/app/(app)/canvas/[canvasId]/error.tsx new file mode 100644 index 0000000..1cc154d --- /dev/null +++ b/app/(app)/canvas/[canvasId]/error.tsx @@ -0,0 +1,37 @@ +"use client"; + +import Link from "next/link"; + +import { Button } from "@/components/ui/button"; + +type CanvasErrorProps = { + error: Error & { digest?: string }; + unstable_retry: () => void; +}; + +export default function CanvasError({ error, unstable_retry }: CanvasErrorProps) { + return ( +
+
+
+

Canvas konnte nicht geladen werden

+

+ Beim Laden dieses Canvas ist ein Fehler aufgetreten. +

+ {error.digest ? ( +

Fehler-ID: {error.digest}

+ ) : null} +
+ +
+ + +
+
+
+ ); +} diff --git a/app/(app)/canvas/[canvasId]/page.tsx b/app/(app)/canvas/[canvasId]/page.tsx index 1864148..0525a1f 100644 --- a/app/(app)/canvas/[canvasId]/page.tsx +++ b/app/(app)/canvas/[canvasId]/page.tsx @@ -1,6 +1,7 @@ import { notFound, redirect } from "next/navigation"; import Canvas from "@/components/canvas/canvas"; +import ConnectionBanner from "@/components/canvas/connection-banner"; import CanvasSidebar from "@/components/canvas/canvas-sidebar"; import { api } from "@/convex/_generated/api"; import type { Id } from "@/convex/_generated/dataModel"; @@ -50,7 +51,8 @@ export default async function CanvasPage({ return (
-
+
+
diff --git a/app/error.tsx b/app/error.tsx new file mode 100644 index 0000000..a4a4bfa --- /dev/null +++ b/app/error.tsx @@ -0,0 +1,43 @@ +"use client"; + +import { useEffect } from "react"; + +import { Button } from "@/components/ui/button"; + +type AppErrorProps = { + error: Error & { digest?: string }; + unstable_retry: () => void; +}; + +export default function AppError({ error, unstable_retry }: AppErrorProps) { + useEffect(() => { + const safeError = { + name: error.name, + message: + process.env.NODE_ENV === "development" + ? error.message + : "Unexpected application error", + digest: error.digest, + }; + + console.error("[app/error]", safeError); + }, [error]); + + return ( +
+
+
+

Etwas ist schiefgelaufen

+

+ Wir konnten diesen Bereich nicht laden. Du kannst es direkt erneut + versuchen. +

+
+ + +
+
+ ); +} diff --git a/app/global-error.tsx b/app/global-error.tsx new file mode 100644 index 0000000..c360426 --- /dev/null +++ b/app/global-error.tsx @@ -0,0 +1,40 @@ +"use client"; + +import { Button } from "@/components/ui/button"; + +type GlobalErrorProps = { + error: Error & { digest?: string }; + unstable_retry: () => void; +}; + +export default function GlobalError({ + error, + unstable_retry, +}: GlobalErrorProps) { + return ( + + +
+
+
+

Schwerer Fehler

+

+ Die Anwendung konnte nicht dargestellt werden. Lade den Bereich + neu, um fortzufahren. +

+ {error.digest ? ( +

+ Fehler-ID: {error.digest} +

+ ) : null} +
+ + +
+
+ + + ); +} diff --git a/app/layout.tsx b/app/layout.tsx index e92e713..0f061e2 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -3,7 +3,6 @@ import { Manrope } from "next/font/google"; import "./globals.css"; import { cn } from "@/lib/utils"; import { Providers } from "@/components/providers"; -import { Toaster } from "@/components/ui/sonner"; import { InitUser } from "@/components/init-user"; import { getToken } from "@/lib/auth-server"; @@ -31,7 +30,6 @@ export default async function RootLayout({ {children} - diff --git a/components/canvas/canvas.tsx b/components/canvas/canvas.tsx index 14d2237..baa81e2 100644 --- a/components/canvas/canvas.tsx +++ b/components/canvas/canvas.tsx @@ -21,6 +21,7 @@ import { BackgroundVariant, } from "@xyflow/react"; import "@xyflow/react/dist/style.css"; +import { toast } from "@/lib/toast"; import { useConvexAuth, useMutation, useQuery } from "convex/react"; import { api } from "@/convex/_generated/api"; @@ -113,6 +114,9 @@ const EDGE_INTERSECTION_HIGHLIGHT_STYLE: NonNullable = { strokeWidth: 2, }; +const GENERATION_FAILURE_WINDOW_MS = 5 * 60 * 1000; +const GENERATION_FAILURE_THRESHOLD = 3; + function getEdgeIdFromInteractionElement(element: Element): string | null { const edgeContainer = element.closest(".react-flow__edge"); if (!edgeContainer) return null; @@ -249,6 +253,63 @@ function CanvasInner({ canvasId }: CanvasInnerProps) { const highlightedEdgeOriginalStyleRef = useRef( undefined, ); + const recentGenerationFailureTimestampsRef = useRef([]); + const previousNodeStatusRef = useRef>(new Map()); + const hasInitializedGenerationFailureTrackingRef = useRef(false); + + useEffect(() => { + if (!convexNodes) return; + + const nextNodeStatusMap = new Map(); + let detectedGenerationFailures = 0; + + for (const node of convexNodes) { + nextNodeStatusMap.set(node._id, node.status); + + if (node.type !== "ai-image") { + continue; + } + + const previousStatus = previousNodeStatusRef.current.get(node._id); + if ( + hasInitializedGenerationFailureTrackingRef.current && + node.status === "error" && + previousStatus !== "error" + ) { + detectedGenerationFailures += 1; + } + } + + previousNodeStatusRef.current = nextNodeStatusMap; + + if (!hasInitializedGenerationFailureTrackingRef.current) { + hasInitializedGenerationFailureTrackingRef.current = true; + return; + } + + if (detectedGenerationFailures === 0) { + return; + } + + const now = Date.now(); + const recentFailures = recentGenerationFailureTimestampsRef.current.filter( + (timestamp) => now - timestamp <= GENERATION_FAILURE_WINDOW_MS, + ); + + for (let index = 0; index < detectedGenerationFailures; index += 1) { + recentFailures.push(now); + } + + if (recentFailures.length >= GENERATION_FAILURE_THRESHOLD) { + toast.error( + "Mehrere Generierungen sind fehlgeschlagen. Bitte Prompt, Modell oder Credits prüfen.", + ); + recentGenerationFailureTimestampsRef.current = []; + return; + } + + recentGenerationFailureTimestampsRef.current = recentFailures; + }, [convexNodes]); // ─── Convex → Lokaler State Sync ────────────────────────────── useEffect(() => { diff --git a/components/canvas/connection-banner.tsx b/components/canvas/connection-banner.tsx new file mode 100644 index 0000000..d352e77 --- /dev/null +++ b/components/canvas/connection-banner.tsx @@ -0,0 +1,112 @@ +"use client"; + +import { useEffect, useMemo, useRef, useState } from "react"; +import { useConvexConnectionState } from "convex/react"; + +import { cn } from "@/lib/utils"; + +type BannerState = "hidden" | "reconnecting" | "disconnected" | "reconnected"; + +const RECONNECTED_HIDE_DELAY_MS = 1800; + +export default function ConnectionBanner() { + const connectionState = useConvexConnectionState(); + const previousConnectedRef = useRef(connectionState.isWebSocketConnected); + const [showReconnected, setShowReconnected] = useState(false); + const [isBrowserOnline, setIsBrowserOnline] = useState( + typeof navigator === "undefined" ? true : navigator.onLine, + ); + + useEffect(() => { + const handleOnline = () => setIsBrowserOnline(true); + const handleOffline = () => setIsBrowserOnline(false); + + window.addEventListener("online", handleOnline); + window.addEventListener("offline", handleOffline); + + return () => { + window.removeEventListener("online", handleOnline); + window.removeEventListener("offline", handleOffline); + }; + }, []); + + useEffect(() => { + const wasConnected = previousConnectedRef.current; + const isConnected = connectionState.isWebSocketConnected; + const didReconnect = !wasConnected && isConnected && connectionState.connectionCount > 1; + + if (didReconnect) { + setShowReconnected(true); + } + + if (!isConnected) { + setShowReconnected(false); + } + + previousConnectedRef.current = isConnected; + }, [connectionState.connectionCount, connectionState.isWebSocketConnected]); + + useEffect(() => { + if (!showReconnected) { + return; + } + + const timeoutId = window.setTimeout(() => { + setShowReconnected(false); + }, RECONNECTED_HIDE_DELAY_MS); + + return () => window.clearTimeout(timeoutId); + }, [showReconnected]); + + const bannerState = useMemo(() => { + if (connectionState.isWebSocketConnected) { + return showReconnected ? "reconnected" : "hidden"; + } + + if (!isBrowserOnline) { + return "disconnected"; + } + + if (connectionState.hasEverConnected || connectionState.connectionRetries > 0) { + return "reconnecting"; + } + + return "hidden"; + }, [ + connectionState.connectionRetries, + connectionState.hasEverConnected, + connectionState.isWebSocketConnected, + isBrowserOnline, + showReconnected, + ]); + + if (bannerState === "hidden") { + return null; + } + + const contentByState: Record, { dotClass: string; text: string }> = { + reconnecting: { + dotClass: "bg-amber-500", + text: "Verbindung wird wiederhergestellt…", + }, + disconnected: { + dotClass: "bg-destructive", + text: "Keine Verbindung. Wir verbinden uns automatisch erneut.", + }, + reconnected: { + dotClass: "bg-emerald-500", + text: "Verbindung wiederhergestellt", + }, + }; + + const content = contentByState[bannerState]; + + return ( +
+
+
+
+ ); +} diff --git a/components/canvas/credit-display.tsx b/components/canvas/credit-display.tsx index f9f4c68..b6e0d95 100644 --- a/components/canvas/credit-display.tsx +++ b/components/canvas/credit-display.tsx @@ -3,7 +3,7 @@ import { useMutation, useQuery } from "convex/react"; import { api } from "@/convex/_generated/api"; import { Coins } from "lucide-react"; -import { toast } from "sonner"; +import { toast } from "@/lib/toast"; const TIER_LABELS: Record = { free: "Free", diff --git a/components/canvas/nodes/ai-image-node.tsx b/components/canvas/nodes/ai-image-node.tsx index a263cac..0152a63 100644 --- a/components/canvas/nodes/ai-image-node.tsx +++ b/components/canvas/nodes/ai-image-node.tsx @@ -1,12 +1,14 @@ "use client"; import { useCallback, useState } from "react"; +import { useRouter } from "next/navigation"; import { Handle, Position, useReactFlow, type NodeProps, type Node } from "@xyflow/react"; import { useAction } from "convex/react"; import { api } from "@/convex/_generated/api"; import type { Id } from "@/convex/_generated/dataModel"; import BaseNodeWrapper from "./base-node-wrapper"; import { DEFAULT_MODEL_ID, getModel } from "@/lib/ai-models"; +import { classifyError, type AiErrorCategory } from "@/lib/ai-errors"; import { DEFAULT_ASPECT_RATIO } from "@/lib/image-formats"; import { Loader2, @@ -14,6 +16,9 @@ import { RefreshCw, ImageIcon, Coins, + Clock3, + ShieldAlert, + WifiOff, } from "lucide-react"; type AiImageNodeData = { @@ -31,6 +36,7 @@ type AiImageNodeData = { aspectRatio?: string; outputWidth?: number; outputHeight?: number; + retryCount?: number; _status?: string; _statusMessage?: string; }; @@ -52,6 +58,7 @@ export default function AiImageNode({ }: NodeProps) { const nodeData = data as AiImageNodeData; const { getEdges, getNode } = useReactFlow(); + const router = useRouter(); const [isGenerating, setIsGenerating] = useState(false); const [localError, setLocalError] = useState(null); @@ -60,6 +67,12 @@ export default function AiImageNode({ const status = (nodeData._status ?? "idle") as NodeStatus; const errorMessage = nodeData._statusMessage; + const classifiedError = classifyError(errorMessage ?? localError); + + const executingRetryCount = + typeof nodeData.retryCount === "number" + ? nodeData.retryCount + : classifiedError.retryCount; const isLoading = status === "executing" || @@ -111,8 +124,25 @@ export default function AiImageNode({ const modelName = getModel(nodeData.model ?? DEFAULT_MODEL_ID)?.name ?? "AI"; + const renderErrorIcon = (category: AiErrorCategory) => { + switch (category) { + case "insufficient_credits": + return ; + case "rate_limited": + case "timeout": + return ; + case "content_policy": + return ; + case "network": + return ; + default: + return ; + } + }; + return ( @@ -151,6 +181,13 @@ export default function AiImageNode({ {status === "clarifying" && "Clarifying…"} {(status === "executing" || isGenerating) && "Generating…"}

+ {(status === "executing" || isGenerating) && + typeof executingRetryCount === "number" && + executingRetryCount > 0 && ( +

+ Retry attempt {executingRetryCount} +

+ )}

{modelName}

@@ -159,22 +196,42 @@ export default function AiImageNode({ {status === "error" && !isLoading && (
- + {renderErrorIcon(classifiedError.category)}

- Generation failed + {classifiedError.message}

-

- {errorMessage ?? localError ?? "Unknown error"} — Credits not - charged -

- + {classifiedError.detail && ( +

+ {classifiedError.detail} +

+ )} + {classifiedError.creditsNotCharged && ( +

+ Credits not charged +

+ )} +
+ {classifiedError.showTopUp && ( + + )} + {classifiedError.retryable && ( + + )} +
)} diff --git a/components/canvas/nodes/base-node-wrapper.tsx b/components/canvas/nodes/base-node-wrapper.tsx index fd7b51c..e2666fa 100644 --- a/components/canvas/nodes/base-node-wrapper.tsx +++ b/components/canvas/nodes/base-node-wrapper.tsx @@ -1,8 +1,10 @@ "use client"; import type { ReactNode } from "react"; +import { NodeErrorBoundary } from "./node-error-boundary"; interface BaseNodeWrapperProps { + nodeType: string; selected?: boolean; status?: string; statusMessage?: string; @@ -11,6 +13,7 @@ interface BaseNodeWrapperProps { } export default function BaseNodeWrapper({ + nodeType, selected, status = "idle", statusMessage, @@ -35,7 +38,7 @@ export default function BaseNodeWrapper({ ${className} `} > - {children} + {children} {status === "error" && statusMessage && (
{statusMessage} diff --git a/components/canvas/nodes/compare-node.tsx b/components/canvas/nodes/compare-node.tsx index cfadceb..1683ce1 100644 --- a/components/canvas/nodes/compare-node.tsx +++ b/components/canvas/nodes/compare-node.tsx @@ -63,7 +63,7 @@ export default function CompareNode({ data, selected }: NodeProps) { }, []); return ( - +
⚖️ Compare
diff --git a/components/canvas/nodes/group-node.tsx b/components/canvas/nodes/group-node.tsx index b9ad27a..0eb66c1 100644 --- a/components/canvas/nodes/group-node.tsx +++ b/components/canvas/nodes/group-node.tsx @@ -44,6 +44,7 @@ export default function GroupNode({ id, data, selected }: NodeProps) return ( diff --git a/components/canvas/nodes/image-node.tsx b/components/canvas/nodes/image-node.tsx index 7a5ebbf..2f477d9 100644 --- a/components/canvas/nodes/image-node.tsx +++ b/components/canvas/nodes/image-node.tsx @@ -116,7 +116,7 @@ export default function ImageNode({ id, data, selected }: NodeProps) }, []); return ( - + { + state: NodeErrorBoundaryState = { + hasError: false, + }; + + static getDerivedStateFromError(error: Error): NodeErrorBoundaryState { + return { + hasError: true, + errorMessage: error.message, + }; + } + + override componentDidCatch(error: Error, errorInfo: ErrorInfo) { + console.error("Node rendering error", { + nodeType: this.props.nodeType, + error, + componentStack: errorInfo.componentStack, + }); + } + + private handleRetry = () => { + this.setState({ hasError: false, errorMessage: undefined }); + }; + + override render() { + if (this.state.hasError) { + return ( +
+

Node render failed ({this.props.nodeType})

+ {this.state.errorMessage && ( +

+ {this.state.errorMessage} +

+ )} + +
+ ); + } + + return this.props.children; + } +} diff --git a/components/canvas/nodes/note-node.tsx b/components/canvas/nodes/note-node.tsx index 401d8bd..d68cbb1 100644 --- a/components/canvas/nodes/note-node.tsx +++ b/components/canvas/nodes/note-node.tsx @@ -53,7 +53,7 @@ export default function NoteNode({ id, data, selected }: NodeProps) { ); return ( - + ) { ); return ( - + {children} + diff --git a/components/ui/sonner.tsx b/components/ui/sonner.tsx index 9280ee5..8e19fc7 100644 --- a/components/ui/sonner.tsx +++ b/components/ui/sonner.tsx @@ -6,6 +6,7 @@ import { CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon const Toaster = ({ ...props }: ToasterProps) => { const { theme = "system" } = useTheme() + const { toastOptions, ...restProps } = props return ( { } as React.CSSProperties } toastOptions={{ + ...toastOptions, classNames: { toast: "cn-toast", + error: "border-destructive", + ...toastOptions?.classNames, }, }} - {...props} + {...restProps} /> ) } diff --git a/convex/ai.ts b/convex/ai.ts index 585696e..71561c9 100644 --- a/convex/ai.ts +++ b/convex/ai.ts @@ -7,6 +7,155 @@ import { IMAGE_MODELS, } from "./openrouter"; +const MAX_IMAGE_RETRIES = 2; + +type ErrorCategory = + | "credits" + | "policy" + | "timeout" + | "transient" + | "provider" + | "unknown"; + +function errorMessage(error: unknown): string { + if (error instanceof Error) return error.message; + return String(error ?? "Generation failed"); +} + +function parseOpenRouterStatus(message: string): number | null { + const match = message.match(/OpenRouter API error\s+(\d+)/i); + if (!match) return null; + const parsed = Number(match[1]); + return Number.isFinite(parsed) ? parsed : null; +} + +function categorizeError(error: unknown): { + category: ErrorCategory; + retryable: boolean; +} { + const message = errorMessage(error); + const lower = message.toLowerCase(); + const status = parseOpenRouterStatus(message); + + if ( + lower.includes("insufficient credits") || + lower.includes("daily generation limit") || + lower.includes("concurrent job limit") + ) { + return { category: "credits", retryable: false }; + } + + if ( + lower.includes("modell lehnt ab") || + lower.includes("content policy") || + lower.includes("policy") || + lower.includes("moderation") || + lower.includes("safety") || + lower.includes("refusal") || + lower.includes("policy_violation") + ) { + return { category: "policy", retryable: false }; + } + + if (status !== null) { + if (status >= 500 || status === 408 || status === 429 || status === 499) { + return { category: "provider", retryable: true }; + } + if (status >= 400 && status < 500) { + return { category: "provider", retryable: false }; + } + } + + if ( + lower.includes("timeout") || + lower.includes("timed out") || + lower.includes("deadline") || + lower.includes("abort") || + lower.includes("etimedout") + ) { + return { category: "timeout", retryable: true }; + } + + if ( + lower.includes("fetch failed") || + lower.includes("network") || + lower.includes("connection") || + lower.includes("econnreset") || + lower.includes("temporarily unavailable") || + lower.includes("service unavailable") || + lower.includes("rate limit") || + lower.includes("overloaded") + ) { + return { category: "transient", retryable: true }; + } + + return { category: "unknown", retryable: false }; +} + +function formatTerminalStatusMessage(error: unknown): string { + const message = errorMessage(error).trim() || "Generation failed"; + const { category } = categorizeError(error); + + const prefixByCategory: Record, string> = { + credits: "Credits", + policy: "Policy", + timeout: "Timeout", + transient: "Netzwerk", + provider: "Provider", + }; + + if (category === "unknown") { + return message; + } + + const prefix = prefixByCategory[category]; + if (message.toLowerCase().startsWith(prefix.toLowerCase())) { + return message; + } + + return `${prefix}: ${message}`; +} + +function wait(ms: number) { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); +} + +async function generateImageWithAutoRetry( + operation: () => Promise>>, + onRetry: ( + retryCount: number, + maxRetries: number, + failure: { message: string; category: ErrorCategory } + ) => Promise +) { + let lastError: unknown = null; + + for (let attempt = 0; attempt <= MAX_IMAGE_RETRIES; attempt++) { + try { + return await operation(); + } catch (error) { + lastError = error; + const { retryable, category } = categorizeError(error); + const retryCount = attempt + 1; + const hasRemainingRetry = retryCount <= MAX_IMAGE_RETRIES; + + if (!retryable || !hasRemainingRetry) { + throw error; + } + + await onRetry(retryCount, MAX_IMAGE_RETRIES, { + message: errorMessage(error), + category, + }); + await wait(Math.min(1500, 400 * retryCount)); + } + } + + throw lastError ?? new Error("Generation failed"); +} + export const generateImage = action({ args: { canvasId: v.id("canvases"), @@ -45,8 +194,11 @@ export const generateImage = action({ await ctx.runMutation(api.nodes.updateStatus, { nodeId: args.nodeId, status: "executing", + retryCount: 0, }); + let retryCount = 0; + try { let referenceImageUrl: string | undefined; if (args.referenceStorageId) { @@ -54,12 +206,28 @@ export const generateImage = action({ (await ctx.storage.getUrl(args.referenceStorageId)) ?? undefined; } - const result = await generateImageViaOpenRouter(apiKey, { - prompt: args.prompt, - referenceImageUrl, - model: modelId, - aspectRatio: args.aspectRatio, - }); + const result = await generateImageWithAutoRetry( + () => + generateImageViaOpenRouter(apiKey, { + prompt: args.prompt, + referenceImageUrl, + model: modelId, + aspectRatio: args.aspectRatio, + }), + async (nextRetryCount, maxRetries, failure) => { + retryCount = nextRetryCount; + const reason = + typeof failure.message === "string" + ? failure.message + : "temporärer Fehler"; + await ctx.runMutation(api.nodes.updateStatus, { + nodeId: args.nodeId, + status: "executing", + retryCount: nextRetryCount, + statusMessage: `Retry ${nextRetryCount}/${maxRetries} — ${reason}`, + }); + } + ); const binaryString = atob(result.imageBase64); const bytes = new Uint8Array(binaryString.length); @@ -97,6 +265,7 @@ export const generateImage = action({ await ctx.runMutation(api.nodes.updateStatus, { nodeId: args.nodeId, status: "done", + retryCount, }); if (reservationId) { @@ -115,8 +284,8 @@ export const generateImage = action({ await ctx.runMutation(api.nodes.updateStatus, { nodeId: args.nodeId, status: "error", - statusMessage: - error instanceof Error ? error.message : "Generation failed", + retryCount, + statusMessage: formatTerminalStatusMessage(error), }); throw error; diff --git a/convex/nodes.ts b/convex/nodes.ts index 41c7f08..2a56a4e 100644 --- a/convex/nodes.ts +++ b/convex/nodes.ts @@ -160,6 +160,7 @@ export const create = mutation({ width: args.width, height: args.height, status: "idle", + retryCount: 0, data: args.data, parentId: args.parentId, zIndex: args.zIndex, @@ -276,14 +277,19 @@ export const updateStatus = mutation({ v.literal("error") ), statusMessage: v.optional(v.string()), + retryCount: v.optional(v.number()), }, - handler: async (ctx, { nodeId, status, statusMessage }) => { + handler: async (ctx, { nodeId, status, statusMessage, retryCount }) => { const user = await requireAuth(ctx); const node = await ctx.db.get(nodeId); if (!node) throw new Error("Node not found"); await getCanvasOrThrow(ctx, node.canvasId, user.userId); - const patch: { status: typeof status; statusMessage?: string } = { + const patch: { + status: typeof status; + statusMessage?: string; + retryCount?: number; + } = { status, }; if (statusMessage !== undefined) { @@ -291,6 +297,9 @@ export const updateStatus = mutation({ } else if (status === "done" || status === "executing" || status === "idle") { patch.statusMessage = undefined; } + if (retryCount !== undefined) { + patch.retryCount = retryCount; + } await ctx.db.patch(nodeId, patch); }, }); diff --git a/convex/schema.ts b/convex/schema.ts index aef32fb..4ba1301 100644 --- a/convex/schema.ts +++ b/convex/schema.ts @@ -183,6 +183,7 @@ export default defineSchema({ // Node-Status (UX-Strategie: Status direkt am Node sichtbar) status: nodeStatus, statusMessage: v.optional(v.string()), // z.B. "Timeout — Credits nicht abgebucht" + retryCount: v.optional(v.number()), // Anzahl bereits durchgeführter Retries // Typ-spezifische Daten // Convex empfiehlt v.any() für polymorphe data-Felder // Type Safety wird über den `type`-Discriminator + Zod im Frontend sichergestellt diff --git a/lib/ai-errors.ts b/lib/ai-errors.ts new file mode 100644 index 0000000..606f263 --- /dev/null +++ b/lib/ai-errors.ts @@ -0,0 +1,296 @@ +export type AiErrorCategory = + | "insufficient_credits" + | "rate_limited" + | "content_policy" + | "timeout" + | "network" + | "server" + | "invalid_request" + | "unknown"; + +export interface AiError { + category: AiErrorCategory; + message: string; + detail?: string; + retryable: boolean; + creditsNotCharged: boolean; + showTopUp: boolean; + retryCount?: number; +} + +type RawErrorObject = { + message?: unknown; + detail?: unknown; + category?: unknown; + retryCount?: unknown; +}; + +const CATEGORY_ALIASES: Record = { + insufficient_credits: "insufficient_credits", + insufficientcredits: "insufficient_credits", + not_enough_credits: "insufficient_credits", + notenoughcredits: "insufficient_credits", + credits: "insufficient_credits", + payment_required: "insufficient_credits", + paymentrequired: "insufficient_credits", + rate_limit: "rate_limited", + ratelimit: "rate_limited", + rate_limited: "rate_limited", + ratelimited: "rate_limited", + too_many_requests: "rate_limited", + toomanyrequests: "rate_limited", + content_policy: "content_policy", + contentpolicy: "content_policy", + safety: "content_policy", + timeout: "timeout", + timed_out: "timeout", + timedout: "timeout", + network: "network", + connection: "network", + server: "server", + invalid_request: "invalid_request", + invalidrequest: "invalid_request", + bad_request: "invalid_request", + badrequest: "invalid_request", +}; + +function normalizeCategory(value: string | undefined): AiErrorCategory | undefined { + if (!value) return undefined; + const normalized = value.toLowerCase().replace(/[^a-z]/g, ""); + return CATEGORY_ALIASES[normalized]; +} + +function extractRetryCount(rawText: string, rawObj: RawErrorObject | null): number | undefined { + if (typeof rawObj?.retryCount === "number" && Number.isFinite(rawObj.retryCount)) { + return rawObj.retryCount; + } + + const retryCountMatch = rawText.match(/retry(?:_?count)?\s*[:=]\s*(\d{1,3})/i); + if (retryCountMatch?.[1]) { + return Number.parseInt(retryCountMatch[1], 10); + } + + const attemptMatch = rawText.match(/(?:attempt|retry)\s*#?\s*(\d{1,3})/i); + if (attemptMatch?.[1]) { + return Number.parseInt(attemptMatch[1], 10); + } + + return undefined; +} + +function cleanPrefixMessage(text: string): { category?: AiErrorCategory; message: string } { + const trimmed = text.trim(); + + const bracketPrefix = trimmed.match(/^\[([a-zA-Z_\- ]+)\]\s*[:\-]?\s*(.+)$/); + if (bracketPrefix?.[1] && bracketPrefix[2]) { + const category = normalizeCategory(bracketPrefix[1]); + if (category) { + return { + category, + message: bracketPrefix[2].trim(), + }; + } + } + + const plainPrefix = trimmed.match(/^([a-zA-Z_\- ]{3,40})\s*[:|\-]\s*(.+)$/); + if (plainPrefix?.[1] && plainPrefix[2]) { + const category = normalizeCategory(plainPrefix[1]); + if (category) { + return { + category, + message: plainPrefix[2].trim(), + }; + } + } + + return { message: trimmed }; +} + +function splitMessageAndDetail(message: string): { message: string; detail?: string } { + const separators = [" — ", " - ", "\n"]; + for (const separator of separators) { + const index = message.indexOf(separator); + if (index <= 0) continue; + const lead = message.slice(0, index).trim(); + const tail = message.slice(index + separator.length).trim(); + if (lead && tail) { + return { message: lead, detail: tail }; + } + } + + return { message }; +} + +function inferCategoryFromText(text: string): AiErrorCategory { + const lower = text.toLowerCase(); + + const openRouterStatus = lower.match(/openrouter api error\s*(\d{3})/i); + if (openRouterStatus?.[1]) { + const status = Number.parseInt(openRouterStatus[1], 10); + if (status === 402) return "insufficient_credits"; + if (status === 408 || status === 504) return "timeout"; + if (status === 429) return "rate_limited"; + if (status >= 500) return "server"; + if (status >= 400) return "invalid_request"; + } + + if ( + lower.includes("insufficient credits") || + lower.includes("not enough credits") || + lower.includes("credit balance") || + lower.includes("guthaben") || + lower.includes("nicht genug credits") + ) { + return "insufficient_credits"; + } + + if ( + lower.includes("too many requests") || + lower.includes("rate limit") || + lower.includes("ratelimit") || + lower.includes("429") + ) { + return "rate_limited"; + } + + if ( + lower.includes("timeout") || + lower.includes("timed out") || + lower.includes("deadline exceeded") + ) { + return "timeout"; + } + + if ( + lower.includes("network") || + lower.includes("connection") || + lower.includes("fetch failed") || + lower.includes("econn") + ) { + return "network"; + } + + if ( + lower.includes("policy") || + lower.includes("safety") || + lower.includes("refusal") || + lower.includes("modell lehnt ab") + ) { + return "content_policy"; + } + + if ( + lower.includes("invalid") || + lower.includes("bad request") || + lower.includes("unknown model") || + lower.includes("missing") + ) { + return "invalid_request"; + } + + if (lower.includes("server") || lower.includes("5xx")) { + return "server"; + } + + return "unknown"; +} + +function defaultsForCategory(category: AiErrorCategory): Omit { + switch (category) { + case "insufficient_credits": + return { + message: "Not enough credits for this generation", + retryable: false, + creditsNotCharged: true, + showTopUp: true, + }; + case "rate_limited": + return { + message: "The model is busy right now", + retryable: true, + creditsNotCharged: true, + showTopUp: false, + }; + case "content_policy": + return { + message: "The request was blocked by model safety rules", + retryable: false, + creditsNotCharged: true, + showTopUp: false, + }; + case "timeout": + return { + message: "The generation timed out", + retryable: true, + creditsNotCharged: true, + showTopUp: false, + }; + case "network": + return { + message: "Network issue while contacting the model", + retryable: true, + creditsNotCharged: true, + showTopUp: false, + }; + case "server": + return { + message: "The AI service returned a server error", + retryable: true, + creditsNotCharged: true, + showTopUp: false, + }; + case "invalid_request": + return { + message: "The request could not be processed", + retryable: false, + creditsNotCharged: true, + showTopUp: false, + }; + case "unknown": + default: + return { + message: "Generation failed", + retryable: true, + creditsNotCharged: true, + showTopUp: false, + }; + } +} + +export function classifyError(rawError: unknown): AiError { + const rawObj: RawErrorObject | null = + rawError != null && typeof rawError === "object" + ? (rawError as RawErrorObject) + : null; + + const rawMessage = + typeof rawError === "string" + ? rawError + : rawError instanceof Error + ? rawError.message + : typeof rawObj?.message === "string" + ? rawObj.message + : ""; + + const rawDetail = typeof rawObj?.detail === "string" ? rawObj.detail.trim() : undefined; + + const prefixed = cleanPrefixMessage(rawMessage); + const explicitCategory = + normalizeCategory(typeof rawObj?.category === "string" ? rawObj.category : undefined) ?? + prefixed.category; + const category = explicitCategory ?? inferCategoryFromText(prefixed.message); + + const defaults = defaultsForCategory(category); + const split = splitMessageAndDetail(prefixed.message); + const message = split.message || defaults.message; + + return { + category, + message, + detail: split.detail ?? rawDetail, + retryable: defaults.retryable, + creditsNotCharged: defaults.creditsNotCharged, + showTopUp: defaults.showTopUp, + retryCount: extractRetryCount(rawMessage, rawObj), + }; +} diff --git a/lib/canvas-utils.ts b/lib/canvas-utils.ts index 095eeea..4b2eac5 100644 --- a/lib/canvas-utils.ts +++ b/lib/canvas-utils.ts @@ -17,6 +17,7 @@ export function convexNodeToRF(node: Doc<"nodes">): RFNode { // Status direkt in data durchreichen, damit Node-Komponenten darauf zugreifen können _status: node.status, _statusMessage: node.statusMessage, + retryCount: node.retryCount, }, parentId: node.parentId ?? undefined, zIndex: node.zIndex, diff --git a/lib/toast.ts b/lib/toast.ts new file mode 100644 index 0000000..2c64c2f --- /dev/null +++ b/lib/toast.ts @@ -0,0 +1,82 @@ +import type { ReactNode } from "react" +import { isValidElement } from "react" +import { toast as sonnerToast, type ExternalToast } from "sonner" + +const SUCCESS_DURATION = 4000 +const ERROR_DURATION = 6000 + +type SonnerPromiseInput = Parameters>[0] +type SonnerPromiseOptions = Parameters>[1] +type SonnerPromiseData = NonNullable> + +function hasMessage( + value: unknown, +): value is { + message: ReactNode + duration?: number +} { + return ( + typeof value === "object" && + value !== null && + !isValidElement(value) && + "message" in value + ) +} + +function withStateDuration(state: unknown, duration: number): unknown { + if (state === undefined) { + return undefined + } + + if (typeof state === "function") { + return async (value: T) => { + const result = await state(value) + return withStateDuration(result, duration) + } + } + + if (hasMessage(state)) { + return { + ...state, + duration: state.duration ?? duration, + } + } + + return { + message: state as ReactNode, + duration, + } +} + +export const toast = { + success(message: ReactNode, options?: ExternalToast) { + return sonnerToast.success(message, { + ...options, + duration: options?.duration ?? SUCCESS_DURATION, + }) + }, + error(message: ReactNode, options?: ExternalToast) { + return sonnerToast.error(message, { + ...options, + duration: options?.duration ?? ERROR_DURATION, + }) + }, + loading(message: ReactNode, options?: ExternalToast) { + return sonnerToast.loading(message, options) + }, + dismiss(id?: number | string) { + return sonnerToast.dismiss(id) + }, + promise(promise: SonnerPromiseInput, options?: SonnerPromiseOptions) { + return sonnerToast.promise(promise, { + ...options, + success: withStateDuration(options?.success, SUCCESS_DURATION) as SonnerPromiseData["success"], + error: withStateDuration(options?.error, ERROR_DURATION) as SonnerPromiseData["error"], + }) + }, +} + +export const toastDuration = { + success: SUCCESS_DURATION, + error: ERROR_DURATION, +} as const