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
- 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.
- Updated `get_sleep_avg_duration` and `get_sleep_avg_quality` functions in `placeholder_resolver.py` to provide clearer error messages when data is unavailable.
- Enhanced sleep quality calculations in `recovery_metrics.py` to handle cases with insufficient data more robustly.
- Improved data handling in various metrics files (`activity_metrics.py`, `body_metrics.py`, `nutrition_metrics.py`, `recovery_metrics.py`, and `scores.py`) to ensure consistent float conversions for calculations.
- Added utility functions in `recovery_metrics.py` for parsing and normalizing sleep segment data, enhancing the accuracy of sleep quality assessments.
These changes improve the reliability and clarity of sleep-related metrics and enhance overall data handling across the application.
- Updated `extract_value_raw` to improve JSON parsing and handle unavailable data more effectively.
- Introduced new functions in `placeholder_resolver.py` for standardized responses when data is unavailable, enhancing clarity for users and AI.
- Modified various data retrieval functions to utilize the new response format, providing detailed reasons for unavailability.
- Improved availability checks in `export_placeholder_values_extended` to account for new response formats.
These changes enhance the robustness of the placeholder system and improve user experience by providing clearer error messages and data handling.
- Adjusted the total number of placeholders from 116 to 114 across various documentation and code files to reflect the current state of the system.
- Enhanced TDEE calculation logic in `nutrition_metrics.py` to prioritize Mifflin–St Jeor BMR with PAL when demographic data is available, with a fallback to a weight-based estimate.
- Updated placeholder registrations to ensure consistency with the new metadata structure and improved data handling.
- Revised documentation to clarify the authoritative source of placeholder metadata and the implications of the changes on existing functionalities.
These updates improve the accuracy and consistency of the placeholder system and enhance the nutritional assessment capabilities within the application.
- Introduced functions to retrieve profile name, age, height, and gender for better placeholder resolution.
- Added functions for displaying current date and time period labels (last 7, 30, and 90 days).
- Updated PLACEHOLDER_MAP to utilize new functions for improved readability and maintainability.
- Enhanced placeholder registrations in __init__.py to include new modules for sleep, vital metrics, and profile time periods.
These changes enhance the flexibility and functionality of the placeholder system, allowing for more dynamic content generation.
- Added new functions for BMI and goal weight/body fat percentage retrieval in `body_metrics.py`.
- Introduced training frequency and inter-session gap calculations in `activity_metrics.py`.
- Updated placeholder registrations to include new metrics for nutrition and activity.
- Improved data handling in `placeholder_resolver.py` for better integration of new metrics.
- Enhanced documentation across modules to reflect the new functionalities.
These updates improve the accuracy and comprehensiveness of health and fitness assessments within the application.
- Introduced a single TDEE calculation based on current weight, replacing the fixed 2500 kcal value.
- Updated `get_energy_balance_data` to use daily totals for intake calculations and improved energy balance logic.
- Enhanced `get_nutrition_average_data` to calculate averages over calendar days instead of raw log entries.
- Adjusted placeholder resolution to ensure consistent metadata usage across requests.
- Fixed issues in the charts router to reflect the new energy balance logic and TDEE calculations.
These changes improve the accuracy of nutritional assessments and streamline data handling in the application.
**Error:**
```
psycopg2.ProgrammingError: can't adapt type 'dict'
```
**Root Cause:**
- duplicate_prompt passed Python dicts directly to SQL INSERT
- JSONB fields from r2d() are already deserialized by psycopg2
- PostgreSQL expects JSON strings for JSONB columns
**Fix:**
- Added json.dumps() for all JSONB fields before INSERT:
- stages, output_schema, question_augmentations, graph_data
- Same pattern as import function
Files changed:
- backend/routers/prompts.py: JSON-encode JSONB in duplicate_prompt
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
**Root Cause:**
- FastAPI route matching: /{prompt_id} caught ALL requests including /export-all
- Specific routes MUST be defined BEFORE path parameter routes
**Error:**
```
psycopg2.errors.InvalidTextRepresentation: invalid input syntax for type uuid: "export-all"
LINE 1: SELECT * FROM ai_prompts WHERE id='export-all'
```
**Fix:**
- Moved /export-all and /import endpoints to line 106 (BEFORE /{prompt_id} at ~260)
- Added warning comments to both functions
- Fixed typo: for r in → for row in
**Affected:**
- /export-all: Internal Server Error → now works ✅
- /import: Would have had same issue → preemptively fixed ✅
Files changed:
- backend/routers/prompts.py: Reordered route definitions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Critical bug fix from pytest failures:
**Problem:**
- execute_end_node() tried to use 'graph' variable without defining it
- UnboundLocalError at line 602: "if graph:"
- Caused 2 test failures in test_end_node_template.py
**Root Cause:**
- In Issue #5 fix, added graph lookup for node labels in AUTO mode
- But forgot to get graph from context first
- TEMPLATE mode already had: graph = context.get("graph")
**Fix:**
- Added: graph = context.get("graph") at start of AUTO mode block
- Same pattern as TEMPLATE mode
- graph is optional (None if not in context), so if-check is safe
**Tests:**
- test_auto_mode_concatenates_all_analyses - should pass now
- test_auto_mode_skips_skipped_nodes - should pass now
Files changed:
- backend/workflow_executor.py: Added graph = context.get("graph") line 596
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Introduced a new utility function to streamline the extraction of user-facing content from aggregated workflow results.
- Updated backend prompt handling to utilize the new function for improved clarity and maintainability.
- Adjusted frontend analysis component to leverage the utility for consistent content display across different workflow result formats.
These changes enhance the overall user experience by ensuring more reliable and readable output from workflow executions.
- Added support for handling aggregated results in workflow prompts, allowing for various data formats (string, object).
- Introduced a utility function to filter active prompts for both pipeline and workflow types in the analysis page.
- Updated content handling in the analysis component to accommodate new workflow data structures.
This improves the flexibility and usability of the prompt execution process in both backend and frontend components.
ISSUE: Inline templates referencing node outputs ({{ node_id.analysis_core }},
{{ node_id.signal_xyz }}) were not resolved - AI received empty data from
previous workflow stages.
ROOT CAUSE: load_prompt_template() only loaded system placeholders
(name, age, etc.) but not node execution results from context['node_results'].
FIX:
- Extract node outputs from context['node_results']
- Add as placeholders: node_id.analysis_core, node_id.signal_xyz, node_id.question_xyz
- Format matches PlaceholderPicker extraction logic
- Debug logging shows which node placeholders are added
TESTING:
- System placeholder test: ✅ SUCCESS (name, age, geschlecht resolved)
- Node output placeholders: Fixed (previously missing)
- User workflow: Join → Analysis → End now receives upstream data
Part 3: Inline Prompts - placeholder resolution completion
- Updated the `validate_csv_template` function to normalize both the column signature and field mappings for accurate comparison, preventing false warnings about mismatches.
- Enhanced warning messages to provide clearer guidance on the relationship between normalized signatures and raw field mappings.
- Added a new test to ensure that normalized signatures do not trigger false warnings when compared to raw mappings.
- Introduced a new endpoint for validating CSV templates without saving, allowing users to check field mappings and type conversions.
- Updated the `create_system_template` and `update_system_template` functions to include validation reports in responses.
- Enhanced error handling in CSV import processes by integrating `enrich_row_error` for more informative error messages.
- Improved the AdminCsvTemplateEditorPage to support format checking and display validation results, enhancing user experience.
- Incremented version numbers for `csv_import` and `admin_csv_templates` to reflect these updates.
- Increased precision for `kcal_active`, `kcal_resting`, `hr_avg`, and `hr_max` fields in the activity log schema.
- Added a new function `_activity_hr_bpm` to validate heart rate values during CSV import, ensuring they fall within plausible ranges.
- Updated the CSV parser to utilize the new heart rate validation function for improved data integrity.
- Enhanced the type converter to accommodate additional aliases for energy fields in CSV imports.
- Added a test to verify conversion of active energy from kJ to kcal, ensuring accurate data handling.
- Added SAVEPOINT management to the `_import_activity` function to improve error handling during CSV imports.
- Moved the training type resolution logic to occur within a transaction block, ensuring that errors can be rolled back without affecting the entire import process.
- Enhanced error logging to capture evaluation failures, providing better insights during CSV import operations.
- Modified `_resolve_training_type_for_activity` to accept a database cursor, improving efficiency and avoiding potential deadlocks during CSV imports.
- Introduced `get_training_type_for_activity_with_cursor` to handle training type resolution with an existing cursor, streamlining database interactions.
- Updated related calls in the activity import logic to utilize the new function, ensuring consistent behavior across the application.
- Introduced `diagnose_blood_pressure_row` and `diagnose_activity_row` functions to validate and analyze blood pressure and activity data from CSV imports.
- Updated the CSV import logic to handle combined datetime columns for blood pressure and activity, improving data integrity during import.
- Enhanced type conversion specifications to include `start_time` for blood pressure and activity, ensuring accurate data mapping.
- Added tests to validate the new diagnosis functions and their integration with existing import processes, ensuring robustness and reliability.
- Updated frontend messages to provide clearer guidance on blood pressure and activity data handling during CSV imports.
- Implemented a new endpoint for diagnosing CSV imports without writing to the database, allowing users to validate mappings and type conversions.
- Introduced the `diagnose_vitals_row` function to analyze vital metrics and provide detailed feedback on data validity.
- Enhanced the CSV import logic to include alias handling for vital fields, improving compatibility with different CSV formats.
- Updated the frontend to support the new diagnosis feature, including UI elements for displaying diagnosis results and error details.
- Added tests to ensure the correctness of the new diagnosis functionality and its integration with existing import processes.
- Updated migration scripts to ensure idempotent behavior for the source CHECK constraint, allowing for consistent application even if previous migrations were partially successful.
- Enhanced SQL logic to drop existing constraints safely and re-add them, ensuring compatibility with the universal CSV import.
- Clarified comments for better understanding of migration context and functionality.
- Updated the CSV import logic to include SAVEPOINT management, allowing for better error handling during the vitals baseline import process.
- Enhanced the SQL migration script to drop existing CHECK constraints related to the 'source' field, ensuring compatibility with the new universal CSV import.
- Incremented DB_SCHEMA_VERSION to "20260409c" to reflect these changes and improve the import process reliability.
- Incremented DB_SCHEMA_VERSION to "20260409b" to reflect changes related to the vitals_baseline.source CSV migration.
- Updated comments to clarify the migration context for better maintainability.
- Updated the aggregate_mapped_rows function to support multiple row policies, allowing for flexible handling of duplicate keys during CSV imports.
- Introduced deduplication of identical rows before aggregation, improving data integrity.
- Enhanced validation for multi_row_policy and dedupe_identical_rows in import_row_processing specifications.
- Updated the AdminCsvTemplateEditorPage to include options for multi-row policies and deduplication settings, improving user experience in template management.
- Added comprehensive tests to validate new aggregation behaviors and ensure correct error handling for multiple rows.
- Bumped version numbers for csv_import to 0.3.1 and admin_csv_templates to 0.2.0, reflecting recent enhancements.
- Added support for import_row_processing_default in the CSV modules endpoint, improving data handling capabilities.
- Introduced new row aggregation operations in the AdminCsvTemplateEditorPage, allowing for more flexible data processing options.
- Implemented parsing and validation for custom row processing configurations, enhancing user experience in template management.
- Updated the CSV import logic to support new row processing specifications for weight and vitals baseline, allowing for better data aggregation and validation.
- Implemented handling for multiple rows on the same day, enabling aggregation of values such as averages for vitals and last values for weight.
- Enhanced test coverage for the new import functionalities, ensuring correct behavior during data processing and validation.
- Refactored the module registry to include default import row processing options for better flexibility in handling CSV data.