voidx 3.5.1__tar.gz → 3.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {voidx-3.5.1/src/voidx.egg-info → voidx-3.6.0}/PKG-INFO +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/pyproject.toml +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_execute_tools_guard.py +128 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_graph_authorization.py +7 -3
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_prepare_workflow.py +46 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_run_loop_startup.py +156 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_run_loop_workflow.py +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_session_persistence.py +98 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_session_run_once.py +90 -2
- voidx-3.6.0/src/tests/test_agent/graph/test_subagent_llm_retry.py +301 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_subagent_runner.py +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_tool_execution_auth.py +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_workflow_done.py +2 -5
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_workflow_review.py +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_workflow_transactions_barrier.py +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/slash/test_slash_model.py +74 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_file_rwlock.py +36 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_goal_resolver.py +56 -8
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_goal_resolver_advanced.py +65 -5
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_permission.py +51 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_task_state.py +11 -2
- voidx-3.6.0/src/tests/test_agent/test_task_state_context_sync.py +93 -0
- voidx-3.6.0/src/tests/test_archive_script.py +180 -0
- voidx-3.6.0/src/tests/test_config/test_retry_config.py +95 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_install_sh.py +8 -3
- voidx-3.6.0/src/tests/test_llm/test_goal_resolver_retry.py +98 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_llm/test_llm_provider.py +74 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_mcp/test_mcp.py +96 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_npm_package.py +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_runtime/test_runtime_ui.py +3 -1
- voidx-3.6.0/src/tests/test_selfupdate/test_selfupdate.py +245 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/bash/test_router_git.py +3 -3
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/bash/test_router_safety.py +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/bash/test_router_sed_grep.py +7 -7
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/bash/test_tool.py +7 -7
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_coverage_fingerprint.py +27 -35
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_edit_anchors.py +3 -3
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_edit_bounds_input.py +3 -3
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_edit_coverage.py +3 -3
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_edit_dedup.py +3 -3
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_edit_drift_fallback.py +12 -12
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_edit_drift_fallback_e2e.py +3 -3
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_edit_errors.py +3 -3
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_edit_line_insert.py +10 -10
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_edit_llm_messages.py +3 -3
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_edit_replace.py +88 -3
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_edit_trailing_newline.py +3 -3
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_read.py +9 -9
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_read_write.py +9 -9
- voidx-3.6.0/src/tests/test_tools/file/test_render_numbered_diff.py +59 -0
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/test_write_file.py +32 -13
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_clarify_tool.py +6 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_diffing.py +28 -2
- voidx-3.6.0/src/tests/test_tools/test_file_tools_redesign.py +390 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_infer_state_patch.py +6 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_interactive_tools.py +8 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_interactive_tools_write.py +8 -6
- voidx-3.6.0/src/tests/test_tools/test_load_doc_template.py +164 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_make_interact_callback.py +6 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_plan_checkpoint.py +6 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_replace_failure_logging.py +8 -10
- voidx-3.6.0/src/tests/test_tools/test_retry.py +176 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_search.py +6 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_state_update_from_executed_tools.py +6 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_task_tracker.py +6 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_tool_error_handling.py +10 -10
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_tool_registry.py +6 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_tool_schemas.py +6 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_tool_state_patch.py +6 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_user_interaction_models.py +6 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_web_mcp.py +5 -5
- voidx-3.6.0/src/tests/test_tools/test_webfetch.py +286 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_workflow_tool.py +218 -36
- voidx-3.6.0/src/tests/test_ui/gateway/test_gateway_headless_frontend.py +80 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_gateway_v2_dispatch.py +117 -2
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_gateway_v2_routing.py +46 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_gateway_v2_session.py +60 -0
- voidx-3.6.0/src/tests/test_ui/gateway/test_guidance_fallback.py +116 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_ui_events_dock_status.py +50 -2
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_ui_events_streaming.py +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_ui_gateway.py +35 -2
- voidx-3.6.0/src/tests/test_wheel_build.py +94 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_workflow/test_auto_advance.py +27 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/__init__.py +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/goal_resolver.py +63 -38
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/core/helpers.py +3 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/core/voidx_graph.py +43 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/permissions.py +0 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/run_loop.py +57 -51
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/subagent.py +46 -7
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/tool_executor/executor.py +62 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/tool_executor/helpers.py +18 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/turn_runner.py +13 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/message_trimming.py +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/slash/handler.py +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/slash/model.py +27 -75
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/__init__.py +2 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/models.py +12 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/settings.py +3 -0
- voidx-3.6.0/src/voidx/config/settings_retry.py +28 -0
- voidx-3.6.0/src/voidx/data/documents/README.md +12 -0
- voidx-3.6.0/src/voidx/data/documents/templates/readme.md +9 -0
- voidx-3.6.0/src/voidx/data/documents/voidx-guide/README.md +17 -0
- voidx-3.6.0/src/voidx/data/documents/voidx-guide/context.md +13 -0
- voidx-3.6.0/src/voidx/data/documents/voidx-guide/debug.md +9 -0
- voidx-3.6.0/src/voidx/data/documents/voidx-guide/extension.md +34 -0
- voidx-3.6.0/src/voidx/data/documents/voidx-guide/mode.md +14 -0
- voidx-3.6.0/src/voidx/data/documents/voidx-guide/model.md +16 -0
- voidx-3.6.0/src/voidx/data/documents/voidx-guide/permission.md +33 -0
- voidx-3.6.0/src/voidx/data/documents/voidx-guide/preferences.md +12 -0
- voidx-3.6.0/src/voidx/data/documents/voidx-guide/quickstart.md +40 -0
- voidx-3.6.0/src/voidx/data/documents/voidx-guide/reference.md +29 -0
- voidx-3.6.0/src/voidx/data/documents/voidx-guide/session.md +19 -0
- voidx-3.6.0/src/voidx/data/documents/voidx-guide/upgrade.md +10 -0
- voidx-3.6.0/src/voidx/data/documents/voidx-guide/web.md +11 -0
- voidx-3.6.0/src/voidx/data/documents/voidx-guide/workflow.md +24 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/diffing.py +24 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/llm/provider.py +79 -24
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/mcp/client/base.py +41 -25
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/mcp/client/stdio_transport.py +1 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/mcp/manager.py +2 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/mcp_servers/web.py +1 -2
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/permission/engine.py +7 -5
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/permission/rules.py +49 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/runtime/task_state.py +9 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/runtime/ui.py +5 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/selfupdate.py +109 -15
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/bash/hint/file.py +4 -4
- voidx-3.6.0/src/voidx/tools/document.py +135 -0
- {voidx-3.5.1/src/voidx/tools/file_ops → voidx-3.6.0/src/voidx/tools/file}/__init__.py +6 -3
- voidx-3.6.0/src/voidx/tools/file/manage.py +277 -0
- {voidx-3.5.1/src/voidx/tools/file_ops → voidx-3.6.0/src/voidx/tools/file}/read.py +1 -1
- voidx-3.5.1/src/voidx/tools/file_ops/edit_execute.py → voidx-3.6.0/src/voidx/tools/file/replace.py +51 -7
- voidx-3.5.1/src/voidx/tools/file_ops/edit_resolve.py → voidx-3.6.0/src/voidx/tools/file/replace_resolve.py +2 -2
- {voidx-3.5.1/src/voidx/tools/file_ops → voidx-3.6.0/src/voidx/tools/file}/write.py +65 -31
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/lsp.py +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/registry.py +9 -9
- voidx-3.6.0/src/voidx/tools/retry.py +43 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/shell/common.py +1 -1
- voidx-3.6.0/src/voidx/tools/web/__init__.py +13 -0
- voidx-3.5.1/src/voidx/tools/webfetch.py → voidx-3.6.0/src/voidx/tools/web/fetch.py +29 -5
- voidx-3.5.1/src/voidx/tools/websearch.py → voidx-3.6.0/src/voidx/tools/web/search.py +2 -2
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/workflow.py +84 -31
- voidx-3.6.0/src/voidx/ui/gateway/__init__.py +13 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/adapter.py +1 -0
- voidx-3.6.0/src/voidx/ui/gateway/frontend.py +206 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/run_manager.py +10 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/session/core.py +85 -14
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/session/method/sessions.py +22 -4
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/session/method/settings.py +9 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/console/streaming.py +9 -2
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/dock/app.py +5 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/dock/stream.py +21 -6
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/events/bus.py +5 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/events/consumers.py +42 -12
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/types.py +0 -3
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/protocol/requests.py +1 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/workflow/nodes.py +2 -2
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/workflow/runtime.py +1 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/workflow/types.py +3 -0
- {voidx-3.5.1 → voidx-3.6.0/src/voidx.egg-info}/PKG-INFO +1 -1
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx.egg-info/SOURCES.txt +66 -37
- voidx-3.5.1/src/tests/test_selfupdate/test_selfupdate.py +0 -103
- voidx-3.5.1/src/tests/test_tools/test_load_doc_template.py +0 -68
- voidx-3.5.1/src/tests/test_tools/test_webfetch.py +0 -157
- voidx-3.5.1/src/voidx/data/templates/readme.md +0 -55
- voidx-3.5.1/src/voidx/tools/file_ops/file.py +0 -187
- voidx-3.5.1/src/voidx/tools/load_doc_template.py +0 -67
- voidx-3.5.1/src/voidx/tools/load_skills.py +0 -12
- voidx-3.5.1/src/voidx/ui/gateway/__init__.py +0 -6
- {voidx-3.5.1 → voidx-3.6.0}/LICENSE +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/README.md +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/setup.cfg +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/conftest.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/conftest.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/run_loop_helpers.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/stream_llm_helpers.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_call_llm_compaction.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_call_llm_compaction_advanced.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_call_llm_tools.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_compaction_flow.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_compaction_flow_run_once.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_convergence.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_execute_tools_todo.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_graph_setup_prompts.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_guards_tool_op.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_parallel_subagents.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_parallel_subagents_dedup.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_run_loop_title_lsp.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_run_loop_title_misc.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_run_loop_workflow_advanced.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_runtime_guards.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_session_context_frames.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_session_crud.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_session_messages.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_session_runtime_state.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_session_transcript.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_stream_llm_sanitization.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_subagent_persistence.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_subagent_step_budget.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_subagent_step_budget_convergence.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_subagent_step_budget_final.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_todo_events.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_tool_result_preview.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/graph/test_workflow_transactions.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/slash/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/slash/test_slash_init.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/slash/test_slash_mcp.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/slash/test_slash_model_advanced.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/slash/test_slash_session.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/slash/test_slash_skills.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/slash/test_slash_tavily.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/slash/test_slash_upgrade.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_attachments.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_message_trimming_parsers.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_message_trimming_rules.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_module_boundaries.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_permission_append.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_prompts.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_runtime_context_builder.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_runtime_context_prompts.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_runtime_context_skill_stripping.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_task_state_rendering.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_todo_replay_sanitization.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_tool_exchange_sanitizer.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_tool_filters_gemini.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_tool_messages.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_agent/test_tool_result_storage.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_config/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_config/test_config.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_config/test_config_advanced.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_llm/conftest.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_llm/test_compaction_retry.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_llm/test_fallback_summary.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_llm/test_gemini_provider.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_llm/test_instruction_cache.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_llm/test_llm_catalog.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_llm/test_llm_provider_advanced.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_llm/test_llm_usage.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_llm/test_overflow_threshold.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_llm/test_prune_args.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_llm/test_request_log.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_llm/test_streaming_sanitize.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_llm/test_token_counting.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_logging/test_internal_error.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_logging/test_tool_log.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_lsp/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_lsp/test_lsp.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_lsp/test_lsp_advanced.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_mcp/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_memory/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_memory/test_main.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_memory/test_main_startup.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_memory/test_schema_migration.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_permission/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_runtime/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_runtime/test_goal_resolution_refactor.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_selfupdate/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_skills/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_skills/conftest.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_skills/test_create_skill.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_skills/test_skill_parsing.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_skills/test_skill_references.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_skills/test_workflow_advance.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/bash/__init__.py +0 -0
- {voidx-3.5.1/src/tests/test_tools/file_ops → voidx-3.6.0/src/tests/test_tools/file}/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_git_tool_destructive.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_git_tool_raw_permissions.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_git_tool_schema_errors.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_git_tool_structured.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_powershell_tool.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_resolve_safe.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_skills_tool.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_tools/test_todo_tool.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/conftest.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/helpers.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_adapter.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_diff_review.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_gateway_v2_crud_diff.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_gateway_v2_server.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_run_manager.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_terminal.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_ui_events_dock_bus.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_ui_events_dock_prompts.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_ui_events_subagent.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/gateway/test_ui_events_todo.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/output/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/output/test_dock_formatting.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/output/test_fmt_args.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/output/test_output_browse.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/output/test_scrollback_flush.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/output/test_tree_smoke.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/output/test_ui_diff.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/output/test_ui_session_changes.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/protocol/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/protocol/test_dto.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/protocol/test_v2_envelope.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/protocol/test_v2_methods.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/protocol/test_v2_snapshot.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/protocol/test_v2_threads.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/test_display_policy.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/test_file_picker.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/tools/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/tools/test_clipboard_image.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/tools/test_clipboard_image_windows.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/tools/test_clipboard_text.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/tools/test_clipboard_text_windows.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_ui/tools/test_code_ide.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_workflow/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/tests/test_workflow/test_workflow_reconcile.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/agents.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/attachments.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/compaction.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/compaction_coordinator.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/contracts.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/convergence.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/core/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/core/llm.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/runtime.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/runtime_guards.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/session_mixin.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/session_runtime.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/streaming.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/thread_context.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/title_mixin.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/todo_events.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/tool_execution.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/tool_executor/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/tool_executor/guards.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/tool_executor/types.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/tool_executor/ui.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/tool_executor/workflow.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/topology.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/transcript_mixin.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/turn_mixin.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/wiring.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/graph/workflow_utils.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/message_rows.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/prompts.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/runtime_context.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/slash/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/slash/code_ide.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/slash/guide.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/slash/host.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/slash/init.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/slash/lsp.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/slash/mcp.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/slash/profile.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/slash/runtime.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/slash/session.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/slash/skills.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/slash/upgrade.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/state.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/task_state.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/todo_state.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/tool_call_ids.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/tool_exchange_sanitizer.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/tool_filters.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/tool_messages.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/agent/tool_result_storage.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/defaults.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/enums.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/permissions.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/settings_agent.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/settings_api_keys.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/settings_code_ide.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/settings_custom.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/settings_mcp.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/settings_permissions.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/settings_skills.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/settings_update.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/settings_utils.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/config/settings_web.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/data/__init__.py +0 -0
- {voidx-3.5.1/src/voidx/data → voidx-3.6.0/src/voidx/data/documents}/templates/api-doc.md +0 -0
- {voidx-3.5.1/src/voidx/data → voidx-3.6.0/src/voidx/data/documents}/templates/prd.md +0 -0
- {voidx-3.5.1/src/voidx/data → voidx-3.6.0/src/voidx/data/documents}/templates/rfc.md +0 -0
- {voidx-3.5.1/src/voidx/data → voidx-3.6.0/src/voidx/data/documents}/templates/tech-design.md +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/llm/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/llm/catalog.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/llm/compaction.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/llm/context.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/llm/instruction.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/llm/message_markers.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/llm/message_status.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/llm/service.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/llm/usage.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/logging/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/logging/internal_error.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/logging/request_log.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/logging/tool_log.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/lsp/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/lsp/client.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/lsp/config.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/lsp/detector.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/lsp/detector_data.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/lsp/errors.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/lsp/manager.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/lsp/schema.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/lsp/service.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/main.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/mcp/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/mcp/client/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/mcp/client/errors.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/mcp/client/http_transport.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/mcp/client/sse_transport.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/mcp/schema.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/mcp/tool.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/mcp_servers/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/memory/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/memory/cleanup.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/memory/context_frames.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/memory/jsonl_store.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/memory/model_profiles.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/memory/runtime_state.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/memory/service.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/memory/session.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/memory/store.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/memory/subagents.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/memory/transcript.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/paths.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/permission/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/permission/context.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/permission/evaluate.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/permission/sandbox.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/permission/schema.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/permission/service.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/permission/wildcard.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/runtime/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/runtime/attachments.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/runtime/intent.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/runtime/reference_tokens.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/runtime/todo.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/runtime/ui_port.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/skills/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/skills/context.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/skills/references.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/skills/registry.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/skills/schema.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/skills/service.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/agent.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/base.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/bash/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/bash/core.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/bash/hint/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/bash/hint/git.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/bash/hint/search.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/bash/router.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/bash/safety.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/bash/tool.py +0 -0
- /voidx-3.5.1/src/voidx/tools/plan_checkpoint.py → /voidx-3.6.0/src/voidx/tools/checkpoint.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/clarify.py +0 -0
- /voidx-3.5.1/src/voidx/tools/compact_context.py → /voidx-3.6.0/src/voidx/tools/compact.py +0 -0
- /voidx-3.5.1/src/voidx/tools/file_state.py → /voidx-3.6.0/src/voidx/tools/file/state.py +0 -0
- {voidx-3.5.1/src/voidx/tools/file_ops → voidx-3.6.0/src/voidx/tools/file}/types.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/git.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/powershell/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/powershell/core.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/powershell/hint/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/powershell/hint/file.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/powershell/hint/search.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/powershell/router.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/powershell/safety.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/powershell/sandbox.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/powershell/tool.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/search.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/service.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/shell/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/shell/hint/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/shell/hint/git.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/skills.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/task_status.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/task_tracker.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/tools/todo.py +0 -0
- /voidx-3.5.1/src/voidx/tools/web_content.py → /voidx-3.6.0/src/voidx/tools/web/content.py +0 -0
- /voidx-3.5.1/src/voidx/tools/web_mcp.py → /voidx-3.6.0/src/voidx/tools/web/mcp.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/command_catalog.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/commands.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/frontend.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/bootstrap.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/diff_review.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/server.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/session/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/session/consumer.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/session/method/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/session/method/diff.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/session/method/integrations.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/session/method/terminal.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/gateway/terminal.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/agent_display.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/ansi_marker.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/browse.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/capture.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/console/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/console/app.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/console/formatting.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/diff.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/display_policy.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/dock/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/dock/agent_placeholder.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/dock/formatting.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/dock/nodes.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/dock/nodes_checkpoint.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/dock/nodes_clarify.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/dock/nodes_permission.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/dock/nodes_startup.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/dock/nodes_status.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/dock/state.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/dock/status.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/dock/todo.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/events/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/events/schema.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/output/tree.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/protocol/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/protocol/commands.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/protocol/schema.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/protocol/transcript.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/protocol/v2/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/protocol/v2/envelope.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/protocol/v2/methods.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/protocol/v2/snapshot.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/protocol/v2/threads.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/session.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/tools/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/tools/attachment_tokens.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/tools/clipboard_image.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/tools/clipboard_text.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/tools/code_ide.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/tools/file_picker.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/tools/skill_picker.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/ui/transcript.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/workflow/__init__.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/workflow/auto_advance.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/workflow/context.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/workflow/dag.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/workflow/policy.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/workflow/reconcile.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/workflow/render.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/workflow/route.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/workflow/schema.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx/workflow/service.py +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx.egg-info/dependency_links.txt +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx.egg-info/entry_points.txt +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx.egg-info/requires.txt +0 -0
- {voidx-3.5.1 → voidx-3.6.0}/src/voidx.egg-info/top_level.txt +0 -0
|
@@ -49,7 +49,7 @@ from voidx.tools.base import ToolContext, ToolResult
|
|
|
49
49
|
from voidx.tools.agent import AgentResultContract, AgentTool
|
|
50
50
|
from voidx.tools.registry import ToolRegistry
|
|
51
51
|
from voidx.ui.output.dock import BottomInputDock, set_dock
|
|
52
|
-
from voidx.ui.output.events import DockEventConsumer, TurnStarted, ui_events
|
|
52
|
+
from voidx.ui.output.events import DockEventConsumer, StatusUpdated, ToolResultAppended, TurnStarted, ui_events
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
def _graph(tmp_path):
|
|
@@ -669,3 +669,130 @@ async def test_execute_tools_terminates_turn_when_tool_started_notification_time
|
|
|
669
669
|
and "UI event bus timed out" in str(message.content)
|
|
670
670
|
for message in result["messages"]
|
|
671
671
|
)
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
@pytest.mark.asyncio
|
|
675
|
+
async def test_execute_tools_returns_tool_error_when_result_rendering_fails(tmp_path, monkeypatch):
|
|
676
|
+
graph = _graph(tmp_path)
|
|
677
|
+
|
|
678
|
+
class FakeReadTool:
|
|
679
|
+
id = "read"
|
|
680
|
+
description = "fake read"
|
|
681
|
+
|
|
682
|
+
def parameters_schema(self):
|
|
683
|
+
return {"type": "object", "properties": {}}
|
|
684
|
+
|
|
685
|
+
async def execute(self, args: dict, ctx: ToolContext) -> ToolResult:
|
|
686
|
+
return ToolResult(output="File not found: missing.py", metadata={"error": True})
|
|
687
|
+
|
|
688
|
+
class FailingResultConsumer:
|
|
689
|
+
def handle(self, event):
|
|
690
|
+
if isinstance(event, ToolResultAppended):
|
|
691
|
+
raise RuntimeError("render exploded")
|
|
692
|
+
return None
|
|
693
|
+
|
|
694
|
+
graph.tools.register("read", FakeReadTool(), "fake read", {"type": "object", "properties": {}})
|
|
695
|
+
|
|
696
|
+
async def allow_all(
|
|
697
|
+
tool_calls,
|
|
698
|
+
plan_mode: bool,
|
|
699
|
+
session_id: str,
|
|
700
|
+
interaction_mode=None,
|
|
701
|
+
workflow_runs=None,
|
|
702
|
+
runtime_persona=None,
|
|
703
|
+
):
|
|
704
|
+
return tool_calls, []
|
|
705
|
+
|
|
706
|
+
graph._authorize_tool_calls = allow_all
|
|
707
|
+
monkeypatch.setattr(graph._ui, "via_events", lambda: True)
|
|
708
|
+
graph._ui.events.start(FailingResultConsumer())
|
|
709
|
+
|
|
710
|
+
parent = AIMessage(
|
|
711
|
+
content="",
|
|
712
|
+
tool_calls=[{"name": "read", "args": {"file_path": "missing.py"}, "id": "call_read", "type": "tool_call"}],
|
|
713
|
+
)
|
|
714
|
+
|
|
715
|
+
try:
|
|
716
|
+
result = await graph._execute_tools({
|
|
717
|
+
"messages": [parent],
|
|
718
|
+
"workspace": str(tmp_path),
|
|
719
|
+
"persona": "voidx",
|
|
720
|
+
"plan_mode": False,
|
|
721
|
+
})
|
|
722
|
+
finally:
|
|
723
|
+
await graph._ui.events.stop()
|
|
724
|
+
|
|
725
|
+
assert result["messages"][0].tool_call_id == "call_read"
|
|
726
|
+
assert result["messages"][0].status == "error"
|
|
727
|
+
assert result["messages"][0].content == "File not found: missing.py"
|
|
728
|
+
|
|
729
|
+
|
|
730
|
+
@pytest.mark.asyncio
|
|
731
|
+
async def test_execute_tools_emits_heartbeat_while_tool_is_still_running(tmp_path, monkeypatch):
|
|
732
|
+
from voidx.agent.graph.tool_executor import executor as executor_module
|
|
733
|
+
|
|
734
|
+
graph = _graph(tmp_path)
|
|
735
|
+
emitted: list = []
|
|
736
|
+
|
|
737
|
+
class SlowReadTool:
|
|
738
|
+
id = "read"
|
|
739
|
+
description = "slow read"
|
|
740
|
+
|
|
741
|
+
def parameters_schema(self):
|
|
742
|
+
return {"type": "object", "properties": {}}
|
|
743
|
+
|
|
744
|
+
async def execute(self, args: dict, ctx: ToolContext) -> ToolResult:
|
|
745
|
+
await asyncio.sleep(0.03)
|
|
746
|
+
return ToolResult(output="read output")
|
|
747
|
+
|
|
748
|
+
graph.tools.register("read", SlowReadTool(), "slow read", {"type": "object", "properties": {}})
|
|
749
|
+
|
|
750
|
+
async def allow_all(
|
|
751
|
+
tool_calls,
|
|
752
|
+
plan_mode: bool,
|
|
753
|
+
session_id: str,
|
|
754
|
+
interaction_mode=None,
|
|
755
|
+
workflow_runs=None,
|
|
756
|
+
runtime_persona=None,
|
|
757
|
+
):
|
|
758
|
+
return tool_calls, []
|
|
759
|
+
|
|
760
|
+
async def fake_request(event):
|
|
761
|
+
emitted.append(event)
|
|
762
|
+
return None
|
|
763
|
+
|
|
764
|
+
async def fake_emit(event):
|
|
765
|
+
emitted.append(event)
|
|
766
|
+
return True
|
|
767
|
+
|
|
768
|
+
async def fake_drain():
|
|
769
|
+
return None
|
|
770
|
+
|
|
771
|
+
graph._authorize_tool_calls = allow_all
|
|
772
|
+
monkeypatch.setattr(graph._ui, "via_events", lambda: True)
|
|
773
|
+
monkeypatch.setattr(graph._ui.events, "request", fake_request)
|
|
774
|
+
monkeypatch.setattr(graph._ui.events, "emit", fake_emit)
|
|
775
|
+
monkeypatch.setattr(graph._ui.events, "drain", fake_drain)
|
|
776
|
+
monkeypatch.setattr(executor_module, "TOOL_HEARTBEAT_INITIAL_SECONDS", 0.01)
|
|
777
|
+
monkeypatch.setattr(executor_module, "TOOL_HEARTBEAT_INTERVAL_SECONDS", 0.01)
|
|
778
|
+
|
|
779
|
+
parent = AIMessage(
|
|
780
|
+
content="",
|
|
781
|
+
tool_calls=[{"name": "read", "args": {}, "id": "call_read", "type": "tool_call"}],
|
|
782
|
+
)
|
|
783
|
+
|
|
784
|
+
result = await graph._execute_tools({
|
|
785
|
+
"messages": [parent],
|
|
786
|
+
"workspace": str(tmp_path),
|
|
787
|
+
"persona": "voidx",
|
|
788
|
+
"plan_mode": False,
|
|
789
|
+
})
|
|
790
|
+
|
|
791
|
+
heartbeats = [
|
|
792
|
+
event for event in emitted
|
|
793
|
+
if isinstance(event, StatusUpdated)
|
|
794
|
+
and event.status_id == "tool-heartbeat:call_read"
|
|
795
|
+
]
|
|
796
|
+
assert heartbeats
|
|
797
|
+
assert "read still running" in heartbeats[0].detail
|
|
798
|
+
assert result["messages"][0].content == "read output"
|
|
@@ -459,19 +459,23 @@ async def test_permission_prompt_uses_dock_details_when_events_are_active(tmp_pa
|
|
|
459
459
|
choice = await graph._ask_tool_permission([
|
|
460
460
|
{
|
|
461
461
|
"name": "bash",
|
|
462
|
-
"args": {"command": "npm
|
|
462
|
+
"args": {"command": "npm install lodash"},
|
|
463
463
|
"id": "call_1",
|
|
464
464
|
}
|
|
465
465
|
])
|
|
466
466
|
await graph._ui.events.drain()
|
|
467
467
|
|
|
468
468
|
assert choice == "y"
|
|
469
|
-
assert received_details
|
|
469
|
+
assert received_details == [{
|
|
470
|
+
"name": "bash",
|
|
471
|
+
"pattern": "npm install lodash",
|
|
472
|
+
"args": {"command": "npm install lodash"},
|
|
473
|
+
}]
|
|
470
474
|
record = test_dock.status_record("permission:request")
|
|
471
475
|
assert record is not None
|
|
472
476
|
assert record.label == "Requesting"
|
|
473
477
|
assert "bash" in record.detail
|
|
474
|
-
assert "npm
|
|
478
|
+
assert "npm install lodash" in record.detail
|
|
475
479
|
finally:
|
|
476
480
|
await graph._ui.events.stop()
|
|
477
481
|
test_dock.deactivate()
|
|
@@ -352,3 +352,49 @@ async def test_implement_subagent_injects_workflow_nodes(tmp_path, monkeypatch):
|
|
|
352
352
|
not (isinstance(message, HumanMessage) and "## Runtime State" in str(message.content))
|
|
353
353
|
for message in captured["messages"]
|
|
354
354
|
)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
@pytest.mark.asyncio
|
|
359
|
+
async def test_prepare_does_not_reactivate_satisfied_workflow_via_stale_route(tmp_path):
|
|
360
|
+
"""When a workflow tool advanced feedback->tdd, task_state.workflow_runs
|
|
361
|
+
has feedback=SATISFIED and tdd=ACTIVE. But workflow_route.join still
|
|
362
|
+
points at the old node (feedback) because workflow enter/advance does
|
|
363
|
+
not update the route. The LLM prepare step must not use the stale
|
|
364
|
+
route to reactivate feedback and overwrite its SATISFIED status."""
|
|
365
|
+
graph = VoidXGraph(
|
|
366
|
+
Config(workspace=str(tmp_path)),
|
|
367
|
+
api_key=None,
|
|
368
|
+
settings=Settings(str(tmp_path)),
|
|
369
|
+
)
|
|
370
|
+
result = await graph._prepare_with_stream({
|
|
371
|
+
"messages": [HumanMessage(content="继续实现")],
|
|
372
|
+
"workspace": str(tmp_path),
|
|
373
|
+
"persona": "implement",
|
|
374
|
+
"plan_mode": False,
|
|
375
|
+
"interaction_mode": "auto",
|
|
376
|
+
"task_state": TaskState(
|
|
377
|
+
current_intent=TaskIntent.CODING,
|
|
378
|
+
current_goal=GoalSpec(desc="实现 feature X"),
|
|
379
|
+
workflow_route=WorkflowRoute(join="feedback", leave=None),
|
|
380
|
+
workflow_runs={
|
|
381
|
+
"feedback": WorkflowRunState(
|
|
382
|
+
name="feedback",
|
|
383
|
+
status=WorkflowRunStatus.SATISFIED,
|
|
384
|
+
reason="transition from feedback via nontrivial_fix",
|
|
385
|
+
),
|
|
386
|
+
"tdd": WorkflowRunState(
|
|
387
|
+
name="tdd",
|
|
388
|
+
status=WorkflowRunStatus.ACTIVE,
|
|
389
|
+
reason="transition from feedback via nontrivial_fix",
|
|
390
|
+
),
|
|
391
|
+
},
|
|
392
|
+
).model_dump(mode="json"),
|
|
393
|
+
"tool_results": {},
|
|
394
|
+
"step_count": 0,
|
|
395
|
+
"should_continue": True,
|
|
396
|
+
})
|
|
397
|
+
|
|
398
|
+
result_task_state = TaskState.model_validate(result["task_state"])
|
|
399
|
+
assert result_task_state.workflow_runs["tdd"].status == WorkflowRunStatus.ACTIVE
|
|
400
|
+
assert result_task_state.workflow_runs["feedback"].status == WorkflowRunStatus.SATISFIED
|
|
@@ -138,6 +138,162 @@ async def test_quiet_slash_command_dispatches_without_turn(monkeypatch):
|
|
|
138
138
|
assert dispatched == ["/model reasoning"]
|
|
139
139
|
|
|
140
140
|
|
|
141
|
+
@pytest.mark.asyncio
|
|
142
|
+
async def test_web_headless_uses_gateway_frontend_without_default_tui_factory(monkeypatch, tmp_path):
|
|
143
|
+
graph = _graph(workspace=str(tmp_path))
|
|
144
|
+
_disable_external_managers(graph)
|
|
145
|
+
monkeypatch.setattr(runtime_ui_port, "show_startup", lambda **_: None)
|
|
146
|
+
|
|
147
|
+
def fail_create_frontend(*_args, **_kwargs):
|
|
148
|
+
raise AssertionError("web_headless must not create the default TUI frontend")
|
|
149
|
+
|
|
150
|
+
class ExitHeadlessFrontend:
|
|
151
|
+
instances = []
|
|
152
|
+
|
|
153
|
+
def __init__(self, status, commands):
|
|
154
|
+
self.status = status
|
|
155
|
+
self.commands = commands
|
|
156
|
+
self.request_handler = None
|
|
157
|
+
ExitHeadlessFrontend.instances.append(self)
|
|
158
|
+
|
|
159
|
+
async def run_headless(self, on_submit):
|
|
160
|
+
return
|
|
161
|
+
|
|
162
|
+
def set_external_command_handler(self, handler):
|
|
163
|
+
self.command_handler = handler
|
|
164
|
+
|
|
165
|
+
def set_external_request_handler(self, handler):
|
|
166
|
+
self.request_handler = handler
|
|
167
|
+
|
|
168
|
+
monkeypatch.setattr("voidx.agent.graph.run_loop.create_frontend", fail_create_frontend)
|
|
169
|
+
monkeypatch.setattr("voidx.agent.graph.run_loop.GatewayHeadlessFrontend", ExitHeadlessFrontend)
|
|
170
|
+
monkeypatch.setattr("voidx.agent.graph.run_loop.emit_web_gateway_bootstrap", lambda _url: None)
|
|
171
|
+
|
|
172
|
+
test_dock = BottomInputDock()
|
|
173
|
+
set_dock(test_dock)
|
|
174
|
+
test_dock.begin_capture()
|
|
175
|
+
try:
|
|
176
|
+
await graph.run(web=True, web_headless=True)
|
|
177
|
+
finally:
|
|
178
|
+
test_dock.deactivate()
|
|
179
|
+
test_dock.reset()
|
|
180
|
+
set_dock(None)
|
|
181
|
+
|
|
182
|
+
assert len(ExitHeadlessFrontend.instances) == 1
|
|
183
|
+
assert ExitHeadlessFrontend.instances[0].request_handler is not None
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@pytest.mark.asyncio
|
|
187
|
+
async def test_web_non_headless_falls_back_to_gateway_frontend_when_tui_unavailable(monkeypatch, tmp_path):
|
|
188
|
+
"""--web without --web-headless should fall back to GatewayHeadlessFrontend
|
|
189
|
+
when voidx_cli is not installed, instead of crashing."""
|
|
190
|
+
graph = _graph(workspace=str(tmp_path))
|
|
191
|
+
_disable_external_managers(graph)
|
|
192
|
+
monkeypatch.setattr(runtime_ui_port, "show_startup", lambda **_: None)
|
|
193
|
+
|
|
194
|
+
class ExitHeadlessFrontend:
|
|
195
|
+
instances = []
|
|
196
|
+
|
|
197
|
+
def __init__(self, status, commands):
|
|
198
|
+
self.status = status
|
|
199
|
+
self.commands = commands
|
|
200
|
+
self.request_handler = None
|
|
201
|
+
ExitHeadlessFrontend.instances.append(self)
|
|
202
|
+
|
|
203
|
+
async def run(self, on_submit):
|
|
204
|
+
return
|
|
205
|
+
|
|
206
|
+
async def run_headless(self, on_submit):
|
|
207
|
+
return
|
|
208
|
+
|
|
209
|
+
def set_external_command_handler(self, handler):
|
|
210
|
+
self.command_handler = handler
|
|
211
|
+
|
|
212
|
+
def set_external_request_handler(self, handler):
|
|
213
|
+
self.request_handler = handler
|
|
214
|
+
|
|
215
|
+
def fail_create_frontend(*_args, **_kwargs):
|
|
216
|
+
raise RuntimeError("voidx_cli is required for terminal UI mode.")
|
|
217
|
+
|
|
218
|
+
monkeypatch.setattr("voidx.agent.graph.run_loop.create_frontend", fail_create_frontend)
|
|
219
|
+
monkeypatch.setattr("voidx.agent.graph.run_loop.GatewayHeadlessFrontend", ExitHeadlessFrontend)
|
|
220
|
+
monkeypatch.setattr("voidx.agent.graph.run_loop.emit_web_gateway_bootstrap", lambda _url: None)
|
|
221
|
+
|
|
222
|
+
test_dock = BottomInputDock()
|
|
223
|
+
set_dock(test_dock)
|
|
224
|
+
test_dock.begin_capture()
|
|
225
|
+
try:
|
|
226
|
+
await graph.run(web=True, web_headless=False)
|
|
227
|
+
finally:
|
|
228
|
+
test_dock.deactivate()
|
|
229
|
+
test_dock.reset()
|
|
230
|
+
set_dock(None)
|
|
231
|
+
|
|
232
|
+
assert len(ExitHeadlessFrontend.instances) == 1
|
|
233
|
+
assert ExitHeadlessFrontend.instances[0].request_handler is not None
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
@pytest.mark.asyncio
|
|
237
|
+
async def test_apply_settings_update_refreshes_live_model(monkeypatch, tmp_path):
|
|
238
|
+
from voidx.config import Profile, Settings
|
|
239
|
+
|
|
240
|
+
created_models: list[tuple[str | None, str, str, str | None]] = []
|
|
241
|
+
|
|
242
|
+
def fake_create_chat_model(api_key, model_config):
|
|
243
|
+
marker = SimpleNamespace(
|
|
244
|
+
api_key=api_key,
|
|
245
|
+
provider=model_config.provider,
|
|
246
|
+
model=model_config.model,
|
|
247
|
+
base_url=model_config.base_url,
|
|
248
|
+
)
|
|
249
|
+
created_models.append((api_key, model_config.provider, model_config.model, model_config.base_url))
|
|
250
|
+
return marker
|
|
251
|
+
|
|
252
|
+
monkeypatch.setattr("voidx.agent.graph.core.voidx_graph.create_chat_model", fake_create_chat_model)
|
|
253
|
+
|
|
254
|
+
settings = await Settings.create(str(tmp_path))
|
|
255
|
+
await settings.save_profile(
|
|
256
|
+
Profile(
|
|
257
|
+
name="deepseek/deepseek-v4-pro",
|
|
258
|
+
api_key="sk-deepseek",
|
|
259
|
+
base_url="https://api.deepseek.com",
|
|
260
|
+
protocol="openai",
|
|
261
|
+
)
|
|
262
|
+
)
|
|
263
|
+
graph = VoidXGraph(
|
|
264
|
+
Config(workspace=str(tmp_path), model=ModelConfig(provider="openai", model="gpt-4.1")),
|
|
265
|
+
api_key="sk-openai",
|
|
266
|
+
settings=settings,
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
graph._app = SimpleNamespace(
|
|
270
|
+
status=SimpleNamespace(
|
|
271
|
+
provider="openai",
|
|
272
|
+
model="gpt-4.1",
|
|
273
|
+
context_limit=0,
|
|
274
|
+
reasoning_effort="xhigh",
|
|
275
|
+
)
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
await graph._apply_settings_update(settings)
|
|
279
|
+
|
|
280
|
+
assert graph.config.workspace == str(tmp_path)
|
|
281
|
+
assert graph.config.model.provider == "deepseek"
|
|
282
|
+
assert graph.config.model.model == "deepseek-v4-pro"
|
|
283
|
+
assert graph.config.model.base_url == "https://api.deepseek.com"
|
|
284
|
+
assert graph.api_key == "sk-deepseek"
|
|
285
|
+
assert graph.model.provider == "deepseek"
|
|
286
|
+
assert graph.model.model == "deepseek-v4-pro"
|
|
287
|
+
assert created_models[-1] == (
|
|
288
|
+
"sk-deepseek",
|
|
289
|
+
"deepseek",
|
|
290
|
+
"deepseek-v4-pro",
|
|
291
|
+
"https://api.deepseek.com",
|
|
292
|
+
)
|
|
293
|
+
assert graph._app.status.provider == "deepseek"
|
|
294
|
+
assert graph._app.status.model == "deepseek-v4-pro"
|
|
295
|
+
|
|
296
|
+
|
|
141
297
|
@pytest.mark.asyncio
|
|
142
298
|
async def test_web_guide_submit_records_guidance_without_starting_turn():
|
|
143
299
|
graph = _graph()
|
|
@@ -117,7 +117,7 @@ async def test_run_once_uses_general_fallback_when_structured_resolver_fails(tmp
|
|
|
117
117
|
|
|
118
118
|
initial = captured["initial"]
|
|
119
119
|
assert initial["task_state"]["current_intent"] == "general"
|
|
120
|
-
assert initial["task_state"]["current_goal"] is None
|
|
120
|
+
assert initial["task_state"]["current_goal"] is not None
|
|
121
121
|
assert initial["task_state"]["recent_exchanges"] == []
|
|
122
122
|
rows = await load_messages(graph._session.id)
|
|
123
123
|
assert [row.role for row in rows] == ["user", "assistant"]
|
|
@@ -261,6 +261,104 @@ async def test_run_once_loads_execution_context_runtime_state(tmp_path):
|
|
|
261
261
|
await delete_session(active.id)
|
|
262
262
|
await delete_session(target.id)
|
|
263
263
|
|
|
264
|
+
|
|
265
|
+
@pytest.mark.asyncio
|
|
266
|
+
async def test_run_once_model_enabled_first_turn_syncs_default_task_state(tmp_path):
|
|
267
|
+
from voidx.agent.runtime_context import InteractionMode
|
|
268
|
+
|
|
269
|
+
graph = VoidXGraph(Config(workspace=str(tmp_path)), api_key="test", session=None)
|
|
270
|
+
graph._interaction_mode = InteractionMode.GOAL
|
|
271
|
+
ready = asyncio.Event()
|
|
272
|
+
proceed = asyncio.Event()
|
|
273
|
+
seen: list[str | None] = []
|
|
274
|
+
|
|
275
|
+
class FakeGraph:
|
|
276
|
+
async def ainvoke(self, initial, _config):
|
|
277
|
+
ready.set()
|
|
278
|
+
await asyncio.wait_for(proceed.wait(), timeout=1)
|
|
279
|
+
return {"messages": list(initial["messages"]) + [AIMessage(content="first answer")], "task_state": initial["task_state"]}
|
|
280
|
+
|
|
281
|
+
async def external_reader():
|
|
282
|
+
await asyncio.wait_for(ready.wait(), timeout=1)
|
|
283
|
+
seen.append(graph._task_state.current_goal.desc if graph._task_state.current_goal else None)
|
|
284
|
+
proceed.set()
|
|
285
|
+
|
|
286
|
+
graph.graph = FakeGraph()
|
|
287
|
+
reader_task = asyncio.create_task(external_reader())
|
|
288
|
+
|
|
289
|
+
test_dock = BottomInputDock()
|
|
290
|
+
set_dock(test_dock)
|
|
291
|
+
test_dock.begin_capture()
|
|
292
|
+
try:
|
|
293
|
+
await graph._run_once("first question")
|
|
294
|
+
finally:
|
|
295
|
+
test_dock.deactivate()
|
|
296
|
+
test_dock.reset()
|
|
297
|
+
set_dock(None)
|
|
298
|
+
|
|
299
|
+
await reader_task
|
|
300
|
+
assert seen == ["first question"]
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
@pytest.mark.asyncio
|
|
304
|
+
async def test_run_once_model_enabled_borrowed_context_does_not_leak_task_state(tmp_path):
|
|
305
|
+
from voidx.agent.runtime_context import InteractionMode
|
|
306
|
+
from voidx.memory.runtime_state import RuntimeStateSnapshot, load_runtime_state, save_runtime_state
|
|
307
|
+
from voidx.ui.output.types import ThreadExecutionContext
|
|
308
|
+
|
|
309
|
+
active = await create_session(workspace=str(tmp_path), title="Active")
|
|
310
|
+
target = await create_session(workspace=str(tmp_path), title="Target")
|
|
311
|
+
try:
|
|
312
|
+
active_state = TaskState(current_goal=GoalSpec(desc="active goal"))
|
|
313
|
+
target_state = TaskState(current_goal=GoalSpec(desc="target goal"))
|
|
314
|
+
await save_runtime_state(active.id, RuntimeStateSnapshot(interaction_mode=InteractionMode.GOAL, task_state=active_state))
|
|
315
|
+
await save_runtime_state(target.id, RuntimeStateSnapshot(interaction_mode=InteractionMode.PLAN, task_state=target_state))
|
|
316
|
+
|
|
317
|
+
graph = VoidXGraph(Config(workspace=str(tmp_path)), api_key="test", session=active)
|
|
318
|
+
await graph._restore_runtime_state()
|
|
319
|
+
captured: dict[str, str] = {}
|
|
320
|
+
|
|
321
|
+
class FakeGraph:
|
|
322
|
+
async def ainvoke(self, initial, _config):
|
|
323
|
+
state = TaskState.model_validate(initial["task_state"])
|
|
324
|
+
captured["goal"] = state.current_goal.desc if state.current_goal else ""
|
|
325
|
+
captured["interaction_mode"] = initial["interaction_mode"]
|
|
326
|
+
updated_state = state.model_copy(update={"current_goal": GoalSpec(desc="target mutated goal")})
|
|
327
|
+
return {
|
|
328
|
+
"messages": list(initial["messages"]) + [AIMessage(content="target answer")],
|
|
329
|
+
"task_state": updated_state.model_dump(mode="json"),
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
graph.graph = FakeGraph()
|
|
333
|
+
|
|
334
|
+
test_dock = BottomInputDock()
|
|
335
|
+
set_dock(test_dock)
|
|
336
|
+
test_dock.begin_capture()
|
|
337
|
+
try:
|
|
338
|
+
await graph._run_once(
|
|
339
|
+
"target question",
|
|
340
|
+
context=ThreadExecutionContext(thread_id=target.id, session_id=target.id),
|
|
341
|
+
)
|
|
342
|
+
finally:
|
|
343
|
+
test_dock.deactivate()
|
|
344
|
+
test_dock.reset()
|
|
345
|
+
set_dock(None)
|
|
346
|
+
|
|
347
|
+
assert captured == {"goal": "target goal", "interaction_mode": "plan"}
|
|
348
|
+
assert graph._session.id == active.id
|
|
349
|
+
assert graph._task_state.current_goal is not None
|
|
350
|
+
assert graph._task_state.current_goal.desc == "active goal"
|
|
351
|
+
assert graph._interaction_mode == InteractionMode.GOAL
|
|
352
|
+
|
|
353
|
+
active_snapshot = await load_runtime_state(active.id)
|
|
354
|
+
target_snapshot = await load_runtime_state(target.id)
|
|
355
|
+
assert active_snapshot.task_state.current_goal is not None
|
|
356
|
+
assert active_snapshot.task_state.current_goal.desc == "active goal"
|
|
357
|
+
assert target_snapshot.task_state.current_goal is not None
|
|
358
|
+
assert target_snapshot.task_state.current_goal.desc == "target mutated goal"
|
|
359
|
+
finally:
|
|
360
|
+
await delete_session(active.id)
|
|
361
|
+
await delete_session(target.id)
|
|
264
362
|
@pytest.mark.asyncio
|
|
265
363
|
async def test_run_once_isolates_concurrent_execution_context_state(tmp_path):
|
|
266
364
|
from voidx.agent.runtime_context import InteractionMode
|
|
@@ -49,7 +49,13 @@ from voidx.tools.base import ToolContext, ToolResult
|
|
|
49
49
|
from voidx.tools.agent import AgentResultContract, AgentTool
|
|
50
50
|
from voidx.tools.registry import ToolRegistry
|
|
51
51
|
from voidx.ui.output.dock import BottomInputDock, set_dock
|
|
52
|
-
from voidx.ui.output.events import
|
|
52
|
+
from voidx.ui.output.events import (
|
|
53
|
+
DockEventConsumer,
|
|
54
|
+
TurnCompleted,
|
|
55
|
+
TurnFailed,
|
|
56
|
+
TurnStarted,
|
|
57
|
+
ui_events,
|
|
58
|
+
)
|
|
53
59
|
|
|
54
60
|
|
|
55
61
|
def _graph(tmp_path):
|
|
@@ -189,6 +195,89 @@ async def test_run_once_persists_and_restores_transcript_snapshot(tmp_path):
|
|
|
189
195
|
await delete_session(session.id)
|
|
190
196
|
|
|
191
197
|
|
|
198
|
+
@pytest.mark.asyncio
|
|
199
|
+
async def test_run_once_emits_turn_completed_event(tmp_path):
|
|
200
|
+
session = await create_session(workspace=str(tmp_path))
|
|
201
|
+
events: list[object] = []
|
|
202
|
+
|
|
203
|
+
class RecordingConsumer:
|
|
204
|
+
def handle(self, event):
|
|
205
|
+
events.append(event)
|
|
206
|
+
if isinstance(event, TurnStarted):
|
|
207
|
+
return object()
|
|
208
|
+
return None
|
|
209
|
+
|
|
210
|
+
try:
|
|
211
|
+
graph = VoidXGraph(Config(workspace=str(tmp_path)), api_key=None, session=session)
|
|
212
|
+
|
|
213
|
+
class FakeGraph:
|
|
214
|
+
async def ainvoke(self, initial, _config):
|
|
215
|
+
return {"messages": list(initial["messages"]) + [AIMessage(content="done")]}
|
|
216
|
+
|
|
217
|
+
graph.graph = FakeGraph()
|
|
218
|
+
|
|
219
|
+
test_dock = BottomInputDock()
|
|
220
|
+
set_dock(test_dock)
|
|
221
|
+
test_dock.begin_capture()
|
|
222
|
+
ui_events.start(RecordingConsumer())
|
|
223
|
+
try:
|
|
224
|
+
await graph._run_once("hello")
|
|
225
|
+
await ui_events.drain()
|
|
226
|
+
finally:
|
|
227
|
+
await ui_events.stop()
|
|
228
|
+
test_dock.deactivate()
|
|
229
|
+
test_dock.reset()
|
|
230
|
+
set_dock(None)
|
|
231
|
+
|
|
232
|
+
assert any(isinstance(event, TurnCompleted) for event in events)
|
|
233
|
+
assert not any(isinstance(event, TurnFailed) for event in events)
|
|
234
|
+
finally:
|
|
235
|
+
await delete_session(session.id)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
@pytest.mark.asyncio
|
|
239
|
+
async def test_run_once_emits_turn_failed_event_on_exception(tmp_path):
|
|
240
|
+
session = await create_session(workspace=str(tmp_path))
|
|
241
|
+
events: list[object] = []
|
|
242
|
+
|
|
243
|
+
class RecordingConsumer:
|
|
244
|
+
def handle(self, event):
|
|
245
|
+
events.append(event)
|
|
246
|
+
if isinstance(event, TurnStarted):
|
|
247
|
+
return object()
|
|
248
|
+
return None
|
|
249
|
+
|
|
250
|
+
try:
|
|
251
|
+
graph = VoidXGraph(Config(workspace=str(tmp_path)), api_key=None, session=session)
|
|
252
|
+
|
|
253
|
+
class FakeGraph:
|
|
254
|
+
async def ainvoke(self, initial, _config):
|
|
255
|
+
raise RuntimeError("provider failed")
|
|
256
|
+
|
|
257
|
+
graph.graph = FakeGraph()
|
|
258
|
+
|
|
259
|
+
test_dock = BottomInputDock()
|
|
260
|
+
set_dock(test_dock)
|
|
261
|
+
test_dock.begin_capture()
|
|
262
|
+
ui_events.start(RecordingConsumer())
|
|
263
|
+
try:
|
|
264
|
+
with pytest.raises(RuntimeError, match="provider failed"):
|
|
265
|
+
await graph._run_once("hello")
|
|
266
|
+
await ui_events.drain()
|
|
267
|
+
finally:
|
|
268
|
+
await ui_events.stop()
|
|
269
|
+
test_dock.deactivate()
|
|
270
|
+
test_dock.reset()
|
|
271
|
+
set_dock(None)
|
|
272
|
+
|
|
273
|
+
failures = [event for event in events if isinstance(event, TurnFailed)]
|
|
274
|
+
assert len(failures) == 1
|
|
275
|
+
assert failures[0].message == "provider failed"
|
|
276
|
+
assert not any(isinstance(event, TurnCompleted) for event in events)
|
|
277
|
+
finally:
|
|
278
|
+
await delete_session(session.id)
|
|
279
|
+
|
|
280
|
+
|
|
192
281
|
@pytest.mark.asyncio
|
|
193
282
|
async def test_run_once_commits_event_todo_at_turn_end(tmp_path):
|
|
194
283
|
session = await create_session(workspace=str(tmp_path))
|
|
@@ -338,4 +427,3 @@ async def test_run_once_persists_user_decision_tool_replay_rows(tmp_path):
|
|
|
338
427
|
finally:
|
|
339
428
|
await delete_session(session.id)
|
|
340
429
|
|
|
341
|
-
|