Skip to content

Commit 49ae8b7

Browse files
authored
Feat/implicit rendering phase5 (#740)
* Squashed commit of the following: commit 999ac48fe2a46d9cc2106ce29abe42790291ae80 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed May 14 10:15:41 2025 -0600 refactor(transform): clean up reactive_runtime AST transformer and improve ID stability - Rewrote docstrings for all major methods in AutoAtomTransformer to clarify reactive intent and transformation semantics - Safely refactored tuple unpacking, consumer detection, and parameter mapping logic for readability - Removed unused `_lift_assignment_stmt` method and simplified inline call lifting logic - Added debug level logging guards to avoid excessive output in production - Replaced 8 character MD5 truncation with 12 character hash in `generate_stable_id` for better collision resistance - Ensured reverse mapping and dependency wiring handles tuple returning atoms correctly - Preserved all functionality. no behavior changes introduced commit 9b055b2502f4df5d43753a1cdbd763ad5faa6d03 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Tue May 13 13:55:16 2025 -0600 feat(ast): lift AugAssign into reactive atoms using scoped dependency maps This commit adds support for lifting `AugAssign` (e.g., `counter += val`) into reactive atoms by resolving scoped dependencies via `self._stmt_variable_maps`. It also fully removes the obsolete `variable_assignments_by_lineno` logic. Notable updates: - Introduced `_lift_augassign_stmt` to handle augmented assignments - All variable-to-atom mappings are now scoped via `_get_variable_map_for_stmt` - Added debug logging to trace lifting and component ID generation - Removed stale code tied to per-line variable tracking NOTE: This commit is being checked in as is to preserve progress. commit 17ab16a25a798e4cfcdc895e46c344735fd1ccef Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon May 12 16:07:04 2025 -0600 refactor(ast): lift tuple assignments and unify dependency tracking logic - Add support for lifting tuple unpacking into atoms using intermediate result variable - Introduce `_find_unique_dependencies` to deduplicate dependencies and improve error visibility - Track `tuple_returning_atoms` to allow consumer patching with correct subscript access - Replace `_find_dependencies` with generalized AST visitor that works on all node types - Patch consumer functions with a reverse variable-to-atom lookup for tuple outputs - Refactor `_lift_producer_stmt` to handle both tuple and single targets uniformly - Improve logging for debugging and traceability Note: This commit Includes debug logs, loose variable naming, and areas needing polish. Committed to avoid losing progress before next stage of refactor. commit 0c3ddb6a6d58e4af8ea4964fba9b32bc6026967f Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Fri May 9 11:24:53 2025 -0600 feat(reactive-runtime): lift producers/consumers with scoped atom resolution This change generalizes lifting logic for top-level producer and consumer statements by introducing scoped atom resolution based on statement line numbers. This ensures correct handling of variable shadowing and enables reactive transformation of derived assignments (e.g., val = x * 2). Key changes: - Track variable-to-atom bindings by line number to handle shadowing - Extend _find_dependencies to detect base object access in method calls - Support Assign targets in _build_atom_function, returning result as needed - Introduce _uses_known_atoms and _get_variable_map_for_stmt for scoped analysis - Fix _replace_dep_args to skip Store contexts and support general expressions - Add structured logging for traceability and debugging commit 7342b6077e3b56c7f53ee91596498b045c6644cd Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed May 7 13:41:39 2025 -0600 refactor(ast): extract helper methods for lifting component calls Split `lift_component_call_to_atom` into smaller, focused methods: - `_find_dependencies` identifies dependency atoms and variable names - `_make_param_mapping` maps dependencies to param names - `_patch_callsite` rewrites the AST call with param names and component_id - `_build_atom_function` generates the reactive function definition - `_make_callsite` creates the final function call AST node This improves readability, enables targeted testing, and lays groundwork for Phase 4 support. commit fa8e523c2fdd4fbd93c45c608abf6d79838f552f Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed May 7 11:26:15 2025 -0600 refactor(ast): restructure module transformer with helper methods and runtime scaffolding guards - Split `visit_Module` into multiple helper methods: - `_generate_component_metadata` - `_map_variables_to_atoms` - `_lift_top_level_statements` - `_has_runtime_execution` - `_build_runtime_imports` - `_build_runtime_execution` - Added `_reset` method to clean transformer state between script runs - Preserved original import order and ensured runtime scaffolding (`get_workflow` and `workflow.execute`) is only added when not already present - Cleaned up logging and restructured passes for clarity and extension This sets up a clean and extensible foundation for lifting non-component producers going forward in Phase 4. commit 7d3d4c9109948a2a1dc268b3b05aa3f80880be45 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon May 5 11:10:03 2025 -0600 feat(config): add support for disabling reactivity via preswald.toml - Introduces `disable_reactivity` under the `[project]` section in `preswald.toml` - Adds utility functions `read_disable_reactivity` and `reactivity_explicitly_disabled` in `utils.py` - `main.py` and `runner.py` now respect this config and disable the reactive runtime accordingly - Updates `configuration.mdx` documentation to describe the new option commit ad991735fef6272594d668fc06ff35a507f5803a Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon May 5 06:07:12 2025 -0600 docs(workflow): document automatic lifting of top-level components into atoms Adds a new section to the Workflow documentation explaining how top-level component calls (e.g., `slider()`, `text()`, `table()`) are automatically lifted into workflow atoms during script execution. This enables reactivity in concise scripts without requiring explicit `@workflow.atom()` usage. The section includes: - A minimal working example using `slider` and `table` - An explanation of the benefits (state tracking, DAG inclusion, selective reruns) - A real-world log output showing the transformed AST when debug logging is enabled commit cf152d11695fdfe25a3e7e86466552c0d0584053 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Sun May 4 21:49:23 2025 -0600 chore(logging): guard verbose debug logs in ScriptRunner and WorkflowContext This patch wraps expensive or verbose logging calls in `logger.isEnabledFor(logging.DEBUG)` to improve performance and avoid unnecessary log output in non-debug environments. Changes include: - Guarding component update and output capture logs in `ScriptRunner` - Downgrading frequent info-level logs to debug level where appropriate - Avoiding evaluation of expensive formatting (e.g., tracebacks) unless log level allows - Adding debug logging for context variable assignment in `WorkflowContext` commit 1e8b80233c216dc184b740e6bb0431cf7c7f355e Merge: 241e499 40d9767 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Sun May 4 18:44:48 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/component-dag-reactivity-phase3 commit 241e4999595e25211bd2de9fce7e85cc586fc920 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Sun May 4 18:43:07 2025 -0600 docs(coreconcepts): document reactive fallback behavior and `identifier` usage - Explain when the reactive runtime is disabled and falls back to full script reruns - Add expected log messages for diagnosing fallback mode - Introduce the `identifier` keyword for stable component identity in dynamic contexts - Clarify how `identifier` supports DAG tracking and reactivity commit e9865497fd35edd6f77e0d7b3ff7a8fd6acd3c81 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Sun May 4 17:49:48 2025 -0600 fix(render_tracking): support stable component IDs using `identifier` param Ensure that `with_render_tracking` correctly forwards the `identifier` argument to `generate_stable_id`, enabling deterministic ID generation in dynamic contexts such as loops. This allows multiple components with predictable IDs to be created in user scripts using `identifier=f"text-loop-{num}"`. Verified by rendering two unique text components in a for-loop. commit cc2a7109ea1fd160598fad0f9960d34d5c55cd53 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Sun May 4 17:15:01 2025 -0600 refactor: remove unused reactive system and auto-wrapping support This commit removes the now-unnecessary `reactive.py` module, which included the `@reactive` decorator and `wrap_auto_atoms` logic for manually registering atoms at runtime. These mechanisms have been fully superseded by the new AST-based reactive runtime. - Deleted `preswald/interfaces/reactive.py` - Removed `sl_wrap_auto_atoms` import and usage in `ScriptRunner` - Downgraded `track_dependency` warnings to debug level - Added debug logs for context stack operations in `dependency_tracker.py` This simplifies the runtime model and eliminates legacy code paths. commit fbeaef9ca967bc0f91ea68fccfef0afe41a48a07 Merge: c82c582 7264cc2 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu May 1 18:26:46 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/component-dag-reactivity-phase3 commit c82c582da24fde103074103902c13a9d2cb7c400 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu May 1 14:28:28 2025 -0600 fix: resolve style and import issues in workflow and reactive components - Reordered and cleaned up import statements for clarity. - Replaced `join(stack + [atom_name])` with `join([*stack, atom_name])` to avoid list concatenation. - Replaced `dict()` calls with literal dictionaries where applicable (e.g., `marker={...}`). - Updated the `__init__` constructor of `Workflow` to use `Optional[RetryPolicy]` for better type compatibility. - Minor refactoring of `logger.error` and `logger.debug` calls for consistency. - Fixed incorrect string formatting in the `repr` method of `TrackedValue`. - Replaced tuple-based union type annotations with `Optional` where appropriate. commit b7473e536ffa9de81557e81dc0d669ea598730cf Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu May 1 13:51:50 2025 -0600 refactor(utils): improve generate_stable_id robustness and type annotations - Replaced Optional[...] with `str | None` for consistency with modern typing. - Downgraded identifier hash logging from info to debug for less noisy output. - Replaced preswald source detection with `startswith(preswald_src_dir)` for accuracy. - Minor import cleanup: reordered and removed unused imports. commit 486430173cc424a1e6f277e7046945387930156b Merge: 22e45be 107e6a4 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu May 1 13:33:27 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/component-dag-reactivity-phase3 commit 22e45bef5f25d0622523ae4c0461440c7fddccde Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu May 1 13:01:25 2025 -0600 refactor(runtime): skip reactive transform if reactivity is disabled Move AST transformation logic behind a reactivity check to avoid unnecessary processing. Adds a local `compile_and_run` helper to simplify execution logic across reactive, non-reactive, and fallback paths. Behavior is unchanged, but structure is cleaner. Prepares `run_script` to avoid wasted effort during fallback reruns. commit 29199bf1a4ff59cc01254fb41a0d87765e9b40d6 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu May 1 09:27:51 2025 -0600 feat(runtime): add runtime reactivity toggle with safe fallback execution - Introduced `enable_reactivity()` and `disable_reactivity()` to control reactive execution state at runtime. - Enabled reactivity by default in `ScriptRunner.start()` and disabled it only on AST transform failure or when no atoms are affected. - Updated `with_render_tracking` to respect the reactivity toggle and bypass DAG logic when disabled. - Cleaned up rerun logic and component registration paths to respect the reactivity lifecycle. commit c073e68a2330c5cec94db6bc9ac616c47b3a7267 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed Apr 30 16:35:38 2025 -0600 fix(table): ensure TableViewerWidget updates when rowData changes Previously, the table component was not re-rendering when rowData changed due to memoization logic that did not account for rowData differences. This patch: - Adds a custom areRowDataEqual() function to perform shallow equality checks on row arrays. - Updates the memoization comparison in DynamicComponents to use areRowDataEqual for the `rowData` prop. As a result, TableViewerWidget now correctly reflects updated data, such as when the row limit is adjusted by a slider. commit ee07d8eb0363f85d89b970273110c55c4372ebf7 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed Apr 30 14:31:34 2025 -0600 refactor(transformer): replace top-level atom calls with workflow.execute() Previously, auto-lifted atoms were invoked directly at the top level, forcing eager execution. This change removes those calls and replaces them with: workflow = get_workflow() workflow.execute() This defers atom execution to the reactive runtime, enabling true on-demand reactivity and DAG-based control. Additional changes: - Removed unused imports for `TrackedValue` and `track_dependency`. - Preserved user-defined imports and inserted the `get_workflow` import explicitly. This results in cleaner, more declarative output scripts aligned with reactive principles. commit 906659de609efdf0a3245851481d01df14be7d66 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed Apr 30 10:19:29 2025 -0600 refactor(service): update force_recompute to accept atom names directly Previously, force_recompute() expected component IDs and attempted to map them back to atom producers, which was unnecessary and error-prone. This commit refactors the method to accept a set of atom names directly, removing the need for reverse lookups and simplifying the logic. commit 03fa74a6105d2ee6dd311d45a87a2e7bc591e018 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Tue Apr 29 16:36:01 2025 -0600 feat(runtime): improve reactive DAG tracking, atom execution, and diagnostics - Refactored reactive runtime AST transformer to lift component calls into stable, decorated atoms - Enhanced `BasePreswaldService` to register dummy atoms and manage component-to-atom mapping more reliably - Improved `Workflow` class: - Refined dependency registration, execution ordering, retry logic, and debug logs - Clarified and enriched all key docstrings for better maintainability - Simplified and hardened render tracking with improved `with_render_tracking` decorator - Introduced better state diffing and component handling in `append_component` - Unified retry, DAG traversal, and context management across service layers - Upgraded ScriptRunner to log clearer rerun diagnostics and preserve widget-to-atom context - Rewrote and documented `reactive_runtime.py` AST pass for clarity, stability, and extensibility - Improved `TrackedValue` to log and track dynamic access - Clarified `generate_stable_id` and introduced `generate_stable_atom_name_from_component_id` for consistent naming - Replaced numerous debug logs with info-level summaries and standardized log format commit 663c119290f20319e4d446a8b28b264c07c4a7c2 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Fri Apr 25 15:30:01 2025 -0600 chore(logging): optimize render tracking logs for debug mode - Downgrade component state and dataflow tracking logs to DEBUG level. - Add isEnabledFor(DEBUG) guards around potentially large object serialization. - Avoid logging large component payloads unless explicitly debugging. - Improve DAG related debug logs for better visibility during development. This improves runtime performance when not debugging and avoids unnecessary serialization costs. commit 31bda9c4882ef574fe90bc106bc2c17c3339562e Merge: 53b0076 7a2fb5a Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Fri Apr 25 15:18:43 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/component-dag-reactivity-phase3 commit 53b0076c59db4b8c7edfdbc456a455908f8485aa Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Fri Apr 25 15:06:45 2025 -0600 refactor(reactivity): improve logging, comments, and safety across reactive runtime - Improve DAG and atom tracking logs: consistently use [DAG] prefixes for easier filtering - Downgrade noisy info-level logs (e.g., stable ID generation, atom execution times) to debug - Add missing comments to explain dependency tracking contexts, auto-atom wrapping rules, and fallback behaviors - Strengthen TrackedValue to ensure comparison operators also track dependencies - Safely handle popping empty dependency context stacks with warning - Clarify retry logging during atom execution, including dynamic retry delay - Standardize hash generation callsite logging across utils and reactive system - Add TODO to remove builtins pollution once per-script reactive scoping is ready This cleanup improves the observability and resilience of Phase 3 AST-driven reactivity without changing core behavior. commit 93417e4813aefc9c988e3ae8c79205e87b2959ab Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Fri Apr 25 13:15:16 2025 -0600 feat(runtime): refine reactive rerun, logging, and AST transformer - Improved rerun debouncing and fallback for DAG-based reactivity - Guarded large object logs with DEBUG checks - Cleaned and clarified append_component logic in BasePreswaldService - Improved AST transformer with debug-only variable-to-atom overwrite detection - Ensured safe producer registration for dynamic layouts - Improved DAG registration logging in workflow - Minor performance optimizations and additional debug visibility commit 2dc8da981c1b9791192d1c07de85d1eb5b5ee6f0 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 24 16:23:06 2025 -0600 fix(render_tracking): ensure correct atom context for component DAG registration Wrap component append logic in `with service.active_atom` using a stable atom ID derived from the component ID. This ensures that producer relationships are properly recorded for reactive dependency tracking. commit 0072c03ae0c4d09477f8a56b0021e08a821447df Merge: bd72f61 404cd72 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 24 16:03:47 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/component-dag-reactivity-phase3 commit bd72f61cb4e4a18391d55e76021b4dcab4bf32c8 Merge: 6055ff3 3c5eba9 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 24 15:11:01 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/component-dag-reactivity-phase3 commit 6055ff3ca94f38ce5aeb1e6d040a5c6ae878653b Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 24 09:31:25 2025 -0600 feat(runtime): enable full reactive DAG-based reruns for user scripts This commit introduces the new AST-based reactive runtime system. Key changes include: - Adds `AutoAtomTransformer` and `transform_source` to support dependency tracking and automatic atom generation via AST transformation. - Updates `ScriptRunner` to compile user scripts using the transformer. - Refactors `with_render_tracking` to simplify the decorator logic and remove dynamic **kwargs injection (no longer needed). - Ensures all core components now explicitly accept **kwargs for future extensibility. - Adds `generate_stable_atom_id_from_component_id` for consistent DAG node IDs. This enables fully reactive behavior for user scripts with automatic dependency inference, and lays the foundation for reactive rendering optimizations and custom DAG visualizations. commit 876a87914fba27e77b8fc188694f4da0f8820ebf Merge: f5be426 2253446 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Tue Apr 22 08:29:44 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/component-dag-reactivity-phase3 commit f5be4267a4ddc1856e35e740391546232432f6ab Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon Apr 21 05:54:06 2025 -0600 refactor: fixed typo commit 54a72fb0572c71e1fa9a22bef522d463c8822bc1 Merge: d3ca73f 665cdf6 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon Apr 21 05:48:49 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/component-dag-reactivity-phase3 commit d3ca73fbd74fe92b5b45dd063e4a0dfcbb9d8d3c Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon Apr 21 05:06:28 2025 -0600 feat(reactive): auto-run top-level atoms and support implicit registration - Replaced legacy `main()` workaround with `execute_relevant_atoms()` to auto-run top-level atoms after script execution. - Introduced `_fresh` flag on wrapped atoms to prevent double-wrapping. - Removed redundant hasattr checks for internal workflow attributes, since they are always initialized. - Temporarily filtered out functions with required positional arguments from auto-atom wrapping to avoid breaking user-defined code. - Temporary patches to `builtins` (`sl_reactive`, `sl_wrap_auto_atoms`), will be replaced with an opt-in `with reactive_scope():` context manager. commit f4e020bd6601c5dcb1795f71700bf0a18b0f429e Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Fri Apr 18 15:58:44 2025 -0600 feat(reactive): auto-wrap global atoms and invoke main() in runner - Introduced `builtins.sl_wrap_auto_atoms` to expose the auto-wrapping logic globally. - `ScriptRunner` now calls `sl_wrap_auto_atoms()` after executing user script globals. - As a temporary measure, `main()` is invoked immediately after auto-wrapping if defined. - Deferred some `import` statements inside functions to avoid early workflow access. - These changes ensure all top-level user-defined functions are registered as atoms before dependency tracking begins, eliminating unknown atom errors on reruns. commit 33858cd8f092171dffab12d2de65ad430bb2be61 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Fri Apr 18 14:46:46 2025 -0600 refactor(reactive): dynamically detect builtin components and unify metadata handling Replaces hardcoded BUILTIN_COMPONENTS set with dynamic detection using `_preswald_component_type` metadata added by `with_render_tracking`. Ensures that built-in UI components are excluded from auto-wrapping via `wrap_auto_atoms`. Also refactors `with_render_tracking` to prioritize `_preswald_component` detection before falling back to raw dicts with IDs. Adds `_preswald_component_type` directly to the wrapper for discovery. This enables correct reactive auto-wrapping and builtin component filtering without manual lists. commit dff942868613b78eeff1f602245993b060b2f55e Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Fri Apr 18 12:16:49 2025 -0600 refactor(reactive): move auto-atom registry and tracking to workflow instance This change eliminates global contamination in `reactive.py` by moving both `auto_atom_registry` and `_registered_reactive_atoms` into the `Workflow` object. Each workflow now maintains its own registry of implicit atoms and their decorated functions. Benefits: - Allows multiple workflows to exist concurrently without registry collision. - Makes reactive behavior predictable and testable in server/multi-user contexts. - Avoids hidden side effects across script boundaries. commit 745313074903a17c71b0dfb7a59adb82137fd7ca Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Fri Apr 18 11:58:14 2025 -0600 feat(reactivity): introduce sl_reactive and TrackedValue for implicit DAG tracking This commit introduces the new `sl_reactive` decorator, exposed globally via `builtins.sl_reactive`, enabling automatic atom registration without explicit imports. This allows users to define reactive functions that implicitly register themselves as workflow atoms. Key features: - Introduces `TrackedValue`, which wraps returned values to track dataflow dependencies during access. - Adds `dependency_tracker` module for scoped context tracking via push/pop semantics. - Adds `wrap_auto_atoms` to auto-wrap eligible functions in a module's globals as reactive atoms. - Adds `AtomContext` and `_register_dependency` hooks to the workflow for DAG registration. **BREAKING CHANGE**: Introduces a new global `sl_reactive` variable in the Python `builtins` namespace, which may cause unexpected behavior in environments where this name is already defined. The risk is mmitigated by prefixing with `sl_` to clearly namespace it under StructuredLabs conventions. commit 128deb6b78ade6ac6d9756cf817961131b1970f8 Merge: 509c256 ce3b072 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 17 16:28:44 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/component-dag-reactivity-phase3 commit 509c256b8844dbb404044c9b3bddc85223d970e6 Merge: 5b3eb6a af637f8 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Tue Apr 15 08:59:31 2025 -0600 Merge branch 'feat/component-dag-reactivity' of github.com:BloggerBust/preswald into feat/component-dag-reactivity-phase2 commit af637f8b1548d6679e1e9898073d5de13b02d70a Merge: ef7829b 5c5c534 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Tue Apr 15 08:55:02 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/component-dag-reactivity commit 5b3eb6af7c78118ef51e6ab2113c3284cc19686b Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon Apr 14 17:33:38 2025 -0600 refactor(core): simplify type annotations and streamline DAG handling - Replaced older `typing` constructs (`Optional`, `Dict`, `List`, `Set`) with Python 3.10+ native type hinting (`str | None`, `dict`, `list`, `set`, etc.) - Cleaned up `LayoutManager.patch_component` by removing an unused variable - Improved DAG-related logging clarity in `ScriptRunner` - Removed commented-out `@dataclass` stub from `ComponentReturn` - Reorganized imports across `workflow.py` for readability and consistency These changes modernize the codebase and reduce clutter while improving maintainability and runtime introspection. commit 4f09f7da9812311fb5fc9046aa80668e7849ecb0 Merge: b62d87c ef7829b Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon Apr 14 17:20:24 2025 -0600 Merge branch 'feat/component-dag-reactivity' of github.com:BloggerBust/preswald into feat/component-dag-reactivity-phase2 commit ef7829b57efa9f646810973497cc4ee692ba3cf3 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon Apr 14 17:07:41 2025 -0600 style(components): clean up imports and modernize type hints - Removed unused imports (e.g., `hashlib`, `inspect`, `Optional`, `List`) - Replaced `Optional[T]` and `List[T]` with `T | None` and `list[T]` using Python 3.10+ syntax - Reordered import statements for clarity and consistency - Removed unnecessary service instantiations in component functions - Ran `ruff` to ensure formatting consistency This change improves code readability and aligns the components module with modern Python typing conventions. commit c8bd47de412c45374a9f564df0312a6a70543249 Merge: d0f4317 510172f Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon Apr 14 17:05:11 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/component-dag-reactivity commit b62d87c3b98a599a753c639246c14450fab3c3da Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon Apr 14 16:32:31 2025 -0600 feat(runtime): enable reactive reruns by patching layout instead of full reruns - Implemented DAG-based atom recomputation in `ScriptRunner.rerun` - Introduced `LayoutManager.patch_component` to selectively update component layout - Modified `BasePreswaldService.append_component` to patch existing components - Added `ComponentReturn` class to preserve internal component metadata - Improved dummy atom registration with `_ensure_dummy_atom` fallback - Cleaned up script rerun logic to avoid unnecessary layout clearing - Reorganized result handling to unwrap values and maintain layout consistency This change enables partial reruns of affected atoms, eliminating full script execution and significantly improving reactivity. commit bee9eb4e9297b419002f4171bd1e5b36a29a1431 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Fri Apr 11 13:36:59 2025 -0600 feat(dag): support DAG-aware reactivity with atom re-registration and dummy fallbacks - Introduces original_func param to Atom to preserve the original function across reruns - Ensures component_producer tracking is restored on each run - Adds placeholder atom registration for components or atoms used before explicit definition - Improves logging for debugging DAG structure and reactivity behavior - Adds _is_rerun guard to prevent duplicate atom registration during reactive reruns TODO: Dummy atoms and fallback logic are temporary; these should be removed once all DAGs are defined via @atom decorator. commit 99d911b4a4cee1fc6a66ba137dc5db72c6038221 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 10 14:58:41 2025 -0600 feat(workflow): track component producers and infer DAG dependencies automatically This commit begins phase 2 of the DAG-based reactivity system by introducing automatic tracking of component-producing atoms and registering them as dependencies when their outputs are read. - Adds `register_component_producer()` to `Workflow` and calls it from `BasePreswaldService.append_component` - When `get_component_state()` is called, the service now adds a DAG edge from the active atom to the component’s producer - The `@workflow.atom` decorator now infers dependencies from function parameter names if not explicitly provided - `_execute_atom` now resolves values from declared dependencies, not from parameters This sets the stage for component-level dependency tracking based on value access. commit d0f431775b1352a82b07a7123a84dd70449281f6 Merge: 44dc267 3bb68a4 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 10 12:04:29 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/component-dag-reactivity commit 44dc2671453cdd6d68f1e4d733ed95e8ec46d913 Merge: 57ed4d1 32bafec Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 10 08:17:42 2025 -0600 Merge branch 'feat/renderbuffer-integration' of github.com:BloggerBust/preswald into feat/component-dag-reactivity commit 32bafecded23d4971bd1aed37fb210fd0fac3a10 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 10 08:15:44 2025 -0600 build(pyodide): remove platform constraint on msgpack to enable renderbuffer in virtual_service commit 57ed4d12a10a6f64b6ef0e94abfa3492642d4d86 Merge: d01f694 95a98e7 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 10 08:15:01 2025 -0600 Merge branch 'feat/renderbuffer-integration' of github.com:BloggerBust/preswald into feat/component-dag-reactivity commit 95a98e7ca61fcb9f7033cdc28197c365597f1efe Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 10 07:50:20 2025 -0600 chore: remove .projectile from git and ignore it in .gitignore - Untracked .projectile to prevent accidental commits - Added .projectile to .gitignore under Emacs-specific section commit a80720fda341236b9ef117ece8d15862f4573b36 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 10 07:43:03 2025 -0600 chore: re-enable msgpack dependency for RenderBuffer hashing commit 39d584e44cbdca06e7e80ca5a1b42dd43b824bf3 Merge: 3b4322e d5446df Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 10 07:35:55 2025 -0600 Merge branch 'main' of github.com:StructuredLabs/preswald into feat/renderbuffer-integration commit d01f69455a6396ce3f8b49a731da09aaa95287bb Merge: a3c3741 3b4322e Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed Apr 9 16:17:47 2025 -0600 Merge branch 'feat/renderbuffer-integration' of github.com:BloggerBust/preswald into feat/component-dag-reactivity commit 3b4322e10f520eabf5793eb400797bd76842f5db Merge: 297dbea aa33fcb Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed Apr 9 16:17:04 2025 -0600 Merge branch 'feat/server-preswald-service-renderbuffer' of github.com:BloggerBust/preswald into feat/renderbuffer-integration commit aa33fcbdac90f344dea750ef33cad7d221d6c128 Merge: ecbe88a 499df83 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed Apr 9 16:12:54 2025 -0600 Merge branch 'feat/virtual-service-add-renderbuffer' of github.com:BloggerBust/preswald into feat/server-preswald-service-renderbuffer commit 499df83ba213966e1cca5038c197b1e47085d34c Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed Apr 9 16:11:35 2025 -0600 chore: remove unnecessary import commit a3c3741287ac993013eba3a8ed41beb8ebc01b7f Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed Apr 9 15:33:29 2025 -0600 refactor(components): unify component rendering with @with_render_tracking - Replaced manual render logic in all components with the @with_render_tracking decorator - Standardized all component return types to use ComponentReturn - Centralized stable ID generation with generate_stable_id() - Improved debug logging for DAG dependency tracking and callsite resolution - Removed unused or duplicated logic for appending components - Updated dependencies in pyproject.toml (e.g., re-enabled msgpack) This change simplifies component authoring, improves consistency, and lays the groundwork for DAG-based reactive updates. commit 77e261cf96e0beb957a9cb9428fc93fa6bf7d48d Merge: 59f85fa 297dbea Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed Apr 9 10:28:08 2025 -0600 Merge branch 'feat/renderbuffer-integration' of github.com:BloggerBust/preswald into feat/component-dag-reactivity commit 297dbead3255046f94ab124d1be90fc4813b926b Merge: c37d41d ecbe88a Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed Apr 9 10:22:37 2025 -0600 Merge branch 'feat/server-preswald-service-renderbuffer' of github.com:StructuredLabs/preswald into feat/renderbuffer-integration commit ecbe88a9db6f46821842db98c3494cf99fed97d3 Merge: 3748772 2e39c69 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed Apr 9 09:50:39 2025 -0600 Merge branch 'feat/virtual-service-add-renderbuffer' of github.com:BloggerBust/preswald into feat/server-preswald-service-renderbuffer commit 2e39c69f79ed7de01198f19b49bd80eca56b69a6 Merge: c320d7b b328b42 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed Apr 9 09:49:44 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/virtual-service-add-renderbuffer commit 59f85fad0c56bb8d753711738685611c19de450a Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Tue Apr 8 16:57:13 2025 -0600 feat(engine): add DAG-based reactive execution for component reruns Phase 1 implementation of DAG-based reactivity: - Introduces `Workflow` and `Atom` tracking to `BasePreswaldService` - Adds `active_atom` context manager to record dependencies during component state access - Adds `get_affected_components` and `force_recompute` methods to selectively rerun affected components - Updates `ScriptRunner.rerun()` to compute affected downstream components using the DAG - Uses deferred import of `PreswaldService` in `ScriptRunner` to avoid circular dependency - Ensures each component registers itself in the workflow DAG during rendering This enables rerunning only the components affected by upstream state changes, while still using the RenderBuffer to prevent unnecessary re-renders. commit c37d41ddbe3cc6b5a79086ca570727a3d146ae3e Merge: eb0f1a0 3748772 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Tue Apr 8 10:30:40 2025 -0600 Merge branch 'feat/server-preswald-service-renderbuffer' of github.com:StructuredLabs/preswald into feat/renderbuffer-integration commit 3748772b55cb739212693e93d0532d675c4ac4b9 Merge: 9818ae0 c320d7b Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Tue Apr 8 10:00:40 2025 -0600 Merge branch 'feat/virtual-service-add-renderbuffer' of github.com:StructuredLabs/preswald into feat/server-preswald-service-renderbuffer commit eb0f1a0b61ba7681d06bca7f035807f93658d72b Merge: 4cd0721 c58d046 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Tue Apr 8 08:05:46 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/renderbuffer-integration commit 9818ae06d1dde95b0866af02093d827536d116dc Merge: 52c2d62 c58d046 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Tue Apr 8 08:04:50 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/server-preswald-service-renderbuffer commit c320d7b14bfe7fd861620d3acfdff557c279638e Merge: c7080d8 c58d046 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Tue Apr 8 08:04:15 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/virtual-service-add-renderbuffer commit 4cd07214557136372af6385b1140e2f9eb121fb6 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon Apr 7 20:06:38 2025 -0600 refactor(service): remove fastapi.WebSocket dependency from BasePreswaldService This refactor removes the direct dependency on `fastapi.WebSocket` from `BasePreswaldService` to support alternative websocket implementations such as the `VirtualWebSocket` used in Pyodide. Also includes: - Generalization of type hints for `websocket` parameters to `Any`. - Removal of the `fastapi` import from `base_service.py`. - Removed the platform constraint from the `msgpack` dependency to enable usage in Pyodide. Other unrelated changes: - Removed the platform constraint from `duckdb` as it is now required in Pyodide builds. - Updated the test wheel reference in `pyodide_test.html` from `0.1.49` to `0.1.51`. commit 7ee6cf12f3292301348279520bbfc696ab2a9ceb Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon Apr 7 17:45:02 2025 -0600 feat(renderbuffer): integrate diffing into core components and restore msgpack dependency - Re-added `msgpack` as a dependency in `setup.py`, now required by RenderBuffer (was previously removed when the Fastplotlib component was disabled). - Commented out the unused `render_and_send_fastplotlib()` function, which was left behind after Fastplotlib was removed from `main`. - Applied Ruff formatting and cleanup across engine and interface modules. commit 5d51a179d624d144b86a6bd6e1aea2242a05cb66 Merge: 2a0079f be63e85 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon Apr 7 17:16:12 2025 -0600 Merge branch 'main' of github.com:BloggerBust/preswald into feat/fastplotlib-rerenderbuffer commit 2a0079fb276d8ec74e349139ca645b00d535b9d8 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Mon Apr 7 16:23:57 2025 -0600 feat(components): integrate RenderBuffer to skip redundant renders Introduces `RenderBuffer` support across all Preswald components to prevent unnecessary re-renders and frontend updates when component state has not changed. Components now use `generate_stable_id()` to ensure deterministic ids based on callsite or user-supplied identifiers, enabling consistent diffing between reruns. Additionally, common service logic has been extracted into a shared `BasePreswaldService`, now inherited by both `ServerPreswaldService` and `VirtualPreswaldService`. - All components now use `should_render()` to conditionally append - Debug logs are now guarded to avoid expensive serialization - `RenderBuffer` hashes values internally and accepts either raw objects or precomputed hashes commit 52c2d62c87761b5dd45158f16dc9119125bd0dd2 Merge: 151447b c7080d8 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Fri Apr 4 09:22:47 2025 -0600 Merge branch 'feat/virtual-service-add-renderbuffer' of github.com:StructuredLabs/preswald into feat/server-preswald-service-renderbuffer commit c7080d86323c1838d2615425c4116caad60462f2 Merge: ed9e902 6156f9c Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Fri Apr 4 09:20:24 2025 -0600 Merge branch 'fix/missing-monaco-editor' of github.com:StructuredLabs/preswald into feat/virtual-service-add-renderbuffer commit 6156f9cf08d19c88b16b13ac122073fb637f99b8 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Fri Apr 4 09:05:42 2025 -0600 fix(frontend): add @monaco-editor/react dependency to fix build error The PlaygroundWidget component imports @monaco-editor/react, but the package was missing from the dependencies. This caused the frontend build to fail after syncing with upstream. This commit adds the missing package to resolve the issue. commit 151447ba3bc44f0e347dbc1d6cd438279474eb3a Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 3 14:09:58 2025 -0600 feat(server): use RenderBuffer to skip redundant reruns in ServerPreswaldService This change introduces a render buffer for ServerPreswaldService that tracks component state and avoids unnecessary reruns when updates do not modify any actual values. Aligns behavior with VirtualPreswaldService. Logs a debug message when reruns are skipped due to unchanged state. commit ed9e90229c150c9b7e4cecdcc0ae7dce01837b82 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 3 13:15:44 2025 -0600 feat(runtime): add RenderBuffer to VirtualPreswaldService to skip redundant reruns - Introduces `RenderBuffer` class in `engine/utils.py` to track previous component state. - Integrates `RenderBuffer` into `VirtualPreswaldService` to detect and skip reruns when state hasn't changed. - Adds `update_if_changed` logic to prevent unnecessary recomputations and logging to confirm behavior. - This is a foundational step toward a reactive runtime and will be extended to `ServerPreswaldService` in a follow-up. Tested manually in `pyodide_test.html` by sending repeated identical messages and observing correct skipping of reruns. commit 212d80baa42439c2ce5ad514d7618b848feda3d3 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Thu Apr 3 11:04:45 2025 -0600 fix(virtual_service): suppress Ruff warning and clean up Pyodide handler - Removed unused import (`Object`) from JS bridge - Suppressed RUF006 warning by explicitly allowing fire-and-forget task - Simplified `except` clause (unused exception variable) - Minor style cleanup in test page - Updated `pyodide_test.html` to initialize `PreswaldService` during testing commit 711393c52e6932c1cdff399cfc0c2325e6d8ca39 Author: BloggerBust <trevor.wilson@bloggerbust.ca> Date: Wed Apr 2 18:22:59 2025 -0600 feat: skip reruns in virtual service if no state changes detected - Updates handle_message_from_js to robustly parse JsProxy input - Skips rerun execution when incoming component state matches current state - Ensures backwards compatibility with previous JS message shape - Adds eslint-config-prettier to package-lock.json (already in devDependencies) * fix(utils): restore `export_app_to_pdf` function mistakenly removed during merge The `export_app_to_pdf` function was unintentionally deleted while resolving merge conflicts. This commit restores the original implementation without modifications. * fix(dataProcessing): remove mistakenly reintroduced areRowDataEqual function This function was previously deleted but was unintentionally reintroduced during merge conflict resolution. This commit removes it again to reflect the intended state of the file. * fix(dag): ensure correct producer registration when atom returns tuple - Fixes bug where dynamic producer registration failed for components returned from atoms that produce tuples of components. - Adds defensive guard in `register_component_producer` to skip unknown atoms. - Ensures deduplication of dependencies in the `@workflow.atom` decorator. - Prevents duplicate dependency appends in `get_component_state`. - Make dependencies a set when lifting component call to atom to avoid duplication during AST transformation. * fix(reactive_runtime): correctly resolve atom returning tuple dependencies in AST transformation - Enhanced `_replace_dep_args` to support rewriting variable references for tuple returning atoms. - Added inversion of `variable_to_atom` to enable index-based subscript generation for tuple unpacking. - Introduced `tuple_returning_atoms` set to `AutoAtomTransformer` for accurate subscript handling. This resolves incorrect parameter rewriting when unpacking tuples from atoms and improves AST transformation clarity. * feat(registry): add render registry system for stream and return-based display - Introduce `interfaces.render.registry` for managing: - Output stream functions, such as`print` - Return-based renderers e.g. `df.head()` -> HTML - Mimetype-to-component mappings - Declarative registration via `register_*` functions - Add `generic` component fallback to render arbitrary mimetypes - Enable AST transformer to detect and lift stream/render-return calls into atoms - Support static registration from user scripts via `register_return_renderer`, etc. Also includes internal improvements required to support these features: - Track variable-to-atom mappings per-scope using a `Frame` stack - Skip lifting known components inside user-defined functions - Add blackbox lifting fallback for user-defined functions - Improve diagnostics and modularity for `lift_*_stmt` logic This lays the foundation for Phase 5 goals: auto-lifting displayable user code into renderable components via return values or calls with displayble side effects. * feat(runtime): support return renderers for inferred object types This commit enables automatic lifting of return-renderable expressions based on inferred variable types. For example, if a variable is known to be a `pd.DataFrame`, the transformer can recognize `df.to_html()` and lift it using the registered return renderer for `pandas.DataFrame.to_html`. Key changes: - Track inferred return types for atoms that construct known types. - Normalize candidate keys using `import_aliases` to support user defined import aliases (e.g., `pd` -> `pandas`). - Improve dependency replacement logic for tuple unpacked variables by tracking index positions. - Log helpful diagnostics when expected mappings are missing. * fix(dag): ensure full forward and backward propagation in affected atom traversal Updates `_get_affected_atoms` to perform a full DAG closure including both: - forward propagation by recomputing all consumers of changed atoms - backward propagation by performing a re-run of producers of recomputed consumers This change addresses scenarios where side effecting atoms like `plot` mutate objects used by downstream atoms, such as `fig.savefig` but would not previously trigger recomputation of those downstream consumers. Also adds a detailed docstring explaining the traversal logic. * refactor(transformer): centralize atom finalization and registration logic Introduce `_finalize_and_register_atom` helper to reduce repetition across lifting methods. Also add `_finalize_atom_deps` to ensure dependencies are injected properly. Replace direct usage of `_build_atom_function` and appending to `generated_atoms` with calls to `_finalize_and_register_atom` in: - `_lift_augassign_stmt` - `_lift_output_stream_stmt` - `_lift_return_renderable_call` - `_lift_blackbox_function_call` - `_lift_producer_stmt` - `_lift_consumer_stmt` Also introduce `self._module` field for future use in module aware transforms. * feat(reactive-runtime): add support for lifting display renderers like fig.show() - Introduced a new `FrameContext` class to cleanly manage per-frame transformer state. - Implemented `_try_lift_display_renderer` and `_maybe_lift_display_renderer_from_expr` to handle known display method calls (e.g., `fig.show()`) as reactive atoms. - Patched arg resolution logic to handle tuple-unpacked values. - Registered display renderer for `matplotlib.figure.Figure.show` that captures and renders figures as PNG data URIs. - Extended import generation to include used display renderers. - Updated AST traversal to recognize and lift registered display calls into separate atoms. * feat(runtime): support in script registration of display dependency resolvers This update enables display dependency resolvers to be registered directly within user scripts using `register_display_dependency_resolver`. During AST transformation, such resolver registrations are detected and evaluated early enough to inform dependency lifting logic. - Evaluates lambda resolvers at transform time and registers them immediately. - Adds fallback logic in `_try_lift_display_renderer` to use `_find_dependencies` if the resolver is absent or returns no dependencies. - Adds detection of resolver based dependencies for expressions like `plt.show()`. - Ensures lifted atoms now correctly include dependencies inferred from registered resolvers. * feat: add support for generic fallback rendering and dynamic tuple return registration - Added `GenericWidget` to frontend and handled it in `DynamicComponents.jsx` - Introduced `register_tuple_return` and `get_tuple_return_types` to support dynamic return type registration for tuple returning functions - Updated `register_display_renderer` to accept optional `source_function` and `return_types` for automatic return type registration - Modified `display_matplotlib_show` to return a tuple of generic components for each figure and close figures after rendering to prevent accumulation - Improved logging and fallback behavior in the AST transformer (`reactive_runtime.py`) - Now supports `register_tuple_return` directly in user scripts - Logs helpful warnings when return types are missing - Removed hardcoded matplotlib logic in favor of registry based detection * chore(registry): disable plotly display method to prevent new tab rendering Commented out the pre-registration of `plotly.graph_objects.Figure.show` as a display method. Currently, this causes figures to render in a new browser tab, which is not the intended behavior. We’ll re-enable it once inline rendering is correctly supported. * feat(ui,transformer): add GenericWidget for mimetype rendering and log AST rewrite summary - Introduced `GenericWidget` React component for rendering diverse mimetypes including images, HTML, PDF, and text formats.
1 parent fe302a0 commit 49ae8b7

File tree

10 files changed

+1362
-406
lines changed

10 files changed

+1362
-406
lines changed

frontend/src/components/DynamicComponents.jsx

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { Alert, AlertDescription } from '@/components/ui/alert';
66
import { cn } from '@/lib/utils';
77
// Utilities
88
import { createExtractKeyProps } from '@/utils/extractKeyProps';
9-
import { comm } from '@/utils/websocket';
109

1110
// Widgets
1211
import AlertWidget from './widgets/AlertWidget';
@@ -16,7 +15,7 @@ import ChatWidget from './widgets/ChatWidget';
1615
import CheckboxWidget from './widgets/CheckboxWidget';
1716
import DAGVisualizationWidget from './widgets/DAGVisualizationWidget';
1817
import DataVisualizationWidget from './widgets/DataVisualizationWidget';
19-
import FastplotlibWidget from './widgets/FastplotlibWidget';
18+
//import FastplotlibWidget from './widgets/FastplotlibWidget';
2019
import ImageWidget from './widgets/ImageWidget';
2120
import JSONViewerWidget from './widgets/JSONViewerWidget';
2221
import MarkdownRendererWidget from './widgets/MarkdownRendererWidget';
@@ -31,6 +30,7 @@ import SpinnerWidget from './widgets/SpinnerWidget';
3130
import TableViewerWidget from './widgets/TableViewerWidget';
3231
import TextInputWidget from './widgets/TextInputWidget';
3332
import TopbarWidget from './widgets/TopbarWidget';
33+
import GenericWidget from './widgets/GenericWidget';
3434
import UnknownWidget from './widgets/UnknownWidget';
3535

3636
const extractKeyProps = createExtractKeyProps();
@@ -313,21 +313,21 @@ const MemoizedComponent = memo(
313313
/>
314314
);
315315

316-
case 'fastplotlib_component':
317-
const { className, data, config, label, src } = component;
318-
return (
319-
<FastplotlibWidget
320-
key={componentKey}
321-
{...props}
322-
data={component.data}
323-
config={component.config}
324-
src={src}
325-
label={label}
326-
className={className}
327-
clientId={comm.clientId}
328-
id={componentId}
329-
/>
330-
);
316+
// case 'fastplotlib_component':
317+
// const { className, data, config, label, src } = component;
318+
// return (
319+
// <FastplotlibWidget
320+
// key={componentKey}
321+
// {...props}
322+
// data={component.data}
323+
// config={component.config}
324+
// src={src}
325+
// label={label}
326+
// className={className}
327+
// clientId={comm.clientId}
328+
// id={componentId}
329+
// />
330+
// );
331331

332332
case 'playground':
333333
return (
@@ -350,6 +350,17 @@ const MemoizedComponent = memo(
350350
case 'separator':
351351
return <SeparatorWidget key={componentKey} id={componentId} />;
352352

353+
case 'generic':
354+
return (
355+
<GenericWidget
356+
key={componentKey}
357+
{...props}
358+
value={component.value}
359+
mimetype={component.mimetype || 'text/plain'}
360+
id={componentId}
361+
/>
362+
);
363+
353364
default:
354365
console.warn(`[DynamicComponents] Unknown component type: ${component.type}`);
355366
return (
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import React from 'react';
2+
3+
const GenericWidget = ({ id, value, mimetype = 'text/plain' }) => {
4+
const cleanMime = mimetype.split(';')[0].trim().toLowerCase();
5+
6+
const renderContent = () => {
7+
if (!value) {
8+
return <div className="text-gray-500 italic">No content to display.</div>;
9+
}
10+
11+
if (cleanMime.startsWith('image/')) {
12+
return (
13+
<img
14+
src={value}
15+
alt="rendered image"
16+
className="rounded-lg shadow max-w-full mx-auto"
17+
/>
18+
);
19+
}
20+
21+
if (cleanMime === 'text/html') {
22+
return (
23+
<div
24+
className="prose max-w-none"
25+
dangerouslySetInnerHTML={{ __html: value }}
26+
/>
27+
);
28+
}
29+
30+
if (cleanMime === 'application/pdf') {
31+
return (
32+
<iframe
33+
src={value}
34+
title="PDF viewer"
35+
className="w-full h-[600px] border rounded"
36+
/>
37+
);
38+
}
39+
40+
if ([
41+
'text/plain',
42+
'application/json',
43+
'text/csv',
44+
'text/markdown'
45+
].includes(cleanMime)) {
46+
return (
47+
<pre className="text-sm text-gray-800 whitespace-pre-wrap p-2 bg-gray-100 rounded">
48+
{value}
49+
</pre>
50+
);
51+
}
52+
53+
return (
54+
<div className="text-sm text-gray-500 italic">
55+
Unsupported mimetype <code>{mimetype}</code>
56+
</div>
57+
);
58+
};
59+
60+
return (
61+
<div
62+
id={id}
63+
className="border border-gray-200 rounded-md shadow-sm p-4 bg-white overflow-x-auto"
64+
>
65+
{renderContent()}
66+
</div>
67+
);
68+
};
69+
70+
export default GenericWidget;

preswald/engine/base_service.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,10 @@ def get_component_state(self, component_id: str, default: Any = None) -> Any:
290290
elif producer != self._current_atom:
291291
if logger.isEnabledFor(logging.DEBUG):
292292
logger.debug(f"[DAG] Registering dynamic dependency {self._current_atom=} {producer=}")
293-
self._workflow.atoms[self._current_atom].dependencies.add(producer)
293+
294+
atom = self._workflow.atoms[self._current_atom]
295+
if producer not in atom.dependencies and producer in self._workflow.atoms:
296+
atom.dependencies.append(producer)
294297
else:
295298
logger.info(f"[DAG] Producer matches current atom; skipping dependency {self._current_atom=} {component_id=}")
296299

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class FrameContext:
2+
def __init__(self):
3+
self.variable_to_atom: dict[str, str] = {}
4+
self.generated_atoms: list[ast.FunctionDef] = []
5+
self.stmt_variable_maps = {}
6+
self.tuple_variable_index: dict[str, int] = {}
7+
self.tuple_unpacked_names = {}
8+
self.tuple_returning_atoms: set[str] = set()
9+
self.atom_return_types: dict[str, str] = {}

0 commit comments

Comments
 (0)