deepagents-code 0.1.56__tar.gz → 0.1.57__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.
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/AGENTS.md +1 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/CHANGELOG.md +22 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/PKG-INFO +2 -2
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/THREAT_MODEL.md +3 -2
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_ask_user_types.py +105 -8
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_build_info.py +1 -1
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_dep_floor_check.py +227 -34
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_env_vars.py +33 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_session_stats.py +45 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_textual_patches.py +7 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_version.py +1 -1
- deepagents_code-0.1.57/deepagents_code/acp.py +139 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/agent.py +8 -5
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/app.py +2496 -707
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/app.tcss +41 -5
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/ask_user.py +90 -13
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/auto_mode.py +95 -16
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/commands/extras.py +4 -8
- deepagents_code-0.1.57/deepagents_code/cold_cache.py +1057 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/config.py +7 -4
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/config_manifest.py +49 -1
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/configurable_model.py +251 -10
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/cost_tracking.py +5 -2
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/doctor.py +12 -14
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/models/domain.py +1 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/models/wire.py +1 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/projection.py +3 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/main.py +180 -62
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/model_config.py +125 -7
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/resume_state.py +25 -0
- deepagents_code-0.1.57/deepagents_code/tui/modals/cold_cache.py +361 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/plugin_manager/__init__.py +300 -31
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/plugin_manager/models.py +17 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/plugin_manager/plugin_manager.tcss +20 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/plugin_manager/state.py +8 -1
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/textual_adapter.py +2 -2
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/_paste_textarea.py +37 -0
- deepagents_code-0.1.57/deepagents_code/tui/widgets/ask_user.py +1312 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/chat_input.py +633 -17
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/message_store.py +119 -31
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/messages.py +200 -2
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/model_selector.py +26 -13
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/notification_settings.py +2 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/startup_tip.py +1 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/subagent_panel.py +29 -23
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/thread_selector.py +53 -16
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/welcome.py +17 -1
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/ui.py +5 -3
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/update_check.py +150 -15
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/pyproject.toml +2 -2
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/conftest.py +32 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_engine.py +13 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/plugins/test_plugins_p0.py +75 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/smoke_tests/snapshots/system_prompt_interactive_local.md +2 -1
- deepagents_code-0.1.57/tests/unit_tests/test_acp.py +56 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_agent.py +3 -3
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_app.py +3599 -65
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_ask_user_middleware.py +164 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_auto_mode.py +620 -8
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_charset.py +16 -26
- deepagents_code-0.1.57/tests/unit_tests/test_cold_cache.py +1287 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_compact_tool.py +36 -11
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_config_manifest.py +35 -1
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_configurable_model.py +253 -4
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_debug_console.py +68 -10
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_dep_floor_check.py +309 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_doctor.py +6 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_end_to_end.py +30 -12
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_main.py +351 -38
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_main_acp_mode.py +88 -3
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_main_args.py +4 -4
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_managed_tools.py +17 -7
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_model_config.py +111 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_offload.py +431 -10
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_reload.py +597 -84
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_resume_state.py +52 -13
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_session_stats.py +43 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_threads_resume.py +34 -3
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_transcript_virtualization.py +18 -2
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_update_check.py +314 -15
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_version.py +287 -10
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/modals/plugin_manager/test_structure.py +389 -0
- deepagents_code-0.1.57/tests/unit_tests/tui/modals/test_cold_cache.py +257 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/test_textual_adapter.py +17 -0
- deepagents_code-0.1.57/tests/unit_tests/tui/widgets/test_ask_user.py +2892 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_chat_input.py +644 -3
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_inline_prompt.py +42 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_message_store.py +128 -19
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_messages.py +5 -2
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_model_selector.py +9 -4
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_notification_settings.py +5 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_startup_tip.py +4 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_subagent_panel.py +46 -4
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_thread_selector.py +332 -74
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_welcome.py +23 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/uv.lock +5 -5
- deepagents_code-0.1.56/deepagents_code/tui/widgets/ask_user.py +0 -542
- deepagents_code-0.1.56/deepagents_code/tui/widgets/plugin_reload.py +0 -96
- deepagents_code-0.1.56/tests/unit_tests/tui/widgets/test_ask_user.py +0 -1432
- deepagents_code-0.1.56/tests/unit_tests/tui/widgets/test_plugin_reload.py +0 -61
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/.gitignore +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/ARCHITECTURE.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/COMMANDS.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/DEVELOPMENT.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/HOOKS.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/LICENSE +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/Makefile +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/PRICING.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/README.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/__main__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_cli_context.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_constants.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_debug.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_debug_buffer.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_fake_models.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_git.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_glm_5p2_profile.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_invocation.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_markdown.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_paths.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_repository_bounds.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_server_config.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_startup_error.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_testing_models.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/_tool_stream.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/approval_mode.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/auth_display.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/auth_store.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/built_in_skills/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/built_in_skills/deepagents-thread-inspector/SKILL.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/built_in_skills/deepagents-thread-inspector/scripts/inspect_sessions.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/built_in_skills/remember/SKILL.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/built_in_skills/skill-creator/SKILL.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/bundled_prices.README.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/bundled_prices.json +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/commands/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/commands/auth.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/commands/config.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/commands/mcp.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/commands/tools.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/launch/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/launch/server.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/launch/server_manager.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/non_interactive.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/client/remote_client.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/clipboard.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/command_registry.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/default_agent_prompt.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/diff_utils.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/editor.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/event_bus.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/extras_info.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/file_ops.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/formatting.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/goal_rubric.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/goal_state_notice.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/goal_tools.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/capabilities.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/client.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/client_lifecycle.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/context.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/engine.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/env.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/envelope.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/interrupt.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/legacy.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/loading.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/manager.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/migration.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/models/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/models/adapters.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/models/config.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/models/transport.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/permissions.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/presenter.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/reducer.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/runner.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/runtime.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/server_middleware.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/snapshot.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/tools.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/transcript.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/trust.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/hooks/validate_terminal_sequence.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/input.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/integrations/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/integrations/openai_codex.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/integrations/sandbox_config.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/integrations/sandbox_factory.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/integrations/sandbox_provider.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/integrations/sandbox_registry.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/iterm_cursor_guide.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/json_types.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/local_context.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/managed_tools.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_auth.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_config.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_disabled.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_login_service.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_oauth_ui.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_providers/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_providers/_registry.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_providers/base.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_providers/github.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_providers/slack.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/mcp_tools.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/media_utils.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/memory_guard.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/notifications.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/offload.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/offload_middleware.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/onboarding.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/output.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/paste_collapse.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/_json.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/adapters/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/adapters/hooks.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/adapters/mcp.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/adapters/skills.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/adapters/skills_middleware.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/commands_cli.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/discovery.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/manifest.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/marketplace.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/models.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/store.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/plugins/substitution.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/project_utils.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/py.typed +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/reasoning_effort.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/reliable_rubric.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/server_graph.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/sessions.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/skills/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/skills/commands.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/skills/invocation.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/skills/load.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/skills/merge.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/skills/trust.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/state_migration.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/subagents.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/system_prompt.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/terminal_capabilities.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/terminal_escape.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/theme.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tool_catalog.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tool_display.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tools.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/plugin_manager/content.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/plugin_manager/tabs.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/modals/resume_compact.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/screens/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/_copy_spans.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/_inline_prompt.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/_js_eval_display.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/_links.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/agent_selector.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/approval.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/auth.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/auto_mode_notice.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/autocomplete.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/codex_auth.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/context_usage.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/cwd_switch.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/debug_console.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/diff.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/effort_selector.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/goal_review.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/goal_status.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/history.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/install_confirm.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/launch_init.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/loading.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/mcp_login.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/mcp_reconnect.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/mcp_viewer.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/notification_center.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/notification_detail.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/restart_prompt.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/skill_trust.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/status.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/theme_selector.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/thread_agent_switch.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/tool_renderers.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/tool_widgets.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/update_available.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/update_confirm.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/update_progress.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/tui/widgets/yolo_mode_notice.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/deepagents_code/unicode_security.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/examples/skills/arxiv-search/SKILL.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/examples/skills/arxiv-search/arxiv_search.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/examples/skills/langgraph-docs/SKILL.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/examples/skills/skill-creator/SKILL.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/examples/skills/web-research/SKILL.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/hatch_build.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/images/tui.png +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/scripts/check_imports.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/scripts/debug_server.sh +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/scripts/generate_commands_catalog.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/scripts/install.sh +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/README.md +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/benchmarks/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/benchmarks/test_local_context_benchmarks.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/conftest.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/test_acp_mode.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/test_auto_approve_remote.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/test_compact_resume.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/test_goal_criteria_remote.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/test_offload_server_side.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/test_sandbox_factory.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/integration_tests/test_sandbox_operations.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/client/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/client/commands/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/client/commands/test_auth.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/client/commands/test_extras.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/client/commands/test_mcp.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/client/commands/test_tools.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/data/coding_agent_v1_validator.json +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/models/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/models/test_models.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_client_lifecycle.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_configuration.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_execution.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_manager.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_presenter.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_server_lifecycle.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_transcript.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/hooks/test_trust.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/plugins/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/plugins/test_marketplace.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/plugins/test_plugin_hooks.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/plugins/test_store.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/skills/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/skills/test_commands.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/skills/test_load.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/skills/test_merge.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/skills/test_skill_trust.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/skills/test_skills_json.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/skills/test_thread_inspector.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/smoke_tests/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/smoke_tests/conftest.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/smoke_tests/test_system_prompt.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test__tool_stream.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_agent_friendly.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_approval_mode.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_args.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_ask_user_types.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_auth_display.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_auth_store.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_auth_web_search_restart.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_clipboard.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_coding_agent_metadata.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_command_registry.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_config.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_config_recursion_limit.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_cost_tracking.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_cursor_blink.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_cursor_style.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_debug.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_debug_buffer.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_diff_utils.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_editor.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_env_vars.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_event_bus.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_exception_handling.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_extras_info.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_file_ops.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_formatting.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_git.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_glm_5p2_profile.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_goal_criteria_client.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_goal_rubric.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_goal_state_notice.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_goal_state_persistence.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_goal_tools.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_hatch_build.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_hooks.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_imports.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_input_parsing.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_install_command.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_install_script.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_invocation.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_json_types.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_local_context.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_mcp_auth.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_mcp_config.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_mcp_disabled.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_mcp_login_service.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_mcp_oauth_ui.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_mcp_tools.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_media_utils.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_memory_guard.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_model_switch.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_non_interactive.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_notifications.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_onboarding.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_openai_codex_integration.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_output.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_paths.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_reasoning_effort.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_reliable_rubric.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_remote_client.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_repository_bounds.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_rubric_cli.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_sandbox_config.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_sandbox_factory.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_sandbox_provider.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_sandbox_registry.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_server.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_server_config.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_server_graph.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_server_helpers.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_server_manager.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_sessions.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_shell_allow_list.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_skill_invocation.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_startup_blocking.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_startup_fast_paths.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_state_migration.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_subagents.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_terminal_capabilities.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_terminal_escape.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_terminal_progress_preference.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_textual_patches.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_theme.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_tool_catalog.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_tool_display.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_tracing_replicas.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_ui.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/test_unicode_security.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tools/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tools/test_current_thread.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tools/test_fetch_url.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tools/test_tool_arg_schemas.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/modals/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/modals/plugin_manager/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/test_subagent_stream.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/__init__.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_agent_selector.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_approval.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_auth_widgets.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_auto_mode_notice.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_autocomplete.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_copy_spans.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_cwd_switch.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_diff.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_goal_review.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_history.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_install_confirm.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_launch_init.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_links.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_loading.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_mcp_login_modal.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_mcp_reconnect.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_mcp_viewer.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_notification_center.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_notification_detail.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_restart_prompt.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_skill_trust_screen.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_status.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_thread_agent_switch.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_tool_renderers.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_update_available.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_update_confirm.py +0 -0
- {deepagents_code-0.1.56 → deepagents_code-0.1.57}/tests/unit_tests/tui/widgets/test_update_progress.py +0 -0
|
@@ -78,6 +78,7 @@ Apply these rules to new UI; do not treat them as a mandate to refactor existing
|
|
|
78
78
|
- Use `textual.pilot` for async UI testing - see [Testing guide](https://textual.textualize.io/guide/testing/)
|
|
79
79
|
- Snapshot testing available for visual regression - see repo `notes/snapshot_testing.md`
|
|
80
80
|
- For modal flows, test the real interaction path with keypresses when possible. Unit tests that call action methods or resume handlers directly can miss focus and modal-stack bugs.
|
|
81
|
+
- A modal test that pushes the screen onto a bare `App` host cannot catch app-level key interception. The app owns a priority `shift+tab -> toggle_auto_approve` binding (`app.py`) that wins dispatch over any screen binding; `action_toggle_auto_approve` routes the key to the active screen. Cursor-style modals (highlighted rows, no focusable children) just implement `action_move_up` — the router's `_SupportsReverseNav` protocol branch picks them up automatically. The protocol matches on method *presence*, so enrollment is opt-out, not opt-in: a screen that defines `action_move_up` for its own arrow keys gets `shift+tab` reverse-nav whether or not it was written with that key in mind. Screens needing different behavior (`focus_previous`, tab bars) — or none — need an explicit branch *above* the protocol check in `action_toggle_auto_approve`. Either way, add an app-level regression test in `test_app.py` that presses `shift+tab` through the real `DeepAgentsApp` dispatch, or the modal will silently swallow the key.
|
|
81
82
|
- Do not open another modal or refocus the base chat input directly inside a modal dismiss callback. Preserve the non-blocking `push_screen(..., callback)` flow and schedule follow-up UI work with `call_after_refresh` so the dismissing modal fully unwinds first.
|
|
82
83
|
- Be cautious replacing `push_screen(..., callback)` with an awaited modal result inside slash-command handlers; awaiting can block the Textual message pump and break keyboard navigation in the active modal. Slash commands are dispatched from `on_chat_input_submitted`, which is awaited inline on that pump, so a modal awaited anywhere in the call chain never receives the keys that would resolve it and looks frozen.
|
|
83
84
|
- When a command genuinely needs an awaited modal result, hand the continuation to `_schedule_off_message_pump` so the handler returns first. A detached continuation runs outside the handler's `try/except` and is cancelled at app exit, so it must catch its own exceptions and mount its own failure message — otherwise the failure reaches only `_log_task_exception` and the user sees no outcome at all — and it must tolerate cancellation part-way through, including mid-subprocess. Anything that mutates the running tool environment must also take `_environment_mutation_lock`, since the handler no longer serializes commands by blocking.
|
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
# Deep Agents Code Changelog
|
|
4
4
|
|
|
5
|
+
## [0.1.57](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.56...deepagents-code==0.1.57) (2026-08-18)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- Added warnings before expensive cold-cache turns and trust user-declared endpoints for cold-cache policies ([#5439](https://github.com/langchain-ai/deepagents/issues/5439), [#5462](https://github.com/langchain-ai/deepagents/issues/5462)).
|
|
10
|
+
- Made the chat input resizable by dragging its top border ([#5524](https://github.com/langchain-ai/deepagents/issues/5524)).
|
|
11
|
+
- Added a `multi_select` question type to `ask_user` ([#5097](https://github.com/langchain-ai/deepagents/issues/5097)).
|
|
12
|
+
- Added support for ACP approval modes ([#5394](https://github.com/langchain-ai/deepagents/issues/5394)).
|
|
13
|
+
- Added `DeepSeek-V4-Pro-0813` to the model picker ([#5512](https://github.com/langchain-ai/deepagents/issues/5512)).
|
|
14
|
+
- Show conversation turns alongside message counts ([#5571](https://github.com/langchain-ai/deepagents/issues/5571)).
|
|
15
|
+
- Include `TERM_PROGRAM` in the resume hint ([#5548](https://github.com/langchain-ai/deepagents/issues/5548)).
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
- Report total context after `/offload` ([#5488](https://github.com/langchain-ai/deepagents/issues/5488)).
|
|
20
|
+
- Fixed transcript and thread restoration issues, including hydration lag, scrolling resumed threads to the bottom, and hiding empty previous-thread hints ([#5479](https://github.com/langchain-ai/deepagents/issues/5479), [#5543](https://github.com/langchain-ai/deepagents/issues/5543), [#5552](https://github.com/langchain-ai/deepagents/issues/5552)).
|
|
21
|
+
- Fixed Auto-mode approval handling by binding “yes” to the paired `ask_user` question and avoiding duplicate Auto denial notices ([#5038](https://github.com/langchain-ai/deepagents/issues/5038), [#5501](https://github.com/langchain-ai/deepagents/issues/5501)).
|
|
22
|
+
- Improved reload behavior by keeping the chat input responsive during `/reload`, reporting MCP server changes, and avoiding plugin reload prompt flashes or startup hints ([#5529](https://github.com/langchain-ai/deepagents/issues/5529), [#5504](https://github.com/langchain-ai/deepagents/issues/5504), [#5500](https://github.com/langchain-ai/deepagents/issues/5500), [#5502](https://github.com/langchain-ai/deepagents/issues/5502)).
|
|
23
|
+
- Improved dependency update UI by preserving editable fields and hiding dependency details after updates ([#5521](https://github.com/langchain-ai/deepagents/issues/5521), [#5519](https://github.com/langchain-ai/deepagents/issues/5519)).
|
|
24
|
+
- Fixed chat UI polish issues, including detached spacer mount anchors, the unfocused input cursor, and relative timestamp toggle display ([#5516](https://github.com/langchain-ai/deepagents/issues/5516), [#5258](https://github.com/langchain-ai/deepagents/issues/5258), [#5503](https://github.com/langchain-ai/deepagents/issues/5503)).
|
|
25
|
+
- Refresh the splash version after updates ([#5520](https://github.com/langchain-ai/deepagents/issues/5520)).
|
|
26
|
+
|
|
5
27
|
## [0.1.56](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.55...deepagents-code==0.1.56) (2026-08-14)
|
|
6
28
|
|
|
7
29
|
### Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: deepagents-code
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.57
|
|
4
4
|
Summary: Terminal coding agent built on the Deep Agents SDK - works with any model, with persistent memory, customizable skills, subagents, and approval controls.
|
|
5
5
|
Project-URL: Homepage, https://docs.langchain.com/oss/python/deepagents/overview
|
|
6
6
|
Project-URL: Documentation, https://reference.langchain.com/python/deepagents/
|
|
@@ -31,7 +31,7 @@ Requires-Dist: anyio<5.0.0,>=4.14.2
|
|
|
31
31
|
Requires-Dist: deepagents-acp<1.0.0,>=0.0.10
|
|
32
32
|
Requires-Dist: deepagents==0.7.6
|
|
33
33
|
Requires-Dist: filelock<3.30,>=3.29.7
|
|
34
|
-
Requires-Dist: genai-prices<0.2.0,>=0.1.
|
|
34
|
+
Requires-Dist: genai-prices<0.2.0,>=0.1.3
|
|
35
35
|
Requires-Dist: httpx<1.0.0,>=0.28.1
|
|
36
36
|
Requires-Dist: langchain-anthropic<2.0.0,>=1.5.6
|
|
37
37
|
Requires-Dist: langchain-google-genai<5.0.0,>=4.3.3
|
|
@@ -442,7 +442,7 @@
|
|
|
442
442
|
#### T14: Weaker Auto Classifier Model Weakens Action Review
|
|
443
443
|
|
|
444
444
|
- **Flow**: DF7 (LLM tool call) → Auto classifier review → C4 Tools
|
|
445
|
-
- **Description**: In Auto approval mode, gated tool calls that deterministic policy cannot clear are reviewed by an LLM authorization classifier. That classifier can be pointed at a separate model (`--auto-classifier-model`, `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL`, `[models].auto_classifier`, or `/auto model`) so reviews are cheaper and faster than the main agent model. Review quality then follows the chosen model: a weaker one is likelier to mis-authorize an action, and likelier to be steered by injected instructions in the untrusted material it reads (tool arguments, paths, prior tool output, remote metadata). Choosing the classifier is a user-level decision, so it is restricted to trusted surfaces: shell exports, the global `~/.deepagents/.env`, `~/.deepagents/config.toml`, the CLI flag, and `/auto model`. A *project* `.env` travels with a cloned repo, so `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL` is listed in `config._PROJECT_DOTENV_DENIED_ENV_KEYS` — the same mitigation TB4 applies to the project-MCP trust vars; without that entry a checked-in `.env` could silently downgrade the review on `dcode` startup. With it, this is a self-inflicted weakening of a control rather than an external attack path. Auto's model-independent guards are unchanged by the setting: deterministic allow
|
|
445
|
+
- **Description**: In Auto approval mode, gated tool calls that deterministic policy cannot clear are reviewed by an LLM authorization classifier. That classifier can be pointed at a separate model (`--auto-classifier-model`, `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL`, `[models].auto_classifier`, or `/auto model`) so reviews are cheaper and faster than the main agent model. Review quality then follows the chosen model: a weaker one is likelier to mis-authorize an action, and likelier to be steered by injected instructions in the untrusted material it reads (tool arguments, paths, prior tool output, remote metadata, and the model-authored `ask_user` question text paired with a same-turn answer). Question text is a distinct case: the `ask_user` receipt attests only that this exact text was displayed to the user and answered, never that its content is true, so a question asserting prior or blanket authorization is untrusted content rather than evidence. `_CLASSIFIER_POLICY` instructs the classifier to read a paired question strictly as a description of a proposed action and target, to disregard directives embedded in it, and to allow an action only where that description matches the action's canonical arguments. Choosing the classifier is a user-level decision, so it is restricted to trusted surfaces: shell exports, the global `~/.deepagents/.env`, `~/.deepagents/config.toml`, the CLI flag, and `/auto model`. A *project* `.env` travels with a cloned repo, so `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL` is listed in `config._PROJECT_DOTENV_DENIED_ENV_KEYS` — the same mitigation TB4 applies to the project-MCP trust vars; without that entry a checked-in `.env` could silently downgrade the review on `dcode` startup. With it, this is a self-inflicted weakening of a control rather than an external attack path. Auto's model-independent guards are unchanged by the setting: deterministic allow (the deterministic deny rules are narrow and do not cover the Deny categories, so an action the classifier affirmatively allows is not re-checked downstream), the consecutive/total denial counters, batch-replay detection, control-state availability, and the human-fallback thresholds. A classifier model that cannot be constructed (bad spec, missing credentials, uninstalled provider package) never falls back to the main model — the first such batch is marked `classifier_unavailable`, so those calls are denied and do not execute, and the failing spec is latched so every subsequent batch escalates straight to human approval until a review succeeds. A transient failure instead escalates once `_CONSECUTIVE_UNAVAILABLE_FALLBACK` consecutive batches have failed, or immediately when Auto's control state cannot be persisted. The review deadline is tunable through a subset of the same trusted surfaces — shell exports, the global `~/.deepagents/.env`, and `[models].auto_classifier_timeout` in `~/.deepagents/config.toml` (there is no CLI flag and no `/auto` subcommand for it) — and `DEEPAGENTS_CODE_AUTO_CLASSIFIER_TIMEOUT` is denied from a project `.env` for the same reason, so a cloned repo cannot stall gated batches or squeeze the budget until reviews time out. `config_manifest.resolve_auto_classifier_timeout` rejects any resolved value outside `[AUTO_CLASSIFIER_TIMEOUT_FLOOR, AUTO_CLASSIFIER_TIMEOUT_CEILING]` — out-of-range and malformed values are discarded in favor of the next config source rather than clamped — so the deadline itself cannot be removed; a timed-out batch remains fail-closed (`classifier_unavailable`).
|
|
446
446
|
- **Preconditions**: (1) Auto approval mode is active (interactive TUI only, and not under a sandbox); (2) a classifier model is configured through one of the trusted surfaces above — the default reuses the main agent model; (3) for the injected-review variant, untrusted content reaches the classifier through DF8/DF9 and the chosen model follows it. The intended control is that the human remains the fallback for anything the classifier does not affirmatively allow.
|
|
447
447
|
|
|
448
448
|
---
|
|
@@ -452,7 +452,7 @@
|
|
|
452
452
|
| Input Source | Data Flows | Threats | Validation Points | Responsibility | Gaps |
|
|
453
453
|
|-----------------------|-----------------------|---------------|----------------------------------------------------------------------------|----------------|----------------------------------------------------------------------------------------------|
|
|
454
454
|
| User direct input | DF1, DF2 | None (TB1) | None — prompts accepted verbatim | User | No content filtering — intentional; HITL gates downstream tool calls |
|
|
455
|
-
| LLM output | DF6, DF7 | T1, T2, T3, T4, T13, T14| HITL gate; shell allow-list; Unicode/URL warnings on tool args; Auto classifier review | Project | LLM-generated tool args not scanned for injection beyond Unicode/URL; shell allow-list matches only the command's first token, so allow-listed interpreters/wrappers bypass it (T13); Auto classifier review quality follows the user-selected classifier model, and the classifier reads untrusted tool arguments
|
|
455
|
+
| LLM output | DF6, DF7 | T1, T2, T3, T4, T13, T14| HITL gate; shell allow-list; Unicode/URL warnings on tool args; Auto classifier review | Project | LLM-generated tool args not scanned for injection beyond Unicode/URL; shell allow-list matches only the command's first token, so allow-listed interpreters/wrappers bypass it (T13); Auto classifier review quality follows the user-selected classifier model, and the classifier reads untrusted tool arguments, prior output, and model-authored `ask_user` question text (T14) |
|
|
456
456
|
| Tool/function results | DF9, DF11 | T1 | Unicode warning on URL args; `markdownify` HTML conversion | Shared | Tool *results* pass to context without prompt-injection scan |
|
|
457
457
|
| URL-fetched content | DF8, DF9 | T1 | `check_url_safety` on URL arg; HTML→markdown conversion | Shared | Markup-embedded instructions survive markdownify; no LLM-layer guardrail |
|
|
458
458
|
| Configuration | DF10, DF12, DF15, DF23| T9, T10, T12, T14 | Dotenv shell-env precedence; TOML schema; MCP schema + allow/deny lists; JSON structure check; `class_path` format check; project-`.env` denylist for the Auto classifier model | User | Project `.env` can set shell startup-hook vars; `class_path` executes module code before type check; MCP env dict unfiltered; Auto classifier strength is a user choice with no floor enforced (T14) |
|
|
@@ -521,3 +521,4 @@ Threats that appear valid in isolation but fall outside project responsibility b
|
|
|
521
521
|
| 2026-07-28 | manual update | Extended the out-of-scope hooks row for plugin-contributed hooks: enabled plugins may supply `hooks/hooks.json`, gated by install plus enablement rather than workspace trust, with each handler's environment overlaid only by its own plugin path variables |
|
|
522
522
|
| 2026-08-03 | manual update | Added T14 (a weaker Auto classifier model weakens action review) under TB2, covering the selectable classifier (`--auto-classifier-model`, `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL`, `[models].auto_classifier`, `/auto model`), its restriction to trusted config surfaces via `config._PROJECT_DOTENV_DENIED_ENV_KEYS`, and its fail-closed construction behavior (deny, then latch to human approval; never fall back to the main model). Extended the "LLM output" and "Configuration" input-coverage rows with T14 |
|
|
523
523
|
| 2026-08-04 | manual update | Extended T14 for the configurable Auto classifier review deadline (`DEEPAGENTS_CODE_AUTO_CLASSIFIER_TIMEOUT`, `[models].auto_classifier_timeout`): bounded by `config_manifest.resolve_auto_classifier_timeout` between a floor and ceiling so the deadline cannot be removed, denied from a project `.env` via `config._PROJECT_DOTENV_DENIED_ENV_KEYS`, and fail-closed on expiry |
|
|
524
|
+
| 2026-08-17 | manual update | Extended T14 for `ask_user` question text as a classifier injection source: the receipt attests display and answer, not content, so a question claiming prior or blanket authorization is untrusted content; recorded the `_CLASSIFIER_POLICY` clauses that keep a paired question to an action/target description matched against canonical arguments. Narrowed the T14 "deterministic allow/deny" guard wording, which overstated the deny side: deterministic denies do not cover the Deny categories, and an affirmative classifier allow is not re-checked downstream |
|
|
@@ -11,16 +11,87 @@ side produces it and which reads it.
|
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
|
-
from typing import Annotated, Literal, NotRequired
|
|
14
|
+
from typing import Annotated, Literal, NotRequired, assert_never, get_args
|
|
15
15
|
|
|
16
16
|
from pydantic import Field
|
|
17
17
|
from typing_extensions import TypedDict
|
|
18
18
|
|
|
19
|
+
QuestionType = Literal["text", "multiple_choice", "multi_select"]
|
|
20
|
+
"""Supported `ask_user` question types."""
|
|
21
|
+
|
|
22
|
+
QUESTION_TYPES: frozenset[str] = frozenset(get_args(QuestionType))
|
|
23
|
+
"""Runtime membership view of `QuestionType`.
|
|
24
|
+
|
|
25
|
+
Derived via `get_args` so the membership checks in `ask_user` and `auto_mode`
|
|
26
|
+
cannot drift from the alias when a new question type is added. That drift would
|
|
27
|
+
be silent: an unrecognized type makes `_ask_user_question_count` return `None`,
|
|
28
|
+
which drops the user's answers as same-turn authorization without any error.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _requires_choices(question_type: QuestionType) -> bool:
|
|
33
|
+
"""Return whether `question_type` needs a non-empty `choices` list.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
question_type: A member of `QuestionType`.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
True if questions of this type must define `choices`.
|
|
40
|
+
"""
|
|
41
|
+
if question_type == "text":
|
|
42
|
+
return False
|
|
43
|
+
if question_type in {"multiple_choice", "multi_select"}:
|
|
44
|
+
return True
|
|
45
|
+
# Exhaustiveness guard: adding a `QuestionType` member without deciding here
|
|
46
|
+
# whether it needs choices fails type checking rather than silently landing
|
|
47
|
+
# on the wrong side of `CHOICE_QUESTION_TYPES`.
|
|
48
|
+
assert_never(question_type)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
CHOICE_QUESTION_TYPES: frozenset[str] = frozenset(
|
|
52
|
+
question_type
|
|
53
|
+
for question_type in get_args(QuestionType)
|
|
54
|
+
if _requires_choices(question_type)
|
|
55
|
+
)
|
|
56
|
+
"""Question types that require a non-empty `choices` list.
|
|
57
|
+
|
|
58
|
+
Derived from `_requires_choices` rather than written out, so it cannot omit a
|
|
59
|
+
new choice-based `QuestionType` member. Note that requiring `choices` is not the
|
|
60
|
+
same as being *rendered* as a choice list: the TUI has its own exhaustive
|
|
61
|
+
dispatch in `_QuestionWidget.compose`.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
MULTI_SELECT_ANSWER_SEPARATOR = ", "
|
|
65
|
+
"""Separator joining the selected values of a `multi_select` answer."""
|
|
66
|
+
|
|
67
|
+
MULTI_SELECT_FORBIDDEN_IN_VALUE = ","
|
|
68
|
+
"""Substring a `multi_select` choice value must not contain.
|
|
69
|
+
|
|
70
|
+
Deliberately stated outright rather than derived from
|
|
71
|
+
`MULTI_SELECT_ANSWER_SEPARATOR`, so the two can evolve independently: a separator
|
|
72
|
+
of `" and "` would, if the forbidden text were derived from it, reject every value
|
|
73
|
+
containing "and".
|
|
74
|
+
|
|
75
|
+
This buys *legibility* of the joined answer, not invertibility. Nothing decodes a
|
|
76
|
+
multi-select answer back into its components, and per
|
|
77
|
+
`format_ask_user_transcript` the transcript is not unambiguously decodable
|
|
78
|
+
anyway. If one is ever written, that is the moment to introduce a structured
|
|
79
|
+
answer type instead of leaning on this ban.
|
|
80
|
+
"""
|
|
81
|
+
|
|
19
82
|
|
|
20
83
|
class Choice(TypedDict):
|
|
21
|
-
"""A single choice option for a multiple choice question."""
|
|
84
|
+
"""A single choice option for a multiple choice or multi-select question."""
|
|
22
85
|
|
|
23
|
-
value: Annotated[
|
|
86
|
+
value: Annotated[
|
|
87
|
+
str,
|
|
88
|
+
Field(
|
|
89
|
+
description=(
|
|
90
|
+
"The display label for this choice. Also the text returned as "
|
|
91
|
+
"the answer when this choice is selected."
|
|
92
|
+
)
|
|
93
|
+
),
|
|
94
|
+
]
|
|
24
95
|
|
|
25
96
|
|
|
26
97
|
class Question(TypedDict):
|
|
@@ -29,11 +100,18 @@ class Question(TypedDict):
|
|
|
29
100
|
question: Annotated[str, Field(description="The question text to display.")]
|
|
30
101
|
|
|
31
102
|
type: Annotated[
|
|
32
|
-
|
|
103
|
+
QuestionType,
|
|
33
104
|
Field(
|
|
34
105
|
description=(
|
|
35
106
|
"Question type. 'text' for free-form input, 'multiple_choice' for "
|
|
36
|
-
"predefined
|
|
107
|
+
"picking exactly one predefined option, 'multi_select' for picking "
|
|
108
|
+
"one or more predefined options. Both choice types always append an "
|
|
109
|
+
"'Other' free-form option automatically; multi-select can accept "
|
|
110
|
+
"multiple custom Other values (filling one reveals another). A "
|
|
111
|
+
"'multi_select' answer comes back as the selected values "
|
|
112
|
+
"(including any custom Other text) joined with ', '; if nothing "
|
|
113
|
+
"is selected on an optional question the answer is an empty "
|
|
114
|
+
"string."
|
|
37
115
|
)
|
|
38
116
|
),
|
|
39
117
|
]
|
|
@@ -43,8 +121,12 @@ class Question(TypedDict):
|
|
|
43
121
|
list[Choice],
|
|
44
122
|
Field(
|
|
45
123
|
description=(
|
|
46
|
-
"Options for multiple_choice
|
|
47
|
-
"
|
|
124
|
+
"Options for 'multiple_choice' and 'multi_select' questions. "
|
|
125
|
+
"Every choice needs a non-empty 'value'. An 'Other' free-form "
|
|
126
|
+
"option is always appended automatically for both types; "
|
|
127
|
+
"multi-select may collect multiple custom Other values. "
|
|
128
|
+
"'multi_select' values (including custom Other text) must not "
|
|
129
|
+
"contain ',' because the answer joins them with ', '."
|
|
48
130
|
)
|
|
49
131
|
),
|
|
50
132
|
]
|
|
@@ -53,8 +135,18 @@ class Question(TypedDict):
|
|
|
53
135
|
required: NotRequired[
|
|
54
136
|
Annotated[
|
|
55
137
|
bool,
|
|
138
|
+
# `strict=True` so a stringly-typed `"false"` is rejected at the tool
|
|
139
|
+
# boundary rather than coerced. Without it pydantic accepts the string,
|
|
140
|
+
# the prompt renders, and then `_ask_user_question_count` — which reads
|
|
141
|
+
# the *raw* tool args and requires a real bool — returns `None`, which
|
|
142
|
+
# drops every answer in the call as same-turn authorization with no
|
|
143
|
+
# error. Strict here keeps the two boundaries agreeing, and makes the
|
|
144
|
+
# coercion loud instead of silently expensive.
|
|
56
145
|
Field(
|
|
57
|
-
description=
|
|
146
|
+
description=(
|
|
147
|
+
"Whether the user must answer. Defaults to true if omitted."
|
|
148
|
+
),
|
|
149
|
+
strict=True,
|
|
58
150
|
),
|
|
59
151
|
]
|
|
60
152
|
]
|
|
@@ -75,6 +167,11 @@ class AskUserRequest(TypedDict):
|
|
|
75
167
|
|
|
76
168
|
ASK_USER_AUTHORIZATION_METADATA_KEY = "deepagents_code_ask_user_authorization"
|
|
77
169
|
MAX_ASK_USER_AUTHORIZATION_ANSWER_CHARS = 4000
|
|
170
|
+
# These limits bound the receipt-anchored question/answer evidence copied into
|
|
171
|
+
# Auto's classifier prompt. Questions are model-generated and otherwise have no
|
|
172
|
+
# schema length constraint, so they must not be able to exhaust that context.
|
|
173
|
+
MAX_ASK_USER_AUTHORIZATION_QUESTION_CHARS = 4000
|
|
174
|
+
MAX_ASK_USER_AUTHORIZATION_QUESTION_TOTAL_CHARS = 8000
|
|
78
175
|
|
|
79
176
|
|
|
80
177
|
class AskUserAuthorizationReceipt(TypedDict):
|
|
@@ -10,7 +10,7 @@ editable `direct_url.json` record and skip the check entirely, so end
|
|
|
10
10
|
users pay no startup cost here.
|
|
11
11
|
|
|
12
12
|
Interactive launches on a terminal stop on a blocking pre-TUI prompt
|
|
13
|
-
(continue / mute / abort); headless launches, subcommands, and interactive
|
|
13
|
+
(refresh / continue / mute / abort); headless launches, subcommands, and interactive
|
|
14
14
|
launches whose stdin is piped get a single stderr warning per launch instead,
|
|
15
15
|
since they have no answerable prompt and must never block. A dismissed
|
|
16
16
|
(muted) mismatch is remembered per checkout as a fingerprint of the offending
|
|
@@ -25,7 +25,8 @@ import json
|
|
|
25
25
|
import logging
|
|
26
26
|
import os
|
|
27
27
|
import shlex
|
|
28
|
-
import
|
|
28
|
+
import shutil
|
|
29
|
+
import subprocess # noqa: S404 # fixed-argv environment refresh and Windows quoting
|
|
29
30
|
import sys
|
|
30
31
|
import tempfile
|
|
31
32
|
import threading
|
|
@@ -40,6 +41,8 @@ from deepagents_code.config import _is_editable_install
|
|
|
40
41
|
if TYPE_CHECKING:
|
|
41
42
|
from collections.abc import Iterator
|
|
42
43
|
|
|
44
|
+
from rich.console import Console
|
|
45
|
+
|
|
43
46
|
from deepagents_code.main import _TrustPromptOutcome
|
|
44
47
|
|
|
45
48
|
logger = logging.getLogger(__name__)
|
|
@@ -259,17 +262,177 @@ def _checkout_root() -> Path:
|
|
|
259
262
|
return Path(__file__).resolve().parent.parent
|
|
260
263
|
|
|
261
264
|
|
|
265
|
+
def _is_editable_dist(dist_name: str, path: Path) -> bool:
|
|
266
|
+
"""Check whether an installed distribution is an editable install of `path`.
|
|
267
|
+
|
|
268
|
+
Reads the distribution's own PEP 610 `direct_url.json` rather than the
|
|
269
|
+
directory's existence: most `[tool.uv.sources]` entries back optional
|
|
270
|
+
extras, so a source directory that merely exists in a full monorepo
|
|
271
|
+
checkout must not be reinstalled as an editable over an environment that
|
|
272
|
+
deliberately tracks the released wheel.
|
|
273
|
+
|
|
274
|
+
Args:
|
|
275
|
+
dist_name: Distribution name as passed to `importlib.metadata`.
|
|
276
|
+
path: The source checkout the `[tool.uv.sources]` entry points at.
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
`True` when the distribution is installed editable with a `file://`
|
|
280
|
+
URL resolving to `path`; `False` for wheel installs, missing
|
|
281
|
+
distributions, and unreadable or mismatched metadata.
|
|
282
|
+
"""
|
|
283
|
+
try:
|
|
284
|
+
raw = importlib.metadata.distribution(dist_name).read_text("direct_url.json")
|
|
285
|
+
if not raw:
|
|
286
|
+
return False
|
|
287
|
+
data = json.loads(raw)
|
|
288
|
+
except (
|
|
289
|
+
importlib.metadata.PackageNotFoundError,
|
|
290
|
+
json.JSONDecodeError,
|
|
291
|
+
TypeError,
|
|
292
|
+
):
|
|
293
|
+
return False
|
|
294
|
+
if not isinstance(data, dict):
|
|
295
|
+
return False
|
|
296
|
+
dir_info = data.get("dir_info")
|
|
297
|
+
if not isinstance(dir_info, dict) or dir_info.get("editable") is not True:
|
|
298
|
+
return False
|
|
299
|
+
url = data.get("url", "")
|
|
300
|
+
if not isinstance(url, str) or not url.startswith("file://"):
|
|
301
|
+
return False
|
|
302
|
+
from deepagents_code.extras_info import _file_url_to_path
|
|
303
|
+
|
|
304
|
+
recorded = _file_url_to_path(url)
|
|
305
|
+
# `_file_url_to_path` preserves the `netloc` host, so UNC installs such as
|
|
306
|
+
# `file://server/share/repo` compare equal to the same UNC checkout here;
|
|
307
|
+
# parsing only `urlparse(url).path` would drop the server and omit the
|
|
308
|
+
# editable from the refresh, replacing it with a PyPI wheel.
|
|
309
|
+
return recorded is not None and recorded.resolve() == path
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def _workspace_editable_paths() -> list[Path]:
|
|
313
|
+
"""List the workspace sources this environment actually installed editable.
|
|
314
|
+
|
|
315
|
+
Reads the checkout's own `[tool.uv.sources]`, then keeps only the entries
|
|
316
|
+
whose distribution is currently installed as an editable pointing at that
|
|
317
|
+
same path. Directory existence alone is not enough: partner packages
|
|
318
|
+
(`langchain-daytona`, `langchain-modal`, ...) are optional extras whose
|
|
319
|
+
checkouts always exist in a full monorepo clone, and re-passing them as
|
|
320
|
+
`-e` would replace their released wheels with editables and pull in their
|
|
321
|
+
transitive dependencies.
|
|
322
|
+
|
|
323
|
+
Returns:
|
|
324
|
+
Absolute paths of `editable = true` path sources whose distribution is
|
|
325
|
+
installed editable from that path, in `pyproject.toml` declaration
|
|
326
|
+
order. Empty when the checkout's `pyproject.toml` cannot be read or no
|
|
327
|
+
source qualifies.
|
|
328
|
+
"""
|
|
329
|
+
pyproject = _checkout_root() / "pyproject.toml"
|
|
330
|
+
try:
|
|
331
|
+
data = tomllib.loads(pyproject.read_text(encoding="utf-8"))
|
|
332
|
+
sources = data["tool"]["uv"]["sources"]
|
|
333
|
+
except (OSError, KeyError, TypeError, tomllib.TOMLDecodeError):
|
|
334
|
+
logger.debug(
|
|
335
|
+
"Could not read workspace sources from the source checkout",
|
|
336
|
+
exc_info=True,
|
|
337
|
+
)
|
|
338
|
+
return []
|
|
339
|
+
if not isinstance(sources, dict):
|
|
340
|
+
return []
|
|
341
|
+
checkout = _checkout_root()
|
|
342
|
+
paths: list[Path] = []
|
|
343
|
+
for dist_name, source in sources.items():
|
|
344
|
+
if not isinstance(source, dict):
|
|
345
|
+
continue
|
|
346
|
+
if source.get("editable") is not True or not isinstance(
|
|
347
|
+
source.get("path"), str
|
|
348
|
+
):
|
|
349
|
+
continue
|
|
350
|
+
path = (checkout / source["path"]).resolve()
|
|
351
|
+
if path.is_dir() and _is_editable_dist(dist_name, path):
|
|
352
|
+
paths.append(path)
|
|
353
|
+
return paths
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
def _refresh_args(uv_path: str) -> list[str]:
|
|
357
|
+
"""Build the fixed argv used to refresh this editable environment.
|
|
358
|
+
|
|
359
|
+
Args:
|
|
360
|
+
uv_path: Absolute path to the resolved `uv` binary. Bare names are
|
|
361
|
+
never used: on Windows `subprocess` searches the current working
|
|
362
|
+
directory before `%PATH%`, so a planted `uv.exe` at the project
|
|
363
|
+
root would execute instead of the legitimate binary.
|
|
364
|
+
|
|
365
|
+
Returns:
|
|
366
|
+
Arguments for the user-approved `uv pip install` process.
|
|
367
|
+
"""
|
|
368
|
+
checkout = _checkout_root()
|
|
369
|
+
args = [
|
|
370
|
+
uv_path,
|
|
371
|
+
"pip",
|
|
372
|
+
"install",
|
|
373
|
+
"--python",
|
|
374
|
+
sys.executable,
|
|
375
|
+
"-e",
|
|
376
|
+
str(checkout),
|
|
377
|
+
]
|
|
378
|
+
for path in _workspace_editable_paths():
|
|
379
|
+
args.extend(["-e", str(path)])
|
|
380
|
+
args.append("--upgrade")
|
|
381
|
+
return args
|
|
382
|
+
|
|
383
|
+
|
|
262
384
|
def refresh_command() -> str:
|
|
263
385
|
"""Return the shell command that refreshes this editable environment.
|
|
264
386
|
|
|
265
|
-
|
|
266
|
-
|
|
387
|
+
Workspace sibling editables are included explicitly because resolving only
|
|
388
|
+
`libs/code` would let `--upgrade` replace them with PyPI wheels. The
|
|
389
|
+
warning and interactive refresh share this argv so they cannot drift.
|
|
267
390
|
"""
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
391
|
+
uv_path = shutil.which("uv")
|
|
392
|
+
if uv_path is None:
|
|
393
|
+
return "uv pip install --python <python> -e <checkout> --upgrade"
|
|
394
|
+
return " ".join(_quote_arg(arg) for arg in _refresh_args(uv_path))
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def _refresh_environment(console: Console) -> bool:
|
|
398
|
+
"""Refresh the active environment after the user explicitly requests it.
|
|
399
|
+
|
|
400
|
+
Args:
|
|
401
|
+
console: Console used for progress and failure messages.
|
|
402
|
+
|
|
403
|
+
Returns:
|
|
404
|
+
`True` when `uv` exits successfully, otherwise `False`.
|
|
405
|
+
"""
|
|
406
|
+
uv_path = shutil.which("uv")
|
|
407
|
+
if uv_path is None:
|
|
408
|
+
console.print(
|
|
409
|
+
"[yellow]Environment refresh failed: `uv` not found on PATH.[/yellow]",
|
|
410
|
+
highlight=False,
|
|
411
|
+
)
|
|
412
|
+
return False
|
|
413
|
+
console.print("[dim]Refreshing environment...[/dim]", highlight=False)
|
|
414
|
+
try:
|
|
415
|
+
result = subprocess.run( # noqa: S603 # fixed uv argv, never a shell command
|
|
416
|
+
_refresh_args(uv_path),
|
|
417
|
+
check=False,
|
|
418
|
+
shell=False,
|
|
419
|
+
)
|
|
420
|
+
except OSError as exc:
|
|
421
|
+
from rich.markup import escape
|
|
422
|
+
|
|
423
|
+
console.print(
|
|
424
|
+
f"[yellow]Environment refresh failed: {escape(str(exc))}[/yellow]",
|
|
425
|
+
highlight=False,
|
|
426
|
+
)
|
|
427
|
+
return False
|
|
428
|
+
if result.returncode != 0:
|
|
429
|
+
console.print(
|
|
430
|
+
"[yellow]Environment refresh failed with exit code "
|
|
431
|
+
f"{result.returncode}; choose another action or try again.[/yellow]",
|
|
432
|
+
highlight=False,
|
|
433
|
+
)
|
|
434
|
+
return False
|
|
435
|
+
return True
|
|
273
436
|
|
|
274
437
|
|
|
275
438
|
def _collect_violations() -> list[_FloorViolation]:
|
|
@@ -516,7 +679,7 @@ def warn_if_editable_deps_stale() -> None:
|
|
|
516
679
|
|
|
517
680
|
|
|
518
681
|
def prompt_if_editable_deps_stale() -> _TrustPromptOutcome | None:
|
|
519
|
-
"""Block on a continue/mute/abort prompt
|
|
682
|
+
"""Block on a refresh/continue/mute/abort prompt for a stale interactive launch.
|
|
520
683
|
|
|
521
684
|
Prompts only when violations exist and the exact mismatch was not muted
|
|
522
685
|
for this checkout. The prompt itself is implemented in `main` next to the
|
|
@@ -544,6 +707,7 @@ def _prompt_if_editable_deps_stale() -> _TrustPromptOutcome | None:
|
|
|
544
707
|
from rich.console import Console
|
|
545
708
|
|
|
546
709
|
from deepagents_code.main import (
|
|
710
|
+
_restart_current_process,
|
|
547
711
|
_TrustAction,
|
|
548
712
|
_TrustPromptOutcome,
|
|
549
713
|
prompt_for_dep_floor_mismatch,
|
|
@@ -552,36 +716,65 @@ def _prompt_if_editable_deps_stale() -> _TrustPromptOutcome | None:
|
|
|
552
716
|
violations = _collect_violations()
|
|
553
717
|
if not violations:
|
|
554
718
|
return None
|
|
555
|
-
|
|
556
|
-
if is_dep_floor_mismatch_muted(fingerprint):
|
|
719
|
+
if is_dep_floor_mismatch_muted(_mismatch_fingerprint(violations)):
|
|
557
720
|
return None
|
|
558
721
|
|
|
559
722
|
console = Console(stderr=True)
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
723
|
+
while True:
|
|
724
|
+
fingerprint = _mismatch_fingerprint(violations)
|
|
725
|
+
action = prompt_for_dep_floor_mismatch(console, violations)
|
|
726
|
+
if action in {
|
|
727
|
+
_TrustPromptOutcome.INTERRUPTED,
|
|
728
|
+
_TrustPromptOutcome.CANCELLED,
|
|
729
|
+
}:
|
|
730
|
+
return action
|
|
731
|
+
if action is _TrustAction.REFRESH:
|
|
732
|
+
if not _refresh_environment(console):
|
|
733
|
+
continue
|
|
734
|
+
violations = _collect_violations()
|
|
735
|
+
if violations:
|
|
736
|
+
continue
|
|
565
737
|
console.print(
|
|
566
|
-
"[dim]
|
|
738
|
+
"[dim]Environment refreshed; relaunching.[/dim]",
|
|
567
739
|
highlight=False,
|
|
568
740
|
)
|
|
569
|
-
|
|
741
|
+
# Re-exec rather than continuing in-process: dependencies imported
|
|
742
|
+
# before this prompt (`rich`, `python-dotenv`, ...) keep their
|
|
743
|
+
# stale module objects in memory even after `uv` swaps the dists
|
|
744
|
+
# on disk, so only a fresh interpreter runs the refreshed code.
|
|
745
|
+
# The relaunched process re-runs this check, finds no violations
|
|
746
|
+
# (the precondition for reaching here), and never re-prompts — a
|
|
747
|
+
# refresh that silently no-ops fails the re-check above instead,
|
|
748
|
+
# so this cannot loop. `OSError` from a failed exec propagates to
|
|
749
|
+
# the best-effort boundary in `prompt_if_editable_deps_stale`,
|
|
750
|
+
# which continues this (stale but user-approved) launch.
|
|
751
|
+
_restart_current_process()
|
|
752
|
+
return None # unreachable; exec failure raises, per its contract
|
|
753
|
+
if action is _TrustAction.REMEMBER:
|
|
754
|
+
if mute_dep_floor_mismatch(fingerprint):
|
|
755
|
+
console.print(
|
|
756
|
+
"[dim]Muted until the dependency mismatch changes.[/dim]",
|
|
757
|
+
highlight=False,
|
|
758
|
+
)
|
|
759
|
+
else:
|
|
760
|
+
console.print(
|
|
761
|
+
"[yellow]The dismissal could not be saved; you will be asked "
|
|
762
|
+
"again next launch.[/yellow]",
|
|
763
|
+
highlight=False,
|
|
764
|
+
)
|
|
765
|
+
elif action is _TrustAction.ALLOW_ONCE:
|
|
570
766
|
console.print(
|
|
571
|
-
"[
|
|
572
|
-
"
|
|
767
|
+
"[dim]Continuing this session; you will be asked again next "
|
|
768
|
+
"launch.[/dim]",
|
|
573
769
|
highlight=False,
|
|
574
770
|
)
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
logger.debug("Unexpected dependency floor prompt outcome %r; aborting", action)
|
|
586
|
-
return _TrustPromptOutcome.CANCELLED
|
|
587
|
-
return None
|
|
771
|
+
else:
|
|
772
|
+
# `abort_on_deny` should have collapsed a refusal into `CANCELLED`
|
|
773
|
+
# already, so `DENY` (or any future outcome) only lands here if that
|
|
774
|
+
# mapping regresses. Refuse rather than continuing: matching "continue"
|
|
775
|
+
# by default is what previously turned "Abort launch" into a launch.
|
|
776
|
+
logger.debug(
|
|
777
|
+
"Unexpected dependency floor prompt outcome %r; aborting", action
|
|
778
|
+
)
|
|
779
|
+
return _TrustPromptOutcome.CANCELLED
|
|
780
|
+
return None
|
|
@@ -117,6 +117,27 @@ Parsed by `is_env_truthy`: accepts `1`, `true`, `yes`, `on` (case-insensitive)
|
|
|
117
117
|
as enabled, and `0`, `false`, `no`, `off`, empty string, or unset as disabled.
|
|
118
118
|
"""
|
|
119
119
|
|
|
120
|
+
DEBUG_COLD_CACHE = "DEEPAGENTS_CODE_DEBUG_COLD_CACHE"
|
|
121
|
+
"""Force the cold prompt-cache warning modal on every interactive send.
|
|
122
|
+
|
|
123
|
+
Set to a truthy value when launching the interactive TUI to make
|
|
124
|
+
`_cold_cache_warning_for` synthesize a warning from the current model and
|
|
125
|
+
context, bypassing the provider-policy, token-floor, cache-window, and
|
|
126
|
+
cost-threshold gates as well as both session and persisted suppression. Lets
|
|
127
|
+
the modal be exercised without waiting out a provider cache window.
|
|
128
|
+
|
|
129
|
+
The flag is re-read on every send and nothing clears it, so the modal fires
|
|
130
|
+
for the life of the process, not just once.
|
|
131
|
+
|
|
132
|
+
When the active model has no documented cache policy, `debug_stand_in_policy`
|
|
133
|
+
supplies an Anthropic-shaped placeholder. On a non-Anthropic model the modal
|
|
134
|
+
will therefore cite Anthropic's retention window, and the dollar figures are
|
|
135
|
+
illustrative rather than real estimates.
|
|
136
|
+
|
|
137
|
+
Parsed by `is_env_truthy`: accepts `1`, `true`, `yes`, `on` (case-insensitive)
|
|
138
|
+
as enabled, and `0`, `false`, `no`, `off`, empty string, or unset as disabled.
|
|
139
|
+
"""
|
|
140
|
+
|
|
120
141
|
DEBUG_CONSOLE_CLICK_TO_COPY = "DEEPAGENTS_CODE_DEBUG_CONSOLE_CLICK_TO_COPY"
|
|
121
142
|
r"""Enable click-to-copy in the `Ctrl+\` Debug Console when enabled.
|
|
122
143
|
|
|
@@ -284,6 +305,18 @@ The value is comma-separated for forward-compatibility, not because multiple
|
|
|
284
305
|
destinations are written today.
|
|
285
306
|
"""
|
|
286
307
|
|
|
308
|
+
LAUNCH_TERM_PROGRAM = "DEEPAGENTS_CODE_LAUNCH_TERM_PROGRAM"
|
|
309
|
+
"""Internal sentinel recording the `TERM_PROGRAM` present when `dcode` started.
|
|
310
|
+
|
|
311
|
+
Not user-facing. The resume hint echoes `TERM_PROGRAM` only when the launch
|
|
312
|
+
environment supplied it (an inline `TERM_PROGRAM=x dcode`, a terminal's own
|
|
313
|
+
export, or a shell alias), so the value set by a project or global `.env` file
|
|
314
|
+
*after* launch must not leak in. The app itself never sets `TERM_PROGRAM`, so
|
|
315
|
+
`cli_main` snapshotting the variable here at entry means a set sentinel always
|
|
316
|
+
marks an explicit launch value; the update re-exec inherits it unchanged,
|
|
317
|
+
which is correct because the relaunch runs the command the user typed.
|
|
318
|
+
"""
|
|
319
|
+
|
|
287
320
|
LEGACY_ENABLED_PROJECT_MCP_SERVERS = "DEEPAGENTS_CODE_ENABLED_PROJECT_MCP_SERVERS"
|
|
288
321
|
"""Removed project MCP allowlist env var retained for migration detection only.
|
|
289
322
|
|