Skip to content

GUI – Live State Display (Status Bar + State Tab) #33

Description

@maddes8cht

Summary

Show the current WorkflowState (current_phase, iteration, is_complete, termination_reason, payload) in the GUI during a run — both as a compact status bar and as a detailed State tab.


Display Components

1. Status Bar (compact, always visible)

A narrow bar between the toolbar and the main columns frame, showing the most important fields at a glance:

[●] Phase: loop  |  Iteration: 3 / 10  |  Complete: X  |  Term: —
  • Phase is color-coded: preparation (blue), loop (green), finalization (orange), idle (gray)
  • Iteration shows current / max
  • A small colored dot indicates running / stopped / error state
  • Updates in near-real-time during execution

2. State Tab (detailed)

A third tab State in the existing _output_notebook (alongside Agent Preview and Live Output), showing the full state as a key-value table:

current_phase        loop
iteration            3 / 10
is_complete          False
termination_reason   
payload              { ... }    ← formatted JSON, collapsible if large
  • Read-only key-value list
  • Payload rendered as syntax-highlighted JSON in a scrollable text widget
  • Toggleable auto-scroll to latest state on update
  • Shows placeholder "No state data yet" when idle

Technical Communication Approaches

Three options were considered for feeding state data from the engine thread to the GUI:

A) Queue-based (Recommended)

How: Pass an optional state_callback to ExecutionEngine.__init__. The engine calls state_callback(state.to_dict()) after every self.state.merge(). The GUI passes a lambda that puts ("state", data) onto the existing _log_queue. The _poll_log_queue handler processes "state" messages to update both widgets.

Changes required:

  • core/engine.py: ~3 lines — store state_callback, call it after merge
  • ui/app.py: ~15 lines — new queue message type, update two widgets
  • No new polling, no new threads, no file I/O

Pros: Thread-safe (queue), minimal engine changes, piggybacks on existing architecture, no race conditions, no file I/O latency.
Cons: Slightly more coupling between engine and GUI (one callback).

B) Timer-based Polling

How: In _poll_log_queue (every 100ms), also read self._engine.state fields directly.

Changes required: Only ui/app.py — no engine changes.

Pros: Simplest to implement.
Cons: Race condition (engine thread mutates state while GUI reads — pragmatically safe under GIL, but not guaranteed); reads state even when nothing changed.

C) File Watcher (on .openloop/state_update.json)

How: A periodic timer (every 500ms) checks the mtime of .openloop/state_update.json and re-reads it if changed.

Changes required: Only ui/app.py — no engine changes.

Pros: Decoupled; also useful for debugging post-mortem.
Cons: File I/O every cycle; state only captured after agent writes the file (less granular than after merge); polling for file changes adds complexity; the file path depends on workdir which can change.


Implementation Plan

Phase 1 — Status Bar

  1. Add state_callback parameter to ExecutionEngine.__init__ and invoke after merge()
  2. Add ("state", data) handling in _poll_log_queue
  3. Create StatusBar frame widget in _build_ui (between toolbar and columns)
  4. Wire state updates to status bar labels
  5. Add color coding and status dot

Phase 2 — State Tab

  1. Add third tab to _output_notebook
  2. Build key-value display with formatted JSON payload renderer
  3. Wire same state updates to the tab
  4. Add placeholder text for pre-run / post-run state
  5. Add auto-scroll toggle

Open Questions

  • Should the status bar also show the payload size or a payload preview?
  • Should the State tab allow copying the full state JSON to clipboard?
  • Auto-scroll in State tab: always on or toggleable?
  • How to handle large payloads — truncate in status bar, full in tab?

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions