Goal
Introduce a Debugging Panel component in the Preswald frontend that displays the live app state, tracked variables, and error messages to assist developers in real-time debugging and iteration.
📌 Motivation
Preswald abstracts away much of the complexity in app state management and component interactions. However, when things go wrong (e.g. a workflow fails, a component isn't rendering, or variable values are unexpected), there's currently no visibility into the internal state of the app. This makes debugging opaque and time-consuming.
A built-in debugging panel will:
- Surface variables and their current values
- Show error messages and stack traces in context
- Display execution flow and component states
- Improve developer confidence and iteration speed
✅ Acceptance Criteria
🛠 Implementation Plan
1. Backend – Surface State and Errors
In preswald/service.py, expose get_state_snapshot():
def get_state_snapshot(cls):
return {
"components": cls.get_instance().components,
"variables": cls.get_instance().variable_store,
"errors": cls.get_instance().error_log,
"execution_graph": cls.get_instance().workflow_graph.serialize(),
}
Update server_service.py to stream state snapshots and errors over WebSocket via special __debug__ channel when debug=True.
2. Frontend – Add Debug Panel UI
Create frontend/src/components/common/DebugPanel.jsx:
import React, { useState, useEffect } from 'react';
import { Card } from '@/components/ui/card';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Button } from '@/components/ui/button';
const DebugPanel = ({ state }) => {
const [visible, setVisible] = useState(false);
return (
<div className="fixed bottom-4 right-4 z-50">
<Button onClick={() => setVisible(!visible)} className="mb-2">
{visible ? "Hide Debug" : "Show Debug"}
</Button>
{visible && (
<Card className="w-[400px] h-[500px] overflow-hidden shadow-lg border bg-white dark:bg-gray-900 text-sm">
<ScrollArea className="p-4 h-full">
<pre className="whitespace-pre-wrap">{JSON.stringify(state, null, 2)}</pre>
</ScrollArea>
</Card>
)}
</div>
);
};
export default DebugPanel;
Mount this component inside App.jsx only if debugMode is true.
3. WebSocket Layer – Stream State Updates
Update websocket.js to subscribe to __debug__ messages and store in global state. Example:
socket.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.channel === "__debug__") {
window.__DEBUG_STATE__ = msg.payload;
}
};
4. Toggle Debug Panel Based on Flag
Allow enabling via:
Expose this flag from backend via branding/metadata payload (/api/config).
📄 Example Output
{
"variables": {
"threshold": 0.75,
"selected_region": "Europe"
},
"components": [
{"id": "slider-abc123", "type": "slider", "label": "Threshold"},
{"id": "table-def456", "type": "table", "rows": 200}
],
"errors": [
{"timestamp": "2025-03-23T19:42Z", "message": "KeyError: 'value'"}
]
}
📚 Documentation Updates
🧪 Testing Plan
- Trigger runtime Python errors in workflows
- Confirm they surface in Debug Panel
- Add/modify variables and ensure they update live
- Confirm debug panel does not show in
debug=false mode
🧩 Files Involved
preswald/service.py
preswald/server_service.py
frontend/src/components/common/DebugPanel.jsx
frontend/src/components/App.jsx
websocket.js
💡 Future Enhancements
- Interactive state editing in debug mode (like Redux DevTools)
- Toggle logs per component
- DAG viewer with live execution steps
- Attach profiler/trace mode
Goal
Introduce a Debugging Panel component in the Preswald frontend that displays the live app state, tracked variables, and error messages to assist developers in real-time debugging and iteration.
📌 Motivation
Preswald abstracts away much of the complexity in app state management and component interactions. However, when things go wrong (e.g. a workflow fails, a component isn't rendering, or variable values are unexpected), there's currently no visibility into the internal state of the app. This makes debugging opaque and time-consuming.
A built-in debugging panel will:
✅ Acceptance Criteria
DebugPanel.jsx) in the frontend (floating bottom-right or sidebar)Service.get_state())debug=Trueflag inpreswald.tomlor environment variable to enable/disable panel🛠 Implementation Plan
1. Backend – Surface State and Errors
In
preswald/service.py, exposeget_state_snapshot():Update
server_service.pyto stream state snapshots and errors over WebSocket via special__debug__channel whendebug=True.2. Frontend – Add Debug Panel UI
Create
frontend/src/components/common/DebugPanel.jsx:Mount this component inside
App.jsxonly ifdebugModeistrue.3. WebSocket Layer – Stream State Updates
Update
websocket.jsto subscribe to__debug__messages and store in global state. Example:4. Toggle Debug Panel Based on Flag
Allow enabling via:
preswald.toml:Expose this flag from backend via branding/metadata payload (
/api/config).📄 Example Output
{ "variables": { "threshold": 0.75, "selected_region": "Europe" }, "components": [ {"id": "slider-abc123", "type": "slider", "label": "Threshold"}, {"id": "table-def456", "type": "table", "rows": 200} ], "errors": [ {"timestamp": "2025-03-23T19:42Z", "message": "KeyError: 'value'"} ] }📚 Documentation Updates
docs/coreconcepts/debugging.mdxpreswald.tomldocs🧪 Testing Plan
debug=falsemode🧩 Files Involved
preswald/service.pypreswald/server_service.pyfrontend/src/components/common/DebugPanel.jsxfrontend/src/components/App.jsxwebsocket.js💡 Future Enhancements