- Introduced a new utility function `canonical_csv_header_label` to standardize CSV header labels, improving consistency in field mapping.
- Updated the `_lookup_db_field` function to support prefix matching for longer manual keys, enhancing the accuracy of field resolution.
- Added tests to validate handling of non-breaking space characters in CSV headers and ensure correct mapping to normalized keys, improving robustness of CSV parsing.
- Updated the `ACTIVITY_LOG_PATCHABLE_COLUMNS` and `ACTIVITY_LOG_PATCH_FORBIDDEN` sets to improve validation of CSV imports, ensuring only allowed fields are patched.
- Refactored the `_coerce_raw_value_for_parameter` function to handle string inputs for integer and float types, enhancing data coercion accuracy.
- Modified the `SessionMetricsFields` component to display orphan metrics that do not match the current schema, improving user visibility of imported data discrepancies.
- Enhanced the frontend to handle and display additional metrics, ensuring a more comprehensive representation of session data.
- Updated the CSV import logic to merge active training parameters with static fields for the activity module, improving field mapping accuracy.
- Enhanced validation functions to incorporate dynamic field definitions based on active training parameters, ensuring better data integrity during imports.
- Refactored related functions to streamline the process of handling CSV templates and field mappings, improving maintainability and clarity.
- Added new utility functions for resolving activity log column patches and upserting session metrics from CSV, enhancing the overall import functionality.
- Updated the `get_activity_detail` function to include session metrics in the activity detail output, allowing for enriched data representation.
- Refactored the activity import logic to streamline the process of inserting and updating activity records, utilizing new helper functions for better maintainability.
- Improved the handling of duplicate activity entries by implementing a more robust identification mechanism.
- Enhanced the metadata for activity detail registration to reflect the inclusion of EAV metrics and updated source tables.
- Added a new query parameter `collapseDuplicateSessions` to the activity listing endpoint to enable deduplication of sessions based on date, type, start time, duration, and calories.
- Enhanced backend logic to handle deduplication and return the most recent entry for duplicate sessions.
- Updated frontend to support the new deduplication feature, improving the clarity of displayed activity data.
- Modified API utility to include the new parameter in requests for activity data.
- Introduced a new query parameter for the activity listing endpoint to fetch entries by calendar month (format: YYYY-MM), excluding days and offset.
- Implemented backend validation for the month parameter to ensure correct format and range.
- Enhanced the frontend to support month selection, allowing users to load activities for specific months and dynamically update the displayed entries.
- Improved the user interface to show the selected month and the range of loaded months, enhancing user experience.
- Updated the `replace_activity_session_metrics` function to improve validation logic and error handling for required fields.
- Enhanced the activity listing query to order results by date, start time, and ID, ensuring consistent output.
- Modified the frontend to handle null values in metrics payload and improved the display of activity statistics, including total entries in profile and sample size.
- Added pagination support to the activity listing endpoint with `limit` and `offset` parameters.
- Introduced a `skip_quality_filter` option to allow retrieval of all entries without applying the quality filter.
- Updated the frontend to implement dynamic loading of activity entries and statistics without the quality filter.
- Improved user experience with a "Load More" button for fetching additional entries on the ActivityPage.
- Added new fields to the ActivityEntry model for improved tracking: hr_min, pace_min_per_km, cadence, avg_power, elevation_gain, temperature_celsius, humidity_percent, avg_hr_percent, and kcal_per_km.
- Updated the create_activity function to accommodate the new fields in the activity log.
- Modified session metrics handling to ensure accurate data retrieval and merging based on the updated schema.
- Added a new function to synchronize session metrics with activity log entries, ensuring data consistency.
- Updated the create and update activity endpoints to call the synchronization function after inserting or modifying activity logs.
- Introduced a set of allowed keys for activity log payloads to streamline data handling in the frontend.
- Improved data coercion logic for various data types in the frontend to ensure accurate data submission.
- Implemented a new endpoint to retrieve activity statistics for the last 30 entries, including total calories and duration by activity type.
- Added an endpoint to list activities without assigned training types, grouped by activity type.
- Removed deprecated versions of the statistics and uncategorized activities endpoints for cleaner code.
- Introduced new endpoints for updating training category and type parameters in the backend.
- Added corresponding update functions in the frontend API utility.
- Enhanced the Admin Activity Attribute Profiles page to support editing and saving changes for category and type parameters.
- Implemented state management for editing parameters and improved error handling during updates.
- Added new Admin UI for managing Activity Attribute Profiles.
- Enhanced ActivityPage to support dynamic loading and editing of session metrics.
- Updated API utility functions to handle new endpoints for training parameters and metrics.
- Improved form handling for session metrics, including validation and error management.
- Updated documentation to reflect new features and changes in session metrics handling.
- Introduced Activity Session Metrics for enhanced tracking of session data.
- Updated backend to support new API endpoints for managing session metrics.
- Added new Pydantic models for activity metrics and replaced metrics functionality.
- Enhanced data layer to include session metrics in recent training session data.
- Updated documentation to reflect changes in session metrics handling.
- Added a function to calculate goal progress percentage based on start, target, and current values.
- Updated GoalsPage to display progress in a user-friendly format, including visual progress bars.
- Implemented error handling for goal progress updates in the backend to ensure robustness.
- Add name field to WorkflowNode model
- Extend node_label priority: node.name > prompt_slug > node_type-id
- No new fields in NodeExecutionState (uses existing debug_prompt_slug)
- Simpler approach than previous attempt to avoid 504 timeout
- Add name field to WorkflowNode model
- Add node_name field to NodeExecutionState
- Set node_name in execute_workflow from node.name
- Display priority: node_name > debug_prompt_slug > node_label > node_id
User sees 'Qualitätseinschätzung' instead of 'node_abc123'
Display per node:
- debug_prompt (prompt sent to AI)
- debug_raw_response (raw AI response)
- analysis_core (parsed results)
- normalized_signals (decision signals with status)
- Failed nodes: red border + red background
NO other changes - executeWorkflow still used
- Failed nodes now have:
- Red border (2px instead of 1px)
- Light red background (#D85A3010)
- Red shadow/glow effect
Makes it immediately obvious which nodes had errors.
- workflow_executor.py: Store prompt_slug or generated label in debug_prompt_slug for all nodes
- This makes it easy to identify nodes in the debug panel
- Example: 'wf_nutrition_basis' instead of 'node_5'
- Helps identify which node is which when debugging workflows
- Created WorkflowDebugPanel.jsx: Collapsible panel showing debug info for each workflow node
- Shows prompt sent to AI
- Shows raw AI response
- Shows parsed results
- Shows normalized signals
- Color-coded status (executed/failed/skipped)
- Expandable/collapsible per node
- Updated Analysis.jsx:
- Added WorkflowDebugPanel import
- Store node_states in newResult for debugging
- Display WorkflowDebugPanel below InsightCard (both locations)
This makes it easy to debug workflow issues by seeing exactly what happened at each node.
Backend changes:
- workflow_models.py: Add debug_prompt, debug_raw_response, debug_node_type, debug_prompt_slug, metadata fields to NodeExecutionState
- workflow_executor.py: Capture and store debug info for analysis, logic, and join nodes when enable_debug=True
- Analysis nodes: store full prompt + raw AI response
- Logic nodes: store expression + evaluation result
- Join nodes: store strategy + path statistics
Frontend changes:
- Analysis.jsx: Enable debug mode by default (debug=true) for all workflow executions
This allows developers to see exactly what prompt was sent to the AI, what response was received, and how each node was processed - essential for debugging workflow issues.
- workflow_executor.py: Generate node_label from prompt_slug or node.type (WorkflowNode has no label attribute)
- prompts.py: Fix INSERT statement - use 'created' column instead of 'created_at'
SSE endpoint now works correctly for workflow execution streaming.
Backend:
- workflow_executor.py: Add progress_callback parameter, emit events for execution_started, node_complete, execution_complete, execution_failed
- prompt_executor.py: Thread progress_callback through execute chain
- routers/prompts.py: New /execute-stream endpoint with asyncio Queue for SSE
Frontend:
- utils/api.js: New executeUnifiedPromptStream() function with EventSource
- pages/Analysis.jsx: Use SSE with live progress display (X/Y Nodes)
Fixes:
- No more gateway timeouts for complex workflows (10+ nodes)
- Live progress feedback for users
- Unlimited workflow complexity
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Bug: debug=true in URL was ignored because FastAPI expected it in
request body (POST without Query() expects body params by default).
Result: node_states were never returned, even with ?debug=true
Fix: Changed debug and save to Query parameters:
- debug: bool = Query(False, ...)
- save: bool = Query(False, ...)
Now ?debug=true in URL correctly enables debug output with node_states.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Root cause: UI saves LogicExpression directly as condition:
{operands: [...], operator: "and"}
But Pydantic model expected Condition with wrapped expression:
{expression: {operands: [...], operator: "and"}}
Result: Pydantic deserialized it as Condition with expression=None
→ Logic-Nodes failed with "'NoneType' object has no attribute 'operator'"
Fix:
1. Changed WorkflowNode.condition type from Condition to Any
2. Executor now handles both dict and Pydantic model formats
3. Detects UI format (operator+operands) vs legacy format (expression wrapper)
4. Converts dict to LogicExpression before evaluation
Fixes: Logic-Node execution failures in Training-Tiefenanalyse workflow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previous fix handled hasattr() but didn't check for None values.
Now explicitly checks that operator/expression is not None before using it.
Error was: "'NoneType' object has no attribute 'operator'"
Clearer error message: "condition is None or missing"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Logic-Nodes were timing out because UI saves condition as:
{operands: [...], operator: "and"}
But Backend expected:
{expression: {operands: [...], operator: "and"}}
This caused node.condition.expression to be None, triggering:
- Logic-Node failures
- Join-Node wait_all timeout
- 504 Gateway Timeout
Fix: Accept both formats by checking for operator/operands attributes
directly on condition, falling back to condition.expression.
Fixes: 504 Gateway Timeout in Training-Tiefenanalyse workflow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Problem: Logic nodes without logic_expression defined caused AttributeError
"'NoneType' object has no attribute 'operator'" when evaluating condition.
Solution: Check both node.condition AND node.condition.expression before
calling evaluate_logic_expression(). Return clear FAILED state with error
message instead of crashing.
Impact: Workflows with incomplete logic node definitions now fail gracefully
with clear error message instead of cryptic AttributeError.
Problem: Parser converted question IDs to lowercase ('qAnalyst' → 'qanalyst'),
causing normalization to fail because id_catalog lookup is case-sensitive.
Impact: All workflow question signals were lost - normalized_signals stayed empty,
so template placeholders like {{node_2.signal_qAnalyst}} remained unresolved.
Solution: Removed .lower() call in parse_decision_questions() to preserve
original case from AI response.
Root cause: Line 162 in result_container_parser.py
Fixes: Question augmentation signals not appearing in workflow end nodes
Problem: Workflows executed via /api/prompts/execute (not /api/workflows/execute)
were passing call_openrouter directly to execute_prompt_with_data, which then
passes it to workflow_executor. workflow_executor expects (prompt, model) signature
but call_openrouter has (prompt, max_tokens=4096) signature.
Previous fix in workflows.py was correct but unused - workflows use prompts.py endpoint.
Solution: Added workflow_llm_call() wrapper in execute_unified_prompt() endpoint
that matches expected (prompt, model) -> str signature.
Related: cb3aa48 (workflows.py fix for different endpoint)
Problem: workflow_executor calls openrouter_call_func(prompt, model) but
call_openrouter expects (prompt, max_tokens=4096). This caused the model string
'anthropic/claude-sonnet-4' to be passed as max_tokens, resulting in OpenRouter
requesting 64000 tokens and failing with 402 credit errors.
Solution: Added workflow_llm_call() wrapper in workflows.py that matches the
expected (prompt, model) -> str signature and calls call_openrouter correctly.
Fixes: All workflows failing with 402 'insufficient credits' errors
Problem: Cursor springt nach jedem Tastendruck aus dem ID-Feld
Ursache: key={q.id} in QuestionEditor map
- Wenn ID geändert wird, ändert sich der React Key
- React unmountet alte Component und mountet neue
- Focus geht verloren
Lösung: key={idx} verwenden
- Stabiler Key während Editing
- Komponente bleibt gemountet
- Cursor bleibt im Feld
UX: Jetzt kann man IDs flüssig editieren ohne Unterbrechung
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Introduced `ExpandableCollapsible` component to manage the visibility of lengthy content, allowing users to toggle between expanded and collapsed views.
- Updated `renderTestOutput` to utilize the new component for displaying test results, JSON outputs, and object representations, enhancing user experience by reducing clutter.
- Enhanced `Markdown` component to support fenced code blocks, improving the rendering of code snippets with language labels and better styling.
These changes improve the readability and organization of content within the application, providing users with a more interactive and manageable interface.
- Increased the maximum token limit in the `call_openrouter` function from 1500 to 4096 to allow for more extensive responses.
- Implemented robust error handling for API requests, including timeout and request errors, with detailed HTTP exceptions for better debugging.
- Improved JSON response handling to ensure valid data is returned, with specific error messages for missing content in the response.
- Enhanced the overall reliability of the OpenRouter API integration, providing clearer feedback for users in case of issues.
These changes improve the user experience by ensuring more comprehensive responses and clearer error reporting during API interactions.
- Updated the `_parse_float_auto` function in `type_converter.py` to better handle various decimal and thousand separators, particularly for cases with long decimal parts from sources like Apple Health.
- Enhanced the logic for splitting and processing numeric strings to ensure correct interpretation of values, including edge cases with multiple separators.
- Added handling for cases where numeric strings may contain both commas and periods, improving overall robustness in float parsing.
These changes enhance the accuracy of numeric conversions, ensuring more reliable data processing across the application.
- Updated the Gitea issues index to reflect the latest state as of 2026-04-11, adding issue #76 to the list.
- Refined data handling in `activity_metrics.py`, `body_metrics.py`, `nutrition_metrics.py`, and `scores.py` to ensure consistent float conversions for calculations, improving accuracy in metric evaluations.
- Enhanced the calculation logic for various metrics to handle potential None values more robustly, ensuring smoother data processing and improved reliability across the application.
These changes improve the clarity of the Gitea issues documentation and enhance the overall accuracy and reliability of health and fitness metrics.
- Updated `resolve_placeholders` in `prompt_executor.py` to support combined modifiers for placeholders, allowing for more flexible output formats.
- Enhanced `build_ai_placeholder_caption` in `placeholder_registry.py` to clarify the generation of AI context captions, focusing on descriptions and explanations.
- Introduced new helper functions in `placeholder_resolver.py` to streamline the retrieval of descriptions and explanations for placeholders.
- Modified tests to cover new functionality, ensuring accurate behavior for combined modifiers and improved placeholder resolution.
These changes enhance the usability and clarity of placeholder outputs, providing users with richer contextual information.
- Updated `build_ai_placeholder_caption` in `placeholder_registry.py` to improve the generation of AI context captions by prioritizing descriptions and avoiding redundancy.
- Introduced `format_value_with_d_modifier` in `placeholder_resolver.py` to format values with contextual information, enhancing the clarity of exported placeholder values.
- Modified `export_placeholder_values` in `prompts.py` to utilize the new formatting function, ensuring that exported data includes both raw values and contextual descriptions.
- Added tests for the new formatting function and updated existing tests to ensure accurate caption generation.
These changes improve the contextual relevance of placeholder data and enhance the user experience when interacting with exported values.
- Introduced `build_ai_placeholder_caption` function in `placeholder_registry.py` to generate AI context captions based on placeholder metadata.
- Updated `resolve_placeholders` in `placeholder_resolver.py` to support modifiers for AI context, allowing for enhanced descriptions when placeholders are resolved.
- Modified `get_placeholder_catalog` to include AI captions in the output, improving the metadata available for placeholders.
- Adjusted `export_placeholder_values` to include AI captions in the exported data, enhancing the information provided to users.
These changes improve the flexibility and functionality of the placeholder system, enabling richer context generation for dynamic content.