soothe-cli 0.3.8__tar.gz → 0.4.1__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.8 → soothe_cli-0.4.1}/PKG-INFO +3 -3
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/README.md +1 -1
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/pyproject.toml +1 -1
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/commands/thread_cmd.py +1 -1
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/execution/headless.py +2 -4
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/main.py +1 -1
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/renderer.py +21 -1
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/stream/context.py +4 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/stream/formatter.py +64 -35
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/stream/pipeline.py +248 -80
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/loop_commands.py +1 -1
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/display_policy.py +1 -1
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/event_processor.py +7 -21
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/message_processing.py +35 -44
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/presentation_engine.py +1 -1
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/slash_commands.py +6 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/subagent_routing.py +1 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/suppression_state.py +1 -1
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/tool_formatters/__init__.py +2 -0
- soothe_cli-0.4.1/src/soothe_cli/shared/tool_formatters/subagent.py +122 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/tool_formatters/web.py +3 -3
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/tool_output_formatter.py +8 -28
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/app.py +3 -2
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/command_registry.py +6 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/daemon_session.py +1 -1
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/file_ops.py +8 -4
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/message_display_filter.py +1 -1
- soothe_cli-0.4.1/src/soothe_cli/tui/preview_limits.py +42 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/sessions.py +3 -3
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/textual_adapter.py +49 -28
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/tool_display.py +50 -49
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/approval.py +16 -14
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/autopilot_dashboard.py +14 -5
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/clipboard.py +3 -4
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/diff.py +3 -2
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/messages.py +65 -60
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/tool_widgets.py +18 -16
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/.gitignore +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/__init__.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/__init__.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/commands/__init__.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/commands/autopilot_cmd.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/commands/config_cmd.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/commands/run_cmd.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/commands/status_cmd.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/commands/subagent_names.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/execution/__init__.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/execution/daemon.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/execution/launcher.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/stream/__init__.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/stream/display_line.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/cli/utils.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/config/__init__.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/config/cli_config.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/plan/__init__.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/plan/rich_tree.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/__init__.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/command_router.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/config_loader.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/essential_events.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/processor_state.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/renderer_protocol.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/rendering.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/tool_call_resolution.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/tool_card_payload.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/tool_formatters/base.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/tool_formatters/execution.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/tool_formatters/fallback.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/tool_formatters/file_ops.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/tool_formatters/goal_formatter.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/tool_formatters/media.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/tool_formatters/structured.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/tool_message_format.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/shared/tui_trace_log.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/__init__.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/_ask_user_types.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/_cli_context.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/_env_vars.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/_session_stats.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/_version.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/app.tcss +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/config.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/formatting.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/hooks.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/input.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/media_utils.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/model_config.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/output.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/project_utils.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/skills/__init__.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/skills/invocation.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/skills/load.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/theme.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/unicode_security.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/update_check.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/__init__.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/_links.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/ask_user.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/autocomplete.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/autopilot_screen.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/chat_input.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/editor.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/history.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/loading.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/loop_selector.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/mcp_viewer.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/message_store.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/model_selector.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/notification_settings.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/status.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/theme_selector.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/thread_selector.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/tool_renderers.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/src/soothe_cli/tui/widgets/tools.py +0 -0
- {soothe_cli-0.3.8 → soothe_cli-0.4.1}/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.1
|
|
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.core.verbosity import VerbosityTier
|
|
15
16
|
from soothe_sdk.utils import get_tool_display_name
|
|
16
|
-
from soothe_sdk.verbosity import VerbosityTier
|
|
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
|
|
|
@@ -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_display_name
|
|
6
7
|
|
|
7
8
|
from soothe_cli.cli.stream.display_line import DisplayLine, indent_for_level
|
|
8
9
|
|
|
@@ -95,7 +96,7 @@ def format_goal_header(
|
|
|
95
96
|
DisplayLine for goal header.
|
|
96
97
|
"""
|
|
97
98
|
# Add inline symbol for goal marker
|
|
98
|
-
content = f"
|
|
99
|
+
content = f"{goal}"
|
|
99
100
|
return DisplayLine(
|
|
100
101
|
level=1,
|
|
101
102
|
content=content,
|
|
@@ -125,7 +126,7 @@ def format_step_header(
|
|
|
125
126
|
"""
|
|
126
127
|
suffix = " (parallel)" if parallel else ""
|
|
127
128
|
# Add inline symbol for step progression
|
|
128
|
-
content = f"
|
|
129
|
+
content = f"❇️ {description}{suffix}"
|
|
129
130
|
return DisplayLine(
|
|
130
131
|
level=2,
|
|
131
132
|
content=content,
|
|
@@ -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_display_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,
|
|
@@ -291,6 +318,9 @@ def format_reasoning(
|
|
|
291
318
|
IG-XXX: Shows technical reasoning with "Reasoning:" prefix for clarity.
|
|
292
319
|
Uses solid bullet ● (matching goal) to indicate reasoning is active phase.
|
|
293
320
|
|
|
321
|
+
IG-262: Uses level=2 (flat layout) for consistency with judgement lines.
|
|
322
|
+
Reasoning is a sibling to judgement, not a child.
|
|
323
|
+
|
|
294
324
|
Args:
|
|
295
325
|
reasoning: Internal technical analysis text.
|
|
296
326
|
namespace: Event namespace.
|
|
@@ -303,10 +333,10 @@ def format_reasoning(
|
|
|
303
333
|
content = f"💭 {reasoning}"
|
|
304
334
|
|
|
305
335
|
return DisplayLine(
|
|
306
|
-
level=
|
|
336
|
+
level=2, # IG-262: Use level 2 for flat layout (sibling to judgement, not child)
|
|
307
337
|
content=content,
|
|
308
338
|
icon="●", # Solid bullet matching goal icon (polish)
|
|
309
|
-
indent=indent_for_level(
|
|
339
|
+
indent=indent_for_level(2),
|
|
310
340
|
source_prefix=_derive_source_prefix(namespace, verbosity_tier),
|
|
311
341
|
)
|
|
312
342
|
|
|
@@ -323,11 +353,12 @@ def format_judgement(
|
|
|
323
353
|
|
|
324
354
|
IG-089: Shows meaningful judgement info without raw intermediate data.
|
|
325
355
|
IG-XXX: Prominent reasoning display with "Reason:" prefix for clarity.
|
|
356
|
+
IG-265: Removed [new]/[keep] badge from CLI display (kept in event data for logs).
|
|
326
357
|
|
|
327
358
|
Args:
|
|
328
359
|
judgement: Human-readable summary of the decision.
|
|
329
360
|
action: Action taken ("continue" or "complete").
|
|
330
|
-
plan_action:
|
|
361
|
+
plan_action: Ignored (kept for backward compatibility, appears in logs only).
|
|
331
362
|
namespace: Event namespace.
|
|
332
363
|
verbosity_tier: Current verbosity tier.
|
|
333
364
|
|
|
@@ -336,12 +367,8 @@ def format_judgement(
|
|
|
336
367
|
"""
|
|
337
368
|
action_icon = "○" if action == "continue" else "●" # Polish: ○ for continue, ● for complete
|
|
338
369
|
|
|
339
|
-
badge
|
|
340
|
-
|
|
341
|
-
badge = f"[{plan_action}] "
|
|
342
|
-
|
|
343
|
-
# Polish: Add "Reason:" prefix to make LLM reasoning prominent
|
|
344
|
-
content = f"🌀 {badge}{judgement}"
|
|
370
|
+
# IG-265: Remove badge from CLI display (plan_action kept in event data for logs)
|
|
371
|
+
content = f"🌟 {judgement}"
|
|
345
372
|
|
|
346
373
|
return DisplayLine(
|
|
347
374
|
level=2, # Use level 2 for more prominence (like step headers)
|
|
@@ -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.
|
|
@@ -382,12 +411,12 @@ def format_step_done(
|
|
|
382
411
|
|
|
383
412
|
# Success case: single line
|
|
384
413
|
if success:
|
|
385
|
-
content = f"Done{tool_info}"
|
|
414
|
+
content = f"✓ Done{tool_info}"
|
|
386
415
|
return [
|
|
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),
|
|
@@ -398,8 +427,8 @@ def format_step_done(
|
|
|
398
427
|
lines = [
|
|
399
428
|
DisplayLine(
|
|
400
429
|
level=3,
|
|
401
|
-
content=f"Failed{tool_info}",
|
|
402
|
-
icon="
|
|
430
|
+
content=f"✗ Failed{tool_info}",
|
|
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
|
)
|