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.
Files changed (107) hide show
  1. soothe_cli/__init__.py +5 -0
  2. soothe_cli/cli/__init__.py +1 -0
  3. soothe_cli/cli/commands/__init__.py +1 -0
  4. soothe_cli/cli/commands/autopilot_cmd.py +410 -0
  5. soothe_cli/cli/commands/config_cmd.py +277 -0
  6. soothe_cli/cli/commands/run_cmd.py +87 -0
  7. soothe_cli/cli/commands/status_cmd.py +121 -0
  8. soothe_cli/cli/commands/subagent_names.py +17 -0
  9. soothe_cli/cli/commands/thread_cmd.py +657 -0
  10. soothe_cli/cli/execution/__init__.py +6 -0
  11. soothe_cli/cli/execution/daemon.py +194 -0
  12. soothe_cli/cli/execution/headless.py +99 -0
  13. soothe_cli/cli/execution/launcher.py +31 -0
  14. soothe_cli/cli/main.py +509 -0
  15. soothe_cli/cli/renderer.py +444 -0
  16. soothe_cli/cli/stream/__init__.py +17 -0
  17. soothe_cli/cli/stream/context.py +138 -0
  18. soothe_cli/cli/stream/display_line.py +83 -0
  19. soothe_cli/cli/stream/formatter.py +412 -0
  20. soothe_cli/cli/stream/pipeline.py +521 -0
  21. soothe_cli/cli/utils.py +46 -0
  22. soothe_cli/config/__init__.py +5 -0
  23. soothe_cli/config/cli_config.py +155 -0
  24. soothe_cli/plan/__init__.py +5 -0
  25. soothe_cli/plan/rich_tree.py +54 -0
  26. soothe_cli/shared/__init__.py +107 -0
  27. soothe_cli/shared/command_router.py +246 -0
  28. soothe_cli/shared/config_loader.py +68 -0
  29. soothe_cli/shared/display_policy.py +413 -0
  30. soothe_cli/shared/essential_events.py +68 -0
  31. soothe_cli/shared/event_processor.py +823 -0
  32. soothe_cli/shared/message_processing.py +393 -0
  33. soothe_cli/shared/presentation_engine.py +173 -0
  34. soothe_cli/shared/processor_state.py +80 -0
  35. soothe_cli/shared/renderer_protocol.py +158 -0
  36. soothe_cli/shared/rendering.py +43 -0
  37. soothe_cli/shared/slash_commands.py +354 -0
  38. soothe_cli/shared/subagent_routing.py +63 -0
  39. soothe_cli/shared/suppression_state.py +188 -0
  40. soothe_cli/shared/tool_formatters/__init__.py +27 -0
  41. soothe_cli/shared/tool_formatters/base.py +109 -0
  42. soothe_cli/shared/tool_formatters/execution.py +297 -0
  43. soothe_cli/shared/tool_formatters/fallback.py +128 -0
  44. soothe_cli/shared/tool_formatters/file_ops.py +299 -0
  45. soothe_cli/shared/tool_formatters/goal_formatter.py +331 -0
  46. soothe_cli/shared/tool_formatters/media.py +291 -0
  47. soothe_cli/shared/tool_formatters/structured.py +202 -0
  48. soothe_cli/shared/tool_formatters/web.py +143 -0
  49. soothe_cli/shared/tool_output_formatter.py +227 -0
  50. soothe_cli/shared/tui_trace_log.py +40 -0
  51. soothe_cli/tui/__init__.py +5 -0
  52. soothe_cli/tui/_ask_user_types.py +50 -0
  53. soothe_cli/tui/_cli_context.py +27 -0
  54. soothe_cli/tui/_env_vars.py +56 -0
  55. soothe_cli/tui/_session_stats.py +114 -0
  56. soothe_cli/tui/_version.py +21 -0
  57. soothe_cli/tui/app.py +4992 -0
  58. soothe_cli/tui/app.tcss +302 -0
  59. soothe_cli/tui/command_registry.py +310 -0
  60. soothe_cli/tui/config.py +2381 -0
  61. soothe_cli/tui/daemon_session.py +233 -0
  62. soothe_cli/tui/file_ops.py +409 -0
  63. soothe_cli/tui/formatting.py +28 -0
  64. soothe_cli/tui/hooks.py +23 -0
  65. soothe_cli/tui/input.py +782 -0
  66. soothe_cli/tui/media_utils.py +471 -0
  67. soothe_cli/tui/model_config.py +518 -0
  68. soothe_cli/tui/output.py +69 -0
  69. soothe_cli/tui/project_utils.py +188 -0
  70. soothe_cli/tui/sessions.py +1248 -0
  71. soothe_cli/tui/skills/__init__.py +5 -0
  72. soothe_cli/tui/skills/invocation.py +74 -0
  73. soothe_cli/tui/skills/load.py +93 -0
  74. soothe_cli/tui/textual_adapter.py +1430 -0
  75. soothe_cli/tui/theme.py +838 -0
  76. soothe_cli/tui/tool_display.py +297 -0
  77. soothe_cli/tui/unicode_security.py +502 -0
  78. soothe_cli/tui/update_check.py +447 -0
  79. soothe_cli/tui/widgets/__init__.py +9 -0
  80. soothe_cli/tui/widgets/_links.py +63 -0
  81. soothe_cli/tui/widgets/approval.py +430 -0
  82. soothe_cli/tui/widgets/ask_user.py +392 -0
  83. soothe_cli/tui/widgets/autocomplete.py +666 -0
  84. soothe_cli/tui/widgets/autopilot_dashboard.py +308 -0
  85. soothe_cli/tui/widgets/autopilot_screen.py +64 -0
  86. soothe_cli/tui/widgets/chat_input.py +1834 -0
  87. soothe_cli/tui/widgets/clipboard.py +128 -0
  88. soothe_cli/tui/widgets/diff.py +240 -0
  89. soothe_cli/tui/widgets/editor.py +140 -0
  90. soothe_cli/tui/widgets/history.py +221 -0
  91. soothe_cli/tui/widgets/loading.py +194 -0
  92. soothe_cli/tui/widgets/mcp_viewer.py +352 -0
  93. soothe_cli/tui/widgets/message_store.py +693 -0
  94. soothe_cli/tui/widgets/messages.py +1720 -0
  95. soothe_cli/tui/widgets/model_selector.py +988 -0
  96. soothe_cli/tui/widgets/notification_settings.py +155 -0
  97. soothe_cli/tui/widgets/status.py +403 -0
  98. soothe_cli/tui/widgets/theme_selector.py +158 -0
  99. soothe_cli/tui/widgets/thread_selector.py +1865 -0
  100. soothe_cli/tui/widgets/tool_renderers.py +148 -0
  101. soothe_cli/tui/widgets/tool_widgets.py +254 -0
  102. soothe_cli/tui/widgets/tools.py +165 -0
  103. soothe_cli/tui/widgets/welcome.py +330 -0
  104. soothe_cli-0.1.0.dist-info/METADATA +100 -0
  105. soothe_cli-0.1.0.dist-info/RECORD +107 -0
  106. soothe_cli-0.1.0.dist-info/WHEEL +4 -0
  107. soothe_cli-0.1.0.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,330 @@
1
+ """Welcome banner widget for Soothe."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import random
7
+ from typing import TYPE_CHECKING, Any
8
+
9
+ from textual.color import Color as TColor
10
+ from textual.content import Content
11
+ from textual.style import Style as TStyle
12
+ from textual.widgets import Static
13
+
14
+ if TYPE_CHECKING:
15
+ from textual.events import Click
16
+
17
+ from soothe_cli.tui import theme
18
+ from soothe_cli.tui._version import __version__
19
+ from soothe_cli.tui.config import (
20
+ _get_editable_install_path,
21
+ _is_editable_install,
22
+ fetch_langsmith_project_url,
23
+ get_banner,
24
+ get_glyphs,
25
+ get_langsmith_project_name,
26
+ )
27
+ from soothe_cli.tui.widgets._links import open_style_link
28
+
29
+ _TIPS: list[str] = [
30
+ "Use @ to reference files and / for commands",
31
+ "Try /threads to resume a previous conversation",
32
+ "Use /tokens to check context usage",
33
+ "Use /mcp to see your loaded tools and servers",
34
+ "Use /remember to save learnings from this conversation",
35
+ "Use /model to switch models mid-conversation",
36
+ "Press ctrl+x to compose prompts in your external editor",
37
+ "Press ctrl+u to delete to the start of the line in the chat input",
38
+ "Use /skill:<name> to invoke a skill directly",
39
+ "Type /update to check for and install updates",
40
+ "Use /theme to customize the CLI colors and style",
41
+ "Use /skill:skill-creator to build reusable agent skills",
42
+ "Use /auto-update to toggle automatic CLI updates",
43
+ ]
44
+ """Rotating tips shown in the welcome footer.
45
+
46
+ One is picked per session.
47
+ """
48
+
49
+
50
+ class WelcomeBanner(Static):
51
+ """Welcome banner displayed at startup."""
52
+
53
+ # Disable Textual's auto_links to prevent a flicker cycle: Style.__add__
54
+ # calls .copy() for linked styles, generating a fresh random _link_id on
55
+ # each render. This means highlight_link_id never stabilizes, causing an
56
+ # infinite hover-refresh loop.
57
+ auto_links = False
58
+
59
+ DEFAULT_CSS = """
60
+ WelcomeBanner {
61
+ height: auto;
62
+ padding: 1;
63
+ margin-bottom: 1;
64
+ }
65
+ """
66
+
67
+ def __init__(
68
+ self,
69
+ thread_id: str | None = None,
70
+ mcp_tool_count: int = 0,
71
+ *,
72
+ connecting: bool = False,
73
+ resuming: bool = False,
74
+ local_server: bool = False,
75
+ **kwargs: Any,
76
+ ) -> None:
77
+ """Initialize the welcome banner.
78
+
79
+ Args:
80
+ thread_id: Optional thread ID to display in the banner.
81
+ mcp_tool_count: Number of MCP tools loaded at startup.
82
+ connecting: When `True`, show a "Connecting..." footer instead of
83
+ the normal ready prompt. Call `set_connected` to transition.
84
+ resuming: When `True`, the connecting footer says "Resuming..."
85
+ instead of any `'Connecting...'` variant.
86
+ local_server: When `True`, the connecting footer qualifies the
87
+ server as "local" (i.e. a server process managed by the
88
+ CLI).
89
+
90
+ Ignored when `resuming` is `True`.
91
+ **kwargs: Additional arguments passed to parent.
92
+ """
93
+ # Avoid collision with Widget._thread_id (Textual internal int)
94
+ self._cli_thread_id: str | None = thread_id
95
+ self._mcp_tool_count = mcp_tool_count
96
+ self._connecting = connecting
97
+ self._resuming = resuming
98
+ self._local_server = local_server
99
+ self._failed = False
100
+ self._failure_error: str = ""
101
+ self._project_name: str | None = get_langsmith_project_name()
102
+ self._project_url: str | None = None
103
+ self._tip: str = random.choice(_TIPS) # noqa: S311
104
+
105
+ super().__init__(self._build_banner(), **kwargs)
106
+
107
+ def on_mount(self) -> None:
108
+ """Kick off background fetch for LangSmith project URL."""
109
+ self.watch(self.app, "theme", self._on_theme_change, init=False)
110
+ if self._project_name:
111
+ self.run_worker(self._fetch_and_update, exclusive=True)
112
+
113
+ def _on_theme_change(self) -> None:
114
+ """Re-render the banner when the app theme changes."""
115
+ self.update(self._build_banner(self._project_url))
116
+
117
+ async def _fetch_and_update(self) -> None:
118
+ """Fetch the LangSmith URL in a thread and update the banner."""
119
+ if not self._project_name:
120
+ return
121
+ try:
122
+ project_url = await asyncio.wait_for(
123
+ asyncio.to_thread(fetch_langsmith_project_url, self._project_name),
124
+ timeout=2.0,
125
+ )
126
+ except (TimeoutError, OSError):
127
+ project_url = None
128
+ if project_url:
129
+ self._project_url = project_url
130
+ self.update(self._build_banner(project_url))
131
+
132
+ def update_thread_id(self, thread_id: str) -> None:
133
+ """Update the displayed thread ID and re-render the banner.
134
+
135
+ Args:
136
+ thread_id: The new thread ID to display.
137
+ """
138
+ self._cli_thread_id = thread_id
139
+ self.update(self._build_banner(self._project_url))
140
+
141
+ def set_connected(self, mcp_tool_count: int = 0) -> None:
142
+ """Transition from "connecting" to "ready" state.
143
+
144
+ Args:
145
+ mcp_tool_count: Number of MCP tools loaded during connection.
146
+ """
147
+ self._connecting = False
148
+ self._failed = False
149
+ self._mcp_tool_count = mcp_tool_count
150
+ self.update(self._build_banner(self._project_url))
151
+
152
+ def set_failed(self, error: str) -> None:
153
+ """Transition from "connecting" to a persistent failure state.
154
+
155
+ Args:
156
+ error: Error message describing the server startup failure.
157
+ """
158
+ self._connecting = False
159
+ self._failed = True
160
+ self._failure_error = error
161
+ self.update(self._build_banner(self._project_url))
162
+
163
+ def on_click(self, event: Click) -> None: # noqa: PLR6301 # Textual event handler
164
+ """Open style-embedded hyperlinks on single click."""
165
+ open_style_link(event)
166
+
167
+ def _build_banner(self, project_url: str | None = None) -> Content:
168
+ """Build the banner content.
169
+
170
+ When a `project_url` is provided and a thread ID is set, the thread ID
171
+ is rendered as a clickable hyperlink to the LangSmith thread view.
172
+
173
+ Args:
174
+ project_url: LangSmith project URL used for linking the project
175
+ name and thread ID. When `None`, text is rendered without links.
176
+
177
+ Returns:
178
+ Content object containing the formatted banner.
179
+ """
180
+ parts: list[str | tuple[str, str | TStyle] | Content] = []
181
+ colors = theme.get_theme_colors(self)
182
+ ansi = self.app.theme == "textual-ansi"
183
+
184
+ banner = get_banner()
185
+ primary_style: str | TStyle = (
186
+ "bold" if ansi else TStyle(foreground=TColor.parse(colors.primary), bold=True)
187
+ )
188
+
189
+ if not ansi and _is_editable_install():
190
+ # Highlight local-install version tag with tool accent; art stays primary.
191
+ dev_style = TStyle(foreground=TColor.parse(colors.tool), bold=True)
192
+ version_tag = f"v{__version__} (local)"
193
+ idx = banner.rfind(version_tag)
194
+ if idx >= 0:
195
+ parts.extend(
196
+ [
197
+ (banner[:idx], primary_style),
198
+ (version_tag, dev_style),
199
+ (banner[idx + len(version_tag) :] + "\n", primary_style),
200
+ ]
201
+ )
202
+ else:
203
+ parts.append((banner + "\n", primary_style))
204
+ else:
205
+ parts.append((banner + "\n", primary_style))
206
+
207
+ # For ANSI theme, use "bold" (terminal foreground) instead of hex
208
+ accent: str | TStyle = "bold" if ansi else colors.primary
209
+ success_color: str = "bold green" if ansi else colors.success
210
+
211
+ editable_path = _get_editable_install_path()
212
+ if editable_path:
213
+ parts.extend([("Installed from: ", "dim"), (editable_path, "dim"), "\n"])
214
+
215
+ if self._project_name:
216
+ parts.extend(
217
+ [
218
+ (f"{get_glyphs().checkmark} ", success_color),
219
+ "LangSmith tracing: ",
220
+ ]
221
+ )
222
+ if project_url:
223
+ link_style: str | TStyle
224
+ if ansi:
225
+ url = f"{project_url}?utm_source=soothe"
226
+ link_style = TStyle(bold=True, link=url)
227
+ else:
228
+ link_style = TStyle(
229
+ foreground=TColor.parse(colors.primary),
230
+ link=f"{project_url}?utm_source=Soothe",
231
+ )
232
+ parts.append((f"'{self._project_name}'", link_style))
233
+ else:
234
+ parts.append((f"'{self._project_name}'", accent))
235
+ parts.append("\n")
236
+
237
+ if self._cli_thread_id:
238
+ if project_url:
239
+ thread_url = f"{project_url.rstrip('/')}/t/{self._cli_thread_id}?utm_source=Soothe"
240
+ parts.extend(
241
+ [
242
+ ("Thread: ", "dim"),
243
+ (self._cli_thread_id, TStyle(dim=True, link=thread_url)),
244
+ ("\n", "dim"),
245
+ ]
246
+ )
247
+ else:
248
+ parts.append((f"Thread: {self._cli_thread_id}\n", "dim"))
249
+
250
+ if self._mcp_tool_count > 0:
251
+ parts.append((f"{get_glyphs().checkmark} ", success_color))
252
+ label = "MCP tool" if self._mcp_tool_count == 1 else "MCP tools"
253
+ parts.append(f"Loaded {self._mcp_tool_count} {label}\n")
254
+
255
+ if self._failed:
256
+ parts.append(build_failure_footer(self._failure_error))
257
+ elif self._connecting:
258
+ parts.append(
259
+ build_connecting_footer(
260
+ resuming=self._resuming,
261
+ local_server=self._local_server,
262
+ )
263
+ )
264
+ else:
265
+ ready_color = "bold" if ansi else colors.primary
266
+ parts.append(build_welcome_footer(primary_color=ready_color, tip=self._tip))
267
+ return Content.assemble(*parts)
268
+
269
+
270
+ def build_failure_footer(error: str) -> Content:
271
+ """Build a footer shown when the server failed to start.
272
+
273
+ Args:
274
+ error: Error message describing the failure.
275
+
276
+ Returns:
277
+ Content with a persistent failure message.
278
+ """
279
+ colors = theme.get_theme_colors()
280
+ return Content.assemble(
281
+ ("\nServer failed to start: ", f"bold {colors.error}"),
282
+ (error, colors.error),
283
+ ("\n", colors.error),
284
+ )
285
+
286
+
287
+ def build_connecting_footer(*, resuming: bool = False, local_server: bool = False) -> Content:
288
+ """Build a footer shown while waiting for the server to connect.
289
+
290
+ Args:
291
+ resuming: Show `'Resuming...'` instead of any `'Connecting...'` variant.
292
+ local_server: Qualify the server as "local" in the connecting message.
293
+
294
+ Ignored when `resuming` is `True`.
295
+
296
+ Returns:
297
+ Content with a connecting status message.
298
+ """
299
+ if resuming:
300
+ text = "\nResuming...\n"
301
+ elif local_server:
302
+ text = "\nConnecting to local server...\n"
303
+ else:
304
+ text = "\nConnecting to server...\n"
305
+ return Content.styled(text, "dim")
306
+
307
+
308
+ def build_welcome_footer(*, primary_color: str = theme.PRIMARY, tip: str | None = None) -> Content:
309
+ """Build the footer shown at the bottom of the welcome banner.
310
+
311
+ Includes a tip to help users discover features.
312
+
313
+ Args:
314
+ primary_color: Color string for the ready prompt.
315
+
316
+ Defaults to the module-level ANSI `PRIMARY` constant; widget callers
317
+ should pass the active theme's hex value.
318
+ tip: Tip text to display. When `None`, a random tip is selected.
319
+
320
+ Pass an explicit value to keep the tip stable across re-renders.
321
+
322
+ Returns:
323
+ Content with the ready prompt and a tip.
324
+ """
325
+ if tip is None:
326
+ tip = random.choice(_TIPS) # noqa: S311
327
+ return Content.assemble(
328
+ ("\nReady to unleash your thinking?\n", primary_color),
329
+ (f"Tip: {tip}", "dim italic"),
330
+ )
@@ -0,0 +1,100 @@
1
+ Metadata-Version: 2.4
2
+ Name: soothe-cli
3
+ Version: 0.1.0
4
+ Summary: Soothe CLI client - communicates with daemon via WebSocket
5
+ Project-URL: Homepage, https://github.com/caesar0301/soothe
6
+ Project-URL: Documentation, https://soothe.readthedocs.io
7
+ Project-URL: Repository, https://github.com/caesar0301/soothe
8
+ License: MIT
9
+ Keywords: cli,client,soothe,tui,websocket
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Python: <3.15,>=3.11
21
+ Requires-Dist: python-dotenv<2.0.0,>=1.0.0
22
+ Requires-Dist: pyyaml<7.0.0,>=6.0.0
23
+ Requires-Dist: rich>=13.0.0
24
+ Requires-Dist: soothe-sdk<1.0.0,>=0.2.0
25
+ Requires-Dist: textual>=0.40.0
26
+ Requires-Dist: typer<1.0.0,>=0.9.0
27
+ Requires-Dist: websockets>=12.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: mypy>=1.0.0; extra == 'dev'
30
+ Requires-Dist: pytest-asyncio>=1.3.0; extra == 'dev'
31
+ Requires-Dist: pytest-cov; extra == 'dev'
32
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
33
+ Requires-Dist: ruff>=0.12.0; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # Soothe CLI Client
37
+
38
+ WebSocket-based CLI client for Soothe daemon.
39
+
40
+ ## Installation
41
+
42
+ ```bash
43
+ pip install soothe-cli
44
+ ```
45
+
46
+ ## Usage
47
+
48
+ The `soothe` command provides both CLI and TUI interfaces:
49
+
50
+ ```bash
51
+ # Interactive TUI mode
52
+ soothe
53
+
54
+ # Headless single-prompt mode
55
+ soothe -p "Research AI advances"
56
+
57
+ # Thread management
58
+ soothe thread list
59
+ soothe thread continue abc123
60
+
61
+ # Configuration
62
+ soothe config show
63
+ ```
64
+
65
+ ## Architecture
66
+
67
+ This package is the **client** component that communicates with the Soothe daemon via WebSocket.
68
+
69
+ - **No direct dependencies on daemon runtime** - all communication through WebSocket
70
+ - **Lightweight dependencies** - only typer, textual, rich, and SDK
71
+ - **WebSocket-only transport** - bidirectional streaming protocol
72
+
73
+ ## Dependencies
74
+
75
+ - `soothe-sdk>=0.2.0` - WebSocket client, protocol, types
76
+ - `typer>=0.9.0` - CLI framework
77
+ - `textual>=0.40.0` - TUI framework
78
+ - `rich>=13.0.0` - Console output
79
+
80
+ ## Configuration
81
+
82
+ CLI uses `cli_config.yml`:
83
+
84
+ ```yaml
85
+ websocket:
86
+ host: "localhost"
87
+ port: 8765
88
+
89
+ ui:
90
+ verbosity: "normal"
91
+ format: "text"
92
+
93
+ tui:
94
+ theme: "default"
95
+ ```
96
+
97
+ ## Related Packages
98
+
99
+ - **soothe-daemon**: Server package (agent runtime)
100
+ - **soothe-sdk**: Shared SDK (WebSocket client, types)
@@ -0,0 +1,107 @@
1
+ soothe_cli/__init__.py,sha256=ri29gaUVXhd_y_z7if71ZaOIgrgqDFshsDKWYTQqZoA,103
2
+ soothe_cli/cli/__init__.py,sha256=XpdtQf6anT7IWEGQMbdIUVAK7MO-DrRccghhdWcBTE8,47
3
+ soothe_cli/cli/main.py,sha256=AOzMK5pqKSc-kuf0m8zR0gun47OyyUan8HjVcrPfXlM,15103
4
+ soothe_cli/cli/renderer.py,sha256=qjjRnZl1EdXO3sJD1xWLA7gpGN8L5ROhZNA8x-zYDdM,15528
5
+ soothe_cli/cli/utils.py,sha256=SZXwqe2Oy7pTbrBdoh3l3tFdycWEF09MgS0INnE9oz0,1198
6
+ soothe_cli/cli/commands/__init__.py,sha256=XpdtQf6anT7IWEGQMbdIUVAK7MO-DrRccghhdWcBTE8,47
7
+ soothe_cli/cli/commands/autopilot_cmd.py,sha256=BGm8CQo3Z8qQZUPOLf5KbncPQieMxzLRduV6DuID98k,12622
8
+ soothe_cli/cli/commands/config_cmd.py,sha256=BKaLBFOxUeFOtubx9rhqOhZCjBOZqbijRX_VHUmY8gQ,10459
9
+ soothe_cli/cli/commands/run_cmd.py,sha256=QKfoAiobnvR_xMNHp5WtD2rlW7XtdJENVi9nWnbqHDA,3022
10
+ soothe_cli/cli/commands/status_cmd.py,sha256=ca-M-O8lwqb6rZynth09r12uAtviqO_EJ__5kcTyqnU,3759
11
+ soothe_cli/cli/commands/subagent_names.py,sha256=YFBwIURGNBcitueUoXcfdsZzYsXfjfWgIrHLQ4qmEvw,441
12
+ soothe_cli/cli/commands/thread_cmd.py,sha256=wghgqxQ7RNPBKFXKoQdxYy71RaH-eFvdn1aY5-vJ5zM,22765
13
+ soothe_cli/cli/execution/__init__.py,sha256=bCBxWJ73vEkouKUimPQ5vd352KXZC-o4WFoVPpFJJww,200
14
+ soothe_cli/cli/execution/daemon.py,sha256=TmNO8T5T9LQ53cD-Jj9FkRPy0OCu_yw7GoE2oo1SCd4,7318
15
+ soothe_cli/cli/execution/headless.py,sha256=v07RUNY3zCIeygmhrfFZlP4QsE1i8E6RGNpYd9CjJFM,3347
16
+ soothe_cli/cli/execution/launcher.py,sha256=qlt2BPNhX3Zs0lPP9Z5advIEweMnce5ZJJFouEm3yeg,700
17
+ soothe_cli/cli/stream/__init__.py,sha256=6_zH3uorkhCXjlJZvjvgk0kK6V2Oi9-IAhDQCPwo5no,525
18
+ soothe_cli/cli/stream/context.py,sha256=0evmcTAnbAbZZCXcgSIOK179mP1IbxYI_a0iCrkY_dY,4536
19
+ soothe_cli/cli/stream/display_line.py,sha256=2d6_raNEd6YhNQbiGWzwtVWW9Q-FnjHCUppSwkrckWA,2503
20
+ soothe_cli/cli/stream/formatter.py,sha256=rLwvwRJdZsZfEhACmrR20dVryJl0QAWLuYQQIgvjlWA,11987
21
+ soothe_cli/cli/stream/pipeline.py,sha256=RnYdU_c_-20d70r8_08YRDTHgUAlqUSVBsTshA-30Rk,17212
22
+ soothe_cli/config/__init__.py,sha256=zH5ZustzRm6z1E9AK8wdr1As1smwduLC0uf8bU4gzfU,110
23
+ soothe_cli/config/cli_config.py,sha256=UFxUa6jUZzyXFhdAhQMdHZhqu68ODHIDoZ7sA-vUS8o,4952
24
+ soothe_cli/plan/__init__.py,sha256=Zx6H_w8eSOsMrLVmdAD7sckt_bL4fw4mtKmi2CrBbIc,132
25
+ soothe_cli/plan/rich_tree.py,sha256=T8OENigx82bEemPtDmK56ZuHZhXnZtlwFDo7VpxXOBY,1849
26
+ soothe_cli/shared/__init__.py,sha256=tyPWMdeAAOYNU3N6AsbQzEyBD8ObzseVTIm6xqoHf6U,3075
27
+ soothe_cli/shared/command_router.py,sha256=tws9FQlgEw_5wrClhAZanVEgw2ITcqBYGvR0yKnl6dA,7127
28
+ soothe_cli/shared/config_loader.py,sha256=BwAy5ll3IQL_3cKwcaXayXGKlOdzWxltktMp0tSkJZU,2062
29
+ soothe_cli/shared/display_policy.py,sha256=5PtFNmZ4sC-2ytJgCpyk-vOsXCOerTkqaF9ArGZ94qQ,14251
30
+ soothe_cli/shared/essential_events.py,sha256=ZDup4z_4cMxyUKXjYhKJgmEXCNvvVwugA6Antf0E6hk,1938
31
+ soothe_cli/shared/event_processor.py,sha256=q6vTxAo1pA_w0EtDy16QAU5vBD2OFOLXOuenTHOplIU,32213
32
+ soothe_cli/shared/message_processing.py,sha256=OOH6tG4JhVV4-tzxX9-jks1UgmjNz54lhG7bX_5bk0A,15069
33
+ soothe_cli/shared/presentation_engine.py,sha256=rBeYreEq-EkEXmrSJSM41BGY9ACWshxwNa4DwPPQvbI,5866
34
+ soothe_cli/shared/processor_state.py,sha256=40bn2_WQzm80WTri6cvpwEZSIfK29bkNZGnRuw8e4ck,2698
35
+ soothe_cli/shared/renderer_protocol.py,sha256=IyU5RZCWX6pHYJD2X9NTISKf79eS2KPKw7C7x3lWYFY,4191
36
+ soothe_cli/shared/rendering.py,sha256=cNr4iGymDKGEn69AyB8dEThuvBBKIUhVdueSVk9sSKQ,1441
37
+ soothe_cli/shared/slash_commands.py,sha256=s7auIXaZ5_gjY3XYQNilYzWZYJNlJwTEZlASWRcr-cE,11125
38
+ soothe_cli/shared/subagent_routing.py,sha256=Pyhfx71MwHOK_gm7O6DSFkyCa6HBU2lNu8t7fCT8QSI,2006
39
+ soothe_cli/shared/suppression_state.py,sha256=lyGYNQT_QiKbgPKFq5V8FqGSrQYupS9gKrCqnQQBYhs,6573
40
+ soothe_cli/shared/tool_output_formatter.py,sha256=kqi_L9jj6dKa0FnhCEb1dGyxnY1d1z0U9G1WoO78eos,7117
41
+ soothe_cli/shared/tui_trace_log.py,sha256=aQh2IQj96UcYmF2aSvEdFbzYAfRdVAeQe7Gr5KI47io,1258
42
+ soothe_cli/shared/tool_formatters/__init__.py,sha256=Qk9TM8QG-Rz492XsoEsAv4NJ1mFXKzyb04FzVTRFMPI,1032
43
+ soothe_cli/shared/tool_formatters/base.py,sha256=0GMk4YeqEsxJxfZEfD8SLAolB8mkmiWoWU-7s5tEx68,3173
44
+ soothe_cli/shared/tool_formatters/execution.py,sha256=Qz0ZyMxo4pYzF350mGj5YiWRp-YX3-WXOtubpftbLzw,9429
45
+ soothe_cli/shared/tool_formatters/fallback.py,sha256=_us2VVivkf7IU3M9-a2lOp39CHn4vpJzl1e4qIeuvmc,4520
46
+ soothe_cli/shared/tool_formatters/file_ops.py,sha256=Kc-oPxMgvNagZxl7H5kJDxw4m9k43Nk2y7odgN5NdJA,8930
47
+ soothe_cli/shared/tool_formatters/goal_formatter.py,sha256=lD-RZBR4IuktcN4XXYGwn65gha3jkplYy6AfehitLXk,10092
48
+ soothe_cli/shared/tool_formatters/media.py,sha256=qS9em8J2YKQwQYXdzQ1ddunGFn_LWah-hcQkXY9YwjA,9241
49
+ soothe_cli/shared/tool_formatters/structured.py,sha256=Uz6NikeqNtjAgKrvlXb2DdXcsatp1322ac1HisB3bcU,6412
50
+ soothe_cli/shared/tool_formatters/web.py,sha256=xei_c74pOyq5EcKCxQRvT6deAZaro-gaHF3gJzljHpA,4414
51
+ soothe_cli/tui/__init__.py,sha256=C_BXRLJB8lr_wq3MUDDU29ZyELQIua63eBOpNzDHVIc,135
52
+ soothe_cli/tui/_ask_user_types.py,sha256=MaNQ9V4t5RXMNAkYGKJ8ckzfsSbMcSS3DtkbDMOhSqI,1151
53
+ soothe_cli/tui/_cli_context.py,sha256=FSKtQavoTNIGI6KlGkmayIIIVLovNStxv72SrwqwrY4,783
54
+ soothe_cli/tui/_env_vars.py,sha256=jzCkew5bN1PfgJv9gUGx_M0N8FgjstHzVPQG_antVvc,2304
55
+ soothe_cli/tui/_session_stats.py,sha256=yfHDnAUUVuvihurM9mJ8gg9BvN28LEps-kpP-EWG324,4039
56
+ soothe_cli/tui/_version.py,sha256=T5ZQzEPjE2rqGggihqgDhvxcDcPGm_qIDgo137gDOng,676
57
+ soothe_cli/tui/app.py,sha256=F0fgehjGMqMyDW1Cf2PaZ345NBeW0mA1A0JYDrRsqbs,201711
58
+ soothe_cli/tui/app.tcss,sha256=j5TZyv_Jt-8WOCFEQJYuDhdtzxbLyG1doqakrB7GhDQ,5558
59
+ soothe_cli/tui/command_registry.py,sha256=8FKCf9-ftgyQ8DnYy_EbGkk9dUoFobbH8vxwhYVCeAM,9914
60
+ soothe_cli/tui/config.py,sha256=DaJqp8EQ-ndKZGFUtPjbxnGTmS4Kh_fpHLQwOsyTkNI,83266
61
+ soothe_cli/tui/daemon_session.py,sha256=yCuEsyQsvm6Ao9GaFsZJA1gPGGJNEOoX0tss6VbDqfg,9045
62
+ soothe_cli/tui/file_ops.py,sha256=lcdOiE0VE3aFSJzt77Aq_g10sX-b0R4XYle9VoHUups,14221
63
+ soothe_cli/tui/formatting.py,sha256=t02F18NBtVOL7bN0FybXop16oTMHPgZ7DCvK-txI80c,838
64
+ soothe_cli/tui/hooks.py,sha256=HR07UJg9Ff6U6flO6fd9MFr-QLni8AD12LApPBl6tS8,764
65
+ soothe_cli/tui/input.py,sha256=rjFksv3Y2aE6XQg8FBqWN-JFZ1m-temG71OZ_c_YK04,24335
66
+ soothe_cli/tui/media_utils.py,sha256=zASK7cagJNEdvYN34GuDyNPlkjExOyQu5DOMsjqfTFs,14771
67
+ soothe_cli/tui/model_config.py,sha256=VmD5wiZUWJAkeRHfHqFOcVYPn4p9aNFRwtVy_bZEQ80,16683
68
+ soothe_cli/tui/output.py,sha256=W8j1BleVaQ7M07nDRV9pgW4xSaRwlA5KfWyLtOeUrP0,2044
69
+ soothe_cli/tui/project_utils.py,sha256=8Clza2zFWk06o3rGfB2X5aygfIgqBy0cGed39DYMDes,5824
70
+ soothe_cli/tui/sessions.py,sha256=4oolnbJKLZDksIdsS9uE4mMSRhULMIXnetKW8Bp9ZkU,40921
71
+ soothe_cli/tui/textual_adapter.py,sha256=BIGsvHX9U-N5bOrMWNuwmdz76CWgTx3VDHPv25vLXEs,63594
72
+ soothe_cli/tui/theme.py,sha256=fDCPFCiKiGb09Tkeo2U_uxyKkgl06zeCWnNJ5tvf--A,27825
73
+ soothe_cli/tui/tool_display.py,sha256=fZBrCg3DTnQw_-7d-pYLVhJOC-wFKLa6S0dKM6eVCqw,11351
74
+ soothe_cli/tui/unicode_security.py,sha256=C0cswyga8LrNlExi2Sp9_IEkWkL-2gj23TqjebCNWlA,15961
75
+ soothe_cli/tui/update_check.py,sha256=V4Yv5xTF4bU2VeTNqTuYrQXqWeclQl1mYsXDi8llA9U,14359
76
+ soothe_cli/tui/skills/__init__.py,sha256=e01P8KbL8JuodwY2pN46J_Wt72RAM58zGezyzpvk7zw,229
77
+ soothe_cli/tui/skills/invocation.py,sha256=AowbjmQFSYf2U9ARPQQ6XaE4hm48-BX-IGKgrEp8NII,2407
78
+ soothe_cli/tui/skills/load.py,sha256=cejChCDQ5IWipd09agleMbyOEmtn6Glrkxl4tchpzzs,2967
79
+ soothe_cli/tui/widgets/__init__.py,sha256=NsdEqp9OEjPdj4ivNBcqo9zitsWSnxFlwxbelDWncww,223
80
+ soothe_cli/tui/widgets/_links.py,sha256=XdubfozXhfF8UZ46r0Hz_GAa0-OIn_hk6gd7pSK4JNs,2200
81
+ soothe_cli/tui/widgets/approval.py,sha256=9qJ6-D3tpV2CI7Om-l_R63BIvCRbhlid2o-N14Z6-Sk,16851
82
+ soothe_cli/tui/widgets/ask_user.py,sha256=3FTjiYWjHkpyiQ-oLMij4LIZ1o_HXWaaGbjoh4MgtNE,14685
83
+ soothe_cli/tui/widgets/autocomplete.py,sha256=qzr_jbM70AtEFSx7xLBv1uYFhJ6X8WttJZd_fHForEY,22966
84
+ soothe_cli/tui/widgets/autopilot_dashboard.py,sha256=wfA4OQcpDfFVmNr15MSzIXfYFPvMG0oOu3Ki4ZPdTTo,9033
85
+ soothe_cli/tui/widgets/autopilot_screen.py,sha256=Qd7-057kUyaoRzMQNPjVpJZfNW6OLcmot7s3j8jIs-4,1841
86
+ soothe_cli/tui/widgets/chat_input.py,sha256=7Bq0LyX-fqfC_lQRAtdD-5HMVQYUZPoQxLWbEXIWqdQ,69327
87
+ soothe_cli/tui/widgets/clipboard.py,sha256=pdukLQByFBPCh3c6X6UnOlbqRhpAwIVbQIuOqj0wiAU,3644
88
+ soothe_cli/tui/widgets/diff.py,sha256=qC6z2t9KFjweD_-LjMF4Zp_t7xLHDk_XYepPhXxn-8s,7588
89
+ soothe_cli/tui/widgets/editor.py,sha256=mXa_KnZ5llejtqrU9ltXr8dhph0Z7RgLrJ8422SYXbo,4020
90
+ soothe_cli/tui/widgets/history.py,sha256=5yMCKiT1qXecQEGZXhSwWVewJsvblPlxwQb2R_4g4LQ,7625
91
+ soothe_cli/tui/widgets/loading.py,sha256=Wdu__bOBsfIyQnOg4P5d8i-6YjFHjM0D_tvYXcD6V-o,5813
92
+ soothe_cli/tui/widgets/mcp_viewer.py,sha256=XHVUd-GnqUEmkU78iY99ujHUirJuHDtBmNhzUnetpF0,11529
93
+ soothe_cli/tui/widgets/message_store.py,sha256=Qw9lV7h2TWpE4a4LKx7cLiFf4P0usfEgXn4DDyV8o0M,22683
94
+ soothe_cli/tui/widgets/messages.py,sha256=JWwHFKNpbB_sPxBYa3n6USO1rhNjb3TaNmulJjdCna4,59846
95
+ soothe_cli/tui/widgets/model_selector.py,sha256=U7UevsLRclxSY8JTGnbKWlLHiN31_TI0tmMm9PQjDTQ,36218
96
+ soothe_cli/tui/widgets/notification_settings.py,sha256=nzDZuB71jyXKl4JoIGsqFla4ama3mBKdyQ-PRBR0B1o,4658
97
+ soothe_cli/tui/widgets/status.py,sha256=aWFVnhtv7CeMd5DwA1NbP9SamWOBZ8rPbzifqdmWF6M,12920
98
+ soothe_cli/tui/widgets/theme_selector.py,sha256=wp7gjy8fZmgZncTpaCnGF8aXdt2Kqm5jG4ku18J7ItI,5168
99
+ soothe_cli/tui/widgets/thread_selector.py,sha256=EjotQ38U-iPa2anDDP5rSlbUdiBUou37gzBWAcucxs8,65264
100
+ soothe_cli/tui/widgets/tool_renderers.py,sha256=o37bf44spAmQADwQmtougBDg7N1NSnxXeWdhV1TMFzU,4680
101
+ soothe_cli/tui/widgets/tool_widgets.py,sha256=soEjpGtkjoXAeszvYxo1brPPfQWjQ1JS3MwVjEn9yVs,9073
102
+ soothe_cli/tui/widgets/tools.py,sha256=tV5LCiXs6GBTTZmRCzBsxup7wdPUnGH01_jPIYzRisQ,5742
103
+ soothe_cli/tui/widgets/welcome.py,sha256=bVSlHMbClBW6-DxLCRWcA3GFMgJNaZPA6lT_8pMY3kU,11980
104
+ soothe_cli-0.1.0.dist-info/METADATA,sha256=dAYoSDQtsSJZ7HypvXQz4I_e6_x1tRj2llvplGiFvx4,2673
105
+ soothe_cli-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
106
+ soothe_cli-0.1.0.dist-info/entry_points.txt,sha256=nAROOtQ55Vyh8Di81BsUar5W_8VNEz4Yy6IYO4YL9XA,51
107
+ soothe_cli-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ soothe = soothe_cli.cli.main:app