Skip to content

Commit 1a0aab0

Browse files
committed
feat: enhance DAG visualization and debugging with flow state integration
- Added detailed documentation and philosophy on state management using createFlowState() - Updated DAGVisualization component to receive flowState via props for dynamic styling - Created DebugPanel component to display step statuses, outputs, errors, and event stream - Modified page layout to include both DAG visualization and debug panel with shared flowState - Improved event handling and reactivity by leveraging createFlowState's automatic subscriptions - Updated troubleshooting tips for rendering, reactivity, and animation issues - Overall improvements facilitate observability, debugging, and real-time monitoring of data flow
1 parent a4b4af9 commit 1a0aab0

30 files changed

+2359
-386
lines changed

PHASE_3_DAG_DEBUG.md

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
**Philosophy:** Build the observability foundation. UI can still be basic - focus on data flow and state management.
1717

18+
**State Management:** Phase 2 already implemented `createFlowState()` which auto-discovers steps and manages all event subscriptions. Components receive `flowState` via props and access reactive state through getters.
19+
1820
---
1921

2022
## Tasks
@@ -38,9 +40,11 @@ Create `apps/demo/src/lib/components/DAGVisualization.svelte`:
3840
Use `@xyflow/svelte` to render 4 nodes:
3941
- **Layout:** fetchArticle (top) → parallel nodes (middle) → publish (bottom)
4042
- **Dynamic styling:** Active steps show pulsing animation
41-
- **State integration:** Use pgflowState store to determine node colors/states
43+
- **State integration:** Receive `flowState` via props to determine node colors/states
4244
- **Visual states:** pending (gray), running (pulsing green), completed (solid green), failed (red)
4345

46+
**Props:** `{ flowState }` - the state object created by `createFlowState()`
47+
4448
---
4549

4650
### 3. Create Debug Panel Component
@@ -51,7 +55,9 @@ Create `apps/demo/src/lib/components/DebugPanel.svelte` with 3 sections:
5155
2. **Step States** - Collapsible sections for each step showing status/output/errors
5256
3. **Event Stream** - Real-time log of all events with timestamps
5357

54-
**Key pattern:** Use `run.on('*', handler)` to collect all events for the stream display
58+
**Props:** `{ flowState }` - the state object created by `createFlowState()`
59+
60+
**Key pattern:** The `flowState.events` array already contains all events (collected automatically by `createFlowState`)
5561

5662
---
5763

@@ -61,11 +67,25 @@ Update `apps/demo/src/routes/+page.svelte`:
6167

6268
- Two-column layout: DAG (left) + Debug Panel (right)
6369
- URL input field + "Process Article" button
64-
- Start flow and update pgflowState on events
65-
- Subscribe to both run events and individual step events
66-
- Set `activeStep` when steps start executing
70+
- Pass `flowState` to both DAG and Debug Panel components as props
71+
- Flow state already created using `createFlowState<typeof ArticleFlow>(pgflow, 'article_flow')`
72+
- Event handling is automatic (handled inside `createFlowState`)
73+
74+
**Key changes from current implementation:**
75+
```svelte
76+
<script lang="ts">
77+
import DAGVisualization from '$lib/components/DAGVisualization.svelte';
78+
import DebugPanel from '$lib/components/DebugPanel.svelte';
79+
// ... existing flowState setup ...
80+
</script>
81+
82+
<div class="two-column-layout">
83+
<DAGVisualization {flowState} />
84+
<DebugPanel {flowState} />
85+
</div>
86+
```
6787

68-
**Note:** Remember to trigger reactivity by reassigning `pgflowState.run` after events
88+
**Note:** `createFlowState` already handles all event subscriptions and reactivity via getters
6989

7090
---
7191

@@ -120,9 +140,10 @@ Open http://localhost:5173/, click "Process Article", verify:
120140
## Troubleshooting
121141

122142
- **DAG doesn't render:** Check Svelte Flow installed, browser console, CSS variables
123-
- **Steps don't update:** Check reactivity (`pgflowState.run = run` after events), event subscriptions
143+
- **Steps don't update:** Check that components access `flowState.status`, `flowState.activeStep` etc. (reactivity works via getters)
124144
- **No pulsing animation:** Check CSS keyframes, `--glow-color` variable
125145
- **Retry doesn't happen:** Check `maxAttempts: 3`, `attemptNumber === 1` check, Edge Function logs
146+
- **Props not reactive:** Ensure components use `flowState.property` (not destructuring) to maintain reactivity
126147

127148
---
128149

apps/demo/components.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"$schema": "https://shadcn-svelte.com/schema.json",
3+
"tailwind": {
4+
"css": "src/app.css",
5+
"baseColor": "slate"
6+
},
7+
"aliases": {
8+
"components": "$lib/components",
9+
"utils": "$lib/utils",
10+
"ui": "$lib/components/ui",
11+
"hooks": "$lib/hooks",
12+
"lib": "$lib"
13+
},
14+
"typescript": true,
15+
"registry": "https://shadcn-svelte.com/registry"
16+
}

apps/demo/package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
"devDependencies": {
1717
"@eslint/compat": "^1.4.0",
1818
"@eslint/js": "^9.38.0",
19+
"@lucide/svelte": "^0.552.0",
1920
"@sveltejs/adapter-auto": "^7.0.0",
2021
"@sveltejs/adapter-cloudflare": "^7.2.4",
2122
"@sveltejs/kit": "^2.47.1",
2223
"@sveltejs/vite-plugin-svelte": "^6.2.1",
24+
"@tailwindcss/vite": "^4.1.16",
2325
"@types/node": "^20",
2426
"autoprefixer": "10.4.20",
27+
"clsx": "^2.1.1",
2528
"eslint": "^9.38.0",
2629
"eslint-config-prettier": "^10.1.8",
2730
"eslint-plugin-svelte": "^3.12.4",
@@ -31,7 +34,10 @@
3134
"prettier-plugin-svelte": "^3.4.0",
3235
"svelte": "^5.41.0",
3336
"svelte-check": "^4.3.3",
34-
"tailwindcss": "3.4.17",
37+
"tailwind-merge": "^3.3.1",
38+
"tailwind-variants": "^3.1.1",
39+
"tailwindcss": "4.1.16",
40+
"tw-animate-css": "^1.4.0",
3541
"typescript": "^5.9.3",
3642
"typescript-eslint": "^8.46.1",
3743
"vite": "^7.1.10"

apps/demo/postcss.config.js

Lines changed: 0 additions & 6 deletions
This file was deleted.

apps/demo/src/app.css

Lines changed: 168 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,168 @@
1-
@tailwind base;
2-
@tailwind components;
3-
@tailwind utilities;
1+
@import "tailwindcss";
2+
3+
@custom-variant dark (&:is(.dark *));
4+
5+
@layer base {
6+
* {
7+
@apply border-border outline-ring/50;
8+
}
9+
body {
10+
@apply bg-background text-foreground;
11+
}
12+
}
13+
14+
:root {
15+
--radius: 0.375rem;
16+
/* Light mode - based on website's light theme (inverted from dark mode) */
17+
--background: #f3f7f6;
18+
--foreground: #121a19;
19+
--card: #ffffff;
20+
--card-foreground: #121a19;
21+
--popover: #ffffff;
22+
--popover-foreground: #121a19;
23+
/* pgflow brand green #00574d for light mode (darker) */
24+
--primary: #00574d;
25+
--primary-foreground: #ffffff;
26+
--secondary: #bac5c2;
27+
--secondary-foreground: #121a19;
28+
--muted: #e7f0ee;
29+
--muted-foreground: #495d59;
30+
--accent: #bce0d9;
31+
--accent-foreground: #003b34;
32+
--destructive: #dc2626;
33+
--border: #c2cdca;
34+
--input: #c2cdca;
35+
--ring: #00574d;
36+
--chart-1: oklch(0.646 0.222 41.116);
37+
--chart-2: oklch(0.6 0.118 184.704);
38+
--chart-3: oklch(0.398 0.07 227.392);
39+
--chart-4: oklch(0.828 0.189 84.429);
40+
--chart-5: oklch(0.769 0.188 70.08);
41+
--sidebar: #ffffff;
42+
--sidebar-foreground: #121a19;
43+
--sidebar-primary: #00574d;
44+
--sidebar-primary-foreground: #ffffff;
45+
--sidebar-accent: #e7f0ee;
46+
--sidebar-accent-foreground: #121a19;
47+
--sidebar-border: #c2cdca;
48+
--sidebar-ring: #00574d;
49+
}
50+
51+
.dark {
52+
/* Dark mode - based on website's dark theme */
53+
--background: #121a19;
54+
--foreground: #ffffff;
55+
--card: #182b28;
56+
--card-foreground: #ffffff;
57+
--popover: #182b28;
58+
--popover-foreground: #ffffff;
59+
/* pgflow brand green #007b6e for dark mode */
60+
--primary: #007b6e;
61+
--primary-foreground: #ffffff;
62+
--secondary: #2a3d39;
63+
--secondary-foreground: #ffffff;
64+
--muted: #2a3d39;
65+
--muted-foreground: #92a8a3;
66+
--accent: #002b26;
67+
--accent-foreground: #a3d4cb;
68+
--destructive: #ef4444;
69+
--border: rgba(255, 255, 255, 0.1);
70+
--input: rgba(255, 255, 255, 0.15);
71+
--ring: #007b6e;
72+
--chart-1: oklch(0.488 0.243 264.376);
73+
--chart-2: oklch(0.696 0.17 162.48);
74+
--chart-3: oklch(0.769 0.188 70.08);
75+
--chart-4: oklch(0.627 0.265 303.9);
76+
--chart-5: oklch(0.645 0.246 16.439);
77+
--sidebar: #182b28;
78+
--sidebar-foreground: #ffffff;
79+
--sidebar-primary: #007b6e;
80+
--sidebar-primary-foreground: #ffffff;
81+
--sidebar-accent: #2a3d39;
82+
--sidebar-accent-foreground: #ffffff;
83+
--sidebar-border: rgba(255, 255, 255, 0.1);
84+
--sidebar-ring: #007b6e;
85+
}
86+
87+
/* Additional semantic colors from website */
88+
:root {
89+
/* Blue (Info/Note) */
90+
--color-blue-low: hsl(220, 60%, 92%);
91+
--color-blue: hsl(220, 65%, 50%);
92+
--color-blue-high: hsl(220, 70%, 30%);
93+
94+
/* Purple (Tip) */
95+
--color-purple-low: hsl(280, 50%, 94%);
96+
--color-purple: hsl(280, 55%, 58%);
97+
--color-purple-high: hsl(280, 58%, 32%);
98+
99+
/* Orange (Caution) */
100+
--color-orange-low: hsl(35, 58%, 94%);
101+
--color-orange: hsl(35, 60%, 62%);
102+
--color-orange-high: hsl(35, 65%, 32%);
103+
104+
/* Green (Success) */
105+
--color-green-low: hsl(140, 55%, 92%);
106+
--color-green: hsl(140, 60%, 45%);
107+
--color-green-high: hsl(140, 65%, 25%);
108+
}
109+
110+
.dark {
111+
/* Blue (Info/Note) - dark mode */
112+
--color-blue-low: hsl(220, 45%, 18%);
113+
--color-blue: hsl(220, 65%, 55%);
114+
--color-blue-high: hsl(220, 70%, 90%);
115+
116+
/* Purple (Tip) - dark mode */
117+
--color-purple-low: hsl(280, 40%, 20%);
118+
--color-purple: hsl(280, 55%, 62%);
119+
--color-purple-high: hsl(280, 58%, 90%);
120+
121+
/* Orange (Caution) - dark mode */
122+
--color-orange-low: hsl(35, 38%, 22%);
123+
--color-orange: hsl(35, 60%, 68%);
124+
--color-orange-high: hsl(35, 65%, 92%);
125+
126+
/* Green (Success) - dark mode */
127+
--color-green-low: hsl(140, 42%, 18%);
128+
--color-green: hsl(140, 60%, 50%);
129+
--color-green-high: hsl(140, 65%, 70%);
130+
}
131+
132+
@theme inline {
133+
--radius-sm: calc(var(--radius) - 2px);
134+
--radius-md: var(--radius);
135+
--radius-lg: calc(var(--radius) + 2px);
136+
--radius-xl: calc(var(--radius) + 4px);
137+
--color-background: var(--background);
138+
--color-foreground: var(--foreground);
139+
--color-card: var(--card);
140+
--color-card-foreground: var(--card-foreground);
141+
--color-popover: var(--popover);
142+
--color-popover-foreground: var(--popover-foreground);
143+
--color-primary: var(--primary);
144+
--color-primary-foreground: var(--primary-foreground);
145+
--color-secondary: var(--secondary);
146+
--color-secondary-foreground: var(--secondary-foreground);
147+
--color-muted: var(--muted);
148+
--color-muted-foreground: var(--muted-foreground);
149+
--color-accent: var(--accent);
150+
--color-accent-foreground: var(--accent-foreground);
151+
--color-destructive: var(--destructive);
152+
--color-border: var(--border);
153+
--color-input: var(--input);
154+
--color-ring: var(--ring);
155+
--color-chart-1: var(--chart-1);
156+
--color-chart-2: var(--chart-2);
157+
--color-chart-3: var(--chart-3);
158+
--color-chart-4: var(--chart-4);
159+
--color-chart-5: var(--chart-5);
160+
--color-sidebar: var(--sidebar);
161+
--color-sidebar-foreground: var(--sidebar-foreground);
162+
--color-sidebar-primary: var(--sidebar-primary);
163+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
164+
--color-sidebar-accent: var(--sidebar-accent);
165+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
166+
--color-sidebar-border: var(--sidebar-border);
167+
--color-sidebar-ring: var(--sidebar-ring);
168+
}

apps/demo/src/app.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!doctype html>
2-
<html lang="en">
2+
<html lang="en" class="dark">
33
<head>
44
<meta charset="utf-8" />
55
<meta name="viewport" content="width=device-width, initial-scale=1" />

0 commit comments

Comments
 (0)