feat(extensions): install progress tracking with host agent orchestration#827
feat(extensions): install progress tracking with host agent orchestration#827yasinBursali wants to merge 2 commits intoLight-Heart-Labs:mainfrom
Conversation
…r stopped services User extensions now get real health checking instead of file-based status. "stopped" status (red badge) replaces the misleading "enabled" for crashed containers. Start button allows restarting stopped extensions without the disable-enable workaround. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tion Host agent writes stage-by-stage progress files during extension install (setup_hook → pulling → starting → done/error). Dashboard-API serves progress via polling endpoint and reflects install status in catalog. Replaces two-call install pattern with single 202+background-thread endpoint. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Lightheartdevs
left a comment
There was a problem hiding this comment.
Audit: REQUEST CHANGES — CI failing + depends on #825 + merge conflict
The architecture is solid — background thread install with atomic progress files, 202 immediate response, stage-by-stage tracking (setup_hook → pull → start). Good UX improvement over the current spinner-only experience.
Security looks good from the description:
- Auth enforced before side effects
- Service IDs regex-validated
- subprocess uses list args (no shell=True)
- Progress files are atomic writes
Blockers:
-
CI failing: Ruff lint + api test failures. Need to fix unused imports and test issues.
-
Depends on #825: Shares
user_extensions.pyand health-based status code. #825 needs to merge first, but #825 itself has a merge conflict from the liquid metal migration (#829). -
Merge conflict with main:
Extensions.jsxwas migrated to theme variables in #829. Any frontend changes need to usebg-theme-card,text-theme-text-muted,text-theme-accent-light, etc. instead of hardcoded zinc/indigo. See the mapping in my comment on #825.
Merge order: #825 (rebased) → #827 (rebased) → #828
Question: The frontend timeout (300s per the description) vs backend subprocess timeout (600s) — if the frontend gives up at 300s but the backend is still pulling a 44GB image, what happens? Does the progress file stay in "pulling" state forever? Is there cleanup?
What
Add install progress tracking for extensions — the host agent writes stage-by-stage progress during install, dashboard-api serves it via a polling endpoint, and the catalog reflects real-time install status.
Why
When installing an extension, users see only a spinner for up to 5 minutes with no indication of what's happening. If Docker is pulling a large image on slow internet, there's no progress feedback. If it fails, the error is generic. This makes the install experience feel broken even when it's working.
How
/v1/extension/installendpoint returns 202 immediately, runs setup_hook → pull → start in a background thread. Writes atomic progress files (data/extension-progress/{service_id}.json) at each stage.GET /api/extensions/{service_id}/progressendpoint for frontend polling._compute_extension_status()checks progress files first — returns "installing", "setting_up", or "error" based on active install state._call_agent_install()that handles the full lifecycle.Architecture
Security
_BEARER_REstrips tokens before writing to progress file_resolve_setup_hook()validates path containment via resolve().relative_to()^[a-z0-9][a-z0-9_-]*$before use in filenameTest Coverage
10 new tests in
TestInstallProgress:All tests: 80 passed, 0 failed
Three Pillars Impact
Platform Impact
Manual Test Steps (all platforms)
Known Tech Debt (follow-up)
_handle_setup_hook()has its own inline manifest parsing — should be refactored to use_resolve_setup_hook()shared helperSequence
PR 2 of 3 — Extension Lifecycle States
🤖 Generated with Claude Code