Skip to content

Commit f68ff6b

Browse files
committed
feat: demo add synth events (#332)
1 parent 2e556e4 commit f68ff6b

File tree

13 files changed

+400
-1137
lines changed

13 files changed

+400
-1137
lines changed

apps/demo/src/lib/components/CodePanel.svelte

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { fade } from 'svelte/transition';
44
import { codeToHtml } from 'shiki';
55
import { FLOW_CODE, getStepFromLine, FLOW_SECTIONS } from '$lib/data/flow-code';
6-
import type { createFlowState } from '$lib/stores/pgflow-state-improved.svelte';
6+
import type { createFlowState } from '$lib/stores/pgflow-state.svelte';
77
import StatusBadge from '$lib/components/StatusBadge.svelte';
88
import PulseDot from '$lib/components/PulseDot.svelte';
99
@@ -61,7 +61,8 @@
6161
6262
// Helper to get status for a step badge
6363
function getStepStatus(stepSlug: string): string | null {
64-
const status = flowState.stepStatuses[stepSlug];
64+
// Use reactive step() method from runState
65+
const status = flowState.step(stepSlug).status;
6566
const hasFlowStarted = flowState.status !== 'idle';
6667
6768
// Don't show badge if flow hasn't started yet
@@ -70,7 +71,7 @@
7071
}
7172
7273
// If flow has started but this step has no status yet, don't show indicator
73-
if (!status) {
74+
if (!status || status === 'created') {
7475
return null;
7576
}
7677
@@ -210,8 +211,8 @@
210211
// Explicitly track these dependencies
211212
const currentSelectedStep = selectedStep;
212213
const currentHoveredStep = hoveredStep;
213-
// Ensure reactivity to step status changes by accessing it
214-
void flowState.stepStatuses;
214+
// Ensure reactivity to step status changes by accessing flowState.run
215+
void flowState.run;
215216
216217
if (!codeContainer) return;
217218

apps/demo/src/lib/components/DAGVisualization.svelte

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { createEventDispatcher, onMount } from 'svelte';
33
import { SvelteFlow } from '@xyflow/svelte';
44
import '@xyflow/svelte/dist/style.css';
5-
import type { createFlowState } from '$lib/stores/pgflow-state-improved.svelte';
5+
import type { createFlowState } from '$lib/stores/pgflow-state.svelte';
66
import DAGNode from './DAGNode.svelte';
77
88
interface Props {
@@ -163,16 +163,18 @@
163163
]);
164164
165165
function isStepActive(stepSlug: string): boolean {
166-
const status = flowState.stepStatuses[stepSlug];
167-
return status === 'started';
166+
// Use reactive step() method from runState
167+
return flowState.step(stepSlug).status === 'started';
168168
}
169169
170170
function isStepCompleted(stepSlug: string): boolean {
171-
return flowState.stepStatuses[stepSlug] === 'completed';
171+
// Use reactive step() method from runState
172+
return flowState.step(stepSlug).status === 'completed';
172173
}
173174
174175
function isStepFailed(stepSlug: string): boolean {
175-
return flowState.stepStatuses[stepSlug] === 'failed';
176+
// Use reactive step() method from runState
177+
return flowState.step(stepSlug).status === 'failed';
176178
}
177179
178180
function isEdgeActive(source: string, target: string): boolean {

apps/demo/src/lib/components/DebugPanel.svelte

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script lang="ts">
2-
import type { createFlowState } from '$lib/stores/pgflow-state-improved.svelte';
2+
import type { createFlowState } from '$lib/stores/pgflow-state.svelte';
33
import { codeToHtml } from 'shiki';
44
import { SvelteMap } from 'svelte/reactivity';
55
@@ -45,7 +45,7 @@
4545
// Clear cache when flow resets (events list becomes empty or significantly changes)
4646
let lastEventCount = $state(0);
4747
$effect(() => {
48-
const currentEventCount = flowState.events.length;
48+
const currentEventCount = flowState.timeline.length;
4949
// If events list was cleared or reduced significantly, clear the cache
5050
if (currentEventCount === 0 || currentEventCount < lastEventCount - 5) {
5151
highlightedEvents = new SvelteMap();
@@ -54,23 +54,11 @@
5454
lastEventCount = currentEventCount;
5555
});
5656
57-
// Get relative time from flow start
58-
function formatRelativeTime(timestamp: Date, firstEventTimestamp: Date): string {
59-
const diffMs = timestamp.getTime() - firstEventTimestamp.getTime();
60-
const seconds = (diffMs / 1000).toFixed(3);
61-
return `+${seconds}s`;
62-
}
63-
6457
// Get display status from event_type (use the status part for badge coloring)
6558
function getEventStatus(eventType: string): string {
6659
return eventType.split(':')[1] || 'unknown';
6760
}
6861
69-
// Get full event name for display
70-
function getEventDisplayName(eventType: string): string {
71-
return eventType;
72-
}
73-
7462
// Get color class for event name based on status
7563
function getEventColor(eventType: string): string {
7664
const status = getEventStatus(eventType);
@@ -87,15 +75,16 @@
8775
return 'text-muted-foreground';
8876
}
8977
}
78+
9079
</script>
9180

9281
<div class="flex flex-col h-full min-w-0">
93-
{#if flowState.events.length > 0}
82+
{#if flowState.timeline.length > 0}
9483
<!-- Table-like headers -->
9584
<div
9685
class="flex items-center gap-2 px-3 py-1 border-b border-muted text-xs font-semibold text-muted-foreground"
9786
>
98-
<div class="w-[80px] text-left">TIME</div>
87+
<div class="w-[120px] text-left">TIME</div>
9988
<div class="w-[140px] text-left">EVENT</div>
10089
<div class="flex-1 text-left">STEP</div>
10190
<div class="w-[32px]"></div>
@@ -104,16 +93,14 @@
10493
{/if}
10594

10695
<div class="flex-1 overflow-y-auto overflow-x-hidden space-y-1 min-w-0">
107-
{#if flowState.events.length === 0}
96+
{#if flowState.timeline.length === 0}
10897
<p class="text-sm text-muted-foreground text-center py-8">
10998
No events yet. Start a flow to see events.
11099
</p>
111100
{:else}
112-
{@const firstEventTimestamp = flowState.events[0]?.timestamp}
113-
{#each flowState.events as event, index (index)}
101+
{#each flowState.timeline as event, index (index)}
114102
{@const eventType = event.event_type}
115-
{@const stepSlug = event.data?.step_slug}
116-
{@const eventDisplayName = getEventDisplayName(eventType)}
103+
{@const stepSlug = event.step_slug}
117104
{@const eventColor = getEventColor(eventType)}
118105
{@const isExpanded = expandedEventIndices.has(index)}
119106
{@const isHighlighted = stepSlug && hoveredStep === stepSlug}
@@ -127,11 +114,18 @@
127114
class="flex items-center gap-2 w-full text-left px-1 rounded transition-colors hover:bg-muted/20"
128115
onclick={(e) => toggleEvent(index, e)}
129116
>
130-
<code class="w-[80px] text-base text-muted-foreground font-mono text-left"
131-
>{formatRelativeTime(event.timestamp, firstEventTimestamp)}</code
132-
>
117+
<div class="w-[120px] flex flex-col text-left">
118+
<code class="text-base text-muted-foreground font-mono"
119+
>{event.cumulativeDisplay}</code
120+
>
121+
{#if event.deltaMs > 0}
122+
<code class="text-xs text-muted-foreground/70 font-mono"
123+
>{event.deltaDisplay}</code
124+
>
125+
{/if}
126+
</div>
133127
<code class="w-[140px] text-base font-semibold font-mono {eventColor}">
134-
{eventDisplayName}
128+
{eventType}
135129
</code>
136130
{#if stepSlug}
137131
<code

apps/demo/src/lib/components/ExplanationPanel.svelte

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { fade } from 'svelte/transition';
44
import { Button } from '$lib/components/ui/button';
55
import { codeToHtml } from 'shiki';
6-
import type { createFlowState } from '$lib/stores/pgflow-state-improved.svelte';
6+
import type { createFlowState } from '$lib/stores/pgflow-state.svelte';
77
import StatusBadge from '$lib/components/StatusBadge.svelte';
88
import MiniDAG from '$lib/components/MiniDAG.svelte';
99
import { Clock, Workflow, Play, Hourglass } from '@lucide/svelte';
@@ -232,50 +232,37 @@
232232
selectedStep && stepInfo[selectedStep] ? stepInfo[selectedStep] : null
233233
);
234234
235-
// Build step outputs map from events
236-
const stepOutputs = $derived.by(() => {
237-
const outputs: Record<string, unknown> = {};
238-
flowState.events.forEach((event) => {
239-
if (
240-
event.event_type === 'step:completed' &&
241-
event.data?.step_slug &&
242-
event.data?.output !== undefined
243-
) {
244-
outputs[event.data.step_slug as string] = event.data.output;
245-
}
246-
});
247-
return outputs;
248-
});
249-
250-
// Get step output
251-
const stepOutput = $derived(selectedStep ? stepOutputs[selectedStep] : null);
235+
// Get step output from reactive step() method
236+
const stepOutput = $derived(selectedStep ? flowState.step(selectedStep).output : null);
252237
253238
// Get actual input for the selected step
254239
const stepInput = $derived.by(() => {
255-
if (!selectedStep || !currentStepInfo) return null;
240+
if (!selectedStep || !currentStepInfo || !flowState.run) return null;
256241
257242
// Only show input if step is started or completed
258-
const stepStatus = flowState.stepStatuses[selectedStep];
243+
// Use reactive step() method from runState
244+
const stepStatus = flowState.step(selectedStep).status;
259245
if (stepStatus !== 'started' && stepStatus !== 'completed') return null;
260246
261247
// For steps with dependencies, check if all dependencies are completed
262248
if (currentStepInfo.dependsOn.length > 0) {
263249
const allDepsCompleted = currentStepInfo.dependsOn.every((dep) => {
264-
return flowState.stepStatuses[dep] === 'completed';
250+
// Use reactive step() method from runState
251+
return flowState.step(dep).status === 'completed';
265252
});
266253
if (!allDepsCompleted) return null;
267254
}
268255
269256
const input: Record<string, unknown> = {};
270257
271258
// Always add run input (URL) from flowState.run if available
272-
if (flowState.run?.input) {
259+
if (flowState.run.input) {
273260
input.run = flowState.run.input;
274261
}
275262
276-
// Add outputs from dependencies
263+
// Add outputs from dependencies using reactive step() method
277264
for (const dep of currentStepInfo.dependsOn) {
278-
const depOutput = stepOutputs[dep];
265+
const depOutput = flowState.step(dep).output;
279266
if (depOutput !== undefined) {
280267
input[dep] = depOutput;
281268
}
@@ -286,7 +273,8 @@
286273
287274
// Get current step status
288275
function getStepStatus(stepSlug: string): string | null {
289-
const status = flowState.stepStatuses[stepSlug];
276+
// Use reactive step() method from runState
277+
const status = flowState.step(stepSlug).status;
290278
const hasFlowStarted = flowState.status !== 'idle';
291279
292280
// Don't show badge if flow hasn't started yet

apps/demo/src/lib/components/MiniDAG.svelte

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script lang="ts">
2-
import type { createFlowState } from '$lib/stores/pgflow-state-improved.svelte';
2+
import type { createFlowState } from '$lib/stores/pgflow-state.svelte';
33
44
/**
55
* Minimal DAG visualization for showing flow context
@@ -14,16 +14,18 @@
1414
let { selectedStep, flowState }: Props = $props();
1515
1616
function isStepActive(stepSlug: string): boolean {
17-
const status = flowState.stepStatuses[stepSlug];
18-
return status === 'started';
17+
// Use reactive step() method from runState
18+
return flowState.step(stepSlug).status === 'started';
1919
}
2020
2121
function isStepCompleted(stepSlug: string): boolean {
22-
return flowState.stepStatuses[stepSlug] === 'completed';
22+
// Use reactive step() method from runState
23+
return flowState.step(stepSlug).status === 'completed';
2324
}
2425
2526
function isStepFailed(stepSlug: string): boolean {
26-
return flowState.stepStatuses[stepSlug] === 'failed';
27+
// Use reactive step() method from runState
28+
return flowState.step(stepSlug).status === 'failed';
2729
}
2830
2931
// Node dimensions (smaller for mini view)

0 commit comments

Comments
 (0)