soothe-cli 0.6.13__tar.gz → 0.6.15__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/PKG-INFO +1 -1
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/textual_adapter.py +30 -2
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/messages.py +79 -23
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/.gitignore +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/README.md +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/pyproject.toml +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/__init__.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/cli/__init__.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/cli/commands/__init__.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/cli/commands/autopilot_cmd.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/cli/commands/cron_cmd.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/cli/commands/loop_cmd.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/cli/commands/run_cmd.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/cli/commands/status_cmd.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/cli/execution/__init__.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/cli/execution/daemon.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/cli/execution/daemon_errors.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/cli/execution/headless.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/cli/execution/headless_renderer.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/cli/execution/launcher.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/cli/main.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/config/__init__.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/config/cli_config.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/config/loader.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/config/logging_setup.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/__init__.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/headless/processor.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/headless/processor_state.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/parse/_utils.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/parse/message_processing.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/parse/tool_call_resolution.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/parse/tool_message_format.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/parse/tool_result.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/policy/display_policy.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/policy/essential_events.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/policy/tui_trace_log.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/presentation/duration_format.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/presentation/engine.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/presentation/explore_task_display.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/presentation/renderer_base.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/presentation/renderer_protocol.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/state/file_tracker.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/state/session_stats.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/state/step_router.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/state/stream_accumulator.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/state/transcript.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/transport/session.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/turn/pipeline.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/turn/prepare.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/wire/chunk_filter.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/wire/display_text.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/wire/message_text.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/wire/messages.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/__init__.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/_cli_context.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/_env_vars.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/_version.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/app/__init__.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/app/_app.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/app/_commands.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/app/_execution.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/app/_history.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/app/_messages_mixin.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/app/_model.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/app/_module_init.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/app/_startup.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/app/_ui.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/app/app.tcss +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/binding.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/command_registry.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/commands/__init__.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/commands/command_router.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/commands/slash_commands.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/commands/subagent_routing.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/config.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/file_change_notify.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/file_change_renderers.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/hooks.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/input.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/media_utils.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/model_config.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/path_utils.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/preview_limits.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/project_utils.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/sessions.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/skills/__init__.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/skills/invocation.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/skills/load.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/theme.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/tips.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/tool_display.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/unicode_security.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/update_check.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/__init__.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/_links.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/autocomplete.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/autopilot_dashboard.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/autopilot_screen.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/chat_input.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/clipboard.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/diff.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/editor.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/file_change_preview.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/history.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/loading.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/loop_selector.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/mcp_viewer.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/message_store.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/model_selector.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/notification_settings.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/status.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/theme_selector.py +0 -0
- {soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/tui/widgets/welcome.py +0 -0
|
@@ -119,6 +119,9 @@ from soothe_cli.tui.widgets.messages import (
|
|
|
119
119
|
|
|
120
120
|
logger = logging.getLogger(__name__)
|
|
121
121
|
|
|
122
|
+
# IG-504: LLM retry event type for step card status display
|
|
123
|
+
LLM_RETRY_ATTEMPT = "soothe.cognition.llm.retry.attempt"
|
|
124
|
+
|
|
122
125
|
# ---------------------------------------------------------------------------
|
|
123
126
|
# Adapter core
|
|
124
127
|
# ---------------------------------------------------------------------------
|
|
@@ -2793,12 +2796,37 @@ async def execute_task_textual(
|
|
|
2793
2796
|
)
|
|
2794
2797
|
continue
|
|
2795
2798
|
|
|
2799
|
+
# IG-504: Handle LLM retry events for step card status display
|
|
2800
|
+
if event_type == LLM_RETRY_ATTEMPT:
|
|
2801
|
+
# Find the running step card for this thread and update retry status
|
|
2802
|
+
attempt = int(data.get("attempt", 0))
|
|
2803
|
+
max_attempts = int(data.get("max_attempts", 0))
|
|
2804
|
+
error_type = str(data.get("error_type", "timeout"))
|
|
2805
|
+
# Try to find a running step card via namespace or active steps
|
|
2806
|
+
widget = None
|
|
2807
|
+
if ns_key:
|
|
2808
|
+
widget = adapter._step_by_namespace.get(ns_key)
|
|
2809
|
+
if widget is None:
|
|
2810
|
+
# Fallback: find any running step in current step messages
|
|
2811
|
+
for step_widget in adapter._current_step_messages.values():
|
|
2812
|
+
if step_widget._status == "running": # noqa: SLF001
|
|
2813
|
+
widget = step_widget
|
|
2814
|
+
break
|
|
2815
|
+
if widget is not None:
|
|
2816
|
+
widget.set_retry_status(attempt, max_attempts, error_type)
|
|
2817
|
+
continue
|
|
2818
|
+
|
|
2796
2819
|
if event_type == LOOP_REASON_EVENT_TYPE:
|
|
2797
2820
|
assessment_reasoning = str(
|
|
2798
2821
|
data.get("assessment_reasoning", "")
|
|
2799
2822
|
).strip()
|
|
2800
2823
|
plan_reasoning = str(data.get("plan_reasoning", "")).strip()
|
|
2801
|
-
|
|
2824
|
+
next_action = str(data.get("next_action", "")).strip()
|
|
2825
|
+
if (
|
|
2826
|
+
not assessment_reasoning
|
|
2827
|
+
and not plan_reasoning
|
|
2828
|
+
and not next_action
|
|
2829
|
+
):
|
|
2802
2830
|
continue
|
|
2803
2831
|
pending_text = pending_text_by_namespace.get(ns_key, "")
|
|
2804
2832
|
if pending_text:
|
|
@@ -2814,7 +2842,7 @@ async def execute_task_textual(
|
|
|
2814
2842
|
pa_raw = data.get("plan_action", "")
|
|
2815
2843
|
plan_action = pa_raw if pa_raw in ("keep", "new") else ""
|
|
2816
2844
|
plan_widget = CognitionReasonMessage(
|
|
2817
|
-
next_action=
|
|
2845
|
+
next_action=next_action,
|
|
2818
2846
|
status=str(data.get("status", "")),
|
|
2819
2847
|
iteration=int(data.get("iteration", 0)),
|
|
2820
2848
|
plan_action=str(plan_action),
|
|
@@ -1303,6 +1303,10 @@ class CognitionStepMessage(Vertical):
|
|
|
1303
1303
|
self._last_tool_call_count: int = 0
|
|
1304
1304
|
self._last_summary: str = ""
|
|
1305
1305
|
self._input_tokens: int = 0
|
|
1306
|
+
# IG-504: Retry tracking for running status display
|
|
1307
|
+
self._retry_attempt: int = 0
|
|
1308
|
+
self._max_retry_attempts: int = 0
|
|
1309
|
+
self._retry_error_type: str | None = None
|
|
1306
1310
|
self._output_tokens: int = 0
|
|
1307
1311
|
self._interrupt_message: str | None = None
|
|
1308
1312
|
self._deferred_interrupted: str | None = None
|
|
@@ -2856,14 +2860,53 @@ class CognitionStepMessage(Vertical):
|
|
|
2856
2860
|
self._refresh_tools_display()
|
|
2857
2861
|
|
|
2858
2862
|
def _sync_running_status_line(self) -> None:
|
|
2859
|
-
"""Refresh status text when tool stats change without repainting tool rows.
|
|
2863
|
+
"""Refresh status text when tool stats change without repainting tool rows.
|
|
2864
|
+
|
|
2865
|
+
This method is called when tool calls arrive during a running step,
|
|
2866
|
+
so it updates the status line immediately (without visibility check)
|
|
2867
|
+
to show the tool count in real-time.
|
|
2868
|
+
"""
|
|
2860
2869
|
if self._status == "running":
|
|
2861
|
-
self.
|
|
2870
|
+
self._sync_running_status_text()
|
|
2862
2871
|
elif self._status == "queued":
|
|
2863
2872
|
self._refresh_queued_display()
|
|
2864
2873
|
elif self._status == "pending":
|
|
2865
2874
|
self._refresh_pending_display()
|
|
2866
2875
|
|
|
2876
|
+
def _sync_running_status_text(self) -> None:
|
|
2877
|
+
"""Update running status line text immediately (no visibility check).
|
|
2878
|
+
|
|
2879
|
+
Called when tool stats change during running state to show tool count
|
|
2880
|
+
in real-time, bypassing the animation visibility check that would
|
|
2881
|
+
prevent updates for newly-mounted or off-screen widgets.
|
|
2882
|
+
"""
|
|
2883
|
+
if self._status != "running" or self._status_widget is None:
|
|
2884
|
+
return
|
|
2885
|
+
frames = get_glyphs().spinner_frames
|
|
2886
|
+
frame = frames[self._spinner_position]
|
|
2887
|
+
elapsed = ""
|
|
2888
|
+
if self._start_time is not None:
|
|
2889
|
+
elapsed_secs = int(time() - self._start_time)
|
|
2890
|
+
elapsed = f" ({format_duration(float(elapsed_secs))})"
|
|
2891
|
+
try:
|
|
2892
|
+
colors = theme.get_theme_colors(self)
|
|
2893
|
+
except Exception: # noqa: BLE001
|
|
2894
|
+
colors = theme.DARK_COLORS
|
|
2895
|
+
gutter = f"{get_glyphs().output_prefix} "
|
|
2896
|
+
stats_suffix = self._stats_title_suffix()
|
|
2897
|
+
token_suffix = self._token_budget_suffix()
|
|
2898
|
+
# IG-504: Show retry count in running status when retries are happening
|
|
2899
|
+
retry_suffix = ""
|
|
2900
|
+
if self._retry_attempt > 0 and self._max_retry_attempts > 0:
|
|
2901
|
+
retry_suffix = f" ({self._retry_attempt}/{self._max_retry_attempts} attempts)"
|
|
2902
|
+
head = f"{gutter}{frame} Running{retry_suffix}...{elapsed}"
|
|
2903
|
+
tail = f"{stats_suffix}{token_suffix}"
|
|
2904
|
+
clear_widget_text_selection(self._status_widget)
|
|
2905
|
+
parts: list[object] = [Content.styled(head, colors.warning)]
|
|
2906
|
+
if tail:
|
|
2907
|
+
parts.append(Content.styled(tail, colors.cognition))
|
|
2908
|
+
self._status_widget.update(Content.assemble(*parts))
|
|
2909
|
+
|
|
2867
2910
|
def _refresh_pending_display(self) -> None:
|
|
2868
2911
|
"""Show waiting state for planned steps that are not executing yet."""
|
|
2869
2912
|
if self._status != "pending" or self._status_widget is None:
|
|
@@ -2918,7 +2961,9 @@ class CognitionStepMessage(Vertical):
|
|
|
2918
2961
|
self._status_widget.remove_class("pending")
|
|
2919
2962
|
self._status_widget.remove_class("queued")
|
|
2920
2963
|
self._status_widget.display = True
|
|
2921
|
-
|
|
2964
|
+
# Immediate status line update (bypasses visibility check) so tool count
|
|
2965
|
+
# appears in real-time when tools arrive before the animation timer fires.
|
|
2966
|
+
self._sync_running_status_text()
|
|
2922
2967
|
self._refresh_task_activity_display()
|
|
2923
2968
|
self._animation_timer = self.set_interval(
|
|
2924
2969
|
_RUNNING_SPINNER_INTERVAL_SECONDS,
|
|
@@ -2930,29 +2975,38 @@ class CognitionStepMessage(Vertical):
|
|
|
2930
2975
|
self._animation_timer.stop()
|
|
2931
2976
|
self._animation_timer = None
|
|
2932
2977
|
|
|
2978
|
+
def set_retry_status(self, attempt: int, max_attempts: int, error_type: str) -> None:
|
|
2979
|
+
"""IG-504: Update retry status for running animation display.
|
|
2980
|
+
|
|
2981
|
+
Args:
|
|
2982
|
+
attempt: Current attempt number (1-indexed).
|
|
2983
|
+
max_attempts: Maximum attempts allowed.
|
|
2984
|
+
error_type: "timeout" or "rate_limit".
|
|
2985
|
+
"""
|
|
2986
|
+
self._retry_attempt = attempt
|
|
2987
|
+
self._max_retry_attempts = max_attempts
|
|
2988
|
+
self._retry_error_type = error_type
|
|
2989
|
+
# Trigger immediate refresh of running status (bypass visibility check)
|
|
2990
|
+
if self._status == "running":
|
|
2991
|
+
self._sync_running_status_text()
|
|
2992
|
+
|
|
2933
2993
|
def _update_running_animation(self) -> None:
|
|
2994
|
+
"""Animation timer callback: advance spinner and update status line.
|
|
2995
|
+
|
|
2996
|
+
The visibility check here is for efficiency - skipping expensive
|
|
2997
|
+
re-renders when the widget is off-screen. For immediate tool-stats
|
|
2998
|
+
updates (called when tool calls arrive), use `_sync_running_status_text`
|
|
2999
|
+
which bypasses this check.
|
|
3000
|
+
"""
|
|
2934
3001
|
if self._status != "running" or self._status_widget is None:
|
|
2935
3002
|
return
|
|
2936
3003
|
if not _is_widget_animation_visible(self):
|
|
2937
3004
|
return
|
|
3005
|
+
# Advance spinner position for animation effect
|
|
2938
3006
|
frames = get_glyphs().spinner_frames
|
|
2939
|
-
frame = frames[self._spinner_position]
|
|
2940
3007
|
self._spinner_position = (self._spinner_position + 1) % len(frames)
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
elapsed_secs = int(time() - self._start_time)
|
|
2944
|
-
elapsed = f" ({format_duration(float(elapsed_secs))})"
|
|
2945
|
-
colors = theme.get_theme_colors(self)
|
|
2946
|
-
gutter = f"{get_glyphs().output_prefix} "
|
|
2947
|
-
stats_suffix = self._stats_title_suffix()
|
|
2948
|
-
token_suffix = self._token_budget_suffix()
|
|
2949
|
-
head = f"{gutter}{frame} Running...{elapsed}"
|
|
2950
|
-
tail = f"{stats_suffix}{token_suffix}"
|
|
2951
|
-
clear_widget_text_selection(self._status_widget)
|
|
2952
|
-
parts: list[object] = [Content.styled(head, colors.warning)]
|
|
2953
|
-
if tail:
|
|
2954
|
-
parts.append(Content.styled(tail, colors.cognition))
|
|
2955
|
-
self._status_widget.update(Content.assemble(*parts))
|
|
3008
|
+
# Update status line with current stats
|
|
3009
|
+
self._sync_running_status_text()
|
|
2956
3010
|
if self._has_active_task_branch_animation():
|
|
2957
3011
|
self._refresh_task_activity_display()
|
|
2958
3012
|
|
|
@@ -3187,12 +3241,12 @@ class CognitionReasonMessage(Vertical):
|
|
|
3187
3241
|
"""Initialize a plan-reason card.
|
|
3188
3242
|
|
|
3189
3243
|
Args:
|
|
3190
|
-
next_action:
|
|
3244
|
+
next_action: User-facing plan-generate line (RFC-604 / IG-329).
|
|
3191
3245
|
status: Plan status (continue, replan, done).
|
|
3192
3246
|
iteration: Agent-loop iteration index.
|
|
3193
3247
|
plan_action: ``keep`` or ``new`` (execution strategy).
|
|
3194
|
-
assessment_reasoning: Phase-1 status justification.
|
|
3195
|
-
plan_reasoning:
|
|
3248
|
+
assessment_reasoning: Phase-1 status justification from plan-assess.
|
|
3249
|
+
plan_reasoning: Legacy phase-2 strategy text (usually empty after IG-329).
|
|
3196
3250
|
**kwargs: Passed to ``Vertical``.
|
|
3197
3251
|
"""
|
|
3198
3252
|
super().__init__(**kwargs)
|
|
@@ -3209,6 +3263,8 @@ class CognitionReasonMessage(Vertical):
|
|
|
3209
3263
|
parts.append(self._assessment_reasoning)
|
|
3210
3264
|
if self._plan_reasoning:
|
|
3211
3265
|
parts.append(self._plan_reasoning)
|
|
3266
|
+
elif self._next_action:
|
|
3267
|
+
parts.append(self._next_action)
|
|
3212
3268
|
if len(parts) == 2:
|
|
3213
3269
|
first = parts[0]
|
|
3214
3270
|
if not first.endswith((".", "!", "?")):
|
|
@@ -3217,7 +3273,7 @@ class CognitionReasonMessage(Vertical):
|
|
|
3217
3273
|
elif parts:
|
|
3218
3274
|
body = parts[0]
|
|
3219
3275
|
else:
|
|
3220
|
-
body =
|
|
3276
|
+
body = ""
|
|
3221
3277
|
if self._plan_action in ("keep", "new") and body:
|
|
3222
3278
|
body = f"{body} · {self._plan_action}"
|
|
3223
3279
|
return _assemble_card_header(self, "", body)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/parse/tool_call_resolution.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/presentation/duration_format.py
RENAMED
|
File without changes
|
|
File without changes
|
{soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/presentation/explore_task_display.py
RENAMED
|
File without changes
|
{soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/presentation/renderer_base.py
RENAMED
|
File without changes
|
{soothe_cli-0.6.13 → soothe_cli-0.6.15}/src/soothe_cli/runtime/presentation/renderer_protocol.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|