deepagents-code 0.1.24__tar.gz → 0.1.25__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.24 → deepagents_code-0.1.25}/CHANGELOG.md +15 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/Makefile +1 -1
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/PKG-INFO +7 -1
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/README.md +6 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/THREAT_MODEL.md +17 -6
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/_build_info.py +1 -1
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/_version.py +1 -1
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/agent.py +19 -1
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/auth_store.py +5 -1
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/config.py +45 -4
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/config_commands.py +189 -31
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/config_manifest.py +11 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/extras_info.py +104 -5
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/file_ops.py +42 -11
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/memory_guard.py +83 -15
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/server.py +102 -10
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/server_graph.py +132 -67
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/server_manager.py +11 -5
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/sessions.py +2 -2
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/textual_adapter.py +2 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/tool_display.py +1 -1
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/tools.py +89 -2
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/approval.py +7 -4
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/chat_input.py +83 -26
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/messages.py +1 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/tool_renderers.py +42 -1
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/pyproject.toml +5 -2
- deepagents_code-0.1.25/scripts/check_imports.py +44 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/conftest.py +32 -13
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_agent.py +32 -2
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_app.py +5 -5
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_auth_store.py +8 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_chat_input.py +280 -12
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_config_manifest.py +392 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_extras_info.py +217 -5
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_file_ops.py +90 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_local_context.py +39 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_main.py +5 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_memory_guard.py +112 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_messages.py +6 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_reload.py +64 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_server.py +185 -4
- deepagents_code-0.1.25/tests/unit_tests/test_server_graph.py +425 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_server_helpers.py +13 -10
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_server_manager.py +48 -3
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_sessions.py +13 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_tool_display.py +9 -3
- deepagents_code-0.1.25/tests/unit_tests/test_tool_renderers.py +43 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/tools/test_fetch_url.py +132 -1
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/uv.lock +8 -7
- deepagents_code-0.1.24/scripts/check_imports.py +0 -32
- deepagents_code-0.1.24/tests/unit_tests/test_server_graph.py +0 -199
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/.gitignore +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/AGENTS.md +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/ARCHITECTURE.md +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/COMMANDS.md +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/DEVELOPMENT.md +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/__init__.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/__main__.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/_ask_user_types.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/_cli_context.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/_constants.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/_debug.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/_env_vars.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/_git.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/_paths.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/_server_config.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/_session_stats.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/_startup_error.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/_testing_models.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/_textual_patches.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/app.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/app.tcss +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/approval_mode.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/ask_user.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/auth_commands.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/auth_display.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/built_in_skills/__init__.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/built_in_skills/remember/SKILL.md +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/built_in_skills/skill-creator/SKILL.md +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/clipboard.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/command_registry.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/configurable_model.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/default_agent_prompt.md +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/doctor.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/editor.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/event_bus.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/formatting.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/hooks.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/input.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/integrations/__init__.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/integrations/openai_codex.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/integrations/sandbox_config.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/integrations/sandbox_factory.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/integrations/sandbox_provider.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/integrations/sandbox_registry.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/iterm_cursor_guide.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/local_context.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/main.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/managed_tools.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/mcp_auth.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/mcp_commands.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/mcp_disabled.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/mcp_login_service.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/mcp_oauth_ui.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/mcp_providers/__init__.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/mcp_providers/_registry.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/mcp_providers/base.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/mcp_providers/github.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/mcp_providers/slack.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/mcp_tools.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/mcp_trust.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/media_utils.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/model_config.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/non_interactive.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/notifications.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/offload.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/onboarding.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/output.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/project_utils.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/py.typed +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/remote_client.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/resume_state.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/skills/__init__.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/skills/commands.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/skills/invocation.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/skills/load.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/state_migration.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/subagents.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/system_prompt.md +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/terminal_capabilities.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/terminal_escape.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/theme.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/tools_commands.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/ui.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/unicode_security.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/update_check.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/__init__.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/_js_eval_display.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/_links.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/agent_selector.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/ask_user.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/auth.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/autocomplete.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/codex_auth.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/cwd_switch.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/diff.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/history.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/install_confirm.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/launch_init.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/loading.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/mcp_login.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/mcp_reconnect.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/mcp_viewer.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/message_store.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/model_selector.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/notification_center.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/notification_detail.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/notification_settings.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/restart_prompt.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/status.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/subagent_panel.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/theme_selector.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/thread_selector.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/tool_widgets.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/update_available.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/update_confirm.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/update_progress.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/deepagents_code/widgets/welcome.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/examples/skills/arxiv-search/SKILL.md +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/examples/skills/arxiv-search/arxiv_search.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/examples/skills/langgraph-docs/SKILL.md +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/examples/skills/skill-creator/SKILL.md +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/examples/skills/web-research/SKILL.md +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/hatch_build.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/images/tui.png +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/scripts/debug_server.sh +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/scripts/generate_commands_catalog.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/scripts/install.sh +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/README.md +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/integration_tests/__init__.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/integration_tests/benchmarks/__init__.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/integration_tests/conftest.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/integration_tests/test_acp_mode.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/integration_tests/test_compact_resume.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/integration_tests/test_sandbox_factory.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/integration_tests/test_sandbox_operations.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/__init__.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/skills/__init__.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/skills/test_commands.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/skills/test_load.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/skills/test_skills_json.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_agent_friendly.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_agent_selector.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_approval.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_approval_mode.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_args.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_ask_user.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_ask_user_middleware.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_auth_commands.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_auth_display.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_auth_widgets.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_autocomplete.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_charset.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_clipboard.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_command_registry.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_compact_tool.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_config.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_configurable_model.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_cursor_blink.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_cwd_switch.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_debug.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_doctor.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_editor.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_end_to_end.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_env_vars.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_event_bus.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_exception_handling.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_formatting.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_git.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_hatch_build.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_history.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_hooks.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_imports.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_input_parsing.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_install_command.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_install_confirm.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_install_script.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_launch_init.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_links.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_loading.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_main_acp_mode.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_main_args.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_managed_tools.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_mcp_auth.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_mcp_commands.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_mcp_disabled.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_mcp_login_modal.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_mcp_login_service.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_mcp_oauth_ui.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_mcp_reconnect.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_mcp_tools.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_mcp_trust.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_mcp_viewer.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_media_utils.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_message_store.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_model_config.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_model_selector.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_model_switch.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_non_interactive.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_notification_center.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_notification_detail.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_notifications.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_offload.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_offload_dict_messages.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_onboarding.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_openai_codex_integration.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_output.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_paths.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_remote_client.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_restart_prompt.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_resume_state.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_sandbox_config.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_sandbox_factory.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_sandbox_provider.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_sandbox_registry.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_server_config.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_session_stats.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_shell_allow_list.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_skill_invocation.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_startup_fast_paths.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_state_migration.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_status.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_subagent_panel.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_subagent_stream.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_subagents.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_terminal_capabilities.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_terminal_escape.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_terminal_progress_preference.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_textual_adapter.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_textual_patches.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_theme.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_thread_selector.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_tools_commands.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_tracing_replicas.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_ui.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_unicode_security.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_update_available.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_update_check.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_update_confirm.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_update_progress.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_version.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/test_welcome.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/tools/__init__.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/tools/test_current_thread.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/widgets/__init__.py +0 -0
- {deepagents_code-0.1.24 → deepagents_code-0.1.25}/tests/unit_tests/widgets/test_diff.py +0 -0
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
# Deep Agents Code Changelog
|
|
4
4
|
|
|
5
|
+
## [0.1.25](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.24...deepagents-code==0.1.25) (2026-06-26)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
* Bind ephemeral port instead of squatting `langgraph dev`'s 2024 ([#4264](https://github.com/langchain-ai/deepagents/issues/4264)) ([11e5359](https://github.com/langchain-ai/deepagents/commit/11e5359851f0291783661b4311ad5e4436a36fb7))
|
|
10
|
+
* Block dotenv shell startup hooks ([#4288](https://github.com/langchain-ai/deepagents/issues/4288)) ([686d6f3](https://github.com/langchain-ai/deepagents/commit/686d6f3a1da8b6393efb4c0cf87b3eb35e0cca50))
|
|
11
|
+
* Defer server graph construction ([#4300](https://github.com/langchain-ai/deepagents/issues/4300)) ([220dfc0](https://github.com/langchain-ai/deepagents/commit/220dfc0e6b03f9ccb499c6b850c586b9d57cc077))
|
|
12
|
+
* Avoid blocking MCP imports during graph readiness ([#4302](https://github.com/langchain-ai/deepagents/issues/4302)) ([7533ca8](https://github.com/langchain-ai/deepagents/commit/7533ca89f3afc9863ba5e1ecee2d4c5974dea320))
|
|
13
|
+
* Gate `delete` file operations ([#4299](https://github.com/langchain-ai/deepagents/issues/4299)) ([92a8681](https://github.com/langchain-ai/deepagents/commit/92a86819adfefbc6ccfd01a861191ba292eca754))
|
|
14
|
+
* Handle recursive `fetch_url` conversion ([#4257](https://github.com/langchain-ai/deepagents/issues/4257)) ([f240a40](https://github.com/langchain-ai/deepagents/commit/f240a40dc05d812c38e9926c1d81ba38deb86e3f))
|
|
15
|
+
* Report editable SDK runtime version ([#4304](https://github.com/langchain-ai/deepagents/issues/4304)) ([4439e91](https://github.com/langchain-ai/deepagents/commit/4439e912da4bfa6f1e38e14b5a03d2bfe9367d3b))
|
|
16
|
+
* Show months instead of "0y ago" for 360-364 day old timestamps ([#4267](https://github.com/langchain-ai/deepagents/issues/4267)) ([820b331](https://github.com/langchain-ai/deepagents/commit/820b331552cb7ce4695ddca3c9b8343a3144392b))
|
|
17
|
+
* Surface `/auth`-stored credentials in `config show`/`get` ([#4258](https://github.com/langchain-ai/deepagents/issues/4258)) ([c7c8788](https://github.com/langchain-ai/deepagents/commit/c7c8788ecf0068914298a6055a5f3fd31c36bd44))
|
|
18
|
+
* Switch input mode without flashing the mode trigger ([#4243](https://github.com/langchain-ai/deepagents/issues/4243)) ([fc5d9cb](https://github.com/langchain-ai/deepagents/commit/fc5d9cb8fb978ec95f98407692d4809ea1e86577))
|
|
19
|
+
|
|
5
20
|
## [0.1.24](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.23...deepagents-code==0.1.24) (2026-06-25)
|
|
6
21
|
|
|
7
22
|
### Features
|
|
@@ -105,7 +105,7 @@ check: lint check_imports test
|
|
|
105
105
|
@echo "🔍 Verifying pyproject.toml and _version.py agree..."
|
|
106
106
|
uv run --all-groups python "$(REPO_ROOT)/.github/scripts/check_version_equality.py"
|
|
107
107
|
@echo "🔒 Verifying uv.lock is up-to-date..."
|
|
108
|
-
uv lock --check
|
|
108
|
+
UV_FROZEN=false uv lock --check
|
|
109
109
|
@echo "🔗 Checking SDK pin against workspace SDK (advisory)..."
|
|
110
110
|
@uv run --all-groups python "$(REPO_ROOT)/.github/scripts/check_sdk_pin.py" || \
|
|
111
111
|
{ rc=$$?; [ $$rc -eq 1 ] && echo "⚠️ Stale SDK pin (advisory, non-fatal)." || exit $$rc; }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepagents-code
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.25
|
|
4
4
|
Summary: Terminal interface for Deep Agents - interactive AI agent with file operations, shell access, and sub-agent capabilities.
|
|
5
5
|
Project-URL: Homepage, https://docs.langchain.com/oss/python/deepagents/overview
|
|
6
6
|
Project-URL: Documentation, https://reference.langchain.com/python/deepagents/
|
|
@@ -180,6 +180,12 @@ The fastest way to start using Deep Agents. `deepagents-code` is a pre-built cod
|
|
|
180
180
|
- **Headless mode** — run non-interactively for scripting and CI
|
|
181
181
|
- **Human-in-the-loop** — approve or reject tool calls before execution
|
|
182
182
|
|
|
183
|
+
## 🔒 Security model
|
|
184
|
+
|
|
185
|
+
By default, `dcode` trusts the directory you run it in. Human-in-the-loop approval gates model-requested tool calls, but project artifacts are read before any approval prompt.
|
|
186
|
+
|
|
187
|
+
Do not run `dcode` in a directory you do not trust without a sandbox backend. For untrusted repositories, use a [remote sandbox](https://docs.langchain.com/oss/python/deepagents/code/remote-sandboxes) so execution is isolated from your machine. Running `dcode` in a directory lets that directory's files shape execution. See [`THREAT_MODEL.md`](https://github.com/langchain-ai/deepagents/blob/main/libs/code/THREAT_MODEL.md) for details.
|
|
188
|
+
|
|
183
189
|
## 📖 Resources
|
|
184
190
|
|
|
185
191
|
- **[Documentation](https://docs.langchain.com/deepagents-code)**
|
|
@@ -42,6 +42,12 @@ The fastest way to start using Deep Agents. `deepagents-code` is a pre-built cod
|
|
|
42
42
|
- **Headless mode** — run non-interactively for scripting and CI
|
|
43
43
|
- **Human-in-the-loop** — approve or reject tool calls before execution
|
|
44
44
|
|
|
45
|
+
## 🔒 Security model
|
|
46
|
+
|
|
47
|
+
By default, `dcode` trusts the directory you run it in. Human-in-the-loop approval gates model-requested tool calls, but project artifacts are read before any approval prompt.
|
|
48
|
+
|
|
49
|
+
Do not run `dcode` in a directory you do not trust without a sandbox backend. For untrusted repositories, use a [remote sandbox](https://docs.langchain.com/oss/python/deepagents/code/remote-sandboxes) so execution is isolated from your machine. Running `dcode` in a directory lets that directory's files shape execution. See [`THREAT_MODEL.md`](https://github.com/langchain-ai/deepagents/blob/main/libs/code/THREAT_MODEL.md) for details.
|
|
50
|
+
|
|
45
51
|
## 📖 Resources
|
|
46
52
|
|
|
47
53
|
- **[Documentation](https://docs.langchain.com/deepagents-code)**
|
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
| TB8 | CLI → Server Subprocess IPC | Config passed from CLI to `langgraph dev` subprocess via `DA_SERVER_*` env vars | `ServerConfig.to_env()` serialization; env var scoping to parent+child process | Subprocess environment post-fork; /proc visibility to same-uid processes |
|
|
208
208
|
| TB9 | LocalContextMiddleware → Host Env | Bash detect script output (git info, project files, Makefile) injected into system prompt | Script is framework-generated static code; 30s timeout; exit-code check | Content of Makefile, pyproject.toml, git branch names, directory listing |
|
|
209
209
|
| TB10 | RemoteAgent → LangGraph Dev Server | CLI communicates with agent via HTTP+SSE on localhost | Server bound to `127.0.0.1` (`server.py:_DEFAULT_HOST`); ephemeral per session | No authentication (`LANGGRAPH_AUTH_TYPE=noop`); any localhost process can reach the API |
|
|
210
|
-
| TB11 | Config File → Code Execution | `class_path` in `config.toml` triggers `importlib.import_module()`
|
|
210
|
+
| TB11 | Config File → Code Execution | `class_path` in `config.toml` triggers `importlib.import_module()`; project/global `.env` values are loaded into the process environment and can reach Bash startup hooks | Format validation (`module:ClassName`); `issubclass(BaseChatModel)` check; dotenv loading denies shell startup / environment-hijack keys (`BASH_ENV`, `ENV`) | Module-level side effects execute during import; user controls config file; project files in the working directory influence execution |
|
|
211
211
|
|
|
212
212
|
### Boundary Details
|
|
213
213
|
|
|
@@ -250,7 +250,7 @@
|
|
|
250
250
|
|
|
251
251
|
#### TB10: RemoteAgent → LangGraph Dev Server
|
|
252
252
|
|
|
253
|
-
- **Inside**: Server bound to `127.0.0.1` by default; `server.py:_DEFAULT_HOST = "127.0.0.1"`. `RemoteAgent` only connects to the URL returned by `ServerProcess.url`. Server is ephemeral — started at session start, stopped at session end.
|
|
253
|
+
- **Inside**: Server bound to `127.0.0.1` by default; `server.py:_DEFAULT_HOST = "127.0.0.1"`. `RemoteAgent` only connects to the URL returned by `ServerProcess.url`. Server is ephemeral — started at session start, stopped at session end. Binds a free ephemeral port by default (`server.py:_EPHEMERAL_PORT`); an explicit port is honored but still falls back to a free port if occupied.
|
|
254
254
|
- **Outside**: `LANGGRAPH_AUTH_TYPE=noop` disables all LangGraph server authentication. Any process on localhost that discovers the port can submit requests, read thread state, or inject messages.
|
|
255
255
|
- **Crossing mechanism**: HTTP POST/GET to `http://127.0.0.1:{port}` using `langgraph.pregel.remote.RemoteGraph`.
|
|
256
256
|
|
|
@@ -259,6 +259,8 @@
|
|
|
259
259
|
- **Inside**: `config._create_model_from_class` validates `class_path` format (`module:ClassName`), imports the module via `importlib.import_module()`, and checks `issubclass(cls, BaseChatModel)` before instantiation.
|
|
260
260
|
- **Outside**: Module-level code in the imported module executes unconditionally during `import_module()`. The `issubclass` check only runs after import. Any side effects (file I/O, network calls, subprocess spawning) in the module's top-level scope execute before the type check.
|
|
261
261
|
- **Crossing mechanism**: `importlib.import_module(module_path)` in `config._create_model_from_class`.
|
|
262
|
+
- **Inside (dotenv)**: `config._load_dotenv` loads project and global `.env` values with `override=False` and drops shell startup / environment-hijack keys (`BASH_ENV`, `ENV`, and related) so a project `.env` cannot register a script that Bash would source at startup. The preview path (`_preview_dotenv_environ`) applies the same denylist so a dry-run config change cannot report a value a real reload would reject.
|
|
263
|
+
- **Outside (dotenv)**: All other `.env` keys are applied to the process environment, and any project file in the working directory (`.env`, `Makefile`, build scripts) can still influence execution. See T12.
|
|
262
264
|
|
|
263
265
|
---
|
|
264
266
|
|
|
@@ -346,6 +348,7 @@
|
|
|
346
348
|
| T8 | DF21 | DC3 | Custom subagent AGENTS.md body used verbatim as system_prompt without content validation | None | Low | Verified | `subagents._parse_subagent_file`, `agent.create_cli_agent` |
|
|
347
349
|
| T9 | DF23 | — | `class_path` in config.toml triggers arbitrary Python code execution via `importlib.import_module()` | TB11 | Low | Verified | `config._create_model_from_class`, `model_config.ProviderConfig` |
|
|
348
350
|
| 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` |
|
|
351
|
+
| 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` |
|
|
349
352
|
|
|
350
353
|
### Threat Details
|
|
351
354
|
|
|
@@ -382,7 +385,7 @@
|
|
|
382
385
|
#### T6: Unauthenticated LangGraph Dev Server on Localhost
|
|
383
386
|
|
|
384
387
|
- **Flow**: DF3/DF4 (CLI ↔ LangGraph dev server)
|
|
385
|
-
- **Description**: The CLI spawns a `langgraph dev` server subprocess with `LANGGRAPH_AUTH_TYPE=noop` (`server.py:_build_server_env`). This disables all server-side authentication. The server binds to `127.0.0.1:{port}` (
|
|
388
|
+
- **Description**: The CLI spawns a `langgraph dev` server subprocess with `LANGGRAPH_AUTH_TYPE=noop` (`server.py:_build_server_env`). This disables all server-side authentication. The server binds to `127.0.0.1:{port}` (a free ephemeral port by default, so it no longer squats the well-known `langgraph dev` port 2024). Any local process that discovers the port can: send arbitrary inputs to the running agent thread, read the agent's conversation state (including tool results that may contain file contents or secrets), inject messages into the conversation history, or trigger state updates. The server is ephemeral — it lives only for the duration of the CLI session — but this is the entire attack window. Port discovery is feasible via localhost port scanning or by reading `/proc/{pid}/cmdline` which contains the `--port` argument.
|
|
386
389
|
- **Preconditions**: (1) Attacker has a local process running as the same user (or as root); (2) Attacker discovers the server port (port scan on localhost, or reads process arguments).
|
|
387
390
|
|
|
388
391
|
#### T7: LocalContextMiddleware Injects Host File Contents into System Prompt
|
|
@@ -416,6 +419,12 @@
|
|
|
416
419
|
- **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).
|
|
417
420
|
- **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.
|
|
418
421
|
|
|
422
|
+
#### T12: Project `.env` Injects Shell Interpreter Startup Hooks
|
|
423
|
+
|
|
424
|
+
- **Flow**: DF10 (project `.env` → process environment) → bash subprocess startup (DF19)
|
|
425
|
+
- **Description**: `config._load_dotenv` discovers the nearest project `.env` by walking up from the working directory and applies its values to the process environment (`override=False`, so shell-exported values still win). Bash treats several environment variables as startup hooks — `BASH_ENV` and `ENV` name a file that is sourced when a non-interactive shell starts. Because Deep Agents Code runs its own local-context detection through Bash at startup (`local_context.build_detect_script`) and spawns shells for the `execute` tool, a project `.env` that sets one of these keys could run attacker-controlled scripts inside the `dcode` process *before* any model-requested tool call or HITL approval prompt. The broader trust boundary is that running `dcode` in a project directory lets that project influence the process environment.
|
|
426
|
+
- **Preconditions**: (1) User launches `dcode` in a directory containing an attacker-controlled `.env` (for example, a freshly cloned untrusted repository); (2) the `.env` sets a shell startup-hook key that is not already exported in the user's shell (dotenv uses `override=False`).
|
|
427
|
+
|
|
419
428
|
---
|
|
420
429
|
|
|
421
430
|
## Input Source Coverage
|
|
@@ -426,7 +435,7 @@
|
|
|
426
435
|
| LLM output | DF6, DF7 | T1, T2, T3, T4| HITL gate; shell allow-list; Unicode/URL warnings on tool args | Project | LLM-generated tool args not scanned for injection beyond Unicode/URL |
|
|
427
436
|
| Tool/function results | DF9, DF11 | T1 | Unicode warning on URL args; `markdownify` HTML conversion | Shared | Tool *results* pass to context without prompt-injection scan |
|
|
428
437
|
| 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 |
|
|
429
|
-
| Configuration | DF10, DF12, DF15, DF23| T9, T10
|
|
438
|
+
| Configuration | DF10, DF12, DF15, DF23| T9, T10, T12 | Dotenv shell-env precedence; TOML schema; MCP schema + fingerprint; 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 |
|
|
430
439
|
| Session restore | DF14 | T5 | OS file permissions; SQLite | Project | Unencrypted at rest |
|
|
431
440
|
| 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 |
|
|
432
441
|
| Host environment | DF19, DF20 | T7 | Static script; exit code check; 30s timeout | Shared | Makefile content injected into system prompt without sanitization |
|
|
@@ -450,8 +459,8 @@ Threats that appear valid in isolation but fall outside project responsibility b
|
|
|
450
459
|
| 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`. |
|
|
451
460
|
| Hook commands doing harmful things | Hooks in `~/.deepagents/hooks.json` are 100% user-authored. The payload is data-only (JSON on stdin). | JSON structure validation (`hooks._load_hooks`); 5-second timeout. |
|
|
452
461
|
| 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`). |
|
|
453
|
-
| 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.
|
|
454
|
-
| `.env` file from parent directory changes
|
|
462
|
+
| 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. |
|
|
463
|
+
| `.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. |
|
|
455
464
|
|
|
456
465
|
### Rationale
|
|
457
466
|
|
|
@@ -483,3 +492,5 @@ Threats that appear valid in isolation but fall outside project responsibility b
|
|
|
483
492
|
| 2026-03-10 | langster-threat-model (automated) | Initial threat model |
|
|
484
493
|
| 2026-03-27 | langster-threat-model (automated) | Deep expansion: added C11-C16 (server subprocess, RemoteAgent, LocalContextMiddleware, async subagent config, custom subagent loader); added TB8-TB10 (CLI/server IPC, LocalContext/host env, RemoteAgent/dev server); added DF18-DF22; added T6 (unauthenticated dev server), T7 (Makefile injection), T8 (subagent body injection); updated T5 (upstream msgpack fix confirmed); added data classification; added Investigated and Dismissed section; updated architecture diagram to reflect server-subprocess model |
|
|
485
494
|
| 2026-03-28 | langster-threat-model (automated) | Deep validation pass: added C17 (Model Config Loader with class_path), TB11 (Config→Code Execution); added DC5 (offloaded conversation history); added DF23-DF25 (class_path flow, MCP env dict flow, offload flow); added T9 (class_path arbitrary code execution), T10 (MCP env dict unfiltered); added D3 (SSRF dismissed — HITL is intended control), D4 (offload path injection dismissed — UUID7); **removed Status column and Mitigations/Residual Risk fields from all threats** (open source visibility compliance — mitigation status must not appear in public threat models); updated T6 validation from Likely to Verified (port is deterministic at 2024 default, discoverable via /proc); updated external context (no published advisories found); updated architecture diagram |
|
|
495
|
+
| 2026-06-25 | manual update | Added T12 (project `.env` injects shell interpreter startup hooks) under TB11; extended the TB11 boundary controls and details with the dotenv shell-startup-hook denylist (`BASH_ENV`, `ENV`); clarified the `.env` out-of-scope row to separate ordinary config discovery from the in-scope code-execution implication |
|
|
496
|
+
| 2026-06-25 | manual update | Updated T6 and TB10 to reflect the dev server binding an OS-assigned ephemeral port by default (`server._EPHEMERAL_PORT`) instead of squatting the well-known `langgraph dev` port 2024; noted unpredictable-port-across-runs as added defense-in-depth in the port-discovery dismissal row |
|
|
@@ -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.25" # 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."""
|
|
@@ -217,7 +217,7 @@ class ShellAllowListMiddleware(AgentMiddleware):
|
|
|
217
217
|
|
|
218
218
|
|
|
219
219
|
_INTERPRETER_WRITE_TOOLS: frozenset[str] = frozenset(
|
|
220
|
-
{"execute", "write_file", "edit_file"}
|
|
220
|
+
{"execute", "write_file", "edit_file", "delete"}
|
|
221
221
|
)
|
|
222
222
|
"""Tools considered write/shell capable for PTC auditing.
|
|
223
223
|
|
|
@@ -910,6 +910,17 @@ def _format_edit_file_description(
|
|
|
910
910
|
return f"Action: Replace text ({scope})"
|
|
911
911
|
|
|
912
912
|
|
|
913
|
+
def _format_delete_description(
|
|
914
|
+
_tool_call: ToolCall, _state: AgentState[Any], _runtime: Runtime[Any]
|
|
915
|
+
) -> str:
|
|
916
|
+
"""Format delete tool call for approval prompt.
|
|
917
|
+
|
|
918
|
+
Returns:
|
|
919
|
+
Formatted description string for the delete tool call.
|
|
920
|
+
"""
|
|
921
|
+
return "Action: Delete file or directory"
|
|
922
|
+
|
|
923
|
+
|
|
913
924
|
def _format_web_search_description(
|
|
914
925
|
tool_call: ToolCall, _state: AgentState[Any], _runtime: Runtime[Any]
|
|
915
926
|
) -> str:
|
|
@@ -1146,6 +1157,12 @@ def _add_interrupt_on() -> dict[str, InterruptOnConfig]:
|
|
|
1146
1157
|
"when": _should_interrupt_tool_call,
|
|
1147
1158
|
}
|
|
1148
1159
|
|
|
1160
|
+
delete_interrupt_config: InterruptOnConfig = {
|
|
1161
|
+
"allowed_decisions": ["approve", "reject"],
|
|
1162
|
+
"description": _format_delete_description, # ty: ignore[invalid-argument-type] # Callable description narrower than TypedDict expects
|
|
1163
|
+
"when": _should_interrupt_tool_call,
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1149
1166
|
web_search_interrupt_config: InterruptOnConfig = {
|
|
1150
1167
|
"allowed_decisions": ["approve", "reject"],
|
|
1151
1168
|
"description": _format_web_search_description, # ty: ignore[invalid-argument-type] # Callable description narrower than TypedDict expects
|
|
@@ -1174,6 +1191,7 @@ def _add_interrupt_on() -> dict[str, InterruptOnConfig]:
|
|
|
1174
1191
|
"execute": execute_interrupt_config,
|
|
1175
1192
|
"write_file": write_file_interrupt_config,
|
|
1176
1193
|
"edit_file": edit_file_interrupt_config,
|
|
1194
|
+
"delete": delete_interrupt_config,
|
|
1177
1195
|
"web_search": web_search_interrupt_config,
|
|
1178
1196
|
"fetch_url": fetch_url_interrupt_config,
|
|
1179
1197
|
"task": task_interrupt_config,
|
|
@@ -144,7 +144,11 @@ def _read_raw() -> dict | None:
|
|
|
144
144
|
"Check the file permissions on the parent directory."
|
|
145
145
|
)
|
|
146
146
|
raise RuntimeError(msg) from exc
|
|
147
|
-
except json.JSONDecodeError as exc:
|
|
147
|
+
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
|
148
|
+
# `UnicodeDecodeError` (a `ValueError`, not an `OSError`) escapes the
|
|
149
|
+
# handler above when the file holds non-UTF-8 bytes; treat a decode
|
|
150
|
+
# failure as corruption so callers get the same `RuntimeError` hint
|
|
151
|
+
# instead of an unhandled traceback.
|
|
148
152
|
msg = (
|
|
149
153
|
f"Failed to parse credential file {path}: {exc}. "
|
|
150
154
|
"Delete the file and re-add credentials via /auth if it is corrupt."
|
|
@@ -87,9 +87,14 @@ re-applied only to the approval-gated shell backend's `execute` subprocesses by
|
|
|
87
87
|
|
|
88
88
|
_DOTENV_DENIED_ENV_KEYS = frozenset(
|
|
89
89
|
{
|
|
90
|
+
"BASH_ENV",
|
|
91
|
+
"BASHOPTS",
|
|
92
|
+
"CDPATH",
|
|
90
93
|
"DYLD_INSERT_LIBRARIES",
|
|
91
94
|
"DYLD_LIBRARY_PATH",
|
|
95
|
+
"ENV",
|
|
92
96
|
"GIT_ASKPASS",
|
|
97
|
+
"GLOBIGNORE",
|
|
93
98
|
"LD_AUDIT",
|
|
94
99
|
"LD_LIBRARY_PATH",
|
|
95
100
|
"LD_PRELOAD",
|
|
@@ -99,15 +104,42 @@ _DOTENV_DENIED_ENV_KEYS = frozenset(
|
|
|
99
104
|
"PYTHONHOME",
|
|
100
105
|
"PYTHONPATH",
|
|
101
106
|
"PYTHONSTARTUP",
|
|
107
|
+
"SHELLOPTS",
|
|
102
108
|
"SSH_ASKPASS",
|
|
103
109
|
_INHERITED_PYTHONPATH_ENV,
|
|
104
110
|
}
|
|
105
111
|
)
|
|
106
112
|
"""Environment keys that project `.env` files must not inject.
|
|
107
113
|
|
|
114
|
+
A project `.env` is untrusted (it travels with a cloned repo), so it must not be
|
|
115
|
+
able to set variables that turn loading the `.env` into code execution in the
|
|
116
|
+
subprocesses Deep Agents Code spawns. The set spans four threat categories;
|
|
117
|
+
every entry is here for one of these reasons, so do not remove one without
|
|
118
|
+
checking which category it belongs to:
|
|
119
|
+
|
|
120
|
+
- Dynamic-linker preload/audit (`DYLD_INSERT_LIBRARIES`, `DYLD_LIBRARY_PATH`,
|
|
121
|
+
`LD_AUDIT`, `LD_LIBRARY_PATH`, `LD_PRELOAD`): force a loader to map an
|
|
122
|
+
attacker-supplied shared object into every spawned binary.
|
|
123
|
+
- Interpreter startup/path (`NODE_OPTIONS`, `PATH`, `PYTHONEXECUTABLE`,
|
|
124
|
+
`PYTHONHOME`, `PYTHONPATH`, `PYTHONSTARTUP`, `_INHERITED_PYTHONPATH_ENV`):
|
|
125
|
+
hijack which interpreter/binary runs or what it imports at startup.
|
|
126
|
+
- Shell startup hooks (`BASH_ENV`, `ENV`, `BASHOPTS`, `SHELLOPTS`, `CDPATH`,
|
|
127
|
+
`GLOBIGNORE`): `BASH_ENV`/`ENV` source a file on every non-interactive shell;
|
|
128
|
+
`SHELLOPTS`/`BASHOPTS` can force `xtrace`/alias expansion; `CDPATH`/
|
|
129
|
+
`GLOBIGNORE` alter path/glob resolution. The agent runs detection and
|
|
130
|
+
`execute` commands through non-interactive shells, so these are live vectors.
|
|
131
|
+
- Askpass hijack (`GIT_ASKPASS`, `SSH_ASKPASS`): point credential prompts at an
|
|
132
|
+
attacker-controlled binary.
|
|
133
|
+
|
|
108
134
|
`_INHERITED_PYTHONPATH_ENV` is denied so a project `.env` cannot smuggle a
|
|
109
135
|
`PYTHONPATH` into agent `execute` commands through the carrier var; the carrier
|
|
110
|
-
is only meant to relay a value the user set in their launch environment.
|
|
136
|
+
is only meant to relay a value the user set in their launch environment.
|
|
137
|
+
|
|
138
|
+
Matching is exact and case-sensitive: the protected consumers (the dynamic
|
|
139
|
+
linker, bash, CPython) read these names only in their canonical case, so a
|
|
140
|
+
lowercase `bash_env` injected into the environment is inert. Any future entry
|
|
141
|
+
that some consumer reads case-insensitively would need a different check.
|
|
142
|
+
"""
|
|
111
143
|
|
|
112
144
|
|
|
113
145
|
def _find_dotenv_from_start_path(start_path: Path) -> Path | None:
|
|
@@ -169,8 +201,13 @@ def _preview_dotenv_environ(*, start_path: Path | None = None) -> dict[str, str]
|
|
|
169
201
|
)
|
|
170
202
|
return
|
|
171
203
|
for key, value in values.items():
|
|
172
|
-
if value is
|
|
173
|
-
|
|
204
|
+
if value is None or key in env:
|
|
205
|
+
continue
|
|
206
|
+
if key in _DOTENV_DENIED_ENV_KEYS:
|
|
207
|
+
# Log the key only — the value is attacker-controlled.
|
|
208
|
+
logger.debug("Ignoring denied env key %r from %s", key, dotenv_path)
|
|
209
|
+
continue
|
|
210
|
+
env[key] = value
|
|
174
211
|
|
|
175
212
|
project_dotenv: Path | None = None
|
|
176
213
|
try:
|
|
@@ -265,7 +302,11 @@ def _load_dotenv(
|
|
|
265
302
|
values = dotenv.dotenv_values(dotenv_path=dotenv_path)
|
|
266
303
|
applied = False
|
|
267
304
|
for key, value in values.items():
|
|
268
|
-
if value is None or key in os.environ
|
|
305
|
+
if value is None or key in os.environ:
|
|
306
|
+
continue
|
|
307
|
+
if key in _DOTENV_DENIED_ENV_KEYS:
|
|
308
|
+
# Log the key only — the value is attacker-controlled.
|
|
309
|
+
logger.debug("Ignoring denied env key %r from %s", key, dotenv_path)
|
|
269
310
|
continue
|
|
270
311
|
os.environ[key] = value
|
|
271
312
|
_dotenv_loaded_values[key] = value
|