Skip to content

feat: Support structured background tasks with clean REPL rendering#151

Draft
harvisaiagent-bot wants to merge 2 commits intodgarana:masterfrom
harvisaiagent-bot:feature/background-tasks
Draft

feat: Support structured background tasks with clean REPL rendering#151
harvisaiagent-bot wants to merge 2 commits intodgarana:masterfrom
harvisaiagent-bot:feature/background-tasks

Conversation

@harvisaiagent-bot
Copy link
Copy Markdown
Contributor

Summary

This PR implements issue #150 by adding comprehensive support for structured background tasks with clean REPL rendering and task status tracking.

Changes

Core Implementation

  • New BackgroundTaskManager class (vulcano/app/background.py):

    • Task registration with unique IDs
    • Output queuing to prevent prompt corruption
    • Task state tracking (RUNNING, COMPLETED, FAILED)
    • Thread-safe operations with proper locking
  • VulcanoApp Integration:

    • Added background_tasks attribute to all app instances
    • REPL displays queued background output before each prompt
    • Bottom toolbar shows active task count (e.g., "[2 tasks running]")
    • CLI mode waits for all background tasks before process exit

Key Features

  1. N concurrent tasks: Users can run multiple background tasks simultaneously
  2. Clean REPL rendering: Output is queued and displayed between prompts, avoiding corruption
  3. Task status tracking: Tasks have RUNNING/COMPLETED/FAILED states with timestamps
  4. CLI/REPL parity: Coherent behavior in both modes - CLI waits for completion, REPL stays responsive
  5. Toolbar status: prompt_toolkit bottom toolbar displays active task counts

Updated Examples

  • examples/async_output_example.py now demonstrates structured background task usage
  • README updated with comprehensive background task documentation

Tests

  • 10 new unit tests for BackgroundTaskManager
  • 3 new integration tests in classes_test.py
  • All 72 existing tests still pass
  • Full linting compliance

Example Usage

import threading
import time

@app.command
def start_background(interval=1, ticks=5):
    def worker(task_id):
        try:
            for i in range(ticks):
                time.sleep(interval)
                app.background_tasks.enqueue_output(task_id, "tick {}".format(i))
            app.background_tasks.mark_completed(task_id)
        except Exception as e:
            app.background_tasks.mark_failed(task_id, e)

    thread = threading.Thread(target=worker, args=(None,), daemon=True)
    task_id = app.background_tasks.register_task("background_{}".format(ticks), thread)
    thread = threading.Thread(target=worker, args=(task_id,), daemon=True)
    app.background_tasks._tasks[task_id].thread = thread
    thread.start()
    return "Background task started ({})".format(task_id)

Testing

# Run background manager tests
python -m pytest vulcano/app/background_test.py -v

# Run integration tests
python -m pytest vulcano/app/classes_test.py -v

# All tests pass (72 total)

Resolves

Closes #150


Conversation: https://app.warp.dev/conversation/ab6f3eba-df43-4232-8333-f926bc27a1d5
Run: https://oz.warp.dev/runs/019d4b16-5873-7a65-820a-05a57bed5353

This PR was generated with Oz.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 1, 2026

Codecov Report

❌ Patch coverage is 95.71734% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.04%. Comparing base (91ac7b6) to head (f27cbd7).

Files with missing lines Patch % Lines
vulcano/app/background_test.py 93.40% 12 Missing ⚠️
vulcano/app/classes.py 93.22% 8 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##            master     #151      +/-   ##
===========================================
- Coverage   100.00%   99.04%   -0.96%     
===========================================
  Files           21       23       +2     
  Lines         1689     2094     +405     
===========================================
+ Hits          1689     2074     +385     
- Misses           0       20      +20     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@harvisaiagent-bot
Copy link
Copy Markdown
Contributor Author

Update: Enhanced Task Name Display in REPL Toolbar

This update implements the full requirements from issue #150 by making background tasks clearly visible in the REPL UX.

What Changed

The REPL bottom toolbar now displays individual task names alongside the count:

  • Before: [2 tasks running]
  • After: [2 tasks running: download_data, process_file]

Implementation Details

  • Task names are truncated to 15 characters for readability (e.g., very_long_task_... )
  • Shows up to 3 task names; displays ... when more than 3 tasks are active
  • Example with many tasks: [5 tasks running: task1, task2, task3, ...]

Testing

Added 3 new unit tests:

  • test_get_status_summary_with_names: Validates name inclusion
  • test_get_status_summary_truncates_long_names: Ensures 15-char truncation
  • test_get_status_summary_limits_displayed_tasks: Validates 3-task limit with ellipsis

All 13 background manager tests and 39 integration tests pass ✅

Conventional Commit

feat: display individual task names in REPL bottom toolbar

Closes #150

The implementation now fully addresses issue #150's requirement for active background tasks to be visible in the UX itself.

@harvisaiagent-bot
Copy link
Copy Markdown
Contributor Author

UX Fix: Live UI Refresh for Background Task Output

This update addresses the follow-up issue where background task output was not rendered immediately in the REPL. Previously, output was queued correctly but only displayed when the user interacted (typed another command).

Changes

Core Implementation:

  • Added set_ui_invalidate_callback() to BackgroundTaskManager to register a UI refresh callback
  • Integrated prompt_toolkit.application.get_app() and app.invalidate() for thread-safe UI redrawing
  • Created a background polling thread (background_output_renderer) that:
    • Checks output queue every 100ms
    • Displays queued output using print_formatted_text() to render above the active prompt
    • Triggers UI invalidation to update the toolbar in real-time
  • Callback is invoked automatically when:
    • Tasks emit output via enqueue_output()
    • Tasks change status via mark_completed() or mark_failed()

User Experience:

  • ✅ Background output appears immediately without requiring user interaction
  • ✅ Bottom toolbar updates in real-time showing active task count and names
  • ✅ Output renders cleanly above the prompt line (no corruption)
  • ✅ All previous goals maintained: N concurrent tasks, clean REPL rendering, CLI mode waits for completion

Testing

All tests pass:

  • ✅ 13 background manager unit tests
  • ✅ 39 VulcanoApp integration tests
  • ✅ Added test_live_output.py for manual verification

Example Behavior

🌋 test_live interval=1 ticks=5
Background task started! Watch output appear live without typing anything.
[task_0] Live output tick 0 - should appear immediately!  # ← appears after 1s automatically
[task_0] Live output tick 1 - should appear immediately!  # ← appears after 2s automatically
[task_0] Live output tick 2 - should appear immediately!  # ← appears after 3s automatically
[task_0] Live output tick 3 - should appear immediately!  # ← appears after 4s automatically
[task_0] Live output tick 4 - should appear immediately!  # ← appears after 5s automatically
🌋                                                [1 task running: live_test_5]  # ← toolbar updates live

The user doesn't need to type anything - output appears live as tasks emit it!

@harvisaiagent-bot harvisaiagent-bot force-pushed the feature/background-tasks branch from 092fbcc to 3ded1c3 Compare April 1, 2026 22:33
harvisaiagent-bot added a commit to harvisaiagent-bot/vulcano that referenced this pull request Apr 1, 2026
Previously, background task output in direct CLI mode was buffered and
only displayed after all tasks completed. This fix adds a background
polling thread (cli_output_renderer) that continuously checks for and
displays queued output every 50ms during CLI execution.

The fix ensures:
- CLI mode remains alive until all background tasks finish
- Background output streams progressively while tasks run
- REPL behavior and toolbar support remain intact
- Thread cleanup happens properly via try/finally

Addresses follow-up bug in issue dgarana#150 / PR dgarana#151.

Co-Authored-By: Oz <oz-agent@warp.dev>
@harvisaiagent-bot harvisaiagent-bot force-pushed the feature/background-tasks branch from ce23229 to f27cbd7 Compare April 1, 2026 22:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support structured background tasks with clean REPL rendering and task status

1 participant