deepagents-code 0.1.12__tar.gz → 0.1.14__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.12 → deepagents_code-0.1.14}/AGENTS.md +9 -1
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/CHANGELOG.md +42 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/PKG-INFO +23 -23
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/THREAT_MODEL.md +7 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/_debug.py +29 -9
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/_env_vars.py +37 -7
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/_server_config.py +3 -1
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/_textual_patches.py +134 -1
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/_version.py +1 -1
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/agent.py +106 -22
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/app.py +528 -51
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/config.py +327 -137
- deepagents_code-0.1.14/deepagents_code/config_commands.py +487 -0
- deepagents_code-0.1.14/deepagents_code/config_manifest.py +1055 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/extras_info.py +79 -0
- deepagents_code-0.1.14/deepagents_code/integrations/sandbox_config.py +198 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/integrations/sandbox_factory.py +74 -71
- deepagents_code-0.1.14/deepagents_code/integrations/sandbox_provider.py +137 -0
- deepagents_code-0.1.14/deepagents_code/integrations/sandbox_registry.py +341 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/local_context.py +104 -16
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/main.py +321 -73
- deepagents_code-0.1.14/deepagents_code/managed_tools.py +470 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/model_config.py +34 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/server.py +25 -1
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/subagents.py +72 -5
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/textual_adapter.py +33 -10
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/theme.py +26 -2
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/ui.py +60 -1
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/ask_user.py +5 -2
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/autocomplete.py +94 -23
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/chat_input.py +219 -5
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/diff.py +17 -13
- deepagents_code-0.1.14/deepagents_code/widgets/install_confirm.py +120 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/messages.py +13 -2
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/status.py +113 -1
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/theme_selector.py +60 -6
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/welcome.py +24 -175
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/pyproject.toml +19 -18
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_agent.py +237 -11
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_app.py +1145 -40
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_args.py +73 -1
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_autocomplete.py +378 -3
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_charset.py +17 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_chat_input.py +297 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_config.py +428 -0
- deepagents_code-0.1.14/tests/unit_tests/test_config_manifest.py +999 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_debug.py +72 -1
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_install_command.py +127 -4
- deepagents_code-0.1.14/tests/unit_tests/test_install_confirm.py +88 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_local_context.py +233 -45
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_main.py +117 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_main_args.py +347 -0
- deepagents_code-0.1.14/tests/unit_tests/test_managed_tools.py +690 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_model_config.py +23 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_reload.py +11 -1
- deepagents_code-0.1.14/tests/unit_tests/test_sandbox_config.py +140 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_sandbox_factory.py +86 -1
- deepagents_code-0.1.14/tests/unit_tests/test_sandbox_provider.py +50 -0
- deepagents_code-0.1.14/tests/unit_tests/test_sandbox_registry.py +305 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_server_helpers.py +67 -9
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_startup_fast_paths.py +2 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_status.py +216 -5
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_subagents.py +168 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_textual_adapter.py +218 -29
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_textual_patches.py +115 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_theme.py +561 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_ui.py +34 -1
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_version.py +123 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_welcome.py +47 -143
- deepagents_code-0.1.14/tests/unit_tests/widgets/__init__.py +0 -0
- deepagents_code-0.1.14/tests/unit_tests/widgets/test_diff.py +130 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/uv.lock +110 -171
- deepagents_code-0.1.12/deepagents_code/integrations/sandbox_provider.py +0 -71
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/.gitignore +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/COMMANDS.md +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/DEV.md +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/Makefile +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/README.md +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/__init__.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/__main__.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/_ask_user_types.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/_cli_context.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/_constants.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/_git.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/_session_stats.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/_startup_error.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/_testing_models.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/app.tcss +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/ask_user.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/auth_display.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/auth_store.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/built_in_skills/__init__.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/built_in_skills/remember/SKILL.md +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/built_in_skills/skill-creator/SKILL.md +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/clipboard.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/command_registry.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/configurable_model.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/default_agent_prompt.md +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/editor.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/event_bus.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/file_ops.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/filesystem_empty_result.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/formatting.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/hooks.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/input.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/integrations/__init__.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/iterm_cursor_guide.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/mcp_auth.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/mcp_commands.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/mcp_disabled.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/mcp_login_service.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/mcp_oauth_ui.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/mcp_providers/__init__.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/mcp_providers/_registry.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/mcp_providers/base.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/mcp_providers/github.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/mcp_providers/slack.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/mcp_tools.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/mcp_trust.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/media_utils.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/memory_guard.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/non_interactive.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/notifications.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/offload.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/onboarding.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/output.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/project_utils.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/py.typed +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/remote_client.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/resume_state.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/server_graph.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/server_manager.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/sessions.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/skills/__init__.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/skills/commands.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/skills/invocation.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/skills/load.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/state_migration.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/system_prompt.md +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/terminal_capabilities.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/terminal_escape.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/tool_display.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/tools.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/unicode_security.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/update_check.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/__init__.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/_links.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/agent_selector.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/approval.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/auth.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/cwd_switch.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/history.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/launch_init.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/loading.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/mcp_login.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/mcp_reconnect.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/mcp_viewer.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/message_store.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/model_selector.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/notification_center.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/notification_detail.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/notification_settings.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/restart_prompt.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/thread_selector.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/tool_renderers.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/tool_widgets.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/update_available.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/deepagents_code/widgets/update_progress.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/examples/skills/arxiv-search/SKILL.md +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/examples/skills/arxiv-search/arxiv_search.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/examples/skills/langgraph-docs/SKILL.md +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/examples/skills/skill-creator/SKILL.md +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/examples/skills/web-research/SKILL.md +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/images/tui.png +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/scripts/check_imports.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/scripts/debug_server.sh +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/scripts/generate_commands_catalog.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/scripts/install.sh +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/README.md +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/integration_tests/__init__.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/integration_tests/benchmarks/__init__.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/integration_tests/conftest.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/integration_tests/test_acp_mode.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/integration_tests/test_compact_resume.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/integration_tests/test_sandbox_factory.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/integration_tests/test_sandbox_operations.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/__init__.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/conftest.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/skills/__init__.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/skills/test_commands.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/skills/test_load.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/skills/test_skills_json.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_agent_friendly.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_agent_selector.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_approval.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_ask_user.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_ask_user_middleware.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_auth_display.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_auth_store.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_auth_widgets.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_clipboard.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_command_registry.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_compact_tool.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_configurable_model.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_cursor_blink.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_cwd_switch.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_editor.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_end_to_end.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_env_vars.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_event_bus.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_exception_handling.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_extras_info.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_file_ops.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_filesystem_empty_result.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_formatting.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_git.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_history.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_hooks.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_imports.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_input_parsing.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_launch_init.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_links.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_loading.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_main_acp_mode.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_mcp_auth.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_mcp_commands.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_mcp_disabled.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_mcp_login_modal.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_mcp_login_service.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_mcp_oauth_ui.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_mcp_reconnect.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_mcp_tools.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_mcp_trust.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_mcp_viewer.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_media_utils.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_memory_guard.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_message_store.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_messages.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_model_selector.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_model_switch.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_non_interactive.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_notification_center.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_notification_detail.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_notifications.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_offload.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_offload_dict_messages.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_onboarding.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_output.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_remote_client.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_restart_prompt.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_resume_state.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_server.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_server_config.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_server_graph.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_server_manager.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_session_stats.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_sessions.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_shell_allow_list.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_skill_invocation.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_state_migration.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_terminal_capabilities.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_terminal_escape.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_terminal_progress_preference.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_thread_selector.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_tool_display.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_unicode_security.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_update_available.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_update_check.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/test_update_progress.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/tools/__init__.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/tools/test_current_thread.py +0 -0
- {deepagents_code-0.1.12 → deepagents_code-0.1.14}/tests/unit_tests/tools/test_fetch_url.py +0 -0
|
@@ -38,6 +38,13 @@ Textual's `App.notify(message)` parses the message string as Rich markup by defa
|
|
|
38
38
|
|
|
39
39
|
`console.print()` defaults to `highlight=True`, which runs `ReprHighlighter` and auto-applies bold + cyan to any detected numbers. This visually overrides subtle styles like `dim` (bold cancels dim in most terminals). Pass `highlight=False` on any `console.print()` call where the content contains numbers and consistent dim/subtle styling matters.
|
|
40
40
|
|
|
41
|
+
### Glyphs and spinners — reuse, don't redefine
|
|
42
|
+
|
|
43
|
+
Charset-dependent characters and animations have **single sources of truth**. Reuse them instead of hand-rolling new ones — copies drift, and (more subtly) a hardcoded Unicode literal won't degrade to ASCII on terminals that need it.
|
|
44
|
+
|
|
45
|
+
- **Glyphs** (checkmarks, arrows, ellipsis, cursor, box-drawing, branch icon, etc.): pull from `get_glyphs()` (`config.Glyphs`). Each glyph has a Unicode and an ASCII variant; `get_glyphs()` returns the right set for the active terminal. Never inline `"✓"`, `"…"`, `"›"`, and friends.
|
|
46
|
+
- **Animated spinners**: reuse the `Spinner` class in `widgets/loading.py`, which wraps `get_glyphs().spinner_frames` (braille on Unicode, `(-) (\) (|) (/)` on ASCII) and exposes `next_frame()`/`current_frame()`. Do **not** define your own frame tuples or interval constants for a spinner — drive a `Spinner` on a `set_interval`. The status-bar reconnect indicator (`widgets/status.py`) is the reference example; it ticks at the same 0.1s cadence as `LoadingWidget`. All connection/queue progress lives in the status bar — the welcome banner deliberately stays out of it, so there are currently no bespoke spinners to carve an exception for.
|
|
47
|
+
|
|
41
48
|
### Textual patterns used in this codebase
|
|
42
49
|
|
|
43
50
|
- **Workers** (`@work` decorator) for async operations - see [Workers guide](https://textual.textualize.io/guide/workers/)
|
|
@@ -140,7 +147,8 @@ To add a new slash command: (1) add a `SlashCommand` entry to `COMMANDS`, (2) se
|
|
|
140
147
|
1. `deepagents_code/model_config.py` — add `"provider_name": "ENV_VAR_NAME"` to `PROVIDER_API_KEY_ENV`
|
|
141
148
|
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
|
|
142
149
|
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
|
|
143
|
-
4. `
|
|
150
|
+
4. `deepagents_code/model_config.py` — add `"provider_name"` to `RETRY_PARAM_BY_PROVIDER` if the provider's chat model accepts `max_retries`
|
|
151
|
+
5. `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
|
|
144
152
|
|
|
145
153
|
### `PROVIDER_BASE_URL_ENV` guidelines
|
|
146
154
|
|
|
@@ -2,6 +2,48 @@
|
|
|
2
2
|
|
|
3
3
|
# Deep Agents Code Changelog
|
|
4
4
|
|
|
5
|
+
## [0.1.14](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.13...deepagents-code==0.1.14) (2026-06-12)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
* Surface editable mode and core deps in `/version` ([#3898](https://github.com/langchain-ai/deepagents/issues/3898)) ([d4f5a12](https://github.com/langchain-ai/deepagents/commit/d4f5a12cc6d73dc19d24d5748242705d79fa65bf))
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* Don't move cursor on click that re-focuses terminal ([#3893](https://github.com/langchain-ai/deepagents/issues/3893)) ([b76788b](https://github.com/langchain-ai/deepagents/commit/b76788b7850e910fe2882cb1a62ffff6ff5085b0))
|
|
14
|
+
* Label `-r` resume as `"Resuming..."` in the status bar ([#3892](https://github.com/langchain-ai/deepagents/issues/3892)) ([70cd286](https://github.com/langchain-ai/deepagents/commit/70cd28643bc2ca7da5a61a7b7203c6de2266ca4e))
|
|
15
|
+
* Scope `@` file completion to current cwd ([#3874](https://github.com/langchain-ai/deepagents/issues/3874)) ([dd237ac](https://github.com/langchain-ai/deepagents/commit/dd237acd21a39e98e37bb9d98dfae09bc44d5457))
|
|
16
|
+
* Set dcode agent names in trace metadata ([#3901](https://github.com/langchain-ai/deepagents/issues/3901)) ([ac94dd6](https://github.com/langchain-ai/deepagents/commit/ac94dd6b139211187cad8685c1152f02c51ba086))
|
|
17
|
+
* Surface untracked files in `@` completion ([#3872](https://github.com/langchain-ai/deepagents/issues/3872)) ([2bdf6ea](https://github.com/langchain-ai/deepagents/commit/2bdf6ea329c6b4c8be5f0075528e00c7ce2c1e6a))
|
|
18
|
+
* Warn on misconfigured subagent files ([#3873](https://github.com/langchain-ai/deepagents/issues/3873)) ([f1614d6](https://github.com/langchain-ai/deepagents/commit/f1614d67827c3d4d3bd01a784f57f83a50ec3410))
|
|
19
|
+
|
|
20
|
+
### Performance Improvements
|
|
21
|
+
|
|
22
|
+
* Cache theme colors/charset, fix `O(n^2)` tool-call streaming ([#3881](https://github.com/langchain-ai/deepagents/issues/3881)) ([9d463f5](https://github.com/langchain-ai/deepagents/commit/9d463f52fb3a4d458477982963f3d278d5362b48))
|
|
23
|
+
|
|
24
|
+
## [0.1.13](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.12...deepagents-code==0.1.13) (2026-06-11)
|
|
25
|
+
|
|
26
|
+
### Features
|
|
27
|
+
|
|
28
|
+
* Pluggable third-party sandbox backends ([#3842](https://github.com/langchain-ai/deepagents/issues/3842)) ([2b635a7](https://github.com/langchain-ai/deepagents/commit/2b635a7e6e6b50ca8ce783c2ac96ed8643ae0224))
|
|
29
|
+
* Auto-install ripgrep on first run ([#3348](https://github.com/langchain-ai/deepagents/issues/3348)) ([fecf22b](https://github.com/langchain-ai/deepagents/commit/fecf22b0909e79ff7bdf180baf20abf5fdf1f390))
|
|
30
|
+
* `config` command and canonical config manifest ([#3763](https://github.com/langchain-ai/deepagents/issues/3763)) ([79899a3](https://github.com/langchain-ai/deepagents/commit/79899a306d01de6217a1dfcc013ae92c808a47a0))
|
|
31
|
+
* Confirm modal for `/install --package` ([#3840](https://github.com/langchain-ai/deepagents/issues/3840)) ([3d75026](https://github.com/langchain-ai/deepagents/commit/3d75026e2f241648fae78d9e1de2cbb4985f58ff))
|
|
32
|
+
* Copy focused input selection on `Ctrl+C` ([#3841](https://github.com/langchain-ai/deepagents/issues/3841)) ([99f782c](https://github.com/langchain-ai/deepagents/commit/99f782cf08336c200d02a24ae4edaa650af67ed2))
|
|
33
|
+
* `[retries]` config ([#3772](https://github.com/langchain-ai/deepagents/issues/3772)) ([9334d91](https://github.com/langchain-ai/deepagents/commit/9334d91ef94997e46d5373daca9c146fa9498763))
|
|
34
|
+
* Show connection state in the status bar ([#3710](https://github.com/langchain-ai/deepagents/issues/3710)) ([3e3e8fe](https://github.com/langchain-ai/deepagents/commit/3e3e8feb0e6e1b77be75a7756fbf32e5c9497c28))
|
|
35
|
+
* Surface LangSmith tracing projects in `LocalContextMiddleware` ([#3836](https://github.com/langchain-ai/deepagents/issues/3836)) ([676abec](https://github.com/langchain-ai/deepagents/commit/676abecf892ff537fcb1425ba5929cace3c5d503))
|
|
36
|
+
|
|
37
|
+
### Bug Fixes
|
|
38
|
+
|
|
39
|
+
* Add debug-log guidance for truncated startup errors ([#3849](https://github.com/langchain-ai/deepagents/issues/3849)) ([cd1ef30](https://github.com/langchain-ai/deepagents/commit/cd1ef303cf5d0e9d746c787eb09a4a89437e965a))
|
|
40
|
+
* Drop lock-key events so Caps Lock in iTerm2 doesn't type ([#3855](https://github.com/langchain-ai/deepagents/issues/3855)) ([110f1a7](https://github.com/langchain-ai/deepagents/commit/110f1a7a975743efda12e181cb3afc8404202254))
|
|
41
|
+
* Hand pointer over splash tracing project link ([#3858](https://github.com/langchain-ai/deepagents/issues/3858)) ([ea7dae5](https://github.com/langchain-ai/deepagents/commit/ea7dae58a37cfb1d2b96544eb7c941aad331b280))
|
|
42
|
+
* Keep terminal-default theme on Esc in `/theme` selector ([#3854](https://github.com/langchain-ai/deepagents/issues/3854)) ([c3bc67b](https://github.com/langchain-ai/deepagents/commit/c3bc67b0cdeda6f4dbcc6360ddd72b455aec4fe7))
|
|
43
|
+
* Preserve inherited `PYTHONPATH` for server subprocess ([#3833](https://github.com/langchain-ai/deepagents/issues/3833)) ([4689569](https://github.com/langchain-ai/deepagents/commit/4689569f94138987319cd9cbb45ce66a1f496934))
|
|
44
|
+
* Resolve interpreter PTC allowlist against the runtime tool registry ([#3845](https://github.com/langchain-ai/deepagents/issues/3845)) ([c59a27e](https://github.com/langchain-ai/deepagents/commit/c59a27ef2405b8e04c4351ce7ffa53d8d16d519c))
|
|
45
|
+
* Treat multi-line key-event pastes as one input ([#3856](https://github.com/langchain-ai/deepagents/issues/3856)) ([6bb15d4](https://github.com/langchain-ai/deepagents/commit/6bb15d4bd97bd16f47504f937c8458d1b53d9cc4))
|
|
46
|
+
|
|
5
47
|
## [0.1.12](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.11...deepagents-code==0.1.12) (2026-06-10)
|
|
6
48
|
|
|
7
49
|
### Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepagents-code
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.14
|
|
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/
|
|
@@ -29,16 +29,16 @@ Requires-Dist: aiosqlite<1.0.0,>=0.22.1
|
|
|
29
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
|
-
Requires-Dist: langchain-anthropic<2.0.0,>=1.4.
|
|
33
|
-
Requires-Dist: langchain-google-genai<5.0.0,>=4.2.
|
|
32
|
+
Requires-Dist: langchain-anthropic<2.0.0,>=1.4.5
|
|
33
|
+
Requires-Dist: langchain-google-genai<5.0.0,>=4.2.5
|
|
34
34
|
Requires-Dist: langchain-mcp-adapters<1.0.0,>=0.3.0
|
|
35
|
-
Requires-Dist: langchain-openai<2.0.0,>=1.
|
|
36
|
-
Requires-Dist: langchain<2.0.0,>=1.3.
|
|
35
|
+
Requires-Dist: langchain-openai<2.0.0,>=1.3.0
|
|
36
|
+
Requires-Dist: langchain<2.0.0,>=1.3.8
|
|
37
37
|
Requires-Dist: langgraph-checkpoint-sqlite<4.0.0,>=3.1.0
|
|
38
|
-
Requires-Dist: langgraph-cli[inmem]<1.0.0,>=0.4.
|
|
39
|
-
Requires-Dist: langgraph-runtime-inmem<1.0.0,>=0.
|
|
38
|
+
Requires-Dist: langgraph-cli[inmem]<1.0.0,>=0.4.29
|
|
39
|
+
Requires-Dist: langgraph-runtime-inmem<1.0.0,>=0.30.0
|
|
40
40
|
Requires-Dist: langgraph-sdk<1.0.0,>=0.4.2
|
|
41
|
-
Requires-Dist: langsmith[sandbox]>=0.8.
|
|
41
|
+
Requires-Dist: langsmith[sandbox]>=0.8.15
|
|
42
42
|
Requires-Dist: markdownify<2.0.0,>=1.2.2
|
|
43
43
|
Requires-Dist: packaging>=26.2
|
|
44
44
|
Requires-Dist: pillow<13.0.0,>=12.2.0
|
|
@@ -48,7 +48,7 @@ Requires-Dist: python-dotenv<2.0.0,>=1.2.2
|
|
|
48
48
|
Requires-Dist: pyyaml>=6.0.3
|
|
49
49
|
Requires-Dist: requests<3.0.0,>=2.34.2
|
|
50
50
|
Requires-Dist: rich<16.0.0,>=15.0.0
|
|
51
|
-
Requires-Dist: tavily-python<1.0.0,>=0.7.
|
|
51
|
+
Requires-Dist: tavily-python<1.0.0,>=0.7.26
|
|
52
52
|
Requires-Dist: textual-autocomplete<5.0.0,>=4.0.6
|
|
53
53
|
Requires-Dist: textual-speedups<1.0.0,>=0.2.1
|
|
54
54
|
Requires-Dist: textual<9.0.0,>=8.2.7
|
|
@@ -57,24 +57,24 @@ Requires-Dist: uuid-utils<1.0.0,>=0.16.0
|
|
|
57
57
|
Provides-Extra: agentcore
|
|
58
58
|
Requires-Dist: langchain-agentcore-codeinterpreter<1.0.0,>=0.0.4; extra == 'agentcore'
|
|
59
59
|
Provides-Extra: all-providers
|
|
60
|
-
Requires-Dist: langchain-anthropic<2.0.0,>=1.4.
|
|
60
|
+
Requires-Dist: langchain-anthropic<2.0.0,>=1.4.5; extra == 'all-providers'
|
|
61
61
|
Requires-Dist: langchain-aws<2.0.0,>=1.5.1; extra == 'all-providers'
|
|
62
62
|
Requires-Dist: langchain-baseten<1.0.0,>=0.2.0; extra == 'all-providers'
|
|
63
63
|
Requires-Dist: langchain-cohere<1.0.0,>=0.6.0; extra == 'all-providers'
|
|
64
64
|
Requires-Dist: langchain-deepseek<2.0.0,>=1.1.0; extra == 'all-providers'
|
|
65
65
|
Requires-Dist: langchain-fireworks<2.0.0,>=1.4.2; extra == 'all-providers'
|
|
66
|
-
Requires-Dist: langchain-google-genai<5.0.0,>=4.2.
|
|
67
|
-
Requires-Dist: langchain-google-vertexai<4.0.0,>=3.2.
|
|
68
|
-
Requires-Dist: langchain-groq<2.0.0,>=1.1.
|
|
66
|
+
Requires-Dist: langchain-google-genai<5.0.0,>=4.2.5; extra == 'all-providers'
|
|
67
|
+
Requires-Dist: langchain-google-vertexai<4.0.0,>=3.2.4; extra == 'all-providers'
|
|
68
|
+
Requires-Dist: langchain-groq<2.0.0,>=1.1.3; extra == 'all-providers'
|
|
69
69
|
Requires-Dist: langchain-huggingface<2.0.0,>=1.2.2; extra == 'all-providers'
|
|
70
70
|
Requires-Dist: langchain-ibm<2.0.0,>=1.1.0; extra == 'all-providers'
|
|
71
71
|
Requires-Dist: langchain-litellm<2.0.0,>=0.6.6; extra == 'all-providers'
|
|
72
|
-
Requires-Dist: langchain-mistralai<2.0.0,>=1.1.
|
|
72
|
+
Requires-Dist: langchain-mistralai<2.0.0,>=1.1.5; extra == 'all-providers'
|
|
73
73
|
Requires-Dist: langchain-nvidia-ai-endpoints<2.0.0,>=1.4.1; extra == 'all-providers'
|
|
74
74
|
Requires-Dist: langchain-ollama<2.0.0,>=1.1.0; extra == 'all-providers'
|
|
75
|
-
Requires-Dist: langchain-openai<2.0.0,>=1.
|
|
75
|
+
Requires-Dist: langchain-openai<2.0.0,>=1.3.0; extra == 'all-providers'
|
|
76
76
|
Requires-Dist: langchain-openrouter<2.0.0,>=0.2.3; extra == 'all-providers'
|
|
77
|
-
Requires-Dist: langchain-perplexity<2.0.0,>=1.
|
|
77
|
+
Requires-Dist: langchain-perplexity<2.0.0,>=1.4.0; extra == 'all-providers'
|
|
78
78
|
Requires-Dist: langchain-together<2.0.0,>=0.4.0; extra == 'all-providers'
|
|
79
79
|
Requires-Dist: langchain-xai<2.0.0,>=1.2.2; extra == 'all-providers'
|
|
80
80
|
Provides-Extra: all-sandboxes
|
|
@@ -83,7 +83,7 @@ Requires-Dist: langchain-daytona>=0.0.7; extra == 'all-sandboxes'
|
|
|
83
83
|
Requires-Dist: langchain-modal>=0.0.5; extra == 'all-sandboxes'
|
|
84
84
|
Requires-Dist: langchain-runloop>=0.0.6; extra == 'all-sandboxes'
|
|
85
85
|
Provides-Extra: anthropic
|
|
86
|
-
Requires-Dist: langchain-anthropic<2.0.0,>=1.4.
|
|
86
|
+
Requires-Dist: langchain-anthropic<2.0.0,>=1.4.5; extra == 'anthropic'
|
|
87
87
|
Provides-Extra: baseten
|
|
88
88
|
Requires-Dist: langchain-baseten<1.0.0,>=0.2.0; extra == 'baseten'
|
|
89
89
|
Provides-Extra: bedrock
|
|
@@ -97,9 +97,9 @@ Requires-Dist: langchain-deepseek<2.0.0,>=1.1.0; extra == 'deepseek'
|
|
|
97
97
|
Provides-Extra: fireworks
|
|
98
98
|
Requires-Dist: langchain-fireworks<2.0.0,>=1.4.2; extra == 'fireworks'
|
|
99
99
|
Provides-Extra: google-genai
|
|
100
|
-
Requires-Dist: langchain-google-genai<5.0.0,>=4.2.
|
|
100
|
+
Requires-Dist: langchain-google-genai<5.0.0,>=4.2.5; extra == 'google-genai'
|
|
101
101
|
Provides-Extra: groq
|
|
102
|
-
Requires-Dist: langchain-groq<2.0.0,>=1.1.
|
|
102
|
+
Requires-Dist: langchain-groq<2.0.0,>=1.1.3; extra == 'groq'
|
|
103
103
|
Provides-Extra: huggingface
|
|
104
104
|
Requires-Dist: langchain-huggingface<2.0.0,>=1.2.2; extra == 'huggingface'
|
|
105
105
|
Provides-Extra: ibm
|
|
@@ -107,7 +107,7 @@ Requires-Dist: langchain-ibm<2.0.0,>=1.1.0; extra == 'ibm'
|
|
|
107
107
|
Provides-Extra: litellm
|
|
108
108
|
Requires-Dist: langchain-litellm<2.0.0,>=0.6.6; extra == 'litellm'
|
|
109
109
|
Provides-Extra: mistralai
|
|
110
|
-
Requires-Dist: langchain-mistralai<2.0.0,>=1.1.
|
|
110
|
+
Requires-Dist: langchain-mistralai<2.0.0,>=1.1.5; extra == 'mistralai'
|
|
111
111
|
Provides-Extra: modal
|
|
112
112
|
Requires-Dist: langchain-modal>=0.0.5; extra == 'modal'
|
|
113
113
|
Provides-Extra: nvidia
|
|
@@ -115,11 +115,11 @@ Requires-Dist: langchain-nvidia-ai-endpoints<2.0.0,>=1.4.1; extra == 'nvidia'
|
|
|
115
115
|
Provides-Extra: ollama
|
|
116
116
|
Requires-Dist: langchain-ollama<2.0.0,>=1.1.0; extra == 'ollama'
|
|
117
117
|
Provides-Extra: openai
|
|
118
|
-
Requires-Dist: langchain-openai<2.0.0,>=1.
|
|
118
|
+
Requires-Dist: langchain-openai<2.0.0,>=1.3.0; extra == 'openai'
|
|
119
119
|
Provides-Extra: openrouter
|
|
120
120
|
Requires-Dist: langchain-openrouter<2.0.0,>=0.2.3; extra == 'openrouter'
|
|
121
121
|
Provides-Extra: perplexity
|
|
122
|
-
Requires-Dist: langchain-perplexity<2.0.0,>=1.
|
|
122
|
+
Requires-Dist: langchain-perplexity<2.0.0,>=1.4.0; extra == 'perplexity'
|
|
123
123
|
Provides-Extra: quickjs
|
|
124
124
|
Requires-Dist: langchain-quickjs<0.2.0,>=0.1.4; extra == 'quickjs'
|
|
125
125
|
Provides-Extra: runloop
|
|
@@ -127,7 +127,7 @@ 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
|
|
130
|
-
Requires-Dist: langchain-google-vertexai<4.0.0,>=3.2.
|
|
130
|
+
Requires-Dist: langchain-google-vertexai<4.0.0,>=3.2.4; extra == 'vertex'
|
|
131
131
|
Provides-Extra: xai
|
|
132
132
|
Requires-Dist: langchain-xai<2.0.0,>=1.2.2; extra == 'xai'
|
|
133
133
|
Description-Content-Type: text/markdown
|
|
@@ -409,6 +409,13 @@
|
|
|
409
409
|
- **Description**: The `"env"` field in stdio MCP server definitions (`.mcp.json`) accepts an arbitrary key-value dict. `mcp_tools._validate_server_config` only checks that the field is a dict — it does not filter key names or values. The dict is forwarded directly to `StdioConnection(env=...)` which passes it to the subprocess. An attacker who can modify a project-level `.mcp.json` could set `PATH` to redirect command resolution, `LD_PRELOAD` to inject shared libraries, or `PYTHONPATH` to hijack Python imports in the MCP subprocess.
|
|
410
410
|
- **Preconditions**: (1) Attacker has write access to a project-level `.mcp.json`; (2) The project MCP config must be trusted by the user (fingerprint approval gate via `mcp_trust`). For user-level `~/.deepagents/.mcp.json`, the attacker already has home directory write access. Note: the `env` dict from MCP config is passed to `StdioConnection` — whether it replaces or merges with `os.environ` depends on the `langchain_mcp_adapters` library implementation.
|
|
411
411
|
|
|
412
|
+
#### T11: Auto-Installed ripgrep Binary from Upstream Release
|
|
413
|
+
|
|
414
|
+
- **Flow**: First-run download performed by `managed_tools.ensure_ripgrep` when `rg` is not on `PATH`.
|
|
415
|
+
- **Description**: On first invocation without a system `rg`, Deep Agents Code fetches the pinned ripgrep release tarball from `github.com/BurntSushi/ripgrep/releases/...`, verifies it against an in-tree SHA-256 (`RIPGREP_ASSETS`), extracts it under a `TemporaryDirectory`, and atomically moves the binary into `~/.deepagents/bin/rg`. The binary then runs unsandboxed, inheriting the same trust as a user-installed `rg` (the SDK invokes it via `subprocess.run(["rg", ...])`).
|
|
416
|
+
- **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. (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.
|
|
417
|
+
- **Preconditions**: User has not installed `rg` via their package manager, `DEEPAGENTS_CODE_OFFLINE` is unset, 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
|
+
|
|
412
419
|
---
|
|
413
420
|
|
|
414
421
|
## Input Source Coverage
|
|
@@ -13,7 +13,12 @@ import os
|
|
|
13
13
|
import sys
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
|
|
16
|
-
from deepagents_code._env_vars import
|
|
16
|
+
from deepagents_code._env_vars import (
|
|
17
|
+
DEBUG,
|
|
18
|
+
DEBUG_FILE,
|
|
19
|
+
DEFAULT_DEBUG_FILE,
|
|
20
|
+
is_env_truthy,
|
|
21
|
+
)
|
|
17
22
|
|
|
18
23
|
_DEBUG_HANDLER_ATTR = "_deepagents_code_debug_handler"
|
|
19
24
|
|
|
@@ -25,8 +30,8 @@ def configure_debug_logging(target: logging.Logger) -> None:
|
|
|
25
30
|
module loggers reach the same file via propagation, so individual modules do
|
|
26
31
|
not configure logging themselves.
|
|
27
32
|
|
|
28
|
-
The log file defaults to `
|
|
29
|
-
|
|
33
|
+
The log file defaults to `DEFAULT_DEBUG_FILE` but can be overridden with
|
|
34
|
+
`DEEPAGENTS_CODE_DEBUG_FILE`. The handler appends (`mode='a'`) so logs
|
|
30
35
|
are preserved across separate process runs. Calling this again with the same
|
|
31
36
|
resolved path is a no-op: the existing tagged handler is reused rather than
|
|
32
37
|
stacking duplicates. If the resolved path changes, the stale handler is
|
|
@@ -40,12 +45,7 @@ def configure_debug_logging(target: logging.Logger) -> None:
|
|
|
40
45
|
if not is_env_truthy(DEBUG):
|
|
41
46
|
return
|
|
42
47
|
|
|
43
|
-
debug_path = Path(
|
|
44
|
-
os.environ.get(
|
|
45
|
-
DEBUG_FILE,
|
|
46
|
-
"/tmp/deepagents_debug.log", # noqa: S108
|
|
47
|
-
)
|
|
48
|
-
)
|
|
48
|
+
debug_path = Path(os.environ.get(DEBUG_FILE, DEFAULT_DEBUG_FILE))
|
|
49
49
|
for existing in list(target.handlers):
|
|
50
50
|
if not (
|
|
51
51
|
isinstance(existing, logging.FileHandler)
|
|
@@ -74,3 +74,23 @@ def configure_debug_logging(target: logging.Logger) -> None:
|
|
|
74
74
|
handler.setFormatter(logging.Formatter("%(asctime)s %(name)s %(message)s"))
|
|
75
75
|
target.addHandler(handler)
|
|
76
76
|
target.setLevel(logging.DEBUG)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def installed_debug_log_path() -> Path | None:
|
|
80
|
+
"""Return the path of the active debug log file, or `None` if not logging.
|
|
81
|
+
|
|
82
|
+
Reflects the file handler actually attached by `configure_debug_logging`,
|
|
83
|
+
not the current `DEEPAGENTS_CODE_DEBUG` env value. The two diverge when the
|
|
84
|
+
variable is set after import — e.g. via a project/global `.env` loaded during
|
|
85
|
+
settings bootstrap — in which case the variable reads truthy but no handler
|
|
86
|
+
was installed and no log file exists. Callers that surface "full error in
|
|
87
|
+
<path>" hints must use this rather than the env var to avoid pointing users
|
|
88
|
+
at a file that was never created.
|
|
89
|
+
"""
|
|
90
|
+
package_logger = logging.getLogger(__package__ or "deepagents_code")
|
|
91
|
+
for handler in package_logger.handlers:
|
|
92
|
+
if isinstance(handler, logging.FileHandler) and getattr(
|
|
93
|
+
handler, _DEBUG_HANDLER_ATTR, False
|
|
94
|
+
):
|
|
95
|
+
return Path(handler.baseFilename)
|
|
96
|
+
return None
|
|
@@ -46,7 +46,10 @@ as enabled, and `0`, `false`, `no`, `off`, empty string, or unset as disabled.
|
|
|
46
46
|
"""
|
|
47
47
|
|
|
48
48
|
DEBUG_FILE = "DEEPAGENTS_CODE_DEBUG_FILE"
|
|
49
|
-
"""Path for the debug log file (default:
|
|
49
|
+
"""Path for the debug log file (default: `DEFAULT_DEBUG_FILE`)."""
|
|
50
|
+
|
|
51
|
+
DEFAULT_DEBUG_FILE = "/tmp/deepagents_debug.log" # noqa: S108 # opt-in debug log
|
|
52
|
+
"""Default path for the debug log when `DEBUG_FILE` is unset."""
|
|
50
53
|
|
|
51
54
|
DEBUG_MCP_PROJECT_TRUST = "DEEPAGENTS_CODE_DEBUG_MCP_PROJECT_TRUST"
|
|
52
55
|
"""Force the project MCP approval prompt for manual UI testing.
|
|
@@ -124,6 +127,14 @@ NO_TERMINAL_ESCAPE = "DEEPAGENTS_CODE_NO_TERMINAL_ESCAPE"
|
|
|
124
127
|
NO_UPDATE_CHECK = "DEEPAGENTS_CODE_NO_UPDATE_CHECK"
|
|
125
128
|
"""Disable automatic update checking when set."""
|
|
126
129
|
|
|
130
|
+
OFFLINE = "DEEPAGENTS_CODE_OFFLINE"
|
|
131
|
+
"""Disable network downloads of managed binaries (e.g. ripgrep).
|
|
132
|
+
|
|
133
|
+
Parsed by `is_env_truthy`: accepts `1`, `true`, `yes`, `on` as enabled. When
|
|
134
|
+
truthy, `managed_tools.ensure_ripgrep` will not attempt to download a binary
|
|
135
|
+
and falls back to the existing missing-tool notification + slow Python regex
|
|
136
|
+
path."""
|
|
137
|
+
|
|
127
138
|
OLLAMA_DISCOVERY = "DEEPAGENTS_CODE_OLLAMA_DISCOVERY"
|
|
128
139
|
"""Toggle Ollama model and profile discovery probes.
|
|
129
140
|
|
|
@@ -164,6 +175,29 @@ _TRUTHY_VALUES = frozenset({"1", "true", "yes", "on"})
|
|
|
164
175
|
_FALSY_VALUES = frozenset({"0", "false", "no", "off", ""})
|
|
165
176
|
|
|
166
177
|
|
|
178
|
+
def classify_env_bool(raw: str) -> bool | None:
|
|
179
|
+
"""Classify a raw env-var string as a truthy, falsy, or unrecognized token.
|
|
180
|
+
|
|
181
|
+
The single source of truth for which strings count as boolean on/off
|
|
182
|
+
values; `is_env_truthy` and the config resolver both build on it so they
|
|
183
|
+
agree on what "recognizably boolean" means.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
raw: The raw (unstripped) environment-variable value.
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
`True` for `1`/`true`/`yes`/`on`, `False` for `0`/`false`/`no`/`off`/
|
|
190
|
+
empty string (case-insensitive), or `None` when the value
|
|
191
|
+
is neither.
|
|
192
|
+
"""
|
|
193
|
+
lowered = raw.strip().lower()
|
|
194
|
+
if lowered in _TRUTHY_VALUES:
|
|
195
|
+
return True
|
|
196
|
+
if lowered in _FALSY_VALUES:
|
|
197
|
+
return False
|
|
198
|
+
return None
|
|
199
|
+
|
|
200
|
+
|
|
167
201
|
def is_env_truthy(name: str, *, default: bool = False) -> bool:
|
|
168
202
|
"""Return whether env var *name* is set to a recognizably truthy value.
|
|
169
203
|
|
|
@@ -184,9 +218,5 @@ def is_env_truthy(name: str, *, default: bool = False) -> bool:
|
|
|
184
218
|
raw = os.environ.get(name)
|
|
185
219
|
if raw is None:
|
|
186
220
|
return default
|
|
187
|
-
|
|
188
|
-
if
|
|
189
|
-
return True
|
|
190
|
-
if lowered in _FALSY_VALUES:
|
|
191
|
-
return False
|
|
192
|
-
return default
|
|
221
|
+
classified = classify_env_bool(raw)
|
|
222
|
+
return default if classified is None else classified
|
|
@@ -164,7 +164,9 @@ class ServerConfig:
|
|
|
164
164
|
|
|
165
165
|
`None` means "fall through to whatever `settings.interpreter_ptc` resolves
|
|
166
166
|
to from `~/.deepagents/config.toml`". A string is one of `"safe"`/`"all"`;
|
|
167
|
-
a list is an explicit allowlist of tool names
|
|
167
|
+
a list is an explicit allowlist of tool names that may also include the
|
|
168
|
+
`"safe"` preset (expanded at agent-build time); `"all"` is rejected inside
|
|
169
|
+
a list.
|
|
168
170
|
"""
|
|
169
171
|
|
|
170
172
|
interpreter_ptc_acknowledge_unsafe: bool = False
|
|
@@ -13,7 +13,30 @@ upstream.
|
|
|
13
13
|
`alt+enter`. Tracked in Textualize/textual#6378. Remove this patch and
|
|
14
14
|
the Textual pin comment in `pyproject.toml` when that lands.
|
|
15
15
|
|
|
16
|
-
2.
|
|
16
|
+
2. Kitty lock-key and sub-field handling. Two related problems with the
|
|
17
|
+
pinned Textual parser:
|
|
18
|
+
|
|
19
|
+
a. Lock keys (Caps Lock / Num Lock / Scroll Lock) must never produce
|
|
20
|
+
text, but terminals encode them inconsistently. kitty/Ghostty/VS Code
|
|
21
|
+
send the functional key code (`CSI 57358 ... u`) with associated text
|
|
22
|
+
set to the letter the *next* key would have produced. iTerm2 instead
|
|
23
|
+
reports the Caps Lock toggle as a bare upper-case ASCII letter (`CSI
|
|
24
|
+
65 u` → 'A') with no modifier or associated-text field — not a valid
|
|
25
|
+
encoding for a real key press per the kitty spec. Either way the chat
|
|
26
|
+
input would type a stray capital. The patch collapses both forms to a
|
|
27
|
+
single character-less `caps_lock` event, regardless of the modifier,
|
|
28
|
+
associated-text, or event-type sub-fields the terminal includes.
|
|
29
|
+
|
|
30
|
+
b. `_re_extended_key` only accepts `;`-separated numeric fields, so any
|
|
31
|
+
*non-lock* kitty sequence carrying `:`-separated sub-fields — alternate
|
|
32
|
+
keys (`unicode:shifted:base`) or an event-type (`modifiers:event`) —
|
|
33
|
+
fails to match and is re-emitted one byte at a time as literal text.
|
|
34
|
+
The patch strips the `:` sub-fields before Textual parses the sequence
|
|
35
|
+
so it resolves to a single key event.
|
|
36
|
+
|
|
37
|
+
Remove when the pinned Textual neutralizes lock keys and widens its parser.
|
|
38
|
+
|
|
39
|
+
3. Double-click word selection. Stock Textual selects the entire widget on
|
|
17
40
|
a click chain; these patches narrow a double-click (and double-click
|
|
18
41
|
drag) to word boundaries. No upstream issue tracks this yet, so it has
|
|
19
42
|
no removal criterion — it stays until Textual grows native word select.
|
|
@@ -24,6 +47,7 @@ Imported for side effect from `app.py` before any `App()` is created.
|
|
|
24
47
|
from __future__ import annotations
|
|
25
48
|
|
|
26
49
|
import logging
|
|
50
|
+
import re
|
|
27
51
|
from inspect import isawaitable
|
|
28
52
|
from typing import TYPE_CHECKING
|
|
29
53
|
|
|
@@ -60,6 +84,99 @@ try:
|
|
|
60
84
|
except (ImportError, AttributeError) as exc: # pragma: no cover - defensive
|
|
61
85
|
logger.warning("Textual keyboard parser patch skipped: %s", exc)
|
|
62
86
|
else:
|
|
87
|
+
# Kitty functional key codes for the lock keys (Caps Lock, Scroll Lock,
|
|
88
|
+
# Num Lock). The kitty protocol assigns these Private Use Area codepoints;
|
|
89
|
+
# they appear as the leading key-code field of a `CSI ... u` sequence.
|
|
90
|
+
_KITTY_LOCK_KEY_CODES = frozenset({"57358", "57359", "57360"})
|
|
91
|
+
_KITTY_LOCK_KEY_NAMES = {
|
|
92
|
+
"57358": "caps_lock",
|
|
93
|
+
"57359": "scroll_lock",
|
|
94
|
+
"57360": "num_lock",
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Any `CSI <code>[:...][;...] u` sequence. Group 1 is the leading key-code
|
|
98
|
+
# field (before any `:` alternate-key sub-field); `_lock_key_event` checks
|
|
99
|
+
# it against the lock-key set. The match is deliberately broad so the code
|
|
100
|
+
# is extracted regardless of the modifier / associated-text / event-type
|
|
101
|
+
# sub-fields that follow, which iTerm2 and other terminals encode in
|
|
102
|
+
# varying shapes.
|
|
103
|
+
_KITTY_KEY_SEQUENCE = re.compile(r"\x1b\[(\d+)[\d;:]*u")
|
|
104
|
+
|
|
105
|
+
# Kitty extended-key sequence carrying `:` sub-fields (alternate keys or an
|
|
106
|
+
# event-type sub-field). The pinned Textual's `_re_extended_key` rejects the
|
|
107
|
+
# colons, so non-lock keys with these sub-fields would otherwise leak as
|
|
108
|
+
# literal text — strip the sub-fields so they parse to a single key event.
|
|
109
|
+
_KITTY_SUBFIELD_KEY = re.compile(r"\x1b\[[\d;:]*:[\d;:]*[u~ABCDEFHPQRS]")
|
|
110
|
+
|
|
111
|
+
# iTerm2 reports the Caps Lock toggle as a `CSI u` sequence whose primary
|
|
112
|
+
# key code is the *uppercase* ASCII letter that would be produced next
|
|
113
|
+
# (e.g. `CSI 65 u` → 'A'), with no real modifier bits and no associated
|
|
114
|
+
# text. The kitty spec requires the primary code to be the unshifted
|
|
115
|
+
# (lower-case) code point, so a bare upper-case letter here is iTerm2's
|
|
116
|
+
# Caps Lock artifact rather than a real key press. Group 1 is the code
|
|
117
|
+
# point; group 2 the optional modifier field; group 3 the optional text.
|
|
118
|
+
_KITTY_CSI_U = re.compile(
|
|
119
|
+
r"\x1b\[(\d+)(?::\d+)*(?:;(\d+)[\d:]*)?(?:;(\d+)[\d:]*)?u"
|
|
120
|
+
)
|
|
121
|
+
_ASCII_UPPER_A = 65
|
|
122
|
+
_ASCII_UPPER_Z = 90
|
|
123
|
+
# Modifier mask for the "real" modifiers (shift|alt|ctrl|super|hyper|meta);
|
|
124
|
+
# excludes the caps_lock (64) and num_lock (128) lock bits.
|
|
125
|
+
_REAL_MODIFIER_MASK = 0b111111
|
|
126
|
+
|
|
127
|
+
def _spurious_caps_lock(sequence: str) -> bool:
|
|
128
|
+
"""Whether `sequence` is iTerm2's bare Caps Lock toggle report.
|
|
129
|
+
|
|
130
|
+
Matches a `CSI u` key whose primary code point is an upper-case ASCII
|
|
131
|
+
letter with no real modifiers and no associated-text field — which the
|
|
132
|
+
kitty spec never produces for a genuine key press.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
`True` if `sequence` is the spurious Caps Lock toggle report.
|
|
136
|
+
"""
|
|
137
|
+
match = _KITTY_CSI_U.fullmatch(sequence)
|
|
138
|
+
if match is None:
|
|
139
|
+
return False
|
|
140
|
+
code = int(match.group(1))
|
|
141
|
+
if not _ASCII_UPPER_A <= code <= _ASCII_UPPER_Z:
|
|
142
|
+
return False
|
|
143
|
+
modifier_bits = (int(match.group(2)) - 1) if match.group(2) else 0
|
|
144
|
+
has_text = match.group(3) is not None
|
|
145
|
+
return modifier_bits & _REAL_MODIFIER_MASK == 0 and not has_text
|
|
146
|
+
|
|
147
|
+
def _strip_kitty_subfields(sequence: str) -> str:
|
|
148
|
+
"""Drop `:` sub-fields from a kitty extended-key sequence.
|
|
149
|
+
|
|
150
|
+
Keeps the primary value of each `;`-separated field (the unicode key
|
|
151
|
+
code, modifier mask, and associated text), which is all Textual reads.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
The sequence with every `:` sub-field removed.
|
|
155
|
+
"""
|
|
156
|
+
body, terminator = sequence[2:-1], sequence[-1]
|
|
157
|
+
primary = ";".join(field.split(":", 1)[0] for field in body.split(";"))
|
|
158
|
+
return f"\x1b[{primary}{terminator}"
|
|
159
|
+
|
|
160
|
+
def _lock_key_event(sequence: str) -> events.Key | None:
|
|
161
|
+
"""Return a text-free lock-key event for a kitty lock-key sequence.
|
|
162
|
+
|
|
163
|
+
Lock keys must never produce text. Under the kitty protocol with
|
|
164
|
+
associated-text reporting, terminals (notably iTerm2) encode Caps
|
|
165
|
+
Lock as a `CSI 57358 ... u` sequence whose associated-text field is
|
|
166
|
+
the letter the *next* key would have produced — Textual then either
|
|
167
|
+
types that letter or, when `:` sub-fields are present, leaks the raw
|
|
168
|
+
sequence byte by byte. Collapsing any lock-key sequence to a single
|
|
169
|
+
character-less event stops both failure modes at the source, for
|
|
170
|
+
every widget.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
A `Key` event for the lock key, or `None` if `sequence` is not a
|
|
174
|
+
kitty lock-key sequence.
|
|
175
|
+
"""
|
|
176
|
+
match = _KITTY_KEY_SEQUENCE.fullmatch(sequence)
|
|
177
|
+
if match is None or match.group(1) not in _KITTY_LOCK_KEY_CODES:
|
|
178
|
+
return None
|
|
179
|
+
return events.Key(_KITTY_LOCK_KEY_NAMES[match.group(1)], None)
|
|
63
180
|
|
|
64
181
|
def _emit_alt(keys: tuple, character: str | None) -> Iterable[events.Key]:
|
|
65
182
|
for key in keys:
|
|
@@ -68,6 +185,22 @@ else:
|
|
|
68
185
|
def _sequence_to_key_events_with_alt(
|
|
69
186
|
self: XTermParser, sequence: str, alt: bool = False
|
|
70
187
|
) -> Iterable[events.Key]:
|
|
188
|
+
# Lock keys (Caps Lock / Num Lock / Scroll Lock) must never type. Emit
|
|
189
|
+
# a single character-less event regardless of how the terminal encoded
|
|
190
|
+
# the modifiers, associated text, or event-type sub-fields.
|
|
191
|
+
if (lock_event := _lock_key_event(sequence)) is not None:
|
|
192
|
+
yield lock_event
|
|
193
|
+
return
|
|
194
|
+
# iTerm2 reports the Caps Lock toggle as a bare upper-case letter (e.g.
|
|
195
|
+
# `CSI 65 u` → 'A') rather than the kitty `57358` functional code. Drop
|
|
196
|
+
# it so the toggle never types a stray capital into the input.
|
|
197
|
+
if _spurious_caps_lock(sequence):
|
|
198
|
+
yield events.Key("caps_lock", None)
|
|
199
|
+
return
|
|
200
|
+
# Normalize any other kitty sequence with `:` sub-fields so it resolves
|
|
201
|
+
# to a single key event instead of leaking raw bytes.
|
|
202
|
+
if _KITTY_SUBFIELD_KEY.fullmatch(sequence):
|
|
203
|
+
sequence = _strip_kitty_subfields(sequence)
|
|
71
204
|
# Fast path: \x1b<byte> on first pass. Short-circuits the ~100 ms
|
|
72
205
|
# escape-delay wait when both bytes arrive together. Semantic side
|
|
73
206
|
# effect: \x1b\x1b dispatches as `alt+escape` with no delay, matching
|
|
@@ -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.14" # 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."""
|