aru-code 0.55.0__tar.gz → 0.56.0__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.
- {aru_code-0.55.0/aru_code.egg-info → aru_code-0.56.0}/PKG-INFO +1 -1
- aru_code-0.56.0/aru/__init__.py +1 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/display.py +6 -3
- {aru_code-0.55.0 → aru_code-0.56.0/aru_code.egg-info}/PKG-INFO +1 -1
- {aru_code-0.55.0 → aru_code-0.56.0}/pyproject.toml +1 -1
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_permission_flow.py +34 -0
- aru_code-0.55.0/aru/__init__.py +0 -1
- {aru_code-0.55.0 → aru_code-0.56.0}/LICENSE +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/README.md +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/_debug/__init__.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/_debug/analyze_trace.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/_debug/loop_tracer.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/agent_factory.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/agents/__init__.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/agents/base.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/agents/catalog.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/agents/planner.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/cache_patch.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/checkpoints.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/cli.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/commands.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/completers.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/config.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/context.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/doom_loop.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/events.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/format/__init__.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/format/manager.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/format/runner.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/history_blocks.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/lsp/__init__.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/lsp/client.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/lsp/manager.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/lsp/protocol.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/memory/__init__.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/memory/extractor.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/memory/loader.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/memory/store.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/permissions.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/plugin_cache.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/plugins/__init__.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/plugins/custom_tools.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/plugins/hooks.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/plugins/manager.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/plugins/tool_api.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/providers.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/runner.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/runtime.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/select.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/session.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/sinks.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/streaming.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tool_policy.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/__init__.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/_diff.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/_shared.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/apply_patch.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/apply_patch_prompt.txt +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/ast_tools.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/codebase.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/delegate.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/delegate_prompt.txt +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/file_ops.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/gitignore.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/lsp.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/mcp_client.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/memory_tool.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/plan_mode.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/ranker.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/registry.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/search.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/shell.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/skill.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/tasklist.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/web.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tools/worktree.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/__init__.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/app.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/log_bridge.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/notifications.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/sanitize.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/screens/__init__.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/screens/choice.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/screens/confirm.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/screens/keymap.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/screens/search.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/screens/session_picker.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/screens/text_input.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/sinks.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/slash_bridge.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/themes.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/ui.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/__init__.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/chat.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/completer.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/context_pane.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/file_link.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/header.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/inline_choice.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/loaded_pane.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/prompt_area.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/prompt_queue.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/status.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/subagent_panel.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/tasklist_panel.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/thinking.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/tui/widgets/tools.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru/ui.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru_code.egg-info/SOURCES.txt +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru_code.egg-info/dependency_links.txt +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru_code.egg-info/entry_points.txt +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru_code.egg-info/requires.txt +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/aru_code.egg-info/top_level.txt +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/setup.cfg +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_agents_base.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_agents_md_coverage.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_apply_patch.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_async_tool_permission.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_cache_patch_metrics.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_cache_patch_stop_reason.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_catalog.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_chat_scrollable.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_checkpoints.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_cli.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_cli_advanced.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_cli_base.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_cli_completers.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_cli_new.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_cli_run_cli.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_cli_session.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_cli_shell.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_codebase.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_confabulation_regression.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_config.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_context.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_context_pane.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_cwd_awareness.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_delegate.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_doom_loop.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_events_backward_compat.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_events_schema.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_fork_ctx_concurrency.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_format.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_gitignore.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_guardrails_scenarios.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_invoke_skill.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_invoked_skills.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_loaded_pane_path.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_lsp.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_lsp_rename.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_main.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_markdown_to_text.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_mcp_client.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_mcp_health.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_memory.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_memory_tool.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_microcompact.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_permission_timeout_suspension.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_permissions.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_plan_mode_refactor.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_plugin_cache.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_plugin_errors.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_plugin_hooks_v2.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_plugins.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_providers.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_ranker.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_reasoning.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_runner_interrupt.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_runner_recovery.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_runtime.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_select.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_session_free_cost.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_skill_disallowed_tools.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_status_breakdown.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_status_cost.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_streaming_sink.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_subagent_tool_events.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tasklist.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_thread_tool_timeout.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tool_policy.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_truncation_marker.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_app_boot.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_bindings.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_bus_flow.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_chat.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_chat_adversarial.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_completer.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_completer_dynamic.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_copy.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_error_display.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_file_link.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_input_behaviour.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_layer12_recovery.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_layer13_recovery.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_mention_expand.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_modals.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_mode_cycle.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_native_selection.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_plan_task_render.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_prompt_queue.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_shell_bang.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_sidebar_toggle.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_slash_bridge.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_slash_model.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_snapshot_smoke.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_subagent_panel.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_theme.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_thinking_and_boot.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_tui_widgets_visual.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_ui_adapter.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_worktree.py +0 -0
- {aru_code-0.55.0 → aru_code-0.56.0}/tests/test_worktree_session_restore.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.56.0"
|
|
@@ -301,13 +301,16 @@ class ToolTracker:
|
|
|
301
301
|
self._completed: list[tuple[str, float]] = [] # (label, duration)
|
|
302
302
|
|
|
303
303
|
def start(self, tool_id: str, label: str):
|
|
304
|
-
|
|
304
|
+
# perf_counter, not monotonic: on Windows monotonic() has ~15.6ms
|
|
305
|
+
# resolution, so a sub-tick tool call would report a 0.0 duration.
|
|
306
|
+
# perf_counter is monotonic too but high-resolution (~100ns).
|
|
307
|
+
self._active[tool_id] = (label, time.perf_counter())
|
|
305
308
|
|
|
306
309
|
def complete(self, tool_id: str) -> tuple[str, float] | None:
|
|
307
310
|
entry = self._active.pop(tool_id, None)
|
|
308
311
|
if entry:
|
|
309
312
|
label, start = entry
|
|
310
|
-
duration = time.
|
|
313
|
+
duration = time.perf_counter() - start
|
|
311
314
|
self._completed.append((label, duration))
|
|
312
315
|
return label, duration
|
|
313
316
|
return None
|
|
@@ -315,7 +318,7 @@ class ToolTracker:
|
|
|
315
318
|
@property
|
|
316
319
|
def active_labels(self) -> list[tuple[str, float]]:
|
|
317
320
|
"""Return (label, elapsed_seconds) for each active tool."""
|
|
318
|
-
now = time.
|
|
321
|
+
now = time.perf_counter()
|
|
319
322
|
return [(label, now - start) for label, start in self._active.values()]
|
|
320
323
|
|
|
321
324
|
def pop_completed(self) -> list[tuple[str, float]]:
|
|
@@ -9,6 +9,33 @@ import pytest
|
|
|
9
9
|
pytest.importorskip("textual")
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
async def _wait_for_inline_focus(app, pilot, *, max_iter: int = 50):
|
|
13
|
+
"""Block until the InlineChoicePrompt's OptionList owns focus.
|
|
14
|
+
|
|
15
|
+
``query(InlineChoicePrompt)`` returns the widget as soon as it is in
|
|
16
|
+
the DOM, but the OptionList only gains focus (and its default
|
|
17
|
+
highlight) inside ``InlineChoicePrompt.on_mount`` — a message
|
|
18
|
+
dispatched *after* mount completes. Pressing Enter / arrow keys
|
|
19
|
+
before that lands sends the key nowhere useful: ``OptionSelected``
|
|
20
|
+
never fires and the worker thread blocks until its timeout. In
|
|
21
|
+
isolation the gap is sub-tick so the press always lands; under a
|
|
22
|
+
loaded suite the mount lifecycle slips behind detection and the test
|
|
23
|
+
flakes with a TimeoutError. Waiting for focus closes the race.
|
|
24
|
+
"""
|
|
25
|
+
from textual.widgets import OptionList
|
|
26
|
+
|
|
27
|
+
from aru.tui.widgets.inline_choice import InlineChoicePrompt
|
|
28
|
+
|
|
29
|
+
for _ in range(max_iter):
|
|
30
|
+
prompts = list(app.query(InlineChoicePrompt))
|
|
31
|
+
if prompts:
|
|
32
|
+
opts = list(prompts[0].query(OptionList))
|
|
33
|
+
if opts and app.focused is opts[0] and opts[0].highlighted is not None:
|
|
34
|
+
return opts[0]
|
|
35
|
+
await pilot.pause(0.05)
|
|
36
|
+
raise AssertionError("InlineChoicePrompt OptionList never took focus")
|
|
37
|
+
|
|
38
|
+
|
|
12
39
|
@pytest.mark.asyncio
|
|
13
40
|
async def test_tui_ask_choice_from_worker_resolves_via_modal():
|
|
14
41
|
"""TuiUI.ask_choice invoked from a worker thread returns modal result.
|
|
@@ -106,6 +133,9 @@ async def test_ask_choice_with_details_uses_inline_prompt_not_modal():
|
|
|
106
133
|
"expected InlineChoicePrompt in ChatPane"
|
|
107
134
|
)
|
|
108
135
|
# Press Enter — OptionList focuses on mount, default=0 highlighted.
|
|
136
|
+
# Wait for that focus to actually land first; querying the prompt
|
|
137
|
+
# only proves it is in the DOM (see _wait_for_inline_focus).
|
|
138
|
+
await _wait_for_inline_focus(app, pilot)
|
|
109
139
|
await pilot.press("enter")
|
|
110
140
|
await asyncio.wait_for(task, timeout=5.0)
|
|
111
141
|
assert holder["choice"] == 0
|
|
@@ -156,6 +186,7 @@ async def test_inline_prompt_hides_input_bar_and_restores_on_answer():
|
|
|
156
186
|
assert inp.has_class("-hidden"), (
|
|
157
187
|
"input should be hidden while InlineChoicePrompt is mounted"
|
|
158
188
|
)
|
|
189
|
+
await _wait_for_inline_focus(app, pilot)
|
|
159
190
|
await pilot.press("enter")
|
|
160
191
|
await asyncio.wait_for(task, timeout=5.0)
|
|
161
192
|
# After the user answers, the input bar is restored.
|
|
@@ -199,6 +230,7 @@ async def test_ask_choice_inline_esc_cancels_with_cancel_value():
|
|
|
199
230
|
await pilot.pause(0.05)
|
|
200
231
|
if list(app.query_one(ChatPane).query(InlineChoicePrompt)):
|
|
201
232
|
break
|
|
233
|
+
await _wait_for_inline_focus(app, pilot)
|
|
202
234
|
await pilot.press("escape")
|
|
203
235
|
await asyncio.wait_for(task, timeout=5.0)
|
|
204
236
|
assert holder["choice"] == 99
|
|
@@ -257,6 +289,7 @@ async def test_auto_accept_inline_choice_updates_status_pane_mode():
|
|
|
257
289
|
if list(chat.query(InlineChoicePrompt)):
|
|
258
290
|
break
|
|
259
291
|
# Option index 1 = "Yes, and auto-accept edits".
|
|
292
|
+
await _wait_for_inline_focus(app, pilot)
|
|
260
293
|
await pilot.press("down")
|
|
261
294
|
await pilot.press("enter")
|
|
262
295
|
await asyncio.wait_for(task, timeout=5.0)
|
|
@@ -320,6 +353,7 @@ async def test_thinking_spinner_hidden_while_prompt_open():
|
|
|
320
353
|
"spinner must be hidden while the permission prompt is open"
|
|
321
354
|
)
|
|
322
355
|
|
|
356
|
+
await _wait_for_inline_focus(app, pilot)
|
|
323
357
|
await pilot.press("enter")
|
|
324
358
|
await asyncio.wait_for(task, timeout=5.0)
|
|
325
359
|
for _ in range(20):
|
aru_code-0.55.0/aru/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.55.0"
|
|
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
|
|
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
|
|
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
|
|
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
|