soothe-cli 0.4.6__tar.gz → 0.4.7__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.
Files changed (127) hide show
  1. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/PKG-INFO +1 -1
  2. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/execution/daemon.py +2 -2
  3. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/execution/headless_renderer.py +1 -1
  4. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/stream/pipeline.py +2 -2
  5. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/core/processor_state.py +2 -4
  6. soothe_cli-0.4.7/src/soothe_cli/shared/tools/__init__.py +96 -0
  7. soothe_cli-0.4.7/src/soothe_cli/shared/tools/_utils.py +30 -0
  8. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_card_payload.py +2 -2
  9. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_formatters/execution.py +8 -14
  10. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_formatters/fallback.py +2 -2
  11. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_formatters/file_ops.py +11 -8
  12. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_formatters/goal_formatter.py +6 -5
  13. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_formatters/media.py +5 -4
  14. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_formatters/subagent.py +2 -2
  15. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_formatters/web.py +4 -3
  16. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_output_formatter.py +3 -2
  17. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/app.py +5 -5
  18. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/textual_adapter.py +15 -11
  19. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/tool_display.py +1 -1
  20. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/messages.py +2 -2
  21. soothe_cli-0.4.6/src/soothe_cli/shared/presentation_engine.py +0 -5
  22. soothe_cli-0.4.6/src/soothe_cli/shared/renderer_base.py +0 -5
  23. soothe_cli-0.4.6/src/soothe_cli/shared/stream_accumulator.py +0 -13
  24. soothe_cli-0.4.6/src/soothe_cli/shared/subagent_routing.py +0 -15
  25. soothe_cli-0.4.6/src/soothe_cli/shared/tools/__init__.py +0 -3
  26. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/.gitignore +0 -0
  27. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/README.md +0 -0
  28. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/pyproject.toml +0 -0
  29. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/__init__.py +0 -0
  30. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/__init__.py +0 -0
  31. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/commands/__init__.py +0 -0
  32. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/commands/autopilot_cmd.py +0 -0
  33. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/commands/loop_cmd.py +0 -0
  34. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/commands/run_cmd.py +0 -0
  35. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/commands/thread_cmd.py +0 -0
  36. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/execution/__init__.py +0 -0
  37. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/execution/headless.py +0 -0
  38. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/execution/launcher.py +0 -0
  39. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/main.py +0 -0
  40. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/stream/__init__.py +0 -0
  41. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/stream/context.py +0 -0
  42. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/stream/display_line.py +0 -0
  43. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/stream/formatter.py +0 -0
  44. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/cli/stream/task_scope.py +0 -0
  45. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/config/__init__.py +0 -0
  46. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/config/cli_config.py +0 -0
  47. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/plan/__init__.py +0 -0
  48. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/plan/rich_tree.py +0 -0
  49. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/__init__.py +0 -0
  50. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/commands/__init__.py +0 -0
  51. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/commands/command_router.py +0 -0
  52. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/commands/slash_commands.py +0 -0
  53. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/commands/subagent_routing.py +0 -0
  54. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/config_loader.py +0 -0
  55. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/core/__init__.py +0 -0
  56. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/core/event_processor.py +0 -0
  57. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/core/presentation_engine.py +0 -0
  58. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/core/renderer_protocol.py +0 -0
  59. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/events/__init__.py +0 -0
  60. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/events/display_policy.py +0 -0
  61. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/events/essential_events.py +0 -0
  62. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/events/explore_task_display.py +0 -0
  63. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/events/stream_accumulator.py +0 -0
  64. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/events/tui_trace_log.py +0 -0
  65. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/rendering/__init__.py +0 -0
  66. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/rendering/async_renderer_protocol.py +0 -0
  67. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/rendering/renderer_base.py +0 -0
  68. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/message_processing.py +0 -0
  69. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/rendering.py +0 -0
  70. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_call_resolution.py +0 -0
  71. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_card_visibility.py +0 -0
  72. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_formatters/__init__.py +0 -0
  73. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_formatters/base.py +0 -0
  74. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_formatters/structured.py +0 -0
  75. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/shared/tools/tool_message_format.py +0 -0
  76. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/__init__.py +0 -0
  77. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/_ask_user_types.py +0 -0
  78. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/_cli_context.py +0 -0
  79. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/_env_vars.py +0 -0
  80. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/_session_stats.py +0 -0
  81. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/_version.py +0 -0
  82. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/app.tcss +0 -0
  83. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/command_registry.py +0 -0
  84. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/config.py +0 -0
  85. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/daemon_session.py +0 -0
  86. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/file_ops.py +0 -0
  87. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/formatting.py +0 -0
  88. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/hooks.py +0 -0
  89. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/input.py +0 -0
  90. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/media_utils.py +0 -0
  91. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/message_display_filter.py +0 -0
  92. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/model_config.py +0 -0
  93. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/output.py +0 -0
  94. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/preview_limits.py +0 -0
  95. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/project_utils.py +0 -0
  96. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/sessions.py +0 -0
  97. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/skills/__init__.py +0 -0
  98. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/skills/invocation.py +0 -0
  99. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/skills/load.py +0 -0
  100. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/theme.py +0 -0
  101. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/unicode_security.py +0 -0
  102. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/update_check.py +0 -0
  103. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/__init__.py +0 -0
  104. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/_links.py +0 -0
  105. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/approval.py +0 -0
  106. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/ask_user.py +0 -0
  107. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/autocomplete.py +0 -0
  108. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/autopilot_dashboard.py +0 -0
  109. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/autopilot_screen.py +0 -0
  110. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/chat_input.py +0 -0
  111. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/clipboard.py +0 -0
  112. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/diff.py +0 -0
  113. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/editor.py +0 -0
  114. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/history.py +0 -0
  115. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/loading.py +0 -0
  116. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/loop_selector.py +0 -0
  117. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/mcp_viewer.py +0 -0
  118. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/message_store.py +0 -0
  119. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/model_selector.py +0 -0
  120. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/notification_settings.py +0 -0
  121. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/status.py +0 -0
  122. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/theme_selector.py +0 -0
  123. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/thread_selector.py +0 -0
  124. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/tool_renderers.py +0 -0
  125. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/tool_widgets.py +0 -0
  126. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/src/soothe_cli/tui/widgets/tools.py +0 -0
  127. {soothe_cli-0.4.6 → soothe_cli-0.4.7}/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.4.6
3
+ Version: 0.4.7
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
@@ -20,8 +20,8 @@ from soothe_sdk.client import (
20
20
 
21
21
  from soothe_cli.cli.execution.headless_renderer import HeadlessCliRenderer
22
22
  from soothe_cli.shared import EventProcessor
23
- from soothe_cli.shared.presentation_engine import PresentationEngine
24
- from soothe_cli.shared.subagent_routing import parse_subagent_from_input
23
+ from soothe_cli.shared.commands.subagent_routing import parse_subagent_from_input
24
+ from soothe_cli.shared.core.presentation_engine import PresentationEngine
25
25
 
26
26
  logger = logging.getLogger(__name__)
27
27
 
@@ -12,7 +12,7 @@ from typing import Any
12
12
 
13
13
  from rich.console import Console
14
14
 
15
- from soothe_cli.shared.renderer_base import RendererBase
15
+ from soothe_cli.shared.rendering.renderer_base import RendererBase
16
16
 
17
17
 
18
18
  class HeadlessCliRenderer(RendererBase):
@@ -30,13 +30,13 @@ from soothe_cli.cli.stream.formatter import (
30
30
  format_subagent_done,
31
31
  format_subagent_milestone,
32
32
  )
33
- from soothe_cli.shared.essential_events import (
33
+ from soothe_cli.shared.core.presentation_engine import PresentationEngine
34
+ from soothe_cli.shared.events.essential_events import (
34
35
  LOOP_REASON_EVENT_TYPE,
35
36
  is_goal_start_event_type,
36
37
  is_step_complete_event_type,
37
38
  is_step_start_event_type,
38
39
  )
39
- from soothe_cli.shared.presentation_engine import PresentationEngine
40
40
 
41
41
  logger = logging.getLogger(__name__)
42
42
 
@@ -13,7 +13,7 @@ from typing import TYPE_CHECKING, Any
13
13
  if TYPE_CHECKING:
14
14
  from soothe_sdk.client.schemas import Plan
15
15
 
16
- from soothe_cli.shared.events.stream_accumulator import StreamingTextAccumulator
16
+ from soothe_cli.shared.events.stream_accumulator import StreamingTextAccumulator
17
17
 
18
18
 
19
19
  @dataclass
@@ -56,9 +56,7 @@ class ProcessorState:
56
56
 
57
57
  # Unified streaming text accumulator (RFC-614)
58
58
  streaming_accumulator: StreamingTextAccumulator = field(
59
- default_factory=lambda: __import__(
60
- "soothe_cli.shared.stream_accumulator", fromlist=["StreamingTextAccumulator"]
61
- ).StreamingTextAccumulator()
59
+ default_factory=StreamingTextAccumulator
62
60
  )
63
61
  """Unified streaming text accumulator with namespace isolation."""
64
62
 
@@ -0,0 +1,96 @@
1
+ """Tool call/result handling utilities."""
2
+
3
+ from soothe_cli.shared.tools.message_processing import (
4
+ accumulate_tool_call_chunks,
5
+ coerce_tool_call_args_to_dict,
6
+ extract_tool_args_dict,
7
+ extract_tool_brief,
8
+ finalize_pending_tool_call,
9
+ format_tool_call_args,
10
+ normalize_tool_calls_list,
11
+ strip_internal_tags,
12
+ tool_calls_have_any_arg_dict,
13
+ try_parse_pending_tool_call_args,
14
+ )
15
+ from soothe_cli.shared.tools.rendering import update_name_map_from_tool_calls
16
+ from soothe_cli.shared.tools.tool_call_resolution import (
17
+ build_streaming_args_overlay,
18
+ infer_tool_name_from_call_id,
19
+ materialize_ai_blocks_with_resolved_tools,
20
+ tool_args_meaningful,
21
+ )
22
+ from soothe_cli.shared.tools.tool_card_payload import (
23
+ ToolResultCardPayload,
24
+ extract_tool_result_card_payload,
25
+ infer_tool_output_suggests_error,
26
+ )
27
+ from soothe_cli.shared.tools.tool_card_visibility import (
28
+ should_elide_completed_tool_call_message,
29
+ should_elide_stream_tool_card_mount,
30
+ should_elide_tool_card_no_info,
31
+ )
32
+ from soothe_cli.shared.tools.tool_formatters import (
33
+ BaseFormatter,
34
+ ExecutionFormatter,
35
+ FallbackFormatter,
36
+ FileOpsFormatter,
37
+ GoalFormatter,
38
+ MediaFormatter,
39
+ StructuredFormatter,
40
+ SubagentFormatter,
41
+ WebFormatter,
42
+ )
43
+ from soothe_cli.shared.tools.tool_message_format import (
44
+ format_content_block_for_tool_display,
45
+ format_tool_message_content,
46
+ run_python_envelope_indicates_failure,
47
+ try_parse_run_python_result_envelope,
48
+ )
49
+ from soothe_cli.shared.tools.tool_output_formatter import ToolBrief, ToolOutputFormatter
50
+
51
+ __all__ = [
52
+ # Message processing
53
+ "accumulate_tool_call_chunks",
54
+ "coerce_tool_call_args_to_dict",
55
+ "extract_tool_args_dict",
56
+ "extract_tool_brief",
57
+ "finalize_pending_tool_call",
58
+ "format_tool_call_args",
59
+ "normalize_tool_calls_list",
60
+ "strip_internal_tags",
61
+ "tool_calls_have_any_arg_dict",
62
+ "try_parse_pending_tool_call_args",
63
+ # Rendering
64
+ "update_name_map_from_tool_calls",
65
+ # Tool call resolution
66
+ "build_streaming_args_overlay",
67
+ "infer_tool_name_from_call_id",
68
+ "materialize_ai_blocks_with_resolved_tools",
69
+ "tool_args_meaningful",
70
+ # Tool card payload
71
+ "ToolResultCardPayload",
72
+ "extract_tool_result_card_payload",
73
+ "infer_tool_output_suggests_error",
74
+ # Tool card visibility
75
+ "should_elide_completed_tool_call_message",
76
+ "should_elide_stream_tool_card_mount",
77
+ "should_elide_tool_card_no_info",
78
+ # Tool message format
79
+ "format_content_block_for_tool_display",
80
+ "format_tool_message_content",
81
+ "run_python_envelope_indicates_failure",
82
+ "try_parse_run_python_result_envelope",
83
+ # Formatter
84
+ "ToolBrief",
85
+ "ToolOutputFormatter",
86
+ # Formatters
87
+ "BaseFormatter",
88
+ "ExecutionFormatter",
89
+ "FallbackFormatter",
90
+ "FileOpsFormatter",
91
+ "GoalFormatter",
92
+ "MediaFormatter",
93
+ "SubagentFormatter",
94
+ "StructuredFormatter",
95
+ "WebFormatter",
96
+ ]
@@ -0,0 +1,30 @@
1
+ """Internal utilities for tool formatting (not part of public API)."""
2
+
3
+
4
+ def normalize_tool_name(tool_name: str) -> str:
5
+ """Normalize tool name to snake_case for comparison and lookup.
6
+
7
+ Args:
8
+ tool_name: Raw tool name (may contain dashes or spaces).
9
+
10
+ Returns:
11
+ Lowercase snake_case name.
12
+ """
13
+ return tool_name.lower().replace("-", "_").replace(" ", "_")
14
+
15
+
16
+ def text_looks_like_error(text: str) -> bool:
17
+ """Return True if text content suggests a tool failure.
18
+
19
+ Checks for common error indicator substrings.
20
+
21
+ Args:
22
+ text: Tool output text to inspect.
23
+
24
+ Returns:
25
+ True if any error indicator is found.
26
+ """
27
+ if not text:
28
+ return False
29
+ lowered = text.lower()
30
+ return any(indicator in lowered for indicator in ("error", "failed", "exception", "traceback"))
@@ -13,6 +13,7 @@ from collections.abc import Mapping
13
13
  from dataclasses import dataclass
14
14
  from typing import Any
15
15
 
16
+ from soothe_cli.shared.tools._utils import text_looks_like_error
16
17
  from soothe_cli.shared.tools.tool_call_resolution import infer_tool_name_from_call_id
17
18
  from soothe_cli.shared.tools.tool_message_format import (
18
19
  format_tool_message_content,
@@ -38,8 +39,7 @@ def infer_tool_output_suggests_error(output_display: str, _tool_name: str = "")
38
39
 
39
40
  if not output_display:
40
41
  return False
41
- lowered = output_display.lower()
42
- return any(indicator in lowered for indicator in ("error", "failed", "exception", "traceback"))
42
+ return text_looks_like_error(output_display)
43
43
 
44
44
 
45
45
  @dataclass(frozen=True, slots=True)
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  from typing import Any
6
6
 
7
+ from soothe_cli.shared.tools._utils import normalize_tool_name, text_looks_like_error
7
8
  from soothe_cli.shared.tools.tool_formatters.base import BaseFormatter
8
9
  from soothe_cli.shared.tools.tool_message_format import try_parse_run_python_result_envelope
9
10
  from soothe_cli.shared.tools.tool_output_formatter import ToolBrief
@@ -37,10 +38,11 @@ class ExecutionFormatter(BaseFormatter):
37
38
  '✓ Done'
38
39
  """
39
40
  # Normalize tool name
40
- normalized = tool_name.lower().replace("-", "_").replace(" ", "_")
41
+ normalized = normalize_tool_name(tool_name)
41
42
 
42
43
  # Route to specific formatter
43
- if normalized == "run_command":
44
+ # execute/shell/bash are aliases of run_command (per TOOL_REGISTRY)
45
+ if normalized in ("run_command", "execute", "shell", "bash"):
44
46
  return self._format_run_command(result)
45
47
  if normalized == "run_python":
46
48
  return self._format_run_python(result)
@@ -83,9 +85,7 @@ class ExecutionFormatter(BaseFormatter):
83
85
  )
84
86
 
85
87
  # Check for other error patterns
86
- error_indicators = ["failed:", "exception:", "traceback", "command not found"]
87
- result_lower = result.lower()
88
- if any(indicator in result_lower for indicator in error_indicators):
88
+ if text_looks_like_error(result):
89
89
  # Extract first line as error message
90
90
  first_line = result.partition("\n")[0].strip()
91
91
  return ToolBrief(
@@ -170,13 +170,7 @@ class ExecutionFormatter(BaseFormatter):
170
170
 
171
171
  # Handle string result (fallback — not the standard run_python JSON envelope)
172
172
  if isinstance(result, str):
173
- lowered = result.lower()
174
- if (
175
- "traceback" in lowered
176
- or "exception:" in lowered
177
- or "failed:" in lowered
178
- or result.startswith("Error:")
179
- ):
173
+ if text_looks_like_error(result) or result.startswith("Error:"):
180
174
  return ToolBrief(
181
175
  icon="✗",
182
176
  summary="Execution failed",
@@ -240,7 +234,7 @@ class ExecutionFormatter(BaseFormatter):
240
234
 
241
235
  # Handle string result (fallback)
242
236
  if isinstance(result, str):
243
- if "error" in result.lower() or "failed" in result.lower():
237
+ if text_looks_like_error(result):
244
238
  return ToolBrief(
245
239
  icon="✗",
246
240
  summary="Start failed",
@@ -280,7 +274,7 @@ class ExecutionFormatter(BaseFormatter):
280
274
  'Terminated PID 12345'
281
275
  """
282
276
  # Check for error
283
- if "error" in result.lower() or "failed" in result.lower() or "not found" in result.lower():
277
+ if text_looks_like_error(result) or "not found" in result.lower():
284
278
  return ToolBrief(
285
279
  icon="✗",
286
280
  summary="Termination failed",
@@ -6,6 +6,7 @@ from typing import Any
6
6
 
7
7
  from soothe_sdk.client.protocol import preview_first
8
8
 
9
+ from soothe_cli.shared.tools._utils import text_looks_like_error
9
10
  from soothe_cli.shared.tools.tool_formatters.base import BaseFormatter
10
11
  from soothe_cli.shared.tools.tool_output_formatter import ToolBrief
11
12
 
@@ -40,8 +41,7 @@ class FallbackFormatter(BaseFormatter):
40
41
  # Handle string results
41
42
  if isinstance(result, str):
42
43
  # Check for error indicators
43
- error_indicators = ["error:", "failed:", "exception:", "traceback"]
44
- is_error = any(indicator in result.lower() for indicator in error_indicators)
44
+ is_error = text_looks_like_error(result)
45
45
 
46
46
  if is_error:
47
47
  # Extract error message (first line or first 80 chars)
@@ -5,6 +5,7 @@ from __future__ import annotations
5
5
  import re
6
6
  from typing import Any
7
7
 
8
+ from soothe_cli.shared.tools._utils import normalize_tool_name, text_looks_like_error
8
9
  from soothe_cli.shared.tools.tool_formatters.base import BaseFormatter
9
10
  from soothe_cli.shared.tools.tool_output_formatter import ToolBrief
10
11
 
@@ -38,7 +39,7 @@ class FileOpsFormatter(BaseFormatter):
38
39
  '✓ Read 12 B (2 lines)'
39
40
  """
40
41
  # Normalize tool name
41
- normalized = tool_name.lower().replace("-", "_").replace(" ", "_")
42
+ normalized = normalize_tool_name(tool_name)
42
43
 
43
44
  # Route to specific formatter
44
45
  if normalized == "read_file":
@@ -159,7 +160,7 @@ class FileOpsFormatter(BaseFormatter):
159
160
  'Wrote 0 B'
160
161
  """
161
162
  # Check for error
162
- if "error" in result.lower() or "failed" in result.lower():
163
+ if text_looks_like_error(result):
163
164
  return ToolBrief(
164
165
  icon="✗",
165
166
  summary="Write failed",
@@ -194,7 +195,7 @@ class FileOpsFormatter(BaseFormatter):
194
195
  'Deleted'
195
196
  """
196
197
  # Check for error
197
- if "error" in result.lower() or "failed" in result.lower():
198
+ if text_looks_like_error(result):
198
199
  return ToolBrief(
199
200
  icon="✗",
200
201
  summary="Delete failed",
@@ -226,7 +227,7 @@ class FileOpsFormatter(BaseFormatter):
226
227
  'Found 3 items'
227
228
  """
228
229
  # Check for error
229
- if "error" in result.lower() or "failed" in result.lower():
230
+ if text_looks_like_error(result):
230
231
  return ToolBrief(
231
232
  icon="✗",
232
233
  summary="List failed",
@@ -265,7 +266,7 @@ class FileOpsFormatter(BaseFormatter):
265
266
  'Found 2 matches'
266
267
  """
267
268
  # Check for error
268
- if "error" in result.lower() or "failed" in result.lower():
269
+ if text_looks_like_error(result):
269
270
  return ToolBrief(
270
271
  icon="✗",
271
272
  summary="Search failed",
@@ -311,12 +312,14 @@ class FileOpsFormatter(BaseFormatter):
311
312
  >>> brief.summary
312
313
  'Found 2 files'
313
314
  """
314
- # Check for error
315
- if "error" in result.lower() or "failed" in result.lower():
315
+ # Check for actual error message (not file paths containing error-like words)
316
+ # Glob results are newline-separated paths; errors start with "Error:"
317
+ if result.startswith("Error:"):
318
+ error_msg = result[6:].strip()
316
319
  return ToolBrief(
317
320
  icon="✗",
318
321
  summary="Glob failed",
319
- detail=self._truncate_text(result, 80),
322
+ detail=self._truncate_text(error_msg, 80),
320
323
  metrics={"error": True},
321
324
  )
322
325
 
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  from typing import Any
6
6
 
7
+ from soothe_cli.shared.tools._utils import normalize_tool_name, text_looks_like_error
7
8
  from soothe_cli.shared.tools.tool_formatters.base import BaseFormatter
8
9
  from soothe_cli.shared.tools.tool_output_formatter import ToolBrief
9
10
 
@@ -36,7 +37,7 @@ class GoalFormatter(BaseFormatter):
36
37
  '✓ Created goal g1'
37
38
  """
38
39
  # Normalize tool name
39
- normalized = tool_name.lower().replace("-", "_").replace(" ", "_")
40
+ normalized = normalize_tool_name(tool_name)
40
41
 
41
42
  # Route to specific formatter
42
43
  if normalized == "create_goal":
@@ -100,7 +101,7 @@ class GoalFormatter(BaseFormatter):
100
101
 
101
102
  # Handle string result (fallback)
102
103
  if isinstance(result, str):
103
- if "error" in result.lower() or "failed" in result.lower():
104
+ if text_looks_like_error(result):
104
105
  return ToolBrief(
105
106
  icon="✗",
106
107
  summary="Create failed",
@@ -167,7 +168,7 @@ class GoalFormatter(BaseFormatter):
167
168
 
168
169
  # Handle string result (fallback)
169
170
  if isinstance(result, str):
170
- if "error" in result.lower() or "failed" in result.lower():
171
+ if text_looks_like_error(result):
171
172
  return ToolBrief(
172
173
  icon="✗",
173
174
  summary="List failed",
@@ -234,7 +235,7 @@ class GoalFormatter(BaseFormatter):
234
235
 
235
236
  # Handle string result (fallback)
236
237
  if isinstance(result, str):
237
- if "error" in result.lower() or "failed" in result.lower():
238
+ if text_looks_like_error(result):
238
239
  return ToolBrief(
239
240
  icon="✗",
240
241
  summary="Complete failed",
@@ -307,7 +308,7 @@ class GoalFormatter(BaseFormatter):
307
308
 
308
309
  # Handle string result (fallback)
309
310
  if isinstance(result, str):
310
- if "error" in result.lower() or "failed" in result.lower():
311
+ if text_looks_like_error(result):
311
312
  return ToolBrief(
312
313
  icon="✗",
313
314
  summary="Fail operation failed",
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  from typing import Any
6
6
 
7
+ from soothe_cli.shared.tools._utils import normalize_tool_name, text_looks_like_error
7
8
  from soothe_cli.shared.tools.tool_formatters.base import BaseFormatter
8
9
  from soothe_cli.shared.tools.tool_output_formatter import ToolBrief
9
10
 
@@ -36,7 +37,7 @@ class MediaFormatter(BaseFormatter):
36
37
  '✓ Transcribed 45.2s (en)'
37
38
  """
38
39
  # Normalize tool name
39
- normalized = tool_name.lower().replace("-", "_").replace(" ", "_")
40
+ normalized = normalize_tool_name(tool_name)
40
41
 
41
42
  # Route to specific formatter
42
43
  if normalized == "transcribe_audio":
@@ -104,7 +105,7 @@ class MediaFormatter(BaseFormatter):
104
105
 
105
106
  # Handle string result (fallback)
106
107
  if isinstance(result, str):
107
- if "error" in result.lower() or "failed" in result.lower():
108
+ if text_looks_like_error(result):
108
109
  return ToolBrief(
109
110
  icon="✗",
110
111
  summary="Transcription failed",
@@ -182,7 +183,7 @@ class MediaFormatter(BaseFormatter):
182
183
 
183
184
  # Handle string result (fallback)
184
185
  if isinstance(result, str):
185
- if "error" in result.lower() or "failed" in result.lower():
186
+ if text_looks_like_error(result):
186
187
  return ToolBrief(
187
188
  icon="✗",
188
189
  summary="Video info failed",
@@ -267,7 +268,7 @@ class MediaFormatter(BaseFormatter):
267
268
 
268
269
  # Handle string result (fallback)
269
270
  if isinstance(result, str):
270
- if "error" in result.lower() or "failed" in result.lower():
271
+ if text_looks_like_error(result):
271
272
  return ToolBrief(
272
273
  icon="✗",
273
274
  summary="Image analysis failed",
@@ -7,6 +7,7 @@ from __future__ import annotations
7
7
 
8
8
  from typing import Any
9
9
 
10
+ from soothe_cli.shared.tools._utils import text_looks_like_error
10
11
  from soothe_cli.shared.tools.tool_formatters.base import BaseFormatter
11
12
  from soothe_cli.shared.tools.tool_output_formatter import ToolBrief
12
13
 
@@ -36,8 +37,7 @@ class SubagentFormatter(BaseFormatter):
36
37
  # Handle string results
37
38
  if isinstance(result, str):
38
39
  # Check for error indicators
39
- error_indicators = ["error:", "failed:", "exception:", "traceback"]
40
- is_error = any(indicator in result.lower() for indicator in error_indicators)
40
+ is_error = text_looks_like_error(result)
41
41
 
42
42
  if is_error:
43
43
  # Extract first line of error
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  from typing import Any
6
6
 
7
+ from soothe_cli.shared.tools._utils import normalize_tool_name, text_looks_like_error
7
8
  from soothe_cli.shared.tools.tool_formatters.base import BaseFormatter
8
9
  from soothe_cli.shared.tools.tool_output_formatter import ToolBrief
9
10
 
@@ -36,7 +37,7 @@ class WebFormatter(BaseFormatter):
36
37
  'Found 2 results'
37
38
  """
38
39
  # Normalize tool name
39
- normalized = tool_name.lower().replace("-", "_").replace(" ", "_")
40
+ normalized = normalize_tool_name(tool_name)
40
41
 
41
42
  # Route to specific formatter (handle both legacy and wizsearch naming)
42
43
  if normalized in ("search_web", "wizsearch_search"):
@@ -64,7 +65,7 @@ class WebFormatter(BaseFormatter):
64
65
  'Found 2 results'
65
66
  """
66
67
  # Check for error
67
- if "error" in result.lower() or "failed" in result.lower():
68
+ if text_looks_like_error(result):
68
69
  return ToolBrief(
69
70
  icon="✗",
70
71
  summary="Search failed",
@@ -114,7 +115,7 @@ class WebFormatter(BaseFormatter):
114
115
  '450 words'
115
116
  """
116
117
  # Check for error
117
- if "error" in result.lower() or "failed" in result.lower():
118
+ if text_looks_like_error(result):
118
119
  return ToolBrief(
119
120
  icon="✗",
120
121
  summary="Crawl failed",
@@ -12,6 +12,8 @@ from typing import Any
12
12
 
13
13
  from soothe_sdk.utils import get_tool_categories
14
14
 
15
+ from soothe_cli.shared.tools._utils import normalize_tool_name
16
+
15
17
  logger = logging.getLogger(__name__)
16
18
 
17
19
 
@@ -82,8 +84,7 @@ def classify_tool(tool_name: str) -> str:
82
84
  >>> classify_tool("unknown_tool")
83
85
  'unknown'
84
86
  """
85
- # Normalize tool name to snake_case (handle variations)
86
- normalized = tool_name.lower().replace("-", "_").replace(" ", "_")
87
+ normalized = normalize_tool_name(tool_name)
87
88
 
88
89
  # Look up in category mapping
89
90
  return TOOL_CATEGORIES.get(normalized, "unknown")
@@ -30,7 +30,7 @@ from textual.style import Style as TStyle
30
30
  from textual.theme import Theme
31
31
  from textual.widgets import Static
32
32
 
33
- from soothe_cli.shared.tool_card_payload import extract_tool_result_card_payload
33
+ from soothe_cli.shared.tools.tool_card_payload import extract_tool_result_card_payload
34
34
  from soothe_cli.tui import theme
35
35
  from soothe_cli.tui._cli_context import CLIContext
36
36
  from soothe_cli.tui._session_stats import (
@@ -2657,11 +2657,11 @@ class SootheApp(App):
2657
2657
  Args:
2658
2658
  command: The slash command (including /)
2659
2659
  """
2660
- from soothe_cli.shared.command_router import (
2660
+ from soothe_cli.shared.commands.command_router import (
2661
2661
  parse_slash_command,
2662
2662
  validate_command,
2663
2663
  )
2664
- from soothe_cli.shared.slash_commands import COMMANDS as _RFC404_COMMANDS
2664
+ from soothe_cli.shared.commands.slash_commands import COMMANDS as _RFC404_COMMANDS
2665
2665
 
2666
2666
  # RFC-404 daemon *routing* commands (/browser, /claude, /research, /plan):
2667
2667
  # send the full line as a normal user turn so ``parse_subagent_from_input``
@@ -3221,7 +3221,7 @@ class SootheApp(App):
3221
3221
  """
3222
3222
  from langchain_core.messages import AIMessage, ToolMessage
3223
3223
 
3224
- from soothe_cli.shared.message_processing import (
3224
+ from soothe_cli.shared.tools.message_processing import (
3225
3225
  extract_tool_args_dict,
3226
3226
  normalize_tool_calls_list,
3227
3227
  )
@@ -3899,7 +3899,7 @@ class SootheApp(App):
3899
3899
  from langchain_core.messages import AIMessage, AIMessageChunk, ToolMessage
3900
3900
 
3901
3901
  from soothe_cli.cli.stream.pipeline import StreamDisplayPipeline
3902
- from soothe_cli.shared.message_processing import extract_tool_args_dict
3902
+ from soothe_cli.shared.tools.message_processing import extract_tool_args_dict
3903
3903
 
3904
3904
  progress_pipeline = StreamDisplayPipeline()
3905
3905
  tool_cards: dict[str, ToolCallMessage] = {}
@@ -56,21 +56,21 @@ from soothe_sdk.ux.task_namespace import (
56
56
  )
57
57
 
58
58
  from soothe_cli.cli.stream.display_line import DisplayLine
59
- from soothe_cli.shared.essential_events import (
59
+ from soothe_cli.shared.commands.subagent_routing import parse_subagent_from_input
60
+ from soothe_cli.shared.core.presentation_engine import PresentationEngine
61
+ from soothe_cli.shared.events.essential_events import (
60
62
  LOOP_REASON_EVENT_TYPE,
61
63
  is_essential_progress_event_type,
62
64
  )
63
- from soothe_cli.shared.message_processing import (
65
+ from soothe_cli.shared.rendering.renderer_base import RendererBase
66
+ from soothe_cli.shared.tools.message_processing import (
64
67
  accumulate_tool_call_chunks,
65
68
  extract_tool_args_dict,
66
69
  format_tool_call_args,
67
70
  )
68
- from soothe_cli.shared.presentation_engine import PresentationEngine
69
- from soothe_cli.shared.renderer_base import RendererBase
70
- from soothe_cli.shared.subagent_routing import parse_subagent_from_input
71
- from soothe_cli.shared.tool_call_resolution import build_streaming_args_overlay
72
- from soothe_cli.shared.tool_card_payload import extract_tool_result_card_payload
73
- from soothe_cli.shared.tool_card_visibility import (
71
+ from soothe_cli.shared.tools.tool_call_resolution import build_streaming_args_overlay
72
+ from soothe_cli.shared.tools.tool_card_payload import extract_tool_result_card_payload
73
+ from soothe_cli.shared.tools.tool_card_visibility import (
74
74
  should_elide_completed_tool_call_message,
75
75
  should_elide_stream_tool_card_mount,
76
76
  should_elide_tool_card_no_info,
@@ -307,7 +307,7 @@ def _raw_tool_content_for_presentation(message: Any) -> str:
307
307
  """Serialize tool message body for ``PresentationEngine.format_tool_result_status_line``."""
308
308
  from langchain_core.messages import ToolMessage
309
309
 
310
- from soothe_cli.shared.tool_message_format import format_tool_message_content
310
+ from soothe_cli.shared.tools.tool_message_format import format_tool_message_content
311
311
 
312
312
  if isinstance(message, ToolMessage):
313
313
  return format_tool_message_content(getattr(message, "content", ""))
@@ -661,7 +661,9 @@ def _tui_effective_ai_blocks(
661
661
  """
662
662
  from langchain_core.messages import AIMessage, AIMessageChunk
663
663
 
664
- from soothe_cli.shared.tool_call_resolution import materialize_ai_blocks_with_resolved_tools
664
+ from soothe_cli.shared.tools.tool_call_resolution import (
665
+ materialize_ai_blocks_with_resolved_tools,
666
+ )
665
667
 
666
668
  message = _coerce_ai_message_for_blocks(message)
667
669
  if not isinstance(message, (AIMessage, AIMessageChunk)):
@@ -2331,7 +2333,9 @@ async def _flush_assistant_text_ns(
2331
2333
  If no message exists yet, creates one with the full content.
2332
2334
  """
2333
2335
  from soothe_cli.cli.stream.task_scope import format_task_scope_prefix
2334
- from soothe_cli.shared.explore_task_display import format_explore_task_json_blob_for_display
2336
+ from soothe_cli.shared.events.explore_task_display import (
2337
+ format_explore_task_json_blob_for_display,
2338
+ )
2335
2339
 
2336
2340
  repaired_text = RendererBase.repair_concatenated_output(text)
2337
2341
  repaired_text = format_explore_task_json_blob_for_display(repaired_text)
@@ -12,7 +12,7 @@ from typing import Any
12
12
 
13
13
  from soothe_sdk.utils import get_all_path_arg_keys, get_tool_display_name, get_tool_meta
14
14
 
15
- from soothe_cli.shared.message_processing import (
15
+ from soothe_cli.shared.tools.message_processing import (
16
16
  _normalize_tool_name_for_arg_map,
17
17
  extract_tool_args_dict,
18
18
  format_tool_call_args,
@@ -18,8 +18,8 @@ from textual.events import Click
18
18
  from textual.reactive import var
19
19
  from textual.widgets import Static
20
20
 
21
- from soothe_cli.shared.presentation_engine import PresentationEngine
22
- from soothe_cli.shared.tool_call_resolution import infer_tool_name_from_call_id
21
+ from soothe_cli.shared.core.presentation_engine import PresentationEngine
22
+ from soothe_cli.shared.tools.tool_call_resolution import infer_tool_name_from_call_id
23
23
  from soothe_cli.tui import theme
24
24
  from soothe_cli.tui.config import (
25
25
  MODE_DISPLAY_GLYPHS,
@@ -1,5 +0,0 @@
1
- """Compatibility re-export (IG-351); implementation in ``core.presentation_engine``."""
2
-
3
- from soothe_cli.shared.core.presentation_engine import PresentationEngine
4
-
5
- __all__ = ["PresentationEngine"]
@@ -1,5 +0,0 @@
1
- """Compatibility re-export (IG-351); implementation in ``rendering.renderer_base``."""
2
-
3
- from soothe_cli.shared.rendering.renderer_base import RendererBase
4
-
5
- __all__ = ["RendererBase"]
@@ -1,13 +0,0 @@
1
- """Compatibility re-export (IG-351); implementation in ``events.stream_accumulator``."""
2
-
3
- from soothe_cli.shared.events.stream_accumulator import (
4
- StreamAccumulator,
5
- StreamingAccumState,
6
- StreamingTextAccumulator,
7
- )
8
-
9
- __all__ = [
10
- "StreamAccumulator",
11
- "StreamingAccumState",
12
- "StreamingTextAccumulator",
13
- ]
@@ -1,15 +0,0 @@
1
- """Compatibility re-export (IG-351). Implementation lives in ``commands.subagent_routing``."""
2
-
3
- from soothe_cli.shared.commands.subagent_routing import (
4
- BUILTIN_SUBAGENT_NAMES,
5
- SUBAGENT_DISPLAY_NAMES,
6
- get_subagent_display_name,
7
- parse_subagent_from_input,
8
- )
9
-
10
- __all__ = [
11
- "BUILTIN_SUBAGENT_NAMES",
12
- "SUBAGENT_DISPLAY_NAMES",
13
- "get_subagent_display_name",
14
- "parse_subagent_from_input",
15
- ]
@@ -1,3 +0,0 @@
1
- """Tool call/result handling utilities (submodules: message_processing, rendering, ...)."""
2
-
3
- __all__: list[str] = []
File without changes
File without changes
File without changes