soothe-cli 0.3.7__tar.gz → 0.4.0__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.3.7 → soothe_cli-0.4.0}/PKG-INFO +3 -3
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/README.md +1 -1
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/pyproject.toml +1 -1
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/commands/thread_cmd.py +1 -1
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/execution/headless.py +2 -4
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/main.py +1 -1
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/renderer.py +23 -3
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/stream/context.py +4 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/stream/formatter.py +51 -22
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/stream/pipeline.py +238 -77
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/loop_commands.py +1 -1
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/display_policy.py +1 -1
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/event_processor.py +7 -21
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/message_processing.py +24 -43
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/presentation_engine.py +1 -1
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/slash_commands.py +6 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/subagent_routing.py +1 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/suppression_state.py +1 -1
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/tool_formatters/web.py +3 -3
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/tool_output_formatter.py +4 -28
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/app.py +3 -2
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/command_registry.py +6 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/daemon_session.py +1 -1
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/file_ops.py +8 -4
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/message_display_filter.py +1 -1
- soothe_cli-0.4.0/src/soothe_cli/tui/preview_limits.py +42 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/sessions.py +3 -3
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/textual_adapter.py +49 -28
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/tool_display.py +50 -49
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/approval.py +16 -14
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/autopilot_dashboard.py +14 -5
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/clipboard.py +3 -4
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/diff.py +3 -2
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/messages.py +65 -60
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/tool_widgets.py +18 -16
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/.gitignore +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/__init__.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/__init__.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/commands/__init__.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/commands/autopilot_cmd.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/commands/config_cmd.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/commands/run_cmd.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/commands/status_cmd.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/commands/subagent_names.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/execution/__init__.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/execution/daemon.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/execution/launcher.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/stream/__init__.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/stream/display_line.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/cli/utils.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/config/__init__.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/config/cli_config.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/plan/__init__.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/plan/rich_tree.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/__init__.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/command_router.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/config_loader.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/essential_events.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/processor_state.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/renderer_protocol.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/rendering.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/tool_call_resolution.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/tool_card_payload.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/tool_formatters/__init__.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/tool_formatters/base.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/tool_formatters/execution.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/tool_formatters/fallback.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/tool_formatters/file_ops.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/tool_formatters/goal_formatter.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/tool_formatters/media.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/tool_formatters/structured.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/tool_message_format.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/shared/tui_trace_log.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/__init__.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/_ask_user_types.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/_cli_context.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/_env_vars.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/_session_stats.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/_version.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/app.tcss +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/config.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/formatting.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/hooks.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/input.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/media_utils.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/model_config.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/output.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/project_utils.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/skills/__init__.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/skills/invocation.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/skills/load.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/theme.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/unicode_security.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/update_check.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/__init__.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/_links.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/ask_user.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/autocomplete.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/autopilot_screen.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/chat_input.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/editor.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/history.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/loading.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/loop_selector.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/mcp_viewer.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/message_store.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/model_selector.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/notification_settings.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/status.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/theme_selector.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/thread_selector.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/tool_renderers.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/tools.py +0 -0
- {soothe_cli-0.3.7 → soothe_cli-0.4.0}/src/soothe_cli/tui/widgets/welcome.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: soothe-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Soothe CLI client - communicates with daemon via WebSocket
|
|
5
5
|
Project-URL: Homepage, https://github.com/OpenSoothe/soothe
|
|
6
6
|
Project-URL: Documentation, https://soothe.readthedocs.io
|
|
@@ -21,7 +21,7 @@ Requires-Python: <3.15,>=3.11
|
|
|
21
21
|
Requires-Dist: python-dotenv<2.0.0,>=1.0.0
|
|
22
22
|
Requires-Dist: pyyaml<7.0.0,>=6.0.0
|
|
23
23
|
Requires-Dist: rich>=13.0.0
|
|
24
|
-
Requires-Dist: soothe-sdk<1.0.0,>=0.
|
|
24
|
+
Requires-Dist: soothe-sdk<1.0.0,>=0.4.0
|
|
25
25
|
Requires-Dist: textual>=0.40.0
|
|
26
26
|
Requires-Dist: typer<1.0.0,>=0.9.0
|
|
27
27
|
Requires-Dist: websockets>=12.0
|
|
@@ -96,5 +96,5 @@ tui:
|
|
|
96
96
|
|
|
97
97
|
## Related Packages
|
|
98
98
|
|
|
99
|
-
- **
|
|
99
|
+
- **soothed**: Server package (agent runtime)
|
|
100
100
|
- **soothe-sdk**: Shared SDK (WebSocket client, types)
|
|
@@ -23,7 +23,7 @@ classifiers = [
|
|
|
23
23
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
24
24
|
]
|
|
25
25
|
dependencies = [
|
|
26
|
-
"soothe-sdk>=0.
|
|
26
|
+
"soothe-sdk>=0.4.0,<1.0.0", # WebSocket client, protocol, types
|
|
27
27
|
"typer>=0.9.0,<1.0.0", # CLI framework
|
|
28
28
|
"textual>=0.40.0", # TUI framework
|
|
29
29
|
"rich>=13.0.0", # Console output
|
|
@@ -31,7 +31,7 @@ def _require_daemon(ws_url: str) -> None:
|
|
|
31
31
|
live = asyncio.run(_check_daemon(ws_url))
|
|
32
32
|
if not live:
|
|
33
33
|
typer.echo(
|
|
34
|
-
"Error: Daemon not running. Start with '
|
|
34
|
+
"Error: Daemon not running. Start with 'soothed start'.",
|
|
35
35
|
err=True,
|
|
36
36
|
)
|
|
37
37
|
sys.exit(1)
|
|
@@ -32,7 +32,7 @@ def run_headless(
|
|
|
32
32
|
Connects to running daemon via WebSocket if available to avoid RocksDB lock conflicts.
|
|
33
33
|
Auto-starts daemon if not running (RFC-0013 daemon lifecycle).
|
|
34
34
|
|
|
35
|
-
Note (RFC-0013): Daemon persists after request completion. Use '
|
|
35
|
+
Note (RFC-0013): Daemon persists after request completion. Use 'soothed stop'
|
|
36
36
|
to explicitly shutdown the daemon.
|
|
37
37
|
"""
|
|
38
38
|
from soothe_cli.cli.execution.daemon import run_headless_via_daemon
|
|
@@ -91,9 +91,7 @@ def run_headless(
|
|
|
91
91
|
|
|
92
92
|
# Handle daemon fallback (unresponsive daemon)
|
|
93
93
|
if daemon_exit_code == _DAEMON_FALLBACK_EXIT_CODE:
|
|
94
|
-
typer.echo(
|
|
95
|
-
"Error: Daemon is unresponsive. Please restart with 'soothe-daemon restart'", err=True
|
|
96
|
-
)
|
|
94
|
+
typer.echo("Error: Daemon is unresponsive. Please restart with 'soothed restart'", err=True)
|
|
97
95
|
sys.exit(1)
|
|
98
96
|
|
|
99
97
|
sys.exit(daemon_exit_code)
|
|
@@ -87,7 +87,7 @@ def main(
|
|
|
87
87
|
|
|
88
88
|
Run without arguments for interactive TUI mode, or provide a prompt via --prompt/-p option.
|
|
89
89
|
|
|
90
|
-
Note: This is the CLI client. Use '
|
|
90
|
+
Note: This is the CLI client. Use 'soothed' command to manage the daemon server.
|
|
91
91
|
|
|
92
92
|
Examples:
|
|
93
93
|
soothe # Interactive TUI mode
|
|
@@ -12,8 +12,8 @@ import time
|
|
|
12
12
|
from dataclasses import dataclass, field
|
|
13
13
|
from typing import TYPE_CHECKING, Any
|
|
14
14
|
|
|
15
|
-
from soothe_sdk.
|
|
16
|
-
from soothe_sdk.
|
|
15
|
+
from soothe_sdk.core.verbosity import VerbosityTier
|
|
16
|
+
from soothe_sdk.utils import get_tool_pascal_name
|
|
17
17
|
|
|
18
18
|
from soothe_cli.cli.stream import DisplayLine, StreamDisplayPipeline
|
|
19
19
|
from soothe_cli.cli.utils import make_tool_block
|
|
@@ -111,6 +111,16 @@ class CliRenderer:
|
|
|
111
111
|
"""Shared presentation policy used with StreamDisplayPipeline and EventProcessor."""
|
|
112
112
|
return self._presentation
|
|
113
113
|
|
|
114
|
+
def _is_inside_step_context(self) -> bool:
|
|
115
|
+
"""Check if we're inside an active step (for indentation).
|
|
116
|
+
|
|
117
|
+
IG-257: Used to determine if tool calls/results should be indented as tree children.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
True if current_step_id is set in pipeline context.
|
|
121
|
+
"""
|
|
122
|
+
return self._pipeline._context.current_step_id is not None
|
|
123
|
+
|
|
114
124
|
def write_lines(self, lines: list[DisplayLine]) -> None:
|
|
115
125
|
"""Write display lines to stderr.
|
|
116
126
|
|
|
@@ -213,7 +223,7 @@ class CliRenderer:
|
|
|
213
223
|
|
|
214
224
|
self._stderr_begin_icon_block()
|
|
215
225
|
|
|
216
|
-
display_name =
|
|
226
|
+
display_name = get_tool_pascal_name(name)
|
|
217
227
|
|
|
218
228
|
# Pass args directly, including any _raw fallback
|
|
219
229
|
args_str = format_tool_call_args(name, {"args": args, "_raw": args.get("_raw", "")})
|
|
@@ -221,6 +231,11 @@ class CliRenderer:
|
|
|
221
231
|
# Use display helper for consistency with TUI (RFC-0020 Principle 5)
|
|
222
232
|
tool_block = make_tool_block(display_name, args_str, status="running")
|
|
223
233
|
|
|
234
|
+
# IG-257: Add indentation when inside step context
|
|
235
|
+
# Unicode U+2514 "└─" (Box Drawings Light Up and Right) for tree branch
|
|
236
|
+
if self._is_inside_step_context():
|
|
237
|
+
tool_block = f" └─ {tool_block}"
|
|
238
|
+
|
|
224
239
|
# Track start time for duration display (RFC-0020)
|
|
225
240
|
if tool_call_id:
|
|
226
241
|
self._state.tool_call_start_times[tool_call_id] = time.time()
|
|
@@ -272,6 +287,11 @@ class CliRenderer:
|
|
|
272
287
|
if duration_ms > 0:
|
|
273
288
|
result_line += f" ({duration_ms}ms)"
|
|
274
289
|
|
|
290
|
+
# IG-257: Add indentation when inside step context
|
|
291
|
+
# Unicode U+2514 "└─" (Box Drawings Light Up and Right) for tree branch
|
|
292
|
+
if self._is_inside_step_context():
|
|
293
|
+
result_line = f" └─ {result_line}"
|
|
294
|
+
|
|
275
295
|
sys.stderr.write(result_line + "\n")
|
|
276
296
|
sys.stderr.flush()
|
|
277
297
|
|
|
@@ -62,6 +62,8 @@ class PipelineContext:
|
|
|
62
62
|
# Subagent tracking
|
|
63
63
|
subagent_name: str | None = None
|
|
64
64
|
subagent_milestones: list[str] = field(default_factory=list)
|
|
65
|
+
subagent_completion_shown: bool = False # IG-255: Track if completion already displayed
|
|
66
|
+
subagent_result_preview: str = "" # IG-255: Cache result preview for deduplication
|
|
65
67
|
|
|
66
68
|
def reset_goal(self) -> None:
|
|
67
69
|
"""Reset goal-related state."""
|
|
@@ -84,6 +86,8 @@ class PipelineContext:
|
|
|
84
86
|
self.parallel_header_emitted = False
|
|
85
87
|
self.subagent_name = None
|
|
86
88
|
self.subagent_milestones.clear()
|
|
89
|
+
self.subagent_completion_shown = False # IG-255: Reset completion flag
|
|
90
|
+
self.subagent_result_preview = "" # IG-255: Reset result preview
|
|
87
91
|
# Don't clear _active_step_ids here - it's cleared when steps complete
|
|
88
92
|
|
|
89
93
|
def complete_step(self, step_id: str) -> None:
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from soothe_sdk.verbosity import VerbosityTier
|
|
5
|
+
from soothe_sdk.core.verbosity import VerbosityTier
|
|
6
|
+
from soothe_sdk.utils import get_tool_pascal_name
|
|
6
7
|
|
|
7
8
|
from soothe_cli.cli.stream.display_line import DisplayLine, indent_for_level
|
|
8
9
|
|
|
@@ -143,24 +144,33 @@ def format_tool_call(
|
|
|
143
144
|
namespace: tuple[str, ...] = (),
|
|
144
145
|
verbosity_tier: VerbosityTier = VerbosityTier.NORMAL,
|
|
145
146
|
) -> DisplayLine:
|
|
146
|
-
"""Format a tool call line.
|
|
147
|
+
"""Format a tool/subagent call line.
|
|
148
|
+
|
|
149
|
+
IG-256: Restored uniform tool display - no subagent differentiation.
|
|
150
|
+
All tools/subagents use same wrench emoji and gear icon.
|
|
147
151
|
|
|
148
152
|
Args:
|
|
149
|
-
name: Tool name.
|
|
150
|
-
args_summary: Truncated args.
|
|
151
|
-
running: Whether tool is
|
|
153
|
+
name: Tool or subagent name.
|
|
154
|
+
args_summary: Truncated args or query preview.
|
|
155
|
+
running: Whether tool/subagent is running.
|
|
152
156
|
namespace: Event namespace.
|
|
153
157
|
verbosity_tier: Current verbosity tier.
|
|
154
158
|
|
|
155
159
|
Returns:
|
|
156
|
-
DisplayLine for tool call.
|
|
160
|
+
DisplayLine for tool/subagent call with uniform wrench icon.
|
|
157
161
|
"""
|
|
158
|
-
#
|
|
159
|
-
|
|
162
|
+
# Transform to PascalCase for display
|
|
163
|
+
display_name = get_tool_pascal_name(name)
|
|
164
|
+
|
|
165
|
+
# IG-256: No differentiation - use wrench for all tools/subagents
|
|
166
|
+
icon_emoji = "🔧"
|
|
167
|
+
icon_char = "⚙"
|
|
168
|
+
|
|
169
|
+
content = f"{icon_emoji} {display_name}({args_summary})"
|
|
160
170
|
return DisplayLine(
|
|
161
171
|
level=2,
|
|
162
172
|
content=content,
|
|
163
|
-
icon=
|
|
173
|
+
icon=icon_char,
|
|
164
174
|
indent=indent_for_level(2),
|
|
165
175
|
status="running" if running else None,
|
|
166
176
|
source_prefix=_derive_source_prefix(namespace, verbosity_tier),
|
|
@@ -206,17 +216,19 @@ def format_subagent_milestone(
|
|
|
206
216
|
namespace: tuple[str, ...] = (),
|
|
207
217
|
verbosity_tier: VerbosityTier = VerbosityTier.NORMAL,
|
|
208
218
|
) -> DisplayLine:
|
|
209
|
-
"""Format a subagent milestone line.
|
|
219
|
+
"""Format a subagent milestone line showing progress.
|
|
220
|
+
|
|
221
|
+
IG-256: Restored detective emoji for subagent milestones.
|
|
210
222
|
|
|
211
223
|
Args:
|
|
212
|
-
brief: Milestone description.
|
|
224
|
+
brief: Milestone description (e.g., "Step 3: click on login").
|
|
213
225
|
namespace: Event namespace.
|
|
214
226
|
verbosity_tier: Current verbosity tier.
|
|
215
227
|
|
|
216
228
|
Returns:
|
|
217
|
-
DisplayLine for milestone.
|
|
229
|
+
DisplayLine for milestone with detective emoji.
|
|
218
230
|
"""
|
|
219
|
-
#
|
|
231
|
+
# IG-256: Use detective emoji for milestones (restored from IG-255)
|
|
220
232
|
content = f"🕵🏻♂️ {brief}"
|
|
221
233
|
return DisplayLine(
|
|
222
234
|
level=3,
|
|
@@ -230,24 +242,33 @@ def format_subagent_milestone(
|
|
|
230
242
|
def format_subagent_done(
|
|
231
243
|
summary: str,
|
|
232
244
|
duration_s: float,
|
|
245
|
+
result_preview: str = "",
|
|
233
246
|
*,
|
|
234
247
|
namespace: tuple[str, ...] = (),
|
|
235
248
|
verbosity_tier: VerbosityTier = VerbosityTier.NORMAL,
|
|
236
249
|
) -> DisplayLine:
|
|
237
|
-
"""Format a subagent completion line.
|
|
250
|
+
"""Format a subagent completion line with metrics.
|
|
251
|
+
|
|
252
|
+
IG-256: Restored verbose format with triple success markers and separate result display.
|
|
253
|
+
Result preview parameter is ignored - results show via separate tool events.
|
|
238
254
|
|
|
239
255
|
Args:
|
|
240
|
-
summary: Completion summary.
|
|
256
|
+
summary: Completion summary with subagent-specific metrics (e.g., "success", "$1.23").
|
|
241
257
|
duration_s: Duration in seconds.
|
|
258
|
+
result_preview: Ignored (kept for backward compatibility).
|
|
242
259
|
namespace: Event namespace.
|
|
243
260
|
verbosity_tier: Current verbosity tier.
|
|
244
261
|
|
|
245
262
|
Returns:
|
|
246
|
-
DisplayLine for subagent done.
|
|
263
|
+
DisplayLine for subagent done with verbose triple markers.
|
|
247
264
|
"""
|
|
248
265
|
duration_ms = int(duration_s * 1000)
|
|
249
|
-
|
|
250
|
-
|
|
266
|
+
|
|
267
|
+
# IG-256: Verbose format restored - triple success markers, result shows separately
|
|
268
|
+
# Format: "✓ ✅ ✓ {summary}"
|
|
269
|
+
# result_preview is ignored - let result show via separate tool execution events
|
|
270
|
+
content = f"✓ ✅ ✓ {summary}"
|
|
271
|
+
|
|
251
272
|
return DisplayLine(
|
|
252
273
|
level=3,
|
|
253
274
|
content=content,
|
|
@@ -269,8 +290,14 @@ def format_plan_phase_reasoning(
|
|
|
269
290
|
|
|
270
291
|
IG-225: Uses level=2 (flat, no indent) for prominent visibility alongside step headers.
|
|
271
292
|
Uses solid bullet ● (matching goal) to indicate reasoning phase is active.
|
|
293
|
+
|
|
294
|
+
IG-257: When label is empty, shows text without prefix (just emoji + text).
|
|
272
295
|
"""
|
|
273
|
-
|
|
296
|
+
# IG-257: Handle empty label (no prefix)
|
|
297
|
+
if label:
|
|
298
|
+
content = f"💭 {label}: {text}"
|
|
299
|
+
else:
|
|
300
|
+
content = f"💭 {text}"
|
|
274
301
|
return DisplayLine(
|
|
275
302
|
level=2,
|
|
276
303
|
content=content,
|
|
@@ -366,6 +393,8 @@ def format_step_done(
|
|
|
366
393
|
IG-159/IG-182: Shows brief "Done"/"Failed" with tree connector as child of step header.
|
|
367
394
|
No description repeat - user already saw it in the step header above.
|
|
368
395
|
|
|
396
|
+
IG-257: Uses Unicode tree branch "└─" (U+2514) for cleaner visual tree.
|
|
397
|
+
|
|
369
398
|
Args:
|
|
370
399
|
duration_s: Duration in seconds.
|
|
371
400
|
tool_call_count: Number of tool calls made during step execution.
|
|
@@ -387,7 +416,7 @@ def format_step_done(
|
|
|
387
416
|
DisplayLine(
|
|
388
417
|
level=3, # Child node of step header (level 2)
|
|
389
418
|
content=content,
|
|
390
|
-
icon="
|
|
419
|
+
icon="└─", # IG-257: Unicode tree branch (U+2514)
|
|
391
420
|
indent=indent_for_level(3),
|
|
392
421
|
duration_ms=duration_ms,
|
|
393
422
|
source_prefix=_derive_source_prefix(namespace, verbosity_tier),
|
|
@@ -399,7 +428,7 @@ def format_step_done(
|
|
|
399
428
|
DisplayLine(
|
|
400
429
|
level=3,
|
|
401
430
|
content=f"Failed{tool_info}",
|
|
402
|
-
icon="
|
|
431
|
+
icon="└─", # IG-257: Unicode tree branch (U+2514)
|
|
403
432
|
indent=indent_for_level(3),
|
|
404
433
|
duration_ms=duration_ms,
|
|
405
434
|
source_prefix=_derive_source_prefix(namespace, verbosity_tier),
|
|
@@ -412,7 +441,7 @@ def format_step_done(
|
|
|
412
441
|
DisplayLine(
|
|
413
442
|
level=4, # Error detail as child of failed result
|
|
414
443
|
content=f"Error: {error_msg}",
|
|
415
|
-
icon="
|
|
444
|
+
icon="└─", # IG-257: Unicode tree branch (U+2514)
|
|
416
445
|
indent=indent_for_level(4),
|
|
417
446
|
source_prefix=_derive_source_prefix(namespace, verbosity_tier),
|
|
418
447
|
)
|