This commit is contained in:
2026-03-21 15:12:52 -07:00
parent 11384266e3
commit d9a6b1bfb4
6 changed files with 512 additions and 21 deletions

View File

@@ -769,6 +769,7 @@ class PipelineLiveProgress:
self._enabled = bool(enabled)
self._pipe_labels = [str(x) for x in (pipe_labels or [])]
self._lock = RLock()
self._event_callback: Any = None
self._console: Optional[Console] = None
self._live: Optional[Live] = None
@@ -809,6 +810,24 @@ class PipelineLiveProgress:
# Title line state (active per-item context)
self._active_subtask_text: Optional[str] = None
def set_event_callback(self, callback: Any) -> None:
with self._lock:
self._event_callback = callback
def _emit_event(self, event: str, **payload: Any) -> None:
callback = self._event_callback
if not callable(callback):
return
data: Dict[str, Any] = {
"phase": "progress",
"event": str(event or "").strip(),
}
data.update(payload)
try:
callback(data)
except Exception:
logger.exception("Failed to emit PipelineLiveProgress event '%s'", event)
def _title_text(self) -> str:
"""Compute the Pipeline panel title.
@@ -1093,6 +1112,12 @@ class PipelineLiveProgress:
prog.update(task_id, description=msg, refresh=True)
except Exception:
logger.exception("Failed to update status task %s in set_pipe_status_text", task_id)
self._emit_event(
"status",
pipe_index=pidx,
pipe_label=self._pipe_labels[pidx] if 0 <= pidx < len(self._pipe_labels) else str(pidx),
text=msg,
)
def clear_pipe_status_text(self, pipe_index: int) -> None:
if not self._enabled:
@@ -1134,6 +1159,12 @@ class PipelineLiveProgress:
pipe_task = self._pipe_tasks[pidx]
pipe_progress.update(pipe_task, completed=pct, total=100, refresh=True)
self._update_overall()
self._emit_event(
"pipe-percent",
pipe_index=pidx,
pipe_label=self._pipe_labels[pidx] if 0 <= pidx < len(self._pipe_labels) else str(pidx),
percent=pct,
)
except Exception:
logger.exception("Failed to set pipe percent for pipe %s in set_pipe_percent", pipe_index)
@@ -1262,6 +1293,7 @@ class PipelineLiveProgress:
try:
task_id = self._transfers.add_task(key, total=task_total)
self._transfer_tasks[key] = task_id
self._emit_event("transfer-begin", label=key, total=task_total)
except Exception:
logger.exception("Failed to add transfer task %s in begin_transfer", key)
@@ -1290,6 +1322,12 @@ class PipelineLiveProgress:
if total is not None and total > 0:
kwargs["total"] = int(total)
self._transfers.update(task_id, refresh=True, **kwargs)
self._emit_event(
"transfer",
label=key,
completed=(int(completed) if completed is not None else None),
total=(int(total) if total is not None and total > 0 else None),
)
except Exception:
logger.exception("Failed to update transfer '%s'", key)
@@ -1302,6 +1340,7 @@ class PipelineLiveProgress:
return
try:
self._transfers.remove_task(task_id)
self._emit_event("transfer-finish", label=key)
except Exception:
logger.exception("Failed to remove transfer task '%s' in finish_transfer", key)
@@ -1363,6 +1402,13 @@ class PipelineLiveProgress:
logger.exception("Failed to start pipe task timer in begin_pipe for %s", pipe_index)
self._update_overall()
self._emit_event(
"pipe-begin",
pipe_index=pipe_index,
pipe_label=self._pipe_labels[pipe_index] if 0 <= pipe_index < len(self._pipe_labels) else str(pipe_index),
total_items=total_items,
percent_mode=percent_mode,
)
labels: List[str] = []
if isinstance(items_preview, list) and items_preview:
@@ -1452,6 +1498,15 @@ class PipelineLiveProgress:
else:
pipe_progress.update(pipe_task, completed=done)
self._emit_event(
"pipe-emit",
pipe_index=pipe_index,
pipe_label=self._pipe_labels[pipe_index] if 0 <= pipe_index < len(self._pipe_labels) else str(pipe_index),
completed=done,
total=self._pipe_totals[pipe_index],
item_label=_pipeline_progress_item_label(emitted),
)
self._update_overall()
# Clear any status line now that it emitted.
@@ -1538,6 +1593,14 @@ class PipelineLiveProgress:
except Exception:
logger.exception("Failed to stop pipe task %s during finish_pipe", pipe_index)
self._emit_event(
"pipe-finish",
pipe_index=pipe_index,
pipe_label=self._pipe_labels[pipe_index] if 0 <= pipe_index < len(self._pipe_labels) else str(pipe_index),
completed=self._pipe_done[pipe_index],
total=self._pipe_totals[pipe_index],
)
self._update_overall()
def complete_all_pipes(self) -> None: