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