deepagents-cli 0.0.40__tar.gz → 0.0.42__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_cli-0.0.40 → deepagents_cli-0.0.42}/.gitignore +1 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/CHANGELOG.md +28 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/PKG-INFO +5 -5
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/_env_vars.py +15 -0
- deepagents_cli-0.0.42/deepagents_cli/_git.py +236 -0
- deepagents_cli-0.0.42/deepagents_cli/_textual_patches.py +66 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/_version.py +8 -1
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/agent.py +34 -7
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/app.py +1185 -143
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/app.tcss +0 -2
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/ask_user.py +1 -1
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/config.py +92 -54
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/deploy/bundler.py +33 -4
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/deploy/config.py +80 -2
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/deploy/templates.py +141 -0
- deepagents_cli-0.0.42/deepagents_cli/extras_info.py +178 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/local_context.py +21 -7
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/main.py +147 -22
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/non_interactive.py +137 -0
- deepagents_cli-0.0.42/deepagents_cli/notifications.py +244 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/project_utils.py +3 -12
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/system_prompt.md +1 -1
- deepagents_cli-0.0.42/deepagents_cli/terminal_capabilities.py +115 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/textual_adapter.py +49 -13
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/ui.py +4 -1
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/update_check.py +272 -12
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/_links.py +33 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/ask_user.py +23 -1
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/chat_input.py +1 -1
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/loading.py +10 -2
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/message_store.py +40 -3
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/messages.py +82 -9
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/model_selector.py +23 -2
- deepagents_cli-0.0.42/deepagents_cli/widgets/notification_center.py +399 -0
- deepagents_cli-0.0.42/deepagents_cli/widgets/notification_detail.py +257 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/status.py +0 -1
- deepagents_cli-0.0.42/deepagents_cli/widgets/update_available.py +311 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/welcome.py +1 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/pyproject.toml +7 -4
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/conftest.py +15 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/deploy/test_bundler.py +88 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/deploy/test_config.py +124 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_agent.py +110 -6
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_app.py +1816 -27
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_args.py +33 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_ask_user.py +57 -1
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_config.py +413 -46
- deepagents_cli-0.0.42/tests/unit_tests/test_extras_info.py +162 -0
- deepagents_cli-0.0.42/tests/unit_tests/test_git.py +264 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_loading.py +21 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_local_context.py +39 -10
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_main.py +77 -33
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_main_args.py +80 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_message_store.py +31 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_messages.py +82 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_model_switch.py +95 -14
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_non_interactive.py +178 -1
- deepagents_cli-0.0.42/tests/unit_tests/test_notification_center.py +312 -0
- deepagents_cli-0.0.42/tests/unit_tests/test_notification_detail.py +133 -0
- deepagents_cli-0.0.42/tests/unit_tests/test_notifications.py +204 -0
- deepagents_cli-0.0.42/tests/unit_tests/test_terminal_capabilities.py +203 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_textual_adapter.py +305 -5
- deepagents_cli-0.0.42/tests/unit_tests/test_textual_patches.py +92 -0
- deepagents_cli-0.0.42/tests/unit_tests/test_tool_display.py +470 -0
- deepagents_cli-0.0.42/tests/unit_tests/test_update_available.py +183 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_update_check.py +493 -4
- deepagents_cli-0.0.42/tests/unit_tests/test_version.py +396 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_welcome.py +4 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/uv.lock +34 -21
- deepagents_cli-0.0.40/tests/unit_tests/test_version.py +0 -166
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/DEV.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/Makefile +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/README.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/THREAT_MODEL.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/__init__.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/__main__.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/_ask_user_types.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/_cli_context.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/_debug.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/_server_config.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/_session_stats.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/_testing_models.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/built_in_skills/__init__.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/built_in_skills/remember/SKILL.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/built_in_skills/skill-creator/SKILL.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/clipboard.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/command_registry.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/configurable_model.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/default_agent_prompt.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/deploy/__init__.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/deploy/commands.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/editor.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/file_ops.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/formatting.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/hooks.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/input.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/integrations/__init__.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/integrations/sandbox_factory.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/integrations/sandbox_provider.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/mcp_tools.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/mcp_trust.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/media_utils.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/model_config.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/offload.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/output.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/py.typed +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/remote_client.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/server.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/server_graph.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/server_manager.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/sessions.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/skills/__init__.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/skills/commands.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/skills/invocation.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/skills/load.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/subagents.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/theme.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/token_state.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/tool_display.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/tools.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/unicode_security.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/__init__.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/agent_selector.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/approval.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/autocomplete.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/diff.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/history.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/mcp_viewer.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/notification_settings.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/theme_selector.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/thread_selector.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/tool_renderers.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/deepagents_cli/widgets/tool_widgets.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/examples/deploy-content-writer/.env.example +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/examples/deploy-content-writer/skills/blog-post/SKILL.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/examples/deploy-content-writer/skills/social-media/SKILL.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/examples/deploy-content-writer/user/context.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/examples/deploy-content-writer/user/preferences.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/examples/skills/arxiv-search/SKILL.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/examples/skills/arxiv-search/arxiv_search.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/examples/skills/langgraph-docs/SKILL.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/examples/skills/skill-creator/SKILL.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/examples/skills/web-research/SKILL.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/images/cli.png +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/scripts/check_imports.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/scripts/debug_server.sh +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/scripts/install.sh +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/README.md +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/integration_tests/__init__.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/integration_tests/benchmarks/__init__.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/integration_tests/conftest.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/integration_tests/test_acp_mode.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/integration_tests/test_compact_resume.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/integration_tests/test_sandbox_factory.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/integration_tests/test_sandbox_operations.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/__init__.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/deploy/__init__.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/deploy/test_commands.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/skills/__init__.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/skills/test_commands.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/skills/test_load.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/skills/test_skills_json.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_agent_friendly.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_agent_selector.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_approval.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_ask_user_middleware.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_autocomplete.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_charset.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_chat_input.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_command_registry.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_compact_tool.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_configurable_model.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_debug.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_editor.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_end_to_end.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_env_vars.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_exception_handling.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_file_ops.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_formatting.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_history.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_hooks.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_imports.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_input_parsing.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_links.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_main_acp_mode.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_mcp_tools.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_mcp_trust.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_mcp_viewer.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_media_utils.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_model_config.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_model_selector.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_offload.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_offload_dict_messages.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_output.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_reload.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_remote_client.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_sandbox_factory.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_server.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_server_config.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_server_graph.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_server_helpers.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_server_manager.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_session_stats.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_sessions.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_shell_allow_list.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_skill_invocation.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_status.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_subagents.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_theme.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_thread_selector.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_token_tracker.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_ui.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/test_unicode_security.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/tools/__init__.py +0 -0
- {deepagents_cli-0.0.40 → deepagents_cli-0.0.42}/tests/unit_tests/tools/test_fetch_url.py +0 -0
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.42](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.41...deepagents-cli==0.0.42) (2026-04-29)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* `shift+enter` newline on kitty-capable terminals ([#2869](https://github.com/langchain-ai/deepagents/issues/2869)) ([34e6614](https://github.com/langchain-ai/deepagents/commit/34e6614a2c6e6a7e33f763ac5b527c13b324a690))
|
|
8
|
+
* Hint `Enter` behavior in `/model` empty state ([#2933](https://github.com/langchain-ai/deepagents/issues/2933)) ([7cffa16](https://github.com/langchain-ai/deepagents/commit/7cffa16a072bc77def78e4cda09c2e5a2cf8ca39))
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
* Queue `/model` switches during server startup ([#2895](https://github.com/langchain-ai/deepagents/issues/2895)) ([6ed7b65](https://github.com/langchain-ai/deepagents/commit/6ed7b65a40ac5bd926e94edd944bd552e8d6b5b4))
|
|
13
|
+
|
|
14
|
+
## [0.0.41](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.40...deepagents-cli==0.0.41) (2026-04-21)
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* `--startup-cmd` flag ([#2841](https://github.com/langchain-ai/deepagents/issues/2841)) ([8adcc2c](https://github.com/langchain-ai/deepagents/commit/8adcc2c2e612346c263d02d1ec5c33e0d63da5a3))
|
|
19
|
+
* Actionable notifications, update modal ([#2855](https://github.com/langchain-ai/deepagents/issues/2855)) ([5fcd368](https://github.com/langchain-ai/deepagents/commit/5fcd368088079a84f151e0a3f5e4b9ac29c360c1))
|
|
20
|
+
* Custom auth via `[auth]` in `deepagents deploy` ([#2734](https://github.com/langchain-ai/deepagents/issues/2734)) ([417ddaa](https://github.com/langchain-ai/deepagents/commit/417ddaab4804a54a8f83721bb8577d65cfa3659f))
|
|
21
|
+
* Refresh footer git branch after shell commands ([#2851](https://github.com/langchain-ai/deepagents/issues/2851)) ([ee4fddd](https://github.com/langchain-ai/deepagents/commit/ee4fddde9454ee8f7ede98ee9a346da6c5ccd3d9))
|
|
22
|
+
* Rework `/version`, add release-age and editable-install guard ([#2854](https://github.com/langchain-ai/deepagents/issues/2854)) ([1ae053f](https://github.com/langchain-ai/deepagents/commit/1ae053f347679e58562d2b81eb6d6e6e9bbf0b07))
|
|
23
|
+
|
|
24
|
+
### Bug Fixes
|
|
25
|
+
|
|
26
|
+
* Gate agent-swap resume hint on server checkpoint ([#2862](https://github.com/langchain-ai/deepagents/issues/2862)) ([f14b9cd](https://github.com/langchain-ai/deepagents/commit/f14b9cd3cc41f92ddb089d4294cba8496d517807))
|
|
27
|
+
* Keep thinking spinner visible during text streaming ([#2849](https://github.com/langchain-ai/deepagents/issues/2849)) ([2cb2244](https://github.com/langchain-ai/deepagents/commit/2cb22446bc1351d20e8bbfa9f23b5d668947351f))
|
|
28
|
+
* Re-show thinking spinner on hitl/`ask_user` resume ([#2847](https://github.com/langchain-ai/deepagents/issues/2847)) ([34a6167](https://github.com/langchain-ai/deepagents/commit/34a6167b0c275c7e4da067ef276a837f60da2f8a))
|
|
29
|
+
* Restore `ctrl+j` newline keybinding ([#2827](https://github.com/langchain-ai/deepagents/issues/2827)) ([2e1a3f4](https://github.com/langchain-ai/deepagents/commit/2e1a3f45a9ff56390e294ea5b0f6a837200874ec))
|
|
30
|
+
|
|
3
31
|
## [0.0.40](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.39...deepagents-cli==0.0.40) (2026-04-20)
|
|
4
32
|
|
|
5
33
|
### Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepagents-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.42
|
|
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/
|
|
@@ -27,9 +27,9 @@ Classifier: Topic :: Terminals
|
|
|
27
27
|
Requires-Python: <4.0,>=3.11
|
|
28
28
|
Requires-Dist: aiosqlite<1.0.0,>=0.19.0
|
|
29
29
|
Requires-Dist: deepagents-acp>=0.0.4
|
|
30
|
-
Requires-Dist: deepagents==0.5.
|
|
30
|
+
Requires-Dist: deepagents==0.5.4
|
|
31
31
|
Requires-Dist: httpx<1.0.0,>=0.28.1
|
|
32
|
-
Requires-Dist: langchain-anthropic<2.0.0,>=1.4.
|
|
32
|
+
Requires-Dist: langchain-anthropic<2.0.0,>=1.4.2
|
|
33
33
|
Requires-Dist: langchain-google-genai<5.0.0,>=4.2.1
|
|
34
34
|
Requires-Dist: langchain-mcp-adapters<1.0.0,>=0.2.0
|
|
35
35
|
Requires-Dist: langchain-openai<2.0.0,>=1.1.12
|
|
@@ -57,7 +57,7 @@ Requires-Dist: uuid-utils<1.0.0,>=0.10.0
|
|
|
57
57
|
Provides-Extra: agentcore
|
|
58
58
|
Requires-Dist: langchain-agentcore-codeinterpreter>=0.0.1; 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.2; extra == 'all-providers'
|
|
61
61
|
Requires-Dist: langchain-aws<2.0.0,>=1.0.0; extra == 'all-providers'
|
|
62
62
|
Requires-Dist: langchain-baseten<1.0.0,>=0.1.9; extra == 'all-providers'
|
|
63
63
|
Requires-Dist: langchain-cohere<1.0.0,>=0.5.0; extra == 'all-providers'
|
|
@@ -82,7 +82,7 @@ Requires-Dist: langchain-daytona>=0.0.4; extra == 'all-sandboxes'
|
|
|
82
82
|
Requires-Dist: langchain-modal>=0.0.2; extra == 'all-sandboxes'
|
|
83
83
|
Requires-Dist: langchain-runloop>=0.0.3; extra == 'all-sandboxes'
|
|
84
84
|
Provides-Extra: anthropic
|
|
85
|
-
Requires-Dist: langchain-anthropic<2.0.0,>=1.4.
|
|
85
|
+
Requires-Dist: langchain-anthropic<2.0.0,>=1.4.2; extra == 'anthropic'
|
|
86
86
|
Provides-Extra: baseten
|
|
87
87
|
Requires-Dist: langchain-baseten<1.0.0,>=0.1.9; extra == 'baseten'
|
|
88
88
|
Provides-Extra: bedrock
|
|
@@ -37,9 +37,24 @@ DEBUG = "DEEPAGENTS_CLI_DEBUG"
|
|
|
37
37
|
DEBUG_FILE = "DEEPAGENTS_CLI_DEBUG_FILE"
|
|
38
38
|
"""Path for the debug log file (default: `/tmp/deepagents_debug.log`)."""
|
|
39
39
|
|
|
40
|
+
DEBUG_NOTIFICATIONS = "DEEPAGENTS_CLI_DEBUG_NOTIFICATIONS"
|
|
41
|
+
"""Inject sample missing-dependency notifications at launch so the notification
|
|
42
|
+
center UI can be exercised without waiting for real conditions. Does not
|
|
43
|
+
auto-open the update modal (use `DEEPAGENTS_CLI_DEBUG_UPDATE` for that). Any
|
|
44
|
+
non-empty value enables the flag (including `"0"` or `"false"`)."""
|
|
45
|
+
|
|
46
|
+
DEBUG_UPDATE = "DEEPAGENTS_CLI_DEBUG_UPDATE"
|
|
47
|
+
"""Inject a sample update-available notification and auto-open the update modal
|
|
48
|
+
at launch so the update-available flow can be exercised without waiting for a
|
|
49
|
+
real PyPI release. Any non-empty value enables the flag (including `"0"` or
|
|
50
|
+
`"false"`)."""
|
|
51
|
+
|
|
40
52
|
EXTRA_SKILLS_DIRS = "DEEPAGENTS_CLI_EXTRA_SKILLS_DIRS"
|
|
41
53
|
"""Colon-separated paths added to the skill containment allowlist."""
|
|
42
54
|
|
|
55
|
+
KITTY_KEYBOARD = "DEEPAGENTS_CLI_KITTY_KEYBOARD"
|
|
56
|
+
"""Override kitty-keyboard detection (`1` forces on, `0` forces off)."""
|
|
57
|
+
|
|
43
58
|
LANGSMITH_PROJECT = "DEEPAGENTS_CLI_LANGSMITH_PROJECT"
|
|
44
59
|
"""Override LangSmith project name for agent traces."""
|
|
45
60
|
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
"""Lightweight git metadata helpers for CLI state detection."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
_GIT_DIR_POINTER_PREFIX = "gitdir: "
|
|
11
|
+
"""Prefix used by worktree-style `.git` files to point at the real git dir."""
|
|
12
|
+
|
|
13
|
+
_GIT_HEAD_REF_PREFIX = "ref: "
|
|
14
|
+
"""Prefix used by `HEAD` when it points at a named ref instead of a commit."""
|
|
15
|
+
|
|
16
|
+
_GIT_REF_PREFIXES = ("refs/heads/", "refs/remotes/", "refs/tags/", "refs/")
|
|
17
|
+
"""Known git ref prefixes stripped when formatting a branch-like display name."""
|
|
18
|
+
|
|
19
|
+
_git_dir_cache: dict[str, Path] = {}
|
|
20
|
+
"""Positive-only cache of resolved git metadata directories keyed by lookup path."""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _abbreviate_git_ref(ref: str) -> str:
|
|
24
|
+
"""Convert a full git ref into a short display name.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
ref: Full git ref name from repository metadata.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
The abbreviated ref name suitable for display.
|
|
31
|
+
"""
|
|
32
|
+
for prefix in _GIT_REF_PREFIXES:
|
|
33
|
+
if ref.startswith(prefix):
|
|
34
|
+
return ref.removeprefix(prefix)
|
|
35
|
+
return ref
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _parse_git_dir_pointer(git_entry: Path) -> Path | None:
|
|
39
|
+
"""Resolve a `.git` file containing a `gitdir:` pointer.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
git_entry: `.git` file to parse.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
The resolved git directory path, or `None` if the file is not a valid
|
|
46
|
+
gitdir pointer.
|
|
47
|
+
"""
|
|
48
|
+
try:
|
|
49
|
+
raw = git_entry.read_text(encoding="utf-8").strip()
|
|
50
|
+
except OSError:
|
|
51
|
+
logger.debug("Failed to read gitdir pointer from %s", git_entry, exc_info=True)
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
if not raw.startswith(_GIT_DIR_POINTER_PREFIX):
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
pointer = raw.removeprefix(_GIT_DIR_POINTER_PREFIX).strip()
|
|
58
|
+
if not pointer:
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
git_dir = Path(pointer)
|
|
62
|
+
if not git_dir.is_absolute():
|
|
63
|
+
git_dir = git_entry.parent / git_dir
|
|
64
|
+
return git_dir.resolve(strict=False)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _normalize_lookup_path(path: str | Path) -> Path:
|
|
68
|
+
"""Normalize a lookup path for git metadata discovery.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
path: Directory or file path inside a repository.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
A normalized absolute path when possible, or the expanded path if full
|
|
75
|
+
resolution fails.
|
|
76
|
+
"""
|
|
77
|
+
try:
|
|
78
|
+
return Path(path).expanduser().resolve(strict=False)
|
|
79
|
+
except OSError:
|
|
80
|
+
return Path(path).expanduser()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _find_git_dir_uncached(path: Path) -> Path | None:
|
|
84
|
+
"""Locate the effective git metadata directory without using caches.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
path: Normalized directory or file path inside a repository.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
The git metadata directory for the repository containing `path`, or
|
|
91
|
+
`None` when no repository can be identified.
|
|
92
|
+
"""
|
|
93
|
+
current = path
|
|
94
|
+
if not current.is_dir():
|
|
95
|
+
current = current.parent
|
|
96
|
+
|
|
97
|
+
for directory in (current, *current.parents):
|
|
98
|
+
git_entry = directory / ".git"
|
|
99
|
+
if git_entry.is_dir():
|
|
100
|
+
return git_entry
|
|
101
|
+
if git_entry.is_file():
|
|
102
|
+
git_dir = _parse_git_dir_pointer(git_entry)
|
|
103
|
+
if git_dir is not None and git_dir.is_dir():
|
|
104
|
+
return git_dir
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def find_git_dir(path: str | Path) -> Path | None:
|
|
111
|
+
"""Locate the effective git metadata directory for a path.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
path: Directory or file path inside a repository.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
The git metadata directory for the repository containing `path`, or
|
|
118
|
+
`None` when no repository can be identified.
|
|
119
|
+
"""
|
|
120
|
+
current = _normalize_lookup_path(path)
|
|
121
|
+
key = str(current)
|
|
122
|
+
cached = _git_dir_cache.get(key)
|
|
123
|
+
if cached is not None:
|
|
124
|
+
return cached
|
|
125
|
+
|
|
126
|
+
git_dir = _find_git_dir_uncached(current)
|
|
127
|
+
if git_dir is not None:
|
|
128
|
+
_git_dir_cache[key] = git_dir
|
|
129
|
+
return git_dir
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def find_git_root(path: str | Path) -> Path | None:
|
|
133
|
+
"""Locate the repository root for a path.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
path: Directory or file path inside a repository.
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
The repository root containing `path`, or `None` when no repository can
|
|
140
|
+
be identified.
|
|
141
|
+
"""
|
|
142
|
+
current = _normalize_lookup_path(path)
|
|
143
|
+
if not current.is_dir():
|
|
144
|
+
current = current.parent
|
|
145
|
+
|
|
146
|
+
for directory in (current, *current.parents):
|
|
147
|
+
git_entry = directory / ".git"
|
|
148
|
+
if git_entry.is_dir():
|
|
149
|
+
return directory
|
|
150
|
+
if git_entry.is_file():
|
|
151
|
+
git_dir = _parse_git_dir_pointer(git_entry)
|
|
152
|
+
if git_dir is not None and git_dir.is_dir():
|
|
153
|
+
return directory
|
|
154
|
+
return None
|
|
155
|
+
|
|
156
|
+
return None
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def read_git_branch_from_filesystem(path: str | Path) -> str | None:
|
|
160
|
+
"""Read the current git branch from repository metadata.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
path: Directory or file path inside a repository.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
The abbreviated branch name, `HEAD` for detached HEAD, an empty string
|
|
167
|
+
when `path` is not inside a git repository, or `None` when metadata
|
|
168
|
+
exists but cannot be parsed confidently.
|
|
169
|
+
"""
|
|
170
|
+
git_dir = find_git_dir(path)
|
|
171
|
+
if git_dir is None:
|
|
172
|
+
return ""
|
|
173
|
+
|
|
174
|
+
head_path = git_dir / "HEAD"
|
|
175
|
+
try:
|
|
176
|
+
head = head_path.read_text(encoding="utf-8").strip()
|
|
177
|
+
except FileNotFoundError:
|
|
178
|
+
logger.debug("Git HEAD file not found in %s", git_dir)
|
|
179
|
+
return None
|
|
180
|
+
except OSError:
|
|
181
|
+
logger.debug("Failed to read git HEAD from %s", git_dir, exc_info=True)
|
|
182
|
+
return None
|
|
183
|
+
|
|
184
|
+
if not head:
|
|
185
|
+
return ""
|
|
186
|
+
if head.startswith(_GIT_HEAD_REF_PREFIX):
|
|
187
|
+
ref = head.removeprefix(_GIT_HEAD_REF_PREFIX).strip()
|
|
188
|
+
return _abbreviate_git_ref(ref) if ref else None
|
|
189
|
+
return "HEAD"
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def read_git_branch_via_subprocess(path: str | Path) -> str:
|
|
193
|
+
"""Fall back to `git rev-parse` for unusual repository layouts.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
path: Directory or file path inside a repository.
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
The branch name reported by git, or an empty string on failure.
|
|
200
|
+
"""
|
|
201
|
+
import subprocess # noqa: S404 # stdlib subprocess fallback
|
|
202
|
+
|
|
203
|
+
try:
|
|
204
|
+
result = subprocess.run(
|
|
205
|
+
["git", "rev-parse", "--abbrev-ref", "HEAD"], # noqa: S607
|
|
206
|
+
capture_output=True,
|
|
207
|
+
text=True,
|
|
208
|
+
timeout=2,
|
|
209
|
+
check=False,
|
|
210
|
+
cwd=path,
|
|
211
|
+
)
|
|
212
|
+
if result.returncode == 0:
|
|
213
|
+
return result.stdout.strip()
|
|
214
|
+
except FileNotFoundError:
|
|
215
|
+
pass # git not installed
|
|
216
|
+
except subprocess.TimeoutExpired:
|
|
217
|
+
logger.debug("Git branch detection timed out")
|
|
218
|
+
except OSError:
|
|
219
|
+
logger.debug("Git branch detection failed", exc_info=True)
|
|
220
|
+
return ""
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def resolve_git_branch(path: str | Path) -> str:
|
|
224
|
+
"""Resolve the current git branch with a filesystem-first strategy.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
path: Directory or file path inside a repository.
|
|
228
|
+
|
|
229
|
+
Returns:
|
|
230
|
+
The current branch name, `HEAD` for detached HEAD, or an empty string
|
|
231
|
+
when no branch can be determined.
|
|
232
|
+
"""
|
|
233
|
+
branch = read_git_branch_from_filesystem(path)
|
|
234
|
+
if branch is not None:
|
|
235
|
+
return branch
|
|
236
|
+
return read_git_branch_via_subprocess(path)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
r"""Preserve the `alt` modifier on legacy `ESC + <byte>` sequences.
|
|
2
|
+
|
|
3
|
+
Upstream `XTermParser._sequence_to_key_events` drops the `alt` flag on
|
|
4
|
+
the tuple-branch fast path, so VSCode's `sendSequence` shift+enter
|
|
5
|
+
binding (which writes `\x1b\r` to the PTY) arrives as bare `enter`
|
|
6
|
+
instead of `alt+enter`. Tracked in Textualize/textual#6378. Remove this
|
|
7
|
+
file and the Textual pin comment in `pyproject.toml` when that lands.
|
|
8
|
+
|
|
9
|
+
Imported for side effect from `app.py` before any `App()` is created.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
from typing import TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from collections.abc import Iterable
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
_ESC_PREFIX_LEN = 2
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
from textual import events
|
|
26
|
+
from textual._ansi_sequences import (
|
|
27
|
+
ANSI_SEQUENCES_KEYS, # noqa: PLC2701
|
|
28
|
+
IGNORE_SEQUENCE, # noqa: PLC2701
|
|
29
|
+
)
|
|
30
|
+
from textual._xterm_parser import XTermParser # noqa: PLC2701
|
|
31
|
+
|
|
32
|
+
_original = XTermParser._sequence_to_key_events
|
|
33
|
+
except (ImportError, AttributeError) as exc: # pragma: no cover - defensive
|
|
34
|
+
logger.warning("Textual keyboard parser patch skipped: %s", exc)
|
|
35
|
+
else:
|
|
36
|
+
|
|
37
|
+
def _emit_alt(keys: tuple, character: str | None) -> Iterable[events.Key]:
|
|
38
|
+
for key in keys:
|
|
39
|
+
yield events.Key(f"alt+{key.value}", character)
|
|
40
|
+
|
|
41
|
+
def _sequence_to_key_events_with_alt(
|
|
42
|
+
self: XTermParser, sequence: str, alt: bool = False
|
|
43
|
+
) -> Iterable[events.Key]:
|
|
44
|
+
# Fast path: \x1b<byte> on first pass. Short-circuits the ~100 ms
|
|
45
|
+
# escape-delay wait when both bytes arrive together. Semantic side
|
|
46
|
+
# effect: \x1b\x1b dispatches as `alt+escape` with no delay, matching
|
|
47
|
+
# crossterm and Node TTY.
|
|
48
|
+
if not alt and len(sequence) == _ESC_PREFIX_LEN and sequence[0] == "\x1b":
|
|
49
|
+
inner = ANSI_SEQUENCES_KEYS.get(sequence[1])
|
|
50
|
+
if inner is not IGNORE_SEQUENCE and isinstance(inner, tuple):
|
|
51
|
+
yield from _emit_alt(inner, None)
|
|
52
|
+
return
|
|
53
|
+
# Correctness fix (Textualize/textual#6378): preserve `alt` on the
|
|
54
|
+
# reissue path for single-byte tuple mappings.
|
|
55
|
+
if alt:
|
|
56
|
+
keys = ANSI_SEQUENCES_KEYS.get(sequence)
|
|
57
|
+
if keys is not IGNORE_SEQUENCE and isinstance(keys, tuple):
|
|
58
|
+
character = sequence if len(sequence) == 1 else None
|
|
59
|
+
yield from _emit_alt(keys, character)
|
|
60
|
+
return
|
|
61
|
+
yield from _original(self, sequence, alt=alt)
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
XTermParser._sequence_to_key_events = _sequence_to_key_events_with_alt # ty: ignore[invalid-assignment]
|
|
65
|
+
except (AttributeError, TypeError) as exc: # pragma: no cover - defensive
|
|
66
|
+
logger.warning("Textual keyboard parser patch assignment rejected: %s", exc)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Version information and lightweight constants for `deepagents-cli`."""
|
|
2
2
|
|
|
3
|
-
__version__ = "0.0.
|
|
3
|
+
__version__ = "0.0.42" # x-release-please-version
|
|
4
4
|
|
|
5
5
|
DOCS_URL = "https://docs.langchain.com/oss/python/deepagents/cli"
|
|
6
6
|
"""URL for `deepagents-cli` documentation."""
|
|
@@ -8,6 +8,13 @@ DOCS_URL = "https://docs.langchain.com/oss/python/deepagents/cli"
|
|
|
8
8
|
PYPI_URL = "https://pypi.org/pypi/deepagents-cli/json"
|
|
9
9
|
"""PyPI JSON API endpoint for version checks."""
|
|
10
10
|
|
|
11
|
+
SDK_PYPI_URL = "https://pypi.org/pypi/deepagents/json"
|
|
12
|
+
"""PyPI JSON API endpoint for reading `deepagents` SDK release metadata.
|
|
13
|
+
|
|
14
|
+
The CLI only reads release-age metadata from this endpoint; it never
|
|
15
|
+
performs SDK update checks.
|
|
16
|
+
"""
|
|
17
|
+
|
|
11
18
|
CHANGELOG_URL = (
|
|
12
19
|
"https://github.com/langchain-ai/deepagents/blob/main/libs/cli/CHANGELOG.md"
|
|
13
20
|
)
|
|
@@ -16,6 +16,18 @@ from deepagents.backends import CompositeBackend, LocalShellBackend
|
|
|
16
16
|
from deepagents.backends.filesystem import FilesystemBackend
|
|
17
17
|
from deepagents.middleware import MemoryMiddleware, SkillsMiddleware
|
|
18
18
|
|
|
19
|
+
# Backwards-compat flag: SDKs before 0.5.4 accept only `list[str]` for
|
|
20
|
+
# `SkillsMiddleware.sources`; newer SDKs expose the `SkillSource` alias
|
|
21
|
+
# that permits `(path, label)` tuples. The `skills` module is already
|
|
22
|
+
# loaded by the `SkillsMiddleware` import above, so the extra lookup
|
|
23
|
+
# here adds no startup cost.
|
|
24
|
+
try:
|
|
25
|
+
from deepagents.middleware.skills import SkillSource as _SkillSource # noqa: F401
|
|
26
|
+
except ImportError:
|
|
27
|
+
_SUPPORTS_SKILL_SOURCE_TUPLES = False
|
|
28
|
+
else:
|
|
29
|
+
_SUPPORTS_SKILL_SOURCE_TUPLES = True
|
|
30
|
+
|
|
19
31
|
if TYPE_CHECKING:
|
|
20
32
|
from collections.abc import Awaitable, Callable, Sequence
|
|
21
33
|
|
|
@@ -1116,25 +1128,40 @@ def create_cli_agent(
|
|
|
1116
1128
|
# built-in -> user .deepagents -> user .agents
|
|
1117
1129
|
# -> project .deepagents -> project .agents
|
|
1118
1130
|
# -> user .claude (experimental) -> project .claude (experimental)
|
|
1119
|
-
sources
|
|
1120
|
-
|
|
1131
|
+
# Labels disambiguate user- vs project-scoped sources that share a
|
|
1132
|
+
# `.../skills` leaf; the middleware would otherwise derive identical
|
|
1133
|
+
# labels from the parent directory name.
|
|
1134
|
+
sources: list[tuple[str, str]] = [
|
|
1135
|
+
(str(settings.get_built_in_skills_dir()), "Built-in"),
|
|
1136
|
+
(str(skills_dir), "User Deepagents"),
|
|
1137
|
+
(str(user_agent_skills_dir), "User Agents"),
|
|
1138
|
+
]
|
|
1121
1139
|
if project_skills_dir:
|
|
1122
|
-
sources.append(str(project_skills_dir))
|
|
1140
|
+
sources.append((str(project_skills_dir), "Project Deepagents"))
|
|
1123
1141
|
if project_agent_skills_dir:
|
|
1124
|
-
sources.append(str(project_agent_skills_dir))
|
|
1142
|
+
sources.append((str(project_agent_skills_dir), "Project Agents"))
|
|
1125
1143
|
|
|
1126
1144
|
# Experimental: Claude Code skill directories
|
|
1127
1145
|
user_claude_skills_dir = settings.get_user_claude_skills_dir()
|
|
1128
1146
|
if user_claude_skills_dir.exists():
|
|
1129
|
-
sources.append(str(user_claude_skills_dir))
|
|
1147
|
+
sources.append((str(user_claude_skills_dir), "User Claude"))
|
|
1130
1148
|
project_claude_skills_dir = settings.get_project_claude_skills_dir()
|
|
1131
1149
|
if project_claude_skills_dir:
|
|
1132
|
-
sources.append(str(project_claude_skills_dir))
|
|
1150
|
+
sources.append((str(project_claude_skills_dir), "Project Claude"))
|
|
1151
|
+
|
|
1152
|
+
# Backwards-compat: strip labels when the installed SDK is too old
|
|
1153
|
+
# to accept `(path, label)` tuples. Label-based disambiguation
|
|
1154
|
+
# regresses to the pre-alias behavior (user- and project-scoped
|
|
1155
|
+
# `.claude/skills` collapse to the same label), but functionality
|
|
1156
|
+
# is preserved.
|
|
1157
|
+
middleware_sources: Sequence[str | tuple[str, str]] = (
|
|
1158
|
+
sources if _SUPPORTS_SKILL_SOURCE_TUPLES else [path for path, _ in sources]
|
|
1159
|
+
)
|
|
1133
1160
|
|
|
1134
1161
|
agent_middleware.append(
|
|
1135
1162
|
SkillsMiddleware(
|
|
1136
1163
|
backend=FilesystemBackend(),
|
|
1137
|
-
sources=
|
|
1164
|
+
sources=middleware_sources,
|
|
1138
1165
|
)
|
|
1139
1166
|
)
|
|
1140
1167
|
|