soothe-cli 0.1.0__tar.gz → 0.2.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.1.0 → soothe_cli-0.2.0}/.gitignore +1 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/PKG-INFO +3 -3
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/pyproject.toml +3 -3
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/commands/autopilot_cmd.py +11 -11
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/commands/config_cmd.py +3 -3
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/commands/run_cmd.py +6 -5
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/commands/status_cmd.py +2 -2
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/commands/thread_cmd.py +2 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/execution/daemon.py +2 -2
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/renderer.py +2 -2
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/stream/display_line.py +8 -5
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/stream/formatter.py +51 -17
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/stream/pipeline.py +127 -32
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/config/cli_config.py +2 -2
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/__init__.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/config_loader.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/display_policy.py +3 -7
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/event_processor.py +5 -4
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/message_processing.py +4 -2
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/presentation_engine.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/processor_state.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/renderer_protocol.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/rendering.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/tool_formatters/fallback.py +2 -2
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/tool_formatters/structured.py +3 -3
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/tool_output_formatter.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/tui_trace_log.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/app.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/config.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/model_config.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/sessions.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/textual_adapter.py +39 -15
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/theme.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/tool_display.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/update_check.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/autopilot_dashboard.py +4 -4
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/autopilot_screen.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/chat_input.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/history.py +1 -1
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/messages.py +24 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/README.md +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/__init__.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/__init__.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/commands/__init__.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/commands/subagent_names.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/execution/__init__.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/execution/headless.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/execution/launcher.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/main.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/stream/__init__.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/stream/context.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/cli/utils.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/config/__init__.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/plan/__init__.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/plan/rich_tree.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/command_router.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/essential_events.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/slash_commands.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/subagent_routing.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/suppression_state.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/tool_formatters/__init__.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/tool_formatters/base.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/tool_formatters/execution.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/tool_formatters/file_ops.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/tool_formatters/goal_formatter.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/tool_formatters/media.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/shared/tool_formatters/web.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/__init__.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/_ask_user_types.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/_cli_context.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/_env_vars.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/_session_stats.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/_version.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/app.tcss +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/command_registry.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/daemon_session.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/file_ops.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/formatting.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/hooks.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/input.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/media_utils.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/output.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/project_utils.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/skills/__init__.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/skills/invocation.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/skills/load.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/unicode_security.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/__init__.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/_links.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/approval.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/ask_user.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/autocomplete.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/clipboard.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/diff.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/editor.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/loading.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/mcp_viewer.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/message_store.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/model_selector.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/notification_settings.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/status.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/theme_selector.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/thread_selector.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/tool_renderers.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/tool_widgets.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/tools.py +0 -0
- {soothe_cli-0.1.0 → soothe_cli-0.2.0}/src/soothe_cli/tui/widgets/welcome.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: soothe-cli
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Soothe CLI client - communicates with daemon via WebSocket
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Soothe CLI client - communicates with daemon via WebSocket (updated for SDK v0.4.0)
|
|
5
5
|
Project-URL: Homepage, https://github.com/caesar0301/soothe
|
|
6
6
|
Project-URL: Documentation, https://soothe.readthedocs.io
|
|
7
7
|
Project-URL: Repository, https://github.com/caesar0301/soothe
|
|
@@ -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
|
|
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "soothe-cli"
|
|
7
|
-
version = "0.
|
|
8
|
-
description = "Soothe CLI client - communicates with daemon via WebSocket"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Soothe CLI client - communicates with daemon via WebSocket (updated for SDK v0.4.0)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
11
11
|
requires-python = ">=3.11,<3.15"
|
|
@@ -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 (v0.4.0 breaking change)
|
|
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
|
|
@@ -9,7 +9,7 @@ from __future__ import annotations
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
|
|
11
11
|
import typer
|
|
12
|
-
from soothe_sdk.protocol import preview_first
|
|
12
|
+
from soothe_sdk.client.protocol import preview_first
|
|
13
13
|
|
|
14
14
|
app = typer.Typer(help="Autopilot mode — long-running autonomous agent control.")
|
|
15
15
|
|
|
@@ -55,7 +55,7 @@ def submit(
|
|
|
55
55
|
"""
|
|
56
56
|
from datetime import UTC, datetime
|
|
57
57
|
|
|
58
|
-
from soothe_sdk import SOOTHE_HOME
|
|
58
|
+
from soothe_sdk.client.config import SOOTHE_HOME
|
|
59
59
|
|
|
60
60
|
inbox_dir = SOOTHE_HOME / "autopilot" / "inbox"
|
|
61
61
|
inbox_dir.mkdir(parents=True, exist_ok=True)
|
|
@@ -72,7 +72,7 @@ def submit(
|
|
|
72
72
|
@app.command("status")
|
|
73
73
|
def status() -> None:
|
|
74
74
|
"""Show overall autopilot state."""
|
|
75
|
-
from soothe_sdk import SOOTHE_HOME
|
|
75
|
+
from soothe_sdk.client.config import SOOTHE_HOME
|
|
76
76
|
|
|
77
77
|
autopilot_dir = SOOTHE_HOME / "autopilot"
|
|
78
78
|
state_file = autopilot_dir / "status.json"
|
|
@@ -106,7 +106,7 @@ def list_goals(
|
|
|
106
106
|
status_filter: str = typer.Option("", "--status", "-s", help="Filter by status."),
|
|
107
107
|
) -> None:
|
|
108
108
|
"""List all goals."""
|
|
109
|
-
from soothe_sdk import SOOTHE_HOME
|
|
109
|
+
from soothe_sdk.client.config import SOOTHE_HOME
|
|
110
110
|
|
|
111
111
|
autopilot_dir = SOOTHE_HOME / "autopilot"
|
|
112
112
|
goals = _discover_goals(autopilot_dir)
|
|
@@ -130,7 +130,7 @@ def show_goal(
|
|
|
130
130
|
goal_id: str = typer.Argument(..., help="Goal ID to show details for."),
|
|
131
131
|
) -> None:
|
|
132
132
|
"""Show details for a specific goal."""
|
|
133
|
-
from soothe_sdk import SOOTHE_HOME
|
|
133
|
+
from soothe_sdk.client.config import SOOTHE_HOME
|
|
134
134
|
|
|
135
135
|
autopilot_dir = SOOTHE_HOME / "autopilot"
|
|
136
136
|
goals = _discover_goals(autopilot_dir)
|
|
@@ -160,7 +160,7 @@ def cancel_goal(
|
|
|
160
160
|
goal_id: str = typer.Argument(..., help="Goal ID to cancel."),
|
|
161
161
|
) -> None:
|
|
162
162
|
"""Cancel a goal (remove from inbox if pending)."""
|
|
163
|
-
from soothe_sdk import SOOTHE_HOME
|
|
163
|
+
from soothe_sdk.client.config import SOOTHE_HOME
|
|
164
164
|
|
|
165
165
|
inbox_dir = SOOTHE_HOME / "autopilot" / "inbox"
|
|
166
166
|
if not inbox_dir.exists():
|
|
@@ -190,7 +190,7 @@ def approve_goal(
|
|
|
190
190
|
"""Approve a MUST-confirmation goal."""
|
|
191
191
|
import json
|
|
192
192
|
|
|
193
|
-
from soothe_sdk import SOOTHE_HOME
|
|
193
|
+
from soothe_sdk.client.config import SOOTHE_HOME
|
|
194
194
|
|
|
195
195
|
confirmations_file = SOOTHE_HOME / "autopilot" / "pending_confirmations.json"
|
|
196
196
|
if not confirmations_file.exists():
|
|
@@ -223,7 +223,7 @@ def reject_goal(
|
|
|
223
223
|
"""Reject a proposed goal."""
|
|
224
224
|
import json
|
|
225
225
|
|
|
226
|
-
from soothe_sdk import SOOTHE_HOME
|
|
226
|
+
from soothe_sdk.client.config import SOOTHE_HOME
|
|
227
227
|
|
|
228
228
|
confirmations_file = SOOTHE_HOME / "autopilot" / "pending_confirmations.json"
|
|
229
229
|
if not confirmations_file.exists():
|
|
@@ -248,7 +248,7 @@ def reject_goal(
|
|
|
248
248
|
@app.command("wake")
|
|
249
249
|
def wake() -> None:
|
|
250
250
|
"""Exit dreaming mode — resume active execution."""
|
|
251
|
-
from soothe_sdk import SOOTHE_HOME
|
|
251
|
+
from soothe_sdk.client.config import SOOTHE_HOME
|
|
252
252
|
|
|
253
253
|
inbox_dir = SOOTHE_HOME / "autopilot" / "inbox"
|
|
254
254
|
inbox_dir.mkdir(parents=True, exist_ok=True)
|
|
@@ -261,7 +261,7 @@ def wake() -> None:
|
|
|
261
261
|
@app.command("dream")
|
|
262
262
|
def dream() -> None:
|
|
263
263
|
"""Force enter dreaming mode."""
|
|
264
|
-
from soothe_sdk import SOOTHE_HOME
|
|
264
|
+
from soothe_sdk.client.config import SOOTHE_HOME
|
|
265
265
|
|
|
266
266
|
inbox_dir = SOOTHE_HOME / "autopilot" / "inbox"
|
|
267
267
|
inbox_dir.mkdir(parents=True, exist_ok=True)
|
|
@@ -276,7 +276,7 @@ def view_inbox(
|
|
|
276
276
|
limit: int = typer.Option(10, "--limit", "-n", help="Max tasks to show."),
|
|
277
277
|
) -> None:
|
|
278
278
|
"""View pending inbox tasks."""
|
|
279
|
-
from soothe_sdk import SOOTHE_HOME
|
|
279
|
+
from soothe_sdk.client.config import SOOTHE_HOME
|
|
280
280
|
|
|
281
281
|
inbox_dir = SOOTHE_HOME / "autopilot" / "inbox"
|
|
282
282
|
if not inbox_dir.exists():
|
|
@@ -113,7 +113,7 @@ def config_show(
|
|
|
113
113
|
sys.exit(0)
|
|
114
114
|
except Exception as e:
|
|
115
115
|
logger.exception("Config command error")
|
|
116
|
-
from soothe_sdk import format_cli_error
|
|
116
|
+
from soothe_sdk.utils import format_cli_error
|
|
117
117
|
|
|
118
118
|
typer.echo(f"Error: {format_cli_error(e)}", err=True)
|
|
119
119
|
sys.exit(1)
|
|
@@ -137,7 +137,7 @@ def config_init(
|
|
|
137
137
|
from importlib.resources import as_file, files
|
|
138
138
|
from pathlib import Path
|
|
139
139
|
|
|
140
|
-
from soothe_sdk import SOOTHE_HOME
|
|
140
|
+
from soothe_sdk.client.config import SOOTHE_HOME
|
|
141
141
|
|
|
142
142
|
home = Path(SOOTHE_HOME).expanduser()
|
|
143
143
|
target = home / "config" / "config.yml"
|
|
@@ -209,7 +209,7 @@ def config_validate(
|
|
|
209
209
|
"""
|
|
210
210
|
from pathlib import Path
|
|
211
211
|
|
|
212
|
-
from soothe_sdk import SOOTHE_HOME
|
|
212
|
+
from soothe_sdk.client.config import SOOTHE_HOME
|
|
213
213
|
|
|
214
214
|
try:
|
|
215
215
|
cfg = load_config(config)
|
|
@@ -7,7 +7,8 @@ from pathlib import Path
|
|
|
7
7
|
from typing import Literal
|
|
8
8
|
|
|
9
9
|
import typer
|
|
10
|
-
from soothe_sdk import SOOTHE_HOME
|
|
10
|
+
from soothe_sdk.client.config import SOOTHE_HOME
|
|
11
|
+
from soothe_sdk.utils.logging import VERBOSITY_TO_LOG_LEVEL
|
|
11
12
|
|
|
12
13
|
from soothe_cli.cli.execution import run_headless, run_tui
|
|
13
14
|
from soothe_cli.shared import load_config, setup_logging
|
|
@@ -42,9 +43,9 @@ def run_impl(
|
|
|
42
43
|
try:
|
|
43
44
|
cfg = load_config(config)
|
|
44
45
|
if verbosity is not None:
|
|
45
|
-
|
|
46
|
-
cfg =
|
|
47
|
-
log_level = VERBOSITY_TO_LOG_LEVEL.get(cfg.
|
|
46
|
+
# CLIConfig is a dataclass, update verbosity directly
|
|
47
|
+
cfg.verbosity = verbosity
|
|
48
|
+
log_level = VERBOSITY_TO_LOG_LEVEL.get(cfg.verbosity, "INFO")
|
|
48
49
|
log_file = Path(SOOTHE_HOME) / "logs" / "soothe-cli.log"
|
|
49
50
|
setup_logging(log_level, log_file=log_file)
|
|
50
51
|
|
|
@@ -81,7 +82,7 @@ def run_impl(
|
|
|
81
82
|
sys.exit(0)
|
|
82
83
|
except Exception as e:
|
|
83
84
|
logger.exception("CLI run error")
|
|
84
|
-
from soothe_sdk import format_cli_error
|
|
85
|
+
from soothe_sdk.utils import format_cli_error
|
|
85
86
|
|
|
86
87
|
typer.echo(f"Error: {format_cli_error(e)}", err=True)
|
|
87
88
|
sys.exit(1)
|
|
@@ -80,7 +80,7 @@ def agent_list(
|
|
|
80
80
|
sys.exit(0)
|
|
81
81
|
except Exception as e:
|
|
82
82
|
logger.exception("Agent list error")
|
|
83
|
-
from soothe_sdk import format_cli_error
|
|
83
|
+
from soothe_sdk.utils import format_cli_error
|
|
84
84
|
|
|
85
85
|
typer.echo(f"Error: {format_cli_error(e)}", err=True)
|
|
86
86
|
sys.exit(1)
|
|
@@ -115,7 +115,7 @@ def agent_status(
|
|
|
115
115
|
typer.echo(f"\nTotal: {enabled_count}/{total_count} agents enabled")
|
|
116
116
|
except Exception as e:
|
|
117
117
|
logger.exception("Agent status error")
|
|
118
|
-
from soothe_sdk import format_cli_error
|
|
118
|
+
from soothe_sdk.utils import format_cli_error
|
|
119
119
|
|
|
120
120
|
typer.echo(f"Error: {format_cli_error(e)}", err=True)
|
|
121
121
|
sys.exit(1)
|
|
@@ -10,8 +10,9 @@ from pathlib import Path
|
|
|
10
10
|
from typing import Annotated, Any
|
|
11
11
|
|
|
12
12
|
import typer
|
|
13
|
-
from soothe_sdk import SOOTHE_HOME, VERBOSITY_TO_LOG_LEVEL
|
|
14
13
|
from soothe_sdk.client import WebSocketClient, is_daemon_live, websocket_url_from_config
|
|
14
|
+
from soothe_sdk.client.config import SOOTHE_HOME
|
|
15
|
+
from soothe_sdk.utils.logging import VERBOSITY_TO_LOG_LEVEL
|
|
15
16
|
|
|
16
17
|
from soothe_cli.shared import load_config
|
|
17
18
|
|
|
@@ -178,13 +178,13 @@ async def run_headless_via_daemon(
|
|
|
178
178
|
|
|
179
179
|
except (ConnectionError, OSError, TimeoutError) as e:
|
|
180
180
|
logger.exception("Daemon connection failed")
|
|
181
|
-
from soothe_sdk import format_cli_error
|
|
181
|
+
from soothe_sdk.utils import format_cli_error
|
|
182
182
|
|
|
183
183
|
typer.echo(f"Error: {format_cli_error(e, context='daemon connection')}", err=True)
|
|
184
184
|
return _DAEMON_FALLBACK_EXIT_CODE
|
|
185
185
|
except Exception as e:
|
|
186
186
|
logger.exception("Failed to run via daemon")
|
|
187
|
-
from soothe_sdk import format_cli_error
|
|
187
|
+
from soothe_sdk.utils import format_cli_error
|
|
188
188
|
|
|
189
189
|
typer.echo(f"Error: {format_cli_error(e)}", err=True)
|
|
190
190
|
return 1
|
|
@@ -12,7 +12,7 @@ import time
|
|
|
12
12
|
from dataclasses import dataclass, field
|
|
13
13
|
from typing import TYPE_CHECKING, Any
|
|
14
14
|
|
|
15
|
-
from soothe_sdk import get_tool_display_name
|
|
15
|
+
from soothe_sdk.utils import get_tool_display_name
|
|
16
16
|
from soothe_sdk.verbosity import VerbosityTier
|
|
17
17
|
|
|
18
18
|
from soothe_cli.cli.stream import DisplayLine, StreamDisplayPipeline
|
|
@@ -23,7 +23,7 @@ from soothe_cli.shared.presentation_engine import PresentationEngine
|
|
|
23
23
|
from soothe_cli.shared.suppression_state import SuppressionState
|
|
24
24
|
|
|
25
25
|
if TYPE_CHECKING:
|
|
26
|
-
from soothe_sdk import Plan
|
|
26
|
+
from soothe_sdk.client.schemas import Plan
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
@dataclass
|
|
@@ -66,18 +66,21 @@ class DisplayLine:
|
|
|
66
66
|
return "".join(parts)
|
|
67
67
|
|
|
68
68
|
|
|
69
|
-
def indent_for_level(
|
|
69
|
+
def indent_for_level(level: int) -> str:
|
|
70
70
|
"""Get indentation string for a display level.
|
|
71
71
|
|
|
72
|
-
Headless CLI uses
|
|
72
|
+
IG-182: Headless CLI uses flat layout for levels 1-2, but tree indentation
|
|
73
|
+
for level-3 child nodes (step results with "|__" connector).
|
|
73
74
|
|
|
74
75
|
Args:
|
|
75
|
-
|
|
76
|
+
level: Display level (1=goal, 2=step/tool, 3=result child).
|
|
76
77
|
|
|
77
78
|
Returns:
|
|
78
|
-
Indentation string
|
|
79
|
+
Indentation string: "" for level 1-2, " " for level 3 (tree child).
|
|
79
80
|
"""
|
|
80
|
-
|
|
81
|
+
if level >= 3: # noqa: PLR2004
|
|
82
|
+
return " " # 2-space indent for tree children (IG-182)
|
|
83
|
+
return "" # Flat layout for goal/step headers
|
|
81
84
|
|
|
82
85
|
|
|
83
86
|
__all__ = ["DisplayLine", "indent_for_level"]
|
|
@@ -280,7 +280,7 @@ def format_reasoning(
|
|
|
280
280
|
DisplayLine for reasoning.
|
|
281
281
|
"""
|
|
282
282
|
# Polish: Add "Reasoning:" prefix to make internal analysis visible
|
|
283
|
-
content = f"💭
|
|
283
|
+
content = f"💭 {reasoning}"
|
|
284
284
|
|
|
285
285
|
return DisplayLine(
|
|
286
286
|
level=3, # Use level 3 for less prominence (subordinate to next_action)
|
|
@@ -329,38 +329,72 @@ def format_judgement(
|
|
|
329
329
|
|
|
330
330
|
|
|
331
331
|
def format_step_done(
|
|
332
|
-
description: str,
|
|
333
332
|
duration_s: float,
|
|
334
333
|
*,
|
|
335
334
|
tool_call_count: int = 0,
|
|
335
|
+
success: bool = True,
|
|
336
|
+
error_msg: str | None = None,
|
|
336
337
|
namespace: tuple[str, ...] = (),
|
|
337
338
|
verbosity_tier: VerbosityTier = VerbosityTier.NORMAL,
|
|
338
|
-
) -> DisplayLine:
|
|
339
|
-
"""Format
|
|
339
|
+
) -> list[DisplayLine]:
|
|
340
|
+
"""Format step completion as level-3 child node (IG-182).
|
|
341
|
+
|
|
342
|
+
IG-159/IG-182: Shows brief "Done"/"Failed" with tree connector as child of step header.
|
|
343
|
+
No description repeat - user already saw it in the step header above.
|
|
340
344
|
|
|
341
345
|
Args:
|
|
342
|
-
description: Step description (same as header).
|
|
343
346
|
duration_s: Duration in seconds.
|
|
344
347
|
tool_call_count: Number of tool calls made during step execution.
|
|
348
|
+
success: Whether step succeeded.
|
|
349
|
+
error_msg: Error message if failed.
|
|
345
350
|
namespace: Event namespace.
|
|
346
351
|
verbosity_tier: Current verbosity tier.
|
|
347
352
|
|
|
348
353
|
Returns:
|
|
349
|
-
DisplayLine for step
|
|
354
|
+
List of DisplayLine objects for step result tree (1-2 lines).
|
|
350
355
|
"""
|
|
351
356
|
duration_ms = int(duration_s * 1000)
|
|
352
|
-
# Abbreviate description for cleaner display
|
|
353
|
-
abbreviated = abbreviate_text(description, max_length=50)
|
|
354
357
|
tool_info = f" [{tool_call_count} tools]" if tool_call_count > 0 else ""
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
content=
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
358
|
+
|
|
359
|
+
# Success case: single line
|
|
360
|
+
if success:
|
|
361
|
+
content = f"Done{tool_info}"
|
|
362
|
+
return [
|
|
363
|
+
DisplayLine(
|
|
364
|
+
level=3, # Child node of step header (level 2)
|
|
365
|
+
content=content,
|
|
366
|
+
icon="|__", # Tree connector (IG-159)
|
|
367
|
+
indent=indent_for_level(3),
|
|
368
|
+
duration_ms=duration_ms,
|
|
369
|
+
source_prefix=_derive_source_prefix(namespace, verbosity_tier),
|
|
370
|
+
)
|
|
371
|
+
]
|
|
372
|
+
|
|
373
|
+
# Error case: result line + optional error detail
|
|
374
|
+
lines = [
|
|
375
|
+
DisplayLine(
|
|
376
|
+
level=3,
|
|
377
|
+
content=f"Failed{tool_info}",
|
|
378
|
+
icon="|__",
|
|
379
|
+
indent=indent_for_level(3),
|
|
380
|
+
duration_ms=duration_ms,
|
|
381
|
+
source_prefix=_derive_source_prefix(namespace, verbosity_tier),
|
|
382
|
+
)
|
|
383
|
+
]
|
|
384
|
+
|
|
385
|
+
# Show error message on level-4 line if present
|
|
386
|
+
if error_msg:
|
|
387
|
+
lines.append(
|
|
388
|
+
DisplayLine(
|
|
389
|
+
level=4, # Error detail as child of failed result
|
|
390
|
+
content=f"Error: {error_msg}",
|
|
391
|
+
icon="|__",
|
|
392
|
+
indent=indent_for_level(4),
|
|
393
|
+
source_prefix=_derive_source_prefix(namespace, verbosity_tier),
|
|
394
|
+
)
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
return lines
|
|
364
398
|
|
|
365
399
|
|
|
366
400
|
def format_goal_done(
|
|
@@ -6,7 +6,7 @@ import logging
|
|
|
6
6
|
import time
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
|
-
from soothe_sdk.protocol import preview_first
|
|
9
|
+
from soothe_sdk.client.protocol import preview_first
|
|
10
10
|
from soothe_sdk.verbosity import VerbosityTier
|
|
11
11
|
|
|
12
12
|
from soothe_cli.cli.stream.context import PipelineContext
|
|
@@ -114,7 +114,7 @@ class StreamDisplayPipeline:
|
|
|
114
114
|
Returns:
|
|
115
115
|
VerbosityTier for the event.
|
|
116
116
|
"""
|
|
117
|
-
from soothe_sdk.
|
|
117
|
+
from soothe_sdk.ux import classify_event_to_tier, is_subagent_progress_event
|
|
118
118
|
|
|
119
119
|
# Goal events - NORMAL
|
|
120
120
|
if is_goal_start_event_type(event_type):
|
|
@@ -128,8 +128,16 @@ class StreamDisplayPipeline:
|
|
|
128
128
|
if event_type in GOAL_COMPLETE_EVENTS:
|
|
129
129
|
return VerbosityTier.QUIET
|
|
130
130
|
|
|
131
|
+
# Subagent capability events - DETAILED by default, NORMAL for important progress
|
|
132
|
+
# IG-192: Use SDK helper to identify important progress events (started/completed/judgement)
|
|
133
|
+
if event_type.startswith("soothe.capability."):
|
|
134
|
+
if is_subagent_progress_event(event_type):
|
|
135
|
+
return VerbosityTier.NORMAL
|
|
136
|
+
# Other capability events (internal steps) - DETAILED
|
|
137
|
+
return VerbosityTier.DETAILED
|
|
138
|
+
|
|
131
139
|
# soothe.* events: defer to SDK domain-based classification (RFC-0020)
|
|
132
|
-
# Step completion, tool events
|
|
140
|
+
# Step completion, tool events use domain defaults
|
|
133
141
|
if event_type.startswith("soothe."):
|
|
134
142
|
return classify_event_to_tier(event_type)
|
|
135
143
|
|
|
@@ -150,12 +158,36 @@ class StreamDisplayPipeline:
|
|
|
150
158
|
Returns:
|
|
151
159
|
List of DisplayLine objects.
|
|
152
160
|
"""
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
161
|
+
# Capability events (soothe.capability.<subagent>.<action>)
|
|
162
|
+
# IG-192: Handle new unified naming scheme for subagent events
|
|
163
|
+
if event_type.startswith("soothe.capability."):
|
|
164
|
+
parts = event_type.split(".")
|
|
165
|
+
if len(parts) >= 4: # noqa: PLR2004
|
|
166
|
+
# soothe.capability.<subagent>.<action>
|
|
167
|
+
subagent = parts[2]
|
|
168
|
+
action = parts[3]
|
|
169
|
+
|
|
170
|
+
# Started/dispatched events
|
|
171
|
+
if action in ("started", "dispatching"):
|
|
172
|
+
return self._on_subagent_dispatched(event, subagent)
|
|
173
|
+
|
|
174
|
+
# Judgement events (research)
|
|
175
|
+
if "judgement" in action:
|
|
176
|
+
return self._on_subagent_judgement(event)
|
|
177
|
+
|
|
178
|
+
# Step events (browser automation steps)
|
|
179
|
+
if "step" in action and "running" in action:
|
|
180
|
+
return self._on_capability_step(event, subagent)
|
|
181
|
+
|
|
182
|
+
# Completed events
|
|
183
|
+
if action == "completed":
|
|
184
|
+
return self._on_subagent_completed(event, subagent)
|
|
185
|
+
|
|
186
|
+
# Text/tool events (claude) - DETAILED level
|
|
187
|
+
if action in ("text", "tool") and "running" in event_type:
|
|
188
|
+
return self._on_capability_activity(event, subagent, action)
|
|
189
|
+
|
|
190
|
+
# Legacy subagent events (.subagent.* format)
|
|
159
191
|
if ".subagent." in event_type and ".dispatched" in event_type:
|
|
160
192
|
return self._on_subagent_dispatched(event)
|
|
161
193
|
|
|
@@ -168,6 +200,13 @@ class StreamDisplayPipeline:
|
|
|
168
200
|
if ".subagent." in event_type and ".completed" in event_type:
|
|
169
201
|
return self._on_subagent_completed(event)
|
|
170
202
|
|
|
203
|
+
# Goal/step events
|
|
204
|
+
if is_goal_start_event_type(event_type):
|
|
205
|
+
return self._on_goal_started(event)
|
|
206
|
+
|
|
207
|
+
if is_step_start_event_type(event_type):
|
|
208
|
+
return self._on_step_started(event)
|
|
209
|
+
|
|
171
210
|
if is_step_complete_event_type(event_type):
|
|
172
211
|
return self._on_step_completed(event)
|
|
173
212
|
|
|
@@ -244,24 +283,27 @@ class StreamDisplayPipeline:
|
|
|
244
283
|
)
|
|
245
284
|
]
|
|
246
285
|
|
|
247
|
-
def _on_subagent_dispatched(
|
|
286
|
+
def _on_subagent_dispatched(
|
|
287
|
+
self, event: dict[str, Any], subagent_name: str = ""
|
|
288
|
+
) -> list[DisplayLine]:
|
|
248
289
|
"""Handle subagent dispatched event.
|
|
249
290
|
|
|
250
291
|
Args:
|
|
251
292
|
event: Event dictionary.
|
|
293
|
+
subagent_name: Subagent name (extracted from event type).
|
|
252
294
|
|
|
253
295
|
Returns:
|
|
254
296
|
Display lines (none for dispatch, just tracking).
|
|
255
297
|
"""
|
|
256
|
-
# Extract name from event type: soothe.
|
|
298
|
+
# Extract name from event type: soothe.capability.<name>.started
|
|
257
299
|
event_type = event.get("type", "")
|
|
258
300
|
parts = event_type.split(".")
|
|
259
301
|
name = ""
|
|
260
|
-
# Pattern: soothe.
|
|
261
|
-
# Need at least 3 parts for valid
|
|
262
|
-
if len(parts) >= 3 and parts[1] == "
|
|
302
|
+
# Pattern: soothe.capability.<name>.started -> parts[0]=soothe, parts[1]=capability, parts[2]=name
|
|
303
|
+
# Need at least 3 parts for valid capability event type
|
|
304
|
+
if len(parts) >= 3 and parts[1] == "capability": # noqa: PLR2004
|
|
263
305
|
name = parts[2]
|
|
264
|
-
name = name or event.get("name", event.get("subagent_name", ""))
|
|
306
|
+
name = name or subagent_name or event.get("name", event.get("subagent_name", ""))
|
|
265
307
|
self._context.subagent_name = name
|
|
266
308
|
self._context.subagent_milestones.clear()
|
|
267
309
|
|
|
@@ -272,6 +314,7 @@ class StreamDisplayPipeline:
|
|
|
272
314
|
format_tool_call(
|
|
273
315
|
f"{name}_subagent",
|
|
274
316
|
args_summary,
|
|
317
|
+
running=True,
|
|
275
318
|
namespace=self._current_namespace,
|
|
276
319
|
verbosity_tier=self._verbosity_tier,
|
|
277
320
|
)
|
|
@@ -334,11 +377,14 @@ class StreamDisplayPipeline:
|
|
|
334
377
|
)
|
|
335
378
|
]
|
|
336
379
|
|
|
337
|
-
def _on_subagent_completed(
|
|
380
|
+
def _on_subagent_completed(
|
|
381
|
+
self, event: dict[str, Any], subagent_name: str = ""
|
|
382
|
+
) -> list[DisplayLine]:
|
|
338
383
|
"""Handle subagent completed event.
|
|
339
384
|
|
|
340
385
|
Args:
|
|
341
386
|
event: Event dictionary.
|
|
387
|
+
subagent_name: Subagent name (extracted from event type).
|
|
342
388
|
|
|
343
389
|
Returns:
|
|
344
390
|
Display lines for completion.
|
|
@@ -371,6 +417,57 @@ class StreamDisplayPipeline:
|
|
|
371
417
|
)
|
|
372
418
|
]
|
|
373
419
|
|
|
420
|
+
def _on_capability_step(self, event: dict[str, Any], subagent_name: str) -> list[DisplayLine]:
|
|
421
|
+
"""Handle capability step event (e.g., browser automation steps).
|
|
422
|
+
|
|
423
|
+
Args:
|
|
424
|
+
event: Event dictionary.
|
|
425
|
+
subagent_name: Subagent name (browser, etc.).
|
|
426
|
+
|
|
427
|
+
Returns:
|
|
428
|
+
Display lines for step milestone.
|
|
429
|
+
"""
|
|
430
|
+
# Extract step info from different event schemas
|
|
431
|
+
step = event.get("step", "")
|
|
432
|
+
url = event.get("url", "")
|
|
433
|
+
action = event.get("action", "")
|
|
434
|
+
title = event.get("title", "")
|
|
435
|
+
|
|
436
|
+
# Build brief description
|
|
437
|
+
if url:
|
|
438
|
+
brief = f"Step {step}: {action} on {url}"
|
|
439
|
+
elif action:
|
|
440
|
+
brief = f"Step {step}: {action}"
|
|
441
|
+
elif title:
|
|
442
|
+
brief = f"Step {step}: {title}"
|
|
443
|
+
else:
|
|
444
|
+
brief = f"Step {step}"
|
|
445
|
+
|
|
446
|
+
return [
|
|
447
|
+
format_subagent_milestone(
|
|
448
|
+
preview_first(brief, 60),
|
|
449
|
+
namespace=self._current_namespace,
|
|
450
|
+
verbosity_tier=self._verbosity_tier,
|
|
451
|
+
)
|
|
452
|
+
]
|
|
453
|
+
|
|
454
|
+
def _on_capability_activity(
|
|
455
|
+
self, event: dict[str, Any], subagent_name: str, action_type: str
|
|
456
|
+
) -> list[DisplayLine]:
|
|
457
|
+
"""Handle capability activity event (e.g., claude text/tool).
|
|
458
|
+
|
|
459
|
+
Args:
|
|
460
|
+
event: Event dictionary.
|
|
461
|
+
subagent_name: Subagent name (claude, etc.).
|
|
462
|
+
action_type: Activity type (text, tool).
|
|
463
|
+
|
|
464
|
+
Returns:
|
|
465
|
+
Display lines for activity milestone (empty for DETAILED events).
|
|
466
|
+
"""
|
|
467
|
+
# Claude text/tool events are DETAILED level - not shown at normal verbosity
|
|
468
|
+
# Just return empty list, classification already filters them
|
|
469
|
+
return []
|
|
470
|
+
|
|
374
471
|
def _on_step_completed(self, event: dict[str, Any]) -> list[DisplayLine]:
|
|
375
472
|
"""Handle step completed event.
|
|
376
473
|
|
|
@@ -390,13 +487,11 @@ class StreamDisplayPipeline:
|
|
|
390
487
|
if duration_s == 0 and self._context.step_start_time:
|
|
391
488
|
duration_s = time.time() - self._context.step_start_time
|
|
392
489
|
|
|
393
|
-
#
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
or "Completed action"
|
|
399
|
-
)
|
|
490
|
+
# Get success/error status (IG-182)
|
|
491
|
+
success = event.get("success", True)
|
|
492
|
+
error_msg = None
|
|
493
|
+
if not success:
|
|
494
|
+
error_msg = event.get("error", event.get("error_message", ""))
|
|
400
495
|
|
|
401
496
|
# Get tool call count from event
|
|
402
497
|
tool_call_count = event.get("tool_call_count", 0)
|
|
@@ -411,15 +506,15 @@ class StreamDisplayPipeline:
|
|
|
411
506
|
self._context.current_step_description = None
|
|
412
507
|
self._context.step_start_time = None
|
|
413
508
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
509
|
+
# IG-182: Return list directly (formatter returns list now)
|
|
510
|
+
return format_step_done(
|
|
511
|
+
duration_s,
|
|
512
|
+
tool_call_count=tool_call_count,
|
|
513
|
+
success=success,
|
|
514
|
+
error_msg=error_msg,
|
|
515
|
+
namespace=self._current_namespace,
|
|
516
|
+
verbosity_tier=self._verbosity_tier,
|
|
517
|
+
)
|
|
423
518
|
|
|
424
519
|
def _on_goal_completed(self, event: dict[str, Any]) -> list[DisplayLine]:
|
|
425
520
|
"""Handle goal completed event.
|
|
@@ -73,7 +73,7 @@ class CLIConfig:
|
|
|
73
73
|
Full config available via daemon RPC.
|
|
74
74
|
|
|
75
75
|
Args:
|
|
76
|
-
config_path: Path to config file. Defaults to ~/.soothe/config.yml.
|
|
76
|
+
config_path: Path to config file. Defaults to ~/.soothe/config/cli_config.yml.
|
|
77
77
|
|
|
78
78
|
Returns:
|
|
79
79
|
CLIConfig instance with minimal settings.
|
|
@@ -81,7 +81,7 @@ class CLIConfig:
|
|
|
81
81
|
import yaml
|
|
82
82
|
|
|
83
83
|
if config_path is None:
|
|
84
|
-
config_path = Path.home() / ".soothe" / "config.yml"
|
|
84
|
+
config_path = Path.home() / ".soothe" / "config" / "cli_config.yml"
|
|
85
85
|
|
|
86
86
|
if not config_path.exists():
|
|
87
87
|
return cls() # Use defaults
|