feat: add chat based testing for voice agent (#308)

* feat: add backend foundations

* feat: add text chat UI

* chore: simplify the reload behaviour

* fix: fix upgrade banner to be triggered after package upload

* feat: simplify TesterPanel design

* chore: fix formatting and generate client

* chore: fix tracing for text chat mode

* fix: fix revert and edit CTA

* refactor: refactor TesterPanel into smaller components

* feat: enable runtime transition of nodes

* fix: fix review comments
This commit is contained in:
Abhishek 2026-05-21 15:20:02 +05:30 committed by GitHub
parent 67479e98fd
commit d97d1d72cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
96 changed files with 7630 additions and 1684 deletions

View file

@ -9,8 +9,10 @@ export const BaseNode = forwardRef<
invalid?: boolean;
selected_through_edge?: boolean;
hovered_through_edge?: boolean;
runtimeActive?: boolean;
runtimePulseNonce?: number;
}
>(({ className, selected, invalid, selected_through_edge, hovered_through_edge, ...props }, ref) => (
>(({ children, className, selected, invalid, selected_through_edge, hovered_through_edge, runtimeActive, runtimePulseNonce, ...props }, ref) => (
<div
ref={ref}
className={cn(
@ -26,11 +28,22 @@ export const BaseNode = forwardRef<
// Hovered through edge takes precedence over selected through edge
hovered_through_edge ? "ring-2 ring-primary/60 shadow-[0_0_12px_rgba(96,165,250,0.3)]" : "",
!hovered_through_edge && selected_through_edge ? "ring-1 ring-primary/50 shadow-[0_0_8px_rgba(59,130,246,0.2)]" : "",
runtimeActive ? "ring-2 ring-sky-400/60 shadow-[0_0_0_1px_rgba(56,189,248,0.18),0_0_24px_rgba(14,165,233,0.18)]" : "",
!selected_through_edge && !hovered_through_edge && "hover:border-muted-foreground/50",
)}
tabIndex={0}
{...props}
/>
>
{runtimeActive ? (
<span
key={`runtime-pulse-${runtimePulseNonce ?? 0}`}
className="pointer-events-none absolute -inset-2 rounded-[18px] border-2 border-sky-400/55"
aria-hidden="true"
style={{ animation: "ping 900ms ease-out 2" }}
/>
) : null}
{children}
</div>
));
BaseNode.displayName = "BaseNode";

View file

@ -608,6 +608,8 @@ export const GenericNode = memo(({ data, selected, id, type }: GenericNodeProps)
invalid={data.invalid}
selected_through_edge={data.selected_through_edge}
hovered_through_edge={data.hovered_through_edge}
runtimeActive={data.runtime_active}
runtimePulseNonce={data.runtime_pulse_nonce}
title={data.name || fallbackTitle}
icon={<Icon />}
badgeLabel={badge.label}

View file

@ -10,6 +10,8 @@ interface NodeContentProps {
invalid?: boolean;
selected_through_edge?: boolean;
hovered_through_edge?: boolean;
runtimeActive?: boolean;
runtimePulseNonce?: number;
title: string;
icon: ReactNode;
badgeLabel?: string;
@ -31,6 +33,8 @@ export const NodeContent = ({
invalid,
selected_through_edge,
hovered_through_edge,
runtimeActive,
runtimePulseNonce,
title,
icon,
badgeLabel,
@ -54,6 +58,8 @@ export const NodeContent = ({
invalid={invalid}
selected_through_edge={selected_through_edge}
hovered_through_edge={hovered_through_edge}
runtimeActive={runtimeActive}
runtimePulseNonce={runtimePulseNonce}
className={`p-0 ${className}`}
onDoubleClick={onDoubleClick}
>

View file

@ -17,6 +17,8 @@ export type FlowNodeData = {
validationMessage?: string | null;
selected_through_edge?: boolean;
hovered_through_edge?: boolean;
runtime_active?: boolean;
runtime_pulse_nonce?: number;
allow_interrupt?: boolean;
extraction_enabled?: boolean;
extraction_prompt?: string;