deepagents-code 0.1.59__tar.gz → 0.1.60__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.59 → deepagents_code-0.1.60}/CHANGELOG.md +21 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/COMMANDS.md +1 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/PKG-INFO +1 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/THREAT_MODEL.md +4 -3
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_ask_user_types.py +154 -8
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_build_info.py +1 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_env_vars.py +13 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_textual_patches.py +110 -3
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_version.py +1 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/agent.py +0 -60
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/app.py +170 -64
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/approval_mode.py +9 -7
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/ask_user.py +142 -130
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/auto_mode.py +2 -11
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/commands/config.py +34 -2
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/command_registry.py +1 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/config.py +151 -37
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/config_manifest.py +164 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/model_config.py +111 -12
- deepagents_code-0.1.60/deepagents_code/tui/key_hints.py +31 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/cold_cache.py +2 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/plugin_manager/__init__.py +6 -4
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/plugin_manager/plugin_manager.tcss +1 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/agent_selector.py +11 -7
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/approval.py +1 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/ask_user.py +6 -5
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/auth.py +125 -15
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/chat_input.py +138 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/debug_console.py +70 -5
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/effort_selector.py +3 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/launch_init.py +2 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/mcp_viewer.py +4 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/message_store.py +2 -2
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/messages.py +1 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/model_selector.py +7 -3
- deepagents_code-0.1.60/deepagents_code/tui/widgets/notification_center.py +1044 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/notification_detail.py +4 -2
- deepagents_code-0.1.60/deepagents_code/tui/widgets/notification_settings.py +15 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/theme_selector.py +6 -5
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/update_available.py +4 -2
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/pyproject.toml +1 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_agent.py +10 -31
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_app.py +639 -18
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_ask_user_middleware.py +333 -205
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_ask_user_types.py +52 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_auto_mode.py +8 -2
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_config.py +57 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_config_manifest.py +156 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_configuration.py +25 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_debug_console.py +52 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_end_to_end.py +105 -13
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_model_config.py +172 -5
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_reload.py +246 -5
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_textual_patches.py +109 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/modals/plugin_manager/test_structure.py +2 -0
- deepagents_code-0.1.60/tests/unit_tests/tui/test_key_hints.py +33 -0
- deepagents_code-0.1.60/tests/unit_tests/tui/test_modal_footer_layout.py +200 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/test_textual_adapter.py +6 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_agent_selector.py +1 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_approval.py +2 -2
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_auth_widgets.py +231 -8
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_chat_input.py +227 -1
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_mcp_viewer.py +1 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_model_selector.py +6 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_notification_center.py +201 -6
- deepagents_code-0.1.60/tests/unit_tests/tui/widgets/test_notification_settings.py +313 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/uv.lock +1 -1
- deepagents_code-0.1.59/deepagents_code/_tool_errors.py +0 -20
- deepagents_code-0.1.59/deepagents_code/tui/widgets/notification_center.py +0 -464
- deepagents_code-0.1.59/deepagents_code/tui/widgets/notification_settings.py +0 -179
- deepagents_code-0.1.59/tests/unit_tests/tui/widgets/test_notification_settings.py +0 -145
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/.gitignore +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/AGENTS.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/ARCHITECTURE.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/DEVELOPMENT.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/HOOKS.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/LICENSE +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/Makefile +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/PRICING.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/README.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/__main__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_cli_context.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_constants.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_debug.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_debug_buffer.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_dep_floor_check.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_fake_models.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_git.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_glm_5p2_profile.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_invocation.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_markdown.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_paths.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_repository_bounds.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_server_config.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_session_stats.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_startup_error.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_testing_models.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_tool_stream.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/_tracing.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/acp.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/app.tcss +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/auth_display.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/auth_store.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/built_in_skills/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/built_in_skills/deepagents-thread-inspector/SKILL.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/built_in_skills/deepagents-thread-inspector/scripts/inspect_sessions.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/built_in_skills/remember/SKILL.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/built_in_skills/skill-creator/SKILL.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/bundled_prices.README.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/bundled_prices.json +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/commands/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/commands/auth.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/commands/extras.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/commands/mcp.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/commands/tools.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/launch/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/launch/server.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/launch/server_manager.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/non_interactive.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/client/remote_client.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/clipboard.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/cold_cache.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configurable_model.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configuration/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configuration/paths.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configuration/providers.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configuration/resolver.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configuration/service.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configuration/types.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/configuration/writer.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/cost_tracking.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/default_agent_prompt.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/diff_utils.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/doctor.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/editor.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/event_bus.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/extras_info.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/file_ops.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/formatting.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/goal_rubric.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/goal_state_notice.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/goal_tools.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/capabilities.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/client.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/client_lifecycle.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/context.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/engine.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/env.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/envelope.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/interrupt.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/legacy.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/loading.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/manager.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/migration.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/models/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/models/adapters.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/models/config.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/models/domain.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/models/transport.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/models/wire.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/permissions.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/presenter.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/projection.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/reducer.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/runner.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/runtime.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/server_middleware.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/snapshot.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/tools.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/transcript.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/trust.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/hooks/validate_terminal_sequence.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/input.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/integrations/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/integrations/openai_codex.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/integrations/sandbox_config.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/integrations/sandbox_factory.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/integrations/sandbox_provider.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/integrations/sandbox_registry.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/iterm_cursor_guide.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/json_types.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/local_context.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/main.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/managed_tools.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_auth.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_config.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_disabled.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_login_service.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_oauth_ui.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_providers/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_providers/_registry.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_providers/base.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_providers/github.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_providers/slack.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/mcp_tools.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/media_utils.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/memory_guard.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/notifications.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/offload.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/offload_middleware.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/onboarding.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/output.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/paste_collapse.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/_json.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/adapters/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/adapters/hooks.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/adapters/mcp.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/adapters/skills.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/adapters/skills_middleware.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/commands_cli.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/discovery.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/manifest.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/marketplace.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/models.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/store.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/plugins/substitution.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/project_utils.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/py.typed +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/reasoning_effort.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/reliable_rubric.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/resume_state.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/server_graph.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/sessions.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/skills/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/skills/commands.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/skills/invocation.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/skills/load.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/skills/merge.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/skills/trust.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/state_migration.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/subagents.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/system_prompt.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/terminal_capabilities.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/terminal_escape.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/theme.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tool_catalog.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tool_display.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tools.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/plugin_manager/content.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/plugin_manager/models.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/plugin_manager/state.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/plugin_manager/tabs.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/modals/resume_compact.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/screens/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/textual_adapter.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/_copy_spans.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/_inline_prompt.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/_js_eval_display.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/_links.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/_paste_textarea.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/auto_mode_notice.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/autocomplete.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/codex_auth.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/context_usage.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/cwd_switch.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/diff.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/goal_review.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/goal_status.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/history.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/install_confirm.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/loading.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/mcp_login.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/mcp_reconnect.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/restart_prompt.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/skill_trust.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/startup_tip.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/status.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/subagent_panel.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/thread_agent_switch.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/thread_selector.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/tool_renderers.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/tool_widgets.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/update_confirm.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/update_progress.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/welcome.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/tui/widgets/yolo_mode_notice.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/ui.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/unicode_security.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/deepagents_code/update_check.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/examples/skills/arxiv-search/SKILL.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/examples/skills/arxiv-search/arxiv_search.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/examples/skills/langgraph-docs/SKILL.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/examples/skills/skill-creator/SKILL.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/examples/skills/web-research/SKILL.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/hatch_build.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/images/tui.png +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/scripts/check_imports.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/scripts/debug_server.sh +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/scripts/generate_commands_catalog.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/scripts/install.sh +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/README.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/benchmarks/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/benchmarks/test_local_context_benchmarks.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/conftest.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/test_acp_mode.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/test_auto_approve_remote.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/test_compact_resume.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/test_goal_criteria_remote.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/test_offload_server_side.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/test_sandbox_factory.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/integration_tests/test_sandbox_operations.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/client/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/client/commands/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/client/commands/test_auth.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/client/commands/test_extras.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/client/commands/test_mcp.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/client/commands/test_tools.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/conftest.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/data/coding_agent_v1_validator.json +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/models/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/models/test_models.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_client_lifecycle.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_configuration.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_engine.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_execution.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_manager.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_presenter.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_server_lifecycle.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_transcript.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/hooks/test_trust.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/plugins/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/plugins/test_marketplace.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/plugins/test_plugin_hooks.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/plugins/test_plugins_p0.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/plugins/test_store.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/skills/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/skills/test_commands.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/skills/test_load.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/skills/test_merge.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/skills/test_skill_trust.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/skills/test_skills_json.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/skills/test_thread_inspector.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/smoke_tests/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/smoke_tests/conftest.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/smoke_tests/snapshots/system_prompt_interactive_local.md +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/smoke_tests/test_system_prompt.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test__tool_stream.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_acp.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_agent_friendly.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_approval_mode.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_args.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_auth_display.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_auth_store.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_auth_web_search_restart.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_charset.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_clipboard.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_coding_agent_metadata.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_cold_cache.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_command_registry.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_compact_tool.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_config_recursion_limit.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_configurable_model.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_configuration_resolution.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_configuration_resolver.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_cost_tracking.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_cursor_blink.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_cursor_style.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_debug.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_debug_buffer.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_dep_floor_check.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_diff_utils.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_doctor.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_editor.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_env_vars.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_event_bus.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_exception_handling.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_extras_info.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_file_ops.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_formatting.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_git.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_glm_5p2_profile.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_goal_criteria_client.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_goal_rubric.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_goal_state_notice.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_goal_state_persistence.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_goal_tools.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_hatch_build.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_hooks.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_imports.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_input_parsing.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_install_command.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_install_script.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_invocation.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_json_types.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_local_context.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_main.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_main_acp_mode.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_main_args.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_managed_tools.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_mcp_auth.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_mcp_config.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_mcp_disabled.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_mcp_login_service.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_mcp_oauth_ui.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_mcp_tools.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_media_utils.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_memory_guard.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_model_switch.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_non_interactive.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_notifications.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_offload.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_onboarding.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_openai_codex_integration.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_output.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_paths.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_reasoning_effort.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_reliable_rubric.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_remote_client.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_repository_bounds.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_resume_state.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_rubric_cli.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_sandbox_config.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_sandbox_factory.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_sandbox_provider.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_sandbox_registry.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_server.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_server_config.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_server_graph.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_server_helpers.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_server_manager.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_session_stats.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_sessions.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_shell_allow_list.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_skill_invocation.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_startup_blocking.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_startup_fast_paths.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_state_migration.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_subagents.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_terminal_capabilities.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_terminal_escape.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_terminal_progress_preference.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_theme.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_threads_resume.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_tool_catalog.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_tool_display.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_tracing.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_tracing_replicas.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_transcript_virtualization.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_ui.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_unicode_security.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_update_check.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/test_version.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tools/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tools/test_current_thread.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tools/test_fetch_url.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tools/test_tool_arg_schemas.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/modals/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/modals/plugin_manager/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/modals/test_cold_cache.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/test_subagent_stream.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/__init__.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_ask_user.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_auto_mode_notice.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_autocomplete.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_copy_spans.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_cwd_switch.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_diff.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_goal_review.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_history.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_inline_prompt.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_install_confirm.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_launch_init.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_links.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_loading.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_mcp_login_modal.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_mcp_reconnect.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_message_store.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_messages.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_notification_detail.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_restart_prompt.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_skill_trust_screen.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_startup_tip.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_status.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_subagent_panel.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_thread_agent_switch.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_thread_selector.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_tool_renderers.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_update_available.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_update_confirm.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_update_progress.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_welcome.py +0 -0
- {deepagents_code-0.1.59 → deepagents_code-0.1.60}/tests/unit_tests/tui/widgets/test_yolo_mode_notice.py +0 -0
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
# Deep Agents Code Changelog
|
|
4
4
|
|
|
5
|
+
## [0.1.60](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.59...deepagents-code==0.1.60) (2026-08-23)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- Added `editable` trace metadata ([#5737](https://github.com/langchain-ai/deepagents/issues/5737)) ([23b83ad](https://github.com/langchain-ai/deepagents/commit/23b83ad50f63d241d0069a3dc426d43b211adf2e)).
|
|
10
|
+
- Added shell command highlighting in the chat input ([#5675](https://github.com/langchain-ai/deepagents/issues/5675)) ([d711bc6](https://github.com/langchain-ai/deepagents/commit/d711bc61300090181dc89e3e116e8b343fb65425)).
|
|
11
|
+
- Made project `.env` loading configurable ([#5726](https://github.com/langchain-ai/deepagents/issues/5726)) ([995cad6](https://github.com/langchain-ai/deepagents/commit/995cad67519af294851282133f8c40f643807c88)).
|
|
12
|
+
- Unified notification center and settings ([#5698](https://github.com/langchain-ai/deepagents/issues/5698)) ([9767f42](https://github.com/langchain-ai/deepagents/commit/9767f420c622a31a7511c4601739534ddc6062a7)).
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
- Blocked dotenv git config injection keys ([#5723](https://github.com/langchain-ai/deepagents/issues/5723)) ([328f916](https://github.com/langchain-ai/deepagents/commit/328f9160e0f95a459be8ad57f76e7178b24a3ef8)).
|
|
17
|
+
- Persisted Auto approval mode between sessions and simplified Auto fallback copy ([#5665](https://github.com/langchain-ai/deepagents/issues/5665)) ([3ac059e](https://github.com/langchain-ai/deepagents/commit/3ac059e1574963fe216692642aa1b1a4044daaa9)), ([#5670](https://github.com/langchain-ai/deepagents/issues/5670)) ([42afcde](https://github.com/langchain-ai/deepagents/commit/42afcded97029070f393232778c84aaf3b69fb1c)).
|
|
18
|
+
- Fixed recognition of in-flight trace messages ([#5738](https://github.com/langchain-ai/deepagents/issues/5738)) ([f1d1f63](https://github.com/langchain-ai/deepagents/commit/f1d1f632812a85646d25ac2f3d2d7f39b65a0b49)).
|
|
19
|
+
- Increased the warm limit to 800 ([#5728](https://github.com/langchain-ai/deepagents/issues/5728)) ([f954cde](https://github.com/langchain-ai/deepagents/commit/f954cde37f1171adc2ec3f1516a0393bded47e82)).
|
|
20
|
+
- Improved text selection by supporting `Shift` + `click` to extend selections ([#5732](https://github.com/langchain-ai/deepagents/issues/5732)) ([e05931b](https://github.com/langchain-ai/deepagents/commit/e05931b3016ed3d1500df0c5b77402f457ee5686)).
|
|
21
|
+
- Polished notification settings by removing expand flicker and the trailing disclosure glyph ([#5734](https://github.com/langchain-ai/deepagents/issues/5734)) ([5397812](https://github.com/langchain-ai/deepagents/commit/5397812ad5f217cd84f871f121cf9ea8f3d63f4f)).
|
|
22
|
+
- Improved authentication footers with contextual actions ([#5690](https://github.com/langchain-ai/deepagents/issues/5690)) ([074a501](https://github.com/langchain-ai/deepagents/commit/074a5019e1f3edfd589614774958400d051e5fe1)).
|
|
23
|
+
- Standardized modal navigation hints ([#5699](https://github.com/langchain-ai/deepagents/issues/5699)) ([85c6833](https://github.com/langchain-ai/deepagents/commit/85c6833734a547e968221c1199a769d7aac69430)).
|
|
24
|
+
- Aligned wrapped debug snapshot values ([#5727](https://github.com/langchain-ai/deepagents/issues/5727)) ([1f74959](https://github.com/langchain-ai/deepagents/commit/1f7495949232fe2e3e3328b6ff9054c202002f95)).
|
|
25
|
+
|
|
5
26
|
## [0.1.59](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.58...deepagents-code==0.1.59) (2026-08-20)
|
|
6
27
|
|
|
7
28
|
### Features
|
|
@@ -33,7 +33,7 @@ aliases, descriptions, visibility, or hidden-command metadata.
|
|
|
33
33
|
| `/manual` | | Switch to Manual approval mode |
|
|
34
34
|
| `/mcp` | | Manage MCP servers and authentication |
|
|
35
35
|
| `/model` | | Switch models or edit model settings |
|
|
36
|
-
| `/notifications` | |
|
|
36
|
+
| `/notifications` | | Review notifications and configure warning settings |
|
|
37
37
|
| `/offload` | `/compact` | Summarize and offload older messages to free context |
|
|
38
38
|
| `/plugins` | | Manage plugins |
|
|
39
39
|
| `/quit` | `/q` | Exit app |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: deepagents-code
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.60
|
|
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://www.langchain.com/dcode
|
|
6
6
|
Project-URL: Documentation, https://docs.langchain.com/oss/deepagents/code/overview
|
|
@@ -260,7 +260,7 @@
|
|
|
260
260
|
- **Inside**: `config._create_model_from_class` validates `class_path` format (`module:ClassName`), imports the module via `importlib.import_module()`, and checks `issubclass(cls, BaseChatModel)` before instantiation.
|
|
261
261
|
- **Outside**: Module-level code in the imported module executes unconditionally during `import_module()`. The `issubclass` check only runs after import. Any side effects (file I/O, network calls, subprocess spawning) in the module's top-level scope execute before the type check.
|
|
262
262
|
- **Crossing mechanism**: `importlib.import_module(module_path)` in `config._create_model_from_class`.
|
|
263
|
-
- **Inside (dotenv)**: `config._load_dotenv` loads project and global `.env` values with `override=False` and drops shell startup / environment-hijack keys (`BASH_ENV`, `ENV`, and related) so a project `.env` cannot register a script that Bash would source at startup. The preview path (`_preview_dotenv_environ`) applies the same denylist so a dry-run config change cannot report a value a real reload would reject.
|
|
263
|
+
- **Inside (dotenv)**: `config._load_dotenv` loads project and global `.env` values with `override=False` and drops shell startup / environment-hijack keys (`BASH_ENV`, `ENV`, and related) so a project `.env` cannot register a script that Bash would source at startup. The denylist is best-effort: it enumerates environment variables known to reach a code-execution consumer (a shell's startup hook, the dynamic linker, an interpreter's startup path) and cannot claim completeness — any tool `dcode` spawns that honors an environment-driven execution hook not yet in the list remains a live vector until the key is added. The preview path (`_preview_dotenv_environ`) applies the same denylist so a dry-run config change cannot report a value a real reload would reject.
|
|
264
264
|
- **Outside (dotenv)**: All other `.env` keys are applied to the process environment, and any project file in the working directory (`.env`, `Makefile`, build scripts) can still influence execution. See T12.
|
|
265
265
|
|
|
266
266
|
#### TB12: Managed Config → Runtime
|
|
@@ -453,7 +453,7 @@
|
|
|
453
453
|
#### T12: Project `.env` Injects Shell Interpreter Startup Hooks
|
|
454
454
|
|
|
455
455
|
- **Flow**: DF10 (project `.env` → process environment) → bash subprocess startup (DF19)
|
|
456
|
-
- **Description**: `config._load_dotenv` discovers the nearest project `.env` by walking up from the working directory and applies its values to the process environment (`override=False`, so shell-exported values still win). Bash treats several environment variables as startup hooks — `BASH_ENV` and `ENV` name a file that is sourced when a non-interactive shell starts. Because Deep Agents Code runs its own local-context detection through Bash at startup (`local_context.build_detect_script`) and spawns shells for the `execute` tool, a project `.env` that sets one of these keys could run attacker-controlled scripts inside the `dcode` process *before* any model-requested tool call or HITL approval prompt. The broader trust boundary is that running `dcode` in a project directory lets that project influence the process environment.
|
|
456
|
+
- **Description**: `config._load_dotenv` discovers the nearest project `.env` by walking up from the working directory and applies its values to the process environment (`override=False`, so shell-exported values still win). Bash treats several environment variables as startup hooks — `BASH_ENV` and `ENV` name a file that is sourced when a non-interactive shell starts. Because Deep Agents Code runs its own local-context detection through Bash at startup (`local_context.build_detect_script`) and spawns shells for the `execute` tool, a project `.env` that sets one of these keys could run attacker-controlled scripts inside the `dcode` process *before* any model-requested tool call or HITL approval prompt. The broader trust boundary is that running `dcode` in a project directory lets that project influence the process environment. The mitigation is a key denylist (`config._DOTENV_DENIED_ENV_KEYS`) covering known execution-hook consumers (shell startup, dynamic linker, interpreter startup/paths, askpass hijack); it is a best-effort enumeration, not a closed set, so an execution hook consumed by some other spawned tool remains viable until its keys are added to the list.
|
|
457
457
|
- **Preconditions**: (1) User launches `dcode` in a directory containing an attacker-controlled `.env` (for example, a freshly cloned untrusted repository); (2) the `.env` sets a shell startup-hook key that is not already exported in the user's shell (dotenv uses `override=False`).
|
|
458
458
|
|
|
459
459
|
#### T13: First-Token Shell Allow-List Bypass via Interpreters/Wrappers
|
|
@@ -478,7 +478,7 @@
|
|
|
478
478
|
| 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) |
|
|
479
479
|
| Tool/function results | DF9, DF11 | T1 | Unicode warning on URL args; `markdownify` HTML conversion | Shared | Tool *results* pass to context without prompt-injection scan |
|
|
480
480
|
| 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 |
|
|
481
|
-
| 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;
|
|
481
|
+
| 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; dotenv denylist for execution-hook env keys and project-`.env` trust vars | User | Dotenv denylist is best-effort — execution-hook env keys consumed by tools not yet enumerated still reach subprocesses; `class_path` executes module code before type check; MCP env dict unfiltered; Auto classifier strength is a user choice with no floor enforced (T14) |
|
|
482
482
|
| Session restore | DF14 | T5 | OS file permissions; SQLite | Project | Unencrypted at rest |
|
|
483
483
|
| Server IPC (env vars) | DF18 | T6 | `ServerConfig` serialization; parent env passed to child | Project | Provider API keys flow to server subprocess; system prompt in env |
|
|
484
484
|
| Host environment | DF19, DF20 | T7 | Static script; exit code check; 30s timeout | Shared | Makefile content injected into system prompt without sanitization |
|
|
@@ -545,3 +545,4 @@ Threats that appear valid in isolation but fall outside project responsibility b
|
|
|
545
545
|
| 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 |
|
|
546
546
|
| 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 |
|
|
547
547
|
| 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 |
|
|
548
|
+
| 2026-08-21 | manual update | Clarified that the dotenv execution-hook denylist (`config._DOTENV_DENIED_ENV_KEYS`) is a best-effort enumeration of known code-execution consumers, not a closed set: TB11's inside-detail and T12's description now state this explicitly, and the Configuration input-coverage gap was reworded from the stale "project `.env` can set shell startup-hook vars" (denylisted since #4288) to the actual residual — execution-hook keys consumed by not-yet-enumerated tools still reach subprocesses |
|
|
@@ -14,7 +14,7 @@ from __future__ import annotations
|
|
|
14
14
|
import json
|
|
15
15
|
from typing import Annotated, Literal, NotRequired, assert_never, get_args
|
|
16
16
|
|
|
17
|
-
from pydantic import Field
|
|
17
|
+
from pydantic import AfterValidator, Field
|
|
18
18
|
from typing_extensions import TypedDict
|
|
19
19
|
|
|
20
20
|
QuestionType = Literal["text", "multiple_choice", "multi_select"]
|
|
@@ -155,6 +155,65 @@ def ask_user_answer_is_empty(answer: str, question_type: object) -> bool:
|
|
|
155
155
|
return not answer.strip()
|
|
156
156
|
|
|
157
157
|
|
|
158
|
+
def _validate_question_text(text: str) -> str:
|
|
159
|
+
"""Reject a `question` that is empty or all whitespace.
|
|
160
|
+
|
|
161
|
+
This is the only rule that *rejects* blank question text.
|
|
162
|
+
`messages._ask_user_question_count` also tests it, but degrades to a count
|
|
163
|
+
of zero instead of rejecting.
|
|
164
|
+
|
|
165
|
+
Do not reorder this annotation and the `Field` beside it. As the inner
|
|
166
|
+
annotation it runs before `min_length=1`, which therefore never rejects
|
|
167
|
+
anything — that constraint is kept only because it is what puts
|
|
168
|
+
`minLength: 1` in the JSON schema the model reads. Swapping the two moves
|
|
169
|
+
the empty-string rejection onto `min_length` and changes the error the
|
|
170
|
+
model sees from this function's message to `string_too_short`. A string
|
|
171
|
+
like `" "` would render as a visually blank prompt.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
text: The parsed `question` text to check.
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
The same `text`, unchanged.
|
|
178
|
+
|
|
179
|
+
Raises:
|
|
180
|
+
ValueError: If `text` has no non-whitespace character.
|
|
181
|
+
"""
|
|
182
|
+
if not text.strip():
|
|
183
|
+
msg = "question text must not be blank"
|
|
184
|
+
raise ValueError(msg)
|
|
185
|
+
return text
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def _validate_choice(choice: Choice) -> Choice:
|
|
189
|
+
"""Reject a choice whose `value` is blank.
|
|
190
|
+
|
|
191
|
+
A blank value would render as an unlabelled option the user can select but
|
|
192
|
+
whose answer reads as "no answer".
|
|
193
|
+
|
|
194
|
+
Attached to the item annotation inside `Question.choices`, not to `Choice`
|
|
195
|
+
itself, so `TypeAdapter(Choice)` does not apply it.
|
|
196
|
+
|
|
197
|
+
Callers must pass a parsed `Choice`. A missing `value` never reaches here —
|
|
198
|
+
it is a required key, so pydantic rejects it as `choices.N.value: Field
|
|
199
|
+
required` before the choice-level validators run. On a raw dict this would
|
|
200
|
+
raise `KeyError`, which is not a `ValidationError` and would halt the run.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
choice: The parsed `Choice` to check.
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
The same `choice`, unchanged.
|
|
207
|
+
|
|
208
|
+
Raises:
|
|
209
|
+
ValueError: If `value` is blank or whitespace-only.
|
|
210
|
+
"""
|
|
211
|
+
if not choice["value"].strip():
|
|
212
|
+
msg = f"choice has a blank 'value': {choice!r}"
|
|
213
|
+
raise ValueError(msg)
|
|
214
|
+
return choice
|
|
215
|
+
|
|
216
|
+
|
|
158
217
|
class Choice(TypedDict):
|
|
159
218
|
"""A single choice option for a multiple choice or multi-select question."""
|
|
160
219
|
|
|
@@ -173,10 +232,48 @@ class Choice(TypedDict):
|
|
|
173
232
|
]
|
|
174
233
|
|
|
175
234
|
|
|
235
|
+
def _validate_question(question: Question) -> Question:
|
|
236
|
+
"""Apply the cross-field rules of a single question.
|
|
237
|
+
|
|
238
|
+
These are the rules no single field type can express: choice questions need
|
|
239
|
+
a non-empty `choices` list, and non-choice questions must not define one.
|
|
240
|
+
|
|
241
|
+
`Literal` already rejects an unknown `type` and `strict=True` a non-boolean
|
|
242
|
+
`required` before this runs, so they are not re-checked here.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
question: The parsed `Question` to check.
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
The same `question`, unchanged.
|
|
249
|
+
|
|
250
|
+
Raises:
|
|
251
|
+
ValueError: If the question violates one of the rules above.
|
|
252
|
+
"""
|
|
253
|
+
question_type = question["type"]
|
|
254
|
+
question_text = question["question"]
|
|
255
|
+
choices = question.get("choices")
|
|
256
|
+
if question_type in CHOICE_QUESTION_TYPES:
|
|
257
|
+
if not choices:
|
|
258
|
+
msg = (
|
|
259
|
+
f"{question_type} question {question_text!r} requires a "
|
|
260
|
+
f"non-empty 'choices' list"
|
|
261
|
+
)
|
|
262
|
+
raise ValueError(msg)
|
|
263
|
+
elif choices:
|
|
264
|
+
msg = f"{question_type} question {question_text!r} must not define 'choices'"
|
|
265
|
+
raise ValueError(msg)
|
|
266
|
+
return question
|
|
267
|
+
|
|
268
|
+
|
|
176
269
|
class Question(TypedDict):
|
|
177
270
|
"""A question to ask the user."""
|
|
178
271
|
|
|
179
|
-
question: Annotated[
|
|
272
|
+
question: Annotated[
|
|
273
|
+
str,
|
|
274
|
+
AfterValidator(_validate_question_text),
|
|
275
|
+
Field(description="The question text to display.", min_length=1),
|
|
276
|
+
]
|
|
180
277
|
|
|
181
278
|
type: Annotated[
|
|
182
279
|
QuestionType,
|
|
@@ -196,7 +293,7 @@ class Question(TypedDict):
|
|
|
196
293
|
|
|
197
294
|
choices: NotRequired[
|
|
198
295
|
Annotated[
|
|
199
|
-
list[Choice],
|
|
296
|
+
list[Annotated[Choice, AfterValidator(_validate_choice)]],
|
|
200
297
|
Field(
|
|
201
298
|
description=(
|
|
202
299
|
"Options for 'multiple_choice' and 'multi_select' questions. "
|
|
@@ -231,14 +328,62 @@ class Question(TypedDict):
|
|
|
231
328
|
]
|
|
232
329
|
|
|
233
330
|
|
|
331
|
+
ValidatedQuestion = Annotated[Question, AfterValidator(_validate_question)]
|
|
332
|
+
"""A `Question` with its cross-field rules applied during pydantic parsing.
|
|
333
|
+
|
|
334
|
+
Only the cross-field `choices` rules are scoped to this alias. The field-level
|
|
335
|
+
rules on `Question.question` and on `Question.choices` are unconditional, so
|
|
336
|
+
they also apply wherever `Question` itself is pydantic-parsed — notably
|
|
337
|
+
`TypeAdapter(AskUserRequest)` in `tui.textual_adapter`, which re-validates the
|
|
338
|
+
interrupt payload client-side and re-raises on failure. Keep that in mind
|
|
339
|
+
before adding another field-level rule here.
|
|
340
|
+
|
|
341
|
+
Where a `ValueError` from one of these validators ends up depends on the path.
|
|
342
|
+
On the tool path it becomes a tool-call `ValidationError`, which `ToolNode`
|
|
343
|
+
turns into an error `ToolMessage` the model can correct and retry from. On the
|
|
344
|
+
client re-validation path there is no tool call and `textual_adapter` logs and
|
|
345
|
+
re-raises instead."""
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
def _validate_questions(questions: list[ValidatedQuestion]) -> list[ValidatedQuestion]:
|
|
349
|
+
"""Reject an empty `questions` list.
|
|
350
|
+
|
|
351
|
+
Per-question rules live on `ValidatedQuestion`; this covers the one rule
|
|
352
|
+
about the list itself. Attached both to the tool's `questions` parameter
|
|
353
|
+
and to `AskUserRequest.questions`, so the client re-validation boundary
|
|
354
|
+
rejects an empty list too — `AskUserMenu([])` would otherwise build a
|
|
355
|
+
titled prompt with no question widgets and nothing focusable.
|
|
356
|
+
|
|
357
|
+
Args:
|
|
358
|
+
questions: The parsed `questions` argument to check.
|
|
359
|
+
|
|
360
|
+
Returns:
|
|
361
|
+
The same `questions`, unchanged.
|
|
362
|
+
|
|
363
|
+
Raises:
|
|
364
|
+
ValueError: If the list is empty.
|
|
365
|
+
"""
|
|
366
|
+
if not questions:
|
|
367
|
+
msg = "ask_user requires at least one question"
|
|
368
|
+
raise ValueError(msg)
|
|
369
|
+
return questions
|
|
370
|
+
|
|
371
|
+
|
|
234
372
|
class AskUserRequest(TypedDict):
|
|
235
373
|
"""Request payload sent via interrupt when asking the user questions."""
|
|
236
374
|
|
|
237
375
|
type: Literal["ask_user"]
|
|
238
376
|
"""Discriminator tag, always `'ask_user'`."""
|
|
239
377
|
|
|
240
|
-
questions: list[
|
|
241
|
-
"""Questions to present to the user.
|
|
378
|
+
questions: Annotated[list[ValidatedQuestion], AfterValidator(_validate_questions)]
|
|
379
|
+
"""Questions to present to the user.
|
|
380
|
+
|
|
381
|
+
`ValidatedQuestion` rather than `Question`, and carrying
|
|
382
|
+
`_validate_questions`, so every rule the tool applies also applies where
|
|
383
|
+
`tui.textual_adapter` re-validates this payload. A choice question with no
|
|
384
|
+
`choices` would otherwise reach the client and degrade to a text box, and
|
|
385
|
+
an empty list would render a prompt with no questions in it.
|
|
386
|
+
"""
|
|
242
387
|
|
|
243
388
|
tool_call_id: str
|
|
244
389
|
"""ID of the originating tool call, used to route the response back."""
|
|
@@ -446,9 +591,10 @@ def format_ask_user_transcript(questions: list[Question], answers: list[str]) ->
|
|
|
446
591
|
|
|
447
592
|
Args:
|
|
448
593
|
questions: Questions that were asked. Callers must pass questions whose
|
|
449
|
-
`question` text is a non-empty string; `
|
|
450
|
-
enforces that before interrupting.
|
|
451
|
-
keeps a caller that skips validation
|
|
594
|
+
`question` text is a non-empty string; `_validate_question_text`,
|
|
595
|
+
attached to `Question.question`, enforces that before interrupting.
|
|
596
|
+
The empty default below only keeps a caller that skips validation
|
|
597
|
+
from raising `KeyError`.
|
|
452
598
|
answers: Answers, positionally matched to `questions`. A missing entry
|
|
453
599
|
falls back to `ASK_USER_NO_ANSWER`; extra entries are dropped.
|
|
454
600
|
|
|
@@ -444,6 +444,19 @@ request. Also the escape hatch for hosts embedding this package that manage
|
|
|
444
444
|
process, so an embedder that starts its own would otherwise race this one.
|
|
445
445
|
"""
|
|
446
446
|
|
|
447
|
+
READ_PROJECT_DOTENV = "DEEPAGENTS_CODE_READ_PROJECT_DOTENV"
|
|
448
|
+
"""Toggle loading the *project* `.env` (the one found walking up from cwd).
|
|
449
|
+
|
|
450
|
+
Enabled by default, preserving the historical behavior of applying the nearest
|
|
451
|
+
project `.env` to the process environment (`override=False`, shell exports
|
|
452
|
+
win). Set to a falsy value (`0`, `false`, `no`, `off`) — or `[startup]`
|
|
453
|
+
`read_project_dotenv = false` in config.toml — to skip the project file
|
|
454
|
+
entirely, as defense-in-depth against a cloned repo whose `.env` carries
|
|
455
|
+
hostile values the dotenv denylist does not yet enumerate. The global
|
|
456
|
+
`~/.deepagents/.env` is unaffected. This is user-controlled process env, not a
|
|
457
|
+
repo file, so a project `.env` cannot disable itself.
|
|
458
|
+
"""
|
|
459
|
+
|
|
447
460
|
RECURSION_LIMIT = "DEEPAGENTS_CODE_RECURSION_LIMIT"
|
|
448
461
|
"""Override the main agent's LangGraph `recursion_limit` (graph step budget).
|
|
449
462
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
r"""Runtime patches over Textual internals, imported for side effect.
|
|
2
2
|
|
|
3
|
-
This module hosts
|
|
3
|
+
This module hosts six independent best-effort patches over private Textual
|
|
4
4
|
APIs. Each guards its own import/assignment and degrades to stock Textual
|
|
5
5
|
behavior (logging a warning) if the targeted internals move, so they have
|
|
6
6
|
separate lifecycles — do not delete the whole file when only one lands
|
|
@@ -42,7 +42,23 @@ upstream.
|
|
|
42
42
|
drag) to word boundaries. No upstream issue tracks this yet, so it has
|
|
43
43
|
no removal criterion — it stays until Textual grows native word select.
|
|
44
44
|
|
|
45
|
-
4.
|
|
45
|
+
4. Shift-click selection extension. Stock Textual replaces an existing text
|
|
46
|
+
selection on every mouse press, so Shift+click cannot move the active end
|
|
47
|
+
of a drag-selected range. The patch preserves the original selection anchor
|
|
48
|
+
and applies the click as its new end. No upstream issue tracks this yet.
|
|
49
|
+
|
|
50
|
+
Known terminal limitation: this only works when the terminal delivers the
|
|
51
|
+
modified click to the app. Ghostty binds Shift+click to its own selection
|
|
52
|
+
and never forwards the event while mouse reporting is active, so
|
|
53
|
+
Shift+click is a no-op there (users can `keybind = shift+click=unbind` to
|
|
54
|
+
opt out). iTerm2, kitty, and WezTerm forward it with the shift modifier
|
|
55
|
+
bit set, which is what the patch keys on. If Shift+click "does nothing"
|
|
56
|
+
for a user, check terminal delivery first — e.g. run
|
|
57
|
+
`printf '\e[?1003h\e[?1006h'; cat -v` and confirm Shift+click prints a
|
|
58
|
+
`^[[<;...;4M`-style sequence (the `4` is the shift bit) — before digging
|
|
59
|
+
into this patch.
|
|
60
|
+
|
|
61
|
+
5. Detached-widget hit filtering. The compositor keeps reporting a widget as
|
|
46
62
|
visible for a few event-loop iterations after it leaves the DOM, which
|
|
47
63
|
`Markdown.update` (and therefore the `MarkdownStream` that drives every
|
|
48
64
|
streaming assistant message) does constantly. `Screen._forward_event`
|
|
@@ -51,7 +67,7 @@ upstream.
|
|
|
51
67
|
crashes the app with `AttributeError: 'NoneType' object has no attribute
|
|
52
68
|
'region'`. Tracked in Textualize/textual#6643; remove when that lands.
|
|
53
69
|
|
|
54
|
-
|
|
70
|
+
6. Diff-gutter exclusion from selections. Textual paints the selection
|
|
55
71
|
highlight from the geometry stored in `Screen.selections`, so excluding
|
|
56
72
|
a diff row's decorative gutter (line number, `+`/`-` marker) only in
|
|
57
73
|
`Widget.get_selection` would copy the right text while still highlighting
|
|
@@ -447,6 +463,97 @@ else:
|
|
|
447
463
|
)
|
|
448
464
|
|
|
449
465
|
|
|
466
|
+
try:
|
|
467
|
+
from textual import events as _shift_events
|
|
468
|
+
from textual.screen import Screen as _ShiftScreen
|
|
469
|
+
from textual.selection import SelectEnd, SelectStart, SelectState
|
|
470
|
+
|
|
471
|
+
_original_forward_event_with_shift = _ShiftScreen._forward_event
|
|
472
|
+
except (ImportError, AttributeError) as exc: # pragma: no cover - defensive
|
|
473
|
+
logger.warning(
|
|
474
|
+
"Textual Shift+click selection patch skipped (textual %s): %s",
|
|
475
|
+
_textual_version,
|
|
476
|
+
exc,
|
|
477
|
+
)
|
|
478
|
+
else:
|
|
479
|
+
|
|
480
|
+
def _shift_click_anchor(screen: Screen, event: Event) -> SelectState | None:
|
|
481
|
+
# When this returns None the press falls through to stock Textual,
|
|
482
|
+
# which starts a fresh selection — indistinguishable from the event
|
|
483
|
+
# never arriving. Before debugging the branches below, confirm the
|
|
484
|
+
# terminal forwarded a shift-modified click at all (see the module
|
|
485
|
+
# docstring's patch 4 note); terminals like Ghostty consume Shift+click
|
|
486
|
+
# locally, so `event.shift` never becomes True here.
|
|
487
|
+
if (
|
|
488
|
+
not isinstance(event, _shift_events.MouseDown)
|
|
489
|
+
or not event.shift
|
|
490
|
+
or screen.app.mouse_captured
|
|
491
|
+
or not screen.selections
|
|
492
|
+
):
|
|
493
|
+
return None
|
|
494
|
+
select_state = screen._select_state
|
|
495
|
+
if select_state is None or select_state.end is None:
|
|
496
|
+
return None
|
|
497
|
+
content_widget = select_state.start.content_widget
|
|
498
|
+
if content_widget is not None and not content_widget.is_attached:
|
|
499
|
+
return None
|
|
500
|
+
return select_state if select_state.is_attached_to_dom() else None
|
|
501
|
+
|
|
502
|
+
def _rebase_anchor_scroll(anchor_start: SelectStart) -> SelectStart:
|
|
503
|
+
# `SelectStart.pointer_start_offset` adds the scroll travelled since
|
|
504
|
+
# the drag began, which tracks the viewport rather than the anchored
|
|
505
|
+
# text. That is harmless mid-drag, but a Shift+click can arrive many
|
|
506
|
+
# rows after the container scrolled — the transcript auto-scrolls while
|
|
507
|
+
# a message streams — leaving the anchor pointing at whatever text now
|
|
508
|
+
# occupies its old screen row. Fold the drift into the pointer delta
|
|
509
|
+
# and re-base against the current scroll offset, so the anchor stays on
|
|
510
|
+
# its original text.
|
|
511
|
+
container = anchor_start.container
|
|
512
|
+
drift = container.scroll_offset - anchor_start.container_initial_scroll_offset
|
|
513
|
+
return SelectStart(
|
|
514
|
+
container,
|
|
515
|
+
anchor_start.container_pointer_delta - drift,
|
|
516
|
+
anchor_start.container_initial_offset,
|
|
517
|
+
container.scroll_offset,
|
|
518
|
+
content_widget=anchor_start.content_widget,
|
|
519
|
+
content_offset=anchor_start.content_offset,
|
|
520
|
+
)
|
|
521
|
+
|
|
522
|
+
def _extend_selection_to_click(
|
|
523
|
+
screen: Screen,
|
|
524
|
+
anchor: SelectState | None,
|
|
525
|
+
event: _shift_events.MouseDown,
|
|
526
|
+
) -> None:
|
|
527
|
+
click_state = screen._select_state
|
|
528
|
+
if anchor is None or click_state is None:
|
|
529
|
+
return
|
|
530
|
+
click = click_state.start
|
|
531
|
+
# Stock Textual clears the selection when a MouseUp lands on the
|
|
532
|
+
# offset of its MouseDown. Forget the offset so the Shift+click's own
|
|
533
|
+
# MouseUp leaves the extension we install below alone.
|
|
534
|
+
screen._mouse_down_offset = None
|
|
535
|
+
screen._select_state = SelectState(
|
|
536
|
+
event.screen_offset,
|
|
537
|
+
_rebase_anchor_scroll(anchor.start),
|
|
538
|
+
SelectEnd(click.container, click.content_widget, click.content_offset),
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
def _forward_event_with_shift_select(self: Screen, event: Event) -> None:
|
|
542
|
+
shift_anchor = _shift_click_anchor(self, event)
|
|
543
|
+
_original_forward_event_with_shift(self, event)
|
|
544
|
+
if isinstance(event, _shift_events.MouseDown):
|
|
545
|
+
_extend_selection_to_click(self, shift_anchor, event)
|
|
546
|
+
|
|
547
|
+
try:
|
|
548
|
+
_ShiftScreen._forward_event = _forward_event_with_shift_select # ty: ignore[invalid-assignment]
|
|
549
|
+
except (AttributeError, TypeError) as exc: # pragma: no cover - defensive
|
|
550
|
+
logger.warning(
|
|
551
|
+
"Textual Shift+click selection patch assignment rejected (textual %s): %s",
|
|
552
|
+
_textual_version,
|
|
553
|
+
exc,
|
|
554
|
+
)
|
|
555
|
+
|
|
556
|
+
|
|
450
557
|
try:
|
|
451
558
|
from textual.screen import Screen as _HitScreen
|
|
452
559
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Keep the `x-release-please-version` annotation — release-please uses it to
|
|
4
4
|
# bump `__version__` in sync with `pyproject.toml` on every release PR.
|
|
5
|
-
__version__ = "0.1.
|
|
5
|
+
__version__ = "0.1.60" # x-release-please-version
|
|
6
6
|
|
|
7
7
|
DOCS_URL = "https://docs.langchain.com/oss/python/deepagents/code"
|
|
8
8
|
"""URL for `deepagents-code` documentation."""
|
|
@@ -48,7 +48,6 @@ if TYPE_CHECKING:
|
|
|
48
48
|
from langchain.agents.middleware import (
|
|
49
49
|
HumanInTheLoopMiddleware,
|
|
50
50
|
InterruptOnConfig,
|
|
51
|
-
ToolErrorMiddleware,
|
|
52
51
|
)
|
|
53
52
|
from langchain.agents.middleware.types import AgentMiddleware, ToolCallRequest
|
|
54
53
|
from langchain.tools import (
|
|
@@ -70,7 +69,6 @@ from deepagents_code._repository_bounds import (
|
|
|
70
69
|
REPOSITORY_TOOL_NAMES,
|
|
71
70
|
RepositoryBounds,
|
|
72
71
|
)
|
|
73
|
-
from deepagents_code._tool_errors import ToolArgumentError
|
|
74
72
|
from deepagents_code.approval_mode import (
|
|
75
73
|
ApprovalMode,
|
|
76
74
|
aread_approval_mode_from_store,
|
|
@@ -178,47 +176,6 @@ def _get_harness_tool_descriptions(
|
|
|
178
176
|
return dict(_harness_profile_for_model(model, None).tool_description_overrides)
|
|
179
177
|
|
|
180
178
|
|
|
181
|
-
# Tools that raise `ToolArgumentError` on model-authored arguments. The name
|
|
182
|
-
# filter is a second gate only: recovery keys off the exception type, so a
|
|
183
|
-
# different error from one of these tools still halts the run.
|
|
184
|
-
#
|
|
185
|
-
# `read_file` is deliberately absent. It catches its own argument errors and
|
|
186
|
-
# returns an error `ToolMessage` already. The only `ValueError`s that escape it
|
|
187
|
-
# come from backend invariants the model cannot fix, and the SDK raises those
|
|
188
|
-
# on purpose to stop a backend from silently skipping unshown source lines.
|
|
189
|
-
_TOOL_ARG_VALIDATION_TOOLS: tuple[str, ...] = ("ask_user",)
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
def _tool_arg_validation_on_error(
|
|
193
|
-
exc: Exception, request: ToolCallRequest
|
|
194
|
-
) -> str | None:
|
|
195
|
-
"""Convert a `ToolArgumentError` into a model-correctable message.
|
|
196
|
-
|
|
197
|
-
`ToolErrorMiddleware` re-raises `GraphBubbleUp` before it calls this, so
|
|
198
|
-
interrupts and parent commands never arrive here.
|
|
199
|
-
|
|
200
|
-
Args:
|
|
201
|
-
exc: Exception raised during tool execution.
|
|
202
|
-
request: The tool call request that failed.
|
|
203
|
-
|
|
204
|
-
Returns:
|
|
205
|
-
A message naming the tool and the validation detail, so the model can
|
|
206
|
-
fix its input and retry. `None` for any other exception, so
|
|
207
|
-
unexpected errors propagate and halt the run.
|
|
208
|
-
"""
|
|
209
|
-
if isinstance(exc, ToolArgumentError):
|
|
210
|
-
# The run no longer fails, so this is the only record that the model
|
|
211
|
-
# sent bad arguments. `exc_info` keeps the raise site for debugging.
|
|
212
|
-
logger.warning(
|
|
213
|
-
"Recovered tool argument error from %s: %s",
|
|
214
|
-
request.tool_call["name"],
|
|
215
|
-
exc,
|
|
216
|
-
exc_info=exc,
|
|
217
|
-
)
|
|
218
|
-
return f"`{request.tool_call['name']}` failed: {exc}. Fix the input and retry."
|
|
219
|
-
return None
|
|
220
|
-
|
|
221
|
-
|
|
222
179
|
def _inject_fs_tools_into_subagents(
|
|
223
180
|
custom_subagents: list[SubAgent | CompiledSubAgent],
|
|
224
181
|
*,
|
|
@@ -2554,9 +2511,6 @@ def create_cli_agent(
|
|
|
2554
2511
|
from deepagents_code.hooks.server_middleware import ServerHooksMiddleware
|
|
2555
2512
|
|
|
2556
2513
|
hooks_cwd = Path(effective_cwd) if effective_cwd is not None else Path.cwd()
|
|
2557
|
-
# No `ToolErrorMiddleware` here. `_TOOL_ARG_VALIDATION_TOOLS` covers
|
|
2558
|
-
# `ask_user` only, and subagents never get `AskUserMiddleware`, so an
|
|
2559
|
-
# instance on this stack could never fire.
|
|
2560
2514
|
middleware.append(
|
|
2561
2515
|
ServerHooksMiddleware(
|
|
2562
2516
|
cwd=hooks_cwd,
|
|
@@ -3130,20 +3084,6 @@ def create_cli_agent(
|
|
|
3130
3084
|
rubric_kwargs["max_iterations"] = rubric_max_iterations
|
|
3131
3085
|
agent_middleware.append(ReliableRubricMiddleware(**rubric_kwargs))
|
|
3132
3086
|
|
|
3133
|
-
# Turn a `ToolArgumentError` into a recoverable error `ToolMessage` instead
|
|
3134
|
-
# of a fatal run error. Any other exception propagates and halts the run.
|
|
3135
|
-
#
|
|
3136
|
-
# This must stay last. `_chain_tool_call_wrappers` composes the list first
|
|
3137
|
-
# to outermost, so anything appended after this would run inside the
|
|
3138
|
-
# handler. `ServerHooksMiddleware` keeps a plain `ValueError` fatal on
|
|
3139
|
-
# purpose: it means the client answered a different request. Catching that
|
|
3140
|
-
# here would report a hook fault to the model as its own bad tool input.
|
|
3141
|
-
agent_middleware.append(
|
|
3142
|
-
ToolErrorMiddleware(
|
|
3143
|
-
_tool_arg_validation_on_error, tools=list(_TOOL_ARG_VALIDATION_TOOLS)
|
|
3144
|
-
)
|
|
3145
|
-
)
|
|
3146
|
-
|
|
3147
3087
|
# Create the agent
|
|
3148
3088
|
all_subagents: list[SubAgent | CompiledSubAgent | AsyncSubAgent] = [
|
|
3149
3089
|
*custom_subagents,
|