voidx 3.4.4__tar.gz → 3.5.1__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 (543) hide show
  1. {voidx-3.4.4/src/voidx.egg-info → voidx-3.5.1}/PKG-INFO +1 -1
  2. {voidx-3.4.4 → voidx-3.5.1}/pyproject.toml +3 -3
  3. voidx-3.5.1/src/tests/conftest.py +17 -0
  4. voidx-3.5.1/src/tests/test_agent/conftest.py +101 -0
  5. voidx-3.5.1/src/tests/test_agent/graph/run_loop_helpers.py +107 -0
  6. voidx-3.5.1/src/tests/test_agent/graph/stream_llm_helpers.py +252 -0
  7. voidx-3.5.1/src/tests/test_agent/graph/test_call_llm_compaction.py +629 -0
  8. voidx-3.5.1/src/tests/test_agent/graph/test_call_llm_compaction_advanced.py +247 -0
  9. voidx-3.5.1/src/tests/test_agent/graph/test_call_llm_tools.py +336 -0
  10. voidx-3.5.1/src/tests/test_agent/graph/test_compaction_flow.py +462 -0
  11. voidx-3.5.1/src/tests/test_agent/graph/test_compaction_flow_run_once.py +370 -0
  12. voidx-3.5.1/src/tests/test_agent/graph/test_convergence.py +74 -0
  13. voidx-3.5.1/src/tests/test_agent/graph/test_execute_tools_guard.py +671 -0
  14. voidx-3.5.1/src/tests/test_agent/graph/test_execute_tools_todo.py +439 -0
  15. voidx-3.5.1/src/tests/test_agent/graph/test_graph_authorization.py +478 -0
  16. voidx-3.5.1/src/tests/test_agent/graph/test_graph_setup_prompts.py +351 -0
  17. voidx-3.5.1/src/tests/test_agent/graph/test_guards_tool_op.py +301 -0
  18. voidx-3.5.1/src/tests/test_agent/graph/test_parallel_subagents.py +420 -0
  19. voidx-3.5.1/src/tests/test_agent/graph/test_parallel_subagents_dedup.py +391 -0
  20. voidx-3.5.1/src/tests/test_agent/graph/test_prepare_workflow.py +354 -0
  21. voidx-3.5.1/src/tests/test_agent/graph/test_run_loop_startup.py +469 -0
  22. voidx-3.5.1/src/tests/test_agent/graph/test_run_loop_title_lsp.py +157 -0
  23. voidx-3.5.1/src/tests/test_agent/graph/test_run_loop_title_misc.py +174 -0
  24. voidx-3.5.1/src/tests/test_agent/graph/test_run_loop_workflow.py +172 -0
  25. voidx-3.5.1/src/tests/test_agent/graph/test_run_loop_workflow_advanced.py +148 -0
  26. voidx-3.5.1/src/tests/test_agent/graph/test_runtime_guards.py +401 -0
  27. voidx-3.5.1/src/tests/test_agent/graph/test_session_context_frames.py +199 -0
  28. voidx-3.5.1/src/tests/test_agent/graph/test_session_crud.py +420 -0
  29. voidx-3.5.1/src/tests/test_agent/graph/test_session_messages.py +468 -0
  30. voidx-3.5.1/src/tests/test_agent/graph/test_session_persistence.py +545 -0
  31. voidx-3.5.1/src/tests/test_agent/graph/test_session_run_once.py +341 -0
  32. voidx-3.5.1/src/tests/test_agent/graph/test_session_runtime_state.py +406 -0
  33. voidx-3.5.1/src/tests/test_agent/graph/test_session_transcript.py +484 -0
  34. voidx-3.5.1/src/tests/test_agent/graph/test_stream_llm_sanitization.py +527 -0
  35. voidx-3.5.1/src/tests/test_agent/graph/test_subagent_persistence.py +389 -0
  36. voidx-3.5.1/src/tests/test_agent/graph/test_subagent_runner.py +416 -0
  37. voidx-3.5.1/src/tests/test_agent/graph/test_subagent_step_budget.py +375 -0
  38. voidx-3.5.1/src/tests/test_agent/graph/test_subagent_step_budget_convergence.py +364 -0
  39. voidx-3.5.1/src/tests/test_agent/graph/test_subagent_step_budget_final.py +515 -0
  40. voidx-3.5.1/src/tests/test_agent/graph/test_todo_events.py +290 -0
  41. voidx-3.5.1/src/tests/test_agent/graph/test_tool_execution_auth.py +386 -0
  42. voidx-3.5.1/src/tests/test_agent/graph/test_tool_result_preview.py +248 -0
  43. voidx-3.5.1/src/tests/test_agent/graph/test_workflow_done.py +314 -0
  44. voidx-3.5.1/src/tests/test_agent/graph/test_workflow_review.py +319 -0
  45. voidx-3.5.1/src/tests/test_agent/graph/test_workflow_transactions.py +315 -0
  46. voidx-3.5.1/src/tests/test_agent/graph/test_workflow_transactions_barrier.py +350 -0
  47. voidx-3.5.1/src/tests/test_agent/slash/__init__.py +0 -0
  48. voidx-3.5.1/src/tests/test_agent/slash/test_slash_init.py +97 -0
  49. voidx-3.5.1/src/tests/test_agent/slash/test_slash_mcp.py +185 -0
  50. voidx-3.5.1/src/tests/test_agent/slash/test_slash_model.py +521 -0
  51. voidx-3.5.1/src/tests/test_agent/slash/test_slash_model_advanced.py +466 -0
  52. voidx-3.5.1/src/tests/test_agent/slash/test_slash_session.py +453 -0
  53. voidx-3.5.1/src/tests/test_agent/slash/test_slash_skills.py +84 -0
  54. voidx-3.5.1/src/tests/test_agent/slash/test_slash_tavily.py +197 -0
  55. voidx-3.5.1/src/tests/test_agent/slash/test_slash_upgrade.py +108 -0
  56. voidx-3.5.1/src/tests/test_agent/test_attachments.py +185 -0
  57. voidx-3.5.1/src/tests/test_agent/test_file_rwlock.py +304 -0
  58. voidx-3.5.1/src/tests/test_agent/test_goal_resolver.py +557 -0
  59. voidx-3.5.1/src/tests/test_agent/test_goal_resolver_advanced.py +400 -0
  60. voidx-3.5.1/src/tests/test_agent/test_message_trimming_parsers.py +214 -0
  61. voidx-3.5.1/src/tests/test_agent/test_message_trimming_rules.py +493 -0
  62. voidx-3.5.1/src/tests/test_agent/test_module_boundaries.py +240 -0
  63. voidx-3.5.1/src/tests/test_agent/test_permission.py +480 -0
  64. voidx-3.5.1/src/tests/test_agent/test_permission_append.py +21 -0
  65. voidx-3.5.1/src/tests/test_agent/test_prompts.py +53 -0
  66. voidx-3.5.1/src/tests/test_agent/test_runtime_context_builder.py +555 -0
  67. voidx-3.5.1/src/tests/test_agent/test_runtime_context_prompts.py +40 -0
  68. voidx-3.5.1/src/tests/test_agent/test_runtime_context_skill_stripping.py +288 -0
  69. voidx-3.5.1/src/tests/test_agent/test_task_state.py +216 -0
  70. voidx-3.5.1/src/tests/test_agent/test_task_state_rendering.py +229 -0
  71. voidx-3.5.1/src/tests/test_agent/test_todo_replay_sanitization.py +60 -0
  72. voidx-3.5.1/src/tests/test_agent/test_tool_exchange_sanitizer.py +166 -0
  73. voidx-3.5.1/src/tests/test_agent/test_tool_filters_gemini.py +124 -0
  74. voidx-3.5.1/src/tests/test_agent/test_tool_messages.py +19 -0
  75. voidx-3.5.1/src/tests/test_agent/test_tool_result_storage.py +101 -0
  76. voidx-3.5.1/src/tests/test_config/__init__.py +0 -0
  77. voidx-3.5.1/src/tests/test_config/test_config.py +354 -0
  78. voidx-3.5.1/src/tests/test_config/test_config_advanced.py +500 -0
  79. {voidx-3.4.4 → voidx-3.5.1/src}/tests/test_install_sh.py +4 -4
  80. voidx-3.5.1/src/tests/test_llm/conftest.py +60 -0
  81. voidx-3.5.1/src/tests/test_llm/test_compaction_retry.py +500 -0
  82. voidx-3.5.1/src/tests/test_llm/test_fallback_summary.py +110 -0
  83. voidx-3.5.1/src/tests/test_llm/test_gemini_provider.py +347 -0
  84. voidx-3.5.1/src/tests/test_llm/test_instruction_cache.py +88 -0
  85. voidx-3.5.1/src/tests/test_llm/test_llm_catalog.py +49 -0
  86. voidx-3.5.1/src/tests/test_llm/test_llm_provider.py +387 -0
  87. voidx-3.5.1/src/tests/test_llm/test_llm_provider_advanced.py +379 -0
  88. voidx-3.5.1/src/tests/test_llm/test_llm_usage.py +211 -0
  89. voidx-3.5.1/src/tests/test_llm/test_overflow_threshold.py +83 -0
  90. voidx-3.5.1/src/tests/test_llm/test_prune_args.py +451 -0
  91. voidx-3.5.1/src/tests/test_llm/test_request_log.py +315 -0
  92. voidx-3.5.1/src/tests/test_llm/test_streaming_sanitize.py +102 -0
  93. voidx-3.5.1/src/tests/test_llm/test_token_counting.py +377 -0
  94. voidx-3.5.1/src/tests/test_logging/test_internal_error.py +67 -0
  95. voidx-3.5.1/src/tests/test_logging/test_tool_log.py +117 -0
  96. voidx-3.5.1/src/tests/test_lsp/__init__.py +0 -0
  97. voidx-3.5.1/src/tests/test_lsp/test_lsp.py +359 -0
  98. voidx-3.5.1/src/tests/test_lsp/test_lsp_advanced.py +331 -0
  99. voidx-3.5.1/src/tests/test_mcp/__init__.py +0 -0
  100. voidx-3.5.1/src/tests/test_mcp/test_mcp.py +376 -0
  101. voidx-3.5.1/src/tests/test_memory/__init__.py +0 -0
  102. voidx-3.5.1/src/tests/test_memory/test_main.py +76 -0
  103. voidx-3.5.1/src/tests/test_memory/test_main_startup.py +129 -0
  104. voidx-3.5.1/src/tests/test_memory/test_schema_migration.py +111 -0
  105. {voidx-3.4.4 → voidx-3.5.1/src}/tests/test_npm_package.py +35 -1
  106. voidx-3.5.1/src/tests/test_permission/__init__.py +0 -0
  107. voidx-3.5.1/src/tests/test_runtime/__init__.py +0 -0
  108. voidx-3.5.1/src/tests/test_runtime/test_goal_resolution_refactor.py +125 -0
  109. voidx-3.5.1/src/tests/test_runtime/test_runtime_ui.py +112 -0
  110. voidx-3.5.1/src/tests/test_selfupdate/__init__.py +0 -0
  111. voidx-3.5.1/src/tests/test_selfupdate/test_selfupdate.py +103 -0
  112. voidx-3.5.1/src/tests/test_skills/__init__.py +0 -0
  113. voidx-3.5.1/src/tests/test_skills/conftest.py +14 -0
  114. voidx-3.5.1/src/tests/test_skills/test_create_skill.py +154 -0
  115. voidx-3.5.1/src/tests/test_skills/test_skill_parsing.py +264 -0
  116. voidx-3.5.1/src/tests/test_skills/test_skill_references.py +356 -0
  117. voidx-3.5.1/src/tests/test_skills/test_workflow_advance.py +495 -0
  118. voidx-3.5.1/src/tests/test_tools/__init__.py +0 -0
  119. voidx-3.5.1/src/tests/test_tools/bash/__init__.py +0 -0
  120. voidx-3.5.1/src/tests/test_tools/bash/test_router_git.py +318 -0
  121. voidx-3.5.1/src/tests/test_tools/bash/test_router_safety.py +94 -0
  122. voidx-3.5.1/src/tests/test_tools/bash/test_router_sed_grep.py +376 -0
  123. voidx-3.5.1/src/tests/test_tools/bash/test_tool.py +165 -0
  124. voidx-3.5.1/src/tests/test_tools/file_ops/__init__.py +0 -0
  125. voidx-3.5.1/src/tests/test_tools/file_ops/test_coverage_fingerprint.py +579 -0
  126. voidx-3.5.1/src/tests/test_tools/file_ops/test_edit_anchors.py +297 -0
  127. voidx-3.5.1/src/tests/test_tools/file_ops/test_edit_bounds_input.py +102 -0
  128. voidx-3.5.1/src/tests/test_tools/file_ops/test_edit_coverage.py +180 -0
  129. voidx-3.5.1/src/tests/test_tools/file_ops/test_edit_dedup.py +298 -0
  130. voidx-3.5.1/src/tests/test_tools/file_ops/test_edit_drift_fallback.py +121 -0
  131. voidx-3.5.1/src/tests/test_tools/file_ops/test_edit_drift_fallback_e2e.py +190 -0
  132. voidx-3.5.1/src/tests/test_tools/file_ops/test_edit_errors.py +136 -0
  133. voidx-3.5.1/src/tests/test_tools/file_ops/test_edit_line_insert.py +217 -0
  134. voidx-3.5.1/src/tests/test_tools/file_ops/test_edit_llm_messages.py +80 -0
  135. voidx-3.5.1/src/tests/test_tools/file_ops/test_edit_replace.py +391 -0
  136. voidx-3.5.1/src/tests/test_tools/file_ops/test_edit_trailing_newline.py +296 -0
  137. voidx-3.5.1/src/tests/test_tools/file_ops/test_read.py +402 -0
  138. voidx-3.5.1/src/tests/test_tools/file_ops/test_read_write.py +309 -0
  139. voidx-3.5.1/src/tests/test_tools/file_ops/test_write_file.py +360 -0
  140. voidx-3.5.1/src/tests/test_tools/test_clarify_tool.py +285 -0
  141. voidx-3.5.1/src/tests/test_tools/test_diffing.py +128 -0
  142. voidx-3.5.1/src/tests/test_tools/test_git_tool_destructive.py +94 -0
  143. voidx-3.5.1/src/tests/test_tools/test_git_tool_raw_permissions.py +391 -0
  144. voidx-3.5.1/src/tests/test_tools/test_git_tool_schema_errors.py +144 -0
  145. voidx-3.5.1/src/tests/test_tools/test_git_tool_structured.py +431 -0
  146. voidx-3.5.1/src/tests/test_tools/test_infer_state_patch.py +72 -0
  147. voidx-3.5.1/src/tests/test_tools/test_interactive_tools.py +454 -0
  148. voidx-3.5.1/src/tests/test_tools/test_interactive_tools_write.py +430 -0
  149. voidx-3.5.1/src/tests/test_tools/test_load_doc_template.py +68 -0
  150. voidx-3.5.1/src/tests/test_tools/test_make_interact_callback.py +201 -0
  151. voidx-3.5.1/src/tests/test_tools/test_plan_checkpoint.py +445 -0
  152. voidx-3.5.1/src/tests/test_tools/test_powershell_tool.py +385 -0
  153. voidx-3.5.1/src/tests/test_tools/test_replace_failure_logging.py +142 -0
  154. voidx-3.5.1/src/tests/test_tools/test_resolve_safe.py +68 -0
  155. voidx-3.5.1/src/tests/test_tools/test_search.py +456 -0
  156. voidx-3.5.1/src/tests/test_tools/test_skills_tool.py +244 -0
  157. voidx-3.5.1/src/tests/test_tools/test_state_update_from_executed_tools.py +267 -0
  158. voidx-3.5.1/src/tests/test_tools/test_task_tracker.py +165 -0
  159. voidx-3.5.1/src/tests/test_tools/test_todo_tool.py +26 -0
  160. voidx-3.5.1/src/tests/test_tools/test_tool_error_handling.py +220 -0
  161. voidx-3.5.1/src/tests/test_tools/test_tool_registry.py +122 -0
  162. voidx-3.5.1/src/tests/test_tools/test_tool_schemas.py +178 -0
  163. voidx-3.5.1/src/tests/test_tools/test_tool_state_patch.py +57 -0
  164. voidx-3.5.1/src/tests/test_tools/test_user_interaction_models.py +58 -0
  165. voidx-3.5.1/src/tests/test_tools/test_web_mcp.py +280 -0
  166. voidx-3.5.1/src/tests/test_tools/test_webfetch.py +157 -0
  167. voidx-3.5.1/src/tests/test_tools/test_workflow_tool.py +634 -0
  168. voidx-3.5.1/src/tests/test_ui/gateway/__init__.py +0 -0
  169. voidx-3.5.1/src/tests/test_ui/gateway/conftest.py +44 -0
  170. voidx-3.5.1/src/tests/test_ui/gateway/helpers.py +23 -0
  171. voidx-3.5.1/src/tests/test_ui/gateway/test_adapter.py +473 -0
  172. voidx-3.5.1/src/tests/test_ui/gateway/test_diff_review.py +217 -0
  173. voidx-3.5.1/src/tests/test_ui/gateway/test_gateway_v2_crud_diff.py +336 -0
  174. voidx-3.5.1/src/tests/test_ui/gateway/test_gateway_v2_dispatch.py +306 -0
  175. voidx-3.5.1/src/tests/test_ui/gateway/test_gateway_v2_routing.py +480 -0
  176. voidx-3.5.1/src/tests/test_ui/gateway/test_gateway_v2_server.py +527 -0
  177. voidx-3.5.1/src/tests/test_ui/gateway/test_gateway_v2_session.py +301 -0
  178. voidx-3.5.1/src/tests/test_ui/gateway/test_run_manager.py +183 -0
  179. voidx-3.5.1/src/tests/test_ui/gateway/test_terminal.py +279 -0
  180. voidx-3.5.1/src/tests/test_ui/gateway/test_ui_events_dock_bus.py +206 -0
  181. voidx-3.5.1/src/tests/test_ui/gateway/test_ui_events_dock_prompts.py +471 -0
  182. voidx-3.5.1/src/tests/test_ui/gateway/test_ui_events_dock_status.py +355 -0
  183. voidx-3.5.1/src/tests/test_ui/gateway/test_ui_events_streaming.py +349 -0
  184. voidx-3.5.1/src/tests/test_ui/gateway/test_ui_events_subagent.py +454 -0
  185. voidx-3.5.1/src/tests/test_ui/gateway/test_ui_events_todo.py +336 -0
  186. voidx-3.5.1/src/tests/test_ui/gateway/test_ui_gateway.py +396 -0
  187. voidx-3.5.1/src/tests/test_ui/output/__init__.py +0 -0
  188. voidx-3.5.1/src/tests/test_ui/output/test_dock_formatting.py +97 -0
  189. voidx-3.5.1/src/tests/test_ui/output/test_fmt_args.py +50 -0
  190. voidx-3.5.1/src/tests/test_ui/output/test_output_browse.py +22 -0
  191. voidx-3.5.1/src/tests/test_ui/output/test_scrollback_flush.py +150 -0
  192. voidx-3.5.1/src/tests/test_ui/output/test_tree_smoke.py +327 -0
  193. voidx-3.5.1/src/tests/test_ui/output/test_ui_diff.py +88 -0
  194. voidx-3.5.1/src/tests/test_ui/output/test_ui_session_changes.py +131 -0
  195. voidx-3.5.1/src/tests/test_ui/protocol/__init__.py +0 -0
  196. voidx-3.5.1/src/tests/test_ui/protocol/test_dto.py +151 -0
  197. voidx-3.5.1/src/tests/test_ui/protocol/test_v2_envelope.py +173 -0
  198. voidx-3.5.1/src/tests/test_ui/protocol/test_v2_methods.py +107 -0
  199. voidx-3.5.1/src/tests/test_ui/protocol/test_v2_snapshot.py +84 -0
  200. voidx-3.5.1/src/tests/test_ui/protocol/test_v2_threads.py +84 -0
  201. voidx-3.5.1/src/tests/test_ui/test_display_policy.py +166 -0
  202. voidx-3.5.1/src/tests/test_ui/test_file_picker.py +68 -0
  203. voidx-3.5.1/src/tests/test_ui/tools/__init__.py +0 -0
  204. voidx-3.5.1/src/tests/test_ui/tools/test_clipboard_image.py +99 -0
  205. voidx-3.5.1/src/tests/test_ui/tools/test_clipboard_image_windows.py +216 -0
  206. voidx-3.5.1/src/tests/test_ui/tools/test_clipboard_text.py +22 -0
  207. voidx-3.5.1/src/tests/test_ui/tools/test_clipboard_text_windows.py +53 -0
  208. voidx-3.5.1/src/tests/test_ui/tools/test_code_ide.py +74 -0
  209. voidx-3.5.1/src/tests/test_workflow/__init__.py +0 -0
  210. voidx-3.5.1/src/tests/test_workflow/test_auto_advance.py +412 -0
  211. voidx-3.5.1/src/tests/test_workflow/test_workflow_reconcile.py +338 -0
  212. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/__init__.py +1 -1
  213. voidx-3.5.1/src/voidx/agent/__init__.py +0 -0
  214. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/attachments.py +2 -1
  215. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/compaction_coordinator.py +0 -8
  216. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/contracts.py +17 -13
  217. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/core/__init__.py +1 -1
  218. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/core/helpers.py +50 -0
  219. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/core/llm.py +25 -3
  220. voidx-3.4.4/src/voidx/agent/graph/core/_voidx_graph.py → voidx-3.5.1/src/voidx/agent/graph/core/voidx_graph.py +134 -3
  221. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/run_loop.py +37 -9
  222. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/runtime_guards.py +8 -4
  223. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/session_runtime.py +4 -0
  224. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/subagent.py +2 -1
  225. voidx-3.5.1/src/voidx/agent/graph/thread_context.py +171 -0
  226. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/tool_executor/executor.py +51 -3
  227. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/tool_executor/helpers.py +27 -0
  228. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/tool_executor/ui.py +3 -3
  229. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/turn_mixin.py +3 -2
  230. voidx-3.5.1/src/voidx/agent/graph/turn_runner.py +513 -0
  231. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/slash/handler.py +2 -6
  232. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/slash/model.py +29 -7
  233. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/slash/runtime.py +2 -1
  234. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/slash/session.py +23 -23
  235. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/todo_state.py +2 -6
  236. voidx-3.5.1/src/voidx/agent/tool_filters.py +58 -0
  237. voidx-3.5.1/src/voidx/config/defaults.py +12 -0
  238. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/models.py +3 -2
  239. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/settings.py +55 -13
  240. voidx-3.5.1/src/voidx/llm/__init__.py +0 -0
  241. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/llm/catalog.py +3 -0
  242. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/llm/context.py +4 -2
  243. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/llm/instruction.py +2 -1
  244. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/llm/provider.py +54 -8
  245. voidx-3.5.1/src/voidx/logging/__init__.py +7 -0
  246. voidx-3.5.1/src/voidx/logging/internal_error.py +77 -0
  247. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/logging/request_log.py +3 -1
  248. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/logging/tool_log.py +3 -1
  249. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/lsp/client.py +7 -6
  250. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/lsp/config.py +1 -2
  251. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/lsp/detector.py +3 -2
  252. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/mcp/client/base.py +3 -2
  253. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/memory/session.py +18 -11
  254. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/memory/store.py +43 -25
  255. voidx-3.5.1/src/voidx/paths.py +45 -0
  256. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/runtime/ui.py +33 -1
  257. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/selfupdate.py +3 -2
  258. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/skills/registry.py +3 -2
  259. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/skills/service.py +4 -0
  260. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/base.py +8 -0
  261. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/clarify.py +3 -1
  262. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/file_ops/edit_execute.py +236 -36
  263. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/file_ops/edit_resolve.py +89 -37
  264. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/plan_checkpoint.py +2 -1
  265. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/todo.py +1 -1
  266. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/workflow.py +107 -9
  267. voidx-3.5.1/src/voidx/ui/__init__.py +0 -0
  268. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/gateway/adapter.py +35 -1
  269. voidx-3.5.1/src/voidx/ui/gateway/run_manager.py +269 -0
  270. voidx-3.5.1/src/voidx/ui/gateway/server.py +242 -0
  271. voidx-3.5.1/src/voidx/ui/gateway/session/__init__.py +4 -0
  272. voidx-3.5.1/src/voidx/ui/gateway/session/consumer.py +22 -0
  273. voidx-3.5.1/src/voidx/ui/gateway/session/core.py +399 -0
  274. voidx-3.5.1/src/voidx/ui/gateway/session/method/__init__.py +0 -0
  275. voidx-3.5.1/src/voidx/ui/gateway/session/method/diff.py +56 -0
  276. voidx-3.5.1/src/voidx/ui/gateway/session/method/integrations.py +187 -0
  277. voidx-3.5.1/src/voidx/ui/gateway/session/method/sessions.py +142 -0
  278. voidx-3.5.1/src/voidx/ui/gateway/session/method/settings.py +250 -0
  279. voidx-3.5.1/src/voidx/ui/gateway/session/method/terminal.py +64 -0
  280. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/gateway/terminal.py +4 -2
  281. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/__init__.py +2 -1
  282. voidx-3.5.1/src/voidx/ui/output/ansi_marker.py +10 -0
  283. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/display_policy.py +3 -5
  284. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/dock/__init__.py +4 -0
  285. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/dock/app.py +2 -0
  286. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/dock/formatting.py +1 -1
  287. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/dock/status.py +14 -0
  288. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/events/__init__.py +8 -1
  289. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/events/bus.py +37 -2
  290. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/events/consumers.py +12 -1
  291. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/events/schema.py +17 -0
  292. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/tree.py +1 -4
  293. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/types.py +56 -2
  294. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/protocol/commands.py +17 -1
  295. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/protocol/v2/envelope.py +1 -0
  296. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/protocol/v2/snapshot.py +6 -0
  297. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/protocol/v2/threads.py +3 -2
  298. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/tools/clipboard_image.py +1 -2
  299. {voidx-3.4.4 → voidx-3.5.1/src/voidx.egg-info}/PKG-INFO +1 -1
  300. voidx-3.5.1/src/voidx.egg-info/SOURCES.txt +516 -0
  301. {voidx-3.4.4 → voidx-3.5.1}/src/voidx.egg-info/top_level.txt +1 -0
  302. voidx-3.4.4/src/voidx/agent/graph/turn_runner.py +0 -511
  303. voidx-3.4.4/src/voidx/agent/tool_filters.py +0 -24
  304. voidx-3.4.4/src/voidx/logging/__init__.py +0 -6
  305. voidx-3.4.4/src/voidx/ui/gateway/server.py +0 -114
  306. voidx-3.4.4/src/voidx/ui/gateway/session.py +0 -917
  307. voidx-3.4.4/src/voidx/ui/tui/__init__.py +0 -4
  308. voidx-3.4.4/src/voidx/ui/tui/activity.py +0 -64
  309. voidx-3.4.4/src/voidx/ui/tui/app.py +0 -616
  310. voidx-3.4.4/src/voidx/ui/tui/choice_mixin.py +0 -59
  311. voidx-3.4.4/src/voidx/ui/tui/clipboard_mixin.py +0 -83
  312. voidx-3.4.4/src/voidx/ui/tui/helpers.py +0 -144
  313. voidx-3.4.4/src/voidx/ui/tui/input.py +0 -370
  314. voidx-3.4.4/src/voidx/ui/tui/overlays.py +0 -157
  315. voidx-3.4.4/src/voidx/ui/tui/panels.py +0 -346
  316. voidx-3.4.4/src/voidx/ui/tui/parser.py +0 -531
  317. voidx-3.4.4/src/voidx/ui/tui/render_activity.py +0 -135
  318. voidx-3.4.4/src/voidx/ui/tui/render_frame.py +0 -615
  319. voidx-3.4.4/src/voidx/ui/tui/render_input.py +0 -154
  320. voidx-3.4.4/src/voidx/ui/tui/render_status.py +0 -266
  321. voidx-3.4.4/src/voidx/ui/tui/render_todo.py +0 -79
  322. voidx-3.4.4/src/voidx/ui/tui/renderer.py +0 -24
  323. voidx-3.4.4/src/voidx/ui/tui/state.py +0 -254
  324. voidx-3.4.4/src/voidx/ui/tui/terminal_mixin.py +0 -95
  325. voidx-3.4.4/src/voidx/ui/tui/text_prompt_mixin.py +0 -49
  326. voidx-3.4.4/src/voidx.egg-info/SOURCES.txt +0 -311
  327. {voidx-3.4.4 → voidx-3.5.1}/LICENSE +0 -0
  328. {voidx-3.4.4 → voidx-3.5.1}/README.md +0 -0
  329. {voidx-3.4.4 → voidx-3.5.1}/setup.cfg +0 -0
  330. {voidx-3.4.4/src/voidx/agent → voidx-3.5.1/src/tests}/__init__.py +0 -0
  331. {voidx-3.4.4/src/voidx/llm → voidx-3.5.1/src/tests/test_agent}/__init__.py +0 -0
  332. {voidx-3.4.4/src/voidx/ui → voidx-3.5.1/src/tests/test_agent/graph}/__init__.py +0 -0
  333. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/agents.py +0 -0
  334. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/goal_resolver.py +0 -0
  335. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/__init__.py +0 -0
  336. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/compaction.py +0 -0
  337. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/convergence.py +0 -0
  338. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/permissions.py +0 -0
  339. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/runtime.py +0 -0
  340. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/session_mixin.py +0 -0
  341. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/streaming.py +0 -0
  342. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/title_mixin.py +0 -0
  343. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/todo_events.py +0 -0
  344. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/tool_execution.py +0 -0
  345. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/tool_executor/__init__.py +0 -0
  346. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/tool_executor/guards.py +0 -0
  347. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/tool_executor/types.py +0 -0
  348. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/tool_executor/workflow.py +0 -0
  349. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/topology.py +0 -0
  350. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/transcript_mixin.py +0 -0
  351. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/wiring.py +0 -0
  352. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/graph/workflow_utils.py +0 -0
  353. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/message_rows.py +0 -0
  354. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/message_trimming.py +0 -0
  355. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/prompts.py +0 -0
  356. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/runtime_context.py +0 -0
  357. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/slash/__init__.py +0 -0
  358. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/slash/code_ide.py +0 -0
  359. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/slash/guide.py +0 -0
  360. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/slash/host.py +0 -0
  361. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/slash/init.py +0 -0
  362. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/slash/lsp.py +0 -0
  363. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/slash/mcp.py +0 -0
  364. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/slash/profile.py +0 -0
  365. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/slash/skills.py +0 -0
  366. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/slash/upgrade.py +0 -0
  367. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/state.py +0 -0
  368. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/task_state.py +0 -0
  369. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/tool_call_ids.py +0 -0
  370. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/tool_exchange_sanitizer.py +0 -0
  371. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/tool_messages.py +0 -0
  372. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/agent/tool_result_storage.py +0 -0
  373. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/__init__.py +0 -0
  374. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/enums.py +0 -0
  375. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/permissions.py +0 -0
  376. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/settings_agent.py +0 -0
  377. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/settings_api_keys.py +0 -0
  378. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/settings_code_ide.py +0 -0
  379. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/settings_custom.py +0 -0
  380. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/settings_mcp.py +0 -0
  381. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/settings_permissions.py +0 -0
  382. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/settings_skills.py +0 -0
  383. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/settings_update.py +0 -0
  384. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/settings_utils.py +0 -0
  385. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/config/settings_web.py +0 -0
  386. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/data/__init__.py +0 -0
  387. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/data/templates/api-doc.md +0 -0
  388. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/data/templates/prd.md +0 -0
  389. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/data/templates/readme.md +0 -0
  390. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/data/templates/rfc.md +0 -0
  391. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/data/templates/tech-design.md +0 -0
  392. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/diffing.py +0 -0
  393. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/llm/compaction.py +0 -0
  394. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/llm/message_markers.py +0 -0
  395. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/llm/message_status.py +0 -0
  396. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/llm/service.py +0 -0
  397. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/llm/usage.py +0 -0
  398. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/lsp/__init__.py +0 -0
  399. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/lsp/detector_data.py +0 -0
  400. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/lsp/errors.py +0 -0
  401. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/lsp/manager.py +0 -0
  402. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/lsp/schema.py +0 -0
  403. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/lsp/service.py +0 -0
  404. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/main.py +0 -0
  405. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/mcp/__init__.py +0 -0
  406. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/mcp/client/__init__.py +0 -0
  407. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/mcp/client/errors.py +0 -0
  408. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/mcp/client/http_transport.py +0 -0
  409. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/mcp/client/sse_transport.py +0 -0
  410. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/mcp/client/stdio_transport.py +0 -0
  411. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/mcp/manager.py +0 -0
  412. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/mcp/schema.py +0 -0
  413. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/mcp/tool.py +0 -0
  414. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/mcp_servers/__init__.py +0 -0
  415. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/mcp_servers/web.py +0 -0
  416. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/memory/__init__.py +0 -0
  417. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/memory/cleanup.py +0 -0
  418. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/memory/context_frames.py +0 -0
  419. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/memory/jsonl_store.py +0 -0
  420. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/memory/model_profiles.py +0 -0
  421. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/memory/runtime_state.py +0 -0
  422. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/memory/service.py +0 -0
  423. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/memory/subagents.py +0 -0
  424. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/memory/transcript.py +0 -0
  425. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/permission/__init__.py +0 -0
  426. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/permission/context.py +0 -0
  427. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/permission/engine.py +0 -0
  428. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/permission/evaluate.py +0 -0
  429. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/permission/rules.py +0 -0
  430. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/permission/sandbox.py +0 -0
  431. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/permission/schema.py +0 -0
  432. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/permission/service.py +0 -0
  433. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/permission/wildcard.py +0 -0
  434. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/runtime/__init__.py +0 -0
  435. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/runtime/attachments.py +0 -0
  436. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/runtime/intent.py +0 -0
  437. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/runtime/reference_tokens.py +0 -0
  438. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/runtime/task_state.py +0 -0
  439. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/runtime/todo.py +0 -0
  440. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/runtime/ui_port.py +0 -0
  441. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/skills/__init__.py +0 -0
  442. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/skills/context.py +0 -0
  443. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/skills/references.py +0 -0
  444. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/skills/schema.py +0 -0
  445. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/__init__.py +0 -0
  446. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/agent.py +0 -0
  447. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/bash/__init__.py +0 -0
  448. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/bash/core.py +0 -0
  449. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/bash/hint/__init__.py +0 -0
  450. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/bash/hint/file.py +0 -0
  451. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/bash/hint/git.py +0 -0
  452. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/bash/hint/search.py +0 -0
  453. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/bash/router.py +0 -0
  454. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/bash/safety.py +0 -0
  455. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/bash/tool.py +0 -0
  456. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/compact_context.py +0 -0
  457. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/file_ops/__init__.py +0 -0
  458. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/file_ops/file.py +0 -0
  459. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/file_ops/read.py +0 -0
  460. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/file_ops/types.py +0 -0
  461. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/file_ops/write.py +0 -0
  462. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/file_state.py +0 -0
  463. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/git.py +0 -0
  464. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/load_doc_template.py +0 -0
  465. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/load_skills.py +0 -0
  466. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/lsp.py +0 -0
  467. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/powershell/__init__.py +0 -0
  468. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/powershell/core.py +0 -0
  469. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/powershell/hint/__init__.py +0 -0
  470. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/powershell/hint/file.py +0 -0
  471. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/powershell/hint/search.py +0 -0
  472. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/powershell/router.py +0 -0
  473. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/powershell/safety.py +0 -0
  474. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/powershell/sandbox.py +0 -0
  475. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/powershell/tool.py +0 -0
  476. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/registry.py +0 -0
  477. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/search.py +0 -0
  478. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/service.py +0 -0
  479. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/shell/__init__.py +0 -0
  480. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/shell/common.py +0 -0
  481. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/shell/hint/__init__.py +0 -0
  482. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/shell/hint/git.py +0 -0
  483. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/skills.py +0 -0
  484. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/task_status.py +0 -0
  485. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/task_tracker.py +0 -0
  486. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/web_content.py +0 -0
  487. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/web_mcp.py +0 -0
  488. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/webfetch.py +0 -0
  489. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/tools/websearch.py +0 -0
  490. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/command_catalog.py +0 -0
  491. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/commands.py +0 -0
  492. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/frontend.py +0 -0
  493. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/gateway/__init__.py +0 -0
  494. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/gateway/bootstrap.py +0 -0
  495. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/gateway/diff_review.py +0 -0
  496. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/agent_display.py +0 -0
  497. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/browse.py +0 -0
  498. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/capture.py +0 -0
  499. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/console/__init__.py +0 -0
  500. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/console/app.py +0 -0
  501. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/console/formatting.py +0 -0
  502. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/console/streaming.py +0 -0
  503. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/diff.py +0 -0
  504. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/dock/agent_placeholder.py +0 -0
  505. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/dock/nodes.py +0 -0
  506. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/dock/nodes_checkpoint.py +0 -0
  507. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/dock/nodes_clarify.py +0 -0
  508. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/dock/nodes_permission.py +0 -0
  509. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/dock/nodes_startup.py +0 -0
  510. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/dock/nodes_status.py +0 -0
  511. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/dock/state.py +0 -0
  512. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/dock/stream.py +0 -0
  513. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/output/dock/todo.py +0 -0
  514. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/protocol/__init__.py +0 -0
  515. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/protocol/requests.py +0 -0
  516. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/protocol/schema.py +0 -0
  517. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/protocol/transcript.py +0 -0
  518. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/protocol/v2/__init__.py +0 -0
  519. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/protocol/v2/methods.py +0 -0
  520. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/session.py +0 -0
  521. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/tools/__init__.py +0 -0
  522. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/tools/attachment_tokens.py +0 -0
  523. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/tools/clipboard_text.py +0 -0
  524. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/tools/code_ide.py +0 -0
  525. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/tools/file_picker.py +0 -0
  526. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/tools/skill_picker.py +0 -0
  527. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/ui/transcript.py +0 -0
  528. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/workflow/__init__.py +0 -0
  529. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/workflow/auto_advance.py +0 -0
  530. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/workflow/context.py +0 -0
  531. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/workflow/dag.py +0 -0
  532. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/workflow/nodes.py +0 -0
  533. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/workflow/policy.py +0 -0
  534. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/workflow/reconcile.py +0 -0
  535. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/workflow/render.py +0 -0
  536. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/workflow/route.py +0 -0
  537. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/workflow/runtime.py +0 -0
  538. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/workflow/schema.py +0 -0
  539. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/workflow/service.py +0 -0
  540. {voidx-3.4.4 → voidx-3.5.1}/src/voidx/workflow/types.py +0 -0
  541. {voidx-3.4.4 → voidx-3.5.1}/src/voidx.egg-info/dependency_links.txt +0 -0
  542. {voidx-3.4.4 → voidx-3.5.1}/src/voidx.egg-info/entry_points.txt +0 -0
  543. {voidx-3.4.4 → voidx-3.5.1}/src/voidx.egg-info/requires.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voidx
3
- Version: 3.4.4
3
+ Version: 3.5.1
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,7 +19,7 @@ dependencies = [
19
19
  "httpx>=0.28.0",
20
20
  "websockets>=14",
21
21
  "pathspec>=0.12",
22
- "Pillow>=10.0.0; platform_system == 'Windows'",
22
+ "Pillow>=10.0.0; platform_system == 'Windows'",
23
23
  ]
24
24
 
25
25
  [project.scripts]
@@ -60,5 +60,5 @@ where = ["src"]
60
60
 
61
61
  [tool.pytest.ini_options]
62
62
  asyncio_mode = "auto"
63
- pythonpath = ["src"]
64
- testpaths = ["tests"]
63
+ pythonpath = ["src", "tui"]
64
+ testpaths = ["src/tests", "tui/tests"]
@@ -0,0 +1,17 @@
1
+ from pathlib import Path
2
+
3
+ import pytest
4
+ from voidx.memory import store
5
+
6
+
7
+ @pytest.fixture(autouse=True)
8
+ def isolated_settings_home(monkeypatch: pytest.MonkeyPatch, tmp_path: Path):
9
+ monkeypatch.setattr("voidx.config.settings._settings_home", lambda: tmp_path)
10
+ if store._conn is not None:
11
+ store._conn.close()
12
+ store._conn = None
13
+ monkeypatch.setattr(store, "DATA_DIR", tmp_path / ".voidx")
14
+ yield
15
+ if store._conn is not None:
16
+ store._conn.close()
17
+ store._conn = None
@@ -0,0 +1,101 @@
1
+ """Shared fixtures and helpers for test_agent tests."""
2
+
3
+ import json
4
+ import sqlite3
5
+ import sys
6
+ from pathlib import Path
7
+
8
+
9
+ import pytest
10
+
11
+ import voidx.memory.store as store
12
+
13
+
14
+ @pytest.fixture(autouse=True)
15
+ def isolated_memory_store(tmp_path):
16
+ if store._conn is not None:
17
+ store._conn.close()
18
+ store._conn = None
19
+ store.DATA_DIR = tmp_path / ".voidx"
20
+ yield
21
+ if store._conn is not None:
22
+ store._conn.close()
23
+ store._conn = None
24
+
25
+
26
+ def _session_dir(session_id: str) -> Path:
27
+ return store.DATA_DIR / "sessions" / session_id
28
+
29
+
30
+ def _read_jsonl(path: Path) -> list[dict]:
31
+ return [json.loads(line) for line in path.read_text(encoding="utf-8").splitlines()]
32
+
33
+
34
+ async def _table_names() -> set[str]:
35
+ rows = await store._fetch_all("SELECT name FROM sqlite_master WHERE type = 'table'")
36
+ return {str(row["name"]) for row in rows}
37
+
38
+
39
+ async def _table_columns(table: str) -> set[str]:
40
+ rows = await store._fetch_all(f"PRAGMA table_info({table})")
41
+ return {str(row["name"]) for row in rows}
42
+
43
+
44
+ def _create_legacy_db(path: Path, session_id: str, *, title: str = "Legacy") -> None:
45
+ path.parent.mkdir(parents=True, exist_ok=True)
46
+ conn = sqlite3.connect(str(path))
47
+ try:
48
+ conn.execute(
49
+ """CREATE TABLE sessions (
50
+ id TEXT PRIMARY KEY,
51
+ title TEXT NOT NULL DEFAULT 'New session',
52
+ workspace TEXT NOT NULL DEFAULT '.',
53
+ model_provider TEXT NOT NULL DEFAULT 'anthropic',
54
+ model_name TEXT NOT NULL DEFAULT 'claude-sonnet-4-6',
55
+ created_at TEXT NOT NULL,
56
+ updated_at TEXT NOT NULL
57
+ )"""
58
+ )
59
+ conn.execute(
60
+ """CREATE TABLE messages (
61
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
62
+ session_id TEXT NOT NULL,
63
+ role TEXT NOT NULL,
64
+ content TEXT NOT NULL DEFAULT '',
65
+ tool_calls TEXT,
66
+ tool_call_id TEXT,
67
+ created_at TEXT NOT NULL
68
+ )"""
69
+ )
70
+ conn.execute(
71
+ """INSERT INTO sessions (
72
+ id, title, workspace, model_provider, model_name, created_at, updated_at
73
+ )
74
+ VALUES (?, ?, '.', 'anthropic', 'claude-sonnet-4-6', '2026-06-14T00:00:00+00:00', '2026-06-14T00:00:00+00:00')""",
75
+ (session_id, title),
76
+ )
77
+ conn.execute(
78
+ """INSERT INTO messages (session_id, role, content, created_at)
79
+ VALUES (?, 'user', 'hello', '2026-06-14T00:00:00+00:00')""",
80
+ (session_id,),
81
+ )
82
+ conn.commit()
83
+ finally:
84
+ conn.close()
85
+
86
+
87
+ def _create_new_store_db(path: Path, session_id: str, *, title: str = "New Store") -> None:
88
+ path.parent.mkdir(parents=True, exist_ok=True)
89
+ conn = sqlite3.connect(str(path))
90
+ try:
91
+ store._init_schema(conn)
92
+ conn.execute(
93
+ """INSERT INTO sessions (
94
+ id, title, workspace, model_provider, model_name, created_at, updated_at, message_count
95
+ )
96
+ VALUES (?, ?, '.', 'anthropic', 'claude-sonnet-4-6', '2026-06-14T00:00:00+00:00', '2026-06-14T00:00:00+00:00', 0)""",
97
+ (session_id, title),
98
+ )
99
+ conn.commit()
100
+ finally:
101
+ conn.close()
@@ -0,0 +1,107 @@
1
+ """Shared helpers for test_run_loop split files."""
2
+
3
+ import sys
4
+ from pathlib import Path
5
+ from types import SimpleNamespace
6
+
7
+ import voidx.memory.store as store
8
+
9
+
10
+ from voidx.agent.graph import VoidXGraph
11
+ from voidx.agent.graph.run_loop import GraphRunLoopMixin
12
+ from voidx.agent.graph.title_mixin import _sanitize_generated_title
13
+ from voidx.config import Config, ModelConfig
14
+ from voidx.llm.usage import UsageStats
15
+ from voidx.tools.task_tracker import TaskTracker
16
+ from voidx.ui.output.dock import BottomInputDock, set_dock
17
+ from voidx.ui.output.events import DockEventConsumer, ui_events
18
+ from voidx.ui.protocol import UiSubmitCommand
19
+ from voidx.runtime.ui_port import runtime_ui_port
20
+
21
+
22
+ class FakeTui:
23
+ instances = []
24
+
25
+ def __init__(self, status, commands):
26
+ self.status = status
27
+ self.commands = commands
28
+ FakeTui.instances.append(self)
29
+
30
+ async def run(self, on_submit):
31
+ keep_running = await on_submit("/model reasoning")
32
+ assert keep_running is True
33
+
34
+ def set_external_command_handler(self, handler):
35
+ self.command_handler = handler
36
+
37
+ def consume_quiet_command(self, command: str) -> bool:
38
+ return command == "/model reasoning"
39
+
40
+
41
+ class ExitTui:
42
+ def __init__(self, status, commands):
43
+ self.status = status
44
+ self.commands = commands
45
+ self.command_handler = None
46
+
47
+ async def run(self, on_submit):
48
+ return
49
+
50
+ def set_external_command_handler(self, handler):
51
+ self.command_handler = handler
52
+
53
+
54
+ class NoopMcpManager:
55
+ def statuses(self):
56
+ return []
57
+
58
+ async def start_all(self):
59
+ return None
60
+
61
+ async def stop_all(self):
62
+ return None
63
+
64
+
65
+ class NoopLspManager:
66
+ initialized = True
67
+ initializing = False
68
+
69
+ async def initialize(self):
70
+ return None
71
+
72
+ def doctor(self):
73
+ return []
74
+
75
+ async def warm_up(self):
76
+ return {}
77
+
78
+ async def stop_all(self):
79
+ return None
80
+
81
+
82
+ def _graph(session=None, workspace: str = "/tmp/workspace") -> GraphRunLoopMixin:
83
+ graph = GraphRunLoopMixin()
84
+ graph._session = session
85
+ graph._workspace = workspace
86
+ graph.model = object()
87
+ graph.config = SimpleNamespace(
88
+ workspace=workspace,
89
+ model=ModelConfig(provider="mimo", model="mimo-v2.5", reasoning_effort="high"),
90
+ )
91
+ graph._settings = SimpleNamespace(list_mcp_servers=lambda: [], path=f"{workspace}/.voidx/settings.json")
92
+ graph._permission = SimpleNamespace(
93
+ status_label=lambda: "default",
94
+ clear_session_permissions=lambda: None,
95
+ )
96
+ graph._usage_stats = UsageStats()
97
+ graph._debug = False
98
+ graph._plan_mode = False
99
+ graph._tracker = TaskTracker()
100
+ graph._session_msg_cache = None
101
+ graph._ui = runtime_ui_port
102
+ return graph
103
+
104
+
105
+ def _disable_external_managers(graph) -> None:
106
+ graph._mcp_manager = NoopMcpManager()
107
+ graph._lsp_manager = NoopLspManager()
@@ -0,0 +1,252 @@
1
+ """Shared helpers for test_stream_llm split files."""
2
+
3
+ import sys
4
+ from pathlib import Path
5
+ from types import SimpleNamespace
6
+
7
+ from langchain_core.messages import AIMessage, AIMessageChunk, HumanMessage, RemoveMessage, SystemMessage, ToolMessage
8
+ from langgraph.graph.message import REMOVE_ALL_MESSAGES
9
+ from rich.console import Console
10
+
11
+
12
+ from voidx.agent.graph.streaming import stream_llm as _stream_llm
13
+ from voidx.agent.graph import VoidXGraph
14
+ from voidx.agent.graph.convergence import is_step_hint_message
15
+ from voidx.agent.runtime_context import RuntimeContextBuilder
16
+ from voidx.agent.task_state import TaskState, TodoRunState
17
+ from voidx.config import Config, ModelConfig
18
+ from voidx.llm.compaction import CompactionSelection
19
+ from voidx.llm.message_markers import is_guidance_message
20
+ from voidx.memory.context_frames import load_context_frames
21
+ from voidx.memory.session import MessageRow, create_session, delete_session, save_message
22
+ from voidx.ui.output.console import StreamingRenderer
23
+ from voidx.ui.output.dock import ANSI_LINE_PREFIX, BottomInputDock, set_dock
24
+ from voidx.ui.output.events import AnsiAppended, DockEventConsumer, StatusFinished, StatusUpdated, ui_events
25
+ from voidx.workflow.runtime import WorkflowRunState, WorkflowRunStatus
26
+
27
+ def _plain(line: str) -> str:
28
+ return line.replace(ANSI_LINE_PREFIX, "")
29
+
30
+
31
+ class FakeStreamingModel:
32
+ def __init__(self) -> None:
33
+ self.messages = None
34
+
35
+ def bind_tools(self, tool_defs):
36
+ return self
37
+
38
+ async def astream(self, messages):
39
+ self.messages = messages
40
+ yield AIMessageChunk(content=[{"type": "thinking", "text": "think"}])
41
+ yield AIMessageChunk(content="answer")
42
+
43
+
44
+ class FakeUsageStreamingModel:
45
+ def bind_tools(self, tool_defs):
46
+ return self
47
+
48
+ async def astream(self, messages):
49
+ yield AIMessageChunk(
50
+ content="answer",
51
+ usage_metadata={
52
+ "input_tokens": 7,
53
+ "output_tokens": 3,
54
+ "total_tokens": 10,
55
+ },
56
+ )
57
+
58
+
59
+ class FakeDuplicatedReasoningStreamingModel:
60
+ async def astream(self, messages):
61
+ yield AIMessageChunk(
62
+ content="622",
63
+ additional_kwargs={"reasoning_content": "622"},
64
+ )
65
+ yield AIMessageChunk(content="final answer")
66
+
67
+
68
+ class FakeDsmlStreamingModel:
69
+ def __init__(self) -> None:
70
+ self.messages = None
71
+
72
+ def bind_tools(self, tool_defs):
73
+ return self
74
+
75
+ async def astream(self, messages):
76
+ self.messages = messages
77
+ yield AIMessageChunk(content=(
78
+ '也必须在 commands 列表中注册:\n\n'
79
+ '<||DSML||tool_calls>\n'
80
+ '<||DSML||invoke name="grep">\n'
81
+ '<||DSML||parameter name="path" string="true">src/voidx/ui/commands.py</||DSML||parameter>\n'
82
+ '<||DSML||parameter name="pattern" string="true">permissions</||DSML||parameter>\n'
83
+ '</||DSML||invoke>\n'
84
+ '</||DSML||tool_calls>'
85
+ ))
86
+
87
+
88
+ class FakeMalformedDsmlStreamingModel:
89
+ def bind_tools(self, tool_defs):
90
+ return self
91
+
92
+ async def astream(self, messages):
93
+ yield AIMessageChunk(content=(
94
+ '<|||DSML||tool_calls>\n'
95
+ '<||DSML||invoke name="grep">\n'
96
+ '<||DSML||parameter name="path" string="true">src/voidx/ui/commands.py</||DSML||parameter>\n'
97
+ '</||DSML||invoke>\n'
98
+ '</|||DSML||tool_calls>'
99
+ ))
100
+
101
+
102
+ class FakeMalformedLegacyXmlStreamingModel:
103
+ def bind_tools(self, tool_defs):
104
+ return self
105
+
106
+ async def astream(self, messages):
107
+ yield AIMessageChunk(content=(
108
+ "<tool_call>"
109
+ "<tool_name>read</tool_name>"
110
+ "<arg_key>file_path</arg_key><arg_value>src/voidx/permission/engine.py</arg_value>"
111
+ ))
112
+
113
+
114
+ class RepairsMalformedToolCallStreamingModel:
115
+ def __init__(self) -> None:
116
+ self.calls = 0
117
+ self.messages_by_call = []
118
+
119
+ def bind_tools(self, tool_defs):
120
+ return self
121
+
122
+ async def astream(self, messages):
123
+ self.calls += 1
124
+ self.messages_by_call.append(messages)
125
+ if self.calls == 1:
126
+ yield AIMessageChunk(content=(
127
+ "<tool_call>"
128
+ "<tool_name>read</tool_name>"
129
+ "<arg_key>file_path</arg_key><arg_value>src/voidx/permission/engine.py</arg_value>"
130
+ ))
131
+ return
132
+ yield AIMessageChunk(content="repaired answer")
133
+
134
+
135
+ class AlwaysMalformedToolCallStreamingModel:
136
+ def __init__(self) -> None:
137
+ self.calls = 0
138
+
139
+ def bind_tools(self, tool_defs):
140
+ return self
141
+
142
+ async def astream(self, messages):
143
+ self.calls += 1
144
+ yield AIMessageChunk(content=(
145
+ "<tool_call>"
146
+ "<tool_name>read</tool_name>"
147
+ "<arg_key>file_path</arg_key><arg_value>src/voidx/permission/engine.py</arg_value>"
148
+ ))
149
+
150
+
151
+ class FakeMalformedProviderJsonToolCallStreamingModel:
152
+ def bind_tools(self, tool_defs):
153
+ return self
154
+
155
+ async def astream(self, messages):
156
+ yield AIMessageChunk(content=(
157
+ '{"tool_calls":[{"function":{"name":"read","arguments":"{\\"file_path\\":'
158
+ ))
159
+
160
+
161
+ class FakeLegacyXmlToolCallStreamingModel:
162
+ def bind_tools(self, tool_defs):
163
+ return self
164
+
165
+ async def astream(self, messages):
166
+ yield AIMessageChunk(content=(
167
+ "<tool_call>"
168
+ "<tool_name>Read</tool_name>"
169
+ "<arg_key>file_path</arg_key><arg_value>src/voidx/permission/engine.py</arg_value>"
170
+ "<arg_key>offset</arg_key><arg_value>110</arg_value>"
171
+ "<arg_key>limit</arg_key><arg_value>50</arg_value>"
172
+ "</tool_call>"
173
+ ))
174
+
175
+
176
+ class FakeLegacyXmlArgPairToolCallStreamingModel:
177
+ def bind_tools(self, tool_defs):
178
+ return self
179
+
180
+ async def astream(self, messages):
181
+ yield AIMessageChunk(content=(
182
+ "<tool_call>"
183
+ "<arg_key>tool_name</arg_key><arg_value>read</arg_value>"
184
+ "<arg_key>file_path</arg_key><arg_value>src/voidx/permission/engine.py</arg_value>"
185
+ "<arg_key>offset</arg_key><arg_value>110</arg_value>"
186
+ "</tool_call>"
187
+ ))
188
+
189
+
190
+ class TrackingStreamingModel(FakeStreamingModel):
191
+ def __init__(self) -> None:
192
+ super().__init__()
193
+ self.bound_tools = None
194
+
195
+ def bind_tools(self, tool_defs):
196
+ self.bound_tools = tool_defs
197
+ return self
198
+
199
+
200
+ class FailsOnceStreamingModel(FakeStreamingModel):
201
+ def __init__(self) -> None:
202
+ super().__init__()
203
+ self.calls = 0
204
+
205
+ async def astream(self, messages):
206
+ self.calls += 1
207
+ if self.calls == 1:
208
+ raise ConnectionError("Connection error.")
209
+ self.messages = messages
210
+ yield AIMessageChunk(content="answer")
211
+
212
+
213
+ class FakeRenderer:
214
+ def __init__(self, *args, **kwargs) -> None:
215
+ self.text: list[str] = []
216
+ self.thinking: list[str] = []
217
+ self.started = False
218
+ self.done_called = False
219
+ self.discarded = False
220
+
221
+ def start(self) -> None:
222
+ self.started = True
223
+
224
+ def feed_text(self, text: str) -> None:
225
+ self.text.append(text)
226
+
227
+ def feed_thinking(self, text: str) -> None:
228
+ self.thinking.append(text)
229
+
230
+ def discard(self) -> None:
231
+ self.discarded = True
232
+
233
+ def done(self) -> None:
234
+ self.done_called = True
235
+
236
+ def error(self, text: str) -> None:
237
+ pass
238
+
239
+
240
+ class FailsNonRetryableStreamingModel(FakeStreamingModel):
241
+ """Raises an exception with status_code=404 on first call."""
242
+ def __init__(self) -> None:
243
+ super().__init__()
244
+ self.calls = 0
245
+
246
+ async def astream(self, messages):
247
+ self.calls += 1
248
+ # Must yield first to remain an async generator
249
+ yield AIMessageChunk(content="")
250
+ exc = RuntimeError("404 model_not_found")
251
+ exc.status_code = 404 # type: ignore
252
+ raise exc