soothe-cli 0.1.0__py3-none-any.whl
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/__init__.py +5 -0
- soothe_cli/cli/__init__.py +1 -0
- soothe_cli/cli/commands/__init__.py +1 -0
- soothe_cli/cli/commands/autopilot_cmd.py +410 -0
- soothe_cli/cli/commands/config_cmd.py +277 -0
- soothe_cli/cli/commands/run_cmd.py +87 -0
- soothe_cli/cli/commands/status_cmd.py +121 -0
- soothe_cli/cli/commands/subagent_names.py +17 -0
- soothe_cli/cli/commands/thread_cmd.py +657 -0
- soothe_cli/cli/execution/__init__.py +6 -0
- soothe_cli/cli/execution/daemon.py +194 -0
- soothe_cli/cli/execution/headless.py +99 -0
- soothe_cli/cli/execution/launcher.py +31 -0
- soothe_cli/cli/main.py +509 -0
- soothe_cli/cli/renderer.py +444 -0
- soothe_cli/cli/stream/__init__.py +17 -0
- soothe_cli/cli/stream/context.py +138 -0
- soothe_cli/cli/stream/display_line.py +83 -0
- soothe_cli/cli/stream/formatter.py +412 -0
- soothe_cli/cli/stream/pipeline.py +521 -0
- soothe_cli/cli/utils.py +46 -0
- soothe_cli/config/__init__.py +5 -0
- soothe_cli/config/cli_config.py +155 -0
- soothe_cli/plan/__init__.py +5 -0
- soothe_cli/plan/rich_tree.py +54 -0
- soothe_cli/shared/__init__.py +107 -0
- soothe_cli/shared/command_router.py +246 -0
- soothe_cli/shared/config_loader.py +68 -0
- soothe_cli/shared/display_policy.py +413 -0
- soothe_cli/shared/essential_events.py +68 -0
- soothe_cli/shared/event_processor.py +823 -0
- soothe_cli/shared/message_processing.py +393 -0
- soothe_cli/shared/presentation_engine.py +173 -0
- soothe_cli/shared/processor_state.py +80 -0
- soothe_cli/shared/renderer_protocol.py +158 -0
- soothe_cli/shared/rendering.py +43 -0
- soothe_cli/shared/slash_commands.py +354 -0
- soothe_cli/shared/subagent_routing.py +63 -0
- soothe_cli/shared/suppression_state.py +188 -0
- soothe_cli/shared/tool_formatters/__init__.py +27 -0
- soothe_cli/shared/tool_formatters/base.py +109 -0
- soothe_cli/shared/tool_formatters/execution.py +297 -0
- soothe_cli/shared/tool_formatters/fallback.py +128 -0
- soothe_cli/shared/tool_formatters/file_ops.py +299 -0
- soothe_cli/shared/tool_formatters/goal_formatter.py +331 -0
- soothe_cli/shared/tool_formatters/media.py +291 -0
- soothe_cli/shared/tool_formatters/structured.py +202 -0
- soothe_cli/shared/tool_formatters/web.py +143 -0
- soothe_cli/shared/tool_output_formatter.py +227 -0
- soothe_cli/shared/tui_trace_log.py +40 -0
- soothe_cli/tui/__init__.py +5 -0
- soothe_cli/tui/_ask_user_types.py +50 -0
- soothe_cli/tui/_cli_context.py +27 -0
- soothe_cli/tui/_env_vars.py +56 -0
- soothe_cli/tui/_session_stats.py +114 -0
- soothe_cli/tui/_version.py +21 -0
- soothe_cli/tui/app.py +4992 -0
- soothe_cli/tui/app.tcss +302 -0
- soothe_cli/tui/command_registry.py +310 -0
- soothe_cli/tui/config.py +2381 -0
- soothe_cli/tui/daemon_session.py +233 -0
- soothe_cli/tui/file_ops.py +409 -0
- soothe_cli/tui/formatting.py +28 -0
- soothe_cli/tui/hooks.py +23 -0
- soothe_cli/tui/input.py +782 -0
- soothe_cli/tui/media_utils.py +471 -0
- soothe_cli/tui/model_config.py +518 -0
- soothe_cli/tui/output.py +69 -0
- soothe_cli/tui/project_utils.py +188 -0
- soothe_cli/tui/sessions.py +1248 -0
- soothe_cli/tui/skills/__init__.py +5 -0
- soothe_cli/tui/skills/invocation.py +74 -0
- soothe_cli/tui/skills/load.py +93 -0
- soothe_cli/tui/textual_adapter.py +1430 -0
- soothe_cli/tui/theme.py +838 -0
- soothe_cli/tui/tool_display.py +297 -0
- soothe_cli/tui/unicode_security.py +502 -0
- soothe_cli/tui/update_check.py +447 -0
- soothe_cli/tui/widgets/__init__.py +9 -0
- soothe_cli/tui/widgets/_links.py +63 -0
- soothe_cli/tui/widgets/approval.py +430 -0
- soothe_cli/tui/widgets/ask_user.py +392 -0
- soothe_cli/tui/widgets/autocomplete.py +666 -0
- soothe_cli/tui/widgets/autopilot_dashboard.py +308 -0
- soothe_cli/tui/widgets/autopilot_screen.py +64 -0
- soothe_cli/tui/widgets/chat_input.py +1834 -0
- soothe_cli/tui/widgets/clipboard.py +128 -0
- soothe_cli/tui/widgets/diff.py +240 -0
- soothe_cli/tui/widgets/editor.py +140 -0
- soothe_cli/tui/widgets/history.py +221 -0
- soothe_cli/tui/widgets/loading.py +194 -0
- soothe_cli/tui/widgets/mcp_viewer.py +352 -0
- soothe_cli/tui/widgets/message_store.py +693 -0
- soothe_cli/tui/widgets/messages.py +1720 -0
- soothe_cli/tui/widgets/model_selector.py +988 -0
- soothe_cli/tui/widgets/notification_settings.py +155 -0
- soothe_cli/tui/widgets/status.py +403 -0
- soothe_cli/tui/widgets/theme_selector.py +158 -0
- soothe_cli/tui/widgets/thread_selector.py +1865 -0
- soothe_cli/tui/widgets/tool_renderers.py +148 -0
- soothe_cli/tui/widgets/tool_widgets.py +254 -0
- soothe_cli/tui/widgets/tools.py +165 -0
- soothe_cli/tui/widgets/welcome.py +330 -0
- soothe_cli-0.1.0.dist-info/METADATA +100 -0
- soothe_cli-0.1.0.dist-info/RECORD +107 -0
- soothe_cli-0.1.0.dist-info/WHEEL +4 -0
- soothe_cli-0.1.0.dist-info/entry_points.txt +2 -0
soothe_cli/cli/main.py
ADDED
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
"""Main CLI entry point using Typer."""
|
|
2
|
+
|
|
3
|
+
# Load environment variables from .env file BEFORE any langchain imports
|
|
4
|
+
# This is required for LangSmith tracing to be activated at import time
|
|
5
|
+
from dotenv import load_dotenv
|
|
6
|
+
|
|
7
|
+
load_dotenv()
|
|
8
|
+
|
|
9
|
+
from importlib.metadata import version # noqa: E402
|
|
10
|
+
from typing import Annotated, Literal # noqa: E402
|
|
11
|
+
|
|
12
|
+
import typer # noqa: E402
|
|
13
|
+
|
|
14
|
+
app = typer.Typer(
|
|
15
|
+
name="soothe",
|
|
16
|
+
help="Intelligent AI assistant for complex tasks",
|
|
17
|
+
no_args_is_help=False,
|
|
18
|
+
add_completion=False,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def add_help_alias(nested_app: typer.Typer) -> None:
|
|
23
|
+
"""Add -h as an alias for --help to a nested Typer app.
|
|
24
|
+
|
|
25
|
+
This is a workaround for Typer not supporting -h for nested command groups.
|
|
26
|
+
Must be called AFTER creating the nested app but BEFORE adding commands.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
nested_app: The nested Typer app to add -h support to.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
# Add a callback that defines -h option
|
|
33
|
+
@nested_app.callback(invoke_without_command=True)
|
|
34
|
+
def help_callback(
|
|
35
|
+
ctx: typer.Context,
|
|
36
|
+
show_help: Annotated[ # noqa: FBT002
|
|
37
|
+
bool,
|
|
38
|
+
typer.Option("-h", "--help", is_flag=True, help="Show this message and exit."),
|
|
39
|
+
] = False,
|
|
40
|
+
) -> None:
|
|
41
|
+
# If -h/--help is passed, show help and exit before command parsing
|
|
42
|
+
if show_help:
|
|
43
|
+
typer.echo(ctx.get_help())
|
|
44
|
+
raise typer.Exit(code=0)
|
|
45
|
+
|
|
46
|
+
# If no subcommand and no help flag, show help by default
|
|
47
|
+
if ctx.invoked_subcommand is None:
|
|
48
|
+
typer.echo(ctx.get_help())
|
|
49
|
+
raise typer.Exit(code=0)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@app.callback(invoke_without_command=True)
|
|
53
|
+
def main(
|
|
54
|
+
ctx: typer.Context,
|
|
55
|
+
config: Annotated[
|
|
56
|
+
str | None,
|
|
57
|
+
typer.Option("--config", "-c", help="Path to configuration file."),
|
|
58
|
+
] = None,
|
|
59
|
+
prompt: Annotated[
|
|
60
|
+
str | None,
|
|
61
|
+
typer.Option(
|
|
62
|
+
"--prompt", "-p", help="Prompt to send as user message (headless single-shot mode)."
|
|
63
|
+
),
|
|
64
|
+
] = None,
|
|
65
|
+
no_tui: Annotated[ # noqa: FBT002
|
|
66
|
+
bool,
|
|
67
|
+
typer.Option("--no-tui", help="Disable TUI; run single prompt and exit."),
|
|
68
|
+
] = False,
|
|
69
|
+
output_format: Annotated[
|
|
70
|
+
str,
|
|
71
|
+
typer.Option("--format", "-f", help="Output format for headless mode: text or jsonl."),
|
|
72
|
+
] = "text",
|
|
73
|
+
verbosity: Annotated[
|
|
74
|
+
Literal["quiet", "minimal", "normal", "detailed", "debug"] | None,
|
|
75
|
+
typer.Option(
|
|
76
|
+
"--verbosity",
|
|
77
|
+
"-v",
|
|
78
|
+
help="Verbosity level: quiet, normal, detailed, debug. 'minimal' is accepted as an alias.",
|
|
79
|
+
),
|
|
80
|
+
] = None,
|
|
81
|
+
show_help: Annotated[ # noqa: FBT002
|
|
82
|
+
bool,
|
|
83
|
+
typer.Option("--help", "-h", is_flag=True, help="Show this message and exit."),
|
|
84
|
+
] = False,
|
|
85
|
+
show_version: Annotated[ # noqa: FBT002
|
|
86
|
+
bool,
|
|
87
|
+
typer.Option("--version", is_flag=True, help="Show version and exit."),
|
|
88
|
+
] = False,
|
|
89
|
+
) -> None:
|
|
90
|
+
"""Soothe CLI - Intelligent AI assistant client.
|
|
91
|
+
|
|
92
|
+
Run without arguments for interactive TUI mode, or provide a prompt via --prompt/-p option.
|
|
93
|
+
|
|
94
|
+
Note: This is the CLI client. Use 'soothe-daemon' command to manage the daemon server.
|
|
95
|
+
|
|
96
|
+
Examples:
|
|
97
|
+
soothe # Interactive TUI mode
|
|
98
|
+
soothe -p "Research AI advances" # Headless single-prompt mode
|
|
99
|
+
soothe --config custom.yml # Use custom CLI config
|
|
100
|
+
soothe thread list # List conversation threads
|
|
101
|
+
"""
|
|
102
|
+
# Handle -h/--help flag
|
|
103
|
+
if show_help:
|
|
104
|
+
typer.echo(ctx.get_help())
|
|
105
|
+
raise typer.Exit
|
|
106
|
+
|
|
107
|
+
# Handle --version flag
|
|
108
|
+
if show_version:
|
|
109
|
+
typer.echo(f"soothe {version('soothe-cli')}")
|
|
110
|
+
raise typer.Exit
|
|
111
|
+
|
|
112
|
+
# Only run default behavior if no subcommand is being invoked
|
|
113
|
+
if ctx.invoked_subcommand is None:
|
|
114
|
+
from soothe_cli.cli.commands.run_cmd import run_impl
|
|
115
|
+
|
|
116
|
+
run_impl(
|
|
117
|
+
prompt=prompt,
|
|
118
|
+
config=config,
|
|
119
|
+
thread_id=None,
|
|
120
|
+
no_tui=no_tui,
|
|
121
|
+
autonomous=False,
|
|
122
|
+
max_iterations=None,
|
|
123
|
+
output_format=output_format,
|
|
124
|
+
verbosity=verbosity,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
# ---------------------------------------------------------------------------
|
|
129
|
+
# Thread Command (Nested Subcommands)
|
|
130
|
+
# ---------------------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
thread_app = typer.Typer(name="thread", help="Manage conversation threads")
|
|
133
|
+
add_help_alias(thread_app)
|
|
134
|
+
app.add_typer(thread_app)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@thread_app.command("list")
|
|
138
|
+
def _thread_list(
|
|
139
|
+
config: Annotated[
|
|
140
|
+
str | None,
|
|
141
|
+
typer.Option("--config", "-c", help="Path to configuration file."),
|
|
142
|
+
] = None,
|
|
143
|
+
status: Annotated[
|
|
144
|
+
str | None,
|
|
145
|
+
typer.Option("--status", "-s", help="Filter by status (active, archived)."),
|
|
146
|
+
] = None,
|
|
147
|
+
) -> None:
|
|
148
|
+
"""List all conversation threads.
|
|
149
|
+
|
|
150
|
+
Examples:
|
|
151
|
+
soothe thread list
|
|
152
|
+
soothe thread list --status active
|
|
153
|
+
"""
|
|
154
|
+
from soothe_cli.cli.commands.thread_cmd import thread_list
|
|
155
|
+
|
|
156
|
+
thread_list(config=config, status=status)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@thread_app.command("show")
|
|
160
|
+
def _thread_show(
|
|
161
|
+
thread_id: Annotated[str, typer.Argument(help="Thread ID to show.")],
|
|
162
|
+
config: Annotated[
|
|
163
|
+
str | None,
|
|
164
|
+
typer.Option("--config", "-c", help="Path to configuration file."),
|
|
165
|
+
] = None,
|
|
166
|
+
) -> None:
|
|
167
|
+
"""Show thread details.
|
|
168
|
+
|
|
169
|
+
Example:
|
|
170
|
+
soothe thread show abc123
|
|
171
|
+
"""
|
|
172
|
+
from soothe_cli.cli.commands.thread_cmd import thread_show
|
|
173
|
+
|
|
174
|
+
thread_show(thread_id=thread_id, config=config)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@thread_app.command("continue")
|
|
178
|
+
def _thread_continue(
|
|
179
|
+
thread_id: Annotated[
|
|
180
|
+
str | None,
|
|
181
|
+
typer.Argument(help="Thread ID to continue. Omit to continue last active thread."),
|
|
182
|
+
] = None,
|
|
183
|
+
config: Annotated[
|
|
184
|
+
str | None,
|
|
185
|
+
typer.Option("--config", "-c", help="Path to configuration file."),
|
|
186
|
+
] = None,
|
|
187
|
+
new: Annotated[ # noqa: FBT002
|
|
188
|
+
bool,
|
|
189
|
+
typer.Option("--new", help="Create a new thread instead of continuing."),
|
|
190
|
+
] = False,
|
|
191
|
+
) -> None:
|
|
192
|
+
"""Continue a conversation thread in the TUI.
|
|
193
|
+
|
|
194
|
+
Requires a running daemon. Start daemon with 'soothe-daemon start' first.
|
|
195
|
+
|
|
196
|
+
Examples:
|
|
197
|
+
soothe thread continue abc123
|
|
198
|
+
soothe thread continue --new
|
|
199
|
+
soothe thread continue
|
|
200
|
+
"""
|
|
201
|
+
from soothe_cli.cli.commands.thread_cmd import thread_continue
|
|
202
|
+
|
|
203
|
+
thread_continue(thread_id=thread_id, config=config, new=new)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@thread_app.command("archive")
|
|
207
|
+
def _thread_archive(
|
|
208
|
+
thread_id: Annotated[str, typer.Argument(help="Thread ID to archive.")],
|
|
209
|
+
config: Annotated[
|
|
210
|
+
str | None,
|
|
211
|
+
typer.Option("--config", "-c", help="Path to configuration file."),
|
|
212
|
+
] = None,
|
|
213
|
+
) -> None:
|
|
214
|
+
"""Archive a thread.
|
|
215
|
+
|
|
216
|
+
Example:
|
|
217
|
+
soothe thread archive abc123
|
|
218
|
+
"""
|
|
219
|
+
from soothe_cli.cli.commands.thread_cmd import thread_archive
|
|
220
|
+
|
|
221
|
+
thread_archive(thread_id=thread_id, config=config)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
@thread_app.command("delete")
|
|
225
|
+
def _thread_delete(
|
|
226
|
+
thread_id: Annotated[str, typer.Argument(help="Thread ID to delete.")],
|
|
227
|
+
config: Annotated[
|
|
228
|
+
str | None,
|
|
229
|
+
typer.Option("--config", "-c", help="Path to configuration file."),
|
|
230
|
+
] = None,
|
|
231
|
+
yes: Annotated[ # noqa: FBT002
|
|
232
|
+
bool,
|
|
233
|
+
typer.Option("--yes", "-y", help="Skip confirmation."),
|
|
234
|
+
] = False,
|
|
235
|
+
) -> None:
|
|
236
|
+
"""Permanently delete a thread.
|
|
237
|
+
|
|
238
|
+
Example:
|
|
239
|
+
soothe thread delete abc123
|
|
240
|
+
"""
|
|
241
|
+
from soothe_cli.cli.commands.thread_cmd import thread_delete
|
|
242
|
+
|
|
243
|
+
thread_delete(thread_id=thread_id, config=config, yes=yes)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@thread_app.command("export")
|
|
247
|
+
def _thread_export(
|
|
248
|
+
thread_id: Annotated[str, typer.Argument(help="Thread ID to export.")],
|
|
249
|
+
output: Annotated[
|
|
250
|
+
str | None,
|
|
251
|
+
typer.Option("--output", "-o", help="Output file path."),
|
|
252
|
+
] = None,
|
|
253
|
+
export_format: Annotated[
|
|
254
|
+
str,
|
|
255
|
+
typer.Option("--format", "-f", help="Export format: jsonl or md."),
|
|
256
|
+
] = "jsonl",
|
|
257
|
+
) -> None:
|
|
258
|
+
"""Export thread conversation to a file.
|
|
259
|
+
|
|
260
|
+
Example:
|
|
261
|
+
soothe thread export abc123 --output out.json
|
|
262
|
+
"""
|
|
263
|
+
from soothe_cli.cli.commands.thread_cmd import thread_export
|
|
264
|
+
|
|
265
|
+
thread_export(thread_id=thread_id, output=output, export_format=export_format)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
@thread_app.command("stats")
|
|
269
|
+
def _thread_stats(
|
|
270
|
+
thread_id: Annotated[str, typer.Argument(help="Thread ID.")],
|
|
271
|
+
config: Annotated[
|
|
272
|
+
str | None,
|
|
273
|
+
typer.Option("--config", "-c", help="Path to configuration file."),
|
|
274
|
+
] = None,
|
|
275
|
+
) -> None:
|
|
276
|
+
"""Show thread execution statistics.
|
|
277
|
+
|
|
278
|
+
Example:
|
|
279
|
+
soothe thread stats abc123
|
|
280
|
+
"""
|
|
281
|
+
from soothe_cli.cli.commands.thread_cmd import thread_stats
|
|
282
|
+
|
|
283
|
+
thread_stats(thread_id=thread_id, config=config)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
@thread_app.command("tag")
|
|
287
|
+
def _thread_tag(
|
|
288
|
+
thread_id: Annotated[str, typer.Argument(help="Thread ID.")],
|
|
289
|
+
tags: Annotated[
|
|
290
|
+
list[str],
|
|
291
|
+
typer.Argument(help="Tags to add/remove."),
|
|
292
|
+
],
|
|
293
|
+
config: Annotated[
|
|
294
|
+
str | None,
|
|
295
|
+
typer.Option("--config", "-c", help="Path to configuration file."),
|
|
296
|
+
] = None,
|
|
297
|
+
remove: Annotated[ # noqa: FBT002
|
|
298
|
+
bool,
|
|
299
|
+
typer.Option("--remove", help="Remove tags instead of adding."),
|
|
300
|
+
] = False,
|
|
301
|
+
) -> None:
|
|
302
|
+
"""Add or remove tags from a thread.
|
|
303
|
+
|
|
304
|
+
Examples:
|
|
305
|
+
soothe thread tag abc123 research analysis
|
|
306
|
+
soothe thread tag abc123 research --remove
|
|
307
|
+
"""
|
|
308
|
+
from soothe_cli.cli.commands.thread_cmd import thread_tag
|
|
309
|
+
|
|
310
|
+
thread_tag(thread_id=thread_id, tags=tags, config=config, remove=remove)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
@thread_app.command("create")
|
|
314
|
+
def _thread_create(
|
|
315
|
+
config: Annotated[
|
|
316
|
+
str | None,
|
|
317
|
+
typer.Option("--config", "-c", help="Path to configuration file."),
|
|
318
|
+
] = None,
|
|
319
|
+
message: Annotated[
|
|
320
|
+
str | None,
|
|
321
|
+
typer.Option("--message", "-m", help="Initial message to seed the thread."),
|
|
322
|
+
] = None,
|
|
323
|
+
tag: Annotated[
|
|
324
|
+
list[str] | None,
|
|
325
|
+
typer.Option("--tag", "-t", help="Tags for the thread (repeatable)."),
|
|
326
|
+
] = None,
|
|
327
|
+
) -> None:
|
|
328
|
+
"""Create a new persisted thread.
|
|
329
|
+
|
|
330
|
+
Examples:
|
|
331
|
+
soothe thread create
|
|
332
|
+
soothe thread create --message "Hello world"
|
|
333
|
+
soothe thread create --tag research
|
|
334
|
+
"""
|
|
335
|
+
from soothe_cli.cli.commands.thread_cmd import thread_create
|
|
336
|
+
|
|
337
|
+
thread_create(config=config, message=message, tag=tag)
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
@thread_app.command("artifacts")
|
|
341
|
+
def _thread_artifacts(
|
|
342
|
+
thread_id: Annotated[str, typer.Argument(help="Thread ID to list artifacts for.")],
|
|
343
|
+
config: Annotated[
|
|
344
|
+
str | None,
|
|
345
|
+
typer.Option("--config", "-c", help="Path to configuration file."),
|
|
346
|
+
] = None,
|
|
347
|
+
) -> None:
|
|
348
|
+
"""List artifacts for a thread.
|
|
349
|
+
|
|
350
|
+
Example:
|
|
351
|
+
soothe thread artifacts abc123
|
|
352
|
+
"""
|
|
353
|
+
from soothe_cli.cli.commands.thread_cmd import thread_artifacts
|
|
354
|
+
|
|
355
|
+
thread_artifacts(thread_id=thread_id, config=config)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
# ---------------------------------------------------------------------------
|
|
359
|
+
# Config Command (Nested Subcommands)
|
|
360
|
+
# ---------------------------------------------------------------------------
|
|
361
|
+
|
|
362
|
+
config_app = typer.Typer(name="config", help="Manage Soothe configuration")
|
|
363
|
+
add_help_alias(config_app)
|
|
364
|
+
app.add_typer(config_app)
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
@config_app.command("show")
|
|
368
|
+
def _config_show(
|
|
369
|
+
config: Annotated[
|
|
370
|
+
str | None,
|
|
371
|
+
typer.Option("--config", "-c", help="Path to configuration file."),
|
|
372
|
+
] = None,
|
|
373
|
+
format_output: Annotated[
|
|
374
|
+
str,
|
|
375
|
+
typer.Option("--format", "-f", help="Output format: json or summary."),
|
|
376
|
+
] = "summary",
|
|
377
|
+
show_sensitive: Annotated[ # noqa: FBT002
|
|
378
|
+
bool,
|
|
379
|
+
typer.Option("--show-sensitive", help="Show sensitive values like API keys."),
|
|
380
|
+
] = False,
|
|
381
|
+
) -> None:
|
|
382
|
+
"""Display current configuration.
|
|
383
|
+
|
|
384
|
+
Examples:
|
|
385
|
+
soothe config show
|
|
386
|
+
soothe config show --show-sensitive
|
|
387
|
+
soothe config show --format json
|
|
388
|
+
"""
|
|
389
|
+
from soothe_cli.cli.commands.config_cmd import config_show
|
|
390
|
+
|
|
391
|
+
config_show(config=config, format_output=format_output, show_sensitive=show_sensitive)
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
@config_app.command("init")
|
|
395
|
+
def _config_init(
|
|
396
|
+
force: Annotated[ # noqa: FBT002
|
|
397
|
+
bool,
|
|
398
|
+
typer.Option(
|
|
399
|
+
"--force", "-f", help="Overwrite existing configuration without confirmation."
|
|
400
|
+
),
|
|
401
|
+
] = False,
|
|
402
|
+
) -> None:
|
|
403
|
+
"""Initialize ~/.soothe with a default configuration.
|
|
404
|
+
|
|
405
|
+
Examples:
|
|
406
|
+
soothe config init
|
|
407
|
+
soothe config init --force
|
|
408
|
+
"""
|
|
409
|
+
from soothe_cli.cli.commands.config_cmd import config_init
|
|
410
|
+
|
|
411
|
+
config_init(force=force)
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
@config_app.command("validate")
|
|
415
|
+
def _config_validate(
|
|
416
|
+
config: Annotated[
|
|
417
|
+
str | None,
|
|
418
|
+
typer.Option("--config", "-c", help="Path to configuration file."),
|
|
419
|
+
] = None,
|
|
420
|
+
) -> None:
|
|
421
|
+
"""Validate configuration file and show basic info.
|
|
422
|
+
|
|
423
|
+
Examples:
|
|
424
|
+
soothe config validate
|
|
425
|
+
soothe config validate --config custom.yml
|
|
426
|
+
"""
|
|
427
|
+
from soothe_cli.cli.commands.config_cmd import config_validate
|
|
428
|
+
|
|
429
|
+
config_validate(config=config)
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
# ---------------------------------------------------------------------------
|
|
433
|
+
# Agent Command (Nested Subcommands)
|
|
434
|
+
# ---------------------------------------------------------------------------
|
|
435
|
+
|
|
436
|
+
agent_app = typer.Typer(name="agent", help="List and manage agents")
|
|
437
|
+
add_help_alias(agent_app)
|
|
438
|
+
app.add_typer(agent_app)
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
@agent_app.command("list")
|
|
442
|
+
def _agent_list(
|
|
443
|
+
config: Annotated[
|
|
444
|
+
str | None,
|
|
445
|
+
typer.Option("--config", "-c", help="Path to configuration file."),
|
|
446
|
+
] = None,
|
|
447
|
+
enabled: Annotated[ # noqa: FBT002
|
|
448
|
+
bool,
|
|
449
|
+
typer.Option("--enabled", help="Show only enabled agents."),
|
|
450
|
+
] = False,
|
|
451
|
+
disabled: Annotated[ # noqa: FBT002
|
|
452
|
+
bool,
|
|
453
|
+
typer.Option("--disabled", help="Show only disabled agents."),
|
|
454
|
+
] = False,
|
|
455
|
+
) -> None:
|
|
456
|
+
"""List available agents and their status.
|
|
457
|
+
|
|
458
|
+
Examples:
|
|
459
|
+
soothe agent list
|
|
460
|
+
soothe agent list --enabled
|
|
461
|
+
soothe agent list --disabled
|
|
462
|
+
"""
|
|
463
|
+
from soothe_cli.cli.commands.status_cmd import agent_list
|
|
464
|
+
|
|
465
|
+
agent_list(config=config, enabled=enabled, disabled=disabled)
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
@agent_app.command("status")
|
|
469
|
+
def _agent_status(
|
|
470
|
+
config: Annotated[
|
|
471
|
+
str | None,
|
|
472
|
+
typer.Option("--config", "-c", help="Path to configuration file."),
|
|
473
|
+
] = None,
|
|
474
|
+
) -> None:
|
|
475
|
+
"""Show detailed agent status.
|
|
476
|
+
|
|
477
|
+
Example:
|
|
478
|
+
soothe agent status
|
|
479
|
+
"""
|
|
480
|
+
from soothe_cli.cli.commands.status_cmd import agent_status
|
|
481
|
+
|
|
482
|
+
agent_status(config=config)
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
# ---------------------------------------------------------------------------
|
|
486
|
+
# Autopilot Command (Nested Subcommands)
|
|
487
|
+
# ---------------------------------------------------------------------------
|
|
488
|
+
|
|
489
|
+
from soothe_cli.cli.commands.autopilot_cmd import app as _autopilot_app # noqa: E402
|
|
490
|
+
|
|
491
|
+
add_help_alias(_autopilot_app)
|
|
492
|
+
app.add_typer(_autopilot_app, name="autopilot")
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
# ---------------------------------------------------------------------------
|
|
496
|
+
# Help Command
|
|
497
|
+
# ---------------------------------------------------------------------------
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
@app.command(name="help")
|
|
501
|
+
def help_command(ctx: typer.Context) -> None:
|
|
502
|
+
"""Show help message and exit."""
|
|
503
|
+
# Get the parent context (the main app) to show full help
|
|
504
|
+
parent_ctx = ctx.parent or ctx
|
|
505
|
+
typer.echo(parent_ctx.get_help())
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
if __name__ == "__main__":
|
|
509
|
+
app()
|