deepagents-cli 0.0.45__tar.gz → 0.0.46__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.45 → deepagents_cli-0.0.46}/CHANGELOG.md +7 -0
- deepagents_cli-0.0.46/DEV.md +92 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/PKG-INFO +1 -1
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/_debug.py +3 -3
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/_env_vars.py +38 -1
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/_version.py +1 -1
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/app.py +73 -4
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/main.py +45 -15
- deepagents_cli-0.0.46/deepagents_cli/mcp_auth.py +704 -0
- deepagents_cli-0.0.46/deepagents_cli/mcp_commands.py +202 -0
- deepagents_cli-0.0.46/deepagents_cli/mcp_providers/__init__.py +23 -0
- deepagents_cli-0.0.46/deepagents_cli/mcp_providers/_registry.py +39 -0
- deepagents_cli-0.0.46/deepagents_cli/mcp_providers/base.py +99 -0
- deepagents_cli-0.0.46/deepagents_cli/mcp_providers/github.py +91 -0
- deepagents_cli-0.0.46/deepagents_cli/mcp_providers/slack.py +130 -0
- deepagents_cli-0.0.46/deepagents_cli/mcp_tools.py +1521 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/server.py +20 -3
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/server_graph.py +25 -2
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/server_manager.py +64 -1
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/ui.py +35 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/mcp_viewer.py +159 -89
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/welcome.py +44 -1
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/pyproject.toml +7 -1
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_agent_friendly.py +8 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_app.py +57 -6
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_args.py +74 -1
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_env_vars.py +45 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_local_context.py +3 -1
- deepagents_cli-0.0.46/tests/unit_tests/test_mcp_auth.py +957 -0
- deepagents_cli-0.0.46/tests/unit_tests/test_mcp_commands.py +332 -0
- deepagents_cli-0.0.46/tests/unit_tests/test_mcp_tools.py +2264 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_mcp_viewer.py +14 -6
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_server_graph.py +13 -6
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_server_manager.py +60 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/uv.lock +1 -1
- deepagents_cli-0.0.45/DEV.md +0 -52
- deepagents_cli-0.0.45/deepagents_cli/mcp_tools.py +0 -712
- deepagents_cli-0.0.45/tests/unit_tests/test_mcp_tools.py +0 -1804
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/.gitignore +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/Makefile +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/README.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/THREAT_MODEL.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/__init__.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/__main__.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/_ask_user_types.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/_cli_context.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/_git.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/_server_config.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/_session_stats.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/_testing_models.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/_textual_patches.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/agent.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/app.tcss +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/ask_user.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/built_in_skills/__init__.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/built_in_skills/remember/SKILL.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/built_in_skills/skill-creator/SKILL.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/clipboard.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/command_registry.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/config.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/configurable_model.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/default_agent_prompt.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/deploy/__init__.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/deploy/bundler.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/deploy/commands.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/deploy/config.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/deploy/frontend_dist/assets/anonymous-B9UzAXQd.js +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/deploy/frontend_dist/assets/clerk-5xHgyQyG.js +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/deploy/frontend_dist/assets/highlighted-body-OFNGDK62-rX-7qT8o.js +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/deploy/frontend_dist/assets/index-DM3gptpu.js +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/deploy/frontend_dist/assets/index-Ddy7F6KI.css +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/deploy/frontend_dist/assets/supabase-S6NACDgm.js +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/deploy/frontend_dist/index.html +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/deploy/frontend_dist/logo-dark.svg +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/deploy/frontend_dist/logo-light.svg +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/deploy/templates.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/editor.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/extras_info.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/file_ops.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/formatting.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/hooks.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/input.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/integrations/__init__.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/integrations/sandbox_factory.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/integrations/sandbox_provider.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/local_context.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/mcp_trust.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/media_utils.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/model_config.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/non_interactive.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/notifications.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/offload.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/output.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/project_utils.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/py.typed +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/remote_client.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/sessions.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/skills/__init__.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/skills/commands.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/skills/invocation.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/skills/load.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/subagents.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/system_prompt.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/terminal_capabilities.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/textual_adapter.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/theme.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/token_state.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/tool_display.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/tools.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/unicode_security.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/update_check.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/__init__.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/_links.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/agent_selector.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/approval.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/ask_user.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/autocomplete.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/chat_input.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/diff.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/history.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/loading.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/message_store.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/messages.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/model_selector.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/notification_center.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/notification_detail.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/notification_settings.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/status.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/theme_selector.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/thread_selector.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/tool_renderers.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/tool_widgets.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/deepagents_cli/widgets/update_available.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/examples/deploy-content-writer/.env.example +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/examples/deploy-content-writer/skills/blog-post/SKILL.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/examples/deploy-content-writer/skills/social-media/SKILL.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/examples/deploy-content-writer/user/context.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/examples/deploy-content-writer/user/preferences.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/examples/skills/arxiv-search/SKILL.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/examples/skills/arxiv-search/arxiv_search.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/examples/skills/langgraph-docs/SKILL.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/examples/skills/skill-creator/SKILL.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/examples/skills/web-research/SKILL.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/.nvmrc +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/index.html +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/package-lock.json +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/package.json +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/postcss.config.js +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/public/logo-dark.svg +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/public/logo-light.svg +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/App.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/ThemeProvider.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/auth/anonymous.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/auth/clerk.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/auth/loader.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/auth/supabase.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/auth/types.ts +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/components/AppHeader.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/components/FilePanels.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/components/MessageList.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/components/SubagentActivity.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/components/ThreadPicker.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/components/TodosPanel.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/components/ToolCallCard.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/components/toolcalls/FileToolCard.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/components/toolcalls/SearchCard.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/components/toolcalls/ThinkCard.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/components/toolcalls/TodosCard.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/components/toolcalls/index.ts +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/constants.ts +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/index.css +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/main.tsx +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/runtimeConfig.ts +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/types.ts +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/src/vite-env.d.ts +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/tsconfig.json +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/frontend/vite.config.ts +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/images/cli.png +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/scripts/check_imports.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/scripts/debug_server.sh +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/scripts/install.sh +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/README.md +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/integration_tests/__init__.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/integration_tests/benchmarks/__init__.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/integration_tests/conftest.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/integration_tests/test_acp_mode.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/integration_tests/test_compact_resume.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/integration_tests/test_sandbox_factory.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/integration_tests/test_sandbox_operations.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/__init__.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/conftest.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/deploy/__init__.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/deploy/test_bundler.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/deploy/test_commands.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/deploy/test_config.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/deploy/test_frontend_bundle.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/deploy/test_frontend_config.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/skills/__init__.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/skills/test_commands.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/skills/test_load.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/skills/test_skills_json.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_agent.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_agent_selector.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_approval.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_ask_user.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_ask_user_middleware.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_autocomplete.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_charset.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_chat_input.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_command_registry.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_compact_tool.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_config.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_configurable_model.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_debug.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_editor.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_end_to_end.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_exception_handling.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_extras_info.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_file_ops.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_formatting.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_git.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_history.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_hooks.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_imports.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_input_parsing.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_links.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_loading.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_main.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_main_acp_mode.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_main_args.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_mcp_trust.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_media_utils.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_message_store.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_messages.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_model_config.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_model_selector.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_model_switch.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_non_interactive.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_notification_center.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_notification_detail.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_notifications.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_offload.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_offload_dict_messages.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_output.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_reload.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_remote_client.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_sandbox_factory.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_server.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_server_config.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_server_helpers.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_session_stats.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_sessions.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_shell_allow_list.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_skill_invocation.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_status.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_subagents.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_terminal_capabilities.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_textual_adapter.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_textual_patches.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_theme.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_thread_selector.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_token_tracker.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_tool_display.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_ui.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_unicode_security.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_update_available.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_update_check.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_version.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/test_welcome.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/tools/__init__.py +0 -0
- {deepagents_cli-0.0.45 → deepagents_cli-0.0.46}/tests/unit_tests/tools/test_fetch_url.py +0 -0
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.46](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.45...deepagents-cli==0.0.46) (2026-04-30)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* Rework MCP integration and add OAuth login ([#2906](https://github.com/langchain-ai/deepagents/issues/2906)) ([6b7b0be](https://github.com/langchain-ai/deepagents/commit/6b7b0bef95db673fed23fc92803abaaa398b0a6d))
|
|
8
|
+
* `allowedTools` and `disabledTools` filters in MCP config ([#2835](https://github.com/langchain-ai/deepagents/issues/2835)) ([eafd691](https://github.com/langchain-ai/deepagents/commit/eafd6912db637ab59085a0b05d6e36d6cdd10e1a))
|
|
9
|
+
|
|
3
10
|
## [0.0.45](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.44...deepagents-cli==0.0.45) (2026-04-30)
|
|
4
11
|
|
|
5
12
|
### Bug Fixes
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# CLI Development Guide
|
|
2
|
+
|
|
3
|
+
## Live CSS development with Textual devtools
|
|
4
|
+
|
|
5
|
+
Textual's devtools console enables CSS hot-reload and live `self.log()` output during development.
|
|
6
|
+
|
|
7
|
+
### Prerequisites
|
|
8
|
+
|
|
9
|
+
Sync the `test` dependency group (includes `textual-dev`):
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
cd libs/cli && uv sync --group test
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Create the dev wrapper script (one-time):
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
cat > /tmp/dev_deepagents.py << 'PYEOF'
|
|
19
|
+
"""Dev wrapper to run Deep Agents CLI with textual devtools."""
|
|
20
|
+
import sys
|
|
21
|
+
sys.argv = ["deepagents"] + sys.argv[1:]
|
|
22
|
+
|
|
23
|
+
from deepagents_cli.main import cli_main
|
|
24
|
+
cli_main()
|
|
25
|
+
PYEOF
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Running
|
|
29
|
+
|
|
30
|
+
**Terminal 1** — devtools console:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cd libs/cli && uv run --group test textual console
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Terminal 2** — CLI with live reload:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
cd libs/cli && uv run --group test textual run --dev /tmp/dev_deepagents.py
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Edit any `.tcss` file and save — changes appear immediately. Any `self.log()` calls in widget code show in the console.
|
|
43
|
+
|
|
44
|
+
### Console options
|
|
45
|
+
|
|
46
|
+
- `textual console -v` — verbose mode, shows all events (key presses, mouse, etc.)
|
|
47
|
+
- `textual console -x EVENT` — exclude noisy event groups
|
|
48
|
+
- `textual console --port 7342` — custom port (pass matching `--port` to `textual run`)
|
|
49
|
+
|
|
50
|
+
### Why the wrapper script?
|
|
51
|
+
|
|
52
|
+
`textual run --dev` handles the devtools connection, but it needs to run inside the project's virtualenv to import `deepagents_cli`. The wrapper script bridges the gap — `uv run --group test textual run --dev` ensures both `textual-dev` (from the `test` group) and `deepagents_cli` are available in the same environment.
|
|
53
|
+
|
|
54
|
+
## Debugging
|
|
55
|
+
|
|
56
|
+
The CLI runs a `langgraph dev` subprocess for every interactive session. When the subprocess crashes during startup, the TUI shows a one-line failure banner; the actual exception lives in the subprocess's stdout/stderr, which is captured to a temp file.
|
|
57
|
+
|
|
58
|
+
### Environment variables
|
|
59
|
+
|
|
60
|
+
| Variable | Effect |
|
|
61
|
+
| --- | --- |
|
|
62
|
+
| `DEEPAGENTS_CLI_DEBUG=1` | Preserves the server subprocess log on shutdown and prints its path to stderr. Without this, the log is deleted when the process stops. Also enables the CLI-process file handler below. Accepts `1`/`true`/`yes`/`on` (case-insensitive) as enabled; `0`/`false`/`no`/`off`/empty/unset as disabled. |
|
|
63
|
+
| `DEEPAGENTS_CLI_DEBUG_FILE=<path>` | Overrides the default path (`/tmp/deepagents_debug.log`) for the CLI-process file handler, which attaches at `DEBUG` level to `textual_adapter` and `remote_client`. **Only takes effect when `DEEPAGENTS_CLI_DEBUG` is truthy.** Useful for diagnosing streaming/client-side issues; does **not** capture the server subprocess. |
|
|
64
|
+
|
|
65
|
+
`DEEPAGENTS_CLI_DEBUG` is what you want for startup crashes (graph init, MCP config, sandbox): the preserved subprocess log contains the real traceback. The optional `DEEPAGENTS_CLI_DEBUG_FILE` override is for post-startup client-side debugging.
|
|
66
|
+
|
|
67
|
+
### Finding the server subprocess log
|
|
68
|
+
|
|
69
|
+
On macOS, `tempfile` resolves to `$TMPDIR` (a path under `/var/folders/.../T/`). Each `ServerProcess` writes its combined stdout+stderr to a file matching `deepagents_server_log_*.txt`:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Newest first
|
|
73
|
+
ls -lt ${TMPDIR:-/tmp}/deepagents_server_log_*.txt | head -5
|
|
74
|
+
|
|
75
|
+
# Tail the latest while reproducing the crash
|
|
76
|
+
tail -F "$(ls -t ${TMPDIR:-/tmp}/deepagents_server_log_*.txt | head -1)"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The interesting line is `Failed to initialize server graph: <exc>` followed by a traceback — everything above that is uvicorn/lifespan unwinding.
|
|
80
|
+
|
|
81
|
+
### Triage flow for a startup crash
|
|
82
|
+
|
|
83
|
+
1. **Rerun with `DEEPAGENTS_CLI_DEBUG=1`.** The log is preserved and a "Server log preserved at: ..." line is printed to stderr. Textual's fullscreen mode can hide that line, but the file itself is still on disk.
|
|
84
|
+
2. **Locate the log** via the `ls` command above. Open it in your editor.
|
|
85
|
+
3. **Search for `Failed to initialize server graph`.** The stack trace beneath names the concrete failure point (MCP config validation, sandbox init, model resolution, subagent load, etc.).
|
|
86
|
+
4. **Pre-flight validators run in the CLI process** for the common failure modes (e.g., `--mcp-config` is validated in `start_server_and_get_agent` before the subprocess spawns). When the banner shows `MCPConfigError: <path>: <reason>`, the subprocess never started — fix the file and retry.
|
|
87
|
+
|
|
88
|
+
### Common startup failure patterns
|
|
89
|
+
|
|
90
|
+
- **`MCPConfigError: Invalid MCP config at <path>: ...`** — malformed `--mcp-config`. The pre-flight wraps the underlying `ValueError`/`TypeError` with the offending path. See `_preflight_validate_mcp_config` in `server_manager.py`.
|
|
91
|
+
- **`Server 'X' missing required 'command' field`** (from a discovered project `.mcp.json`, not `--mcp-config`) — an stdio server config without `command`. For remote servers, just use `{"url": "..."}`; transport is inferred as `http` when no `type`/`transport` is present.
|
|
92
|
+
- **Uncaught exception inside a bare `sys.exit(1)`** — usually means the surrounding `make_graph()` raised. Look one traceback up in the subprocess log for the real cause.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepagents-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.46
|
|
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/
|
|
@@ -12,7 +12,7 @@ import logging
|
|
|
12
12
|
import os
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
|
|
15
|
-
from deepagents_cli._env_vars import DEBUG, DEBUG_FILE
|
|
15
|
+
from deepagents_cli._env_vars import DEBUG, DEBUG_FILE, is_env_truthy
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def configure_debug_logging(target: logging.Logger) -> None:
|
|
@@ -22,12 +22,12 @@ def configure_debug_logging(target: logging.Logger) -> None:
|
|
|
22
22
|
with `DEEPAGENTS_CLI_DEBUG_FILE`. The handler appends so that multiple
|
|
23
23
|
modules share the same log file across a session.
|
|
24
24
|
|
|
25
|
-
Does nothing when `DEEPAGENTS_CLI_DEBUG` is not
|
|
25
|
+
Does nothing when `DEEPAGENTS_CLI_DEBUG` is not truthy (see `is_env_truthy`).
|
|
26
26
|
|
|
27
27
|
Args:
|
|
28
28
|
target: Logger to configure.
|
|
29
29
|
"""
|
|
30
|
-
if not
|
|
30
|
+
if not is_env_truthy(DEBUG):
|
|
31
31
|
return
|
|
32
32
|
|
|
33
33
|
debug_path = Path(
|
|
@@ -23,6 +23,8 @@ ever renamed, only the value here changes.
|
|
|
23
23
|
|
|
24
24
|
from __future__ import annotations
|
|
25
25
|
|
|
26
|
+
import os
|
|
27
|
+
|
|
26
28
|
# ---------------------------------------------------------------------------
|
|
27
29
|
# Constants — import these instead of bare string literals.
|
|
28
30
|
# Keep alphabetically sorted by constant name.
|
|
@@ -32,7 +34,10 @@ AUTO_UPDATE = "DEEPAGENTS_CLI_AUTO_UPDATE"
|
|
|
32
34
|
"""Enable automatic CLI updates ('1', 'true', or 'yes')."""
|
|
33
35
|
|
|
34
36
|
DEBUG = "DEEPAGENTS_CLI_DEBUG"
|
|
35
|
-
"""Enable verbose debug logging
|
|
37
|
+
"""Enable verbose debug logging and preserve the server subprocess log.
|
|
38
|
+
|
|
39
|
+
Parsed by `is_env_truthy`: accepts `1`, `true`, `yes`, `on` (case-insensitive)
|
|
40
|
+
as enabled, and `0`, `false`, `no`, `off`, empty string, or unset as disabled."""
|
|
36
41
|
|
|
37
42
|
DEBUG_FILE = "DEEPAGENTS_CLI_DEBUG_FILE"
|
|
38
43
|
"""Path for the debug log file (default: `/tmp/deepagents_debug.log`)."""
|
|
@@ -69,3 +74,35 @@ SHELL_ALLOW_LIST = "DEEPAGENTS_CLI_SHELL_ALLOW_LIST"
|
|
|
69
74
|
|
|
70
75
|
USER_ID = "DEEPAGENTS_CLI_USER_ID"
|
|
71
76
|
"""Attach a user identifier to LangSmith trace metadata."""
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
_TRUTHY_VALUES = frozenset({"1", "true", "yes", "on"})
|
|
80
|
+
_FALSY_VALUES = frozenset({"0", "false", "no", "off", ""})
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def is_env_truthy(name: str, *, default: bool = False) -> bool:
|
|
84
|
+
"""Return whether env var *name* is set to a recognizably truthy value.
|
|
85
|
+
|
|
86
|
+
Unlike `bool(os.environ.get(name))`, this does not treat `"0"` or
|
|
87
|
+
`"false"` as enabled. Use this for on/off flags where the user would
|
|
88
|
+
reasonably expect `VAR=0` to mean "disabled".
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
name: Environment variable name (typically a `DEEPAGENTS_CLI_*`
|
|
92
|
+
constant from this module).
|
|
93
|
+
default: Value returned when the variable is unset OR set to a
|
|
94
|
+
value that is neither recognizably truthy nor falsy.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
`True` for `1`/`true`/`yes`/`on` (case-insensitive), `False` for
|
|
98
|
+
`0`/`false`/`no`/`off`/empty string, or `default` otherwise.
|
|
99
|
+
"""
|
|
100
|
+
raw = os.environ.get(name)
|
|
101
|
+
if raw is None:
|
|
102
|
+
return default
|
|
103
|
+
lowered = raw.strip().lower()
|
|
104
|
+
if lowered in _TRUTHY_VALUES:
|
|
105
|
+
return True
|
|
106
|
+
if lowered in _FALSY_VALUES:
|
|
107
|
+
return False
|
|
108
|
+
return default
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Version information and lightweight constants for `deepagents-cli`."""
|
|
2
2
|
|
|
3
|
-
__version__ = "0.0.
|
|
3
|
+
__version__ = "0.0.46" # 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."""
|
|
@@ -428,6 +428,27 @@ def _truncate(text: str, *, limit: int) -> str:
|
|
|
428
428
|
return text[: limit - 1].rstrip() + "…"
|
|
429
429
|
|
|
430
430
|
|
|
431
|
+
def _format_startup_error(error: BaseException) -> str:
|
|
432
|
+
"""Format a server-startup exception for the welcome banner.
|
|
433
|
+
|
|
434
|
+
`wait_for_server_healthy` appends a tail of the subprocess log to its
|
|
435
|
+
`RuntimeError` message (see `_LOG_TAIL_CHARS` in `server.py`), which
|
|
436
|
+
would overwhelm the banner. Trim to the headline so the user sees an
|
|
437
|
+
actionable line instead of a scrolling traceback; `DEEPAGENTS_CLI_DEBUG=1`
|
|
438
|
+
preserves the full log on disk for triage.
|
|
439
|
+
|
|
440
|
+
Args:
|
|
441
|
+
error: The exception raised during server startup.
|
|
442
|
+
|
|
443
|
+
Returns:
|
|
444
|
+
A single-line `Type: message` summary suitable for the banner.
|
|
445
|
+
"""
|
|
446
|
+
first_line = str(error).splitlines()[0].strip() if str(error) else ""
|
|
447
|
+
if not first_line:
|
|
448
|
+
first_line = error.__class__.__name__
|
|
449
|
+
return f"{type(error).__name__}: {_truncate(first_line, limit=300)}"
|
|
450
|
+
|
|
451
|
+
|
|
431
452
|
class TextualSessionState:
|
|
432
453
|
"""Session state for the Textual app."""
|
|
433
454
|
|
|
@@ -755,6 +776,19 @@ class DeepAgentsApp(App):
|
|
|
755
776
|
self._mcp_tool_count = sum(len(s.tools) for s in (mcp_server_info or []))
|
|
756
777
|
"""Total tool count across MCP servers, displayed in the status bar."""
|
|
757
778
|
|
|
779
|
+
self._mcp_unauthenticated = sum(
|
|
780
|
+
1 for s in (mcp_server_info or []) if s.status == "unauthenticated"
|
|
781
|
+
)
|
|
782
|
+
"""MCP servers awaiting a `deepagents mcp login` run."""
|
|
783
|
+
|
|
784
|
+
self._mcp_errored = sum(
|
|
785
|
+
1 for s in (mcp_server_info or []) if s.status == "error"
|
|
786
|
+
)
|
|
787
|
+
"""MCP servers that failed to load (config or network error)."""
|
|
788
|
+
|
|
789
|
+
self._active_mcp_viewer: Any = None
|
|
790
|
+
"""Handle to the `/mcp` modal so server-ready events can refresh it."""
|
|
791
|
+
|
|
758
792
|
self._profile_override = profile_override
|
|
759
793
|
"""Extra profile fields from `--profile-override`, retained so later
|
|
760
794
|
profile-aware behavior (model selection, offload budget display,
|
|
@@ -1090,6 +1124,8 @@ class DeepAgentsApp(App):
|
|
|
1090
1124
|
yield WelcomeBanner(
|
|
1091
1125
|
thread_id=self._lc_thread_id,
|
|
1092
1126
|
mcp_tool_count=self._mcp_tool_count,
|
|
1127
|
+
mcp_unauthenticated=self._mcp_unauthenticated,
|
|
1128
|
+
mcp_errored=self._mcp_errored,
|
|
1093
1129
|
connecting=self._connecting,
|
|
1094
1130
|
resuming=self._resume_thread_intent is not None,
|
|
1095
1131
|
local_server=self._server_kwargs is not None,
|
|
@@ -1707,14 +1743,28 @@ class DeepAgentsApp(App):
|
|
|
1707
1743
|
self._server_proc = event.server_proc
|
|
1708
1744
|
self._mcp_server_info = event.mcp_server_info
|
|
1709
1745
|
self._mcp_tool_count = sum(len(s.tools) for s in (event.mcp_server_info or []))
|
|
1746
|
+
self._mcp_unauthenticated = sum(
|
|
1747
|
+
1 for s in (event.mcp_server_info or []) if s.status == "unauthenticated"
|
|
1748
|
+
)
|
|
1749
|
+
self._mcp_errored = sum(
|
|
1750
|
+
1 for s in (event.mcp_server_info or []) if s.status == "error"
|
|
1751
|
+
)
|
|
1710
1752
|
|
|
1711
1753
|
# Update welcome banner to show ready state
|
|
1712
1754
|
try:
|
|
1713
1755
|
banner = self.query_one("#welcome-banner", WelcomeBanner)
|
|
1714
|
-
banner.set_connected(
|
|
1756
|
+
banner.set_connected(
|
|
1757
|
+
self._mcp_tool_count,
|
|
1758
|
+
mcp_unauthenticated=self._mcp_unauthenticated,
|
|
1759
|
+
mcp_errored=self._mcp_errored,
|
|
1760
|
+
)
|
|
1715
1761
|
except NoMatches:
|
|
1716
1762
|
logger.warning("Welcome banner not found during server ready transition")
|
|
1717
1763
|
|
|
1764
|
+
if self._active_mcp_viewer is not None:
|
|
1765
|
+
with suppress(Exception):
|
|
1766
|
+
self._active_mcp_viewer.refresh_server_info(self._mcp_server_info or [])
|
|
1767
|
+
|
|
1718
1768
|
# Session-start sequence: load resumed history, run `--startup-cmd`
|
|
1719
1769
|
# (if any), then dispatch the initial prompt/skill and drain
|
|
1720
1770
|
# user-typed messages. Sequenced through a single task so the
|
|
@@ -1746,8 +1796,14 @@ class DeepAgentsApp(App):
|
|
|
1746
1796
|
|
|
1747
1797
|
def on_deep_agents_app_server_start_failed(self, event: ServerStartFailed) -> None:
|
|
1748
1798
|
"""Handle background server startup failure."""
|
|
1799
|
+
from deepagents_cli.mcp_tools import MCPConfigError
|
|
1800
|
+
|
|
1749
1801
|
self._connecting = False
|
|
1750
|
-
|
|
1802
|
+
if isinstance(event.error, MCPConfigError):
|
|
1803
|
+
# Already carries the path + hint; showing the class name is noise.
|
|
1804
|
+
self._server_startup_error = str(event.error)
|
|
1805
|
+
else:
|
|
1806
|
+
self._server_startup_error = _format_startup_error(event.error)
|
|
1751
1807
|
logger.error("Server startup failed: %s", event.error, exc_info=event.error)
|
|
1752
1808
|
# Update banner to show persistent failure state
|
|
1753
1809
|
try:
|
|
@@ -5048,6 +5104,7 @@ class DeepAgentsApp(App):
|
|
|
5048
5104
|
bar indicator and session state.
|
|
5049
5105
|
"""
|
|
5050
5106
|
from deepagents_cli.widgets.agent_selector import AgentSelectorScreen
|
|
5107
|
+
from deepagents_cli.widgets.mcp_viewer import MCPViewerScreen
|
|
5051
5108
|
from deepagents_cli.widgets.notification_center import (
|
|
5052
5109
|
NotificationCenterScreen,
|
|
5053
5110
|
)
|
|
@@ -5074,6 +5131,9 @@ class DeepAgentsApp(App):
|
|
|
5074
5131
|
):
|
|
5075
5132
|
self.screen.action_move_up()
|
|
5076
5133
|
return
|
|
5134
|
+
if isinstance(self.screen, MCPViewerScreen):
|
|
5135
|
+
self.screen.action_move_up()
|
|
5136
|
+
return
|
|
5077
5137
|
# shift+tab is reused for navigation inside modal screens (e.g.
|
|
5078
5138
|
# ModelSelectorScreen); skip the toggle so it doesn't fire through.
|
|
5079
5139
|
if isinstance(self.screen, ModalScreen):
|
|
@@ -5645,7 +5705,11 @@ class DeepAgentsApp(App):
|
|
|
5645
5705
|
self._connecting = False
|
|
5646
5706
|
try:
|
|
5647
5707
|
banner = self.query_one("#welcome-banner", WelcomeBanner)
|
|
5648
|
-
banner.set_connected(
|
|
5708
|
+
banner.set_connected(
|
|
5709
|
+
self._mcp_tool_count,
|
|
5710
|
+
mcp_unauthenticated=self._mcp_unauthenticated,
|
|
5711
|
+
mcp_errored=self._mcp_errored,
|
|
5712
|
+
)
|
|
5649
5713
|
except NoMatches:
|
|
5650
5714
|
pass
|
|
5651
5715
|
self.notify(
|
|
@@ -6221,9 +6285,14 @@ class DeepAgentsApp(App):
|
|
|
6221
6285
|
"""Show read-only MCP server/tool viewer as a modal screen."""
|
|
6222
6286
|
from deepagents_cli.widgets.mcp_viewer import MCPViewerScreen
|
|
6223
6287
|
|
|
6224
|
-
screen = MCPViewerScreen(
|
|
6288
|
+
screen = MCPViewerScreen(
|
|
6289
|
+
server_info=self._mcp_server_info or [],
|
|
6290
|
+
connecting=self._connecting,
|
|
6291
|
+
)
|
|
6292
|
+
self._active_mcp_viewer = screen
|
|
6225
6293
|
|
|
6226
6294
|
def handle_result(result: None) -> None: # noqa: ARG001
|
|
6295
|
+
self._active_mcp_viewer = None
|
|
6227
6296
|
if self._chat_input:
|
|
6228
6297
|
self._chat_input.focus_input()
|
|
6229
6298
|
|
|
@@ -388,6 +388,7 @@ def parse_args() -> argparse.Namespace:
|
|
|
388
388
|
Parsed arguments namespace.
|
|
389
389
|
"""
|
|
390
390
|
from deepagents_cli.deploy import setup_deploy_parsers
|
|
391
|
+
from deepagents_cli.mcp_commands import setup_mcp_parsers
|
|
391
392
|
from deepagents_cli.output import add_json_output_arg
|
|
392
393
|
from deepagents_cli.skills import setup_skills_parser
|
|
393
394
|
|
|
@@ -516,6 +517,10 @@ def parse_args() -> argparse.Namespace:
|
|
|
516
517
|
subparsers,
|
|
517
518
|
make_help_action=_make_help_action,
|
|
518
519
|
)
|
|
520
|
+
setup_mcp_parsers(
|
|
521
|
+
subparsers,
|
|
522
|
+
make_help_action=_make_help_action,
|
|
523
|
+
)
|
|
519
524
|
|
|
520
525
|
threads_parser = subparsers.add_parser(
|
|
521
526
|
"threads",
|
|
@@ -1301,24 +1306,29 @@ def _print_session_stats(stats: Any, console: Any) -> None: # noqa: ANN401
|
|
|
1301
1306
|
|
|
1302
1307
|
|
|
1303
1308
|
def _check_mcp_project_trust(*, trust_flag: bool = False) -> bool | None:
|
|
1304
|
-
"""Check whether project-level MCP
|
|
1309
|
+
"""Check whether project-level MCP servers should be trusted.
|
|
1310
|
+
|
|
1311
|
+
Both stdio and remote (http/sse) project entries require approval —
|
|
1312
|
+
remote entries from an attacker-controlled `.mcp.json` can SSRF or
|
|
1313
|
+
exfiltrate environment variables via `${VAR}` interpolation in their
|
|
1314
|
+
`headers`, so they are gated identically to stdio commands.
|
|
1305
1315
|
|
|
1306
|
-
When the project has no
|
|
1307
|
-
`None` (no gate needed). When `--trust-project-mcp` was passed,
|
|
1308
|
-
`True`. Otherwise checks the persistent trust store; if
|
|
1309
|
-
an interactive approval prompt.
|
|
1316
|
+
When the project has no servers in project-level configs, returns
|
|
1317
|
+
`None` (no gate needed). When `--trust-project-mcp` was passed,
|
|
1318
|
+
returns `True`. Otherwise checks the persistent trust store; if
|
|
1319
|
+
untrusted, shows an interactive approval prompt.
|
|
1310
1320
|
|
|
1311
1321
|
Args:
|
|
1312
1322
|
trust_flag: Whether `--trust-project-mcp` was passed.
|
|
1313
1323
|
|
|
1314
1324
|
Returns:
|
|
1315
|
-
`True` to allow project
|
|
1316
|
-
when no project
|
|
1325
|
+
`True` to allow project servers, `False` to deny, or `None`
|
|
1326
|
+
when no project servers exist.
|
|
1317
1327
|
"""
|
|
1318
1328
|
from deepagents_cli.mcp_tools import (
|
|
1319
1329
|
classify_discovered_configs,
|
|
1320
1330
|
discover_mcp_configs,
|
|
1321
|
-
|
|
1331
|
+
extract_project_server_summaries,
|
|
1322
1332
|
load_mcp_config_lenient,
|
|
1323
1333
|
)
|
|
1324
1334
|
from deepagents_cli.project_utils import ProjectContext
|
|
@@ -1333,14 +1343,14 @@ def _check_mcp_project_trust(*, trust_flag: bool = False) -> bool | None:
|
|
|
1333
1343
|
if not project_configs:
|
|
1334
1344
|
return None
|
|
1335
1345
|
|
|
1336
|
-
# Collect all stdio
|
|
1337
|
-
|
|
1346
|
+
# Collect all servers (stdio + remote) across project configs
|
|
1347
|
+
all_servers: list[tuple[str, str, str]] = []
|
|
1338
1348
|
for path in project_configs:
|
|
1339
1349
|
cfg = load_mcp_config_lenient(path)
|
|
1340
1350
|
if cfg is not None:
|
|
1341
|
-
|
|
1351
|
+
all_servers.extend(extract_project_server_summaries(cfg))
|
|
1342
1352
|
|
|
1343
|
-
if not
|
|
1353
|
+
if not all_servers:
|
|
1344
1354
|
return None
|
|
1345
1355
|
|
|
1346
1356
|
if trust_flag:
|
|
@@ -1369,9 +1379,8 @@ def _check_mcp_project_trust(*, trust_flag: bool = False) -> bool | None:
|
|
|
1369
1379
|
prompt_console.print(
|
|
1370
1380
|
"[bold yellow]Project MCP servers require approval:[/bold yellow]"
|
|
1371
1381
|
)
|
|
1372
|
-
for name,
|
|
1373
|
-
|
|
1374
|
-
prompt_console.print(f' [bold]"{name}"[/bold]: {cmd} {args_str}')
|
|
1382
|
+
for name, kind, summary in all_servers:
|
|
1383
|
+
prompt_console.print(f' [bold]"{name}"[/bold] ({kind}): {summary}')
|
|
1375
1384
|
prompt_console.print()
|
|
1376
1385
|
|
|
1377
1386
|
try:
|
|
@@ -1767,6 +1776,27 @@ def cli_main() -> None:
|
|
|
1767
1776
|
from deepagents_cli.deploy import execute_deploy_command
|
|
1768
1777
|
|
|
1769
1778
|
execute_deploy_command(args)
|
|
1779
|
+
elif args.command == "mcp":
|
|
1780
|
+
from deepagents_cli.mcp_commands import run_mcp_login
|
|
1781
|
+
from deepagents_cli.ui import show_mcp_help
|
|
1782
|
+
|
|
1783
|
+
if args.mcp_command == "login":
|
|
1784
|
+
if getattr(args, "mcp_config", None) and not args.config_path:
|
|
1785
|
+
print( # noqa: T201
|
|
1786
|
+
"--mcp-config is not supported for 'mcp login'. "
|
|
1787
|
+
"Use: deepagents mcp login <server> --config <path>",
|
|
1788
|
+
file=sys.stderr,
|
|
1789
|
+
)
|
|
1790
|
+
sys.exit(2)
|
|
1791
|
+
sys.exit(
|
|
1792
|
+
asyncio.run(
|
|
1793
|
+
run_mcp_login(
|
|
1794
|
+
server=args.server,
|
|
1795
|
+
config_path=args.config_path,
|
|
1796
|
+
)
|
|
1797
|
+
)
|
|
1798
|
+
)
|
|
1799
|
+
show_mcp_help()
|
|
1770
1800
|
elif args.command == "threads":
|
|
1771
1801
|
from deepagents_cli.sessions import (
|
|
1772
1802
|
delete_thread_command,
|