deepagents-code 0.1.9__tar.gz → 0.1.11__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.9 → deepagents_code-0.1.11}/AGENTS.md +16 -6
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/CHANGELOG.md +23 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/PKG-INFO +4 -4
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/THREAT_MODEL.md +1 -1
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/_env_vars.py +10 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/_server_config.py +3 -3
- deepagents_code-0.1.11/deepagents_code/_textual_patches.py +287 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/_version.py +1 -1
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/agent.py +35 -22
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/app.py +256 -110
- deepagents_code-0.1.11/deepagents_code/auth_display.py +137 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/auth_store.py +53 -4
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/clipboard.py +0 -3
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/config.py +13 -1
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/input.py +67 -6
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/integrations/sandbox_factory.py +34 -46
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/main.py +265 -13
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/mcp_disabled.py +4 -4
- deepagents_code-0.1.11/deepagents_code/mcp_trust.py +207 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/model_config.py +310 -7
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/non_interactive.py +1 -2
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/server_manager.py +2 -4
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/ui.py +7 -3
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/update_check.py +228 -19
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/auth.py +70 -24
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/loading.py +23 -4
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/model_selector.py +3 -20
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/pyproject.toml +3 -9
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/conftest.py +36 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_agent.py +259 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_app.py +189 -4
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_args.py +20 -3
- deepagents_code-0.1.11/tests/unit_tests/test_auth_display.py +187 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_auth_store.py +57 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_auth_widgets.py +149 -13
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_clipboard.py +34 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_config.py +140 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_input_parsing.py +68 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_install_command.py +110 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_loading.py +78 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_main.py +345 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_main_args.py +151 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_mcp_disabled.py +1 -1
- deepagents_code-0.1.11/tests/unit_tests/test_mcp_trust.py +158 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_model_config.py +493 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_sandbox_factory.py +139 -4
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_server_config.py +1 -1
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_textual_patches.py +54 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_update_check.py +284 -4
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/uv.lock +167 -154
- deepagents_code-0.1.9/deepagents_code/_textual_patches.py +0 -66
- deepagents_code-0.1.9/deepagents_code/mcp_trust.py +0 -167
- deepagents_code-0.1.9/tests/unit_tests/test_mcp_trust.py +0 -112
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/.gitignore +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/COMMANDS.md +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/DEV.md +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/Makefile +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/README.md +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/__init__.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/__main__.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/_ask_user_types.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/_cli_context.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/_constants.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/_debug.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/_git.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/_session_stats.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/_startup_error.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/_testing_models.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/app.tcss +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/ask_user.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/built_in_skills/__init__.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/built_in_skills/remember/SKILL.md +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/built_in_skills/skill-creator/SKILL.md +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/command_registry.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/configurable_model.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/default_agent_prompt.md +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/editor.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/event_bus.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/extras_info.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/file_ops.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/filesystem_empty_result.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/formatting.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/hooks.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/integrations/__init__.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/integrations/sandbox_provider.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/iterm_cursor_guide.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/local_context.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/mcp_auth.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/mcp_commands.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/mcp_login_service.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/mcp_oauth_ui.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/mcp_providers/__init__.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/mcp_providers/_registry.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/mcp_providers/base.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/mcp_providers/github.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/mcp_providers/slack.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/mcp_tools.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/media_utils.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/notifications.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/offload.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/onboarding.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/output.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/project_utils.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/py.typed +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/remote_client.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/resume_state.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/server.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/server_graph.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/sessions.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/skills/__init__.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/skills/commands.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/skills/invocation.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/skills/load.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/state_migration.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/subagents.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/system_prompt.md +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/terminal_capabilities.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/terminal_escape.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/textual_adapter.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/theme.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/tool_display.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/tools.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/unicode_security.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/__init__.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/_links.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/agent_selector.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/approval.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/ask_user.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/autocomplete.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/chat_input.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/diff.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/history.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/launch_init.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/mcp_login.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/mcp_reconnect.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/mcp_viewer.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/message_store.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/messages.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/notification_center.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/notification_detail.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/notification_settings.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/status.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/theme_selector.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/thread_selector.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/tool_renderers.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/tool_widgets.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/update_available.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/update_progress.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/deepagents_code/widgets/welcome.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/examples/skills/arxiv-search/SKILL.md +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/examples/skills/arxiv-search/arxiv_search.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/examples/skills/langgraph-docs/SKILL.md +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/examples/skills/skill-creator/SKILL.md +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/examples/skills/web-research/SKILL.md +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/images/tui.png +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/scripts/check_imports.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/scripts/debug_server.sh +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/scripts/generate_commands_catalog.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/scripts/install.sh +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/README.md +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/integration_tests/__init__.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/integration_tests/benchmarks/__init__.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/integration_tests/conftest.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/integration_tests/test_acp_mode.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/integration_tests/test_compact_resume.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/integration_tests/test_sandbox_factory.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/integration_tests/test_sandbox_operations.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/__init__.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/skills/__init__.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/skills/test_commands.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/skills/test_load.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/skills/test_skills_json.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_agent_friendly.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_agent_selector.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_approval.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_ask_user.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_ask_user_middleware.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_autocomplete.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_charset.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_chat_input.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_command_registry.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_compact_tool.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_configurable_model.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_cursor_blink.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_debug.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_editor.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_end_to_end.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_env_vars.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_event_bus.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_exception_handling.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_extras_info.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_file_ops.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_filesystem_empty_result.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_formatting.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_git.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_history.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_hooks.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_imports.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_launch_init.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_links.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_local_context.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_main_acp_mode.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_mcp_auth.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_mcp_commands.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_mcp_login_modal.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_mcp_login_service.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_mcp_oauth_ui.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_mcp_reconnect.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_mcp_tools.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_mcp_viewer.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_media_utils.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_message_store.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_messages.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_model_selector.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_model_switch.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_non_interactive.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_notification_center.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_notification_detail.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_notifications.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_offload.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_offload_dict_messages.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_onboarding.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_output.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_reload.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_remote_client.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_resume_state.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_server.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_server_graph.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_server_helpers.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_server_manager.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_session_stats.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_sessions.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_shell_allow_list.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_skill_invocation.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_startup_fast_paths.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_state_migration.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_status.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_subagents.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_terminal_capabilities.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_terminal_escape.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_terminal_progress_preference.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_textual_adapter.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_theme.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_thread_selector.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_tool_display.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_ui.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_unicode_security.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_update_available.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_update_progress.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_version.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/test_welcome.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/tools/__init__.py +0 -0
- {deepagents_code-0.1.9 → deepagents_code-0.1.11}/tests/unit_tests/tools/test_fetch_url.py +0 -0
|
@@ -10,10 +10,10 @@ For monorepo-wide conventions (commit titles, lint, testing, docs, CI, benchmark
|
|
|
10
10
|
|
|
11
11
|
**Key Textual resources:**
|
|
12
12
|
|
|
13
|
-
- **Guide:** https://textual.textualize.io/guide
|
|
14
|
-
- **Widget gallery:** https://textual.textualize.io/widget_gallery
|
|
15
|
-
- **CSS reference:** https://textual.textualize.io/styles
|
|
16
|
-
- **API reference:** https://textual.textualize.io/api
|
|
13
|
+
- **Guide:** <https://textual.textualize.io/guide/>
|
|
14
|
+
- **Widget gallery:** <https://textual.textualize.io/widget_gallery/>
|
|
15
|
+
- **CSS reference:** <https://textual.textualize.io/styles/>
|
|
16
|
+
- **API reference:** <https://textual.textualize.io/api/>
|
|
17
17
|
|
|
18
18
|
### Styled text in widgets
|
|
19
19
|
|
|
@@ -92,8 +92,18 @@ To add a new slash command: (1) add a `SlashCommand` entry to `COMMANDS`, (2) se
|
|
|
92
92
|
`deepagents-code` supports LangChain-based chat model providers as optional dependencies. To add a new provider, update these files (all entries alphabetically sorted):
|
|
93
93
|
|
|
94
94
|
1. `deepagents_code/model_config.py` — add `"provider_name": "ENV_VAR_NAME"` to `PROVIDER_API_KEY_ENV`
|
|
95
|
-
2. `
|
|
96
|
-
3. `
|
|
95
|
+
2. `deepagents_code/model_config.py` — if the provider reads a *dedicated* endpoint env var, add `"provider_name": ("CANONICAL_BASE_URL", "ALTERNATE", ...)` to `PROVIDER_BASE_URL_ENV` (see guidelines below); omit the provider entirely when it has no provider-specific endpoint variable
|
|
96
|
+
3. `pyproject.toml` — add `provider = ["langchain-provider>=X.Y.Z,<N.0.0"]` to `[project.optional-dependencies]` and include it in the `all-providers` composite extra
|
|
97
|
+
4. `tests/unit_tests/test_model_config.py` — add `assert PROVIDER_API_KEY_ENV["provider_name"] == "ENV_VAR_NAME"` to `TestProviderApiKeyEnv.test_contains_major_providers`, and pin any `PROVIDER_BASE_URL_ENV` entry with a matching assertion
|
|
98
|
+
|
|
99
|
+
### `PROVIDER_BASE_URL_ENV` guidelines
|
|
100
|
+
|
|
101
|
+
`PROVIDER_BASE_URL_ENV` pairs a provider with the endpoint env var(s) its LangChain integration and SDK read, so a stored `/auth` endpoint resolves and an inherited gateway URL cannot leak. Before adding an entry:
|
|
102
|
+
|
|
103
|
+
- **Verify against source — never infer from naming.** Read both the `langchain-<provider>` chat model (look for `from_env` / `get_from_dict_or_env` / `secret_from_env`, or a `Field` default on the `base_url`/`endpoint` alias) and the underlying vendor SDK, and record the exact env var name each reads. The integration and the SDK often read different names (e.g. `GROQ_API_BASE` vs `GROQ_BASE_URL`).
|
|
104
|
+
- **Canonical name first.** Element `[0]` is written by `apply_stored_credentials` and read by `get_base_url`; every other name the integration or SDK may read goes in the tuple so it is cleared too. By convention the SDK's `*_BASE_URL`-style name is canonical and the integration's `*_API_BASE`/`*_API_URL` name is the alternate.
|
|
105
|
+
- **Never list another provider's shared var.** OpenAI-compatible providers (e.g. `deepseek`, `openrouter`, `together`, `xai`, `baseten`) sit on the `openai` SDK, whose only endpoint var is the shared `OPENAI_BASE_URL`. Listing it under those providers would clobber the user's real OpenAI endpoint when their credential is written or cleared — list only the provider's own var (e.g. `DEEPSEEK_API_BASE`), or nothing.
|
|
106
|
+
- **Omit providers with no dedicated var.** When the endpoint is a hardcoded default plus a constructor arg (`baseten`), an `api_base` arg resolved per-provider inside the library (`litellm`), or derived from the region (`google_vertexai`), leave the provider out. A `/auth` endpoint still resolves through `get_base_url`'s stored-credential step and reaches the model as the `base_url` kwarg.
|
|
97
107
|
|
|
98
108
|
**Not required** unless the provider's models have a distinctive name prefix (like `gpt-*`, `claude*`, `gemini*`):
|
|
99
109
|
|
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
# Deep Agents Code Changelog
|
|
4
4
|
|
|
5
|
+
## [0.1.11](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.10...deepagents-code==0.1.11) (2026-06-07)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
* Pause loading timer during approvals ([#3782](https://github.com/langchain-ai/deepagents/issues/3782)) ([f98fb0c](https://github.com/langchain-ai/deepagents/commit/f98fb0c80d08e408a018ea33a8aa7144180f4e93))
|
|
10
|
+
* Run auto-update before startup ([#3784](https://github.com/langchain-ai/deepagents/issues/3784)) ([c160ea3](https://github.com/langchain-ai/deepagents/commit/c160ea3eeda1d0ba707bb524cfd0ce087a854e08))
|
|
11
|
+
* Skip update prompts for editable installs ([#3781](https://github.com/langchain-ai/deepagents/issues/3781)) ([ae2874e](https://github.com/langchain-ai/deepagents/commit/ae2874e8ece96c04233c1a88a9da1bd7b9ee2bb2))
|
|
12
|
+
|
|
13
|
+
## [0.1.10](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.9...deepagents-code==0.1.10) (2026-06-05)
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* Pair model API keys with their endpoints ([#3770](https://github.com/langchain-ai/deepagents/issues/3770)) ([cf98030](https://github.com/langchain-ai/deepagents/commit/cf9803072dc0fdc1d5850c9fd2fc4eb6893ed8c9))
|
|
18
|
+
* Word-level double-click selection ([#3740](https://github.com/langchain-ai/deepagents/issues/3740)) ([4bb4286](https://github.com/langchain-ai/deepagents/commit/4bb4286a26c9c9bc69a36f2714d9eb0e3e5e4d40))
|
|
19
|
+
* Blueprint bootstrapping for Runloop sandboxes ([#3556](https://github.com/langchain-ai/deepagents/issues/3556)) ([13dafd8](https://github.com/langchain-ai/deepagents/commit/13dafd8823c4b530c8e096012733ad74cd501b59))
|
|
20
|
+
|
|
21
|
+
### Bug Fixes
|
|
22
|
+
|
|
23
|
+
* Propagate runtime model switches to subagents ([#3771](https://github.com/langchain-ai/deepagents/issues/3771)) ([f577182](https://github.com/langchain-ai/deepagents/commit/f577182c84746e625b65c3c2fda95f8ca21164cf))
|
|
24
|
+
* Guard pasted-path probes against `OSError` ([#3745](https://github.com/langchain-ai/deepagents/issues/3745)) ([c9617d3](https://github.com/langchain-ai/deepagents/commit/c9617d3594ab1448c4f3ee2212cdc66cbf138b77))
|
|
25
|
+
* Keep startup import prewarm from crashing the TUI mid-upgrade ([#3756](https://github.com/langchain-ai/deepagents/issues/3756)) ([867a2e5](https://github.com/langchain-ai/deepagents/commit/867a2e5c341bd9dfa70b47c7fafc194ac51d7469))
|
|
26
|
+
* Move MCP trust state out of user config ([#3742](https://github.com/langchain-ai/deepagents/issues/3742)) ([a97f2fd](https://github.com/langchain-ai/deepagents/commit/a97f2fd394e6b0b943225a0195b0901188bd368c))
|
|
27
|
+
|
|
5
28
|
## [0.1.9](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.8...deepagents-code==0.1.9) (2026-06-03)
|
|
6
29
|
|
|
7
30
|
### Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepagents-code
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.11
|
|
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/
|
|
@@ -26,7 +26,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
26
26
|
Classifier: Topic :: Terminals
|
|
27
27
|
Requires-Python: <4.0,>=3.11
|
|
28
28
|
Requires-Dist: aiosqlite<1.0.0,>=0.22.1
|
|
29
|
-
Requires-Dist: deepagents-acp<1.0.0,>=0.0.
|
|
29
|
+
Requires-Dist: deepagents-acp<1.0.0,>=0.0.8
|
|
30
30
|
Requires-Dist: deepagents==0.6.8
|
|
31
31
|
Requires-Dist: httpx<1.0.0,>=0.28.1
|
|
32
32
|
Requires-Dist: langchain-anthropic<2.0.0,>=1.4.4
|
|
@@ -81,7 +81,7 @@ Provides-Extra: all-sandboxes
|
|
|
81
81
|
Requires-Dist: langchain-agentcore-codeinterpreter<1.0.0,>=0.0.3; extra == 'all-sandboxes'
|
|
82
82
|
Requires-Dist: langchain-daytona>=0.0.6; extra == 'all-sandboxes'
|
|
83
83
|
Requires-Dist: langchain-modal>=0.0.4; extra == 'all-sandboxes'
|
|
84
|
-
Requires-Dist: langchain-runloop>=0.0.
|
|
84
|
+
Requires-Dist: langchain-runloop>=0.0.6; extra == 'all-sandboxes'
|
|
85
85
|
Provides-Extra: anthropic
|
|
86
86
|
Requires-Dist: langchain-anthropic<2.0.0,>=1.4.4; extra == 'anthropic'
|
|
87
87
|
Provides-Extra: baseten
|
|
@@ -123,7 +123,7 @@ Requires-Dist: langchain-perplexity<2.0.0,>=1.3.1; extra == 'perplexity'
|
|
|
123
123
|
Provides-Extra: quickjs
|
|
124
124
|
Requires-Dist: langchain-quickjs<0.2.0,>=0.1.3; extra == 'quickjs'
|
|
125
125
|
Provides-Extra: runloop
|
|
126
|
-
Requires-Dist: langchain-runloop>=0.0.
|
|
126
|
+
Requires-Dist: langchain-runloop>=0.0.6; extra == 'runloop'
|
|
127
127
|
Provides-Extra: together
|
|
128
128
|
Requires-Dist: langchain-together<2.0.0,>=0.4.0; extra == 'together'
|
|
129
129
|
Provides-Extra: vertex
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
| DC1 | API Keys / Credentials | `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `TAVILY_API_KEY`, `LANGSMITH_API_KEY`, `LANGGRAPH_API_KEY` | Critical | Process environment only; never written to disk by CLI code | N/A (in-memory) | Process lifetime | All — breach trigger |
|
|
157
157
|
| DC2 | Conversation Messages | User prompts, LLM responses, tool args/results | High | SQLite (`~/.deepagents/*.db`) via LangGraph checkpointer | No (local file, unencrypted) | Unbounded (session files persist) | GDPR if personal data is discussed |
|
|
158
158
|
| DC3 | System Prompt Content | `DA_SERVER_SYSTEM_PROMPT` env var; custom AGENTS.md contents | Medium | Process environment (transient); `~/.deepagents/{agent}/AGENTS.md` on disk | No | Config lifetime | None direct |
|
|
159
|
-
| DC4 | MCP Trust Fingerprints | `
|
|
159
|
+
| DC4 | MCP Trust Fingerprints | `projects.*` in `mcp_trust.json` | Low | `~/.deepagents/.state/mcp_trust.json` | No | Until revoked | None |
|
|
160
160
|
| DC5 | Offloaded Conversation History | Summarized + raw conversation messages written to sandbox backend | High | Sandbox filesystem at `/conversation_history/{thread_id}.md` | Depends on sandbox provider | Sandbox session lifetime | GDPR if personal data is discussed |
|
|
161
161
|
|
|
162
162
|
### Data Classification Details
|
|
@@ -134,6 +134,16 @@ and `/api/show`. See `_ollama_discovery_enabled` for accepted truthy/falsy
|
|
|
134
134
|
values.
|
|
135
135
|
"""
|
|
136
136
|
|
|
137
|
+
RESTARTED_AFTER_UPDATE = "DEEPAGENTS_CODE_RESTARTED_AFTER_UPDATE"
|
|
138
|
+
"""Internal sentinel recording the target version immediately before the
|
|
139
|
+
startup auto-update re-execs the process.
|
|
140
|
+
|
|
141
|
+
Not user-facing. The re-exec'd process consumes it and, if that same version
|
|
142
|
+
still reports as available (a no-op upgrade that did not change the running
|
|
143
|
+
version), skips auto-updating to break out of an otherwise endless
|
|
144
|
+
upgrade/restart loop. Set and read internally across `os.execv`.
|
|
145
|
+
"""
|
|
146
|
+
|
|
137
147
|
SERVER_ENV_PREFIX = "DEEPAGENTS_CODE_SERVER_"
|
|
138
148
|
"""Environment variable prefix used to pass CLI config to the server subprocess."""
|
|
139
149
|
|
|
@@ -180,7 +180,7 @@ class ServerConfig:
|
|
|
180
180
|
"""Existing sandbox ID to attach to; `None` creates a fresh sandbox."""
|
|
181
181
|
|
|
182
182
|
sandbox_snapshot_name: str | None = None
|
|
183
|
-
"""Sandbox snapshot
|
|
183
|
+
"""Sandbox snapshot (langsmith) or blueprint (runloop) name; must be `None`
|
|
184
184
|
when `sandbox_id` is set."""
|
|
185
185
|
|
|
186
186
|
sandbox_setup: str | None = None
|
|
@@ -365,8 +365,8 @@ class ServerConfig:
|
|
|
365
365
|
server subprocess for `ShellAllowListMiddleware`.
|
|
366
366
|
sandbox_type: Sandbox type.
|
|
367
367
|
sandbox_id: Existing sandbox ID to reuse.
|
|
368
|
-
sandbox_snapshot_name:
|
|
369
|
-
|
|
368
|
+
sandbox_snapshot_name: Snapshot (langsmith) or blueprint (runloop)
|
|
369
|
+
name to use or create.
|
|
370
370
|
sandbox_setup: Path to setup script for the sandbox.
|
|
371
371
|
enable_shell: Enable shell execution tools.
|
|
372
372
|
enable_ask_user: Enable ask_user tool.
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
r"""Runtime patches over Textual internals, imported for side effect.
|
|
2
|
+
|
|
3
|
+
This module hosts two independent best-effort patches over private Textual
|
|
4
|
+
APIs. Each guards its own import/assignment and degrades to stock Textual
|
|
5
|
+
behavior (logging a warning) if the targeted internals move, so they have
|
|
6
|
+
separate lifecycles — do not delete the whole file when only one lands
|
|
7
|
+
upstream.
|
|
8
|
+
|
|
9
|
+
1. Alt-modifier preservation on legacy `ESC + <byte>` sequences. Upstream
|
|
10
|
+
`XTermParser._sequence_to_key_events` drops the `alt` flag on the
|
|
11
|
+
tuple-branch fast path, so VSCode's `sendSequence` shift+enter binding
|
|
12
|
+
(which writes `\x1b\r` to the PTY) arrives as bare `enter` instead of
|
|
13
|
+
`alt+enter`. Tracked in Textualize/textual#6378. Remove this patch and
|
|
14
|
+
the Textual pin comment in `pyproject.toml` when that lands.
|
|
15
|
+
|
|
16
|
+
2. Double-click word selection. Stock Textual selects the entire widget on
|
|
17
|
+
a click chain; these patches narrow a double-click (and double-click
|
|
18
|
+
drag) to word boundaries. No upstream issue tracks this yet, so it has
|
|
19
|
+
no removal criterion — it stays until Textual grows native word select.
|
|
20
|
+
|
|
21
|
+
Imported for side effect from `app.py` before any `App()` is created.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import logging
|
|
27
|
+
from inspect import isawaitable
|
|
28
|
+
from typing import TYPE_CHECKING
|
|
29
|
+
|
|
30
|
+
from rich.text import Text
|
|
31
|
+
from textual import __version__ as _textual_version
|
|
32
|
+
from textual.content import Content
|
|
33
|
+
from textual.geometry import Offset
|
|
34
|
+
from textual.selection import Selection
|
|
35
|
+
|
|
36
|
+
if TYPE_CHECKING:
|
|
37
|
+
from collections.abc import Iterable
|
|
38
|
+
|
|
39
|
+
from textual.events import Click, Event
|
|
40
|
+
from textual.screen import Screen
|
|
41
|
+
from textual.selection import SelectState
|
|
42
|
+
from textual.widget import Widget
|
|
43
|
+
|
|
44
|
+
logger = logging.getLogger(__name__)
|
|
45
|
+
|
|
46
|
+
_ESC_PREFIX_LEN = 2
|
|
47
|
+
_DOUBLE_CLICK_CHAIN = 2
|
|
48
|
+
_TRIPLE_CLICK_CHAIN = 3
|
|
49
|
+
_DEEPAGENTS_WORD_SELECT_ACTIVE = "_deepagents_word_select_active"
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
from textual import events
|
|
53
|
+
from textual._ansi_sequences import (
|
|
54
|
+
ANSI_SEQUENCES_KEYS, # noqa: PLC2701
|
|
55
|
+
IGNORE_SEQUENCE, # noqa: PLC2701
|
|
56
|
+
)
|
|
57
|
+
from textual._xterm_parser import XTermParser # noqa: PLC2701
|
|
58
|
+
|
|
59
|
+
_original = XTermParser._sequence_to_key_events
|
|
60
|
+
except (ImportError, AttributeError) as exc: # pragma: no cover - defensive
|
|
61
|
+
logger.warning("Textual keyboard parser patch skipped: %s", exc)
|
|
62
|
+
else:
|
|
63
|
+
|
|
64
|
+
def _emit_alt(keys: tuple, character: str | None) -> Iterable[events.Key]:
|
|
65
|
+
for key in keys:
|
|
66
|
+
yield events.Key(f"alt+{key.value}", character)
|
|
67
|
+
|
|
68
|
+
def _sequence_to_key_events_with_alt(
|
|
69
|
+
self: XTermParser, sequence: str, alt: bool = False
|
|
70
|
+
) -> Iterable[events.Key]:
|
|
71
|
+
# Fast path: \x1b<byte> on first pass. Short-circuits the ~100 ms
|
|
72
|
+
# escape-delay wait when both bytes arrive together. Semantic side
|
|
73
|
+
# effect: \x1b\x1b dispatches as `alt+escape` with no delay, matching
|
|
74
|
+
# crossterm and Node TTY.
|
|
75
|
+
if not alt and len(sequence) == _ESC_PREFIX_LEN and sequence[0] == "\x1b":
|
|
76
|
+
inner = ANSI_SEQUENCES_KEYS.get(sequence[1])
|
|
77
|
+
if inner is not IGNORE_SEQUENCE and isinstance(inner, tuple):
|
|
78
|
+
yield from _emit_alt(inner, None)
|
|
79
|
+
return
|
|
80
|
+
# Correctness fix (Textualize/textual#6378): preserve `alt` on the
|
|
81
|
+
# reissue path for single-byte tuple mappings.
|
|
82
|
+
if alt:
|
|
83
|
+
keys = ANSI_SEQUENCES_KEYS.get(sequence)
|
|
84
|
+
if keys is not IGNORE_SEQUENCE and isinstance(keys, tuple):
|
|
85
|
+
character = sequence if len(sequence) == 1 else None
|
|
86
|
+
yield from _emit_alt(keys, character)
|
|
87
|
+
return
|
|
88
|
+
yield from _original(self, sequence, alt=alt)
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
XTermParser._sequence_to_key_events = _sequence_to_key_events_with_alt # ty: ignore[invalid-assignment]
|
|
92
|
+
except (AttributeError, TypeError) as exc: # pragma: no cover - defensive
|
|
93
|
+
logger.warning("Textual keyboard parser patch assignment rejected: %s", exc)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _rendered_text(widget: Widget) -> str | None:
|
|
97
|
+
visual = widget._render() # match Textual's get_selection path
|
|
98
|
+
if isinstance(visual, (Content, Text)):
|
|
99
|
+
return str(visual)
|
|
100
|
+
return None
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _word_bounds(text: str, offset: Offset) -> tuple[Offset, Offset] | None:
|
|
104
|
+
lines = text.splitlines()
|
|
105
|
+
if not lines:
|
|
106
|
+
return None
|
|
107
|
+
|
|
108
|
+
y = min(max(offset.y, 0), len(lines) - 1)
|
|
109
|
+
line = lines[y]
|
|
110
|
+
if not line:
|
|
111
|
+
return None
|
|
112
|
+
|
|
113
|
+
x = min(max(offset.x, 0), len(line))
|
|
114
|
+
index = min(x, len(line) - 1)
|
|
115
|
+
if line[index].isspace():
|
|
116
|
+
# A click just past the final character (x == len(line)) lands on the
|
|
117
|
+
# virtual end-of-line position; snap back onto the trailing word so
|
|
118
|
+
# double-clicking after a word still selects it. Genuine whitespace
|
|
119
|
+
# clicks fall through and select nothing.
|
|
120
|
+
if x == len(line) and x > 0 and not line[x - 1].isspace():
|
|
121
|
+
index = x - 1
|
|
122
|
+
else:
|
|
123
|
+
return None
|
|
124
|
+
|
|
125
|
+
start = index
|
|
126
|
+
while start > 0 and not line[start - 1].isspace():
|
|
127
|
+
start -= 1
|
|
128
|
+
|
|
129
|
+
end = index + 1
|
|
130
|
+
while end < len(line) and not line[end].isspace():
|
|
131
|
+
end += 1
|
|
132
|
+
|
|
133
|
+
return Offset(start, y), Offset(end, y)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _word_selection(widget: Widget, selection: Selection) -> Selection | None:
|
|
137
|
+
if selection.start is None or selection.end is None:
|
|
138
|
+
return None
|
|
139
|
+
|
|
140
|
+
text = _rendered_text(widget)
|
|
141
|
+
if text is None:
|
|
142
|
+
return None
|
|
143
|
+
|
|
144
|
+
start, end = selection.start, selection.end
|
|
145
|
+
# `Offset.transpose` is (y, x) — Textual's reading-order key. A backward
|
|
146
|
+
# drag leaves end before start in reading order; normalize so the word
|
|
147
|
+
# bounds below extend outward from the correct endpoints.
|
|
148
|
+
if end.transpose < start.transpose:
|
|
149
|
+
start, end = end, start
|
|
150
|
+
|
|
151
|
+
start_bounds = _word_bounds(text, start)
|
|
152
|
+
end_bounds = _word_bounds(text, end)
|
|
153
|
+
if start_bounds is None and end_bounds is None:
|
|
154
|
+
return None
|
|
155
|
+
|
|
156
|
+
return Selection(
|
|
157
|
+
start_bounds[0] if start_bounds is not None else start,
|
|
158
|
+
end_bounds[1] if end_bounds is not None else end,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _select_word_at_click(widget: Widget, event: Click) -> bool:
|
|
163
|
+
offset = event.get_content_offset(widget)
|
|
164
|
+
if offset is None:
|
|
165
|
+
return False
|
|
166
|
+
|
|
167
|
+
text = _rendered_text(widget)
|
|
168
|
+
if text is None:
|
|
169
|
+
return False
|
|
170
|
+
|
|
171
|
+
bounds = _word_bounds(text, offset)
|
|
172
|
+
if bounds is None:
|
|
173
|
+
widget.screen.clear_selection()
|
|
174
|
+
return True
|
|
175
|
+
|
|
176
|
+
widget.screen.selections = {widget: Selection(*bounds)}
|
|
177
|
+
return True
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
try:
|
|
181
|
+
from textual import events as _events
|
|
182
|
+
from textual.screen import Screen as _Screen
|
|
183
|
+
from textual.widget import Widget as _Widget
|
|
184
|
+
|
|
185
|
+
_original_forward_event = _Screen._forward_event
|
|
186
|
+
_original_watch_select_state = _Screen._watch__select_state
|
|
187
|
+
_original_widget_on_click = _Widget._on_click
|
|
188
|
+
except (ImportError, AttributeError) as exc: # pragma: no cover - defensive
|
|
189
|
+
logger.warning(
|
|
190
|
+
"Textual word-selection patch skipped (textual %s): %s",
|
|
191
|
+
_textual_version,
|
|
192
|
+
exc,
|
|
193
|
+
)
|
|
194
|
+
else:
|
|
195
|
+
|
|
196
|
+
def _is_word_select_start(screen: Screen, event: Event) -> bool:
|
|
197
|
+
# Mirrors Textual's own click-chain detection (App._on_mouse_down),
|
|
198
|
+
# reading its private `_click_chain_last_*` bookkeeping to recognize
|
|
199
|
+
# the second press of a double-click before Textual increments the
|
|
200
|
+
# chain count. Re-verify these attribute names on every Textual bump.
|
|
201
|
+
if not isinstance(event, _events.MouseDown) or screen.app.mouse_captured:
|
|
202
|
+
return False
|
|
203
|
+
|
|
204
|
+
last_offset = getattr(screen.app, "_click_chain_last_offset", None)
|
|
205
|
+
last_time = getattr(screen.app, "_click_chain_last_time", None)
|
|
206
|
+
if last_offset != event.screen_offset or last_time is None:
|
|
207
|
+
return False
|
|
208
|
+
|
|
209
|
+
if event.time - last_time > screen.app.CLICK_CHAIN_TIME_THRESHOLD:
|
|
210
|
+
return False
|
|
211
|
+
|
|
212
|
+
select_widget, select_offset = screen.get_widget_and_offset_at(event.x, event.y)
|
|
213
|
+
return (
|
|
214
|
+
select_widget is not None
|
|
215
|
+
and select_widget.allow_select
|
|
216
|
+
and screen.allow_select
|
|
217
|
+
and screen.app.ALLOW_SELECT
|
|
218
|
+
and select_offset is not None
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
def _forward_event_with_word_select(self: Screen, event: Event) -> None:
|
|
222
|
+
if isinstance(event, _events.MouseDown):
|
|
223
|
+
setattr(
|
|
224
|
+
self,
|
|
225
|
+
_DEEPAGENTS_WORD_SELECT_ACTIVE,
|
|
226
|
+
_is_word_select_start(self, event),
|
|
227
|
+
)
|
|
228
|
+
try:
|
|
229
|
+
_original_forward_event(self, event)
|
|
230
|
+
finally:
|
|
231
|
+
if isinstance(event, _events.MouseUp):
|
|
232
|
+
setattr(self, _DEEPAGENTS_WORD_SELECT_ACTIVE, False)
|
|
233
|
+
|
|
234
|
+
async def _watch_select_state_with_word_select(
|
|
235
|
+
self: Screen,
|
|
236
|
+
select_state: SelectState | None,
|
|
237
|
+
) -> None:
|
|
238
|
+
result = _original_watch_select_state(self, select_state)
|
|
239
|
+
# `_watch__select_state` is synchronous in the pinned Textual; the
|
|
240
|
+
# isawaitable guard tolerates a future release making it a coroutine
|
|
241
|
+
# without forcing a same-day patch update.
|
|
242
|
+
if isawaitable(result):
|
|
243
|
+
await result
|
|
244
|
+
if not getattr(self, _DEEPAGENTS_WORD_SELECT_ACTIVE, False):
|
|
245
|
+
return
|
|
246
|
+
|
|
247
|
+
selections = dict(self.selections)
|
|
248
|
+
changed = False
|
|
249
|
+
for widget, selection in selections.items():
|
|
250
|
+
word_selection = _word_selection(widget, selection)
|
|
251
|
+
if word_selection is None or word_selection == selection:
|
|
252
|
+
continue
|
|
253
|
+
selections[widget] = word_selection
|
|
254
|
+
changed = True
|
|
255
|
+
|
|
256
|
+
if changed:
|
|
257
|
+
self.selections = selections
|
|
258
|
+
|
|
259
|
+
async def _on_click_with_word_select(self: Widget, event: Click) -> None:
|
|
260
|
+
if (
|
|
261
|
+
event.widget is self
|
|
262
|
+
and self.allow_select
|
|
263
|
+
and self.screen.allow_select
|
|
264
|
+
and self.app.ALLOW_SELECT
|
|
265
|
+
):
|
|
266
|
+
if event.chain == _DOUBLE_CLICK_CHAIN and _select_word_at_click(
|
|
267
|
+
self, event
|
|
268
|
+
):
|
|
269
|
+
await self.broker_event("click", event)
|
|
270
|
+
return
|
|
271
|
+
if event.chain == _TRIPLE_CLICK_CHAIN:
|
|
272
|
+
self.text_select_all()
|
|
273
|
+
await self.broker_event("click", event)
|
|
274
|
+
return
|
|
275
|
+
|
|
276
|
+
await _original_widget_on_click(self, event)
|
|
277
|
+
|
|
278
|
+
try:
|
|
279
|
+
_Screen._forward_event = _forward_event_with_word_select # ty: ignore[invalid-assignment]
|
|
280
|
+
_Screen._watch__select_state = _watch_select_state_with_word_select # ty: ignore[invalid-assignment]
|
|
281
|
+
_Widget._on_click = _on_click_with_word_select # ty: ignore[invalid-assignment]
|
|
282
|
+
except (AttributeError, TypeError) as exc: # pragma: no cover - defensive
|
|
283
|
+
logger.warning(
|
|
284
|
+
"Textual word-selection patch assignment rejected (textual %s): %s",
|
|
285
|
+
_textual_version,
|
|
286
|
+
exc,
|
|
287
|
+
)
|
|
@@ -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.11" # 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."""
|
|
@@ -1205,40 +1205,53 @@ def create_cli_agent(
|
|
|
1205
1205
|
else settings.get_project_agents_dir()
|
|
1206
1206
|
)
|
|
1207
1207
|
|
|
1208
|
+
def _subagent_cli_middleware(*, has_explicit_model: bool) -> list[AgentMiddleware]:
|
|
1209
|
+
middleware: list[AgentMiddleware] = []
|
|
1210
|
+
if not has_explicit_model:
|
|
1211
|
+
middleware.append(ConfigurableModelMiddleware())
|
|
1212
|
+
if restrictive_shell_allow_list is not None:
|
|
1213
|
+
middleware.append(ShellAllowListMiddleware(restrictive_shell_allow_list))
|
|
1214
|
+
return middleware
|
|
1215
|
+
|
|
1208
1216
|
for subagent_meta in list_subagents(
|
|
1209
1217
|
user_agents_dir=user_agents_dir,
|
|
1210
1218
|
project_agents_dir=project_agents_dir,
|
|
1211
1219
|
):
|
|
1220
|
+
# Treat a falsy spec (`None` or `""`) as "no explicit model" so an empty
|
|
1221
|
+
# `model:` in subagent frontmatter inherits the runtime model rather than
|
|
1222
|
+
# being forwarded verbatim to `resolve_model("")`.
|
|
1223
|
+
model_spec = subagent_meta["model"]
|
|
1224
|
+
has_explicit_model = bool(model_spec)
|
|
1212
1225
|
subagent: SubAgent = {
|
|
1213
1226
|
"name": subagent_meta["name"],
|
|
1214
1227
|
"description": subagent_meta["description"],
|
|
1215
1228
|
"system_prompt": subagent_meta["system_prompt"],
|
|
1216
1229
|
}
|
|
1217
|
-
if
|
|
1218
|
-
subagent["model"] =
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1230
|
+
if model_spec:
|
|
1231
|
+
subagent["model"] = model_spec
|
|
1232
|
+
subagent_middleware = _subagent_cli_middleware(
|
|
1233
|
+
has_explicit_model=has_explicit_model
|
|
1234
|
+
)
|
|
1235
|
+
if subagent_middleware:
|
|
1236
|
+
subagent["middleware"] = subagent_middleware
|
|
1223
1237
|
custom_subagents.append(subagent)
|
|
1224
1238
|
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
)
|
|
1239
|
+
from deepagents.middleware.subagents import (
|
|
1240
|
+
GENERAL_PURPOSE_SUBAGENT,
|
|
1241
|
+
SubAgent as RuntimeSubAgent,
|
|
1242
|
+
)
|
|
1230
1243
|
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1244
|
+
if not any(
|
|
1245
|
+
subagent["name"] == GENERAL_PURPOSE_SUBAGENT["name"]
|
|
1246
|
+
for subagent in custom_subagents
|
|
1247
|
+
):
|
|
1248
|
+
general_purpose_subagent: RuntimeSubAgent = {
|
|
1249
|
+
"name": GENERAL_PURPOSE_SUBAGENT["name"],
|
|
1250
|
+
"description": GENERAL_PURPOSE_SUBAGENT["description"],
|
|
1251
|
+
"system_prompt": GENERAL_PURPOSE_SUBAGENT["system_prompt"],
|
|
1252
|
+
"middleware": _subagent_cli_middleware(has_explicit_model=False),
|
|
1253
|
+
}
|
|
1254
|
+
custom_subagents.append(general_purpose_subagent)
|
|
1242
1255
|
|
|
1243
1256
|
# Build middleware stack based on enabled features
|
|
1244
1257
|
agent_middleware = [
|