deepagents-code 0.1.51__tar.gz → 0.1.52__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.51 → deepagents_code-0.1.52}/CHANGELOG.md +17 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/COMMANDS.md +1 -1
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/HOOKS.md +19 -2
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/PKG-INFO +2 -2
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/THREAT_MODEL.md +20 -3
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_build_info.py +1 -1
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_cli_context.py +32 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_constants.py +3 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_env_vars.py +68 -6
- deepagents_code-0.1.52/deepagents_code/_markdown.py +26 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_server_config.py +14 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_version.py +1 -1
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/agent.py +38 -25
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/app.py +565 -61
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/auto_mode.py +474 -56
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/commands/config.py +13 -1
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/launch/server_manager.py +8 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/non_interactive.py +32 -5
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/command_registry.py +12 -3
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/config.py +109 -10
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/config_manifest.py +182 -8
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/configurable_model.py +4 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/cost_tracking.py +211 -3
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/engine.py +6 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/loading.py +191 -33
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/manager.py +38 -12
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/models/domain.py +0 -2
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/runtime.py +18 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/server_middleware.py +18 -5
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/snapshot.py +27 -9
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/trust.py +83 -27
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/main.py +145 -6
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/offload_middleware.py +175 -1
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/onboarding.py +17 -4
- deepagents_code-0.1.52/deepagents_code/plugins/adapters/hooks.py +157 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/manifest.py +44 -3
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/models.py +9 -4
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/server_graph.py +1 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/modals/plugin_manager/content.py +10 -9
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/modals/plugin_manager/models.py +6 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/modals/plugin_manager/state.py +4 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/textual_adapter.py +40 -7
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/approval.py +96 -16
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/auto_mode_notice.py +81 -5
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/cwd_switch.py +81 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/model_selector.py +99 -51
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/startup_tip.py +2 -1
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/status.py +6 -1
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/ui.py +8 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/pyproject.toml +2 -2
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/conftest.py +20 -2
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_configuration.py +15 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_engine.py +3 -3
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_manager.py +2 -9
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_server_lifecycle.py +55 -6
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_trust.py +217 -13
- deepagents_code-0.1.52/tests/unit_tests/plugins/test_plugin_hooks.py +150 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_agent.py +135 -6
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_app.py +667 -30
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_auto_mode.py +1124 -101
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_compact_tool.py +70 -1
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_config.py +92 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_config_manifest.py +494 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_configurable_model.py +26 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_cost_tracking.py +398 -1
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_debug_console.py +25 -2
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_main.py +92 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_main_acp_mode.py +24 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_main_args.py +95 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_model_config.py +2 -2
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_non_interactive.py +56 -6
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_onboarding.py +34 -7
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_reload.py +68 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_server_config.py +43 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_server_graph.py +1 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/modals/plugin_manager/test_structure.py +1 -1
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/test_textual_adapter.py +156 -10
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_approval.py +259 -15
- deepagents_code-0.1.52/tests/unit_tests/tui/widgets/test_auto_mode_notice.py +100 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_model_selector.py +221 -49
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_status.py +36 -8
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/uv.lock +6 -6
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/.gitignore +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/AGENTS.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/ARCHITECTURE.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/DEVELOPMENT.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/LICENSE +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/Makefile +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/README.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/__main__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_ask_user_types.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_debug.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_debug_buffer.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_fake_models.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_git.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_glm_5p2_profile.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_invocation.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_paths.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_repository_bounds.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_session_stats.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_startup_error.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_testing_models.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_textual_patches.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/_tool_stream.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/app.tcss +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/approval_mode.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/ask_user.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/auth_display.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/auth_store.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/built_in_skills/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/built_in_skills/deepagents-thread-inspector/SKILL.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/built_in_skills/deepagents-thread-inspector/scripts/inspect_sessions.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/built_in_skills/remember/SKILL.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/built_in_skills/skill-creator/SKILL.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/commands/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/commands/auth.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/commands/extras.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/commands/mcp.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/commands/tools.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/launch/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/launch/server.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/client/remote_client.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/clipboard.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/default_agent_prompt.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/doctor.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/editor.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/event_bus.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/extras_info.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/file_ops.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/formatting.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/goal_rubric.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/goal_state_notice.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/goal_tools.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/capabilities.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/client.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/client_lifecycle.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/context.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/env.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/envelope.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/interrupt.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/legacy.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/migration.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/models/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/models/adapters.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/models/config.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/models/transport.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/models/wire.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/permissions.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/presenter.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/projection.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/reducer.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/runner.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/tools.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/transcript.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/hooks/validate_terminal_sequence.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/input.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/integrations/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/integrations/openai_codex.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/integrations/sandbox_config.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/integrations/sandbox_factory.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/integrations/sandbox_provider.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/integrations/sandbox_registry.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/iterm_cursor_guide.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/json_types.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/local_context.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/managed_tools.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_auth.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_config.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_disabled.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_login_service.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_oauth_ui.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_providers/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_providers/_registry.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_providers/base.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_providers/github.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_providers/slack.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/mcp_tools.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/media_utils.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/memory_guard.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/model_config.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/notifications.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/offload.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/output.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/paste_collapse.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/_json.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/adapters/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/adapters/mcp.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/adapters/skills.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/adapters/skills_middleware.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/commands_cli.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/discovery.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/marketplace.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/store.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/plugins/substitution.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/project_utils.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/py.typed +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/reasoning_effort.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/reliable_rubric.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/resume_state.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/sessions.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/skills/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/skills/commands.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/skills/invocation.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/skills/load.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/skills/merge.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/skills/trust.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/state_migration.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/subagents.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/system_prompt.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/terminal_capabilities.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/terminal_escape.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/theme.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tool_catalog.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tool_display.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tools.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/modals/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/modals/plugin_manager/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/modals/plugin_manager/plugin_manager.tcss +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/modals/plugin_manager/tabs.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/screens/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/_copy_spans.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/_inline_prompt.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/_js_eval_display.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/_links.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/_paste_textarea.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/agent_selector.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/ask_user.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/auth.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/autocomplete.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/chat_input.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/codex_auth.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/debug_console.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/diff.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/effort_selector.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/goal_review.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/goal_status.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/history.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/install_confirm.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/launch_init.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/loading.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/mcp_login.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/mcp_reconnect.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/mcp_viewer.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/message_store.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/messages.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/notification_center.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/notification_detail.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/notification_settings.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/plugin_reload.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/restart_prompt.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/skill_trust.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/subagent_panel.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/theme_selector.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/thread_agent_switch.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/thread_selector.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/tool_renderers.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/tool_widgets.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/update_available.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/update_confirm.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/update_progress.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/welcome.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/tui/widgets/yolo_mode_notice.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/unicode_security.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/deepagents_code/update_check.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/examples/skills/arxiv-search/SKILL.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/examples/skills/arxiv-search/arxiv_search.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/examples/skills/langgraph-docs/SKILL.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/examples/skills/skill-creator/SKILL.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/examples/skills/web-research/SKILL.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/hatch_build.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/images/tui.png +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/scripts/check_imports.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/scripts/debug_server.sh +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/scripts/generate_commands_catalog.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/scripts/install.sh +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/README.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/benchmarks/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/benchmarks/test_local_context_benchmarks.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/conftest.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/test_acp_mode.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/test_auto_approve_remote.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/test_compact_resume.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/test_goal_criteria_remote.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/test_offload_server_side.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/test_sandbox_factory.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/integration_tests/test_sandbox_operations.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/client/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/client/commands/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/client/commands/test_auth.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/client/commands/test_extras.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/client/commands/test_mcp.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/client/commands/test_tools.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/data/coding_agent_v1_validator.json +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/models/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/models/test_models.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_client_lifecycle.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_execution.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_presenter.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/hooks/test_transcript.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/plugins/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/plugins/test_marketplace.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/plugins/test_plugins_p0.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/plugins/test_store.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/skills/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/skills/test_commands.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/skills/test_load.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/skills/test_merge.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/skills/test_skill_trust.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/skills/test_skills_json.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/skills/test_thread_inspector.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/smoke_tests/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/smoke_tests/conftest.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/smoke_tests/snapshots/system_prompt_interactive_local.md +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/smoke_tests/test_system_prompt.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test__tool_stream.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_agent_friendly.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_approval_mode.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_args.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_ask_user_middleware.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_ask_user_types.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_auth_display.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_auth_store.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_auth_web_search_restart.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_charset.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_clipboard.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_coding_agent_metadata.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_command_registry.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_config_recursion_limit.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_cursor_blink.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_cursor_style.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_debug.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_debug_buffer.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_doctor.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_editor.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_end_to_end.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_env_vars.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_event_bus.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_exception_handling.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_extras_info.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_file_ops.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_formatting.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_git.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_glm_5p2_profile.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_goal_criteria_client.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_goal_rubric.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_goal_state_notice.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_goal_state_persistence.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_goal_tools.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_hatch_build.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_hooks.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_imports.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_input_parsing.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_install_command.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_install_script.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_invocation.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_json_types.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_local_context.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_managed_tools.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_mcp_auth.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_mcp_config.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_mcp_disabled.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_mcp_login_service.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_mcp_oauth_ui.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_mcp_tools.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_media_utils.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_memory_guard.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_model_switch.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_notifications.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_offload.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_openai_codex_integration.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_output.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_paths.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_reasoning_effort.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_reliable_rubric.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_remote_client.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_repository_bounds.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_resume_state.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_rubric_cli.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_sandbox_config.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_sandbox_factory.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_sandbox_provider.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_sandbox_registry.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_server.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_server_helpers.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_server_manager.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_session_stats.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_sessions.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_shell_allow_list.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_skill_invocation.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_startup_blocking.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_startup_fast_paths.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_state_migration.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_subagents.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_terminal_capabilities.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_terminal_escape.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_terminal_progress_preference.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_textual_patches.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_theme.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_threads_resume.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_tool_catalog.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_tool_display.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_tracing_replicas.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_transcript_virtualization.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_ui.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_unicode_security.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_update_check.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/test_version.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tools/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tools/test_current_thread.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tools/test_fetch_url.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tools/test_tool_arg_schemas.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/modals/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/modals/plugin_manager/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/test_subagent_stream.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/__init__.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_agent_selector.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_ask_user.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_auth_widgets.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_autocomplete.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_chat_input.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_copy_spans.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_cwd_switch.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_diff.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_goal_review.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_history.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_inline_prompt.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_install_confirm.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_launch_init.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_links.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_loading.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_mcp_login_modal.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_mcp_reconnect.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_mcp_viewer.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_message_store.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_messages.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_notification_center.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_notification_detail.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_notification_settings.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_plugin_reload.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_restart_prompt.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_skill_trust_screen.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_startup_tip.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_subagent_panel.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_thread_agent_switch.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_thread_selector.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_tool_renderers.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_update_available.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_update_confirm.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_update_progress.py +0 -0
- {deepagents_code-0.1.51 → deepagents_code-0.1.52}/tests/unit_tests/tui/widgets/test_welcome.py +0 -0
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
# Deep Agents Code Changelog
|
|
4
4
|
|
|
5
|
+
## [0.1.52](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.51...deepagents-code==0.1.52) (2026-08-04)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- Hooks v2 is now generally available, with support for loading hooks from installed plugins. ([#5307](https://github.com/langchain-ai/deepagents/issues/5307), [#5198](https://github.com/langchain-ai/deepagents/issues/5198))
|
|
10
|
+
- Auto approval classifier configuration now supports selecting the classifier model and setting a review timeout. ([#5205](https://github.com/langchain-ai/deepagents/issues/5205), [#5302](https://github.com/langchain-ai/deepagents/issues/5302))
|
|
11
|
+
- HITL rejection reasons are now framed for the model, and the approval menu makes reject-with-feedback easier to discover. ([#5259](https://github.com/langchain-ai/deepagents/issues/5259), [#5260](https://github.com/langchain-ai/deepagents/issues/5260))
|
|
12
|
+
- Added a tri-state `DEEPAGENTS_CODE_ONBOARDING` environment variable. ([#5301](https://github.com/langchain-ai/deepagents/issues/5301))
|
|
13
|
+
- The `/model` footer Ctrl+N hint now follows the current display mode. ([#5247](https://github.com/langchain-ai/deepagents/issues/5247))
|
|
14
|
+
- The price catalog now refreshes hourly in the background. ([#5264](https://github.com/langchain-ai/deepagents/issues/5264))
|
|
15
|
+
- Updated recommendations to include DeepSeek V4 Flash 0731. ([#5244](https://github.com/langchain-ai/deepagents/issues/5244))
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
- Fixed several Hooks v2 lifecycle issues: session-end teardown is now bounded, hooks refresh after cwd switches, malformed hook resumes are handled, hook stops surface without agent errors, and unused `SessionEndCause` members were removed. ([#5248](https://github.com/langchain-ai/deepagents/issues/5248), [#5249](https://github.com/langchain-ai/deepagents/issues/5249), [#5233](https://github.com/langchain-ai/deepagents/issues/5233), [#5276](https://github.com/langchain-ai/deepagents/issues/5276), [#5240](https://github.com/langchain-ai/deepagents/issues/5240))
|
|
20
|
+
- `PreCompact` now fires before auto-compaction. ([#5277](https://github.com/langchain-ai/deepagents/issues/5277))
|
|
21
|
+
|
|
5
22
|
## [0.1.51](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.50...deepagents-code==0.1.51) (2026-07-31)
|
|
6
23
|
|
|
7
24
|
### Features
|
|
@@ -14,7 +14,7 @@ aliases, descriptions, visibility, or hidden-command metadata.
|
|
|
14
14
|
| --- | --- | --- |
|
|
15
15
|
| `/agents` | | Browse and switch between available agents |
|
|
16
16
|
| `/auth` | `/connect` | Connect and manage provider and service credentials |
|
|
17
|
-
| `/auto` | | Switch to Auto approval mode |
|
|
17
|
+
| `/auto` | | Switch to Auto approval mode, or pick its classifier model for this session |
|
|
18
18
|
| `/auto-update` | | Turn automatic updates on or off |
|
|
19
19
|
| `/changelog` | | Open the changelog in a browser |
|
|
20
20
|
| `/clear` | | Clear the chat and start a new thread |
|
|
@@ -10,8 +10,9 @@ Hooks are user-configured shell commands that run at agent lifecycle events. Eac
|
|
|
10
10
|
| --- | --- | --- |
|
|
11
11
|
| User | `~/.deepagents/hooks.json` | Always (when the file exists) |
|
|
12
12
|
| Project | `{project_root}/.deepagents/hooks.json` | Only after workspace trust |
|
|
13
|
+
| Plugin | `hooks/hooks.json` inside an installed plugin | Whenever the plugin is enabled |
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
Matcher groups are applied project first, then user, then plugin. Precedence decides whose answer wins, not who runs: every matching handler for an event runs concurrently, and their results are then reduced in that order, so the first handler that stops processing decides the event. A plugin handler still executes even when a project or user handler stops the event, so treat a plugin's side effects as unconditional.
|
|
15
16
|
|
|
16
17
|
### Project workspace trust
|
|
17
18
|
|
|
@@ -23,6 +24,22 @@ Project-scoped hooks can execute arbitrary commands from the repository. Before
|
|
|
23
24
|
- Denying skips project hooks for the session and continues with user hooks only.
|
|
24
25
|
- Headless / CI runs do not prompt; pass `--trust-project-hooks` to opt in for that run.
|
|
25
26
|
|
|
27
|
+
### Plugin hooks
|
|
28
|
+
|
|
29
|
+
A plugin contributes hooks from `hooks/hooks.json` in its root, from a `hooks` path in its `plugin.json` manifest, or from an inline manifest `hooks` object. The document uses exactly the same shape as a user or project `hooks.json`.
|
|
30
|
+
|
|
31
|
+
Installing and enabling the plugin is the consent gate — workspace trust governs project hooks only, so it neither grants nor withholds a plugin's hooks. Review a plugin before enabling it; the plugin manager lists the events each one hooks. Because the set of server-owned events is fixed when a session starts, newly enabled plugin hooks take effect after `/reload`.
|
|
32
|
+
|
|
33
|
+
Plugin handlers receive their plugin's path variables in the environment. Shell-form `command` handlers expand those variables normally; direct-exec `argv` handlers resolve them before launch. Quote variables in shell commands because installation paths may contain spaces:
|
|
34
|
+
|
|
35
|
+
| Variable | Value |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| `CLAUDE_PLUGIN_ROOT`, `PLUGIN_ROOT` | The plugin's root directory |
|
|
38
|
+
| `CLAUDE_PLUGIN_DATA`, `PLUGIN_DATA` | The plugin's writable data directory |
|
|
39
|
+
| `CLAUDE_PROJECT_DIR` | The project root |
|
|
40
|
+
|
|
41
|
+
For example, use `"command": "\"${CLAUDE_PLUGIN_ROOT}/scripts/format.sh\""`. Setting `argv` instead avoids shell quoting entirely because those handlers execute directly.
|
|
42
|
+
|
|
26
43
|
## Events and matchers
|
|
27
44
|
|
|
28
45
|
Each top-level key under `"hooks"` is an event name. Values are lists of matcher groups. A group may omit `matcher` (or use `"*"`) to match all values for that event's matcher field. Events with no matcher field reject non-wildcard matchers at load time.
|
|
@@ -33,7 +50,7 @@ Native tools are matched by their wire names (for example `execute` → `Bash`,
|
|
|
33
50
|
| --- | --- | --- | --- |
|
|
34
51
|
| `SessionStart` | client | `cause` | A session starts (`startup`, `resume`, `clear`, `compact`) |
|
|
35
52
|
| `UserPromptSubmit` | client | _(none)_ | The user submits a prompt |
|
|
36
|
-
| `SessionEnd` | client | `cause` | A session ends |
|
|
53
|
+
| `SessionEnd` | client | `cause` | A session ends (`clear`, `resume`, `prompt_input_exit`, `other`) |
|
|
37
54
|
| `PermissionRequest` | client | `tool_name` | The client is about to ask for tool permission |
|
|
38
55
|
| `Notification` | client | `notification_type` | A client lifecycle notification is emitted |
|
|
39
56
|
| `PreToolUse` | server | `tool_name` | Before a tool call runs |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepagents-code
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.52
|
|
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.9
|
|
32
32
|
Requires-Dist: deepagents==0.7.1
|
|
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.1
|
|
35
35
|
Requires-Dist: httpx<1.0.0,>=0.28.1
|
|
36
36
|
Requires-Dist: langchain-anthropic<2.0.0,>=1.5.3
|
|
37
37
|
Requires-Dist: langchain-google-genai<5.0.0,>=4.3.2
|
|
@@ -349,6 +349,7 @@
|
|
|
349
349
|
| T10 | DF24 | DC1 | MCP stdio subprocess env dict accepts arbitrary keys including `PATH`, `LD_PRELOAD`, `PYTHONPATH` without filtering | TB4 | Low | Verified | `mcp_tools._validate_server_config`, `mcp_tools._load_tools_from_config` |
|
|
350
350
|
| T12 | DF10 | — | Project `.env` sets shell startup-hook variables (`BASH_ENV`, `ENV`) that run attacker-controlled scripts when `dcode` spawns Bash, before any HITL approval | TB11 | High | Verified | `config._load_dotenv`, `local_context.build_detect_script` |
|
|
351
351
|
| T13 | DF7 | — | Configured shell allow-list checks only the first token, so an allow-listed interpreter/wrapper (`python3`, `bash`, `env`, `xargs`, …) runs arbitrary code via its arguments without approval in non-interactive mode | TB2 | Medium | Verified | `config.is_shell_command_allowed`, `config.contains_dangerous_patterns` |
|
|
352
|
+
| T14 | DF7, DF9 | — | A weaker model configured for the Auto approval classifier reviews gated actions less reliably, including untrusted text carried in tool arguments and file content | TB2 | Low | Verified | `auto_mode.AutoModeHITLMiddleware._classifier_model`, `config.resolve_auto_classifier_model`, `config_manifest.resolve_auto_classifier_timeout` |
|
|
352
353
|
|
|
353
354
|
### Threat Details
|
|
354
355
|
|
|
@@ -419,6 +420,13 @@
|
|
|
419
420
|
- **Mitigations**: (1) SHA-256 verified against the pinned hash table before move — a mismatch aborts the install and leaves `BIN_DIR` clean. (2) Network egress is limited to `github.com`. (3) Opt-out via `DEEPAGENTS_CODE_OFFLINE` for air-gapped environments, or `DEEPAGENTS_CODE_RIPGREP_INSTALLER=system` to defer to the OS package manager instead of the managed binary. (4) Pinned version + checksums are bumped in-tree, so a compromised upstream release is detected on the next Deep Agents Code release rather than silently propagating. (5) Atomic move-into-place avoids partial installs when concurrent CLI invocations race. (6) The eager install-script path is non-`sudo` (no system package manager is invoked in the default `managed` mode).
|
|
420
421
|
- **Preconditions**: User has not installed `rg` via their package manager, `DEEPAGENTS_CODE_OFFLINE` is unset, `DEEPAGENTS_CODE_RIPGREP_INSTALLER` is not `system`, and the host can reach `github.com`. The pinned SHA-256 in `RIPGREP_ASSETS` would need to be incorrect (a supply-chain compromise of the deepagents-code release) for a tampered binary to be installed.
|
|
421
422
|
|
|
423
|
+
#### T11b: Unpinned Pricing Catalog Fetched Hourly from a Mutable Upstream Ref
|
|
424
|
+
|
|
425
|
+
- **Flow**: Background daemon thread started by `cost_tracking._start_price_updater` on the first priced model request.
|
|
426
|
+
- **Description**: Unless opted out, Deep Agents Code starts `genai_prices.UpdatePrices`, which fetches `raw.githubusercontent.com/pydantic/genai-prices/refs/heads/main/prices/new_data/v2/data.json` every hour and installs it via `set_custom_snapshot`. The fetched catalog wholesale-replaces the pricing data bundled with the installed package for the life of the process. Unlike the ripgrep download (T11), the payload is **not** checksummed and the URL names a mutable branch ref rather than a pinned release, so the content can change between any two fetches. The blast radius is confined to displayed cost estimates — the catalog is parsed as data by `genai-prices`, never executed — but corrupt, regressed, or hostile upstream data silently changes every cost figure the user sees, and a catalog that omits providers makes lookups fail in a way that reads as "this model has no published rates."
|
|
427
|
+
- **Mitigations**: (1) Opt-out via `DEEPAGENTS_CODE_PRICES_AUTO_UPDATE=0` or `[update].prices_auto_update = false` in `config.toml`, or `DEEPAGENTS_CODE_OFFLINE` for air-gapped environments, all checked before the thread starts. (2) `cost_tracking._build_price_updater` refuses a fetched catalog listing fewer providers than the bundled one, so a truncated or mid-publish `data.json` cannot take effect. (3) A refused or failed fetch leaves the previously installed catalog in place rather than clearing it. (4) `genai-prices` rejects any payload that is not a JSON array of schema-valid providers. (5) Network egress is limited to `raw.githubusercontent.com`. (6) The updater is started lazily on first pricing, never at CLI startup, so a session that prices nothing makes no request.
|
|
428
|
+
- **Preconditions**: `DEEPAGENTS_CODE_PRICES_AUTO_UPDATE` is not falsy, `DEEPAGENTS_CODE_OFFLINE` is unset, the host can reach `raw.githubusercontent.com`, and at least one model request is priced. For tampered data to be installed, the upstream repository or the CDN path would need to be compromised **and** the substituted catalog would need to list at least as many providers as the bundled data.
|
|
429
|
+
|
|
422
430
|
#### T12: Project `.env` Injects Shell Interpreter Startup Hooks
|
|
423
431
|
|
|
424
432
|
- **Flow**: DF10 (project `.env` → process environment) → bash subprocess startup (DF19)
|
|
@@ -431,6 +439,12 @@
|
|
|
431
439
|
- **Description**: `is_shell_command_allowed` splits a command on `|`, `;`, `&&`, and `||`, then validates only the *first token* (`tokens[0]`) of each segment against the configured allow-list, after rejecting a set of dangerous patterns (`contains_dangerous_patterns`: command substitution `$(`/backticks, redirects, `${`, bare `$VAR`, background `&`). Because only the executable name is checked, any allow-listed general-purpose interpreter or command wrapper carries arbitrary behavior in its arguments: `python3 -c '<code>'`, `bash script.sh`, `sh -c '<code>'`, `env <cmd>`, `xargs <cmd>`, `uv run <cmd>`, and similar. A user who allow-lists such a program — reasonably believing they have restricted the agent to a "safe" tool — has effectively allowed unrestricted execution, and in headless `-x`/Auto mode those commands run without an approval prompt. This is the same class of weakness as T2 but applies to *normal, non-`all`* allow-lists. The allow-list is an ergonomic auto-approve heuristic, not a security boundary; textual command classification cannot robustly constrain execution.
|
|
432
440
|
- **Preconditions**: (1) User configures a shell allow-list (`--shell-allow-list` / `DEEPAGENTS_SHELL_ALLOW_LIST`) that includes an interpreter or wrapper; (2) non-interactive or Auto mode (interactive Manual mode still shows the human the literal command before it runs); (3) for the injected-command variant, successful prompt injection via DF8/DF9. The intended control is HITL approval; OS-native execution sandboxing would be the robust boundary the string allow-list cannot provide.
|
|
433
441
|
|
|
442
|
+
#### T14: Weaker Auto Classifier Model Weakens Action Review
|
|
443
|
+
|
|
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/deny, 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
|
+
- **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
|
+
|
|
434
448
|
---
|
|
435
449
|
|
|
436
450
|
## Input Source Coverage
|
|
@@ -438,10 +452,10 @@
|
|
|
438
452
|
| Input Source | Data Flows | Threats | Validation Points | Responsibility | Gaps |
|
|
439
453
|
|-----------------------|-----------------------|---------------|----------------------------------------------------------------------------|----------------|----------------------------------------------------------------------------------------------|
|
|
440
454
|
| User direct input | DF1, DF2 | None (TB1) | None — prompts accepted verbatim | User | No content filtering — intentional; HITL gates downstream tool calls |
|
|
441
|
-
| LLM output | DF6, DF7 | T1, T2, T3, T4, T13| HITL gate; shell allow-list; Unicode/URL warnings on tool args
|
|
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 and prior output (T14) |
|
|
442
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 |
|
|
443
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 |
|
|
444
|
-
| Configuration | DF10, DF12, DF15, DF23| T9, T10, T12 | Dotenv shell-env precedence; TOML schema; MCP schema + allow/deny lists; JSON structure check; `class_path` format check | User | Project `.env` can set shell startup-hook vars; `class_path` executes module code before type check; MCP env dict unfiltered |
|
|
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) |
|
|
445
459
|
| Session restore | DF14 | T5 | OS file permissions; SQLite | Project | Unencrypted at rest |
|
|
446
460
|
| 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 |
|
|
447
461
|
| Host environment | DF19, DF20 | T7 | Static script; exit code check; 30s timeout | Shared | Makefile content injected into system prompt without sanitization |
|
|
@@ -463,7 +477,7 @@ Threats that appear valid in isolation but fall outside project responsibility b
|
|
|
463
477
|
| Malicious MCP server injecting prompt instructions | Users configure MCP servers and explicitly trust project-level configs. Once trusted, MCP tool outputs are data from a system the user controls. | Interactive approval prompt + per-server allow/deny lists for project-level configs (`main._check_mcp_project_trust`, `model_config.load_mcp_server_trust_lists`). |
|
|
464
478
|
| LLM jailbreak / safety bypass | Model selection and safety configuration are user-controlled. The project routes prompts to the configured LLM but cannot guarantee model behavior. | Correctly routing prompts to the configured LLM; applying the system prompt from `agent.get_system_prompt`. |
|
|
465
479
|
| Sandbox provider security vulnerabilities | Daytona, LangSmith, Modal, Runloop, and AgentCore are third-party services. Their internal security is not this project's responsibility. | Correctly initializing sandbox sessions via `integrations.sandbox_factory.create_sandbox`. |
|
|
466
|
-
| Hook commands doing harmful things | User-scoped hooks (`~/.deepagents/hooks.json`)
|
|
480
|
+
| Hook commands doing harmful things | User-scoped hooks (`~/.deepagents/hooks.json`), project-scoped hooks (`.deepagents/hooks.json`, only after interactive workspace trust or `--trust-project-hooks`), and plugin-scoped hooks (`hooks/hooks.json` in a plugin the user installed and enabled) are intentionally configured commands. The payload is data-only (JSON on stdin). | Schema validation (`hooks.loading.load_hooks_config`); workspace trust for project hooks (versioned store under `~/.deepagents/.state/hooks_trust.json`; cancelling the trust prompt aborts startup); install plus enablement for plugin hooks, with declared events listed in the plugin manager; bounded execution with per-event default timeouts (600s for most events, 30s for `UserPromptSubmit`); sanitized subprocess environment with only the plugin's own path variables overlaid. |
|
|
467
481
|
| Async subagent traffic interception / MitM | Async subagents connect to user-configured LangGraph deployment URLs. The project does not control those endpoints or their TLS certificates. | Accepting URL/headers from user config and passing them to the LangGraph SDK (`agent.load_async_subagents`). |
|
|
468
482
|
| LangGraph dev server port enumeration / discovery | Discovering the local dev server port requires local access. Port scanning localhost is a general OS security concern, not a framework vulnerability. | Binding to `127.0.0.1` by default (`server._DEFAULT_HOST`); ephemeral server lifetime; OS-assigned ephemeral port (`server._EPHEMERAL_PORT`) is not predictable across runs. |
|
|
469
483
|
| `.env` file from parent directory changes app/API configuration | `config._find_dotenv_from_start_path` walks up the directory tree to find `.env` files. Discovering ordinary configuration values (API keys, `DEEPAGENTS_CODE_*` settings) this way is standard `python-dotenv` behavior, and the user controls their filesystem. The *code-execution* implication of a project `.env` (shell startup hooks) is tracked in-scope as T12. | Finding `.env` from the project root (`config._find_dotenv_from_start_path`); `override=False` by default (existing env vars preserved); shell startup / environment-hijack keys (`BASH_ENV`, `ENV`) denied during dotenv loading. |
|
|
@@ -504,3 +518,6 @@ Threats that appear valid in isolation but fall outside project responsibility b
|
|
|
504
518
|
| 2026-07-21 | manual update | Clarified TB4 after process-wide MCP names and scoped remembered approvals changed from replacement semantics to independent grants. An empty process-wide allowlist no longer suppresses remembered approvals; disabled-server precedence is unchanged. |
|
|
505
519
|
| 2026-07-22 | manual update | Added T13 (first-token shell allow-list bypass via allow-listed interpreters/wrappers) under TB2, distinguishing it from T2's `--shell-allow-list all` sentinel; cross-referenced it from T2 and extended the "LLM output" input-coverage gap to note that allow-list matching only inspects the command's first token |
|
|
506
520
|
| 2026-07-24 | manual update | Corrected the out-of-scope hooks row: Hooks v2 defaults are 600s (30s for `UserPromptSubmit`), not a global 5-second timeout; loading is `hooks.loading.load_hooks_config`; project hooks require workspace trust or `--trust-project-hooks` |
|
|
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
|
+
| 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
|
+
| 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 |
|
|
@@ -11,6 +11,25 @@ from __future__ import annotations
|
|
|
11
11
|
from dataclasses import dataclass, field
|
|
12
12
|
from typing import Any, TypedDict
|
|
13
13
|
|
|
14
|
+
INHERIT_CLASSIFIER_MODEL = "__dcode_inherit_classifier__"
|
|
15
|
+
"""Per-run `classifier_model` value meaning "review with the main agent model".
|
|
16
|
+
|
|
17
|
+
An absent (or `None`) `classifier_model` only says the run carries no
|
|
18
|
+
preference, so the classifier keeps whatever the server resolved at startup
|
|
19
|
+
(`--auto-classifier-model`, `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL`,
|
|
20
|
+
`[models].auto_classifier`). `/auto model clear` needs the stronger statement
|
|
21
|
+
that reviews go back to the main agent model, which this sentinel carries.
|
|
22
|
+
|
|
23
|
+
It cannot collide with a real spec: `create_model` resolves `provider:model`
|
|
24
|
+
(or a bare model name) and has no provider or model named `__dcode_...`. A
|
|
25
|
+
control character such as a leading NUL would also be collision-proof, but this
|
|
26
|
+
value has to survive the trip to a remote deployment intact — the context is
|
|
27
|
+
serialized to JSON and may be persisted, and Postgres `text`/`jsonb` rejects NUL
|
|
28
|
+
outright. A stripped sentinel would silently read as "no preference" and leave a
|
|
29
|
+
startup classifier authorizing actions after the UI reported the clear, so the
|
|
30
|
+
sentinel stays plain ASCII.
|
|
31
|
+
"""
|
|
32
|
+
|
|
14
33
|
|
|
15
34
|
@dataclass
|
|
16
35
|
class CLIContextSchema:
|
|
@@ -39,6 +58,8 @@ class CLIContextSchema:
|
|
|
39
58
|
|
|
40
59
|
model_context_limit: int | None = None
|
|
41
60
|
|
|
61
|
+
classifier_model: str | None = None
|
|
62
|
+
|
|
42
63
|
approval_mode: str = "manual"
|
|
43
64
|
|
|
44
65
|
auto_approve: bool = False
|
|
@@ -81,6 +102,17 @@ class CLIContext(TypedDict, total=False):
|
|
|
81
102
|
model_context_limit: int | None
|
|
82
103
|
"""Effective context-window limit for profile-aware middleware."""
|
|
83
104
|
|
|
105
|
+
classifier_model: str | None
|
|
106
|
+
"""Model spec the Auto approval classifier should use for this run.
|
|
107
|
+
|
|
108
|
+
`None` (or absent) expresses no per-run preference, so the classifier keeps
|
|
109
|
+
whatever the graph was built with — normally the main agent model, but a
|
|
110
|
+
separate model when the session was launched with one.
|
|
111
|
+
`INHERIT_CLASSIFIER_MODEL` overrides that startup value back to the main
|
|
112
|
+
agent model. Set by `/auto model` so the switch takes effect without
|
|
113
|
+
restarting the agent server.
|
|
114
|
+
"""
|
|
115
|
+
|
|
84
116
|
approval_mode: str
|
|
85
117
|
"""`manual`, classifier-backed `auto`, or unrestricted `yolo`."""
|
|
86
118
|
|
|
@@ -27,6 +27,9 @@ drift guards in `test_main_args` and `test_tool_catalog` pin it so a new or
|
|
|
27
27
|
renamed SDK filesystem tool fails a test instead of silently diverging.
|
|
28
28
|
"""
|
|
29
29
|
|
|
30
|
+
SESSION_END_DRAIN_TIMEOUT_SECONDS: Final[float] = 2.0
|
|
31
|
+
"""Maximum time to drain Hooks v2 `SessionEnd` during session teardown."""
|
|
32
|
+
|
|
30
33
|
SDK_DEFAULT_RUBRIC_MAX_ITERATIONS: Final[int] = 3
|
|
31
34
|
"""Default `RubricMiddleware.max_iterations`, shown without importing the SDK.
|
|
32
35
|
|
|
@@ -30,6 +30,42 @@ import os
|
|
|
30
30
|
# Keep alphabetically sorted by constant name.
|
|
31
31
|
# ---------------------------------------------------------------------------
|
|
32
32
|
|
|
33
|
+
AUTO_CLASSIFIER_MODEL = "DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL"
|
|
34
|
+
"""Model spec (`provider:model`) used by the Auto approval-mode classifier.
|
|
35
|
+
|
|
36
|
+
Unset (the default) reuses the main agent model, preserving the historical
|
|
37
|
+
behavior. A `provider:model` value points the authorization classifier at a
|
|
38
|
+
separate — typically faster and cheaper — model without changing the model that
|
|
39
|
+
writes code. The classifier is a security control: a model that cannot be
|
|
40
|
+
resolved (bad spec, missing credentials, uninstalled provider package) never
|
|
41
|
+
falls back to the main model — reviewed actions are denied, and repeated
|
|
42
|
+
failures escalate to your approval. Also settable via `[models].auto_classifier`
|
|
43
|
+
in config.toml and `--auto-classifier-model`.
|
|
44
|
+
|
|
45
|
+
This is user-controlled process env, not a repo file: a committed *project*
|
|
46
|
+
`.env` cannot set it (see `config._PROJECT_DOTENV_DENIED_ENV_KEYS`), so a cloned
|
|
47
|
+
repository cannot point the review that authorizes its own tool calls at a weaker
|
|
48
|
+
model. Only the shell, the launch environment, or the global `~/.deepagents/.env`
|
|
49
|
+
can.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
AUTO_CLASSIFIER_TIMEOUT = "DEEPAGENTS_CODE_AUTO_CLASSIFIER_TIMEOUT"
|
|
53
|
+
"""Seconds the Auto approval-mode classifier may take to review one batch.
|
|
54
|
+
|
|
55
|
+
Raise this when reviews time out on a slow or heavily loaded classifier model:
|
|
56
|
+
a batch that misses the deadline is denied as `classifier_unavailable`, so the
|
|
57
|
+
tool call does not run and repeated misses escalate to your approval. This
|
|
58
|
+
covers the wait for a verdict only — the separate budget for *building* the
|
|
59
|
+
classifier model (cold provider import, credential bootstrap), which denies with
|
|
60
|
+
"could not be built within 30s", is fixed. Values outside 1-300 seconds are
|
|
61
|
+
ignored in favor of the next config source, so the deadline can never be
|
|
62
|
+
removed. Also settable via `[models].auto_classifier_timeout` in config.toml.
|
|
63
|
+
Resolved once per `dcode` start, so a change takes effect on the next launch.
|
|
64
|
+
|
|
65
|
+
Like `AUTO_CLASSIFIER_MODEL`, a committed *project* `.env` cannot set it (see
|
|
66
|
+
`config._PROJECT_DOTENV_DENIED_ENV_KEYS`).
|
|
67
|
+
"""
|
|
68
|
+
|
|
33
69
|
AUTO_UPDATE = "DEEPAGENTS_CODE_AUTO_UPDATE"
|
|
34
70
|
"""Toggle automatic app updates. Enabled by default; set to a falsy value
|
|
35
71
|
('0', 'false', 'no', 'off', or empty) to opt out."""
|
|
@@ -124,12 +160,6 @@ Does not auto-open the update modal (use `DEEPAGENTS_CODE_DEBUG_UPDATE` for that
|
|
|
124
160
|
Any non-empty value enables the flag (including `"0"` or `"false"`).
|
|
125
161
|
"""
|
|
126
162
|
|
|
127
|
-
DEBUG_ONBOARDING = "DEEPAGENTS_CODE_DEBUG_ONBOARDING"
|
|
128
|
-
"""Force the onboarding flow to open on every interactive startup.
|
|
129
|
-
|
|
130
|
-
Parsed by `is_env_truthy`: accepts `1`, `true`, `yes`, `on` as enabled.
|
|
131
|
-
"""
|
|
132
|
-
|
|
133
163
|
DEBUG_UPDATE = "DEEPAGENTS_CODE_DEBUG_UPDATE"
|
|
134
164
|
"""Inject a sample update-available notification and auto-open the update modal
|
|
135
165
|
at launch so the update-available flow can be exercised without waiting for a
|
|
@@ -284,6 +314,22 @@ and `/api/show`. See `_ollama_discovery_enabled` for accepted truthy/falsy
|
|
|
284
314
|
values.
|
|
285
315
|
"""
|
|
286
316
|
|
|
317
|
+
ONBOARDING = "DEEPAGENTS_CODE_ONBOARDING"
|
|
318
|
+
"""Override whether the first-run onboarding flow opens at interactive startup.
|
|
319
|
+
|
|
320
|
+
Three-state, parsed by `classify_env_bool`:
|
|
321
|
+
|
|
322
|
+
- Unset (or an unrecognized token): keep the default first-run behavior, i.e.
|
|
323
|
+
run onboarding until the completion marker exists.
|
|
324
|
+
- Falsy (`0`, `false`, `no`, `off`, or empty): never open onboarding, even on a
|
|
325
|
+
fresh install with no completion marker.
|
|
326
|
+
- Truthy (`1`, `true`, `yes`, `on`): force onboarding to open on every
|
|
327
|
+
interactive startup, ignoring the completion marker.
|
|
328
|
+
|
|
329
|
+
Read by `should_run_onboarding`; skipping the flow this way does not write the
|
|
330
|
+
completion marker, so unsetting the variable restores first-run behavior.
|
|
331
|
+
"""
|
|
332
|
+
|
|
287
333
|
ONBOARDING_INTEGRATIONS_SCREEN = "DEEPAGENTS_CODE_ONBOARDING_INTEGRATIONS_SCREEN"
|
|
288
334
|
"""Show the "Installed Integrations" summary screen during first-run onboarding.
|
|
289
335
|
|
|
@@ -315,6 +361,22 @@ PLUGIN_CACHE_DIR = "DEEPAGENTS_CODE_PLUGIN_CACHE_DIR"
|
|
|
315
361
|
When unset, plugins are stored under `DEFAULT_CONFIG_DIR / "plugins"`.
|
|
316
362
|
"""
|
|
317
363
|
|
|
364
|
+
PRICES_AUTO_UPDATE = "DEEPAGENTS_CODE_PRICES_AUTO_UPDATE"
|
|
365
|
+
"""Toggle hourly background refresh of the `genai-prices` pricing catalog.
|
|
366
|
+
|
|
367
|
+
Enabled by default; set to a falsy value (`0`, `false`, `no`, `off`, or empty)
|
|
368
|
+
to keep using only the pricing data bundled with the installed `genai-prices`
|
|
369
|
+
package. `DEEPAGENTS_CODE_OFFLINE` suppresses the refresh too, along with
|
|
370
|
+
every other network fetch.
|
|
371
|
+
|
|
372
|
+
Parsed by `is_env_truthy` on each pricing call until the updater starts, and
|
|
373
|
+
never read again after that -- so disabling it mid-process has no effect on a
|
|
374
|
+
running updater, while enabling it mid-process starts one on the next priced
|
|
375
|
+
request. Also the escape hatch for hosts embedding this package that manage
|
|
376
|
+
`genai_prices.UpdatePrices` themselves: genai-prices permits one updater per
|
|
377
|
+
process, so an embedder that starts its own would otherwise race this one.
|
|
378
|
+
"""
|
|
379
|
+
|
|
318
380
|
RECURSION_LIMIT = "DEEPAGENTS_CODE_RECURSION_LIMIT"
|
|
319
381
|
"""Override the main agent's LangGraph `recursion_limit` (graph step budget).
|
|
320
382
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Escaping for external text that reaches Rich/Textual markdown source."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
MARKDOWN_ESCAPES = str.maketrans({char: f"\\{char}" for char in "\\&`*_[]<>|~"})
|
|
6
|
+
"""Translation table backing `escape_markdown`.
|
|
7
|
+
|
|
8
|
+
Covers the inline constructs Rich's markdown parser acts on (emphasis, code
|
|
9
|
+
spans, links, autolinks/HTML, HTML entities, strikethrough) plus the `|`
|
|
10
|
+
table-cell separator. Block-level punctuation (`#`, `-`, `>`) only has meaning
|
|
11
|
+
at the start of a line; line breaks are normalized before translation, and `>`
|
|
12
|
+
is escaped anyway because it is cheap.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def escape_markdown(text: str) -> str:
|
|
17
|
+
"""Normalize line breaks and escape markdown syntax in external text.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
text: Display string that may contain markdown punctuation.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
`text` on one line with markdown-significant characters escaped.
|
|
24
|
+
"""
|
|
25
|
+
normalized = text.replace("\r\n", " ").replace("\r", " ").replace("\n", " ")
|
|
26
|
+
return normalized.translate(MARKDOWN_ESCAPES)
|
|
@@ -340,6 +340,14 @@ class ServerConfig:
|
|
|
340
340
|
rubric_max_iterations: int | None = None
|
|
341
341
|
"""Explicit grader iterations per rubric attempt; `None` uses the SDK default."""
|
|
342
342
|
|
|
343
|
+
auto_classifier_model: str | None = None
|
|
344
|
+
"""Classifier model spec for Auto mode (e.g. `'anthropic:claude-haiku-4-5'`).
|
|
345
|
+
|
|
346
|
+
`None` falls through to `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL`, then
|
|
347
|
+
`[models].auto_classifier`, and then to the main agent model. An empty value
|
|
348
|
+
round-trips to `None`, so it means "inherit", never "empty spec".
|
|
349
|
+
"""
|
|
350
|
+
|
|
343
351
|
recursion_limit: int | None = None
|
|
344
352
|
"""Explicit main-agent LangGraph `recursion_limit` (graph step budget).
|
|
345
353
|
|
|
@@ -477,6 +485,7 @@ class ServerConfig:
|
|
|
477
485
|
else None
|
|
478
486
|
),
|
|
479
487
|
"RUBRIC_MODEL": self.rubric_model,
|
|
488
|
+
"AUTO_CLASSIFIER_MODEL": self.auto_classifier_model,
|
|
480
489
|
"RUBRIC_MAX_ITERATIONS": (
|
|
481
490
|
str(self.rubric_max_iterations)
|
|
482
491
|
if self.rubric_max_iterations is not None
|
|
@@ -536,6 +545,7 @@ class ServerConfig:
|
|
|
536
545
|
),
|
|
537
546
|
allow_fs_tools=_read_env_allow_fs_tools(),
|
|
538
547
|
rubric_model=_read_env_str("RUBRIC_MODEL") or None,
|
|
548
|
+
auto_classifier_model=_read_env_str("AUTO_CLASSIFIER_MODEL") or None,
|
|
539
549
|
rubric_max_iterations=_read_env_int("RUBRIC_MAX_ITERATIONS", default=None),
|
|
540
550
|
recursion_limit=_read_env_int("RECURSION_LIMIT", default=None),
|
|
541
551
|
sandbox_type=_read_env_str("SANDBOX_TYPE"),
|
|
@@ -577,6 +587,7 @@ class ServerConfig:
|
|
|
577
587
|
allow_fs_tools: list[FsToolName] | None = None,
|
|
578
588
|
rubric_model: str | None = None,
|
|
579
589
|
rubric_max_iterations: int | None = None,
|
|
590
|
+
auto_classifier_model: str | None = None,
|
|
580
591
|
recursion_limit: int | None = None,
|
|
581
592
|
mcp_config_path: str | None,
|
|
582
593
|
no_mcp: bool,
|
|
@@ -618,6 +629,8 @@ class ServerConfig:
|
|
|
618
629
|
rubric_model: Grader model spec; `None` reuses the main model.
|
|
619
630
|
rubric_max_iterations: Explicit grader iterations per rubric attempt;
|
|
620
631
|
`None` uses the SDK default.
|
|
632
|
+
auto_classifier_model: Auto classifier model spec; `None` resolves from
|
|
633
|
+
env / `config.toml` and then reuses the main model.
|
|
621
634
|
recursion_limit: Explicit main-agent `recursion_limit`; `None` resolves
|
|
622
635
|
from env / `config.toml` / default at agent-build time.
|
|
623
636
|
mcp_config_path: Path to MCP config.
|
|
@@ -651,6 +664,7 @@ class ServerConfig:
|
|
|
651
664
|
allow_fs_tools=allow_fs_tools,
|
|
652
665
|
rubric_model=rubric_model,
|
|
653
666
|
rubric_max_iterations=rubric_max_iterations,
|
|
667
|
+
auto_classifier_model=auto_classifier_model,
|
|
654
668
|
recursion_limit=recursion_limit,
|
|
655
669
|
sandbox_type=sandbox_type,
|
|
656
670
|
sandbox_id=sandbox_id,
|
|
@@ -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.52" # 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."""
|
|
@@ -2200,6 +2200,7 @@ def create_cli_agent(
|
|
|
2200
2200
|
enable_interpreter: bool = False,
|
|
2201
2201
|
rubric_model: str | BaseChatModel | None = None,
|
|
2202
2202
|
rubric_max_iterations: int | None = None,
|
|
2203
|
+
auto_classifier_model: str | BaseChatModel | None = None,
|
|
2203
2204
|
recursion_limit: int | None = None,
|
|
2204
2205
|
checkpointer: BaseCheckpointSaver | None = None,
|
|
2205
2206
|
mcp_server_info: list[MCPServerInfo] | None = None,
|
|
@@ -2325,6 +2326,16 @@ def create_cli_agent(
|
|
|
2325
2326
|
rubric_max_iterations: Explicit grader iterations per rubric attempt
|
|
2326
2327
|
before the agent terminates with `'max_iterations_reached'`; `None`
|
|
2327
2328
|
uses the SDK default.
|
|
2329
|
+
auto_classifier_model: Model the Auto approval classifier reviews with.
|
|
2330
|
+
|
|
2331
|
+
A `'provider:model'` string or `BaseChatModel`.
|
|
2332
|
+
|
|
2333
|
+
When `None`, `DEEPAGENTS_CODE_AUTO_CLASSIFIER_MODEL` is consulted,
|
|
2334
|
+
then `[models].auto_classifier`, and the main `model` is reused when
|
|
2335
|
+
both are unset. A blank string is *not* the same as `None`: it means
|
|
2336
|
+
"inherit the main model" directly and, unlike `None`, does not
|
|
2337
|
+
consult the env var or `config.toml`. Only meaningful when
|
|
2338
|
+
`auto_mode_enabled` is `True`.
|
|
2328
2339
|
recursion_limit: Explicit LangGraph `recursion_limit` (graph step budget)
|
|
2329
2340
|
for the main agent. When `None`, it is resolved from the
|
|
2330
2341
|
`DEEPAGENTS_CODE_RECURSION_LIMIT` env var, `[runtime].recursion_limit`
|
|
@@ -2463,21 +2474,17 @@ def create_cli_agent(
|
|
|
2463
2474
|
# Server-owned hooks must wrap subagent tools too; otherwise Pre/Post
|
|
2464
2475
|
# ToolUse only fire on the parent graph. Disable Stop so finishing a
|
|
2465
2476
|
# subagent does not emit the main-agent Stop event (SubagentStop still
|
|
2466
|
-
# fires from the parent wrap around `task`).
|
|
2467
|
-
|
|
2468
|
-
from deepagents_code._env_vars import EXPERIMENTAL, is_env_truthy
|
|
2469
|
-
|
|
2470
|
-
if is_env_truthy(EXPERIMENTAL):
|
|
2471
|
-
from deepagents_code.hooks.server_middleware import ServerHooksMiddleware
|
|
2477
|
+
# fires from the parent wrap around `task`).
|
|
2478
|
+
from deepagents_code.hooks.server_middleware import ServerHooksMiddleware
|
|
2472
2479
|
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
)
|
|
2480
|
+
hooks_cwd = Path(effective_cwd) if effective_cwd is not None else Path.cwd()
|
|
2481
|
+
middleware.append(
|
|
2482
|
+
ServerHooksMiddleware(
|
|
2483
|
+
cwd=hooks_cwd,
|
|
2484
|
+
emit_stop=False,
|
|
2485
|
+
mcp_tools=mcp_tools,
|
|
2480
2486
|
)
|
|
2487
|
+
)
|
|
2481
2488
|
# Subagents share the on-disk filesystem backend and can edit the user
|
|
2482
2489
|
# AGENTS.md, so they get the same managed onboarding-name block guard as
|
|
2483
2490
|
# the main agent. Gated on memory because the block only exists when
|
|
@@ -2844,13 +2851,25 @@ def create_cli_agent(
|
|
|
2844
2851
|
compaction_middleware = _create_cli_compaction_middleware(model, composite_backend)
|
|
2845
2852
|
if auto_mode_config is not None and resolved_interrupt_on is not None:
|
|
2846
2853
|
from deepagents_code.auto_mode import AutoModeHITLMiddleware
|
|
2854
|
+
from deepagents_code.config import resolve_auto_classifier_model
|
|
2855
|
+
from deepagents_code.config_manifest import resolve_auto_classifier_timeout
|
|
2847
2856
|
|
|
2848
2857
|
trusted_root, narrow_allow_list = auto_mode_config
|
|
2858
|
+
# An explicit argument wins; otherwise the env var / `config.toml`
|
|
2859
|
+
# preference is read here, where agent construction already runs off the
|
|
2860
|
+
# blockbuster-guarded server loop (see `server_graph._make_graph`).
|
|
2861
|
+
classifier_model = (
|
|
2862
|
+
auto_classifier_model
|
|
2863
|
+
if auto_classifier_model is not None
|
|
2864
|
+
else resolve_auto_classifier_model()
|
|
2865
|
+
)
|
|
2849
2866
|
agent_middleware.append(
|
|
2850
2867
|
AutoModeHITLMiddleware(
|
|
2851
2868
|
resolved_interrupt_on,
|
|
2852
2869
|
worktree_root=trusted_root,
|
|
2853
2870
|
shell_allow_list=narrow_allow_list,
|
|
2871
|
+
classifier_model=classifier_model,
|
|
2872
|
+
classifier_timeout_seconds=resolve_auto_classifier_timeout(),
|
|
2854
2873
|
trusted_ask_user_tool=trusted_ask_user_tool,
|
|
2855
2874
|
trusted_compaction_tool=compaction_middleware.tools[0],
|
|
2856
2875
|
)
|
|
@@ -2862,19 +2881,13 @@ def create_cli_agent(
|
|
|
2862
2881
|
agent_middleware.append(AsyncApprovalHITLMiddleware(resolved_interrupt_on))
|
|
2863
2882
|
|
|
2864
2883
|
# Server-owned Hooks v2 lifecycle events (Pre/Post tool, Stop, subagent).
|
|
2865
|
-
#
|
|
2866
|
-
#
|
|
2867
|
-
#
|
|
2868
|
-
|
|
2869
|
-
from deepagents_code._env_vars import EXPERIMENTAL, is_env_truthy
|
|
2870
|
-
|
|
2871
|
-
if is_env_truthy(EXPERIMENTAL):
|
|
2872
|
-
from deepagents_code.hooks.server_middleware import ServerHooksMiddleware
|
|
2884
|
+
# Gated at runtime by `hooks_server_events` on the per-run context so idle
|
|
2885
|
+
# sessions without configured handlers pay no interrupt round-trip. Appended
|
|
2886
|
+
# after the HITL middleware so `PreToolUse` resolves before approval routing.
|
|
2887
|
+
from deepagents_code.hooks.server_middleware import ServerHooksMiddleware
|
|
2873
2888
|
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
ServerHooksMiddleware(cwd=hooks_cwd, mcp_tools=mcp_tools)
|
|
2877
|
-
)
|
|
2889
|
+
hooks_cwd = Path(effective_cwd) if effective_cwd is not None else Path.cwd()
|
|
2890
|
+
agent_middleware.append(ServerHooksMiddleware(cwd=hooks_cwd, mcp_tools=mcp_tools))
|
|
2878
2891
|
|
|
2879
2892
|
if fs_tools is not None:
|
|
2880
2893
|
# `fs_tools` is an explicit allowlist here (`--allow-fs-tools all` and an
|