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.
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/PKG-INFO +1 -1
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/commands/loop_cmd.py +12 -16
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/headless/processor.py +7 -7
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/parse/tool_call_resolution.py +11 -13
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/engine.py +1 -1
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/state/step_router.py +3 -3
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/turn/prepare.py +6 -6
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/_version.py +0 -19
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_execution.py +9 -4
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_messages_mixin.py +4 -8
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/binding.py +1 -1
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/command_registry.py +5 -2
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/commands/slash_commands.py +1 -1
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/sessions.py +2 -3
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/textual_adapter.py +7 -7
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/tips.py +1 -1
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/tool_display.py +4 -4
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/update_check.py +16 -17
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/help_screen.py +1 -1
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/message_store.py +4 -3
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/cognition_step.py +3 -2
- soothe_cli-0.9.4/src/soothe_cli/runtime/parse/message_processing.py +0 -45
- soothe_cli-0.9.4/src/soothe_cli/runtime/parse/tool_result.py +0 -15
- soothe_cli-0.9.4/src/soothe_cli/runtime/state/transcript.py +0 -24
- soothe_cli-0.9.4/src/soothe_cli/runtime/turn/pipeline.py +0 -35
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/.gitignore +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/README.md +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/pyproject.toml +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/__init__.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/__init__.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/commands/__init__.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/commands/autopilot_cmd.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/commands/config_cmd.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/commands/cron_cmd.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/commands/run_cmd.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/commands/status_cmd.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/execution/__init__.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/execution/daemon.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/execution/daemon_errors.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/execution/headless.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/execution/headless_renderer.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/execution/launcher.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/cli/main.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/config/__init__.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/config/cli_config.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/config/loader.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/config/logging_setup.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/__init__.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/headless/processor_state.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/policy/display_policy.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/policy/essential_events.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/policy/tui_trace_log.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/duration_format.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/id_format.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/renderer_base.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/renderer_protocol.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/subagent_task_display.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/state/file_tracker.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/state/session_stats.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/state/stream_accumulator.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/token_events_debug.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/token_usage.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/transport/session.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/wire/chunk_filter.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/wire/message_text.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/wire/messages.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/__init__.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/_cli_context.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/_env_vars.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/__init__.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_app.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_history.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_model.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_module_init.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_startup.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/_ui.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/app/app.tcss +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/commands/__init__.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/commands/command_router.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/commands/subagent_routing.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/config.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/file_change_notify.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/file_change_renderers.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/hooks.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/input.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/markdown_theme.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/media_utils.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/model_config.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/path_utils.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/preview_limits.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/project_utils.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/shell_color.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/skills/__init__.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/skills/invocation.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/skills/load.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/spinner_labels.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/theme.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/unicode_security.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/__init__.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/_links.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/autocomplete.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/chat_input.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/clipboard.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/context_data.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/context_viewer.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/diff.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/editor.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/file_change_preview.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/history.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/loading.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/loop_selector.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/mcp_viewer.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/__init__.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/_helpers.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/app.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/assistant.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/clarification.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/cognition_goal_tree.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/cognition_reason.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/cognition_step_activity.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/cognition_subagent.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/diff_message.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/error.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/skill.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/user.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/model_selector.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/notification_settings.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/plan_quick_view_overlay.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/router_profile_selector.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/status.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/theme_selector.py +0 -0
- {soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/welcome.py +0 -0
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 /
|
|
154
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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("
|
|
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
|
|
645
|
-
self.notify("
|
|
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
|
|
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": "
|
|
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
|
|
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"
|
|
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
|
-
"
|
|
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
|
|
323
|
-
|
|
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(
|
|
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``
|
|
344
|
-
``
|
|
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
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
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``
|
|
366
|
-
|
|
367
|
-
|
|
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", "
|
|
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 ``
|
|
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
|
|
12
|
+
from soothe_sdk.display.transcript_types import (
|
|
13
13
|
UPDATABLE_FIELDS as _UPDATABLE_FIELDS,
|
|
14
14
|
)
|
|
15
|
-
from
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/duration_format.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/renderer_protocol.py
RENAMED
|
File without changes
|
{soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/runtime/presentation/subagent_task_display.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/cognition_goal_tree.py
RENAMED
|
File without changes
|
{soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/cognition_reason.py
RENAMED
|
File without changes
|
{soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/cognition_step_activity.py
RENAMED
|
File without changes
|
{soothe_cli-0.9.4 → soothe_cli-0.9.6}/src/soothe_cli/tui/widgets/messages/cognition_subagent.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|