voidx 3.7.2__tar.gz → 3.7.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {voidx-3.7.2/src/voidx.egg-info → voidx-3.7.3}/PKG-INFO +1 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_call_llm_compaction.py +29 -0
- voidx-3.7.3/src/tests/test_agent/graph/test_call_llm_structure.py +12 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_graph_authorization.py +12 -27
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_subagent_runner.py +0 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_tool_execution_auth.py +23 -3
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_turn_control_e2e.py +5 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_turn_control_integration.py +30 -16
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_workflow_transactions_barrier.py +0 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/slash/test_slash_model.py +6 -6
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/slash/test_slash_model_advanced.py +6 -6
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_permission.py +16 -16
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_permission_phase2.py +5 -5
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_permission_phase4.py +15 -32
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_permission_phase5.py +7 -8
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_permission_phase6.py +7 -20
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_tool_result_storage.py +62 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_config/test_config_advanced.py +15 -16
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_llm_usage.py +25 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_permission/test_risk.py +54 -6
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/bash/test_router_git.py +24 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/bash/test_tool.py +98 -5
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_git_tool_destructive.py +2 -3
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_git_tool_phase5.py +2 -2
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_git_tool_raw_permissions.py +1 -2
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_git_tool_schema_errors.py +0 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_git_tool_structured.py +4 -4
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_powershell_tool.py +52 -2
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_powershell_tool_phase6.py +3 -3
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_shell_tool_phase6.py +3 -3
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_gateway_v2_dispatch.py +3 -5
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/__init__.py +1 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/goal_resolver.py +13 -4
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/contracts.py +3 -2
- voidx-3.7.3/src/voidx/agent/graph/core/context.py +94 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/core/helpers.py +4 -3
- voidx-3.7.3/src/voidx/agent/graph/core/llm.py +548 -0
- voidx-3.7.3/src/voidx/agent/graph/core/loop.py +108 -0
- voidx-3.7.3/src/voidx/agent/graph/core/turn.py +353 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/permissions.py +17 -31
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/run_loop.py +2 -2
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/session_runtime.py +1 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/subagent.py +20 -6
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/tool_executor/executor.py +5 -2
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/tool_executor/helpers.py +2 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/tool_executor/workflow.py +2 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/turn_control.py +7 -2
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/turn_runner.py +5 -4
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/wiring.py +0 -4
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/loop/slash.py +2 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/prompts.py +6 -5
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/runtime_context.py +22 -7
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/slash/handler.py +20 -42
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/slash/host.py +1 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/slash/init.py +2 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/todo_state.py +5 -4
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/tool_result_storage.py +34 -9
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/__init__.py +0 -8
- voidx-3.7.3/src/voidx/config/enums.py +41 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/models.py +2 -6
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/settings.py +0 -8
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/settings_permissions.py +7 -57
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/voidx-guide/permission.md +5 -5
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/voidx-guide/reference.md +1 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/llm/usage.py +20 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/paths.py +2 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/permission/__init__.py +4 -4
- voidx-3.7.3/src/voidx/permission/constants.py +177 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/permission/context.py +20 -11
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/permission/engine.py +6 -6
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/permission/git_policy.py +13 -72
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/permission/grants.py +1 -0
- voidx-3.7.3/src/voidx/permission/presets.py +73 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/permission/rules.py +10 -13
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/permission/sandbox.py +11 -39
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/permission/schema.py +9 -3
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/permission/service.py +36 -73
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/permission/shell_policy.py +13 -14
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/runtime/intent.py +8 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/runtime/task_state.py +8 -2
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/base.py +18 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/bash/tool.py +5 -1
- voidx-3.7.3/src/voidx/tools/git/__init__.py +7 -0
- voidx-3.7.3/src/voidx/tools/git/access.py +251 -0
- voidx-3.7.3/src/voidx/tools/git/constants.py +54 -0
- voidx-3.7.3/src/voidx/tools/git/handlers.py +349 -0
- voidx-3.7.3/src/voidx/tools/git/models.py +38 -0
- voidx-3.7.3/src/voidx/tools/git/parsers.py +247 -0
- voidx-3.7.3/src/voidx/tools/git/process.py +81 -0
- voidx-3.7.3/src/voidx/tools/git/results.py +90 -0
- voidx-3.7.3/src/voidx/tools/git/routing.py +145 -0
- voidx-3.7.3/src/voidx/tools/git/tool.py +109 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/powershell/tool.py +5 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/shell/common.py +19 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/shell/hint/git.py +15 -9
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/command_catalog.py +3 -4
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/commands.py +5 -9
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/session/method/settings.py +4 -8
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/types.py +0 -1
- {voidx-3.7.2 → voidx-3.7.3/src/voidx.egg-info}/PKG-INFO +1 -1
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx.egg-info/SOURCES.txt +15 -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.3}/LICENSE +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/README.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/pyproject.toml +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/setup.cfg +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/conftest.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/conftest.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/conftest.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/run_loop_helpers.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/stream_llm_helpers.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_call_llm_compaction_advanced.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_call_llm_tools.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_compaction_flow.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_compaction_flow_run_once.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_convergence.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_execute_tools_guard.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_execute_tools_todo.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_graph_setup_prompts.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_guards_tool_op.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_parallel_subagents.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_parallel_subagents_dedup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_prepare_workflow.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_run_loop_startup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_run_loop_title_lsp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_run_loop_title_misc.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_run_loop_workflow.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_run_loop_workflow_advanced.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_runtime_guards.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_session_context_frames.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_session_crud.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_session_messages.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_session_persistence.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_session_run_once.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_session_runtime_state.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_session_transcript.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_stream_llm_sanitization.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_subagent_llm_retry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_subagent_persistence.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_subagent_step_budget.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_subagent_step_budget_convergence.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_subagent_step_budget_final.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_todo_events.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_tool_result_preview.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_turn_runner_guidance_discard.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_turn_runner_idle_event.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_turn_stop_without_pending.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_workflow_done.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_workflow_review.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/graph/test_workflow_transactions.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/loop/test_manager.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/loop/test_prompt_source.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/slash/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/slash/test_slash_init.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/slash/test_slash_loop.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/slash/test_slash_mcp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/slash/test_slash_session.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/slash/test_slash_skills.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/slash/test_slash_tavily.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/slash/test_slash_upgrade.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_attachments.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_file_rwlock.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_goal_resolver.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_goal_resolver_advanced.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_guard_guidance.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_guide_command.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_message_trimming_parsers.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_message_trimming_rules.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_module_boundaries.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_permission_append.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_permission_phase3.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_prompts.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_runtime_context_builder.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_runtime_context_prompts.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_runtime_context_skill_stripping.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_task_state.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_task_state_context_sync.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_task_state_rendering.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_todo_replay_sanitization.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_tool_exchange_sanitizer.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_tool_filters_gemini.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_tool_messages.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_turn_control.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_turn_control_prompt.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_turn_metrics.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_agent/test_turn_start.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_archive_script.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_config/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_config/test_config.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_config/test_retry_config.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_install_sh.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/conftest.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_compaction_retry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_fallback_summary.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_gemini_provider.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_goal_resolver_retry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_instruction_cache.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_llm_catalog.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_llm_catalog_fetchers.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_llm_provider.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_llm_provider_advanced.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_overflow_threshold.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_prune_args.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_request_log.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_streaming_sanitize.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_llm/test_token_counting.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_logging/test_external.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_logging/test_internal_error.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_logging/test_tool_log.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_lsp/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_lsp/test_lsp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_lsp/test_lsp_advanced.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_mcp/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_mcp/test_mcp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_memory/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_memory/test_main.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_memory/test_main_startup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_memory/test_schema_migration.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_npm_package.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_permission/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_release_npm_wheel_sync.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_runtime/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_runtime/test_goal_resolution_refactor.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_runtime/test_processes.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_runtime/test_runtime_ui.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_selfupdate/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_selfupdate/test_selfupdate.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_skills/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_skills/conftest.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_skills/test_create_skill.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_skills/test_skill_parsing.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_skills/test_skill_references.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_skills/test_workflow_advance.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_test_runner.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/bash/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/bash/test_router_safety.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/bash/test_router_sed_grep.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_coverage_fingerprint.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_edit_anchors.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_edit_bounds_input.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_edit_coverage.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_edit_dedup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_edit_drift_fallback.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_edit_drift_fallback_e2e.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_edit_errors.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_edit_line_insert.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_edit_llm_messages.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_edit_replace.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_edit_trailing_newline.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_read.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_read_write.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_render_numbered_diff.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/file/test_write_file.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_clarify_tool.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_diffing.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_file_tools_redesign.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_infer_state_patch.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_interactive_tools.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_interactive_tools_write.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_load_doc_template.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_loop_integration.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_loop_registry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_make_interact_callback.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_plan_checkpoint.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_replace_failure_logging.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_resolve_safe.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_retry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_schedule_wakeup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_search.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_skills_tool.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_state_update_from_executed_tools.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_task_tracker.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_todo_tool.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_tool_error_handling.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_tool_registry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_tool_schemas.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_tool_state_patch.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_user_interaction_models.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_web_mcp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_webfetch.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_tools/test_workflow_tool.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/conftest.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/helpers.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_adapter.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_diff_review.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_gateway_headless_frontend.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_gateway_v2_crud_diff.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_gateway_v2_routing.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_gateway_v2_server.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_gateway_v2_session.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_guidance_fallback.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_run_manager.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_terminal.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_ui_events_dock_bus.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_ui_events_dock_prompts.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_ui_events_dock_status.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_ui_events_streaming.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_ui_events_subagent.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_ui_events_todo.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/gateway/test_ui_gateway.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/output/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/output/test_console_app.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/output/test_dock_formatting.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/output/test_fmt_args.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/output/test_output_browse.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/output/test_scrollback_flush.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/output/test_tool_display.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/output/test_tree_smoke.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/output/test_ui_diff.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/output/test_ui_session_changes.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/protocol/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/protocol/test_dto.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/protocol/test_v2_envelope.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/protocol/test_v2_methods.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/protocol/test_v2_snapshot.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/protocol/test_v2_threads.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/test_display_policy.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/test_file_picker.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/tools/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/tools/test_clipboard_image.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/tools/test_clipboard_image_windows.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/tools/test_clipboard_text.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/tools/test_clipboard_text_windows.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_ui/tools/test_code_ide.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_voidx_entrypoint.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_wheel_build.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_wheel_verify_cwd.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_workflow/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_workflow/test_auto_advance.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/tests/test_workflow/test_workflow_reconcile.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/agents.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/attachments.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/compaction.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/compaction_coordinator.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/convergence.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/core/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/core/voidx_graph.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/runtime.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/runtime_guards.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/session_mixin.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/streaming.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/thread_context.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/title_mixin.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/todo_events.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/tool_execution.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/tool_executor/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/tool_executor/guards.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/tool_executor/types.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/tool_executor/ui.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/topology.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/transcript_mixin.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/turn_metrics.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/turn_mixin.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/graph/workflow_utils.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/loop/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/loop/manager.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/loop/prompt_source.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/message_rows.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/message_trimming.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/slash/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/slash/code_ide.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/slash/guide.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/slash/lsp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/slash/mcp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/slash/model.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/slash/profile.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/slash/runtime.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/slash/session.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/slash/skills.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/slash/upgrade.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/state.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/task_state.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/tool_call_ids.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/tool_exchange_sanitizer.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/tool_filters.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/agent/tool_messages.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/defaults.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/settings_agent.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/settings_api_keys.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/settings_code_ide.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/settings_custom.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/settings_mcp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/settings_retry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/settings_skills.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/settings_update.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/settings_utils.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/config/settings_web.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/README.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/templates/api-doc.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/templates/capability-spec.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/templates/implementation-spec.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/templates/prd.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/templates/readme.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/templates/rfc.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/templates/tasks.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/templates/tech-design.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/voidx-guide/README.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/voidx-guide/context.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/voidx-guide/debug.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/voidx-guide/extension.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/voidx-guide/mode.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/voidx-guide/model.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/voidx-guide/preferences.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/voidx-guide/quickstart.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/voidx-guide/session.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/voidx-guide/upgrade.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/voidx-guide/web.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/data/documents/voidx-guide/workflow.md +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/diffing.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/llm/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/llm/catalog.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/llm/compaction.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/llm/context.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/llm/instruction.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/llm/message_markers.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/llm/message_status.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/llm/provider.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/llm/service.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/logging/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/logging/external.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/logging/internal_error.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/logging/request_log.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/logging/tool_log.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/lsp/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/lsp/client.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/lsp/config.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/lsp/detector.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/lsp/detector_data.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/lsp/errors.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/lsp/manager.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/lsp/schema.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/lsp/service.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/main.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/mcp/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/mcp/client/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/mcp/client/base.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/mcp/client/errors.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/mcp/client/http_transport.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/mcp/client/sse_transport.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/mcp/client/stdio_transport.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/mcp/manager.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/mcp/schema.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/mcp/tool.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/mcp_servers/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/mcp_servers/web.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/memory/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/memory/cleanup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/memory/context_frames.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/memory/jsonl_store.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/memory/model_profiles.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/memory/runtime_state.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/memory/service.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/memory/session.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/memory/store.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/memory/subagents.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/memory/transcript.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/permission/evaluate.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/permission/process_sandbox.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/permission/risk.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/permission/wildcard.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/runtime/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/runtime/_win32_jobs.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/runtime/attachments.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/runtime/processes.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/runtime/reference_tokens.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/runtime/todo.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/runtime/ui.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/runtime/ui_port.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/selfupdate.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/skills/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/skills/context.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/skills/references.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/skills/registry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/skills/schema.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/skills/service.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/agent.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/bash/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/bash/core.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/bash/hint/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/bash/hint/file.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/bash/hint/git.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/bash/hint/search.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/bash/router.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/bash/safety.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/checkpoint.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/clarify.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/compact.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/document.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/file/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/file/manage.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/file/read.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/file/replace.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/file/replace_resolve.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/file/safe_path.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/file/state.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/file/types.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/file/write.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/lsp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/powershell/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/powershell/core.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/powershell/hint/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/powershell/hint/file.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/powershell/hint/search.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/powershell/router.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/powershell/safety.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/powershell/sandbox.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/registry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/retry.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/schedule_wakeup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/search.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/service.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/shell/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/shell/hint/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/skills.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/task_status.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/task_tracker.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/todo.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/web/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/web/content.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/web/fetch.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/web/mcp.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/web/search.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/tools/workflow.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/frontend.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/adapter.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/bootstrap.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/diff_review.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/frontend.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/run_manager.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/server.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/session/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/session/consumer.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/session/core.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/session/method/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/session/method/diff.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/session/method/integrations.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/session/method/sessions.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/session/method/terminal.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/gateway/terminal.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/agent_display.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/ansi_marker.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/browse.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/capture.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/console/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/console/app.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/console/formatting.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/console/streaming.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/diff.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/display_policy.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/dock/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/dock/agent_placeholder.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/dock/app.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/dock/formatting.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/dock/nodes.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/dock/nodes_checkpoint.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/dock/nodes_clarify.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/dock/nodes_permission.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/dock/nodes_startup.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/dock/nodes_status.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/dock/state.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/dock/status.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/dock/stream.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/dock/todo.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/events/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/events/bus.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/events/consumers.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/events/schema.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/manage_display.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/tool_display.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/output/tree.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/protocol/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/protocol/commands.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/protocol/requests.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/protocol/schema.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/protocol/transcript.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/protocol/v2/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/protocol/v2/envelope.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/protocol/v2/methods.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/protocol/v2/snapshot.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/protocol/v2/threads.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/session.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/tools/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/tools/attachment_tokens.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/tools/clipboard_image.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/tools/clipboard_text.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/tools/code_ide.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/tools/file_picker.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/tools/skill_picker.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/ui/transcript.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/workflow/__init__.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/workflow/auto_advance.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/workflow/context.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/workflow/dag.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/workflow/nodes.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/workflow/policy.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/workflow/reconcile.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/workflow/render.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/workflow/route.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/workflow/runtime.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/workflow/schema.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/workflow/service.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx/workflow/types.py +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx.egg-info/dependency_links.txt +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx.egg-info/entry_points.txt +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/src/voidx.egg-info/requires.txt +0 -0
- {voidx-3.7.2 → voidx-3.7.3}/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):
|
|
@@ -245,7 +244,6 @@ async def test_graph_authorization_never_approves_mixed_blocked_batch(tmp_path):
|
|
|
245
244
|
@pytest.mark.asyncio
|
|
246
245
|
async def test_graph_authorization_asks_for_write_by_active_workflow_gate(tmp_path):
|
|
247
246
|
graph = _graph(tmp_path)
|
|
248
|
-
graph._permission.approval_policy = "on-request"
|
|
249
247
|
asked: list[list[dict]] = []
|
|
250
248
|
|
|
251
249
|
async def approve(tool_calls):
|
|
@@ -271,8 +269,7 @@ async def test_graph_authorization_asks_for_write_by_active_workflow_gate(tmp_pa
|
|
|
271
269
|
@pytest.mark.asyncio
|
|
272
270
|
async def test_graph_authorization_uses_current_workflow_gate_only(tmp_path):
|
|
273
271
|
graph = _graph(tmp_path)
|
|
274
|
-
|
|
275
|
-
|
|
272
|
+
|
|
276
273
|
approved, denied = await graph._authorize_tool_calls(
|
|
277
274
|
[{
|
|
278
275
|
"name": "edit",
|
|
@@ -295,7 +292,6 @@ async def test_graph_authorization_uses_current_workflow_gate_only(tmp_path):
|
|
|
295
292
|
@pytest.mark.asyncio
|
|
296
293
|
async def test_graph_authorization_allows_plan_gate_doc_paths_only(tmp_path):
|
|
297
294
|
graph = _graph(tmp_path)
|
|
298
|
-
graph._permission.approval_policy = "on-request"
|
|
299
295
|
asked: list[list[dict]] = []
|
|
300
296
|
|
|
301
297
|
async def deny(tool_calls):
|
|
@@ -334,8 +330,7 @@ async def test_graph_authorization_allows_plan_gate_doc_paths_only(tmp_path):
|
|
|
334
330
|
@pytest.mark.asyncio
|
|
335
331
|
async def test_graph_authorization_allowed_paths_match_nested_docs(tmp_path):
|
|
336
332
|
graph = _graph(tmp_path)
|
|
337
|
-
|
|
338
|
-
|
|
333
|
+
|
|
339
334
|
approved, denied = await graph._authorize_tool_calls(
|
|
340
335
|
[{
|
|
341
336
|
"name": "edit",
|
|
@@ -357,8 +352,7 @@ async def test_graph_authorization_allowed_paths_match_nested_docs(tmp_path):
|
|
|
357
352
|
@pytest.mark.asyncio
|
|
358
353
|
async def test_graph_authorization_does_not_block_tools_outside_active_workflow_node_allowlist(tmp_path):
|
|
359
354
|
graph = _graph(tmp_path)
|
|
360
|
-
|
|
361
|
-
|
|
355
|
+
|
|
362
356
|
approved, denied = await graph._authorize_tool_calls(
|
|
363
357
|
[{
|
|
364
358
|
"name": "todo",
|
|
@@ -380,7 +374,6 @@ async def test_graph_authorization_does_not_block_tools_outside_active_workflow_
|
|
|
380
374
|
@pytest.mark.asyncio
|
|
381
375
|
async def test_graph_authorization_asks_for_workflow_gate_tools_instead_of_denying(tmp_path):
|
|
382
376
|
graph = _graph(tmp_path)
|
|
383
|
-
graph._permission.approval_policy = "on-request"
|
|
384
377
|
asked: list[list[dict]] = []
|
|
385
378
|
|
|
386
379
|
async def approve(tool_calls):
|
|
@@ -411,7 +404,6 @@ async def test_graph_authorization_asks_for_workflow_gate_tools_instead_of_denyi
|
|
|
411
404
|
@pytest.mark.asyncio
|
|
412
405
|
async def test_graph_authorization_asks_for_persona_blocked_write(tmp_path):
|
|
413
406
|
graph = _graph(tmp_path)
|
|
414
|
-
graph._permission.approval_policy = "on-request"
|
|
415
407
|
asked: list[list[dict]] = []
|
|
416
408
|
|
|
417
409
|
async def approve(tool_calls):
|
|
@@ -434,7 +426,6 @@ async def test_graph_authorization_asks_for_persona_blocked_write(tmp_path):
|
|
|
434
426
|
@pytest.mark.asyncio
|
|
435
427
|
async def test_permission_result_uses_transient_output(tmp_path):
|
|
436
428
|
graph = _graph(tmp_path)
|
|
437
|
-
graph._permission.approval_policy = "untrusted"
|
|
438
429
|
test_dock = BottomInputDock()
|
|
439
430
|
set_dock(test_dock)
|
|
440
431
|
test_dock.begin_capture()
|
|
@@ -520,9 +511,7 @@ async def test_permission_prompt_uses_dock_details_when_events_are_active(tmp_pa
|
|
|
520
511
|
@pytest.mark.asyncio
|
|
521
512
|
async def test_read_only_permission_prompt_limits_choices_to_once(tmp_path):
|
|
522
513
|
graph = _graph(tmp_path)
|
|
523
|
-
graph._permission.
|
|
524
|
-
graph._permission.permission_mode = "read-only"
|
|
525
|
-
graph._permission.approval_policy = "untrusted"
|
|
514
|
+
graph._permission.set_permission_mode("read_only")
|
|
526
515
|
captured_choices = None
|
|
527
516
|
|
|
528
517
|
class FakeApp:
|
|
@@ -550,8 +539,7 @@ async def test_read_only_permission_prompt_limits_choices_to_once(tmp_path):
|
|
|
550
539
|
@pytest.mark.asyncio
|
|
551
540
|
async def test_permission_prompt_details_include_risk_and_scopes(tmp_path):
|
|
552
541
|
graph = _graph(tmp_path)
|
|
553
|
-
graph._permission.
|
|
554
|
-
graph._permission.approval_policy = "untrusted"
|
|
542
|
+
graph._permission.set_permission_mode("safe")
|
|
555
543
|
received_details = None
|
|
556
544
|
|
|
557
545
|
class FakeApp:
|
|
@@ -589,10 +577,9 @@ async def test_permission_prompt_details_include_risk_and_scopes(tmp_path):
|
|
|
589
577
|
@pytest.mark.asyncio
|
|
590
578
|
async def test_graph_authorization_attaches_approved_risk_token_to_approved_shell_call(tmp_path):
|
|
591
579
|
graph = _graph(tmp_path)
|
|
592
|
-
graph._permission.
|
|
593
|
-
graph._permission.
|
|
594
|
-
|
|
595
|
-
|
|
580
|
+
graph._permission.set_permission_mode("read_only")
|
|
581
|
+
graph._permission.set_permission_mode("read_only")
|
|
582
|
+
|
|
596
583
|
async def approve(_tool_calls):
|
|
597
584
|
return "y"
|
|
598
585
|
|
|
@@ -618,8 +605,7 @@ async def test_graph_authorization_attaches_approved_risk_token_to_approved_shel
|
|
|
618
605
|
@pytest.mark.asyncio
|
|
619
606
|
async def test_blocked_permission_prompt_only_acknowledges_and_denies_execution(tmp_path):
|
|
620
607
|
graph = _graph(tmp_path)
|
|
621
|
-
graph._permission.
|
|
622
|
-
graph._permission.approval_policy = "untrusted"
|
|
608
|
+
graph._permission.set_permission_mode("safe")
|
|
623
609
|
captured_choices = None
|
|
624
610
|
captured_details = None
|
|
625
611
|
|
|
@@ -649,9 +635,8 @@ async def test_blocked_permission_prompt_only_acknowledges_and_denies_execution(
|
|
|
649
635
|
@pytest.mark.asyncio
|
|
650
636
|
async def test_blocked_permission_prompt_cannot_be_approved_with_yes(tmp_path):
|
|
651
637
|
graph = _graph(tmp_path)
|
|
652
|
-
graph._permission.
|
|
653
|
-
|
|
654
|
-
|
|
638
|
+
graph._permission.set_permission_mode("safe")
|
|
639
|
+
|
|
655
640
|
class FakeApp:
|
|
656
641
|
async def ask_choice(self, _prompt, _choices, details=None):
|
|
657
642
|
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.3}/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:
|
|
@@ -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
|
|
@@ -129,7 +129,7 @@ class TestMerge:
|
|
|
129
129
|
|
|
130
130
|
|
|
131
131
|
def test_permission_service_status_label_ignores_session_overrides():
|
|
132
|
-
service = PermissionService(
|
|
132
|
+
service = PermissionService()
|
|
133
133
|
|
|
134
134
|
assert service.status_label() == "Safe"
|
|
135
135
|
|
|
@@ -249,17 +249,19 @@ def test_permission_service_allows_read_only_lsp_tools_but_asks_for_format():
|
|
|
249
249
|
def test_permission_service_preset_updates_runtime_decisions():
|
|
250
250
|
service = PermissionService()
|
|
251
251
|
|
|
252
|
-
service.
|
|
253
|
-
assert service.
|
|
252
|
+
service.set_permission_mode("project_trusted")
|
|
253
|
+
assert service.permission_mode == "project_trusted"
|
|
254
254
|
assert service.status_label() == "Project trusted"
|
|
255
255
|
assert service.decide("manage", "src/app.py") == "allow"
|
|
256
256
|
assert service.decide("write", "src/app.py") == "allow"
|
|
257
257
|
assert service.decide("replace", "src/app.py") == "allow"
|
|
258
|
-
assert service.decide("bash", "pip install requests") == "
|
|
258
|
+
assert service.decide("bash", "pip install requests") == "allow"
|
|
259
|
+
assert service.decide("bash", "python -m pytest") == "allow"
|
|
260
|
+
assert service.decide("bash", "curl https://example.com") == "ask"
|
|
259
261
|
|
|
260
|
-
service.
|
|
261
|
-
assert service.
|
|
262
|
-
assert service.decide("bash", "python -m pytest") == "
|
|
262
|
+
service.set_permission_mode("full_access")
|
|
263
|
+
assert service.permission_mode == "full_access"
|
|
264
|
+
assert service.decide("bash", "python -m pytest") == "allow"
|
|
263
265
|
assert service.status_label() == "Full access"
|
|
264
266
|
|
|
265
267
|
|
|
@@ -346,18 +348,16 @@ def test_permission_engine_plan_mode_uses_sandbox_source(tmp_path):
|
|
|
346
348
|
def test_permission_engine_policy_presets(tmp_path):
|
|
347
349
|
project_trusted = PermissionContext(
|
|
348
350
|
workspace=str(tmp_path),
|
|
349
|
-
|
|
351
|
+
permission_mode="project_trusted",
|
|
350
352
|
)
|
|
351
353
|
full_access = PermissionContext(
|
|
352
354
|
workspace=str(tmp_path),
|
|
353
|
-
sandbox_mode="danger-full-access",
|
|
354
|
-
approval_policy="never",
|
|
355
355
|
)
|
|
356
356
|
|
|
357
357
|
safe_edit = authorize_tool_call({"name": "manage", "args": {"op": "create", "paths": "x.py"}}, PermissionContext(workspace=str(tmp_path)))
|
|
358
358
|
full_access_edit = authorize_tool_call(
|
|
359
359
|
{"name": "manage", "args": {"op": "create", "paths": "x.py"}},
|
|
360
|
-
PermissionContext(workspace=str(tmp_path),
|
|
360
|
+
PermissionContext(workspace=str(tmp_path), permission_mode="full_access"),
|
|
361
361
|
)
|
|
362
362
|
|
|
363
363
|
assert safe_edit.action == "ask"
|
|
@@ -365,7 +365,7 @@ def test_permission_engine_policy_presets(tmp_path):
|
|
|
365
365
|
|
|
366
366
|
|
|
367
367
|
def test_permission_engine_read_only_sandbox_allows_read_bash_but_asks_for_writes(tmp_path):
|
|
368
|
-
context = PermissionContext(workspace=str(tmp_path),
|
|
368
|
+
context = PermissionContext(workspace=str(tmp_path), permission_mode="read_only")
|
|
369
369
|
|
|
370
370
|
assert authorize_tool_call({"name": "bash", "args": {"command": "ls"}}, context).action == "allow"
|
|
371
371
|
assert authorize_tool_call({"name": "git", "args": {"args": "status"}}, context).action == "allow"
|
|
@@ -379,7 +379,7 @@ def test_permission_engine_read_only_sandbox_allows_read_bash_but_asks_for_write
|
|
|
379
379
|
|
|
380
380
|
|
|
381
381
|
def test_permission_engine_asks_for_manage_in_read_only_sandbox(tmp_path):
|
|
382
|
-
context = PermissionContext(workspace=str(tmp_path),
|
|
382
|
+
context = PermissionContext(workspace=str(tmp_path), permission_mode="read_only")
|
|
383
383
|
|
|
384
384
|
assert authorize_tool_call({"name": "manage", "args": {"op": "create", "paths": "x.py"}}, context).action == "ask"
|
|
385
385
|
assert authorize_tool_call({"name": "manage", "args": {"op": "delete", "paths": ["x.py"]}}, context).action == "ask"
|
|
@@ -394,7 +394,7 @@ def test_permission_engine_workspace_write_checks_manage_paths(tmp_path):
|
|
|
394
394
|
outside = tmp_path / "outside"
|
|
395
395
|
workspace.mkdir()
|
|
396
396
|
outside.mkdir()
|
|
397
|
-
context = PermissionContext(workspace=str(workspace),
|
|
397
|
+
context = PermissionContext(workspace=str(workspace), permission_mode="safe")
|
|
398
398
|
|
|
399
399
|
inside = authorize_tool_call({"name": "manage", "args": {"op": "create", "paths": "safe.py"}}, context)
|
|
400
400
|
create_outside = authorize_tool_call({"name": "manage", "args": {"op": "create", "paths": str(outside / "x.py")}}, context)
|
|
@@ -534,7 +534,7 @@ def test_engine_defers_approvable_read(tmp_path):
|
|
|
534
534
|
outside.mkdir()
|
|
535
535
|
target = outside / "file.txt"
|
|
536
536
|
target.write_text("hello\n", encoding="utf-8")
|
|
537
|
-
context = PermissionContext(workspace=str(workspace),
|
|
537
|
+
context = PermissionContext(workspace=str(workspace), permission_mode="safe")
|
|
538
538
|
|
|
539
539
|
decision = authorize_tool_call({"name": "read", "args": {"file_path": str(target)}}, context)
|
|
540
540
|
|
|
@@ -547,7 +547,7 @@ def test_engine_denies_non_approvable_tool(tmp_path):
|
|
|
547
547
|
outside = tmp_path / "outside"
|
|
548
548
|
workspace.mkdir()
|
|
549
549
|
outside.mkdir()
|
|
550
|
-
context = PermissionContext(workspace=str(workspace),
|
|
550
|
+
context = PermissionContext(workspace=str(workspace), permission_mode="safe")
|
|
551
551
|
|
|
552
552
|
decision = authorize_tool_call(
|
|
553
553
|
{"name": "manage", "args": {"op": "create", "paths": str(outside / "x.txt")}},
|
|
@@ -206,7 +206,7 @@ async def test_revision_domains_are_independent(tmp_path):
|
|
|
206
206
|
start_state = service.state_revision
|
|
207
207
|
start_permissions = service.permissions_revision
|
|
208
208
|
|
|
209
|
-
service.
|
|
209
|
+
service.set_permission_mode("project_trusted")
|
|
210
210
|
assert service.state_revision == start_state + 1
|
|
211
211
|
assert service.permissions_revision == start_permissions
|
|
212
212
|
|
|
@@ -291,13 +291,13 @@ async def test_tool_context_get_access_grants_fails_closed_when_not_ready(tmp_pa
|
|
|
291
291
|
|
|
292
292
|
@pytest.mark.asyncio
|
|
293
293
|
async def test_add_grant_rejects_stale_approval_precondition(tmp_path):
|
|
294
|
-
service = PermissionService(
|
|
294
|
+
service = PermissionService()
|
|
295
295
|
precondition = ApprovalPrecondition(
|
|
296
296
|
permission_mode=service.permission_mode,
|
|
297
297
|
revocation_epoch=service.revocation_epoch,
|
|
298
298
|
)
|
|
299
299
|
|
|
300
|
-
service.
|
|
300
|
+
service.set_permission_mode("read_only")
|
|
301
301
|
result = await service.add_grant(
|
|
302
302
|
AccessGrant(path=str(tmp_path / "stale.txt"), access="read", object_type="file", persistence="session"),
|
|
303
303
|
precondition=precondition,
|
|
@@ -331,7 +331,7 @@ def test_permission_transaction_postcommit_recovery(tmp_path, monkeypatch):
|
|
|
331
331
|
|
|
332
332
|
|
|
333
333
|
@pytest.mark.asyncio
|
|
334
|
-
async def
|
|
334
|
+
async def test_permission_mode_change_preserves_path_grant_sources(tmp_path):
|
|
335
335
|
service = PermissionService(
|
|
336
336
|
sandbox_readable_files=[str(tmp_path / "sandbox.txt")],
|
|
337
337
|
sandbox_writable_dirs=[str(tmp_path / "sandbox-dir")],
|
|
@@ -344,7 +344,7 @@ async def test_permission_preset_change_preserves_path_grant_sources(tmp_path):
|
|
|
344
344
|
await service.add_grant(AccessGrant(path=str(runtime_file), access="write", object_type="file", persistence="runtime"))
|
|
345
345
|
start_permissions_revision = service.permissions_revision
|
|
346
346
|
|
|
347
|
-
service.
|
|
347
|
+
service.set_permission_mode("read_only")
|
|
348
348
|
|
|
349
349
|
grants = service.get_access_grants()
|
|
350
350
|
assert str(tmp_path / "sandbox.txt") in grants.readable_files
|