voidx 3.7.2__tar.gz → 3.7.4__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.7.2/src/voidx.egg-info → voidx-3.7.4}/PKG-INFO +1 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_call_llm_compaction.py +29 -0
- voidx-3.7.4/src/tests/test_agent/graph/test_call_llm_structure.py +12 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_graph_authorization.py +83 -31
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_subagent_runner.py +0 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_tool_execution_auth.py +23 -3
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_turn_control_e2e.py +5 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_turn_control_integration.py +30 -16
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_workflow_transactions_barrier.py +0 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/loop/test_manager.py +20 -2
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/slash/test_slash_model.py +6 -6
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/slash/test_slash_model_advanced.py +6 -6
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_permission.py +16 -16
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_permission_phase2.py +5 -5
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_permission_phase4.py +15 -32
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_permission_phase5.py +7 -8
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_permission_phase6.py +7 -20
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_tool_result_storage.py +62 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_config/test_config_advanced.py +15 -16
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_llm_usage.py +25 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_permission/test_risk.py +54 -6
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_skills/test_skill_parsing.py +0 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_skills/test_skill_references.py +0 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_skills/test_workflow_advance.py +0 -5
- voidx-3.7.4/src/tests/test_tools/bash/test_auto_route_git.py +342 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/bash/test_router_git.py +24 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/bash/test_tool.py +98 -5
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_edit_dedup.py +103 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_edit_line_insert.py +181 -0
- voidx-3.7.4/src/tests/test_tools/file/test_overlap.py +73 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_git_tool_destructive.py +2 -3
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_git_tool_phase5.py +2 -2
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_git_tool_raw_permissions.py +1 -2
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_git_tool_schema_errors.py +0 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_git_tool_structured.py +4 -4
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_powershell_tool.py +52 -2
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_powershell_tool_phase6.py +3 -3
- voidx-3.7.4/src/tests/test_tools/test_shell_json_format.py +33 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_shell_tool_phase6.py +3 -3
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_tool_schemas.py +2 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_gateway_v2_dispatch.py +3 -5
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_gateway_v2_routing.py +50 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/__init__.py +1 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/goal_resolver.py +13 -4
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/contracts.py +3 -2
- voidx-3.7.4/src/voidx/agent/graph/core/context.py +94 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/core/helpers.py +4 -3
- voidx-3.7.4/src/voidx/agent/graph/core/llm.py +548 -0
- voidx-3.7.4/src/voidx/agent/graph/core/loop.py +108 -0
- voidx-3.7.4/src/voidx/agent/graph/core/turn.py +353 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/permissions.py +15 -77
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/run_loop.py +2 -2
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/session_runtime.py +1 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/subagent.py +21 -7
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/thread_context.py +3 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/tool_executor/executor.py +5 -2
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/tool_executor/helpers.py +2 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/tool_executor/workflow.py +2 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/turn_control.py +7 -2
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/turn_runner.py +11 -5
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/wiring.py +0 -4
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/loop/manager.py +5 -2
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/loop/slash.py +2 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/prompts.py +7 -6
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/runtime_context.py +22 -7
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/slash/handler.py +20 -42
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/slash/host.py +1 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/slash/init.py +2 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/todo_state.py +5 -4
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/tool_result_storage.py +34 -9
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/__init__.py +0 -8
- voidx-3.7.4/src/voidx/config/enums.py +41 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/models.py +2 -6
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/settings.py +0 -8
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/settings_permissions.py +7 -57
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/voidx-guide/permission.md +5 -5
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/voidx-guide/reference.md +1 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/llm/usage.py +20 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/paths.py +2 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/permission/__init__.py +4 -4
- voidx-3.7.4/src/voidx/permission/constants.py +177 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/permission/context.py +20 -11
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/permission/engine.py +6 -6
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/permission/git_policy.py +13 -72
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/permission/grants.py +1 -0
- voidx-3.7.4/src/voidx/permission/presets.py +73 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/permission/rules.py +10 -13
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/permission/sandbox.py +11 -39
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/permission/schema.py +9 -3
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/permission/service.py +36 -73
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/permission/shell_policy.py +13 -14
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/runtime/intent.py +8 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/runtime/task_state.py +8 -2
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/base.py +18 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/bash/tool.py +5 -1
- voidx-3.7.4/src/voidx/tools/file/overlap.py +35 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/file/replace.py +120 -83
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/file/safe_path.py +0 -2
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/file/write.py +43 -6
- voidx-3.7.4/src/voidx/tools/git/__init__.py +7 -0
- voidx-3.7.4/src/voidx/tools/git/access.py +251 -0
- voidx-3.7.4/src/voidx/tools/git/constants.py +54 -0
- voidx-3.7.4/src/voidx/tools/git/handlers.py +349 -0
- voidx-3.7.4/src/voidx/tools/git/models.py +38 -0
- voidx-3.7.4/src/voidx/tools/git/parsers.py +247 -0
- voidx-3.7.4/src/voidx/tools/git/process.py +81 -0
- voidx-3.7.4/src/voidx/tools/git/results.py +90 -0
- voidx-3.7.4/src/voidx/tools/git/routing.py +145 -0
- voidx-3.7.4/src/voidx/tools/git/tool.py +109 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/powershell/tool.py +5 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/search.py +4 -4
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/shell/common.py +22 -4
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/shell/hint/git.py +15 -9
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/command_catalog.py +3 -4
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/commands.py +5 -9
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/session/core.py +10 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/session/method/settings.py +4 -8
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/events/bus.py +15 -3
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/types.py +0 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/workflow/__init__.py +0 -2
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/workflow/nodes.py +0 -4
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/workflow/policy.py +0 -6
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/workflow/render.py +0 -4
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/workflow/schema.py +0 -10
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/workflow/service.py +0 -1
- {voidx-3.7.2 → voidx-3.7.4/src/voidx.egg-info}/PKG-INFO +1 -1
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx.egg-info/SOURCES.txt +19 -1
- voidx-3.7.2/src/voidx/agent/graph/core/llm.py +0 -800
- voidx-3.7.2/src/voidx/config/enums.py +0 -69
- voidx-3.7.2/src/voidx/permission/presets.py +0 -66
- voidx-3.7.2/src/voidx/tools/git.py +0 -1242
- {voidx-3.7.2 → voidx-3.7.4}/LICENSE +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/README.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/pyproject.toml +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/setup.cfg +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/conftest.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/conftest.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/conftest.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/run_loop_helpers.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/stream_llm_helpers.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_call_llm_compaction_advanced.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_call_llm_tools.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_compaction_flow.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_compaction_flow_run_once.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_convergence.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_execute_tools_guard.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_execute_tools_todo.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_graph_setup_prompts.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_guards_tool_op.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_parallel_subagents.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_parallel_subagents_dedup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_prepare_workflow.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_run_loop_startup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_run_loop_title_lsp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_run_loop_title_misc.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_run_loop_workflow.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_run_loop_workflow_advanced.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_runtime_guards.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_session_context_frames.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_session_crud.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_session_messages.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_session_persistence.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_session_run_once.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_session_runtime_state.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_session_transcript.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_stream_llm_sanitization.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_subagent_llm_retry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_subagent_persistence.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_subagent_step_budget.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_subagent_step_budget_convergence.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_subagent_step_budget_final.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_todo_events.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_tool_result_preview.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_turn_runner_guidance_discard.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_turn_runner_idle_event.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_turn_stop_without_pending.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_workflow_done.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_workflow_review.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_workflow_transactions.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/loop/test_prompt_source.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/slash/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/slash/test_slash_init.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/slash/test_slash_loop.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/slash/test_slash_mcp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/slash/test_slash_session.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/slash/test_slash_skills.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/slash/test_slash_tavily.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/slash/test_slash_upgrade.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_attachments.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_file_rwlock.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_goal_resolver.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_goal_resolver_advanced.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_guard_guidance.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_guide_command.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_message_trimming_parsers.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_message_trimming_rules.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_module_boundaries.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_permission_append.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_permission_phase3.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_prompts.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_runtime_context_builder.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_runtime_context_prompts.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_runtime_context_skill_stripping.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_task_state.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_task_state_context_sync.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_task_state_rendering.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_todo_replay_sanitization.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_tool_exchange_sanitizer.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_tool_filters_gemini.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_tool_messages.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_turn_control.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_turn_control_prompt.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_turn_metrics.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/test_turn_start.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_archive_script.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_config/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_config/test_config.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_config/test_retry_config.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_install_sh.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/conftest.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_compaction_retry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_fallback_summary.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_gemini_provider.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_goal_resolver_retry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_instruction_cache.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_llm_catalog.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_llm_catalog_fetchers.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_llm_provider.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_llm_provider_advanced.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_overflow_threshold.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_prune_args.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_request_log.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_streaming_sanitize.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_llm/test_token_counting.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_logging/test_external.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_logging/test_internal_error.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_logging/test_tool_log.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_lsp/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_lsp/test_lsp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_lsp/test_lsp_advanced.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_mcp/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_mcp/test_mcp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_memory/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_memory/test_main.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_memory/test_main_startup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_memory/test_schema_migration.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_npm_package.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_permission/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_release_npm_wheel_sync.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_runtime/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_runtime/test_goal_resolution_refactor.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_runtime/test_processes.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_runtime/test_runtime_ui.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_selfupdate/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_selfupdate/test_selfupdate.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_skills/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_skills/conftest.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_skills/test_create_skill.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_test_runner.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/bash/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/bash/test_router_safety.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/bash/test_router_sed_grep.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_coverage_fingerprint.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_edit_anchors.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_edit_bounds_input.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_edit_coverage.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_edit_drift_fallback.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_edit_drift_fallback_e2e.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_edit_errors.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_edit_llm_messages.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_edit_replace.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_edit_trailing_newline.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_read.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_read_write.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_render_numbered_diff.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/file/test_write_file.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_clarify_tool.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_diffing.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_file_tools_redesign.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_infer_state_patch.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_interactive_tools.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_interactive_tools_write.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_load_doc_template.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_loop_integration.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_loop_registry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_make_interact_callback.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_plan_checkpoint.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_replace_failure_logging.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_resolve_safe.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_retry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_schedule_wakeup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_search.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_skills_tool.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_state_update_from_executed_tools.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_task_tracker.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_todo_tool.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_tool_error_handling.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_tool_registry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_tool_state_patch.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_user_interaction_models.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_web_mcp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_webfetch.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_tools/test_workflow_tool.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/conftest.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/helpers.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_adapter.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_diff_review.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_gateway_headless_frontend.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_gateway_v2_crud_diff.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_gateway_v2_server.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_gateway_v2_session.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_guidance_fallback.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_run_manager.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_terminal.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_ui_events_dock_bus.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_ui_events_dock_prompts.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_ui_events_dock_status.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_ui_events_streaming.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_ui_events_subagent.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_ui_events_todo.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/gateway/test_ui_gateway.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/output/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/output/test_console_app.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/output/test_dock_formatting.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/output/test_fmt_args.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/output/test_output_browse.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/output/test_scrollback_flush.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/output/test_tool_display.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/output/test_tree_smoke.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/output/test_ui_diff.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/output/test_ui_session_changes.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/protocol/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/protocol/test_dto.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/protocol/test_v2_envelope.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/protocol/test_v2_methods.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/protocol/test_v2_snapshot.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/protocol/test_v2_threads.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/test_display_policy.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/test_file_picker.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/tools/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/tools/test_clipboard_image.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/tools/test_clipboard_image_windows.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/tools/test_clipboard_text.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/tools/test_clipboard_text_windows.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_ui/tools/test_code_ide.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_voidx_entrypoint.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_wheel_build.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_wheel_verify_cwd.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_workflow/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_workflow/test_auto_advance.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/tests/test_workflow/test_workflow_reconcile.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/agents.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/attachments.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/compaction.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/compaction_coordinator.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/convergence.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/core/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/core/voidx_graph.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/runtime.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/runtime_guards.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/session_mixin.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/streaming.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/title_mixin.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/todo_events.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/tool_execution.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/tool_executor/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/tool_executor/guards.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/tool_executor/types.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/tool_executor/ui.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/topology.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/transcript_mixin.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/turn_metrics.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/turn_mixin.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/graph/workflow_utils.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/loop/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/loop/prompt_source.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/message_rows.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/message_trimming.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/slash/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/slash/code_ide.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/slash/guide.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/slash/lsp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/slash/mcp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/slash/model.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/slash/profile.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/slash/runtime.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/slash/session.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/slash/skills.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/slash/upgrade.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/state.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/task_state.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/tool_call_ids.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/tool_exchange_sanitizer.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/tool_filters.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/agent/tool_messages.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/defaults.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/settings_agent.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/settings_api_keys.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/settings_code_ide.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/settings_custom.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/settings_mcp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/settings_retry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/settings_skills.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/settings_update.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/settings_utils.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/config/settings_web.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/README.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/templates/api-doc.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/templates/capability-spec.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/templates/implementation-spec.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/templates/prd.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/templates/readme.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/templates/rfc.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/templates/tasks.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/templates/tech-design.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/voidx-guide/README.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/voidx-guide/context.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/voidx-guide/debug.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/voidx-guide/extension.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/voidx-guide/mode.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/voidx-guide/model.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/voidx-guide/preferences.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/voidx-guide/quickstart.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/voidx-guide/session.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/voidx-guide/upgrade.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/voidx-guide/web.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/data/documents/voidx-guide/workflow.md +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/diffing.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/llm/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/llm/catalog.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/llm/compaction.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/llm/context.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/llm/instruction.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/llm/message_markers.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/llm/message_status.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/llm/provider.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/llm/service.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/logging/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/logging/external.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/logging/internal_error.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/logging/request_log.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/logging/tool_log.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/lsp/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/lsp/client.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/lsp/config.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/lsp/detector.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/lsp/detector_data.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/lsp/errors.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/lsp/manager.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/lsp/schema.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/lsp/service.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/main.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/mcp/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/mcp/client/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/mcp/client/base.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/mcp/client/errors.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/mcp/client/http_transport.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/mcp/client/sse_transport.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/mcp/client/stdio_transport.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/mcp/manager.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/mcp/schema.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/mcp/tool.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/mcp_servers/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/mcp_servers/web.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/memory/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/memory/cleanup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/memory/context_frames.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/memory/jsonl_store.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/memory/model_profiles.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/memory/runtime_state.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/memory/service.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/memory/session.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/memory/store.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/memory/subagents.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/memory/transcript.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/permission/evaluate.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/permission/process_sandbox.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/permission/risk.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/permission/wildcard.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/runtime/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/runtime/_win32_jobs.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/runtime/attachments.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/runtime/processes.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/runtime/reference_tokens.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/runtime/todo.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/runtime/ui.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/runtime/ui_port.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/selfupdate.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/skills/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/skills/context.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/skills/references.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/skills/registry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/skills/schema.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/skills/service.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/agent.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/bash/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/bash/core.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/bash/hint/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/bash/hint/file.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/bash/hint/git.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/bash/hint/search.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/bash/router.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/bash/safety.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/checkpoint.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/clarify.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/compact.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/document.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/file/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/file/manage.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/file/read.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/file/replace_resolve.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/file/state.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/file/types.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/lsp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/powershell/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/powershell/core.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/powershell/hint/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/powershell/hint/file.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/powershell/hint/search.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/powershell/router.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/powershell/safety.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/powershell/sandbox.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/registry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/retry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/schedule_wakeup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/service.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/shell/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/shell/hint/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/skills.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/task_status.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/task_tracker.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/todo.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/web/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/web/content.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/web/fetch.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/web/mcp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/web/search.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/tools/workflow.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/frontend.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/adapter.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/bootstrap.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/diff_review.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/frontend.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/run_manager.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/server.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/session/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/session/consumer.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/session/method/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/session/method/diff.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/session/method/integrations.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/session/method/sessions.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/session/method/terminal.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/gateway/terminal.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/agent_display.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/ansi_marker.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/browse.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/capture.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/console/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/console/app.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/console/formatting.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/console/streaming.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/diff.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/display_policy.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/dock/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/dock/agent_placeholder.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/dock/app.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/dock/formatting.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/dock/nodes.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/dock/nodes_checkpoint.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/dock/nodes_clarify.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/dock/nodes_permission.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/dock/nodes_startup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/dock/nodes_status.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/dock/state.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/dock/status.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/dock/stream.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/dock/todo.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/events/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/events/consumers.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/events/schema.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/manage_display.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/tool_display.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/output/tree.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/protocol/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/protocol/commands.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/protocol/requests.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/protocol/schema.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/protocol/transcript.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/protocol/v2/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/protocol/v2/envelope.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/protocol/v2/methods.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/protocol/v2/snapshot.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/protocol/v2/threads.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/session.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/tools/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/tools/attachment_tokens.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/tools/clipboard_image.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/tools/clipboard_text.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/tools/code_ide.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/tools/file_picker.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/tools/skill_picker.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/ui/transcript.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/workflow/auto_advance.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/workflow/context.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/workflow/dag.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/workflow/reconcile.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/workflow/route.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/workflow/runtime.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx/workflow/types.py +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx.egg-info/dependency_links.txt +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx.egg-info/entry_points.txt +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx.egg-info/requires.txt +0 -0
- {voidx-3.7.2 → voidx-3.7.4}/src/voidx.egg-info/top_level.txt +0 -0
|
@@ -19,6 +19,7 @@ from voidx.agent.task_state import TaskState, TodoRunState
|
|
|
19
19
|
from voidx.config import Config, ModelConfig
|
|
20
20
|
from voidx.agent.graph.compaction_coordinator import CompactionResult, PreflightCompactionResult
|
|
21
21
|
from voidx.llm.compaction import CompactionSelection, SUMMARY_TEMPLATE
|
|
22
|
+
from voidx.llm.usage import estimate_context_tokens
|
|
22
23
|
from voidx.llm.message_markers import is_guidance_message
|
|
23
24
|
from voidx.memory.context_frames import load_context_frames
|
|
24
25
|
from voidx.memory.session import MessageRow, create_session, delete_session, save_message
|
|
@@ -181,6 +182,7 @@ async def test_call_llm_updates_usage_stats_across_turn_control_calls(tmp_path,
|
|
|
181
182
|
"messages": [HumanMessage(content="hi")],
|
|
182
183
|
"step_count": 0,
|
|
183
184
|
"persona": "voidx",
|
|
185
|
+
"turn_state": "running",
|
|
184
186
|
})
|
|
185
187
|
|
|
186
188
|
assert result["step_count"] == 1
|
|
@@ -188,11 +190,38 @@ async def test_call_llm_updates_usage_stats_across_turn_control_calls(tmp_path,
|
|
|
188
190
|
assert graph.model.calls == 2
|
|
189
191
|
assert graph._usage_stats.last_input_tokens == 2
|
|
190
192
|
assert graph._usage_stats.last_output_tokens == 1
|
|
193
|
+
assert graph._usage_stats.context_tokens == 2
|
|
191
194
|
assert graph._usage_stats.total_input_tokens == 9
|
|
192
195
|
assert graph._usage_stats.total_output_tokens == 4
|
|
193
196
|
assert graph._usage_stats.total_calls == 2
|
|
194
197
|
|
|
195
198
|
|
|
199
|
+
@pytest.mark.asyncio
|
|
200
|
+
async def test_call_llm_fallback_context_estimate_includes_tool_schema(tmp_path, monkeypatch):
|
|
201
|
+
import voidx.agent.graph.core.llm as graph_module
|
|
202
|
+
|
|
203
|
+
monkeypatch.setattr(graph_module, "StreamingRenderer", FakeRenderer)
|
|
204
|
+
|
|
205
|
+
graph = VoidXGraph(
|
|
206
|
+
Config(
|
|
207
|
+
model=ModelConfig(provider="openai", model="gpt-4o"),
|
|
208
|
+
workspace=str(tmp_path),
|
|
209
|
+
),
|
|
210
|
+
api_key=None,
|
|
211
|
+
)
|
|
212
|
+
graph.model = FakeStreamingModel()
|
|
213
|
+
|
|
214
|
+
await graph._call_llm({
|
|
215
|
+
"messages": [HumanMessage(content="hi")],
|
|
216
|
+
"step_count": 0,
|
|
217
|
+
"persona": "voidx",
|
|
218
|
+
"turn_state": "running",
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
messages_only = estimate_context_tokens(graph.model.messages, graph.config.model.model)
|
|
222
|
+
assert graph._usage_stats.context_tokens > messages_only
|
|
223
|
+
|
|
224
|
+
|
|
196
225
|
@pytest.mark.asyncio
|
|
197
226
|
async def test_call_llm_persists_context_frame_for_session(tmp_path, monkeypatch):
|
|
198
227
|
import voidx.agent.graph.core.llm as graph_module
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Structure tests for the call_llm refactor."""
|
|
2
|
+
|
|
3
|
+
import importlib
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_call_llm_helpers_live_in_core_modules():
|
|
7
|
+
for module_name in (
|
|
8
|
+
"voidx.agent.graph.core.loop",
|
|
9
|
+
"voidx.agent.graph.core.turn",
|
|
10
|
+
"voidx.agent.graph.core.context",
|
|
11
|
+
):
|
|
12
|
+
assert importlib.import_module(module_name)
|
|
@@ -145,7 +145,6 @@ def test_permission_decision_splits_readonly_and_implement_agents():
|
|
|
145
145
|
@pytest.mark.asyncio
|
|
146
146
|
async def test_graph_authorization_auto_allows_readonly_agent(tmp_path):
|
|
147
147
|
graph = _graph(tmp_path)
|
|
148
|
-
graph._permission.approval_policy = "untrusted"
|
|
149
148
|
approved, denied = await graph._authorize_tool_calls(
|
|
150
149
|
[{
|
|
151
150
|
"name": "agent",
|
|
@@ -217,7 +216,7 @@ async def test_graph_authorization_respects_session_deny_for_safe_bash(tmp_path)
|
|
|
217
216
|
@pytest.mark.asyncio
|
|
218
217
|
async def test_graph_authorization_never_approves_mixed_blocked_batch(tmp_path):
|
|
219
218
|
graph = _graph(tmp_path)
|
|
220
|
-
graph._permission.
|
|
219
|
+
graph._permission.permission_mode = "safe"
|
|
221
220
|
asked: list[list[object]] = []
|
|
222
221
|
|
|
223
222
|
async def approve(tool_calls):
|
|
@@ -242,10 +241,59 @@ async def test_graph_authorization_never_approves_mixed_blocked_batch(tmp_path):
|
|
|
242
241
|
assert [item.tool_call["id"] for item in asked[1]] == ["ask"]
|
|
243
242
|
|
|
244
243
|
|
|
244
|
+
@pytest.mark.asyncio
|
|
245
|
+
async def test_full_access_workflow_gate_advisory_allows_without_approval(tmp_path):
|
|
246
|
+
graph = _graph(tmp_path)
|
|
247
|
+
graph._permission.set_permission_mode("full_access")
|
|
248
|
+
|
|
249
|
+
async def fail_if_asked(_tool_calls):
|
|
250
|
+
pytest.fail("workflow gate should not prompt for approval under full_access")
|
|
251
|
+
|
|
252
|
+
graph._ask_tool_permission = fail_if_asked
|
|
253
|
+
|
|
254
|
+
approved, denied = await graph._authorize_tool_calls(
|
|
255
|
+
[{"name": "write", "args": {"file_path": "app.py", "content": "x"}, "id": "call_1"}],
|
|
256
|
+
plan_mode=False,
|
|
257
|
+
session_id="test",
|
|
258
|
+
workflow_runs=[
|
|
259
|
+
WorkflowRunState(name="brainstorm", status=WorkflowRunStatus.ACTIVE),
|
|
260
|
+
],
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
assert [call["id"] for call in approved] == ["call_1"]
|
|
264
|
+
assert denied == []
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
@pytest.mark.asyncio
|
|
268
|
+
async def test_safe_mode_workflow_gate_still_prompts(tmp_path):
|
|
269
|
+
"""Under safe mode, workflow gate advisory does not bypass permission approval."""
|
|
270
|
+
graph = _graph(tmp_path)
|
|
271
|
+
graph._permission.set_permission_mode("safe")
|
|
272
|
+
asked: list = []
|
|
273
|
+
|
|
274
|
+
async def approve(tool_calls):
|
|
275
|
+
asked.extend(tool_calls)
|
|
276
|
+
return "y"
|
|
277
|
+
|
|
278
|
+
graph._ask_tool_permission = approve
|
|
279
|
+
|
|
280
|
+
approved, denied = await graph._authorize_tool_calls(
|
|
281
|
+
[{"name": "write", "args": {"file_path": "app.py", "content": "x"}, "id": "call_1"}],
|
|
282
|
+
plan_mode=False,
|
|
283
|
+
session_id="test",
|
|
284
|
+
workflow_runs=[
|
|
285
|
+
WorkflowRunState(name="brainstorm", status=WorkflowRunStatus.ACTIVE),
|
|
286
|
+
],
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
assert [call["id"] for call in approved] == ["call_1"]
|
|
290
|
+
assert denied == []
|
|
291
|
+
assert len(asked) > 0
|
|
292
|
+
|
|
293
|
+
|
|
245
294
|
@pytest.mark.asyncio
|
|
246
295
|
async def test_graph_authorization_asks_for_write_by_active_workflow_gate(tmp_path):
|
|
247
296
|
graph = _graph(tmp_path)
|
|
248
|
-
graph._permission.approval_policy = "on-request"
|
|
249
297
|
asked: list[list[dict]] = []
|
|
250
298
|
|
|
251
299
|
async def approve(tool_calls):
|
|
@@ -271,7 +319,13 @@ async def test_graph_authorization_asks_for_write_by_active_workflow_gate(tmp_pa
|
|
|
271
319
|
@pytest.mark.asyncio
|
|
272
320
|
async def test_graph_authorization_uses_current_workflow_gate_only(tmp_path):
|
|
273
321
|
graph = _graph(tmp_path)
|
|
274
|
-
|
|
322
|
+
asked: list[list[dict]] = []
|
|
323
|
+
|
|
324
|
+
async def approve(tool_calls):
|
|
325
|
+
asked.append(tool_calls)
|
|
326
|
+
return "y"
|
|
327
|
+
|
|
328
|
+
graph._ask_tool_permission = approve
|
|
275
329
|
|
|
276
330
|
approved, denied = await graph._authorize_tool_calls(
|
|
277
331
|
[{
|
|
@@ -288,14 +342,15 @@ async def test_graph_authorization_uses_current_workflow_gate_only(tmp_path):
|
|
|
288
342
|
],
|
|
289
343
|
)
|
|
290
344
|
|
|
345
|
+
assert [[call["id"] for call in _asked_tool_calls(batch)] for batch in asked] == [["call_1"]]
|
|
291
346
|
assert [call["id"] for call in approved] == ["call_1"]
|
|
292
347
|
assert denied == []
|
|
293
348
|
|
|
294
349
|
|
|
295
350
|
@pytest.mark.asyncio
|
|
296
|
-
async def
|
|
351
|
+
async def test_graph_authorization_plan_gate_no_longer_bypasses_doc_paths(tmp_path):
|
|
352
|
+
"""allowed_paths bypass removed: both docs and src edits go through normal permission."""
|
|
297
353
|
graph = _graph(tmp_path)
|
|
298
|
-
graph._permission.approval_policy = "on-request"
|
|
299
354
|
asked: list[list[dict]] = []
|
|
300
355
|
|
|
301
356
|
async def deny(tool_calls):
|
|
@@ -325,16 +380,22 @@ async def test_graph_authorization_allows_plan_gate_doc_paths_only(tmp_path):
|
|
|
325
380
|
],
|
|
326
381
|
)
|
|
327
382
|
|
|
328
|
-
assert
|
|
329
|
-
assert [
|
|
330
|
-
assert
|
|
331
|
-
assert denied[0][1] == "User denied: replace"
|
|
383
|
+
assert approved == []
|
|
384
|
+
assert [call["id"] for call, _reason in denied] == ["call_docs", "call_src"]
|
|
385
|
+
assert all(reason == "User denied: replace" for _tc, reason in denied)
|
|
332
386
|
|
|
333
387
|
|
|
334
388
|
@pytest.mark.asyncio
|
|
335
|
-
async def
|
|
389
|
+
async def test_graph_authorization_nested_docs_go_through_normal_permission(tmp_path):
|
|
390
|
+
"""allowed_paths bypass removed: nested docs edits go through normal permission."""
|
|
336
391
|
graph = _graph(tmp_path)
|
|
337
|
-
|
|
392
|
+
asked: list[list[dict]] = []
|
|
393
|
+
|
|
394
|
+
async def approve(tool_calls):
|
|
395
|
+
asked.append(tool_calls)
|
|
396
|
+
return "y"
|
|
397
|
+
|
|
398
|
+
graph._ask_tool_permission = approve
|
|
338
399
|
|
|
339
400
|
approved, denied = await graph._authorize_tool_calls(
|
|
340
401
|
[{
|
|
@@ -350,6 +411,7 @@ async def test_graph_authorization_allowed_paths_match_nested_docs(tmp_path):
|
|
|
350
411
|
],
|
|
351
412
|
)
|
|
352
413
|
|
|
414
|
+
assert [[call["id"] for call in _asked_tool_calls(batch)] for batch in asked] == [["call_nested_docs"]]
|
|
353
415
|
assert [call["id"] for call in approved] == ["call_nested_docs"]
|
|
354
416
|
assert denied == []
|
|
355
417
|
|
|
@@ -357,8 +419,7 @@ async def test_graph_authorization_allowed_paths_match_nested_docs(tmp_path):
|
|
|
357
419
|
@pytest.mark.asyncio
|
|
358
420
|
async def test_graph_authorization_does_not_block_tools_outside_active_workflow_node_allowlist(tmp_path):
|
|
359
421
|
graph = _graph(tmp_path)
|
|
360
|
-
|
|
361
|
-
|
|
422
|
+
|
|
362
423
|
approved, denied = await graph._authorize_tool_calls(
|
|
363
424
|
[{
|
|
364
425
|
"name": "todo",
|
|
@@ -380,7 +441,6 @@ async def test_graph_authorization_does_not_block_tools_outside_active_workflow_
|
|
|
380
441
|
@pytest.mark.asyncio
|
|
381
442
|
async def test_graph_authorization_asks_for_workflow_gate_tools_instead_of_denying(tmp_path):
|
|
382
443
|
graph = _graph(tmp_path)
|
|
383
|
-
graph._permission.approval_policy = "on-request"
|
|
384
444
|
asked: list[list[dict]] = []
|
|
385
445
|
|
|
386
446
|
async def approve(tool_calls):
|
|
@@ -411,7 +471,6 @@ async def test_graph_authorization_asks_for_workflow_gate_tools_instead_of_denyi
|
|
|
411
471
|
@pytest.mark.asyncio
|
|
412
472
|
async def test_graph_authorization_asks_for_persona_blocked_write(tmp_path):
|
|
413
473
|
graph = _graph(tmp_path)
|
|
414
|
-
graph._permission.approval_policy = "on-request"
|
|
415
474
|
asked: list[list[dict]] = []
|
|
416
475
|
|
|
417
476
|
async def approve(tool_calls):
|
|
@@ -434,7 +493,6 @@ async def test_graph_authorization_asks_for_persona_blocked_write(tmp_path):
|
|
|
434
493
|
@pytest.mark.asyncio
|
|
435
494
|
async def test_permission_result_uses_transient_output(tmp_path):
|
|
436
495
|
graph = _graph(tmp_path)
|
|
437
|
-
graph._permission.approval_policy = "untrusted"
|
|
438
496
|
test_dock = BottomInputDock()
|
|
439
497
|
set_dock(test_dock)
|
|
440
498
|
test_dock.begin_capture()
|
|
@@ -520,9 +578,7 @@ async def test_permission_prompt_uses_dock_details_when_events_are_active(tmp_pa
|
|
|
520
578
|
@pytest.mark.asyncio
|
|
521
579
|
async def test_read_only_permission_prompt_limits_choices_to_once(tmp_path):
|
|
522
580
|
graph = _graph(tmp_path)
|
|
523
|
-
graph._permission.
|
|
524
|
-
graph._permission.permission_mode = "read-only"
|
|
525
|
-
graph._permission.approval_policy = "untrusted"
|
|
581
|
+
graph._permission.set_permission_mode("read_only")
|
|
526
582
|
captured_choices = None
|
|
527
583
|
|
|
528
584
|
class FakeApp:
|
|
@@ -550,8 +606,7 @@ async def test_read_only_permission_prompt_limits_choices_to_once(tmp_path):
|
|
|
550
606
|
@pytest.mark.asyncio
|
|
551
607
|
async def test_permission_prompt_details_include_risk_and_scopes(tmp_path):
|
|
552
608
|
graph = _graph(tmp_path)
|
|
553
|
-
graph._permission.
|
|
554
|
-
graph._permission.approval_policy = "untrusted"
|
|
609
|
+
graph._permission.set_permission_mode("safe")
|
|
555
610
|
received_details = None
|
|
556
611
|
|
|
557
612
|
class FakeApp:
|
|
@@ -589,10 +644,9 @@ async def test_permission_prompt_details_include_risk_and_scopes(tmp_path):
|
|
|
589
644
|
@pytest.mark.asyncio
|
|
590
645
|
async def test_graph_authorization_attaches_approved_risk_token_to_approved_shell_call(tmp_path):
|
|
591
646
|
graph = _graph(tmp_path)
|
|
592
|
-
graph._permission.
|
|
593
|
-
graph._permission.
|
|
594
|
-
|
|
595
|
-
|
|
647
|
+
graph._permission.set_permission_mode("read_only")
|
|
648
|
+
graph._permission.set_permission_mode("read_only")
|
|
649
|
+
|
|
596
650
|
async def approve(_tool_calls):
|
|
597
651
|
return "y"
|
|
598
652
|
|
|
@@ -618,8 +672,7 @@ async def test_graph_authorization_attaches_approved_risk_token_to_approved_shel
|
|
|
618
672
|
@pytest.mark.asyncio
|
|
619
673
|
async def test_blocked_permission_prompt_only_acknowledges_and_denies_execution(tmp_path):
|
|
620
674
|
graph = _graph(tmp_path)
|
|
621
|
-
graph._permission.
|
|
622
|
-
graph._permission.approval_policy = "untrusted"
|
|
675
|
+
graph._permission.set_permission_mode("safe")
|
|
623
676
|
captured_choices = None
|
|
624
677
|
captured_details = None
|
|
625
678
|
|
|
@@ -649,9 +702,8 @@ async def test_blocked_permission_prompt_only_acknowledges_and_denies_execution(
|
|
|
649
702
|
@pytest.mark.asyncio
|
|
650
703
|
async def test_blocked_permission_prompt_cannot_be_approved_with_yes(tmp_path):
|
|
651
704
|
graph = _graph(tmp_path)
|
|
652
|
-
graph._permission.
|
|
653
|
-
|
|
654
|
-
|
|
705
|
+
graph._permission.set_permission_mode("safe")
|
|
706
|
+
|
|
655
707
|
class FakeApp:
|
|
656
708
|
async def ask_choice(self, _prompt, _choices, details=None):
|
|
657
709
|
return "y"
|
|
@@ -323,7 +323,6 @@ async def test_subagent_runner_authorizes_with_child_interaction_mode(tmp_path,
|
|
|
323
323
|
@pytest.mark.asyncio
|
|
324
324
|
async def test_graph_authorization_does_not_treat_goal_as_read_only_mode(tmp_path):
|
|
325
325
|
graph = _graph(tmp_path)
|
|
326
|
-
graph._permission.approval_policy = "on-request"
|
|
327
326
|
asked: list[list[dict]] = []
|
|
328
327
|
|
|
329
328
|
async def approve(tool_calls):
|
|
@@ -135,7 +135,7 @@ def _tree_nodes(root):
|
|
|
135
135
|
@pytest.mark.asyncio
|
|
136
136
|
async def test_graph_on_request_auto_approves_need_ask_tools(tmp_path):
|
|
137
137
|
graph = _graph(tmp_path)
|
|
138
|
-
graph._permission.
|
|
138
|
+
graph._permission.permission_mode = "full_access"
|
|
139
139
|
|
|
140
140
|
approved, denied = await graph._authorize_tool_calls(
|
|
141
141
|
[{"name": "write", "args": {"file_path": "app.py", "op": "append", "new_string": "x"}, "id": "call_1"}],
|
|
@@ -149,10 +149,30 @@ async def test_graph_on_request_auto_approves_need_ask_tools(tmp_path):
|
|
|
149
149
|
|
|
150
150
|
|
|
151
151
|
@pytest.mark.asyncio
|
|
152
|
-
async def
|
|
152
|
+
async def test_full_access_auto_approves_write_without_implement_persona(tmp_path):
|
|
153
153
|
graph = _graph(tmp_path)
|
|
154
|
-
graph._permission.
|
|
154
|
+
graph._permission.permission_mode = "full_access"
|
|
155
|
+
|
|
156
|
+
async def fail_if_asked(_tool_calls):
|
|
157
|
+
pytest.fail("full_access should not prompt for workspace edit")
|
|
158
|
+
|
|
159
|
+
graph._ask_tool_permission = fail_if_asked
|
|
160
|
+
|
|
161
|
+
approved, denied = await graph._authorize_tool_calls(
|
|
162
|
+
[{"name": "replace", "args": {"file_path": "app.py", "bounds": [{"line_no": 1, "anchor": "x"}], "new_string": "y"}, "id": "call_1"}],
|
|
163
|
+
runtime_persona="coordinate",
|
|
164
|
+
plan_mode=False,
|
|
165
|
+
session_id="test",
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
assert [tc["name"] for tc in approved] == ["replace"]
|
|
169
|
+
assert denied == []
|
|
170
|
+
|
|
155
171
|
|
|
172
|
+
@pytest.mark.asyncio
|
|
173
|
+
async def test_graph_on_failure_asks_unsafe_bash_before_prompt(tmp_path):
|
|
174
|
+
graph = _graph(tmp_path)
|
|
175
|
+
|
|
156
176
|
asked: list[dict] = []
|
|
157
177
|
|
|
158
178
|
async def ask(tool_calls):
|
|
@@ -102,6 +102,7 @@ async def test_regular_tool_call_resets_missing_turn_count(tmp_path, monkeypatch
|
|
|
102
102
|
"messages": [HumanMessage(content="hello")],
|
|
103
103
|
"step_count": 0,
|
|
104
104
|
"persona": "coordinate",
|
|
105
|
+
"turn_state": "running",
|
|
105
106
|
})
|
|
106
107
|
# The regular tool call should route to execute, not end
|
|
107
108
|
assert result1["messages"][0].tool_calls
|
|
@@ -113,6 +114,7 @@ async def test_regular_tool_call_resets_missing_turn_count(tmp_path, monkeypatch
|
|
|
113
114
|
"messages": [HumanMessage(content="hello"), *result1["messages"]],
|
|
114
115
|
"step_count": 1,
|
|
115
116
|
"persona": "coordinate",
|
|
117
|
+
"turn_state": result1.get("turn_state", "running"),
|
|
116
118
|
})
|
|
117
119
|
assert result2["messages"][0].content == "Final answer."
|
|
118
120
|
assert not result2["messages"][0].tool_calls
|
|
@@ -170,6 +172,7 @@ async def test_turn_call_never_emits_permission_or_execution_events(tmp_path, mo
|
|
|
170
172
|
"messages": [HumanMessage(content="hello")],
|
|
171
173
|
"step_count": 0,
|
|
172
174
|
"persona": "coordinate",
|
|
175
|
+
"turn_state": "running",
|
|
173
176
|
})
|
|
174
177
|
|
|
175
178
|
# Check that no tool permission or tool execution events were emitted
|
|
@@ -195,6 +198,7 @@ async def test_successful_barrier_emits_one_committed_stream(tmp_path, monkeypat
|
|
|
195
198
|
"messages": [HumanMessage(content="hello")],
|
|
196
199
|
"step_count": 0,
|
|
197
200
|
"persona": "coordinate",
|
|
201
|
+
"turn_state": "running",
|
|
198
202
|
})
|
|
199
203
|
|
|
200
204
|
msgs = result["messages"]
|
|
@@ -221,6 +225,7 @@ async def test_regular_tool_continues_after_turn_prompt(tmp_path, monkeypatch):
|
|
|
221
225
|
"messages": [HumanMessage(content="hello")],
|
|
222
226
|
"step_count": 0,
|
|
223
227
|
"persona": "coordinate",
|
|
228
|
+
"turn_state": "running",
|
|
224
229
|
})
|
|
225
230
|
|
|
226
231
|
assert result["messages"][0].tool_calls
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Integration tests for turn control inside _call_llm."""
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
|
-
from langchain_core.messages import AIMessage, AIMessageChunk, HumanMessage
|
|
4
|
+
from langchain_core.messages import AIMessage, AIMessageChunk, HumanMessage, ToolMessage
|
|
5
5
|
|
|
6
6
|
from voidx.agent.graph import VoidXGraph
|
|
7
7
|
from voidx.agent.graph.turn_control import TURN_TOOL_DEFINITION
|
|
@@ -291,11 +291,11 @@ async def test_regular_tool_call_routes_to_execute(tmp_path, monkeypatch):
|
|
|
291
291
|
assert msgs[0].tool_calls[0]["name"] == "read"
|
|
292
292
|
|
|
293
293
|
|
|
294
|
-
# ── Test 4: first plain-text
|
|
294
|
+
# ── Test 4: first plain-text answer can complete immediately ────────────────
|
|
295
295
|
|
|
296
296
|
|
|
297
297
|
@pytest.mark.asyncio
|
|
298
|
-
async def
|
|
298
|
+
async def test_first_plain_text_commits_without_start_prompt(tmp_path, monkeypatch):
|
|
299
299
|
model = ScriptedStreamingModel([
|
|
300
300
|
[_text_chunk("Provisional answer.")],
|
|
301
301
|
[_turn_call_chunk()],
|
|
@@ -311,11 +311,13 @@ async def test_first_plain_text_triggers_first_prompt_then_turn(tmp_path, monkey
|
|
|
311
311
|
msgs = result["messages"]
|
|
312
312
|
assert msgs[0].content == "Provisional answer."
|
|
313
313
|
assert not msgs[0].tool_calls
|
|
314
|
-
assert
|
|
314
|
+
assert result["turn_state"] == "committed"
|
|
315
|
+
assert model.call_index == 1
|
|
316
|
+
assert len(model.received_messages) == 1
|
|
315
317
|
|
|
316
318
|
|
|
317
319
|
@pytest.mark.asyncio
|
|
318
|
-
async def
|
|
320
|
+
async def test_initial_plain_text_keeps_full_tool_set_without_reprompt(tmp_path, monkeypatch):
|
|
319
321
|
model = ScriptedStreamingModel([
|
|
320
322
|
[_text_chunk("Provisional answer.")],
|
|
321
323
|
[_turn_call_chunk()],
|
|
@@ -329,12 +331,8 @@ async def test_missing_turn_reprompt_keeps_full_tool_set_and_appends_turn_prompt
|
|
|
329
331
|
})
|
|
330
332
|
|
|
331
333
|
assert result["messages"][0].content == "Provisional answer."
|
|
332
|
-
assert model.call_index ==
|
|
333
|
-
|
|
334
|
-
assert any(
|
|
335
|
-
isinstance(msg, HumanMessage) and "operation='start'" in str(msg.content)
|
|
336
|
-
for msg in turn_prompt_messages
|
|
337
|
-
)
|
|
334
|
+
assert model.call_index == 1
|
|
335
|
+
assert len(model.received_messages) == 1
|
|
338
336
|
tool_names = [tool["function"]["name"] for tool in model.bound_tools]
|
|
339
337
|
assert "turn" in tool_names
|
|
340
338
|
assert "read" in tool_names
|
|
@@ -352,6 +350,7 @@ async def test_regular_tool_after_turn_prompt_continues_without_committing_text(
|
|
|
352
350
|
"messages": [HumanMessage(content="read x.py")],
|
|
353
351
|
"step_count": 0,
|
|
354
352
|
"persona": "coordinate",
|
|
353
|
+
"turn_state": "running",
|
|
355
354
|
})
|
|
356
355
|
|
|
357
356
|
assert result["messages"][0].tool_calls
|
|
@@ -384,7 +383,7 @@ async def test_decision_only_turn_with_text_is_rejected_before_stop(tmp_path, mo
|
|
|
384
383
|
|
|
385
384
|
|
|
386
385
|
@pytest.mark.asyncio
|
|
387
|
-
async def
|
|
386
|
+
async def test_initial_plain_text_commits_without_hidden_ui_followups(tmp_path, monkeypatch):
|
|
388
387
|
RecordingRenderer.reset()
|
|
389
388
|
model = ScriptedStreamingModel([
|
|
390
389
|
[_text_chunk("First provisional.")],
|
|
@@ -400,10 +399,12 @@ async def test_plain_text_prompts_start_then_stop_without_ui_leak(tmp_path, monk
|
|
|
400
399
|
})
|
|
401
400
|
|
|
402
401
|
visible_text = "".join(RecordingRenderer.visible_text)
|
|
403
|
-
assert result["messages"][0].content == "
|
|
402
|
+
assert result["messages"][0].content == "First provisional."
|
|
404
403
|
assert "First provisional." in visible_text
|
|
404
|
+
assert "Second provisional." not in visible_text
|
|
405
405
|
assert RecordingRenderer.headless_values[0] is False
|
|
406
|
-
assert
|
|
406
|
+
assert RecordingRenderer.headless_values == [False]
|
|
407
|
+
assert model.call_index == 1
|
|
407
408
|
|
|
408
409
|
|
|
409
410
|
# ── Test 6: second plain-text fallback keeps latest response ────────────────
|
|
@@ -422,6 +423,7 @@ async def test_invalid_turn_continue_recovers_with_regular_tool(tmp_path, monkey
|
|
|
422
423
|
"messages": [HumanMessage(content="hello")],
|
|
423
424
|
"step_count": 0,
|
|
424
425
|
"persona": "coordinate",
|
|
426
|
+
"turn_state": "running",
|
|
425
427
|
})
|
|
426
428
|
|
|
427
429
|
assert result["messages"][0].tool_calls
|
|
@@ -512,8 +514,8 @@ async def test_turn_with_non_empty_args_is_rejected(tmp_path, monkeypatch):
|
|
|
512
514
|
}],
|
|
513
515
|
)
|
|
514
516
|
model = ScriptedStreamingModel([
|
|
515
|
-
[_text_chunk("answer")],
|
|
516
517
|
[malformed_turn],
|
|
518
|
+
[_text_chunk("answer")],
|
|
517
519
|
[_turn_call_chunk()],
|
|
518
520
|
])
|
|
519
521
|
graph = _make_graph(tmp_path, model, monkeypatch)
|
|
@@ -623,7 +625,19 @@ async def test_start_prompt_injected_once_then_stop_prompt(tmp_path, monkeypatch
|
|
|
623
625
|
graph = _make_graph(tmp_path, model, monkeypatch)
|
|
624
626
|
|
|
625
627
|
result = await graph._call_llm({
|
|
626
|
-
"messages": [
|
|
628
|
+
"messages": [
|
|
629
|
+
HumanMessage(content="hello"),
|
|
630
|
+
AIMessage(
|
|
631
|
+
content="",
|
|
632
|
+
tool_calls=[{
|
|
633
|
+
"name": "read",
|
|
634
|
+
"args": {"file_path": "x.py"},
|
|
635
|
+
"id": "tc-prior",
|
|
636
|
+
"type": "tool_call",
|
|
637
|
+
}],
|
|
638
|
+
),
|
|
639
|
+
ToolMessage(content="ok", tool_call_id="tc-prior", name="read"),
|
|
640
|
+
],
|
|
627
641
|
"step_count": 0,
|
|
628
642
|
"persona": "coordinate",
|
|
629
643
|
"turn_state": "initial",
|
{voidx-3.7.2 → voidx-3.7.4}/src/tests/test_agent/graph/test_workflow_transactions_barrier.py
RENAMED
|
@@ -293,7 +293,6 @@ async def test_multiple_barriers_apply_patches_in_order(tmp_path):
|
|
|
293
293
|
@pytest.mark.asyncio
|
|
294
294
|
async def test_workflow_transaction_reauthorizes_following_write(tmp_path):
|
|
295
295
|
graph = _graph(tmp_path)
|
|
296
|
-
graph._permission.approval_policy = "on-request"
|
|
297
296
|
invalidations = 0
|
|
298
297
|
|
|
299
298
|
class FakeApp:
|
|
@@ -33,6 +33,23 @@ async def test_fixed_loop_fires_after_interval(tmp_path) -> None:
|
|
|
33
33
|
assert host.turns[:1] == ["tick"]
|
|
34
34
|
|
|
35
35
|
|
|
36
|
+
@pytest.mark.asyncio
|
|
37
|
+
async def test_first_fire_is_immediate(tmp_path) -> None:
|
|
38
|
+
host = FakeHost()
|
|
39
|
+
idle = asyncio.Event()
|
|
40
|
+
idle.set()
|
|
41
|
+
manager = LoopManager(host, idle_event=idle, workspace=str(tmp_path))
|
|
42
|
+
|
|
43
|
+
manager.start(PromptSource.from_raw("tick"), 60)
|
|
44
|
+
for _ in range(20):
|
|
45
|
+
if host.turns:
|
|
46
|
+
break
|
|
47
|
+
await asyncio.sleep(0.005)
|
|
48
|
+
await manager.cleanup()
|
|
49
|
+
|
|
50
|
+
assert host.turns[:1] == ["tick"]
|
|
51
|
+
|
|
52
|
+
|
|
36
53
|
@pytest.mark.asyncio
|
|
37
54
|
async def test_stop_cancels_active_loop_before_fire(tmp_path) -> None:
|
|
38
55
|
host = FakeHost()
|
|
@@ -56,12 +73,13 @@ async def test_dynamic_wakeup_interrupts_default_sleep(tmp_path) -> None:
|
|
|
56
73
|
manager = LoopManager(host, idle_event=idle, workspace=str(tmp_path), default_interval_seconds=10)
|
|
57
74
|
|
|
58
75
|
manager.start(PromptSource.from_raw("tick"), None)
|
|
59
|
-
await asyncio.sleep(0)
|
|
76
|
+
await asyncio.sleep(0.02)
|
|
77
|
+
assert host.turns == ["tick"]
|
|
60
78
|
manager.schedule_wakeup(0.01)
|
|
61
79
|
await asyncio.sleep(0.04)
|
|
62
80
|
await manager.cleanup()
|
|
63
81
|
|
|
64
|
-
assert host.turns == ["tick"]
|
|
82
|
+
assert host.turns == ["tick", "tick"]
|
|
65
83
|
|
|
66
84
|
|
|
67
85
|
|
|
@@ -15,7 +15,7 @@ from voidx.config import (
|
|
|
15
15
|
McpServerConfig,
|
|
16
16
|
ModelConfig,
|
|
17
17
|
ParallelSubagentsConfig,
|
|
18
|
-
|
|
18
|
+
PermissionMode,
|
|
19
19
|
Settings,
|
|
20
20
|
UserProfile,
|
|
21
21
|
)
|
|
@@ -565,7 +565,7 @@ async def test_usage_dispatch_reads_usage_stats():
|
|
|
565
565
|
|
|
566
566
|
|
|
567
567
|
@pytest.mark.asyncio
|
|
568
|
-
async def
|
|
568
|
+
async def test_permission_mode_dispatch_updates_service_and_settings(tmp_path):
|
|
569
569
|
settings = Settings(str(tmp_path))
|
|
570
570
|
permission = PermissionService()
|
|
571
571
|
graph = SimpleNamespace(
|
|
@@ -574,13 +574,13 @@ async def test_permission_preset_dispatch_updates_service_and_settings(tmp_path)
|
|
|
574
574
|
_app=None,
|
|
575
575
|
)
|
|
576
576
|
|
|
577
|
-
assert await SlashHandler(graph).dispatch("/permission
|
|
577
|
+
assert await SlashHandler(graph).dispatch("/permission full_access") is True
|
|
578
578
|
|
|
579
579
|
reloaded = await Settings.create(str(tmp_path))
|
|
580
580
|
cfg = await reloaded.build_config()
|
|
581
|
-
assert permission.
|
|
582
|
-
assert cfg.
|
|
583
|
-
assert reloaded.
|
|
581
|
+
assert permission.permission_mode == "full_access"
|
|
582
|
+
assert cfg.permission_mode == PermissionMode.FULL_ACCESS
|
|
583
|
+
assert reloaded.get_permission_mode() == PermissionMode.FULL_ACCESS
|
|
584
584
|
assert await SlashHandler(graph).dispatch("/permission-mode full-access") is False
|
|
585
585
|
assert await SlashHandler(graph).dispatch("/approval never") is False
|
|
586
586
|
|
|
@@ -15,7 +15,7 @@ from voidx.config import (
|
|
|
15
15
|
McpServerConfig,
|
|
16
16
|
ModelConfig,
|
|
17
17
|
ParallelSubagentsConfig,
|
|
18
|
-
|
|
18
|
+
PermissionMode,
|
|
19
19
|
Settings,
|
|
20
20
|
UserProfile,
|
|
21
21
|
)
|
|
@@ -329,7 +329,7 @@ def test_model_ctx_command_is_in_palette():
|
|
|
329
329
|
assert ("/model ctx", "Set context window size") in COMMANDS
|
|
330
330
|
|
|
331
331
|
@pytest.mark.asyncio
|
|
332
|
-
async def
|
|
332
|
+
async def test_permission_mode_without_args_uses_prompt_app_choice(tmp_path):
|
|
333
333
|
settings = Settings(str(tmp_path))
|
|
334
334
|
permission = PermissionService()
|
|
335
335
|
app = FakeChoiceApp(result="project_trusted")
|
|
@@ -339,11 +339,11 @@ async def test_permission_preset_without_args_uses_prompt_app_choice(tmp_path):
|
|
|
339
339
|
_app=app,
|
|
340
340
|
)
|
|
341
341
|
|
|
342
|
-
assert await SlashHandler(graph).dispatch("/permission
|
|
342
|
+
assert await SlashHandler(graph).dispatch("/permission") is True
|
|
343
343
|
|
|
344
|
-
assert app.prompt == "Permission
|
|
345
|
-
assert permission.
|
|
346
|
-
assert settings.
|
|
344
|
+
assert app.prompt == "Permission mode"
|
|
345
|
+
assert permission.permission_mode == "project_trusted"
|
|
346
|
+
assert settings.get_permission_mode() == PermissionMode.PROJECT_TRUSTED
|
|
347
347
|
|
|
348
348
|
|
|
349
349
|
@pytest.mark.asyncio
|