voidx 3.7.1__tar.gz → 3.7.2__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 (607) hide show
  1. {voidx-3.7.1/src/voidx.egg-info → voidx-3.7.2}/PKG-INFO +1 -1
  2. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_call_llm_compaction.py +20 -0
  3. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_graph_authorization.py +190 -4
  4. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_subagent_runner.py +14 -2
  5. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_tool_execution_auth.py +1 -1
  6. voidx-3.7.2/src/tests/test_agent/graph/test_turn_stop_without_pending.py +236 -0
  7. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_workflow_done.py +10 -5
  8. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_workflow_transactions_barrier.py +3 -0
  9. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/slash/test_slash_model.py +98 -13
  10. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/slash/test_slash_model_advanced.py +7 -11
  11. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/slash/test_slash_tavily.py +0 -4
  12. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_permission.py +30 -48
  13. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_permission_phase2.py +10 -9
  14. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_permission_phase4.py +12 -12
  15. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_permission_phase5.py +5 -6
  16. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_permission_phase6.py +37 -4
  17. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_tool_filters_gemini.py +111 -0
  18. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_config/test_config.py +0 -4
  19. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_config/test_config_advanced.py +25 -37
  20. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_gemini_provider.py +21 -0
  21. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_llm_catalog_fetchers.py +110 -2
  22. voidx-3.7.2/src/tests/test_permission/test_risk.py +102 -0
  23. voidx-3.7.2/src/tests/test_release_npm_wheel_sync.py +97 -0
  24. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_skills/test_workflow_advance.py +1 -1
  25. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_git_tool_phase5.py +1 -1
  26. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_git_tool_raw_permissions.py +61 -0
  27. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_powershell_tool_phase6.py +49 -0
  28. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_shell_tool_phase6.py +54 -0
  29. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_adapter.py +46 -0
  30. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_gateway_v2_dispatch.py +2 -6
  31. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_ui_events_subagent.py +22 -0
  32. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/output/test_tool_display.py +32 -1
  33. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/output/test_tree_smoke.py +18 -0
  34. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_wheel_verify_cwd.py +5 -5
  35. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/__init__.py +1 -1
  36. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/contracts.py +4 -3
  37. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/core/helpers.py +58 -0
  38. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/core/llm.py +43 -12
  39. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/permissions.py +115 -28
  40. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/subagent.py +2 -2
  41. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/tool_executor/executor.py +18 -13
  42. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/tool_executor/workflow.py +1 -30
  43. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/turn_control.py +6 -0
  44. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/wiring.py +1 -0
  45. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/slash/handler.py +30 -53
  46. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/slash/model.py +45 -36
  47. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/tool_filters.py +19 -8
  48. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/__init__.py +2 -6
  49. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/enums.py +9 -0
  50. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/models.py +2 -1
  51. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/settings.py +6 -15
  52. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/settings_permissions.py +13 -23
  53. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/voidx-guide/permission.md +5 -7
  54. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/voidx-guide/reference.md +2 -3
  55. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/llm/catalog.py +134 -25
  56. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/llm/provider.py +18 -1
  57. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/permission/__init__.py +9 -0
  58. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/permission/context.py +7 -1
  59. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/permission/engine.py +70 -41
  60. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/permission/git_policy.py +5 -0
  61. voidx-3.7.2/src/voidx/permission/presets.py +66 -0
  62. voidx-3.7.2/src/voidx/permission/risk.py +94 -0
  63. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/permission/rules.py +1 -1
  64. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/permission/schema.py +1 -1
  65. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/permission/service.py +30 -96
  66. voidx-3.7.2/src/voidx/permission/shell_policy.py +243 -0
  67. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/base.py +18 -0
  68. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/bash/tool.py +14 -12
  69. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/powershell/tool.py +14 -12
  70. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/service.py +2 -0
  71. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/command_catalog.py +3 -5
  72. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/commands.py +5 -12
  73. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/session/method/settings.py +8 -16
  74. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/capture.py +4 -1
  75. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/dock/nodes.py +4 -1
  76. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/events/consumers.py +4 -2
  77. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/events/schema.py +3 -0
  78. voidx-3.7.2/src/voidx/ui/output/tool_display.py +136 -0
  79. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/workflow/__init__.py +0 -2
  80. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/workflow/nodes.py +0 -73
  81. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/workflow/policy.py +0 -4
  82. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/workflow/schema.py +0 -1
  83. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/workflow/service.py +0 -1
  84. {voidx-3.7.1 → voidx-3.7.2/src/voidx.egg-info}/PKG-INFO +1 -1
  85. {voidx-3.7.1 → voidx-3.7.2}/src/voidx.egg-info/SOURCES.txt +5 -1
  86. voidx-3.7.1/src/voidx/config/permissions.py +0 -24
  87. voidx-3.7.1/src/voidx/permission/shell_policy.py +0 -138
  88. voidx-3.7.1/src/voidx/ui/output/tool_display.py +0 -62
  89. {voidx-3.7.1 → voidx-3.7.2}/LICENSE +0 -0
  90. {voidx-3.7.1 → voidx-3.7.2}/README.md +0 -0
  91. {voidx-3.7.1 → voidx-3.7.2}/pyproject.toml +0 -0
  92. {voidx-3.7.1 → voidx-3.7.2}/setup.cfg +0 -0
  93. {voidx-3.7.1 → voidx-3.7.2}/src/tests/__init__.py +0 -0
  94. {voidx-3.7.1 → voidx-3.7.2}/src/tests/conftest.py +0 -0
  95. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/__init__.py +0 -0
  96. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/conftest.py +0 -0
  97. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/__init__.py +0 -0
  98. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/conftest.py +0 -0
  99. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/run_loop_helpers.py +0 -0
  100. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/stream_llm_helpers.py +0 -0
  101. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_call_llm_compaction_advanced.py +0 -0
  102. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_call_llm_tools.py +0 -0
  103. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_compaction_flow.py +0 -0
  104. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_compaction_flow_run_once.py +0 -0
  105. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_convergence.py +0 -0
  106. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_execute_tools_guard.py +0 -0
  107. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_execute_tools_todo.py +0 -0
  108. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_graph_setup_prompts.py +0 -0
  109. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_guards_tool_op.py +0 -0
  110. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_parallel_subagents.py +0 -0
  111. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_parallel_subagents_dedup.py +0 -0
  112. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_prepare_workflow.py +0 -0
  113. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_run_loop_startup.py +0 -0
  114. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_run_loop_title_lsp.py +0 -0
  115. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_run_loop_title_misc.py +0 -0
  116. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_run_loop_workflow.py +0 -0
  117. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_run_loop_workflow_advanced.py +0 -0
  118. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_runtime_guards.py +0 -0
  119. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_session_context_frames.py +0 -0
  120. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_session_crud.py +0 -0
  121. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_session_messages.py +0 -0
  122. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_session_persistence.py +0 -0
  123. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_session_run_once.py +0 -0
  124. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_session_runtime_state.py +0 -0
  125. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_session_transcript.py +0 -0
  126. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_stream_llm_sanitization.py +0 -0
  127. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_subagent_llm_retry.py +0 -0
  128. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_subagent_persistence.py +0 -0
  129. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_subagent_step_budget.py +0 -0
  130. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_subagent_step_budget_convergence.py +0 -0
  131. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_subagent_step_budget_final.py +0 -0
  132. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_todo_events.py +0 -0
  133. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_tool_result_preview.py +0 -0
  134. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_turn_control_e2e.py +0 -0
  135. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_turn_control_integration.py +0 -0
  136. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_turn_runner_guidance_discard.py +0 -0
  137. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_turn_runner_idle_event.py +0 -0
  138. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_workflow_review.py +0 -0
  139. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/graph/test_workflow_transactions.py +0 -0
  140. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/loop/test_manager.py +0 -0
  141. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/loop/test_prompt_source.py +0 -0
  142. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/slash/__init__.py +0 -0
  143. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/slash/test_slash_init.py +0 -0
  144. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/slash/test_slash_loop.py +0 -0
  145. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/slash/test_slash_mcp.py +0 -0
  146. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/slash/test_slash_session.py +0 -0
  147. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/slash/test_slash_skills.py +0 -0
  148. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/slash/test_slash_upgrade.py +0 -0
  149. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_attachments.py +0 -0
  150. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_file_rwlock.py +0 -0
  151. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_goal_resolver.py +0 -0
  152. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_goal_resolver_advanced.py +0 -0
  153. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_guard_guidance.py +0 -0
  154. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_guide_command.py +0 -0
  155. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_message_trimming_parsers.py +0 -0
  156. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_message_trimming_rules.py +0 -0
  157. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_module_boundaries.py +0 -0
  158. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_permission_append.py +0 -0
  159. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_permission_phase3.py +0 -0
  160. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_prompts.py +0 -0
  161. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_runtime_context_builder.py +0 -0
  162. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_runtime_context_prompts.py +0 -0
  163. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_runtime_context_skill_stripping.py +0 -0
  164. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_task_state.py +0 -0
  165. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_task_state_context_sync.py +0 -0
  166. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_task_state_rendering.py +0 -0
  167. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_todo_replay_sanitization.py +0 -0
  168. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_tool_exchange_sanitizer.py +0 -0
  169. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_tool_messages.py +0 -0
  170. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_tool_result_storage.py +0 -0
  171. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_turn_control.py +0 -0
  172. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_turn_control_prompt.py +0 -0
  173. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_turn_metrics.py +0 -0
  174. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_agent/test_turn_start.py +0 -0
  175. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_archive_script.py +0 -0
  176. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_config/__init__.py +0 -0
  177. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_config/test_retry_config.py +0 -0
  178. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_install_sh.py +0 -0
  179. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/conftest.py +0 -0
  180. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_compaction_retry.py +0 -0
  181. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_fallback_summary.py +0 -0
  182. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_goal_resolver_retry.py +0 -0
  183. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_instruction_cache.py +0 -0
  184. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_llm_catalog.py +0 -0
  185. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_llm_provider.py +0 -0
  186. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_llm_provider_advanced.py +0 -0
  187. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_llm_usage.py +0 -0
  188. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_overflow_threshold.py +0 -0
  189. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_prune_args.py +0 -0
  190. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_request_log.py +0 -0
  191. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_streaming_sanitize.py +0 -0
  192. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_llm/test_token_counting.py +0 -0
  193. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_logging/test_external.py +0 -0
  194. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_logging/test_internal_error.py +0 -0
  195. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_logging/test_tool_log.py +0 -0
  196. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_lsp/__init__.py +0 -0
  197. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_lsp/test_lsp.py +0 -0
  198. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_lsp/test_lsp_advanced.py +0 -0
  199. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_mcp/__init__.py +0 -0
  200. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_mcp/test_mcp.py +0 -0
  201. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_memory/__init__.py +0 -0
  202. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_memory/test_main.py +0 -0
  203. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_memory/test_main_startup.py +0 -0
  204. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_memory/test_schema_migration.py +0 -0
  205. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_npm_package.py +0 -0
  206. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_permission/__init__.py +0 -0
  207. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_runtime/__init__.py +0 -0
  208. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_runtime/test_goal_resolution_refactor.py +0 -0
  209. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_runtime/test_processes.py +0 -0
  210. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_runtime/test_runtime_ui.py +0 -0
  211. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_selfupdate/__init__.py +0 -0
  212. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_selfupdate/test_selfupdate.py +0 -0
  213. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_skills/__init__.py +0 -0
  214. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_skills/conftest.py +0 -0
  215. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_skills/test_create_skill.py +0 -0
  216. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_skills/test_skill_parsing.py +0 -0
  217. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_skills/test_skill_references.py +0 -0
  218. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_test_runner.py +0 -0
  219. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/__init__.py +0 -0
  220. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/bash/__init__.py +0 -0
  221. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/bash/test_router_git.py +0 -0
  222. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/bash/test_router_safety.py +0 -0
  223. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/bash/test_router_sed_grep.py +0 -0
  224. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/bash/test_tool.py +0 -0
  225. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/__init__.py +0 -0
  226. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_coverage_fingerprint.py +0 -0
  227. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_edit_anchors.py +0 -0
  228. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_edit_bounds_input.py +0 -0
  229. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_edit_coverage.py +0 -0
  230. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_edit_dedup.py +0 -0
  231. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_edit_drift_fallback.py +0 -0
  232. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_edit_drift_fallback_e2e.py +0 -0
  233. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_edit_errors.py +0 -0
  234. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_edit_line_insert.py +0 -0
  235. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_edit_llm_messages.py +0 -0
  236. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_edit_replace.py +0 -0
  237. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_edit_trailing_newline.py +0 -0
  238. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_read.py +0 -0
  239. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_read_write.py +0 -0
  240. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_render_numbered_diff.py +0 -0
  241. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/file/test_write_file.py +0 -0
  242. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_clarify_tool.py +0 -0
  243. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_diffing.py +0 -0
  244. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_file_tools_redesign.py +0 -0
  245. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_git_tool_destructive.py +0 -0
  246. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_git_tool_schema_errors.py +0 -0
  247. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_git_tool_structured.py +0 -0
  248. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_infer_state_patch.py +0 -0
  249. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_interactive_tools.py +0 -0
  250. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_interactive_tools_write.py +0 -0
  251. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_load_doc_template.py +0 -0
  252. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_loop_integration.py +0 -0
  253. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_loop_registry.py +0 -0
  254. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_make_interact_callback.py +0 -0
  255. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_plan_checkpoint.py +0 -0
  256. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_powershell_tool.py +0 -0
  257. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_replace_failure_logging.py +0 -0
  258. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_resolve_safe.py +0 -0
  259. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_retry.py +0 -0
  260. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_schedule_wakeup.py +0 -0
  261. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_search.py +0 -0
  262. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_skills_tool.py +0 -0
  263. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_state_update_from_executed_tools.py +0 -0
  264. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_task_tracker.py +0 -0
  265. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_todo_tool.py +0 -0
  266. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_tool_error_handling.py +0 -0
  267. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_tool_registry.py +0 -0
  268. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_tool_schemas.py +0 -0
  269. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_tool_state_patch.py +0 -0
  270. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_user_interaction_models.py +0 -0
  271. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_web_mcp.py +0 -0
  272. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_webfetch.py +0 -0
  273. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_tools/test_workflow_tool.py +0 -0
  274. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/__init__.py +0 -0
  275. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/conftest.py +0 -0
  276. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/helpers.py +0 -0
  277. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_diff_review.py +0 -0
  278. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_gateway_headless_frontend.py +0 -0
  279. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_gateway_v2_crud_diff.py +0 -0
  280. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_gateway_v2_routing.py +0 -0
  281. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_gateway_v2_server.py +0 -0
  282. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_gateway_v2_session.py +0 -0
  283. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_guidance_fallback.py +0 -0
  284. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_run_manager.py +0 -0
  285. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_terminal.py +0 -0
  286. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_ui_events_dock_bus.py +0 -0
  287. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_ui_events_dock_prompts.py +0 -0
  288. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_ui_events_dock_status.py +0 -0
  289. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_ui_events_streaming.py +0 -0
  290. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_ui_events_todo.py +0 -0
  291. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/gateway/test_ui_gateway.py +0 -0
  292. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/output/__init__.py +0 -0
  293. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/output/test_console_app.py +0 -0
  294. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/output/test_dock_formatting.py +0 -0
  295. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/output/test_fmt_args.py +0 -0
  296. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/output/test_output_browse.py +0 -0
  297. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/output/test_scrollback_flush.py +0 -0
  298. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/output/test_ui_diff.py +0 -0
  299. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/output/test_ui_session_changes.py +0 -0
  300. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/protocol/__init__.py +0 -0
  301. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/protocol/test_dto.py +0 -0
  302. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/protocol/test_v2_envelope.py +0 -0
  303. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/protocol/test_v2_methods.py +0 -0
  304. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/protocol/test_v2_snapshot.py +0 -0
  305. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/protocol/test_v2_threads.py +0 -0
  306. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/test_display_policy.py +0 -0
  307. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/test_file_picker.py +0 -0
  308. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/tools/__init__.py +0 -0
  309. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/tools/test_clipboard_image.py +0 -0
  310. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/tools/test_clipboard_image_windows.py +0 -0
  311. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/tools/test_clipboard_text.py +0 -0
  312. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/tools/test_clipboard_text_windows.py +0 -0
  313. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_ui/tools/test_code_ide.py +0 -0
  314. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_voidx_entrypoint.py +0 -0
  315. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_wheel_build.py +0 -0
  316. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_workflow/__init__.py +0 -0
  317. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_workflow/test_auto_advance.py +0 -0
  318. {voidx-3.7.1 → voidx-3.7.2}/src/tests/test_workflow/test_workflow_reconcile.py +0 -0
  319. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/__init__.py +0 -0
  320. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/agents.py +0 -0
  321. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/attachments.py +0 -0
  322. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/goal_resolver.py +0 -0
  323. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/__init__.py +0 -0
  324. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/compaction.py +0 -0
  325. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/compaction_coordinator.py +0 -0
  326. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/convergence.py +0 -0
  327. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/core/__init__.py +0 -0
  328. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/core/voidx_graph.py +0 -0
  329. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/run_loop.py +0 -0
  330. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/runtime.py +0 -0
  331. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/runtime_guards.py +0 -0
  332. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/session_mixin.py +0 -0
  333. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/session_runtime.py +0 -0
  334. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/streaming.py +0 -0
  335. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/thread_context.py +0 -0
  336. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/title_mixin.py +0 -0
  337. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/todo_events.py +0 -0
  338. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/tool_execution.py +0 -0
  339. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/tool_executor/__init__.py +0 -0
  340. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/tool_executor/guards.py +0 -0
  341. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/tool_executor/helpers.py +0 -0
  342. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/tool_executor/types.py +0 -0
  343. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/tool_executor/ui.py +0 -0
  344. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/topology.py +0 -0
  345. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/transcript_mixin.py +0 -0
  346. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/turn_metrics.py +0 -0
  347. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/turn_mixin.py +0 -0
  348. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/turn_runner.py +0 -0
  349. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/graph/workflow_utils.py +0 -0
  350. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/loop/__init__.py +0 -0
  351. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/loop/manager.py +0 -0
  352. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/loop/prompt_source.py +0 -0
  353. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/loop/slash.py +0 -0
  354. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/message_rows.py +0 -0
  355. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/message_trimming.py +0 -0
  356. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/prompts.py +0 -0
  357. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/runtime_context.py +0 -0
  358. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/slash/__init__.py +0 -0
  359. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/slash/code_ide.py +0 -0
  360. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/slash/guide.py +0 -0
  361. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/slash/host.py +0 -0
  362. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/slash/init.py +0 -0
  363. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/slash/lsp.py +0 -0
  364. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/slash/mcp.py +0 -0
  365. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/slash/profile.py +0 -0
  366. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/slash/runtime.py +0 -0
  367. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/slash/session.py +0 -0
  368. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/slash/skills.py +0 -0
  369. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/slash/upgrade.py +0 -0
  370. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/state.py +0 -0
  371. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/task_state.py +0 -0
  372. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/todo_state.py +0 -0
  373. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/tool_call_ids.py +0 -0
  374. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/tool_exchange_sanitizer.py +0 -0
  375. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/tool_messages.py +0 -0
  376. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/agent/tool_result_storage.py +0 -0
  377. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/defaults.py +0 -0
  378. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/settings_agent.py +0 -0
  379. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/settings_api_keys.py +0 -0
  380. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/settings_code_ide.py +0 -0
  381. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/settings_custom.py +0 -0
  382. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/settings_mcp.py +0 -0
  383. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/settings_retry.py +0 -0
  384. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/settings_skills.py +0 -0
  385. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/settings_update.py +0 -0
  386. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/settings_utils.py +0 -0
  387. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/config/settings_web.py +0 -0
  388. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/__init__.py +0 -0
  389. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/README.md +0 -0
  390. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/templates/api-doc.md +0 -0
  391. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/templates/capability-spec.md +0 -0
  392. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/templates/implementation-spec.md +0 -0
  393. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/templates/prd.md +0 -0
  394. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/templates/readme.md +0 -0
  395. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/templates/rfc.md +0 -0
  396. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/templates/tasks.md +0 -0
  397. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/templates/tech-design.md +0 -0
  398. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/voidx-guide/README.md +0 -0
  399. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/voidx-guide/context.md +0 -0
  400. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/voidx-guide/debug.md +0 -0
  401. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/voidx-guide/extension.md +0 -0
  402. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/voidx-guide/mode.md +0 -0
  403. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/voidx-guide/model.md +0 -0
  404. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/voidx-guide/preferences.md +0 -0
  405. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/voidx-guide/quickstart.md +0 -0
  406. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/voidx-guide/session.md +0 -0
  407. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/voidx-guide/upgrade.md +0 -0
  408. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/voidx-guide/web.md +0 -0
  409. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/data/documents/voidx-guide/workflow.md +0 -0
  410. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/diffing.py +0 -0
  411. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/llm/__init__.py +0 -0
  412. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/llm/compaction.py +0 -0
  413. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/llm/context.py +0 -0
  414. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/llm/instruction.py +0 -0
  415. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/llm/message_markers.py +0 -0
  416. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/llm/message_status.py +0 -0
  417. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/llm/service.py +0 -0
  418. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/llm/usage.py +0 -0
  419. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/logging/__init__.py +0 -0
  420. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/logging/external.py +0 -0
  421. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/logging/internal_error.py +0 -0
  422. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/logging/request_log.py +0 -0
  423. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/logging/tool_log.py +0 -0
  424. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/lsp/__init__.py +0 -0
  425. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/lsp/client.py +0 -0
  426. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/lsp/config.py +0 -0
  427. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/lsp/detector.py +0 -0
  428. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/lsp/detector_data.py +0 -0
  429. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/lsp/errors.py +0 -0
  430. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/lsp/manager.py +0 -0
  431. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/lsp/schema.py +0 -0
  432. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/lsp/service.py +0 -0
  433. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/main.py +0 -0
  434. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/mcp/__init__.py +0 -0
  435. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/mcp/client/__init__.py +0 -0
  436. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/mcp/client/base.py +0 -0
  437. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/mcp/client/errors.py +0 -0
  438. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/mcp/client/http_transport.py +0 -0
  439. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/mcp/client/sse_transport.py +0 -0
  440. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/mcp/client/stdio_transport.py +0 -0
  441. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/mcp/manager.py +0 -0
  442. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/mcp/schema.py +0 -0
  443. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/mcp/tool.py +0 -0
  444. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/mcp_servers/__init__.py +0 -0
  445. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/mcp_servers/web.py +0 -0
  446. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/memory/__init__.py +0 -0
  447. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/memory/cleanup.py +0 -0
  448. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/memory/context_frames.py +0 -0
  449. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/memory/jsonl_store.py +0 -0
  450. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/memory/model_profiles.py +0 -0
  451. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/memory/runtime_state.py +0 -0
  452. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/memory/service.py +0 -0
  453. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/memory/session.py +0 -0
  454. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/memory/store.py +0 -0
  455. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/memory/subagents.py +0 -0
  456. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/memory/transcript.py +0 -0
  457. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/paths.py +0 -0
  458. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/permission/evaluate.py +0 -0
  459. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/permission/grants.py +0 -0
  460. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/permission/process_sandbox.py +0 -0
  461. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/permission/sandbox.py +0 -0
  462. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/permission/wildcard.py +0 -0
  463. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/runtime/__init__.py +0 -0
  464. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/runtime/_win32_jobs.py +0 -0
  465. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/runtime/attachments.py +0 -0
  466. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/runtime/intent.py +0 -0
  467. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/runtime/processes.py +0 -0
  468. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/runtime/reference_tokens.py +0 -0
  469. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/runtime/task_state.py +0 -0
  470. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/runtime/todo.py +0 -0
  471. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/runtime/ui.py +0 -0
  472. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/runtime/ui_port.py +0 -0
  473. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/selfupdate.py +0 -0
  474. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/skills/__init__.py +0 -0
  475. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/skills/context.py +0 -0
  476. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/skills/references.py +0 -0
  477. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/skills/registry.py +0 -0
  478. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/skills/schema.py +0 -0
  479. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/skills/service.py +0 -0
  480. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/__init__.py +0 -0
  481. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/agent.py +0 -0
  482. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/bash/__init__.py +0 -0
  483. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/bash/core.py +0 -0
  484. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/bash/hint/__init__.py +0 -0
  485. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/bash/hint/file.py +0 -0
  486. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/bash/hint/git.py +0 -0
  487. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/bash/hint/search.py +0 -0
  488. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/bash/router.py +0 -0
  489. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/bash/safety.py +0 -0
  490. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/checkpoint.py +0 -0
  491. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/clarify.py +0 -0
  492. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/compact.py +0 -0
  493. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/document.py +0 -0
  494. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/file/__init__.py +0 -0
  495. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/file/manage.py +0 -0
  496. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/file/read.py +0 -0
  497. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/file/replace.py +0 -0
  498. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/file/replace_resolve.py +0 -0
  499. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/file/safe_path.py +0 -0
  500. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/file/state.py +0 -0
  501. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/file/types.py +0 -0
  502. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/file/write.py +0 -0
  503. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/git.py +0 -0
  504. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/lsp.py +0 -0
  505. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/powershell/__init__.py +0 -0
  506. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/powershell/core.py +0 -0
  507. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/powershell/hint/__init__.py +0 -0
  508. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/powershell/hint/file.py +0 -0
  509. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/powershell/hint/search.py +0 -0
  510. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/powershell/router.py +0 -0
  511. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/powershell/safety.py +0 -0
  512. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/powershell/sandbox.py +0 -0
  513. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/registry.py +0 -0
  514. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/retry.py +0 -0
  515. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/schedule_wakeup.py +0 -0
  516. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/search.py +0 -0
  517. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/shell/__init__.py +0 -0
  518. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/shell/common.py +0 -0
  519. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/shell/hint/__init__.py +0 -0
  520. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/shell/hint/git.py +0 -0
  521. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/skills.py +0 -0
  522. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/task_status.py +0 -0
  523. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/task_tracker.py +0 -0
  524. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/todo.py +0 -0
  525. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/web/__init__.py +0 -0
  526. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/web/content.py +0 -0
  527. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/web/fetch.py +0 -0
  528. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/web/mcp.py +0 -0
  529. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/web/search.py +0 -0
  530. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/tools/workflow.py +0 -0
  531. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/__init__.py +0 -0
  532. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/frontend.py +0 -0
  533. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/__init__.py +0 -0
  534. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/adapter.py +0 -0
  535. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/bootstrap.py +0 -0
  536. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/diff_review.py +0 -0
  537. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/frontend.py +0 -0
  538. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/run_manager.py +0 -0
  539. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/server.py +0 -0
  540. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/session/__init__.py +0 -0
  541. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/session/consumer.py +0 -0
  542. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/session/core.py +0 -0
  543. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/session/method/__init__.py +0 -0
  544. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/session/method/diff.py +0 -0
  545. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/session/method/integrations.py +0 -0
  546. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/session/method/sessions.py +0 -0
  547. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/session/method/terminal.py +0 -0
  548. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/gateway/terminal.py +0 -0
  549. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/__init__.py +0 -0
  550. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/agent_display.py +0 -0
  551. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/ansi_marker.py +0 -0
  552. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/browse.py +0 -0
  553. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/console/__init__.py +0 -0
  554. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/console/app.py +0 -0
  555. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/console/formatting.py +0 -0
  556. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/console/streaming.py +0 -0
  557. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/diff.py +0 -0
  558. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/display_policy.py +0 -0
  559. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/dock/__init__.py +0 -0
  560. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/dock/agent_placeholder.py +0 -0
  561. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/dock/app.py +0 -0
  562. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/dock/formatting.py +0 -0
  563. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/dock/nodes_checkpoint.py +0 -0
  564. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/dock/nodes_clarify.py +0 -0
  565. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/dock/nodes_permission.py +0 -0
  566. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/dock/nodes_startup.py +0 -0
  567. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/dock/nodes_status.py +0 -0
  568. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/dock/state.py +0 -0
  569. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/dock/status.py +0 -0
  570. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/dock/stream.py +0 -0
  571. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/dock/todo.py +0 -0
  572. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/events/__init__.py +0 -0
  573. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/events/bus.py +0 -0
  574. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/manage_display.py +0 -0
  575. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/tree.py +0 -0
  576. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/output/types.py +0 -0
  577. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/protocol/__init__.py +0 -0
  578. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/protocol/commands.py +0 -0
  579. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/protocol/requests.py +0 -0
  580. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/protocol/schema.py +0 -0
  581. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/protocol/transcript.py +0 -0
  582. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/protocol/v2/__init__.py +0 -0
  583. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/protocol/v2/envelope.py +0 -0
  584. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/protocol/v2/methods.py +0 -0
  585. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/protocol/v2/snapshot.py +0 -0
  586. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/protocol/v2/threads.py +0 -0
  587. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/session.py +0 -0
  588. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/tools/__init__.py +0 -0
  589. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/tools/attachment_tokens.py +0 -0
  590. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/tools/clipboard_image.py +0 -0
  591. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/tools/clipboard_text.py +0 -0
  592. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/tools/code_ide.py +0 -0
  593. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/tools/file_picker.py +0 -0
  594. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/tools/skill_picker.py +0 -0
  595. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/ui/transcript.py +0 -0
  596. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/workflow/auto_advance.py +0 -0
  597. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/workflow/context.py +0 -0
  598. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/workflow/dag.py +0 -0
  599. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/workflow/reconcile.py +0 -0
  600. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/workflow/render.py +0 -0
  601. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/workflow/route.py +0 -0
  602. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/workflow/runtime.py +0 -0
  603. {voidx-3.7.1 → voidx-3.7.2}/src/voidx/workflow/types.py +0 -0
  604. {voidx-3.7.1 → voidx-3.7.2}/src/voidx.egg-info/dependency_links.txt +0 -0
  605. {voidx-3.7.1 → voidx-3.7.2}/src/voidx.egg-info/entry_points.txt +0 -0
  606. {voidx-3.7.1 → voidx-3.7.2}/src/voidx.egg-info/requires.txt +0 -0
  607. {voidx-3.7.1 → voidx-3.7.2}/src/voidx.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voidx
3
- Version: 3.7.1
3
+ Version: 3.7.2
4
4
  Summary: A coding agent that quantifies everything and solves with tools, not fuzzy prompts.
5
5
  Author: chikhamx
6
6
  License: MIT
@@ -792,3 +792,23 @@ def test_llm_retry_delay_exponential_cap():
792
792
  assert _llm_retry_delay(8) == 60.0
793
793
  assert _llm_retry_delay(9) == 60.0
794
794
  assert _llm_retry_delay(10) == 60.0
795
+
796
+
797
+ def test_clean_error_message():
798
+ from voidx.agent.graph.core.helpers import _clean_error_message
799
+
800
+ # Test case 1: OpenAI rate limit error with dict representation
801
+ exc1 = Exception("Error code: 402 - {'error': {'type': 'rate_limit_error', 'message': '每日额度超限: 当前 $50.813...'}}")
802
+ assert _clean_error_message(exc1) == "Error code: 402 - 每日额度超限: 当前 $50.813..."
803
+
804
+ # Test case 2: OpenAI error with json representation
805
+ exc2 = Exception('Error code: 400 - {"error": {"message": "Invalid prompt", "type": "invalid_request_error"}}')
806
+ assert _clean_error_message(exc2) == "Error code: 400 - Invalid prompt"
807
+
808
+ # Test case 3: Standard exception with no JSON/dict
809
+ exc3 = Exception("Connection refused")
810
+ assert _clean_error_message(exc3) == "Connection refused"
811
+
812
+ # Test case 4: Dict representation without error key
813
+ exc4 = Exception("Error: {'message': 'Something went wrong'}")
814
+ assert _clean_error_message(exc4) == "Error - Something went wrong"
@@ -72,6 +72,10 @@ def _result_task_state(result: dict) -> TaskState:
72
72
  return TaskState.model_validate(result["task_state"])
73
73
 
74
74
 
75
+ def _asked_tool_calls(batch):
76
+ return [getattr(item, "tool_call", item) for item in batch]
77
+
78
+
75
79
  def _child_goal_resolution(
76
80
  goal_type: str = "feature",
77
81
  *,
@@ -191,7 +195,7 @@ async def test_graph_authorization_prompts_for_implement_agent(tmp_path):
191
195
 
192
196
  assert [tc["name"] for tc in approved] == ["agent"]
193
197
  assert denied == []
194
- assert [[tc["args"]["goal_resolution"]["plan"]["join"] for tc in batch] for batch in asked] == [["tdd"]]
198
+ assert [[tc["args"]["goal_resolution"]["plan"]["join"] for tc in _asked_tool_calls(batch)] for batch in asked] == [["tdd"]]
195
199
 
196
200
 
197
201
  @pytest.mark.asyncio
@@ -210,6 +214,34 @@ async def test_graph_authorization_respects_session_deny_for_safe_bash(tmp_path)
210
214
  assert "Permission denied" in denied[0][1]
211
215
 
212
216
 
217
+ @pytest.mark.asyncio
218
+ async def test_graph_authorization_never_approves_mixed_blocked_batch(tmp_path):
219
+ graph = _graph(tmp_path)
220
+ graph._permission.permission_preset = "safe"
221
+ asked: list[list[object]] = []
222
+
223
+ async def approve(tool_calls):
224
+ asked.append(tool_calls)
225
+ return "y"
226
+
227
+ graph._ask_tool_permission = approve
228
+
229
+ approved, denied = await graph._authorize_tool_calls(
230
+ [
231
+ {"name": "bash", "args": {"command": "rm -rf /"}, "id": "blocked"},
232
+ {"name": "bash", "args": {"command": "echo $(date)"}, "id": "ask"},
233
+ ],
234
+ plan_mode=False,
235
+ session_id="test",
236
+ )
237
+
238
+ assert [call["id"] for call in approved] == ["ask"]
239
+ assert [call["id"] for call, _ in denied] == ["blocked"]
240
+ assert len(asked) == 2
241
+ assert [item.tool_call["id"] for item in asked[0]] == ["blocked"]
242
+ assert [item.tool_call["id"] for item in asked[1]] == ["ask"]
243
+
244
+
213
245
  @pytest.mark.asyncio
214
246
  async def test_graph_authorization_asks_for_write_by_active_workflow_gate(tmp_path):
215
247
  graph = _graph(tmp_path)
@@ -231,7 +263,7 @@ async def test_graph_authorization_asks_for_write_by_active_workflow_gate(tmp_pa
231
263
  ],
232
264
  )
233
265
 
234
- assert [[call["id"] for call in batch] for batch in asked] == [["call_1"]]
266
+ assert [[call["id"] for call in _asked_tool_calls(batch)] for batch in asked] == [["call_1"]]
235
267
  assert [call["id"] for call in approved] == ["call_1"]
236
268
  assert denied == []
237
269
 
@@ -294,7 +326,7 @@ async def test_graph_authorization_allows_plan_gate_doc_paths_only(tmp_path):
294
326
  )
295
327
 
296
328
  assert [call["id"] for call in approved] == ["call_docs"]
297
- assert [[call["id"] for call in batch] for batch in asked] == [["call_src"]]
329
+ assert [[call["id"] for call in _asked_tool_calls(batch)] for batch in asked] == [["call_src"]]
298
330
  assert [call["id"] for call, _reason in denied] == ["call_src"]
299
331
  assert denied[0][1] == "User denied: replace"
300
332
 
@@ -371,7 +403,7 @@ async def test_graph_authorization_asks_for_workflow_gate_tools_instead_of_denyi
371
403
  ],
372
404
  )
373
405
 
374
- assert [[call["id"] for call in batch] for batch in asked] == [["call_src"]]
406
+ assert [[call["id"] for call in _asked_tool_calls(batch)] for batch in asked] == [["call_src"]]
375
407
  assert [call["id"] for call in approved] == ["call_src"]
376
408
  assert denied == []
377
409
 
@@ -470,6 +502,9 @@ async def test_permission_prompt_uses_dock_details_when_events_are_active(tmp_pa
470
502
  "name": "bash",
471
503
  "pattern": "npm install lodash",
472
504
  "args": {"command": "npm install lodash"},
505
+ "risk": None,
506
+ "allowed_scopes": [],
507
+ "default_scope": None,
473
508
  }]
474
509
  record = test_dock.status_record("permission:request")
475
510
  assert record is not None
@@ -480,3 +515,154 @@ async def test_permission_prompt_uses_dock_details_when_events_are_active(tmp_pa
480
515
  await graph._ui.events.stop()
481
516
  test_dock.deactivate()
482
517
  set_dock(None)
518
+
519
+
520
+ @pytest.mark.asyncio
521
+ async def test_read_only_permission_prompt_limits_choices_to_once(tmp_path):
522
+ graph = _graph(tmp_path)
523
+ graph._permission.sandbox_mode = "read-only"
524
+ graph._permission.permission_mode = "read-only"
525
+ graph._permission.approval_policy = "untrusted"
526
+ captured_choices = None
527
+
528
+ class FakeApp:
529
+ async def ask_choice(self, _prompt, choices, details=None):
530
+ nonlocal captured_choices
531
+ captured_choices = choices
532
+ return "y"
533
+
534
+ graph._app = FakeApp()
535
+
536
+ approved, denied = await graph._authorize_tool_calls(
537
+ [{"name": "bash", "args": {"command": "cat input.txt > output.txt"}, "id": "call_1"}],
538
+ plan_mode=False,
539
+ session_id="s",
540
+ )
541
+
542
+ assert [tc["name"] for tc in approved] == ["bash"]
543
+ assert denied == []
544
+ assert captured_choices == [
545
+ ("Yes", "y", "Allow this tool use once"),
546
+ ("No", "n", "Deny these tools"),
547
+ ]
548
+
549
+
550
+ @pytest.mark.asyncio
551
+ async def test_permission_prompt_details_include_risk_and_scopes(tmp_path):
552
+ graph = _graph(tmp_path)
553
+ graph._permission.permission_mode = "default"
554
+ graph._permission.approval_policy = "untrusted"
555
+ received_details = None
556
+
557
+ class FakeApp:
558
+ async def ask_choice(self, _prompt, _choices, details=None):
559
+ nonlocal received_details
560
+ received_details = details
561
+ return "y"
562
+
563
+ graph._app = FakeApp()
564
+
565
+ approved, denied = await graph._authorize_tool_calls(
566
+ [{"name": "bash", "args": {"command": "npm install lodash"}, "id": "call_1"}],
567
+ plan_mode=False,
568
+ session_id="s",
569
+ )
570
+
571
+ assert [tc["name"] for tc in approved] == ["bash"]
572
+ assert denied == []
573
+ assert received_details == [{
574
+ "name": "bash",
575
+ "pattern": "npm install lodash",
576
+ "args": {"command": "npm install lodash"},
577
+ "risk": {
578
+ "level": "extreme",
579
+ "tags": ["dependency_install"],
580
+ "reason": "shell policy deferred: dependency install command",
581
+ "tool_name": "bash",
582
+ "pattern": "npm install lodash",
583
+ },
584
+ "allowed_scopes": ["once"],
585
+ "default_scope": "once",
586
+ }]
587
+
588
+
589
+ @pytest.mark.asyncio
590
+ async def test_graph_authorization_attaches_approved_risk_token_to_approved_shell_call(tmp_path):
591
+ graph = _graph(tmp_path)
592
+ graph._permission.sandbox_mode = "read-only"
593
+ graph._permission.permission_mode = "read-only"
594
+ graph._permission.approval_policy = "untrusted"
595
+
596
+ async def approve(_tool_calls):
597
+ return "y"
598
+
599
+ graph._ask_tool_permission = approve
600
+ command = "cat input.txt > output.txt"
601
+
602
+ approved, denied = await graph._authorize_tool_calls(
603
+ [{"name": "bash", "args": {"command": command}, "id": "call_1"}],
604
+ plan_mode=False,
605
+ session_id="s",
606
+ )
607
+
608
+ assert denied == []
609
+ assert approved[0]["metadata"]["approved_risk"] == {
610
+ "tool_name": "bash",
611
+ "pattern": command,
612
+ "risk_level": "extreme",
613
+ "tags": ["dynamic_shell"],
614
+ "reason": "shell policy deferred: compound shell syntax, compound shell operator",
615
+ }
616
+
617
+
618
+ @pytest.mark.asyncio
619
+ async def test_blocked_permission_prompt_only_acknowledges_and_denies_execution(tmp_path):
620
+ graph = _graph(tmp_path)
621
+ graph._permission.permission_mode = "default"
622
+ graph._permission.approval_policy = "untrusted"
623
+ captured_choices = None
624
+ captured_details = None
625
+
626
+ class FakeApp:
627
+ async def ask_choice(self, _prompt, choices, details=None):
628
+ nonlocal captured_choices, captured_details
629
+ captured_choices = choices
630
+ captured_details = details
631
+ return "n"
632
+
633
+ graph._app = FakeApp()
634
+
635
+ approved, denied = await graph._authorize_tool_calls(
636
+ [{"name": "bash", "args": {"command": "sudo true"}, "id": "call_blocked"}],
637
+ plan_mode=False,
638
+ session_id="s",
639
+ )
640
+
641
+ assert approved == []
642
+ assert denied == [({"name": "bash", "args": {"command": "sudo true"}, "id": "call_blocked"}, "Blocked: sudo is blocked — privilege escalation")]
643
+ assert captured_choices == [("Do not run", "n", "This command is blocked")]
644
+ assert captured_details[0]["risk"]["level"] == "blocked"
645
+ assert captured_details[0]["allowed_scopes"] == []
646
+ assert captured_details[0]["default_scope"] is None
647
+
648
+
649
+ @pytest.mark.asyncio
650
+ async def test_blocked_permission_prompt_cannot_be_approved_with_yes(tmp_path):
651
+ graph = _graph(tmp_path)
652
+ graph._permission.permission_mode = "default"
653
+ graph._permission.approval_policy = "untrusted"
654
+
655
+ class FakeApp:
656
+ async def ask_choice(self, _prompt, _choices, details=None):
657
+ return "y"
658
+
659
+ graph._app = FakeApp()
660
+
661
+ approved, denied = await graph._authorize_tool_calls(
662
+ [{"name": "bash", "args": {"command": "sudo true"}, "id": "call_blocked"}],
663
+ plan_mode=False,
664
+ session_id="s",
665
+ )
666
+
667
+ assert approved == []
668
+ assert denied == [({"name": "bash", "args": {"command": "sudo true"}, "id": "call_blocked"}, "Blocked: sudo is blocked — privilege escalation")]
@@ -72,6 +72,10 @@ def _result_task_state(result: dict) -> TaskState:
72
72
  return TaskState.model_validate(result["task_state"])
73
73
 
74
74
 
75
+ def _asked_tool_calls(batch):
76
+ return [getattr(item, "tool_call", item) for item in batch]
77
+
78
+
75
79
  def _child_goal_resolution(
76
80
  goal_type: str = "feature",
77
81
  *,
@@ -320,6 +324,13 @@ async def test_subagent_runner_authorizes_with_child_interaction_mode(tmp_path,
320
324
  async def test_graph_authorization_does_not_treat_goal_as_read_only_mode(tmp_path):
321
325
  graph = _graph(tmp_path)
322
326
  graph._permission.approval_policy = "on-request"
327
+ asked: list[list[dict]] = []
328
+
329
+ async def approve(tool_calls):
330
+ asked.append(tool_calls)
331
+ return "y"
332
+
333
+ graph._ask_tool_permission = approve
323
334
 
324
335
  approved, denied = await graph._authorize_tool_calls(
325
336
  [{"name": "edit", "args": {"file_path": "src/app.py"}, "id": "call_1"}],
@@ -331,6 +342,7 @@ async def test_graph_authorization_does_not_treat_goal_as_read_only_mode(tmp_pat
331
342
 
332
343
  assert [tc["name"] for tc in approved] == ["replace"]
333
344
  assert denied == []
345
+ assert [[tc["name"] for tc in _asked_tool_calls(batch)] for batch in asked] == [["replace"]]
334
346
 
335
347
 
336
348
  @pytest.mark.asyncio
@@ -369,7 +381,7 @@ async def test_graph_authorization_prompts_for_edit(tmp_path):
369
381
 
370
382
  assert [tc["name"] for tc in approved] == ["replace"]
371
383
  assert denied == []
372
- assert [[tc["name"] for tc in batch] for batch in asked] == [["replace"]]
384
+ assert [[tc["name"] for tc in _asked_tool_calls(batch)] for batch in asked] == [["replace"]]
373
385
 
374
386
 
375
387
  @pytest.mark.asyncio
@@ -413,4 +425,4 @@ async def test_graph_authorization_prompts_for_unsafe_bash(tmp_path):
413
425
 
414
426
  assert [tc["name"] for tc in approved] == ["bash"]
415
427
  assert denied == []
416
- assert [[tc["name"] for tc in batch] for batch in asked] == [["bash"]]
428
+ assert [[tc["name"] for tc in _asked_tool_calls(batch)] for batch in asked] == [["bash"]]
@@ -135,7 +135,7 @@ def _tree_nodes(root):
135
135
  @pytest.mark.asyncio
136
136
  async def test_graph_on_request_auto_approves_need_ask_tools(tmp_path):
137
137
  graph = _graph(tmp_path)
138
- graph._permission.approval_policy = "on-request"
138
+ graph._permission.permission_preset = "full_access"
139
139
 
140
140
  approved, denied = await graph._authorize_tool_calls(
141
141
  [{"name": "write", "args": {"file_path": "app.py", "op": "append", "new_string": "x"}, "id": "call_1"}],
@@ -0,0 +1,236 @@
1
+ """Test: turn stop without pending provisional text in running state.
2
+
3
+ When the main agent calls a child agent (e.g. review) and the child returns,
4
+ the main agent may call turn operation='stop' directly without first emitting
5
+ plain text. In that case pending_provisional is None and validate_turn_call
6
+ rejects the stop. The INVALID_TURN_PROMPT then tells the LLM to "not output
7
+ text, call turn stop" — which is contradictory because there is no pending
8
+ text to commit. This creates a dead loop that ends with a failure message
9
+ and should_continue=False, producing no user-facing text.
10
+ """
11
+
12
+ import pytest
13
+ from langchain_core.messages import AIMessage, AIMessageChunk, HumanMessage, ToolMessage
14
+
15
+ from voidx.agent.graph import VoidXGraph
16
+ from voidx.config import Config, ModelConfig
17
+ from voidx.ui.output.events import AssistantStreamCommitted, AssistantStreamUpdated
18
+ from tests.test_agent.graph.stream_llm_helpers import FakeRenderer
19
+
20
+
21
+ class ScriptedStreamingModel:
22
+ def __init__(self, scripts: list[list[AIMessageChunk]]) -> None:
23
+ self.scripts = list(scripts)
24
+ self.call_index = 0
25
+ self.bound_tools = None
26
+
27
+ def bind_tools(self, tool_defs):
28
+ self.bound_tools = tool_defs
29
+ return self
30
+
31
+ async def astream(self, messages):
32
+ idx = self.call_index
33
+ self.call_index += 1
34
+ if idx >= len(self.scripts):
35
+ pytest.fail(
36
+ f"Unexpected LLM call {idx + 1}; "
37
+ f"only {len(self.scripts)} scripted responses were provided"
38
+ )
39
+ for chunk in self.scripts[idx]:
40
+ yield chunk
41
+
42
+
43
+ def _turn_stop_chunk() -> AIMessageChunk:
44
+ return AIMessageChunk(
45
+ content="",
46
+ tool_calls=[{
47
+ "name": "turn",
48
+ "args": {"operation": "stop", "intent": "", "goal": ""},
49
+ "id": "tc1",
50
+ "type": "tool_call",
51
+ }],
52
+ )
53
+
54
+
55
+ def _text_chunk(text: str) -> AIMessageChunk:
56
+ return AIMessageChunk(content=text)
57
+
58
+
59
+ def _text_and_turn_stop_chunk(text: str) -> AIMessageChunk:
60
+ return AIMessageChunk(
61
+ content=text,
62
+ tool_calls=[{
63
+ "name": "turn",
64
+ "args": {"operation": "stop", "intent": "", "goal": ""},
65
+ "id": "tc1",
66
+ "type": "tool_call",
67
+ }],
68
+ )
69
+
70
+
71
+ def _make_graph(tmp_path, model, monkeypatch, provider="openai"):
72
+ import voidx.agent.graph.core.llm as graph_module
73
+
74
+ async def fail_on_retry(delay):
75
+ pytest.fail(f"Unexpected LLM retry with delay {delay}s")
76
+
77
+ monkeypatch.setattr(graph_module, "StreamingRenderer", FakeRenderer)
78
+ monkeypatch.setattr(graph_module.asyncio, "sleep", fail_on_retry)
79
+
80
+ graph = VoidXGraph(
81
+ Config(
82
+ model=ModelConfig(provider=provider, model="test-model"),
83
+ workspace=str(tmp_path),
84
+ ),
85
+ api_key=None,
86
+ )
87
+ graph.model = model
88
+ return graph
89
+
90
+
91
+ @pytest.mark.asyncio
92
+ async def test_turn_stop_in_running_state_without_pending_emits_text(tmp_path, monkeypatch):
93
+ """When turn_state='running' and LLM calls turn stop without prior text,
94
+ the agent should recover by prompting the LLM to produce text, not enter
95
+ a dead loop that ends with a bare failure message.
96
+ """
97
+ model = ScriptedStreamingModel([
98
+ # 1) LLM calls turn stop directly (no text, no pending_provisional)
99
+ [_turn_stop_chunk()],
100
+ # 2) After MISSING_PENDING_PROMPT, LLM outputs plain text summary
101
+ [_text_chunk("Review completed: PASS")],
102
+ # 3) After TURN_STOP_PROMPT, LLM calls turn stop to commit
103
+ [_turn_stop_chunk()],
104
+ ])
105
+ graph = _make_graph(tmp_path, model, monkeypatch)
106
+
107
+ result = await graph._call_llm({
108
+ "messages": [HumanMessage(content="Run review")],
109
+ "step_count": 1,
110
+ "persona": "coordinate",
111
+ "turn_state": "running",
112
+ })
113
+
114
+ # The agent should produce user-facing text, not a bare failure message.
115
+ msg = result["messages"][0]
116
+ assert isinstance(msg, AIMessage)
117
+ assert not msg.tool_calls
118
+ text = (msg.content or "").strip() if isinstance(msg.content, str) else ""
119
+ assert "Review completed" in text
120
+ assert "LLM call failed" not in text
121
+
122
+
123
+ @pytest.mark.parametrize("repair_shape", ["text_then_stop", "text_and_stop"])
124
+ @pytest.mark.asyncio
125
+ async def test_headless_repair_commit_emits_user_visible_stream(tmp_path, monkeypatch, repair_shape):
126
+ """Gemini often repairs missing pending text by returning text + turn stop
127
+ in one headless repair call. The committed answer must still be emitted to
128
+ the UI; checking only result["messages"] misses the user-visible blank turn.
129
+ """
130
+ import voidx.agent.graph.core.llm as graph_module
131
+
132
+ emitted = []
133
+
134
+ class TrackingEvents:
135
+ async def emit(self, event):
136
+ emitted.append(event)
137
+ return True
138
+
139
+ def emit_direct(self, event):
140
+ emitted.append(event)
141
+ return True
142
+
143
+ async def drain(self):
144
+ pass
145
+
146
+ @property
147
+ def is_running(self):
148
+ return True
149
+
150
+ class TrackingUi:
151
+ class Output:
152
+ def print(self, *args, **kwargs):
153
+ pass
154
+
155
+ def error(self, *args, **kwargs):
156
+ pass
157
+
158
+ def __init__(self):
159
+ self.events = TrackingEvents()
160
+ self.console = None
161
+ self.ui = self.Output()
162
+
163
+ def via_events(self):
164
+ return True
165
+
166
+ class HeadlessAwareRenderer(FakeRenderer):
167
+ def __init__(self, *args, **kwargs) -> None:
168
+ super().__init__(*args, **kwargs)
169
+ self.headless = bool(kwargs.get("headless", False))
170
+
171
+ def feed_text(self, text: str) -> None:
172
+ if not self.headless:
173
+ super().feed_text(text)
174
+
175
+ async def fail_on_retry(delay):
176
+ pytest.fail(f"Unexpected LLM retry with delay {delay}s")
177
+
178
+ monkeypatch.setattr(graph_module, "StreamingRenderer", HeadlessAwareRenderer)
179
+ monkeypatch.setattr(graph_module.asyncio, "sleep", fail_on_retry)
180
+
181
+ scripts = [[_turn_stop_chunk()]]
182
+ if repair_shape == "text_then_stop":
183
+ scripts.extend([[_text_chunk("Review completed: PASS")], [_turn_stop_chunk()]])
184
+ else:
185
+ scripts.append([_text_and_turn_stop_chunk("Review completed: PASS")])
186
+ model = ScriptedStreamingModel(scripts)
187
+ graph = VoidXGraph(
188
+ Config(
189
+ model=ModelConfig(provider="gemini", model="gemini-test"),
190
+ workspace=str(tmp_path),
191
+ ),
192
+ api_key=None,
193
+ )
194
+ graph.model = model
195
+ graph._ui = TrackingUi()
196
+
197
+ result = await graph._call_llm({
198
+ "messages": [HumanMessage(content="Run review")],
199
+ "step_count": 1,
200
+ "persona": "coordinate",
201
+ "turn_state": "running",
202
+ })
203
+
204
+ assert result["messages"][0].content == "Review completed: PASS"
205
+ stream_updates = [event for event in emitted if isinstance(event, AssistantStreamUpdated)]
206
+ assert any("Review completed: PASS" in event.text for event in stream_updates)
207
+ assert any(isinstance(event, AssistantStreamCommitted) for event in emitted)
208
+
209
+
210
+ @pytest.mark.asyncio
211
+ async def test_turn_stop_with_text_after_missing_pending(tmp_path, monkeypatch):
212
+ """When MISSING_PENDING_PROMPT is injected and LLM responds with text +
213
+ turn stop in the same message, the agent should accept the text as
214
+ pending and commit it, not treat it as INVALID_TURN.
215
+ """
216
+ model = ScriptedStreamingModel([
217
+ # 1) LLM calls turn stop directly (no text, no pending_provisional)
218
+ [_turn_stop_chunk()],
219
+ # 2) After MISSING_PENDING_PROMPT, LLM outputs text + turn stop together
220
+ [_text_chunk("Review completed: PASS"), _turn_stop_chunk()],
221
+ ])
222
+ graph = _make_graph(tmp_path, model, monkeypatch)
223
+
224
+ result = await graph._call_llm({
225
+ "messages": [HumanMessage(content="Run review")],
226
+ "step_count": 1,
227
+ "persona": "coordinate",
228
+ "turn_state": "running",
229
+ })
230
+
231
+ msg = result["messages"][0]
232
+ assert isinstance(msg, AIMessage)
233
+ assert not msg.tool_calls
234
+ text = (msg.content or "").strip() if isinstance(msg.content, str) else ""
235
+ assert "Review completed" in text
236
+ assert "LLM call failed" not in text
@@ -132,7 +132,9 @@ def _tree_nodes(root):
132
132
 
133
133
 
134
134
  @pytest.mark.asyncio
135
- async def test_workflow_done_stops_before_followup_llm_when_workflow_complete(tmp_path):
135
+ async def test_workflow_done_returns_to_llm_when_workflow_complete(tmp_path):
136
+ from voidx.agent.graph.topology import route_after_execute_tools
137
+
136
138
  graph = _graph(tmp_path)
137
139
  parent = AIMessage(
138
140
  content="",
@@ -164,7 +166,8 @@ async def test_workflow_done_stops_before_followup_llm_when_workflow_complete(tm
164
166
  ),
165
167
  })
166
168
 
167
- assert result["should_continue"] is False
169
+ assert result.get("should_continue") is not False
170
+ assert route_after_execute_tools(result) == "call_llm"
168
171
  by_name = {run.name: run for run in _result_task_state(result).workflow_runs.values()}
169
172
  assert by_name["verify"].status == WorkflowRunStatus.SATISFIED
170
173
 
@@ -256,7 +259,9 @@ async def test_workflow_route_end_satisfies_non_review_without_successor(tmp_pat
256
259
 
257
260
 
258
261
  @pytest.mark.asyncio
259
- async def test_multiple_workflow_done_calls_finish_batch_before_stopping(tmp_path):
262
+ async def test_multiple_workflow_done_calls_finish_batch_before_returning_to_llm(tmp_path):
263
+ from voidx.agent.graph.topology import route_after_execute_tools
264
+
260
265
  graph = _graph(tmp_path)
261
266
  parent = AIMessage(
262
267
  content="",
@@ -303,9 +308,9 @@ async def test_multiple_workflow_done_calls_finish_batch_before_stopping(tmp_pat
303
308
  "call_design_done",
304
309
  "call_verify_done",
305
310
  ]
306
- assert result["should_continue"] is False
311
+ assert result.get("should_continue") is not False
312
+ assert route_after_execute_tools(result) == "call_llm"
307
313
  by_name = {run.name: run for run in _result_task_state(result).workflow_runs.values()}
308
314
  assert by_name["design"].status == WorkflowRunStatus.SATISFIED
309
315
  assert by_name["verify"].status == WorkflowRunStatus.SATISFIED
310
316
 
311
-
@@ -301,6 +301,9 @@ async def test_workflow_transaction_reauthorizes_following_write(tmp_path):
301
301
  nonlocal invalidations
302
302
  invalidations += 1
303
303
 
304
+ async def ask_choice(self, _prompt, _choices, details=None):
305
+ return "y"
306
+
304
307
  graph._app = FakeApp()
305
308
  parent = AIMessage(
306
309
  content="",