soothe-cli 0.9.4__tar.gz → 0.9.6__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 (132) hide show
  1. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/PKG-INFO +1 -1
  2. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/commands/loop_cmd.py +12 -16
  3. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/headless/processor.py +7 -7
  4. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/parse/tool_call_resolution.py +11 -13
  5. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/engine.py +1 -1
  6. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/state/step_router.py +3 -3
  7. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/turn/prepare.py +6 -6
  8. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/_version.py +0 -19
  9. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_execution.py +9 -4
  10. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_messages_mixin.py +4 -8
  11. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/binding.py +1 -1
  12. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/command_registry.py +5 -2
  13. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/commands/slash_commands.py +1 -1
  14. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/sessions.py +2 -3
  15. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/textual_adapter.py +7 -7
  16. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/tips.py +1 -1
  17. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/tool_display.py +4 -4
  18. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/update_check.py +16 -17
  19. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/help_screen.py +1 -1
  20. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/message_store.py +4 -3
  21. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/cognition_step.py +3 -2
  22. soothe_cli-0.9.4/src/soothe_cli/runtime/parse/message_processing.py +0 -45
  23. soothe_cli-0.9.4/src/soothe_cli/runtime/parse/tool_result.py +0 -15
  24. soothe_cli-0.9.4/src/soothe_cli/runtime/state/transcript.py +0 -24
  25. soothe_cli-0.9.4/src/soothe_cli/runtime/turn/pipeline.py +0 -35
  26. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/.gitignore +0 -0
  27. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/README.md +0 -0
  28. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/pyproject.toml +0 -0
  29. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/__init__.py +0 -0
  30. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/__init__.py +0 -0
  31. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/commands/__init__.py +0 -0
  32. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/commands/autopilot_cmd.py +0 -0
  33. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/commands/config_cmd.py +0 -0
  34. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/commands/cron_cmd.py +0 -0
  35. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/commands/run_cmd.py +0 -0
  36. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/commands/status_cmd.py +0 -0
  37. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/execution/__init__.py +0 -0
  38. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/execution/daemon.py +0 -0
  39. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/execution/daemon_errors.py +0 -0
  40. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/execution/headless.py +0 -0
  41. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/execution/headless_renderer.py +0 -0
  42. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/execution/launcher.py +0 -0
  43. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/main.py +0 -0
  44. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/config/__init__.py +0 -0
  45. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/config/cli_config.py +0 -0
  46. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/config/loader.py +0 -0
  47. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/config/logging_setup.py +0 -0
  48. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/__init__.py +0 -0
  49. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/headless/processor_state.py +0 -0
  50. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/policy/display_policy.py +0 -0
  51. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/policy/essential_events.py +0 -0
  52. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/policy/tui_trace_log.py +0 -0
  53. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/duration_format.py +0 -0
  54. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/id_format.py +0 -0
  55. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/renderer_base.py +0 -0
  56. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/renderer_protocol.py +0 -0
  57. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/subagent_task_display.py +0 -0
  58. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/state/file_tracker.py +0 -0
  59. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/state/session_stats.py +0 -0
  60. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/state/stream_accumulator.py +0 -0
  61. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/token_events_debug.py +0 -0
  62. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/token_usage.py +0 -0
  63. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/transport/session.py +0 -0
  64. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/wire/chunk_filter.py +0 -0
  65. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/wire/message_text.py +0 -0
  66. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/wire/messages.py +0 -0
  67. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/__init__.py +0 -0
  68. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/_cli_context.py +0 -0
  69. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/_env_vars.py +0 -0
  70. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/__init__.py +0 -0
  71. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_app.py +0 -0
  72. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_history.py +0 -0
  73. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_model.py +0 -0
  74. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_module_init.py +0 -0
  75. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_startup.py +0 -0
  76. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_ui.py +0 -0
  77. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/app.tcss +0 -0
  78. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/commands/__init__.py +0 -0
  79. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/commands/command_router.py +0 -0
  80. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/commands/subagent_routing.py +0 -0
  81. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/config.py +0 -0
  82. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/file_change_notify.py +0 -0
  83. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/file_change_renderers.py +0 -0
  84. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/hooks.py +0 -0
  85. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/input.py +0 -0
  86. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/markdown_theme.py +0 -0
  87. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/media_utils.py +0 -0
  88. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/model_config.py +0 -0
  89. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/path_utils.py +0 -0
  90. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/preview_limits.py +0 -0
  91. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/project_utils.py +0 -0
  92. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/shell_color.py +0 -0
  93. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/skills/__init__.py +0 -0
  94. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/skills/invocation.py +0 -0
  95. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/skills/load.py +0 -0
  96. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/spinner_labels.py +0 -0
  97. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/theme.py +0 -0
  98. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/unicode_security.py +0 -0
  99. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/__init__.py +0 -0
  100. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/_links.py +0 -0
  101. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/autocomplete.py +0 -0
  102. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/chat_input.py +0 -0
  103. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/clipboard.py +0 -0
  104. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/context_data.py +0 -0
  105. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/context_viewer.py +0 -0
  106. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/diff.py +0 -0
  107. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/editor.py +0 -0
  108. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/file_change_preview.py +0 -0
  109. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/history.py +0 -0
  110. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/loading.py +0 -0
  111. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/loop_selector.py +0 -0
  112. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/mcp_viewer.py +0 -0
  113. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/__init__.py +0 -0
  114. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/_helpers.py +0 -0
  115. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/app.py +0 -0
  116. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/assistant.py +0 -0
  117. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/clarification.py +0 -0
  118. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/cognition_goal_tree.py +0 -0
  119. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/cognition_reason.py +0 -0
  120. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/cognition_step_activity.py +0 -0
  121. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/cognition_subagent.py +0 -0
  122. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/diff_message.py +0 -0
  123. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/error.py +0 -0
  124. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/skill.py +0 -0
  125. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/user.py +0 -0
  126. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/model_selector.py +0 -0
  127. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/notification_settings.py +0 -0
  128. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/plan_quick_view_overlay.py +0 -0
  129. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/router_profile_selector.py +0 -0
  130. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/status.py +0 -0
  131. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/theme_selector.py +0 -0
  132. {soothe_cli-0.9.4 → soothe_cli-0.9.6}/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.9.4
3
+ Version: 0.9.6
4
4
  Summary: Soothe CLI client - communicates with daemon via WebSocket
5
5
  Project-URL: Homepage, https://github.com/mirasoth/soothe
6
6
  Project-URL: Documentation, https://soothe.readthedocs.io
@@ -46,10 +46,6 @@ async def _check_daemon(ws_url: str) -> bool:
46
46
  return await is_daemon_live(ws_url, timeout=5.0)
47
47
 
48
48
 
49
- # Back-compat alias for tests and internal callers.
50
- _rpc = protocol1_rpc
51
-
52
-
53
49
  def _resolve_continue_loop_id(ws_url: str, loop_id: str | None) -> str:
54
50
  """Resolve target loop ID for `loop continue`.
55
51
 
@@ -60,7 +56,7 @@ def _resolve_continue_loop_id(ws_url: str, loop_id: str | None) -> str:
60
56
  return loop_id
61
57
 
62
58
  response = asyncio.run(
63
- _rpc(
59
+ protocol1_rpc(
64
60
  ws_url,
65
61
  "loop_list",
66
62
  {"limit": 20},
@@ -121,7 +117,7 @@ def list_loops(
121
117
  _require_daemon(ws_url)
122
118
 
123
119
  response = asyncio.run(
124
- _rpc(
120
+ protocol1_rpc(
125
121
  ws_url,
126
122
  "loop_list",
127
123
  {"filter": {"status": status} if status else None, "limit": limit},
@@ -178,7 +174,7 @@ def describe_loop(
178
174
  _require_daemon(ws_url)
179
175
 
180
176
  response = asyncio.run(
181
- _rpc(
177
+ protocol1_rpc(
182
178
  ws_url,
183
179
  "loop_get",
184
180
  {"loop_id": loop_id, "verbose": verbose},
@@ -293,7 +289,7 @@ def visualize_loop_tree(
293
289
  _require_daemon(ws_url)
294
290
 
295
291
  response = asyncio.run(
296
- _rpc(
292
+ protocol1_rpc(
297
293
  ws_url,
298
294
  "loop_tree",
299
295
  {"loop_id": loop_id, "format": format},
@@ -349,7 +345,7 @@ def prune_loop_branches(
349
345
  _require_daemon(ws_url)
350
346
 
351
347
  response = asyncio.run(
352
- _rpc(
348
+ protocol1_rpc(
353
349
  ws_url,
354
350
  "loop_prune",
355
351
  {"loop_id": loop_id, "retention_days": retention_days, "dry_run": dry_run},
@@ -391,7 +387,7 @@ def delete_loop(
391
387
 
392
388
  # Get loop metadata for confirmation
393
389
  response = asyncio.run(
394
- _rpc(
390
+ protocol1_rpc(
395
391
  ws_url,
396
392
  "loop_get",
397
393
  {"loop_id": loop_id, "verbose": False},
@@ -422,7 +418,7 @@ def delete_loop(
422
418
 
423
419
  # Delete loop
424
420
  delete_response = asyncio.run(
425
- _rpc(
421
+ protocol1_rpc(
426
422
  ws_url,
427
423
  "loop_delete",
428
424
  {"loop_id": loop_id},
@@ -705,7 +701,7 @@ def detach_loop(
705
701
  _require_daemon(ws_url)
706
702
 
707
703
  response = asyncio.run(
708
- _rpc(
704
+ protocol1_rpc(
709
705
  ws_url,
710
706
  "loop_detach",
711
707
  {"loop_id": loop_id},
@@ -743,7 +739,7 @@ def attach_loop(
743
739
 
744
740
  # Subscribe to loop (same as continue)
745
741
  response = asyncio.run(
746
- _rpc(
742
+ protocol1_rpc(
747
743
  ws_url,
748
744
  "loop_events",
749
745
  {"loop_id": loop_id},
@@ -759,7 +755,7 @@ def attach_loop(
759
755
 
760
756
  # Show reattachment status
761
757
  status_response = asyncio.run(
762
- _rpc(
758
+ protocol1_rpc(
763
759
  ws_url,
764
760
  "loop_get",
765
761
  {"loop_id": loop_id, "verbose": False},
@@ -800,7 +796,7 @@ def new_loop(
800
796
 
801
797
  # Create new loop
802
798
  response = asyncio.run(
803
- _rpc(
799
+ protocol1_rpc(
804
800
  ws_url,
805
801
  "loop_new",
806
802
  {},
@@ -817,7 +813,7 @@ def new_loop(
817
813
  # Execute prompt if provided
818
814
  if prompt:
819
815
  input_response = asyncio.run(
820
- _rpc(
816
+ protocol1_rpc(
821
817
  ws_url,
822
818
  "loop_input",
823
819
  {"loop_id": loop_id, "content": prompt},
@@ -12,12 +12,7 @@ from typing import TYPE_CHECKING, Any
12
12
  from langchain_core.messages import AIMessage, AIMessageChunk, ToolMessage
13
13
  from soothe_sdk.core.events import PLAN_CREATED
14
14
  from soothe_sdk.core.verbosity import VerbosityTier
15
- from soothe_sdk.ux import classify_event_to_tier
16
- from soothe_sdk.ux.loop_stream import LOOP_ASSISTANT_OUTPUT_PHASES, assistant_output_phase
17
- from soothe_sdk.ux.task_namespace import resolve_task_scope_for_namespace
18
-
19
- from soothe_cli.runtime.headless.processor_state import ProcessorState
20
- from soothe_cli.runtime.parse.message_processing import (
15
+ from soothe_sdk.display.message_processing import (
21
16
  accumulate_tool_call_chunks,
22
17
  extract_tool_args_dict,
23
18
  extract_tool_brief,
@@ -26,10 +21,15 @@ from soothe_cli.runtime.parse.message_processing import (
26
21
  tool_calls_have_any_arg_dict,
27
22
  try_parse_pending_tool_call_args,
28
23
  )
29
- from soothe_cli.runtime.parse.tool_result import (
24
+ from soothe_sdk.display.tool_result import (
30
25
  extract_tool_result_payload,
31
26
  infer_tool_output_suggests_error,
32
27
  )
28
+ from soothe_sdk.ux import classify_event_to_tier
29
+ from soothe_sdk.ux.loop_stream import LOOP_ASSISTANT_OUTPUT_PHASES, assistant_output_phase
30
+ from soothe_sdk.ux.task_namespace import resolve_task_scope_for_namespace
31
+
32
+ from soothe_cli.runtime.headless.processor_state import ProcessorState
33
33
  from soothe_cli.runtime.policy.display_policy import DisplayPolicy
34
34
  from soothe_cli.runtime.policy.tui_trace_log import log_tui_trace
35
35
  from soothe_cli.runtime.presentation.engine import PresentationEngine
@@ -17,6 +17,11 @@ from collections.abc import Mapping
17
17
  from dataclasses import dataclass
18
18
  from typing import Any
19
19
 
20
+ from soothe_sdk.display.message_processing import (
21
+ extract_tool_args_dict,
22
+ normalize_tool_calls_list,
23
+ try_parse_pending_tool_call_args,
24
+ )
20
25
  from soothe_sdk.ux.execute_namespace import (
21
26
  is_root_execute_namespace_key,
22
27
  is_step_level_execute_namespace_key,
@@ -27,12 +32,6 @@ from soothe_sdk.ux.task_namespace import (
27
32
  row_key_for_subgraph_tool,
28
33
  )
29
34
 
30
- from soothe_cli.runtime.parse.message_processing import (
31
- extract_tool_args_dict,
32
- normalize_tool_calls_list,
33
- try_parse_pending_tool_call_args,
34
- )
35
-
36
35
  logger = logging.getLogger(__name__)
37
36
 
38
37
 
@@ -247,13 +246,13 @@ def merge_tool_display_args(
247
246
  if isinstance(raw, dict):
248
247
  stream_args = dict(raw)
249
248
  if not stream_args:
250
- from soothe_cli.runtime.parse.message_processing import (
249
+ from soothe_sdk.display.message_processing import (
251
250
  _resolve_pending_lookup_tool_name,
252
251
  )
253
252
 
254
253
  lookup_name = _resolve_pending_lookup_tool_name(tcid, tool_name=tool_name)
255
254
  if lookup_name and pending_tool_calls_lc:
256
- from soothe_cli.runtime.parse.message_processing import (
255
+ from soothe_sdk.display.message_processing import (
257
256
  _pending_or_overlay_id_matches_lookup,
258
257
  )
259
258
 
@@ -275,7 +274,7 @@ def merge_tool_display_args(
275
274
  stream_args = best
276
275
  pend_parsed: dict[str, Any] = {}
277
276
  if tcid and pending_tool_calls_lc:
278
- from soothe_cli.runtime.parse.message_processing import richest_pending_args_for_lookup
277
+ from soothe_sdk.display.message_processing import richest_pending_args_for_lookup
279
278
 
280
279
  pend_parsed = richest_pending_args_for_lookup(
281
280
  pending_tool_calls_lc,
@@ -294,7 +293,7 @@ def merge_tool_display_args(
294
293
  message_args = extract_tool_args_dict(tc)
295
294
  break
296
295
  if not message_args:
297
- from soothe_cli.runtime.parse.message_processing import (
296
+ from soothe_sdk.display.message_processing import (
298
297
  _resolve_pending_lookup_tool_name,
299
298
  )
300
299
 
@@ -306,7 +305,7 @@ def merge_tool_display_args(
306
305
  if len(matches) == 1:
307
306
  message_args = extract_tool_args_dict(matches[0])
308
307
  elif matches:
309
- from soothe_cli.runtime.parse.message_processing import (
308
+ from soothe_sdk.display.message_processing import (
310
309
  _pending_or_overlay_id_matches_lookup,
311
310
  )
312
311
 
@@ -524,8 +523,7 @@ def build_streaming_args_overlay(
524
523
  Otherwise every pending entry is considered (legacy / final flush).
525
524
  """
526
525
  from langchain_core.messages import AIMessageChunk
527
-
528
- from soothe_cli.runtime.parse.message_processing import tool_ids_touched_by_stream_message
526
+ from soothe_sdk.display.message_processing import tool_ids_touched_by_stream_message
529
527
 
530
528
  overlay: dict[str, dict[str, Any]] = {}
531
529
  chunk_pos = getattr(message, "chunk_position", None)
@@ -143,7 +143,7 @@ class PresentationEngine:
143
143
  Returns:
144
144
  Plain-text status line (may already start with a status icon from brief).
145
145
  """
146
- from soothe_cli.runtime.parse.message_processing import extract_tool_brief
146
+ from soothe_sdk.display.message_processing import extract_tool_brief
147
147
 
148
148
  brief = extract_tool_brief(tool_name, raw_content)
149
149
  summarized = self.summarize_tool_result(brief)
@@ -146,7 +146,7 @@ class StepTaskRouter:
146
146
  self._pending_subgraph_tools[key] = item
147
147
  return
148
148
  # Prefer meaningful args over placeholder metadata like {"_subgraph_tool": true}.
149
- from soothe_cli.runtime.parse.message_processing import extract_tool_args_dict
149
+ from soothe_sdk.display.message_processing import extract_tool_args_dict
150
150
 
151
151
  item_meaningful = extract_tool_args_dict(item.args or {})
152
152
  existing_meaningful = extract_tool_args_dict(existing.args or {})
@@ -521,7 +521,7 @@ class StepTaskRouter:
521
521
  resolved_args = dict(item.args or {})
522
522
  # Placeholder args like {"_subgraph_tool": true} are not meaningful.
523
523
  # Parse raw_args when resolved_args lacks real invocation kwargs.
524
- from soothe_cli.runtime.parse.message_processing import extract_tool_args_dict
524
+ from soothe_sdk.display.message_processing import extract_tool_args_dict
525
525
 
526
526
  meaningful_args = extract_tool_args_dict(resolved_args)
527
527
  if item.raw_args and not meaningful_args:
@@ -531,7 +531,7 @@ class StepTaskRouter:
531
531
  update(row_id, resolved_args)
532
532
  else:
533
533
  resolved_args = dict(item.args or {})
534
- from soothe_cli.runtime.parse.message_processing import extract_tool_args_dict
534
+ from soothe_sdk.display.message_processing import extract_tool_args_dict
535
535
 
536
536
  meaningful_args = extract_tool_args_dict(resolved_args)
537
537
  if item.raw_args and not meaningful_args:
@@ -10,6 +10,12 @@ from dataclasses import dataclass
10
10
  from typing import Any
11
11
 
12
12
  from langchain_core.messages import ToolMessage
13
+ from soothe_client.appkit.turn import (
14
+ PRIORITY_CRITICAL,
15
+ PRIORITY_HIGH,
16
+ PRIORITY_LOW,
17
+ PRIORITY_NORMAL,
18
+ )
13
19
  from soothe_sdk.core.events import (
14
20
  STRANGE_LOOP_COMPLETED,
15
21
  STRANGE_LOOP_PLAN_DECISION,
@@ -24,12 +30,6 @@ from soothe_sdk.ux.stream_tool_wire import STREAM_TOOL_CALL_UPDATE, TOOL_CALL_UP
24
30
 
25
31
  from soothe_cli.runtime.presentation.engine import PresentationEngine
26
32
  from soothe_cli.runtime.state.session_stats import TurnEventStats
27
- from soothe_cli.runtime.turn.pipeline import (
28
- PRIORITY_CRITICAL,
29
- PRIORITY_HIGH,
30
- PRIORITY_LOW,
31
- PRIORITY_NORMAL,
32
- )
33
33
  from soothe_cli.runtime.wire.chunk_filter import (
34
34
  message_has_tool_invocation_metadata,
35
35
  updates_chunk_is_noop,
@@ -94,25 +94,6 @@ def is_editable_install() -> bool:
94
94
  return bool(_editable_source_roots())
95
95
 
96
96
 
97
- def editable_install_display_path() -> str | None:
98
- """Return a ``~``-contracted source path for editable installs."""
99
- roots = _editable_source_roots()
100
- if not roots:
101
- return None
102
-
103
- install_root = roots[0]
104
- for root in roots:
105
- if root.name == "soothe-cli":
106
- install_root = root
107
- break
108
-
109
- path = str(install_root)
110
- home = str(Path.home())
111
- if path.startswith(home):
112
- return "~" + path[len(home) :]
113
- return path
114
-
115
-
116
97
  __version__ = _resolve_version()
117
98
 
118
99
  DOCS_URL = "https://github.com/mirasoth/soothe/docs"
@@ -150,10 +150,15 @@ class _ExecutionMixin:
150
150
 
151
151
  await dispatch_hook("user.prompt", {})
152
152
 
153
- # /quit and /q always execute immediately, even mid-loop-switch.
154
- from soothe_cli.tui.command_registry import ALWAYS_IMMEDIATE
153
+ # /quit, /q, /exit, and bare exit/quit always execute immediately,
154
+ # even mid-loop-switch or while the agent is busy.
155
+ from soothe_cli.tui.command_registry import ALWAYS_IMMEDIATE, BARE_QUIT_WORDS
155
156
 
156
- if mode == "command" and value.lower().strip() in ALWAYS_IMMEDIATE:
157
+ stripped = value.lower().strip()
158
+ if mode == "command" and stripped in ALWAYS_IMMEDIATE:
159
+ self._detach_or_exit()
160
+ return
161
+ if mode == "normal" and stripped in BARE_QUIT_WORDS:
157
162
  self._detach_or_exit()
158
163
  return
159
164
 
@@ -491,7 +496,7 @@ class _ExecutionMixin:
491
496
  cmd = command.lower().strip()
492
497
  cmd_head = resolve_command_head(command)
493
498
 
494
- if cmd in {"/quit", "/q"}:
499
+ if cmd_head == "/quit":
495
500
  self._detach_or_exit()
496
501
  elif cmd == "/help":
497
502
  await self._show_help_screen()
@@ -559,7 +559,7 @@ class _MessagesMixin:
559
559
  1. If input has pending text, clear it (first Ctrl+C)
560
560
  2. If input is empty, interrupt the running task
561
561
 
562
- When idle, Ctrl+C never exits the TUI. Use `/quit` (or `/q`) to exit.
562
+ When idle, Ctrl+C never exits the TUI. Type `exit`, `quit`, or `/quit` to exit.
563
563
 
564
564
  Note: Copying selected text is bound to Ctrl+Y (`action_copy_selection`)
565
565
  so Ctrl+C is reserved for interrupt behavior.
@@ -586,7 +586,7 @@ class _MessagesMixin:
586
586
  # Idle path: clear any pending draft, but never quit via keyboard shortcut.
587
587
  if self._chat_input:
588
588
  self._chat_input.clear_input()
589
- self.notify("Use /quit (or /q) to exit the TUI", timeout=2, markup=False)
589
+ self.notify("Type exit, quit, or /quit to exit the TUI", timeout=2, markup=False)
590
590
 
591
591
  def action_dismiss_ui(self) -> None:
592
592
  """Handle Escape — dismiss overlays and optionally cancel queued goals.
@@ -636,13 +636,9 @@ class _MessagesMixin:
636
636
  if self._chat_input.exit_mode():
637
637
  return
638
638
 
639
- def action_interrupt(self) -> None:
640
- """Backward-compatible alias for :meth:`action_dismiss_ui`."""
641
- self.action_dismiss_ui()
642
-
643
639
  def action_quit_app(self) -> None:
644
- """Handle Ctrl+D by hinting explicit slash-command exit."""
645
- self.notify("Use /quit (or /q) to exit the TUI", timeout=2, markup=False)
640
+ """Handle Ctrl+D by hinting explicit exit words or slash quit."""
641
+ self.notify("Type exit, quit, or /quit to exit the TUI", timeout=2, markup=False)
646
642
 
647
643
  async def _detach_then_exit(self) -> None:
648
644
  """Detach from daemon, then exit the app."""
@@ -7,7 +7,7 @@ import logging
7
7
  import uuid
8
8
  from typing import TYPE_CHECKING, Any
9
9
 
10
- from soothe_cli.runtime.state.transcript import MessageData, MessageType
10
+ from soothe_sdk.display.transcript_types import MessageData, MessageType
11
11
 
12
12
  if TYPE_CHECKING:
13
13
  from textual.widget import Widget
@@ -191,10 +191,10 @@ COMMANDS: tuple[SlashCommand, ...] = (
191
191
  ),
192
192
  SlashCommand(
193
193
  name="/quit",
194
- description="Exit app",
194
+ description="Exit app (also: exit, quit)",
195
195
  bypass_tier=BypassTier.ALWAYS,
196
196
  hidden_keywords="close leave",
197
- aliases=("/q",),
197
+ aliases=("/q", "/exit"),
198
198
  ),
199
199
  )
200
200
  """All slash commands."""
@@ -248,6 +248,9 @@ def _build_bypass_set(tier: BypassTier) -> frozenset[str]:
248
248
  ALWAYS_IMMEDIATE: frozenset[str] = _build_bypass_set(BypassTier.ALWAYS)
249
249
  """Commands that execute regardless of any busy state."""
250
250
 
251
+ BARE_QUIT_WORDS: frozenset[str] = frozenset({"exit", "quit"})
252
+ """Single-word normal-mode input that exits the TUI (no leading slash)."""
253
+
251
254
  BYPASS_WHEN_CONNECTING: frozenset[str] = _build_bypass_set(BypassTier.CONNECTING)
252
255
  """Commands that bypass only during initial server connection."""
253
256
 
@@ -154,7 +154,7 @@ def show_cron_add(console: Console, data: dict[str, Any]) -> None:
154
154
 
155
155
  KEYBOARD_SHORTCUTS: dict[str, str] = {
156
156
  "Esc": "Dismiss modal, plan overlay, or autocomplete",
157
- "Ctrl+D": "Use /quit (or /q) to exit the TUI",
157
+ "Ctrl+D": "Type exit, quit, or /quit to exit the TUI",
158
158
  "Ctrl+C": "Clear input or interrupt running agent/shell",
159
159
  "Ctrl+X": "Open prompt in external editor ($VISUAL/$EDITOR)",
160
160
  "Ctrl+Y": "Copy selected text to clipboard (or show hint if none)",
@@ -253,15 +253,14 @@ async def list_loops_via_daemon_rpc(
253
253
  def get_loop_limit() -> int:
254
254
  """Default maximum loops to load for `/resume` when no explicit limit is set.
255
255
 
256
- Reads ``DA_CLI_RECENT_LOOPS``, then the legacy alias ``DA_CLI_RECENT_THREADS``,
257
- then defaults to ``20``.
256
+ Reads ``DA_CLI_RECENT_LOOPS``, then defaults to ``20``.
258
257
 
259
258
  Returns:
260
259
  A positive integer (falls back to ``20`` when unset or invalid).
261
260
  """
262
261
  import os
263
262
 
264
- raw = os.environ.get("DA_CLI_RECENT_LOOPS") or os.environ.get("DA_CLI_RECENT_THREADS", "20")
263
+ raw = os.environ.get("DA_CLI_RECENT_LOOPS", "20")
265
264
  try:
266
265
  n = int(str(raw).strip(), 10)
267
266
  except ValueError:
@@ -46,6 +46,7 @@ if TYPE_CHECKING:
46
46
 
47
47
 
48
48
  from langchain_core.messages import AIMessage, HumanMessage
49
+ from soothe_client.appkit.turn import run_turn_pipeline
49
50
  from soothe_sdk.core.events import (
50
51
  LOOP_CLARIFICATION_ANSWERED,
51
52
  LOOP_CLARIFICATION_DEFERRED,
@@ -67,6 +68,12 @@ from soothe_sdk.core.subagent_wire import (
67
68
  is_allowlisted_subagent_event_type,
68
69
  parse_subagent_wire_agent,
69
70
  )
71
+ from soothe_sdk.display.message_processing import (
72
+ extract_tool_args_dict,
73
+ ingest_tool_call_stream_state,
74
+ tool_ids_touched_by_stream_message,
75
+ )
76
+ from soothe_sdk.display.tool_result import extract_tool_result_payload
70
77
  from soothe_sdk.ux.loop_stream import (
71
78
  LOOP_ASSISTANT_OUTPUT_PHASES,
72
79
  assistant_output_phase,
@@ -91,11 +98,6 @@ from soothe_sdk.wire.codec import (
91
98
  messages_from_wire_dicts,
92
99
  )
93
100
 
94
- from soothe_cli.runtime.parse.message_processing import (
95
- extract_tool_args_dict,
96
- ingest_tool_call_stream_state,
97
- tool_ids_touched_by_stream_message,
98
- )
99
101
  from soothe_cli.runtime.parse.tool_call_resolution import (
100
102
  build_streaming_args_overlay,
101
103
  is_step_card_tool_scope,
@@ -107,7 +109,6 @@ from soothe_cli.runtime.parse.tool_call_resolution import (
107
109
  should_ingest_tool_for_step_stats,
108
110
  tool_args_meaningful,
109
111
  )
110
- from soothe_cli.runtime.parse.tool_result import extract_tool_result_payload
111
112
  from soothe_cli.runtime.policy.essential_events import (
112
113
  INTENT_CLASSIFIED_EVENT_TYPE,
113
114
  LOOP_REASON_EVENT_TYPE,
@@ -140,7 +141,6 @@ from soothe_cli.runtime.token_usage import (
140
141
  extract_stream_message_token_usage,
141
142
  fetch_conversation_token_count,
142
143
  )
143
- from soothe_cli.runtime.turn.pipeline import run_turn_pipeline
144
144
  from soothe_cli.runtime.turn.prepare import (
145
145
  PreparedTurnChunk,
146
146
  TurnPrepareState,
@@ -7,7 +7,7 @@ import random
7
7
  SESSION_TIPS: list[str] = [
8
8
  "Use @ to reference files and / for commands",
9
9
  "Try /resume to pick up a previous StrangeLoop instance",
10
- "Use /quit (or /q) to exit TUI; use /resume to continue a previous loop",
10
+ "Type exit, quit, or /quit to exit TUI; use /resume to continue a previous loop",
11
11
  "Use /context to check token usage and goal status",
12
12
  "Use /mcp to see your loaded tools and servers",
13
13
  "Use /model to switch models mid-conversation",
@@ -5,15 +5,15 @@ from __future__ import annotations
5
5
  import json
6
6
  from typing import Any
7
7
 
8
+ from soothe_sdk.display.message_processing import (
9
+ _normalize_tool_name_for_arg_map,
10
+ extract_tool_args_dict,
11
+ )
8
12
  from soothe_sdk.tools.metadata import get_tool_meta
9
13
  from soothe_sdk.utils import get_tool_display_name
10
14
  from soothe_sdk.utils.formatting import convert_and_abbreviate_path
11
15
  from soothe_sdk.wire.protocol import preview_first
12
16
 
13
- from soothe_cli.runtime.parse.message_processing import (
14
- _normalize_tool_name_for_arg_map,
15
- extract_tool_args_dict,
16
- )
17
17
  from soothe_cli.runtime.presentation.duration_format import format_duration_ms
18
18
 
19
19
  _ARG_PREVIEW_MAX_CHARS = 80
@@ -319,15 +319,15 @@ async def perform_upgrade() -> tuple[bool, str]:
319
319
  def is_update_check_enabled() -> bool:
320
320
  """Return whether startup update checks are enabled.
321
321
 
322
- Disabled when `SOOTHE_CLI_NO_UPDATE_CHECK` or legacy `SOOTHE_NO_UPDATE_CHECK`
323
- is set. When `SOOTHE_CLI_UPDATE_CHECK` is ``1``/``true``/``yes``, checks are
322
+ Disabled when ``SOOTHE_CLI_NO_UPDATE_CHECK`` is set. When
323
+ ``SOOTHE_CLI_UPDATE_CHECK`` is ``1``/``true``/``yes``, checks are
324
324
  enabled (including when ``[update].check: false`` would otherwise turn them
325
325
  off). Otherwise, respects ``[update].check`` in ``cli.yml`` when
326
326
  present; defaults to on. Use ``/update`` to check manually any time.
327
327
  """
328
328
  from soothe_cli.tui._env_vars import NO_UPDATE_CHECK, UPDATE_CHECK
329
329
 
330
- if os.environ.get("SOOTHE_NO_UPDATE_CHECK") or os.environ.get(NO_UPDATE_CHECK):
330
+ if os.environ.get(NO_UPDATE_CHECK):
331
331
  return False
332
332
  if os.environ.get(UPDATE_CHECK, "").lower() in {"1", "true", "yes"}:
333
333
  return True
@@ -340,20 +340,19 @@ def is_update_check_enabled() -> bool:
340
340
  def _auto_update_env_override() -> bool | None:
341
341
  """Return env-forced auto-update flag, or ``None`` if unset.
342
342
 
343
- ``SOOTHE_CLI_AUTO_UPDATE`` (and legacy ``SOOTHE_AUTO_UPDATE``) may be
344
- ``1``/``true``/``yes`` to force on or ``0``/``false``/``no`` to force off.
343
+ ``SOOTHE_CLI_AUTO_UPDATE`` may be ``1``/``true``/``yes`` to force on or
344
+ ``0``/``false``/``no`` to to force off.
345
345
  """
346
346
  from soothe_cli.tui._env_vars import AUTO_UPDATE
347
347
 
348
- for key in (AUTO_UPDATE, "SOOTHE_AUTO_UPDATE"):
349
- raw = os.environ.get(key)
350
- if raw is None or not str(raw).strip():
351
- continue
352
- lv = str(raw).strip().lower()
353
- if lv in {"1", "true", "yes"}:
354
- return True
355
- if lv in {"0", "false", "no"}:
356
- return False
348
+ raw = os.environ.get(AUTO_UPDATE)
349
+ if raw is None or not str(raw).strip():
350
+ return None
351
+ lv = str(raw).strip().lower()
352
+ if lv in {"1", "true", "yes"}:
353
+ return True
354
+ if lv in {"0", "false", "no"}:
355
+ return False
357
356
  return None
358
357
 
359
358
 
@@ -362,9 +361,9 @@ def is_auto_update_enabled() -> bool:
362
361
 
363
362
  Always disabled for editable installs.
364
363
 
365
- Otherwise, ``SOOTHE_CLI_AUTO_UPDATE`` (or legacy ``SOOTHE_AUTO_UPDATE``)
366
- forces on or off when set. When unset, ``[update].auto_update`` in
367
- ``cli.yml`` is used if present; defaults to on.
364
+ Otherwise, ``SOOTHE_CLI_AUTO_UPDATE`` forces on or off when set. When
365
+ unset, ``[update].auto_update`` in ``cli.yml`` is used if present;
366
+ defaults to on.
368
367
  """
369
368
  from soothe_cli.tui.config import _is_editable_install
370
369
 
@@ -55,7 +55,7 @@ def build_keyboard_shortcut_rows() -> list[tuple[str, str]]:
55
55
  "Insert newline in the chat input",
56
56
  ),
57
57
  ("Esc", "Dismiss modal, plan overlay, or autocomplete"),
58
- ("Ctrl+D", "Use /quit (or /q) to exit the TUI"),
58
+ ("Ctrl+D", "Type exit, quit, or /quit to exit the TUI"),
59
59
  (
60
60
  "Ctrl+C",
61
61
  "Clear input or interrupt running agent/shell",
@@ -1,6 +1,6 @@
1
1
  """Message store for virtualized chat history (DOM window only).
2
2
 
3
- Transcript models live in ``soothe_cli.runtime.state.transcript``. Widget
3
+ Transcript models live in ``soothe_sdk.display.transcript_types``. Widget
4
4
  construction uses ``soothe_cli.tui.binding``.
5
5
  """
6
6
 
@@ -9,14 +9,15 @@ from __future__ import annotations
9
9
  import logging
10
10
  from typing import Any
11
11
 
12
- from soothe_cli.runtime.state.transcript import (
12
+ from soothe_sdk.display.transcript_types import (
13
13
  UPDATABLE_FIELDS as _UPDATABLE_FIELDS,
14
14
  )
15
- from soothe_cli.runtime.state.transcript import (
15
+ from soothe_sdk.display.transcript_types import (
16
16
  MessageData,
17
17
  MessageType,
18
18
  ToolStatus,
19
19
  )
20
+
20
21
  from soothe_cli.tui.binding import message_from_widget, message_to_widget
21
22
 
22
23
  logger = logging.getLogger(__name__)
@@ -817,7 +817,7 @@ class CognitionStepMessage(Vertical):
817
817
  except (TypeError, ValueError):
818
818
  loaded = None
819
819
  if isinstance(loaded, dict):
820
- from soothe_cli.runtime.parse.message_processing import extract_tool_args_dict
820
+ from soothe_sdk.display.message_processing import extract_tool_args_dict
821
821
 
822
822
  parsed_from_raw = extract_tool_args_dict(loaded)
823
823
  if parsed_from_raw:
@@ -908,7 +908,8 @@ class CognitionStepMessage(Vertical):
908
908
 
909
909
  def update_tool_args(self, tool_call_id: str, args: dict[str, Any]) -> None:
910
910
  """Refresh kwargs when streaming fills in arguments."""
911
- from soothe_cli.runtime.parse.message_processing import extract_tool_args_dict
911
+ from soothe_sdk.display.message_processing import extract_tool_args_dict
912
+
912
913
  from soothe_cli.runtime.parse.tool_call_resolution import tool_args_meaningful
913
914
 
914
915
  row = self._row_index.get(str(tool_call_id))
@@ -1,45 +0,0 @@
1
- """Re-export shim for ``soothe_sdk.display.message_processing`` (RFC-413).
2
-
3
- These helpers live in the SDK so the daemon-resident ``CardBinder`` can
4
- reuse them. This module preserves the original CLI import path used
5
- across the runtime, TUI, and tests.
6
- """
7
-
8
- from __future__ import annotations
9
-
10
- # Underscore-prefixed names below are re-exported intentionally — they are
11
- # imported by other CLI modules (tool_call_resolution, widgets/messages, etc.)
12
- # and CLI tests. Keep them in __all__ to keep `ruff` from stripping them.
13
- from soothe_sdk.display.message_processing import (
14
- _normalize_tool_name_for_arg_map,
15
- _pending_or_overlay_id_matches_lookup,
16
- _resolve_pending_lookup_tool_name,
17
- accumulate_tool_call_chunks,
18
- coerce_tool_call_args_to_dict,
19
- extract_tool_args_dict,
20
- extract_tool_brief,
21
- finalize_pending_tool_call,
22
- ingest_tool_call_stream_state,
23
- normalize_tool_calls_list,
24
- richest_pending_args_for_lookup,
25
- tool_calls_have_any_arg_dict,
26
- tool_ids_touched_by_stream_message,
27
- try_parse_pending_tool_call_args,
28
- )
29
-
30
- __all__ = [
31
- "_normalize_tool_name_for_arg_map",
32
- "_pending_or_overlay_id_matches_lookup",
33
- "_resolve_pending_lookup_tool_name",
34
- "accumulate_tool_call_chunks",
35
- "coerce_tool_call_args_to_dict",
36
- "extract_tool_args_dict",
37
- "extract_tool_brief",
38
- "finalize_pending_tool_call",
39
- "ingest_tool_call_stream_state",
40
- "normalize_tool_calls_list",
41
- "richest_pending_args_for_lookup",
42
- "tool_calls_have_any_arg_dict",
43
- "tool_ids_touched_by_stream_message",
44
- "try_parse_pending_tool_call_args",
45
- ]
@@ -1,15 +0,0 @@
1
- """Re-export shim for ``soothe_sdk.display.tool_result`` (RFC-413)."""
2
-
3
- from __future__ import annotations
4
-
5
- from soothe_sdk.display.tool_result import (
6
- extract_tool_result_payload,
7
- infer_tool_output_suggests_error,
8
- is_error_tool_result_text,
9
- )
10
-
11
- __all__ = [
12
- "extract_tool_result_payload",
13
- "infer_tool_output_suggests_error",
14
- "is_error_tool_result_text",
15
- ]
@@ -1,24 +0,0 @@
1
- """Transcript message models for TUI display.
2
-
3
- These types live in ``soothe_sdk.display.transcript_types`` so they can be
4
- shared with the daemon-resident ``CardBinder`` (RFC-413). This module
5
- re-exports them to preserve the CLI's existing import paths.
6
-
7
- DOM virtualization lives in ``soothe_cli.tui.widgets.message_store``.
8
- """
9
-
10
- from __future__ import annotations
11
-
12
- from soothe_sdk.display.transcript_types import (
13
- UPDATABLE_FIELDS,
14
- MessageData,
15
- MessageType,
16
- ToolStatus,
17
- )
18
-
19
- __all__ = [
20
- "UPDATABLE_FIELDS",
21
- "MessageData",
22
- "MessageType",
23
- "ToolStatus",
24
- ]
@@ -1,35 +0,0 @@
1
- """Decouple daemon stream ingestion from chunk processing and UI application.
2
-
3
- Canonical implementation lives in ``soothe_client.appkit.turn`` (RFC-629 Layer 1).
4
- This module re-exports the public API for CLI import stability.
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- from soothe_client.appkit.turn import (
10
- _DEFAULT_BATCH_DELAY_MS,
11
- _DEFAULT_BATCH_SIZE,
12
- _DEFAULT_INBOUND_MAXSIZE,
13
- _DEFAULT_OUTBOUND_MAXSIZE,
14
- PRIORITY_CRITICAL,
15
- PRIORITY_HIGH,
16
- PRIORITY_LOW,
17
- PRIORITY_NORMAL,
18
- TurnApplyBatcher,
19
- TurnEventPipeline,
20
- run_turn_pipeline,
21
- )
22
-
23
- __all__ = [
24
- "PRIORITY_CRITICAL",
25
- "PRIORITY_HIGH",
26
- "PRIORITY_LOW",
27
- "PRIORITY_NORMAL",
28
- "TurnApplyBatcher",
29
- "TurnEventPipeline",
30
- "run_turn_pipeline",
31
- "_DEFAULT_BATCH_SIZE",
32
- "_DEFAULT_BATCH_DELAY_MS",
33
- "_DEFAULT_INBOUND_MAXSIZE",
34
- "_DEFAULT_OUTBOUND_MAXSIZE",
35
- ]
File without changes
File without changes
File without changes